Repository navigation
Fork: settle the running subagent chips a fork copies - #1045
Merged
zeronsh[bot] merged 4 commits intoOct 26, 2026
Merged
Conversation
This was referenced Oct 25, 2026
alexandre-vl
marked this pull request as ready for review
October 25, 2026 16:45
zeronsh
Bot
force-pushed
the
subagents/fork-settles-chips
branch
from
October 26, 2026 19:16
54e5490 to
3890c01
Compare
A fork copies the source's entries as they are, so a subagent still running there kept a `running` chip in the fork. No run in the fork ever settles it: the chip and its lanes-card row spun forever (zeronsh#1001). The copy now settles it `failed`, like run end and the restart sweep do. The chip keeps its ref, so it still opens the subagent's transcript. The source keeps its own. CI now runs the engine's `side_chats` tests, where the fork tests live. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: zeronsh[bot] <346184242+zeronsh[bot]@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: zeronsh[bot] <346184242+zeronsh[bot]@users.noreply.github.com>
zeronsh
Bot
force-pushed
the
subagents/fork-settles-chips
branch
from
October 26, 2026 21:52
3890c01 to
de0cb10
Compare
Contributor
There was a problem hiding this comment.
Security audit clean: engine-only change to ForkSideChat (settles copied running spawn chips failed, matching run end and the restart sweep), one test, docs, media PNGs (no trailing data), and side_chats added to the CI test list. Rebased onto main; locally on Linux: side_chats 7/7, restart_resume 11, e2e 29 pass; the new test fails with the fix reverted; no new clippy warnings in touched files. Reflowed the docs/mcp.md paragraph. Thanks!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1001.
Forking a chat while one of its subagents ran left that subagent spinning in the fork forever. The fork copies the source's entries as they are, so the spawn chip came across
running, and no run in the fork will ever settle it. The copy now settles itfailed, as the engine already does for a running chip it can no longer follow: at run end (crates/engine/src/sessions.rs:4824), and in the restart sweep, which settles running chips in completed parent turns too (mark_abandoned_streams,crates/engine/src/doc_host.rs:949-973). The source keeps its own chip and its real outcome.What changes
ForkSideChatalready resolved the copiedInputparts. It now also settles each copied tool part whose subagent isRunning(crates/engine/src/rpc.rs:2753-2763). ThesubagentRef, settled chips and the source are left alone.Testing
cargo test --locked -p zeron-engine --lib --test side_chats --test restart_resume --test e2egives 630 passed (5 ignored), 7, 11 (1 ignored) and 29 (2 ignored).side_chats: it is named right afterrestart_resumein the engine's list of integration binaries (scripts/ci/test-core.sh:27), which didn't include it. Providers: a switch to turn native subagents off #1046 adds the same change, so the two merge in either order.a_fork_settles_the_running_subagent_chips_it_copies(crates/engine/tests/side_chats.rs:405, next to the six otherForkSideChattests) forks one entry holding a running chip, a done chip and an open question. The fork gets(main--sub--running, failed),(main--sub--done, done)and an answered question; the source keepsrunning,doneand its open question. It fails atside_chats.rs:510with the fix reverted (left: ([(Some("main--sub--running"), Some(Running)), …], [true])), with a copy that drops the ref (left: ([(None, Some(Failed)), …], [true])), and with the question left open (left: (…, [false])).Agentwhose prompt asks forsleep 90in the foreground, ends its turn, and is forked while that subagent still runs: the source's chip readrunningjust before the fork in both runs. Claude Code's Bash tool refused thesleep 90as a standalone sleep, so the subagent ended on its own, after the fork.runningright after the fork and still did 146 s later, while the source's had gonedone.failed, itssubagentRefintact, from the first read afterForkSideChatreturned to the last, 149 s later. The source's went fromrunningtodone. The subagent doc behind that ref still serves the subagent's transcript, which is what the red chip opens when the transcript blob isn't there (crates/ui/src/shell.rs:4624).c04e3749) after these runs, with no conflict. Merged there with the other five PRs of this series (Claude subagents: count and open only this chat's spawns #1041, Claude subagents: forward a foreground subagent's text and thinking #1042, Claude subagents: give a typed /skill's fork a chip and a tab #1043, Claude subagents: fill a typed fork's tab while the CLI holds it #1044, Providers: a switch to turn native subagents off #1046), it passes every suite above again, plus the rest of CI's selection, sync'smock-servertests,zeron-mcpand the UI'ssettings::tests, each executable checked to be built from that merge. The one failure, preview'sbackgrounded_scrubbed_terminal_and_out_of_tree_servers_stay_attributed, fails the same way on v0.2.124 alone, on this Mac.failedin all 30 samples over 149 s, and the source's went fromrunningtodone.Known limits
failedis what the doc already uses for a subagent cut off mid-run.crates/ui/src/shell.rs:4582-4587), and the fork's history prompt leaves the status out (crates/engine/src/sessions.rs:2723).recover_stale,crates/engine/src/sessions.rs:1516-1545), and a fork that never ran has none.Inputbranch of the copy: a question still open in the source gets emptyanswersin the fork. The two conflict as text only. Whichever lands second moves Questions: show what was answered, and close one without answering #1022'sif !*resolved { *answers = Some(Vec::new()); }into thismatch'sInputarm, next to*resolved = true. They change different parts, and this PR's test only readsresolved.scripts/ci/test-core.sh:27). Claude subagents: give a typed /skill's fork a chip and a tab #1043 addsclaude_subagentsto it, and Claude: show Workflow runs as subagents with live progress #784 (with Claude: open each Workflow agent's live transcript #785 on top)workflow_progress, so each conflicts with this PR there. Whichever lands second keeps every name.Screenshots
Offscreen renders of the production
Shell(Window::render_to_image), attached to each engine;docs/media/fork-settles-subagents/README.mdsays how they were made. They come from an earlier run than the one under Testing: v0.2.121, with a subagent runningsleep 70. The media are in their own commit,54e5490f, if you'd rather drop them before merging.Need help on this PR? Tag
@codesmith-botwith what you need.