Commit Graph
326 Commits
Author SHA1 Message Date
creatixchu 302dfca4d5 Merge remote-tracking branch 'origin/master' into doc/host-client-group-readmes
# Conflicts:
#	packages/README.i18n.yaml
#	packages/README.md
#	packages/README.zh.md
#	packages/client/connection/src/index.ts
#	packages/client/connection/src/native-dialog-request.ts
#	packages/client/connection/tests/node-half.spec.ts
#	packages/host/apiproxy/README.i18n.yaml
2026-07-28 21:01:20 +08:00
07akioni a39890bba5 Merge branch 'master' into feat/close-todo 2026-07-28 19:45:36 +08:00
07akioni 2c65ebf6be test(connection): expect fixture todos projection null on empty log 2026-07-28 19:44:36 +08:00
07akioni 7bf36c6aa3 Merge origin/master into feat/close-todo
Keep master's session-projection carrier for todos, and fold turn/start
clearance into the tool-todo projection unit (plus TUI/fixture mirrors).
2026-07-28 19:43:56 +08:00
07akioni 6978dbfb13 fix: cr 2026-07-28 19:16:39 +08:00
Tianyi Cui 291676f704 Merge branch 'master' into xtr/identified-immutable-messages 2026-07-28 18:55:50 +08:00
Chinesezjc 0401c3c6c7 test(ui-theme): resolve elevated surfaces from the palette, not from rebinds
The check added last commit derived its elevated set from the sheets that
already rebind, which cannot catch the omission it targets: such a set only
confirms what someone already remembered, and a surface nobody has rebound
yet defines itself as unelevated. Review found the case that proves it —
TodoPanel scrolls in .list on a --dsw-specific-tip card, the same dark rung
as the menu surface, unrebound and with the derived check green.

Resolves the set from the palette's own dark elevation ladder instead: the
surface tokens whose dark value lands on bg-layer-2 or bg-layer-3, which is
the step the l1/l2 split encodes. A new palette token on an elevated rung is
in scope the moment it is defined.

Scope is by token family rather than geometry: only --dsw-alias-bg-* and
--dsw-specific-* name a surface. The button, interactive, and markdown
families reach the same rungs while naming a control or an inline span that
no scroll container renders a bar against, and shape cannot separate them
since a floating button carries a radius, a shadow, and a fixed size —
ChatView's .toBottom pill was the false positive that showed this.

Adds the missing TodoPanel rebind. Mutation-checked all four rebinds in
turn: each is named with its surface. The palette anchoring has its own
control — narrowing the family pattern turns it red on --dsw-specific-menu.
2026-07-28 18:31:52 +08:00
_Kerman 310e4dff26 test(client): update degraded assistant fixture 2026-07-28 18:24:33 +08:00
Chinesezjc 60248e99d1 Merge remote-tracking branch 'origin/master' into feat/scrollbar-tokens 2026-07-28 18:15:00 +08:00
_Kerman 9220dbd271 Merge remote-tracking branch 'origin/master' into xtr/identified-immutable-messages
# Conflicts:
#	docs/event-producer-consumer.md
#	packages/client/connection/src/client/fixture.ts
#	packages/goal/command-goal/tests/command-goal.spec.ts
#	packages/host/apiproxy/src/api-proxy.ts
#	packages/host/apiproxy/src/api/events.schema.ts
#	packages/host/apiproxy/src/api/events.ts
#	packages/host/apiproxy/tests/api-proxy-view.spec.ts
#	packages/host/apiproxy/tests/rpc-schemas.spec.ts
#	tsconfig.base.json
2026-07-28 18:11:13 +08:00
07akioni 9e94082f4d feat: implement todo plan clearance on turn start 2026-07-28 17:58:09 +08:00
imccyu 5dd2e77914 Merge remote-tracking branch 'origin/master' into worktree-guifork 2026-07-28 17:48:48 +08:00
Chinesezjc 4265ac876c fix(client): rebind the scrollbar indirection on three missed elevated surfaces
Review found three scroll containers sitting on surfaces the rebinding
contract covers, none of which rebound: ui-primitives' shared Menu card
on --dsw-specific-menu (the surface PopupSelectView already rebinds for),
and the composer input and question composer cards, both on
--dsw-specific-input-major. Each rendered the l1 thumb, which differs
from l2 only in the dark palette and only on that surface, so a
light-palette screenshot and a code read both look correct.

