Repository navigation
fix(workspace): Reload Agents re-checks ownership around its awaits (#1282) - #1326
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1282) The reload walked a snapshot and re-checked nothing while it killed and respawned each agent: an agent closed meanwhile came back under a new id, one replaced meanwhile got two successors on one transcript, and a draft typed meanwhile was lost. It now skips an agent that is no longer the same owned agent before its kill, re-checks every successor at commit (killing the orphans, caller reload.orphaned-successor), and carries the live draft, draft images and unread marker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Juliusolsson05
added a commit
that referenced
this pull request
Sep 26, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ait (#1326 review) Round-1 findings: overlapping on/off reloads, project merge mid-reload, close during an awaited orphan kill, rejected orphan kill, failed respawn of a closed agent, and two surviving mutations. Checks and commit are one synchronous run; orphans are killed after it; successors file from the live row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Sep 27, 2026
…round 2) An early successor ran unfiled while later spawns were pending, so a close missed it; a close during the pre-spawn kill was still followed by a spawn; a failed orphan kill was swallowed; and a fresh respawn's durable provider id was dropped. Each agent now commits on its own, ownership is rechecked after every await, orphan kills retry and are retried by the next reload, and the reported provider id is kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reload's per-agent loop keeps #1324's curated failure sentence: the spawn catch computes it and markRespawnFailed carries it onto the failed pane. Adds the combined fail-and-close integration case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…keep refused kills (#1326 verify) A remembered orphan was never retried once every agent was closed, and a kill main refused (false: possibly still running) cleared its record. An all-failed reload also stopped pruning unowned rows. Orphans are retried first, only a confirmed kill clears them, and pruning happens up front. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…phans locally (#1326 verify2) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
Author
Review disposition (#1326): reviewers A, B, C; round 1, round 2 and two verification passes (A, C); final head
|
| Round | Finding | Verdict | Disposition |
|---|---|---|---|
| 1 | A1: overlapping on/off reloads leave the dangerous successors running | valid, Blocker | Fixed: reloads are serialized. |
| 1 | A2: project merge mid-reload files the successor into a deleted project | valid, Blocker | Fixed: the successor is filed from the live row. |
| 1 | A3 / B1: a close during an awaited orphan kill was never re-checked | valid, Major | Fixed; later superseded by per-agent commits. |
| 1 | A4: a rejected orphan kill aborted the reload | valid, Major | Fixed: per-orphan try/catch. |
| 1 | A5: a failed respawn recreated a closed agent's runtime | valid, Minor | Fixed: failed ids are ownership-filtered. |
| 1 | A / B survivors: cwd clause, project-ownership clause | valid | Pinned. |
| 2 | C1: a close during the pre-spawn kill still spawned | valid, Major | Fixed: re-check after the kill. |
| 2 | C2: an early successor ran unfiled while a later spawn stalled | valid, Major | Fixed at the root: each agent commits as its spawn returns. |
| 2 | C3: a swallowed orphan-kill rejection | valid, Major | Fixed: retry, then remembered for the next reload. |
| 2 | A1: a fresh respawn's durable provider id was dropped | valid, Major | Fixed (runtime-start); the provisional id is never carried. |
| 2 | C4: plan and harness comments drifted | valid, Minor | Corrected. |
| 2 | B: two tests green on the round-1 head | accepted | Intentional pins of guards that survived round-1 mutations. |
| verify | A / C + q56: a remembered orphan was not retried with no live agents left | valid, Major | Fixed: retried before the empty return. |
| verify | C + q56: a refused (false) kill cleared the retry record |
valid, Major | Fixed: only true clears it. |
| verify | A: an all-failed reload no longer pruned unowned rows | valid, Minor | Fixed: prune up front. |
| verify | C survivors: relationship and pin remaps | valid | Pinned at the dangerous interval. |
| verify2 | A: rows unowned mid-reload not pruned | valid, Minor | Fixed: per-commit prune restored alongside the up-front one. |
| verify2 | A / C: an orphan's early runtime entry left behind | valid, Minor | Fixed: forgetSessionLocally after a confirmed kill. |
| — | #1324 integration (q42) | done | Merged; the curated sentence survives, with a combined fail-and-close test. |
The #1325 integration (carry workflow runs only for committed pairs) is owned by W3 if #1325 merges first.
Owner
Author
|
Final verification (verify3) at |
Juliusolsson05
added a commit
that referenced
this pull request
Sep 27, 2026
…w-pane Steering q42: #1326 commits each reloaded agent as its own spawn returns and kills orphaned successors. The Reload Agents workflow carry moves next to the per-agent goal-loop carry after commitSuccessor, so only committed pairs are carried, never an orphan. Test added in reloadAgentsOwnership.renderer.test.tsx. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Fixes #1282.
Plan:
docs/plans/2026-09-26-reload-all-ownership.md(first commit; review rounds recorded there).Why
reloadAgentSessions(the Dangerous Agents toggle) walked a snapshot, awaiting a kill and a spawn per agent, and re-checked nothing:replaceSessionhascanCommitfor this (bug(sessions): retire replacement when its source placement disappears #815), reload had nothing;draftImagesandunreadSince/unreadKindwere never copied.What merges
Reloads run one at a time. Clicking the Dangerous Agents switch on and then off leaves the last click's mode running.
Each agent is committed as soon as its own spawn returns. The successor is the pane from that moment, so a close is an ordinary close of the new id. Before, successors ran unfiled until every later spawn returned.
Ownership is re-checked after every await:
"Owned" is
canCommit's rule: same cwd, kind and provider runtime, and still in a project.The successor is filed from the LIVE row. A project merge or rename during the reload is kept. Only spawn-owned fields come from the loop: identity, MCP domains, and the provider session it resumed. A fresh start keeps the durable
providerSessionIdspawn reports (runtime-start) and never carries a provisional one.Orphan cleanup has an owner. A failed kill is retried once, then remembered in
unstoppedReloadSuccessorsRef, and the next reload retries it first (before its no-live-agents return). Only a confirmed kill (true) clears it, becausefalsecan mean "not yours, still running". Application quit'skillAllstops everything regardless. A confirmed kill also drops the orphan's renderer bookkeeping.A failed respawn keeps its pane with fix(ipc): session:spawn launders provider exceptions before they cross IPC (#1267) #1324's curated sentence (never raw IPC text), unless the agent was closed meanwhile.
Unowned rows are pruned up front (so an all-failed reload prunes them too) and again in each commit (for rows that became unowned mid-reload).
The draft, draft images and unread marker come from the live predecessor runtime at commit.
Tests
reloadAgentsOwnership.renderer.test.tsx, 22 cases on the owner's recorded v3 workspace (1 window, 3 projects, 13 sessions, 2 lanes). Spawn and kill IPC are held open so each test acts inside the dangerous interval, not only on the final state:killSession;Every case was shown red on the head before its fix, and each guard is mutation-checked (the remaps, pin, prune, retry order,
true-only clearing, curated message). Workspace suites: 1356/1356.npx tsc -bis clean.Final verification (verify3, A/C, at
9a8e0444): both MERGE-READY, no findings.Residuals
falsecosts one IPC call per later reload.🤖 Generated with Claude Code