A session that stops running while it is not the selected session arms a
green 'done' reminder dot on its sidebar row, so the operator notices a
finished background session and returns to it; opening the session clears
the dot, and a re-run re-arms it on completion.
SessionManager owns the reminder set (a sibling of the waiting-approval
bit): a running->idle edge of a non-selected session arms it, select()
consumes it, removal prunes it, and it survives connection generations.
The bit rides SessionListEntry/SessionSummary into the workspace browser
rows, which render the existing StateDot done state (running keeps the
spinner) and label the hover card '已完成/Completed'.
The client graph's ContentBlock narrows to the base four members, but
fixture turns carry merge-extended blocks at runtime, so removing the
JSON fallback crashed pricing on them. Keep the fallback and suppress
the narrowing-based lint finding with the reason inline.
The token-meter projections now subtract compact/summary's
shadowedTokenCount verbatim, so the seeded-history fixture's hand-picked
10k count drove the message figure negative and killed the projections
baseline. Realize the seed first (realizeSeedFixture, idempotent, shared
with seedSession) and derive the count from the shadowed rows through
the composed meter, reproducing the previous per-node fold bit for bit —
the recorded aria goldens pass unchanged.
Fixture-authored content is the closed base vocabulary, so after the
text/reasoning/tool-call arms only tool-result remains; the literal
comparison and its JSON fallback were dead and failed oxlint.
A defined fold claim is always freshly built and adjacent metering events
cannot repeat, so presence alone decides the claim transition; the value
comparison was unreachable and failed the per-file branch gate.
The per-file 100% thresholds name only the failing file. A custom istanbul
reporter now prints one clickable path:line:col record per uncovered
statement, branch path, and function, right above the threshold errors, in
both the CI coverage lane and local test:coverage runs (they share this
config). CJS because istanbul-reports loads custom reporters with a bare
require() outside the tsx/ESM pipeline.
The contextBreakdown and contextPressure units carried the full priced
surface, so each session's persisted projection checkpoint grew without
bound. A surface replacement is now priced by the shadow-price event
logged directly before it — compact/summary for compaction, the new
compact/prune from tool-result pruning (priced through the injected
token meter) — and the unit states shrink to a fixed handful of numbers.
Regenerate the persistence/cordis/module/config catalogs.