Repository navigation
perf(orchestration): stop and resume wake only that thread's subtree - #488
Conversation
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. |
|
Grok roast at c7ce2fa: BLOCKING The subtree wake on an explicit message resume is the right cut for that one transition. It is not every un-retire the old sweep was actually delivering. Blocking. Spectrum Stop a Spectrum while a drafter has a pending approval. The stop reconcile skips it because the drafter is retired. Unsettle the Spectrum without sending a message. Non-blocking. The other heals the sweep was doing now wait for boot.
Non-blocking, and cleared for a process crash. The separate resume fork is safe. The fork is after Non-blocking. Drop the scope flag.
|
|
Luna review round 1 at c7ce2fa: CHANGES REQUESTED Blocking: Spectrum unsettle can un-retire Drafters without waking their pending child requests. Repro: Stop a Spectrum while a Drafter has a pending approval, then issue Non-blocking: unarchive can leave a child request waiting after the parent becomes available. A child request created while its parent is archived is skipped by Checks: the added regression exercises observable delivery and the PR body reports it fails on the old implementation. I did not run tests. Issue #450 records the upstream search; PR CI's Fork Stack Model check is green. |
c7ce2fa to
7fe94b6
Compare
|
Luna review round 2 at 7fe94b6: APPROVE No blocking findings. |
|
Grok roast round 2 at 7fe94b6: PASS Round 1 blocker is fixed. The Double wake, cleared. Stop still wakes only from the listener, and only when Missing exit, cleared. The only writers of Lock order, cleared. The fork still starts inside I did not run tests. |
A resumed thread keeps forkResumedRetirements set, so every later metadata update of it ran the environment-wide child request sweep. Stop now reconciles only the stopped thread's subtree, and resume reconciles its subtree once, from the commit that un-retires it. Closes #450 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hread Spectrum unsettle acknowledges retirement tokens on its Drafters without an explicit message, so their requests stayed asleep after reopen. Any explicit-input or unsettle commit that adds an acknowledged token now wakes that thread's subtree once. requestWake loses its scope flag; subtree sites call the subtree reconcile directly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7fe94b6 to
936972c
Compare
What: Stop and resume now reconcile child requests only for that thread's subtree, once per transition, instead of on every later metadata update.
Why: A resumed thread keeps
forkResumedRetirementsset, and the event listener treated that persistent field as a trigger, so every later metadata event of the thread ran the global sweep over every subagent thread (12 to 15 s on rocky).So what: Luna review, Grok roast and CI, then the backlog coordinator merges.
Problem
Orchestrator.tscalled the globalrequestWake()whenever athread.metadata-updatedevent had a Stop token matching its command or a non-emptyforkResumedRetirements. The second condition stays true after resume, so title updates,queue.resume, limit recovery and similar events each triggered a fullgetShellSnapshotplusreconcileChildRequestsfor every subagent thread. Stop, which already had an exact trigger, also swept globally.Fix
childThreads/requestWake.ts: newreconcileSubtreeChildRequests(threadId, ...)reconciles the thread and its subagent descendants (found with the existingreadStopDescendants, so deleted intermediate parents still connect descendants).Orchestrator.ts:forkRetirement.token === commandId) now wakes the stopped thread's subtree. TheforkResumedRetirementstrigger is removed.message.dispatchorthread.unsettlechecks its plannedthread.metadata-updatedevents; any that acknowledges a token the thread did not already have is an un-retire transition. After commit, each such thread's subtree is woken once (a resumed thread whose parent is resumed in the same commit is covered by the parent's wake). This covers the core resume path and Spectrum reopen, which acknowledges tokens on the Spectrum and every Drafter (spectrum/commandPlan.ts). The wake is forked intorequestWakeScopebecause it takes ancestor locks.requestWake(threadId?)keeps its original thread or environment meaning; subtree sites callrequestSubtreeWake, which runsreconcileSubtreeChildRequests, so no flag can turn a missing id into an environment-wide sweep.Not handled here by design: a child request skipped while its parent was archived, and a crash between commit and the forked wake, are reconciled by the boot sweep in
recoverDelegatedTasks. Unarchive no longer gets an incidental sweep from unrelated metadata updates, so such a request can wait until the next boot, request event, Stop or resume.Upstream
No match in
pingdotgg/t3codeissues, PRs or code forforkResumedRetirements,requestWakeorreconcilePendingChildRequests.apps/server/src/childThreads/is fork-only (added by #181);Orchestrator.tshunks are in the existing fork-allowlisted file.Proof
Run one file at a time in
apps/serverat the head commit:src/childThreads/requestWake.test.ts: 9 passed.src/childThreads/requestWake.noRequests.test.ts: 1 passed.src/childThreads/requestWake.startup.test.ts: 7 passed.src/spectrum/Controller.integration.test.ts: 17 passed.src/orchestration-v2/ThreadStop.test.ts: 49 passed.vp run typecheckinapps/server: exit 0.vp linton the changed files: no new findings (one pre-existing unused-variable warning inOrchestrator.ts).scripts/fork-check.sh: OK.Failing first:
requestWake.test.ts"committed ancestor resume wakes only its subtree, once": with the original source, fails at the assertion that an unrelated subtree's pending request was not delivered (expected false to be true). It covers Stop, resume, and a later metadata update of the resumed thread.Controller.integration.test.ts"reopening a stopped council wakes a Drafter request suppressed by Stop" (Luna round 1): with the round 1Orchestrator.ts, the Drafter's request is never delivered afterthread.unsettleand the test times out; with this head it is delivered.Not done here: rocky trace check after deploy (Issue required proof) and the optional
RecoveryReactor.ts:131note.Elon record
forkResumedRetirementstrigger in the event listener, the global sweep on Stop, and the scope flag onrequestWake(Grok roast).getShellSnapshotand per-child reads on every metadata update of a resumed thread.Closes #450
Implemented by Claude Opus 5.5 via Claude Code in T3 Code.
🤖 Generated with Claude Code