Repository navigation
fix(spectrum): preserve successor during restart cleanup - #137
Conversation
…quest Restart recovery read a Drafter's latest request and then dispatched a plain session stop, so a genuine successor request landing in between was stopped. The stop now names the request it may end by its event sequence. The engine refuses it, inside the serialized decide step, when the Drafter has a newer request, and always refuses the legacy unnamed form. A refused stop is never persisted, so neither the reactor nor any client projects it as stopped. Spectrum's outbox moves on only when that refusal is a superseded stop, live or replayed. Accepted stops precede every later request, which the reactor handles only after the physical stop finishes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Agent work on this PREstimated cost at least $7.46 · 184 responses · 73 sessions · 12.5 h wall time
Flags: 6 human corrections · 124 large tool outputs · 2 permission requests · 64 repeated commands · 15 repeated failures · 36 repeated reads · 11 repeated skill loads · 89 unpriced responses Details: snapshot, prices, coverage, counters
Token counters by model (native counter semantics; never added across semantics):
Generated tokens (reasoning and other output are disjoint; other output includes code, tool calls and replies):
Usage by work phase (this task's own responses):
Recorded activity by phase (observations, not separate token bills):
Selected rates (USD per million tokens). These rates value the report at the selected schedule date; they do not establish historical prices or subscription spending.
Other output and reasoning are priced without double counting inclusive native output. Missing rates remain unknown. Local measurement from native records; usage totals are not billing. Updated in place by |
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
|
What: Independent review found no actionable defect on Review trace
Evidence inspectedRead the complete four-file PR diff, relevant event/queue/reactor and Spectrum recovery/send/settlement consumers, current workspace No versioning by design. No merge or approval requested. |
What: Preserve genuine successors during Spectrum restart cleanup.
Why: Recovery read request identity then queued an unconditional stop, leaving a physical-stop race.
So what: The server-only fix is proved, independently reviewed and CI-green on the exact head; the user merges this one PR.
Follow-up for #118, parent #113 and merged PR #130, without closing linkage. #118 stays closed. This strengthens the Spectrum outcome in the current Objective.
Recovery intent carries the unique request event sequence in its command ID. The fork-owned guard runs in the engine's existing serialized command decision, rejecting superseded stops before persistence. A reactor-only guard was discarded because the shared client reducer projects a persisted stop event as stopped even when its physical effect is skipped. No client or contract changes.
An accepted stop precedes every later request. The reactor handles persisted events in order, completes compaction cancellation, physical stop and stopped session update before admitting the later request's send. Deterministic Deferred/receipt/drain tests hold an admitted send across stale cleanup, and park the worker while persisting a successor after an accepted stop. They assert physical provider effects and session state, not rejection alone. Spectrum's outbox tolerates a rejection only after confirming that recovery intent is superseded, preserving report/settlement progress and replay.
Requirements and who asked: User requires atomic identity-based stop, physical successor survival, failing-before regression, ordinary-stop compatibility and exactly one server-only PR.
Deleted: Misleading reactor-only guard, new machinery, contracts/client changes, recovery loops, new Issue, versioning, browsers, live servers and installs.
Bottleneck: Request identity must remain valid until stop persistence, and persisted event order must protect forked provider admission.
Checked myself: Full #118/#113 and #130 body, authored diff, engine queue/reactor stop/send path, client reducer projection, actual baseline/final logs, fork registrations, clean local/remote head.
Candidate
Base
86d3269c6eac9dde4697a0fce105efc2abb907e9; head1af9d1ab6d1dfb3c882ff67d809955ed3847f3e8. Clean pushed branchfix/118-recovery-stop-race, exclusive workspace/Users/lukaszmaj/dev/toolboxmd/chromeria-worktrees/118-recovery-stop-race. Writer stopped. No canonical/caller/sibling writes.Four files changed:
apps/server/src/mcp/toolkits/threads/spectrum.ts,spectrumIdentity.ts,spectrum.test.ts, andapps/server/src/orchestration/Layers/OrchestrationEngine.ts. Engine is already registered inscripts/fork-upstream-edits.txt:129anddocs/fork-features.md:173(also :941), verified directly. No duplicate registry entry added.Proof
Node 24.13.1, pnpm 11.10.0. Commands run with
PATH=/Users/lukaszmaj/.nvm/versions/node/v24.13.1/bin:$PATH:Before fix, final assertions with production restored to exact base: 2 failed, 3 passed, exit 1. Both failures observed unexpected physical
stop:sub.spectrum...calls, for successor and legacy recovery. Reversed order and two existing recovery cases passed. Patch restored and matches committed production. An earlier reversed-order expected-state error was an oracle correction, not defect evidence.Final engine candidate: 266 passed in 19 targeted files, exit 0. Typecheck, targeted lint/format, registry (23 features), diff check all pass. No earlier 113-test reactor proof reused and no repo-wide checks. The
deciderargument is a Vitest filename filter selecting 15 decider test files, not a directory or shell glob; expanded names will be recorded below.Regressions prove: successor admitted between identity read and stop survives physically, no stale stop event, no interruption, final session survives; replay finishes one report and one settlement; successor persisted after accepted stop sees physical stop/start/send order and stopped write before its own writes; legacy recovery intent is refused while ordinary stop still persists and physically stops.
Logs outside workspace:
/tmp/promachos-coord/118-recovery-stop-race/, notablybaseline-4-engine-assertions.log,final-tests.log,final-typecheck.log,final-lint.log,final-fmt.log,final-fork-features.log,production.patch. Decisive sanitized results are retained here, no transcript uploads.The 15 decider test files selected by the filename filter were:
apps/server/src/orchestration/decider.active-order.test.tsapps/server/src/orchestration/decider.autoSettleSet.test.tsapps/server/src/orchestration/decider.delete.test.tsapps/server/src/orchestration/decider.import.test.tsapps/server/src/orchestration/decider.pinned.test.tsapps/server/src/orchestration/decider.projectScripts.test.tsapps/server/src/orchestration/decider.projectThreadEnvMode.test.tsapps/server/src/orchestration/decider.pullRequests.test.tsapps/server/src/orchestration/decider.questionAttachments.test.tsapps/server/src/orchestration/decider.settled.test.tsapps/server/src/orchestration/decider.snoozed.test.tsapps/server/src/orchestration/decider.titleRegeneration.test.tsapps/server/src/orchestration/decider.turnDiffComplete.test.tsapps/server/src/orchestration/decider.userInputDismiss.test.tsapps/server/src/orchestration/decider.userMessageAppend.test.tsReview and cost
Passed on exact head
1af9d1ab6d1dfb3c882ff67d809955ed3847f3e8. Independent findings and verdict. Reviewer: Prism GPT-6-Luna through Codex/T3 Code, threadsub.sub.sub.sub.46b03420-8643-4703-8756-8602f14b39fb.dispatcher-aecbb8dc7270.dispatcher-fda19fc83a22.dispatcher-52147369cc30.reviewer-a2810d15e065. Newestreview/independent=success, authenticated creatorlukemaj, targets those findings. No supported blocking finding; reviewer traced forked send admission, physical stop/session writes, rejected-stop projection, outbox replay and compatibility with main's stored-effort changed0fbed7482655a492d44bdb5c7893751034fba91. Requested original base retained, no rebase. Dispatcher additionally inspected main advancement todafca350377d015811aa2d22efc5d16a1b5f7b24: #138 changes only repository-identity/Git remote parsing and registry entries, not this seam. No new candidate or transferred review verdict.Agent Observer cost publication uses the instructed
sync,task show --task toolboxmd/chromeria#137 --json, andpublish --task toolboxmd/chromeria#137 --repo toolboxmd/chromeria --pr 137. Pricing is partial because GPT-6.1-Sol has no known rate; usage is not subscription spending. Refreshed after review withsyncand the same publish command, which updated the existing comment successfully.CI run 36980128289: first attempt's only named assertion failure was unchanged
scripts/knip-schemas.test.ts:13,Test timed out in 20000ms, 329 script tests passed. Runner summary said four failed tasks but identified no other assertion failure, so no additional cause is claimed. The disposable fixture imports Effect schemas and no changed recovery path.PATH=/Users/lukaszmaj/.nvm/versions/node/v24.13.1/bin:$PATH pnpm exec vp test run scripts/knip-schemas.test.tspassed (1 test, 3.21 seconds, exit 0). CI run 36980128289, attempt 2, is SUCCESS on the unchanged head: the bounded rerun Test job 110754499621 passed. Check, all three server shards, Test, Rust, Release Smoke and Mobile Native Changes passed; Mobile Native Static Analysis was intentionally skipped. The initial timeout is superseded by this green retry. No unrelated code/test edits or timeout changes.Assumptions and remaining items
Legacy fork-only recovery stops without identity are deliberately refused. A saved legacy outbox may leave the original hidden Drafter turn to finish, while Spectrum settles/reports uncertainty. Ordinary stops retain existing behavior, including upstream's lack of cancellation for an already-running non-retirement send fiber. No live verification claimed. No open implementation or proof items remain; user merge is the remaining delivery action. No versioning by design. No merge/install. Website/SEO impact none: server restart cleanup changes no website content, URLs or presentation. Task branch/workspace retained for user merge and merger-owned finalization.
Dispatcher: GPT-6.1-Sol through Codex/T3 Code. Writer: Prism worker/hard
claudeAgent/claude-opus-5-5, threadsub.sub.sub.sub.46b03420-8643-4703-8756-8602f14b39fb.dispatcher-aecbb8dc7270.dispatcher-fda19fc83a22.dispatcher-52147369cc30.worker-9a3f366d6b6c, Claude Code/T3 Code. Independent reviewer: Prism GPT-6-Luna through Codex/T3 Code, exact-head verdict passed.