repairGap installed the repulled window without the response projection;
a todo/write missed during the gap and already outside the new tail page
kept the stale list. The spec pins adoption through the repair path.
sessionHistoryValueSchema declared only events/hasMore, so the fetch
carrier's Zod parse stripped the tail page's todos projection — the
in-process and fixture paths carried it while a real WebApiClient lost it.
The fetch-carrier spec pins the field through the wire round trip.
The client's todos projection derived only from the paged display window,
so reopening a session whose last todo/write preceded the tail page showed
an empty plan until the user paged back — session-level state cannot be
reconstructed from an arbitrary window. The host owns the full log, so the
tail history response now attaches todos (latest todo/write backscan, the
same posture as the view pairing); installWindow seeds it, window rebuilds
preserve it, and any in-window or live write keeps overwriting it. The
fixture mirrors the host; docs and both Agent Notes record the mechanism.
runtime README documents ConversationSnapshot.todos and its window-scoped
limitation; the todo tool README and Agent Note name the web client among
the event consumers; the web display note records the cold-load gap and
fix directions (bilingual pair re-recorded).
The tool appends the snapshot mid-execution, between tool/call and
tool/result; the fixture spliced it after step/end with a post-turn
timestamp, so acceptance never exercised the production ordering. A spec
pins call → snapshot → result with monotonic times.
null roots, non-object roots, and null array items (retained verbatim on a
rejected tool/call) now take the documented generic-summary fallback instead
of throwing into the row error boundary.
An item carrying keys beyond content/status (ids, children, priority) was
flattened to {content, status} on append, so the logged snapshot diverged
from what the model believed it wrote (model-visible must equal logged).
Reject loudly; the isError result lets the model self-correct.
fx-alpha gains turn 63: a todo_write call/result pair plus the todo/write
snapshot event, feeding both the TodoRow toolview and the TodoPanel strip
in ?fixture mode. verify-todo-display.mjs drives chromium through panel
visibility, content, row summary, details linkage, collapse and dark.
TodoPanel pins above the composer (776px card axis), hidden while empty,
collapsible with the active item as the collapsed hint; status glyphs
mirror the TUI plan panel. todo_write rows render a plan-flavored summary
(counts + active item) via the toolview registry, generic fallback on
malformed args. Existing fake snapshots gain the required todos field.
Session consumes the todo/write session event as a per-event side effect
(last write wins), rebuilds it on window replay/paging/resync, and exposes
snapshot.todos. TodoItem re-exported through the runtime surface.
The fake terminal retains earlier autocomplete frames, so the directory follow-up assertion could pass before the scoped lookup completed. Wait for the quoted file mention to be applied before submitting.
The master merge introduced a tui goal-restore test and the guard parent
README that still used the removed context/message event. Point both at
the coalesced plugin-sourced user/message.
- Added bilingual notes for the new session feature, detailing the transition to an empty state upon session creation.
- Updated `SessionsService` to include a `clear()` method that resets the current selection and persists the empty state.
- Enhanced the `EmptyState` component to reflect the new design, including workspace selection and input handling.
- Modified CSS styles for improved layout and visual consistency in the empty state.
- Updated tests to cover the new session clearing functionality and its effects on the UI.
Address a fresh-eye review of the disposal/injection fixes:
- disposal now snapshots, clears, and marks disposed BEFORE emitting
agent/inbox/discard (mirroring cancel's snapshot→clear→emit), so a
re-entrant send/cancel from a discard listener throws 'disposed' or
finds an empty inbox instead of leaking or double-discarding an id.
The discard is unconditional (even on unpublished setup-rollback) to
match send's unconditional enqueue, keeping every id balanced.
- restore the turnRecorded guard on the idle-injection flush: a
turn/start rejected pre-commit (append reentrancy / internal-dispatch
veto) records nothing and owes no flush; the previous unconditional
flush emitted a phantom-turn agent/error. The isTurnOpen/turnRecorded
branches are reachable (reentrant inject from a session/event
listener) and now covered by a regression test rather than v8-ignored.
- rewrite the agent/inbox/discard event JSDoc to enumerate all three
emitters (cancel, terminal turn-stop, disposal) — every enqueued id
gets exactly one terminal dequeue-or-discard.
Per-file coverage stays 100%.
- Added TrajectoryCell, TrajectoryGroupHeader, and TrajectoryTurn components for rendering trajectory steps and groups.
- Introduced bilingual support with English and Chinese translations for trajectory notes.
- Updated conversation session models to include timestamps for various message types.
- Enhanced layout logic to handle expanded assistant blocks and tool results with duration metrics.
- Added CSS styles for new components to ensure proper display and alignment.
Address the review bot's five genuinely-new findings on the current code:
- disposal now discards any still-pending inbox items before the loop
exits, so every enqueued id gets a terminal lifecycle event.
- injection (next-step/no-wakeup) validates its payload up front, before
opening the idle one-shot turn, honoring 'invalid input throws before
any append'; and rejects attached contexts (which belong only to inbox
messages) rather than silently dropping them.
- agentMessage() freezes the agent/inbox/* payload so a listener cannot
mutate the shared correlation object mid-dispatch.
- refresh the package READMEs (compact, goal, guard, hook-protocol,
plan-mode, time-context, workspace-context) that still referenced the
removed context/message event, with the source-based user/message
distinction.
The up-front injection validation makes two finally branches unreachable
(v8-ignored as the turn-enclosure backstop). Adds regression tests for
disposal discard, context rejection, up-front validation, and the frozen
payload; per-file coverage stays 100%.