- the cached-identity rung gains a finality gate: the identity value
carries its descriptor seq and a cached row is served only when that
seq lands in the child's own suffix, so a fork seed's replayed
ancestor identity can never outrank the authoritative refold
(stateVersion bumped for the state-shape change)
- the cold preparation validates the inspected header against the
enumerated candidate's lifecycle witness; a republished id degrades to
that child's corrupt diagnostic instead of leaking the new owner's log
- the new projection registration proves HMR disposal; companion notes
qualify the superseded decision text and record the deliberate
error-face asymmetry
- the subagent projection's empty state becomes a serializable null
sentinel (undefined fields vanish in JSON push frames, leaving stale
identities in clients); consumers treat null and a missing key alike,
and cached sentinels defer to the authoritative refold
- the tool catalog generator mounts the projection registry for
list_agents; the shared unavailable-error copy goes catalog-neutral
- the design note's verification section records the new
subagent-diagnostic snapshot honestly, the 2026-07-22 note's test
inventory is rewritten to the current mechanism, and the session-store
error code is documented
Mounting session-projection in the example compositions staled the
generated composition and module graphs; the 2026-07-22 note now
describes the retired optional-session-query spec without a live path.
- listChildren reads the session store via strict ctx.get (property proxy
is caller-scoped), orders candidates branchlessly, narrows the cold-read
return type, and pins the cost model and store/registry composition gaps
with tests; per-file coverage restored
- acp-agent and headless-agent compositions mount session-projection; a
keyless snapshot pins the descriptor-less diagnostic row
- api-proxy cold spec pins header-origin ownership and the legacy
descriptor-only opt-out
- design note ships as implemented with its English pairing; companion
notes and core-data-structures pages synced
The branch control on user and consumed-steering bubbles could enable
only when a completed turn ended with no node after the message at all,
so readers saw a permanently unavailable control whose tooltip promised
a state it could not reach. An enabled one would mislead anyway: a fork
at a message seq cuts at the containing turn/end and takes the answer
along, the opposite of the branch-to-re-ask reading a control on one's
own bubble suggests.
MessageItem loses its fork props, PendingSteeringBubble loses the
showBranch special case, and messageBranchSeqs narrows to
assistantBranchSeqs: only a completed turn's transcript tail that is
the turn's own content-text assistant may fork. A steered turn keeps
its fork point under the settled answer, because fork is a log-prefix
cut and the steer is model-visible history the child inherits.
Web aria goldens drop the user-bubble disabled-branch row and its
hidden explanation text; the nested-subagent golden also loses the one
enabled user-tail fork handle, a loss the decision note accepts.
The profile rework left references to the old entry modes behind. Renames
the user patch-layer API and its spec file (watchPersonalPatches ->
watchUserPatches, personal-config.spec.ts -> user-patches.spec.ts) and
retargets the prose that still named `config.yaml`, `--config`, raw-config
mode, and surface overlays: repository-plugin and mcp-memory READMEs, the
credentials-local anchor into app-boot, vendor manifest items 12-13, the
vendored include/hmr comments, and install.sh.
Restores the boot-failure guard the rework dropped with raw mode: the
built-bin case now boots `--profile web --patch <invalid>` and asserts the
settled diagnostic and exit 1, so the HMR initial-scan deadlock stays
covered; its orphaned raw fixture is renamed and the unused one deleted.
The superseded personal-config Agent Note and its superseding profile note
are now cross-linked.
`assistantActionsSeqs` picked the last content-text assistant of each turn
from the finalized transcript alone. That quantity is stable only once the
turn closes: while a turn is still producing steps, the narration written
before a tool call is the last content assistant so far, so copy, branch,
and the clock appeared under an intermediate sentence for as long as the
tool ran and then moved down to the next step's text.
Pass `ConversationSnapshot.turnEnds` into the derivation and grant the row
only inside a turn that has a durable `turn/end`. This is the same
completion fact the branch control and the `Ran for` label already read, so
the three parts of one row now agree; mid-turn narration owns nothing, and
the seat appears once under the settled answer.
`hasContentText` moves to chat-flow.ts so the ownership gate and
AssistantMarkdown's mount gate cannot drift apart.
apps/web/tests/turn-tail-actions.e2e.ts pins both states through the
assembled application: a hang sidecar on the second model call parks a turn
whose first step narrated before calling bash, and the two goldens hold the
parked flow and the flow after stopping.
Port the two master-side markdown fixes onto the mdast renderer:
cjkFriendlyStrong joins both parse.ts grammars as a micromark extension
(ex remark plugin), and inline-code HTTP(S) URLs gain the safe anchor in
render.tsx without normalizeUri. Re-record the two new web-e2e goldens
whose footer clock spacing diverged from the nine established goldens,
and drop the timing-flaky LLM duration segment one of them captured.
ed30088adb deleted packages/ui/tui, so the two present-tense clauses naming
it in notes this branch already rewrites no longer describe HEAD. The
operative claim — the surfaces beyond the web row needed no change — stands
without naming the package. Pair hashes re-recorded.
Also anchor tool-row-styles.spec.ts's rule lookup at a rule boundary, so a
compound selector landing above a base rule fails loud instead of reading
the wrong declaration block.
`flex: none` stops the `+n` box shrinking but not its text wrapping, so a
row too narrow for title + separator + suffix broke the one-line summary in
the exact case the slot exists for. Add `white-space: nowrap` and pin the
declaration as CSS text, since jsdom has no layout.
Also align the README's row illustration with the English rendering (the
same sentence's plan-strip clause already used it), and record the two
deferred review findings in the Agent Note so they survive merge.
Address review feedback on PR #1738:
- ReactLoopAgent builds its AgentEventDispatch once in the constructor and
routes every emit/serial/waterfall through it, so hot-path dispatches no
longer allocate a carrier and dispatcher per call; the public carrier
field is gone (fused dispatcher is private).
- agentEvents accepts an optional prebuilt carrier.
- The fused payload builder spreads the payload before the injected agent
so a structurally acceptable payload carrying an agent field can never
override the subject.
- Regenerate doc graphs; re-record core + architecture + affected Agent
Note translation pairs; add payload-object event contract Agent Note.
The web-todo-display note still described the dock entry as registering at
order: -1 and reading snapshot.todos through useSession. TodoPanel.tsx
registers at order: 0 and TodoDock reads the host-computed todos projection
through useProjection.
The plan strip header has not emitted `<done>/<total> tasks · <n> in progress`
since #740 replaced it with `·`-joined per-status counts. Four sites still
quoted the old string: plan-summary.ts's module JSDoc, ui-conversation's
README pair, and the web-todo-display note pair.
The parallel-in-progress note's regression example mixed a four-item plan with
an eight-item row reading, and built-boot.snapshot.ts still called itself the
only test loading the built bundles.
The `+N` active count rides ToolRow's non-shrinking `summarySuffix` slot,
but only jsdom package suites covered it: the ACP snapshots render no web
surface and the built-boot smoke asserts no todo row. Add
`apps/web/tests/todo-row.snapshot.ts`, which boots the built client bundles
against the keyless fixture transport and records `summary`, `suffix`, and
the plan strip's header as separate fields, so folding the count back into
the summary string changes the expected output.
The three assembled-jsdom files now share `apps/web/tests/assembled-boot.ts`
instead of each carrying its own copy of the boot entry list, bundle map,
jsdom stubs, and mount call.
Also: name the policy branch in each `allowParallelInProgress` test title so
no case asserting `true` sits under a `false` describe, reword the stale cap
comment in todo-panel.spec.tsx, and record the plan strip's real header
format in the Agent Note (per-status counts, not `<done>/<total> tasks`).
The tool catalog boots every tool with its default config, but
allowParallelInProgress has no default, so the generator has to choose;
the page now says which branch it shows. The Agent Note's sidecar count
went stale twice inside this PR, so it records the refresh rule instead
of a point-in-time census. The SDK builtin entry pins its config literal
with satisfies like every sibling.