Three ds-review-bot round-8 findings on the todo display surfaces.
TodoPanel took the whole `useSession` hook and cast the snapshot to reach
`todos`, which put slot plumbing and an unchecked cast inside the presentation
component. The panel now takes `todos: readonly TodoItem[]`; TodoDock does the
selecting, matching the QueueDock posture the dock slot already establishes.
The todo row carried `onClick` with no keyboard route, so its details panel was
mouse-only. It now takes ToolRow's route verbatim: `role="button"`,
`tabIndex={0}`, and an Enter/Space handler that claims the event. The row stays
a `<div>` because a `<button>` flattens its inline spans.
`session.history`'s tail-only `todos` field was documented at the TS signature
but not in the apiproxy README pair, and the Agent Note claimed the feature
added no new wire vocabulary. Both README sides now state the tail/omission
semantics (an omitted field on a tail response is the empty plan, not unchanged
state), and the note records the one added field instead of denying it.
Tests: TodoPanel specs render the plain list; new TodoDock specs cover selection,
live follow, rollback-to-empty, and the registration shape; a new row spec pins
Enter/Space activation and non-activating keys.
An omitted `todos` on a tail request was treated as "no projection carried"
and preserved the prior value. Every installWindow caller is a tail request
(doOpen, its gap re-pull, repairGap; loadOlder prepends without it), which the
host answers with the full-log projection or omits only when the log holds no
todo/write — so the field's absence is the authoritative empty list. A live
write whose host crashed before persisting therefore left the rolled-back plan
on screen indefinitely; the assignment now clears it on the next open or
resync. Widened the parameter to an explicit `| undefined` so the two meanings
cannot be conflated again, and updated the JSDoc at both declaring seams plus
the bilingual README/note pair.
The automation-only ACP bridge deliberately omits todo presentation (its
edge test asserts plan updates are omitted; the todo-write tool note records
the mapping's retirement). Chinese counterpart updated, pair re-recorded;
the TodoPanel header comment drops the same claim.
Regenerate event-producer-consumer.md after the queued-frame steering removal;
re-record the bilingual consistency records the master merge left stale; and
restore the eight archived notes the agent-loop rename had swept up (archived
notes are frozen — their archival-time path references stand).
- 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.
The mount-local baseline guard was seeded from "a baseline already exists in
the log", which a resumed session and a hot plugin remount both satisfy. That
made a resume skip its baseline, so offline AGENTS.md edits or removals never
reached the first resumed request — violating the documented resume contract.
Distinguish the two by agent/session-start: a startup or resume emits it before
the first step, while a remount attaches to an already-live session and never
witnesses it. Only a remount (no witnessed start, baseline already logged)
keeps the single logged baseline and skips; a resume falls through and
re-composes from current files. Adds a regression that resumes a session with
an offline baseline edit and asserts the fresh baseline reflects it.
Conflict resolution: scripts/type-equiv.manifest.json takes master's new
paired-derivative format (one primary entry per pair) and re-adds this
stack's CodeDispatchLog entry in that format. zh README pairs brought
along for the dispatch-log arm (spill-policy behavior/limitations bullets,
tools limitation bullet now pointing at the shipped bounding).
Responding to ds-review-bot round 2 on #661:
- logWork is bounded: past maxParallelSubCalls pending shaped-append tasks
the ordered commit lane holds (Promise.race drains one), so a slow spill
backend backpressures the run instead of accumulating unbounded pending
I/O and retained results. Tasks self-remove on settlement; run
settlement still drains every task inside the open turn. New spill test
drives three oversized reads against a hung backend at cap 1 and proves
the third dispatch cannot start until a save drains.
- shapeDispatchLog's catch uses errorMessage() (total), so a thrown value
with a throwing toString cannot escape the containment and lose the
settle event.
- CodeDispatchLog.content documented as the RENDERED result projection
(native tool/result vocabulary), not what the program received — the
program gets the structured value; doc pair + type-equiv re-synced.
- New RECORDED tui-agent snapshot scenario code-mode-dispatch-spill: the
real Loader-visible composition (worker runtime + spill-local + policy)
drives an oversized bash sub-call end-to-end; replay proves the durable
dispatch copy is bounded to preview + locator while the program value
stays whole (the outer result carries just the line count).
Agent Note updated (both languages).
Conflict resolution: drainDispatches composes both sides — the reworked
single-lane driver's drive() (ordered stages, mid-flight commit drain)
followed by this branch's logWork drain, so every shaped settle append
still lands inside the open run_code turn.
Responding to ds-review-bot round 2 on #658 (three critical findings, one
warning — all rooted in the pump/commit split racing ordered stages):
- ONE driver lane now owns every ordered stage: the start append, prepare
(pre-execute/guards), and the head-of-line commit (post-execute, context
deferral, settle append). start() is awaited before the next entry can
start, so concurrent submissions can no longer run pre-execute pipelines
concurrently; only the around-dispatch/body stage overlaps, matching the
native loop's fillPool sequencing.
- An exclusive call's barrier now holds through its COMMIT: later starts
wait for the exclusive pipeline (post-execute included) to finish, the
native exclusive-group semantics.
- drainDispatches() awaits the driver run itself, so a commit already
mid-flight when the program returns is drained before run_code closes
the turn — the settle event and deferred contexts land inside it.
- maxParallelSubCalls is resolved and validated at construction (positive
integer), so direct construction can no longer wedge the pool with 0.
New tests: overlapping-submission ordered-prepare, barrier-through-commit,
drain-mid-commit, cap rejection. 96 keyless snapshots replay unchanged;
Agent Note updated (both languages).
The automation bridge inherited two master-era assumptions the message
machine no longer honors. A prompt blocked at pre-turn admission opens no
turn, so no turn/end could ever settle it — the bridge now watches
whenIdle() and reports a turnless slot as cancelled (the disposed-agent
guard moved to a registry identity check before send). A failed turn no
longer rejects at its turn/end either: agent.retry() closes the failed
turn and opens a successor on the same history, so the bridge holds the
terminal error and lets a retry-triggered turn/start adopt the prompt,
rejecting only at quiescence with no successor.
Also: refresh the empty-response-retry fixture for retry-as-turn logging,
adapt master-side tests to the unified send()/UserMessageData API and
registry-fact disposal, resync the doc pairs both sides touched, trim
architecture.md back under its word ceiling, and regenerate the event and
persistence catalogs.
Responding to ds-review-bot on #664:
- SubSpanLane gains a 'timing' discriminant (measured | running | unknown).
A settle-only replay entry (callTime null, start outside the window) was
previously indistinguishable from a measured 0 ms span; it now renders
hollow with a 'duration unknown' hover title, and durationMs stays null
for anything unmeasured. Pairs with the client-runtime fix that stopped
fabricating callTime = settle time (826c3696a on the live-parallel PR).
- The built-client Code Mode fixture snapshot now switches to the
Trajectory and Waterfall tabs and pins the assembled rendering: three
Sub cells with real +0.8s durations and three measured lanes with their
hover titles — product-visible coverage through the real bundle graph,
not just package-level jsdom fixtures.
Agent Note (both languages) updated for the timing contract; pairing
re-recorded.