Adds the mechanical check that would have caught them instead of leaving
it to inspection: a sheet that scrolls somewhere and paints a known
elevated surface somewhere must rebind. The elevated set is derived from
the sheets that already rebind, since a rebinding rule paints the surface
whose elevation it declares, so a new elevated surface joins the set by
rebinding rather than by anyone updating a list. Surface-level rather than
element-level because the card and the descendant that scrolls are
separate rules and CSS text does not say which contains which. Verified by
reverting each of the three fixes in turn: the check names the sheet and
the surface every time.

Also commits snapshots/sidebar-scrollbar/geometry.expected.md, the
resolved scrollbar style and geometry in both palettes. The aria goldens
the other web scenarios commit cannot carry a CSS-only change, since it
alters no DOM and no accessible name and leaves their trees
byte-identical. Absolute coordinates stay out: they track font metrics and
the laid-out sidebar width, so committing them would document the platform
and force a per-platform re-record.
2026-07-28 17:42:57 +08:00
creatixchu 772653464d fix(connection): hold markerless requests to the Host fence — plain-HTTP browser reads carry no markers
Fetch-Metadata and Origin are only attached to trustworthy destinations, so
over plain HTTP a rebound page's same-origin GET (EventSource, images,
navigations) arrives with no browser markers and a readable response. Remove
the marker shortcut; non-browser clients pass the same fence via loopback,
the CLI-derived LAN IP literals, or a declared authority.
2026-07-28 17:02:39 +08:00
imccyu de56936c87 docs: fix test and docs conflicts 2026-07-28 16:50:07 +08:00
creatixchu 7ff8da56df fix(connection): require trustedHosts entries in canonical authority form
A dangling colon (harness.internal:) or zero-padded port parses cleanly while
WHATWG silently rewrites it, turning an intended exact-port grant into an
any-port grant. Replace the character blacklist with a round-trip check: an
entry must read back from parsing exactly as written (case aside), refusing
the whole rewrite class at load.
2026-07-28 16:49:52 +08:00
Chinesezjc 75ae2cb4eb Merge remote-tracking branch 'origin/master' into feat/scrollbar-tokens 2026-07-28 16:23:44 +08:00
creatixchu 34518cb012 fix(connection): judge an entry's explicit port from the parsed URL, not the raw string
WHATWG trimming strips stray whitespace before parsing, so 'host:port ' passed
the load assert while the raw-string port regex read it as port-less —
broadening an exact-port grant to every port on that hostname. The explicit-
port judgment now reads URL parses under both special schemes (:80/:443 stay
explicit), and the load assert refuses whitespace outright.
2026-07-28 16:19:31 +08:00
imccyu 9ce201e490 Merge remote-tracking branch 'origin/master' into worktree-guifork 2026-07-28 16:12:12 +08:00
creatixchu b9cbe2f029 fix(connection): fail the load on a trustedHosts entry that is not a bare authority
WHATWG parsing would quietly read a hostname out of harness.internal/path or
user@harness.internal, authorizing the typo's hostname; other typos would sit
silently ignored until requests 403. Refuse every URL part beyond host[:port]
at plugin load.
2026-07-28 15:57:02 +08:00
07akioni fff09b2a41 Merge branch 'master' into feat/toolcall-open
Keep openFile path links (no tool-row sidebar handoff) while taking master's
cwd-relative summaries, running sweep, and expandable chevron polish.
2026-07-28 15:55:22 +08:00
_Kerman 019b0abb68 Merge remote-tracking branch 'origin/master' into xtr/identified-immutable-messages
# Conflicts:
#	.agents/notes/implemented/architecture/2026-07-24-separate-context-injection-from-turn-execution.i18n.yaml
#	docs/cordis-catalog/services.md
#	docs/core-data-structures/core.i18n.yaml
#	docs/core-data-structures/session.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/persistence-catalog.md
#	packages/core/session/README.i18n.yaml
#	packages/session-title/session-title/tests/persistence.spec.ts
2026-07-28 15:45:53 +08:00
creatixchu 01eea07bab fix(connection): keep LAN serving working under the /api browser-trust fence
Markerless requests pass on any Host (a non-browser sender is the principal
and forges headers anyway); browser Host matching gains port-less entries and
WHATWG normalization; dsh derives LAN IP-literal authorities for an
all-interfaces bind and web grows --trusted-host for named ones.
2026-07-28 15:40:02 +08:00
imccyu ee9627f232 Merge remote-tracking branch 'origin/master' into fix/web-ui-optimization 2026-07-28 15:06:17 +08:00
creatixchu d1ce22e7ad doc(packages): add the host/ and client/ group READMEs and table rows
Both web-GUI groups shipped without the group README that the packages
table names as each group's canonical package/ctx-key map, and without
rows in that table. Adds both bilingual pairs, the two table rows
(ceiling 835→870: two genuinely new product groups joined the canonical
table at minimal row width), and fixes webserver README drift
(WebServerService/ctx.webServer → HttpServerService/ctx.httpServer,
matching src/index.ts).
2026-07-28 15:04:59 +08:00
Chinesezjc fb5c4ef4e3 Merge remote-tracking branch 'origin/master' into feat/scrollbar-tokens 2026-07-28 15:02:38 +08:00
Chinesezjc c3e9690b2e fix(ui-theme): gate the standard scrollbar properties behind the missing WebKit pseudo-element
A non-`auto` `scrollbar-width` or `scrollbar-color` makes Chromium and Safari
discard every `::-webkit-scrollbar*` rule for that element, including
`::-webkit-scrollbar-thumb:hover`. Declaring both unconditionally left the
hover tokens rendering nowhere: the engines implementing the hover
pseudo-element are exactly the ones the standard properties silence, and
Firefox has no hover pseudo-element to fall back on. Both hover tokens and all
four elevated surfaces' hover rebinds were therefore dead code.

