fix(orchestrator): Preserve post-interrupt recovery state#4229
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
12dfe4e to
2b5cda2
Compare
2b5cda2 to
2557fda
Compare
| if (belongsToRootRun) { | ||
| yield* Ref.update(openRunOwnedSubagents, (current) => { | ||
| const subagents = new Map(current.subagents); | ||
| if (isTerminalSubagentStatus(event.subagent.status)) { |
There was a problem hiding this comment.
🟡 Medium orchestration-v2/RunExecutionService.ts:810
When a subagent reaches a terminal status before the root run is interrupted, trackChildLifecycle deletes it from openRunOwnedSubagents.subagents (and its turn item from .turnItems), which also discards the only recorded childThreadId. If that subagent's linked child-thread node is still pending, running, or waiting, cascadeTerminalizeRunOwnedSubagents still finds the node in open.nodes but can no longer match it to any childThreadId, so the node is never terminalized and remains permanently open in the projection. Consider preserving the childThreadId linkage until all linked nodes settle, or storing the linkage separately from the subagent/turn-item snapshots.
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/orchestration-v2/RunExecutionService.ts around line 810:
When a subagent reaches a terminal status before the root run is interrupted, `trackChildLifecycle` deletes it from `openRunOwnedSubagents.subagents` (and its turn item from `.turnItems`), which also discards the only recorded `childThreadId`. If that subagent's linked child-thread node is still `pending`, `running`, or `waiting`, `cascadeTerminalizeRunOwnedSubagents` still finds the node in `open.nodes` but can no longer match it to any `childThreadId`, so the node is never terminalized and remains permanently open in the projection. Consider preserving the `childThreadId` linkage until all linked nodes settle, or storing the linkage separately from the subagent/turn-item snapshots.
Summary
notification arrives during session resume.
the command completion event.
stopped root turn leaves them open.
Stack
This draft targets
t3code/codex-turn-mappingand is stacked on #4193, the samepost-merge fixture-fix base used by #4218. This branch contains one unique
commit above that stack base.
Problem and Fix
task_notificationresult between the first post-Stop prompt and its real response. The adapter treated that result as the active root result, completing the recovery run with no assistant output.item/completedfor an in-flight command. The projected command card remainedrunningafter the run settled.turn.terminal. Late completions are dropped without retaining or waking the stopped run.Validation
vp check: pass with pre-existing warnings onlyvp run typecheck: passturn_interrupt_mid_toolreplay fixture: 3 passedclaude-interrupt-direct-stop: pass with one interrupted run and two distinctcompleted recovery runs
rendered as distinct assistant responses with no stuck Working state
during recovery 1; both recovery runs completed with their expected markers
in Claude and Codex and the stale Claude child root node
failed/cancelled mapping, supersede protection, linked-child cleanup,
unreferenced-child exclusion, partial result preservation, and same-attempt
and cross-attempt late-event rejection
Remaining Provider Behavior
The Codex app-server can report a turn interrupted while the provider-owned
foreground shell and child remain alive beyond the live suite's five-second
process-containment bound. This change settles T3's command projection and drops
late completion traffic, but it does not claim to terminate that external
process. The strict
codex-interrupt-direct-stoppack therefore fails closed onprocess containment even though the UI and recovery-state assertions pass.