Commit Graph

322 Commits

Author SHA1 Message Date
imccyu
25265b312c feat(web): projection-fed permission chip replaces the Access placeholder
PermissionSelect returns as the Access seat's wired occupant: options and
the current value read from the 'permissions' projection through the
standard-kit useProjection (no fetch, no mount timing — the resident
composer's mount-once fetch bug dies with the fetch), key absence renders
nothing (permission-less host, or a Draft with no session), and a pick
submits the '/permission <preset>' command line through the new
ComposerBarInjected.command callback (Session.command = command.execute
admission; the pushed projection frame lands the confirmed value). The
READONLY_OPTIONS placeholder and its local state leave InputBar.

The connection fixture mirrors the host: a permissions unit fold (three
knob events over the fixture preset table), the projections block +
baseline/push frames carry the key, and /permission joins the command
catalog with the same switch-through-knob-events handler shape.
2026-07-28 22:56:43 +08:00
imccyu
c6b552e817 refactor(web): drop the permission RPC pair and turn-anchoring machinery
The session.permissions/setPermission unary pair, the PermissionOption wire
DTO, the client Session wrappers, and the fixture/fake mirrors all leave the
wire: the read side moves to the 'permissions' session projection and the
write side moves to the /permission command in follow-up commits, so the
web protocol gains no permission methods at all.

The pendingSwitches + prompt-submit flush + hasOpenTurn move also goes.
Knob events no longer need turn enclosure: the persistence scanner keeps
standalone events after the last turn/end as part of the preserved prefix
(remove-synthetic-log-only-turns), none of the three knob invariants demand
an open turn, and the setters append bare events. An idle switch commits
immediately; hasOpenTurn stays a user-approval private fold (its audit pair
is the one contract that still requires enclosure).

The old PermissionSelect chip and its mount-time fetch die with the RPCs
(the resident composer broke the mount-once assumption); the projection-fed
replacement lands with the Access seat swap.
2026-07-28 21:35:26 +08:00
imccyu
a66d1e335f Merge origin/master into web-permission-sandbox
39 conflicts resolved per the reattachment plan (missions worktree-projbiz
0728-1859): baseline wins for deleted packages (host/runtime, old ui/acp,
ui-sidebar Rows/tree) and retired specs; unions for wire-layer exports and
client summary fields; the approval takeover, waitingApprovals tracking, and
PendingApproval domain face carry over onto the master structure. The two
new host specs follow the runtime->apiproxy rename. Dead PR-side wiring
(ConversationInjected permissions/setPermission spread, InputBar controls
prop, boot.ts sandbox composition) resolves to master and its replacement
lands in follow-up commits.
2026-07-28 21:20:00 +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
imccyu
de56936c87 docs: fix test and docs conflicts 2026-07-28 16:50:07 +08:00
Chinesezjc
75ae2cb4eb Merge remote-tracking branch 'origin/master' into feat/scrollbar-tokens 2026-07-28 16:23:44 +08:00
imccyu
9ce201e490 Merge remote-tracking branch 'origin/master' into worktree-guifork 2026-07-28 16:12:12 +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
imccyu
ee9627f232 Merge remote-tracking branch 'origin/master' into fix/web-ui-optimization 2026-07-28 15:06:17 +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
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
imccyu
e2791107c4 ci: clear the snapshots-and-artifacts lane — lint sweep and TUI snapshot re-record
Lint: eslint --fix over the merge-crossed projection/command files (arrow
parens, trailing commas, unnecessary assertions), Extract<> replaces the
keyof-map & string intersections no-redundant-type-constituents rejects,
the fold-adapter's merge loop drops its non-null assertions for a
bounds-carrying cursor, one JSDoc line wrapped under max-len (api-catalog
regenerated). Snapshots: the four TUI goldens re-recorded for the merged
event-count shift (the durable command lifecycle adds one event to the
seeded diagnostics log). The headless advanced-toolchain snapshot passes
on CI and fails locally in this sandbox both with and without these
changes (30s child timeout — environment-bound, tracked in the ledger).
2026-07-28 11:48:01 +08:00
07akioni
99d631d41a fix: ci 2026-07-28 11:21:45 +08:00
Chinesezjc
662089dd76 fix(client): theme the scrollbars and reserve the workspace list gutter
design-platform.css declared four --dsw-alias-scrollbar-* tokens in both
palettes that no rule read, so every scrolling region rendered the user
agent's own scrollbar and the dark theme showed a light native bar against
dark surfaces.

The symptom that surfaced the gap was in the sidebar: the workspace
browser's session list is its only scrolling region, and each row's
trailing content (the relative timestamp, and the hover action buttons
that replace it) is `flex: none` flush against the row's 8px right
padding, so an overlaid scrollbar painted on top of the timestamp.

ui-theme/styles/scrollbar.css becomes the sole consumer of the four
tokens, imported by the web shell's base.css after design-platform.css
because it reads that sheet's tokens. The rules sit on `body`, not
`html`: the alias tokens are declared on `body`, custom properties
inherit only downward, and from `html` they resolve to the
guaranteed-invalid value with scrollbar-color computing to `auto`.
scrollbar-width and scrollbar-color are declared on `body, body *` rather
than inherited, because inheritance would carry the color already
substituted at `body` and an elevated surface could not retint its own
thumb; scrollbar-width does not inherit at all.

Both the standard properties and the ::-webkit-scrollbar pseudo-elements
read one indirection pair bound to the l1 tokens, so an elevated surface
rebinds that pair to the l2 tokens once and retints both renderings. The
command popup, slash menu, model-select panel, and settings panel do so,
which gives the l2 tokens their first consumers.

WorkspaceBrowser's `.list` declares scrollbar-gutter: stable, keeping the
bar beside the rows. `stable` rather than `auto` so the reservation holds
when the list is short enough not to scroll: expanding a workspace group
would otherwise shift every row sideways at the moment it starts
scrolling.
2026-07-28 11:02:11 +08:00
07akioni
fb9495b21e Merge branch 'master' into fix/todo-tool-ui 2026-07-28 10:59:05 +08:00
imccyu
a3bdec4450 Merge remote-tracking branch 'origin/master' into worktree-guifork 2026-07-28 10:23:48 +08:00