Measured in chromium on probe elements with `scrollbar-gutter: stable`: an 8px
`::-webkit-scrollbar` alone reserved a 30px band, and adding
`scrollbar-width: thin` dropped it to the 10px `thin` reserves.

The standard properties now sit inside `@supports not
selector(::-webkit-scrollbar)`, so Firefox takes them and WebKit-based engines
take the pseudo-elements. The WebKit rules stay ungated: an engine without
those pseudo-elements drops them as unknown selectors, and gating them would
hide them from an engine that implements them without `selector()` — the
pre-16.4 Safari the ungated form serves correctly.

Three unit assertions pin the split by source offset, which the existing
at-rule-flattening parser cannot see. The web e2e now reads the path chromium
actually takes: the `auto` standard properties as the gate's signature, the
pseudo-element sizing and track, the indirection variables resolved per
throwaway probe, and the hover declaration as cascade rule text — chromium
folds the `:hover` rule into `getComputedStyle(el,
'::-webkit-scrollbar-thumb')`, so no computed query separates the states.
2026-07-28 15:02:20 +08:00
_Kerman 0a3d38bb08 Merge remote-tracking branch 'origin/master' into xtr/identified-immutable-messages
# Conflicts:
#	docs/event-producer-consumer.md
2026-07-28 14:59:40 +08:00
creatixchu 01d68dee4e fix(connection): fence every /api request behind one browser-trust check
The only browser-trust guard covered host.pickDirectory, while the
consequential methods (session.prompt drives bash) accepted any Host —
open to DNS rebinding, where a rebound page reads and writes the API as
if same-origin and only the Host header betrays the attacker's domain.

