Conversation
…5180) /fork previously replaced the current session's runtime in place: the original's kernel was disposed, its resident subagents closed, its cron jobs and heartbeats rebound to the fork, and its identity taken over, so the original vanished from the agents view. Fork is now split into an additive, capability-gated fork_export daemon command (branch export with no teardown) plus client orchestration in DaemonAgentConnection.fork(): export -> create a new daemon session for the forked file -> reattach. The original keeps running with its kernel, subagents, heartbeats, and lease, and stays listed; the fork starts fresh (cold kernel, no subagent registry, no cron), which also keeps the fork as lazy as possible. Legacy fork remains as the fallback for old daemons and in-memory sessions. DAEMON_SCHEMA_REVISION 16 -> 17. Fork transitions are serialized on the connection; the exported file is only removed on a definitive create rejection, and a failed reattach best-effort kills the created fork session.
… into eng-5180 # Conflicts: # packages/coding-agent/CHANGELOG.md
| return this.legacyFork(entryId, options); | ||
| } | ||
| const sourceActiveSessionId = this.activeSessionId; | ||
| const exported = await this.requestData<{ |
There was a problem hiding this comment.
🟠 High agent-connection/daemon-agent-connection.ts:1240
A fork fails after reconnecting to an older daemon instead of falling back to legacyFork. The capability check occurs before requestData, but a recovered request can later throw DaemonCapabilityUnavailableError; catch that post-reconnect error and invoke legacyFork(entryId, options).
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts around line 1240:
A fork fails after reconnecting to an older daemon instead of falling back to `legacyFork`. The capability check occurs before `requestData`, but a recovered request can later throw `DaemonCapabilityUnavailableError`; catch that post-reconnect error and invoke `legacyFork(entryId, options)`.
Evidence trail:
packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts:245-248, 1232-1249, 1301-1311, 1519-1533 at REVIEWED_COMMIT; packages/coding-agent/src/modes/daemon/daemon-client.ts:72-84, 282-285, 293-318, 431-460 at REVIEWED_COMMIT; git diff MERGE_BASE REVIEWED_COMMIT -- packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 93f9493. Configure here.
|
|
||
| private legacyFork( | ||
| entryId: string, | ||
| options?: AgentConnectionForkOptions, |
There was a problem hiding this comment.
Legacy naming left in fork path
Low Severity
The in-place fallback is named legacyFork, and related protocol comments and test titles also use “legacy” vocabulary. Project review rules disallow migration-era terms like legacy in names, comments, and test titles even when an older protocol path remains for compatibility.
Additional Locations (2)
Triggered by project rule: Review rules
Reviewed by Cursor Bugbot for commit 93f9493. Configure here.


Fixes ENG-5180.
What this does
/forkno longer kills the session you fork from. The original keeps running — with its subagents, scheduled heartbeats, and warm state — and stays visible in the agents view. You still land in the new forked chat immediately.What the problem was
Forking used to replace the current session in place: the running session was shut down, its subagents were closed, its scheduled heartbeats were silently handed to the fork, and its identity was taken over. The original survived only as a file on disk and vanished from the session list — "when I do /fork, the original session disappears" (user report).
How it works now
Changes
fork_exportdaemon command plus the client-side fork flow rewrite (+179/−21 source lines across five files).Checks
npm run checkclean; 138 targeted tests pass (108 re-run after merging the newest main).Known cosmetic quirk (pre-existing display behavior, left for a follow-up)
Right after forking, the agents view may briefly group the fork under the original (it is linked as the fork's parent) until the fork's own summary appears; a killed fork also shows as a completed child row when expanding the original. The underlying state is always correct.
Note
Medium Risk
Changes session identity and daemon fork orchestration (create, reattach, kill on failure) with backward compatibility via capability checks; incorrect cleanup or races could strand workers or lose attachment, though tests cover serialization and failure paths.
Overview
Daemon
/forkno longer tears down the source session. When the daemon supportsfork_export, the client exports the chosen branch to a new session file, spawns a new worker on that file, and reattaches you to the fork while the original session keeps running in the list with its subagents, heartbeats, and leases intact.Runtime and protocol:
AgentSessionRuntimeaddsexportForkBranch(sharedresolveForkTarget) to write a branched JSONL file withoutfinishSessionReplacement. The daemon exposesfork_export(schema revision 17) and routes it to the source worker without rebinding cron jobs; legacyforkstill replaces in place for older daemons, non-persisted sessions, or in-process mode.Client orchestration:
DaemonAgentConnection.forkserializes forks and session switches viawithSessionTransition, handles create/reattach failures (orphan file cleanup, kill fork worker, optional reattach to source), and documents extension lifecycle differences inextensions.md.Reviewed by Cursor Bugbot for commit 93f9493. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Keep the original session running when forking in daemon mode
exportForkBranchtoAgentSessionRuntimethat writes a forked session to a new file without replacing the current runtime, leaving the original session active.fork_exportdaemon command (protocol revision 17) that invokesexportForkBranchon the source worker and returns the new session file path.DaemonAgentConnection.forknow usesfork_exportwhen the daemon advertises the capability: it creates a new worker on the exported file and switches the client to it, while the original session and its subagents/leases continue running.Macroscope summarized 93f9493.