Public snapshot state stays in the store engine's plain-data vocabulary
(immer drafts reject Sets without the MapSet plugin, which stays off):
manager/service/contract carry readonly SessionId[] in Host order, and
the tree derivations build their own transient Set — the
expandedProjects pattern. Membership-unchanged installs still keep the
array reference for Object.is short-circuits.
WorkspaceListState gains archivedSessionIds (ReadonlySet, replaced only
on membership change), installed as full snapshots from the list
baseline, the unary echo, and the changed frame. Archiving the current
session clears the selection into the New Session view state. Test
doubles (test-runtime, fake APIs, fixture client) follow the widened
IWorkspaces/IApiClient faces.
Replace the surface-ordered fold with a log-ordered human transcript:
append-origin surface events at their own log positions plus one marker per
landed compaction checkpoint. Command folding, the tool-call index, and the
rev-keyed memo carry over unchanged.
Removes foldDegraded, the padding sentinels, baseSeq, and degradedSeqs() --
they existed only to satisfy the core fold's seq === index assertion. That
also closes the pagination hole A1 exposed: a page can carry a checkpoint
whose shadowed range fell outside the window, and nothing resolves
surfaceOp.start anymore.
Unify the /plan claimed hint with the plan placeholder through a locale
namespace, localize slash menu group titles, replace the PermissionSelect
native select with the Menu primitive, add a goal pause verb chain, clamp
anchored popups to the viewport with scroll-into-view and outside-dismiss,
and fix onPasteUpgrade insertedRange to account for the chip trailing gap.
Shared-surface conflicts resolve as unions: the fixture serves all five
projection keys (title/todos/permissions/plan/goal) with the /permission
and /plan command mirrors side by side, the connection specs assert the
five-key baseline and the shifted approval/question replay indices, and
the cli roster/deps, tsconfig aggregate, and README allowlist carry both
lines' rows. Plan-side content lands verbatim from master.
One end-state consolidation both branches half-did: with questions
(ui-question) and approvals (ApprovalPanel) each owning a composer
takeover, PendingCard retires outright — ChatView renders no pending
placeholder, the card component and its specs go, and both README halves
state the takeover-only contract.
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.
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.
TodoDock reads useProjection('todos') (whole list or null pre-first-write;
absent renders nothing) and declare-merges the todos key through the pure-type
outlet — the identical member the tool-todo host unit owns, drift rejected by
any program holding both. The core Session's todos field, its todo/write case,
and the snapshot member retire; the client folds nothing. Session specs for
the retired client fold move to the value-store spec's seq coverage; snapshot
literals across component specs drop the field.
React half of the session-projection client base: the renderer contract gains
an open-key projections face on SessionMaybeProvideInfo (cellOf(key), distinct
from the static hooks roster), web-react mints projectionHook (per-bundle cache;
per-cell uSES binding via the shared observableHook cache; unresolved keys read
undefined through the absent source so hook order stays constant), standardKit
delivers kit.useProjection, and the runtime merges UseProjection into
SessionStandardProps/SessionMaybeStandardProps (overloads mirror useSession).
3 jsdom specs (kit delivery + live re-render, selector over undefined, faceless
bundle = all absent); existing direct-prop-feed specs gain the one-line stub the
new required seat mandates.
Mechanical --fix output over the newly linted .tsx files (indent,
arrow-parens, comma-dangle, member-delimiter-style, unnecessary type
assertions), plus the three generic-arrow test hooks converted to
function declarations up front: the comma-dangle fixer strips the
<T,> disambiguation comma and turns them into parse errors otherwise.
- TodoPanel mounts through a 'conversation.input.dock' list entry
(todoDockEntry, QueueDock posture, order -1 above the queue rows) instead
of a ConversationRoot hardcode; the inner component is unchanged and takes
useSession from the dock entry's standard kit.
- The verify-todo-display.mjs chromium probe is replaced by an assembled
keyless snapshot (apps/web/tests/todo-display.snapshot.ts, the
code-mode-fixture idiom) pinning the TodoRow summary/state, the dock
panel content, and the collapse round-trip over built bundles.
- Fake snapshots across specs gain the todos field; bilingual note/READMEs
updated for the dock mount and the snapshot.