The pickDirectory-specific loopback guard becomes a prefix-wide fence:
Host must be loopback or an exact host[:port] from the new trustedHosts
config, an attached Origin must equal that authority, and explicit
cross-site markers are refused; requests without browser markers (curl,
tests, native clients) pass, because without a browser there is no
confused deputy. The loopback-socket check is dropped — binding policy
expresses reachability, and the fence is not an auth layer. The Agent
Note records the full threat model and the alternatives.
2026-07-28 14:56:45 +08:00
imccyu 095e3944ae docs(client): state the reactive-read rules positively 2026-07-28 14:52:04 +08:00
imccyu 059ba4e0d1 docs(client): add the reactive-read and contract-currency discipline 2026-07-28 14:48:46 +08:00
imccyu 2665e55e5d docs(runtime): align the zh README resolution sentence with the privatized resolvers 2026-07-28 14:36:16 +08:00
imccyu d833be412a fix(client): contain notification-callback failures and document the source lifecycle
Review follow-ups: the three new notify loops (currentProvideInfo
subscribers, ui-skill lexicon listeners, late-registration controller
setup) now contain per-callback failures so one faulty consumer cannot
starve the rest, abort the list projection pass, or poison the source
roster with no disposer; controller lexicon polling drops a throwing
source with a console record like the candidate path. The ui-slash
README (both languages) now states the late-registration warm and the
subscribeLexicon contract, and the scenario suite drives a typed /name
token gaining its decoration when the roll settles with no further
input.
2026-07-28 14:33:37 +08:00
_Kerman 971f20b66e fix: restore message migration CI coverage 2026-07-28 14:29:54 +08:00
07akioni b926044c13 feat: click file name to open file in toolcall, remove hover bg of toolcall, do not trigger sidebar any more (follow designer's instruction) 2026-07-28 14:24:41 +08:00
imccyu f331f248d8 fix: static 2026-07-28 14:16:14 +08:00
imccyu 2b74db670e refactor(client): rename the provide reprojection to updateCurrentProvideInfo and privatize the id resolvers
provideInfo(id)/maybeProvideInfo(id) lost their last external caller
when the renderer host switched to the currentProvideInfo observable;
both become private (tests assert through the public projection). The
reprojection method's name now says what it does — re-derive and
publish on change — and matches the field family it maintains.
2026-07-28 14:06:08 +08:00
_Kerman f5ec71f5b1 Merge remote-tracking branch 'origin/master' into xtr/identified-immutable-messages
# Conflicts:
#	.agents/notes/implemented/feature/2026-07-21-cross-session-references.i18n.yaml
#	packages/context/session-reference/README.i18n.yaml
#	packages/context/session-reference/README.md
#	packages/context/session-reference/README.zh.md
#	packages/context/session-reference/src/index.ts
2026-07-28 13:58:06 +08:00
_Kerman fbf87e660c refactor: identify and freeze messages at creation 2026-07-28 13:55:59 +08:00
Chinesezjc a6b0cd6f8d Merge remote-tracking branch 'origin/master' into feat/scrollbar-tokens 2026-07-28 13:43:11 +08:00
Yif 8eb1a6f66b fix(web-ui): narrow flow item before reading group results in chat-view spec 2026-07-28 12:25:32 +08:00
Yif 0a625b1144 fix(web-ui): header title 14/20, drop turns counter, global grayscale antialiasing 2026-07-28 12:18:18 +08:00
imccyu b5168bbf86 feat(ui-slots): bind inject hooks compartments into use<Name> selector hooks
Registrant-private reactive facts previously reached components as raw
observables that each component subscribed by hand (InputBar notices/
lexicon via uSES, SettingsRoot via a version/subscribe/getter triple).
The inject face now carries a reserved hooks compartment of bare
sources; the renderer binds each into a use<Name> selector hook through
the same machinery as the provide channel, so components consume
useNotices/useLexicon/useSections and never see a subscription
primitive. InputBar and SettingsRoot are the first two consumers.
2026-07-28 12:09:48 +08:00
imccyu b7f3cd3d78 refactor(client): rename currentProvide to currentProvideInfo 2026-07-28 12:09:48 +08:00
imccyu 71529aa7d2 refactor(client): rename the host provide source to provideInfo 2026-07-28 12:09:48 +08:00
imccyu d3d01cb49c fix(ui-slash): make the reference lexicon reactive end to end
The decoration scan read a mutable lexicon() aggregation during render
with no subscription, so a catalog settling or a child spawning after
prewarm left drafted tokens undecorated until an unrelated re-render.
The controller now publishes the aggregation as a snapshot store fed by
a new optional SlashSource.subscribeLexicon hook (ui-skill notifies on
settle/invalidate, ui-subagent forwards the session-list feed), the
composer keyboard face exposes it as an observable, and InputBar
subscribes through uSES. Sources registered after scope birth now warm
and join live controllers via a service broadcast.
2026-07-28 12:09:48 +08:00
imccyu eae712409b fix(ui-settings): subscribe to the section ledger through useSyncExternalStore
The manual useState+useEffect subscription could miss a registration
landing between render and effect commit; uSES closes that window and
keeps the same version-dedupe behavior.
2026-07-28 12:09:48 +08:00
imccyu a0b618abb9 fix(client): publish current session provide bundle as one reactive projection
A provider roster change under a stable current id rematerialized every
scope's bundle but nothing notified React: SessionProvider resolved the
bundle from a current-id subscription only, so mounted entries kept the
obsolete hook/prop schema until an unrelated re-render. The sessions
service now owns an atomic currentProvide observable fed by both current
writes and roster changes; the renderer host exposes it as
sessions.provide, replacing the current/provideInfo/maybeProvideInfo
trio, and both providers subscribe to it.
2026-07-28 12:09:48 +08:00
Yif 16b54aa4c4 fix(web-ui): cwd-relative path summaries, sweep glare rework, uniform 16px chat rhythm
Tool row summaries strip the session workspace root; the running sweep
becomes a glare-band overlay (deepsuite ShimmerText pattern); assistant
nodes that render nothing no longer split tool-row groups; block and
tool-row spacing collapse to one 16px rhythm.
2026-07-28 12:05:58 +08:00
imccyu 91045a467b Merge branch 'master' into worktree-guifork 2026-07-28 11:50:56 +08:00