Skip to content

Fix concurrent session resumes with clone-on-write branches - #697

Closed
yxlyx wants to merge 2 commits into
mainfrom
fix/689-session-branching
Closed

Fix concurrent session resumes with clone-on-write branches#697
yxlyx wants to merge 2 commits into
mainfrom
fix/689-session-branching

Conversation

@yxlyx

@yxlyx yxlyx commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Closes #689.

What changed

  • Added --resume SOURCE --branch DESTINATION and /resume SOURCE --branch DESTINATION across the default line session, scripted/TTY REPL, fullscreen TUI, ACP startup, and one-shot runtime paths.
  • Persisted branch ancestry, assigned each branch a fresh cache/session UUID, and atomically claimed new destination names so concurrent creators cannot both win.
  • Seeded fullscreen TUI conversations from provider-native restored history and synchronized messages, goal/todo policy, strict/ultracode state, rename state, meters, and shutdown saves back to the selected durable branch.
  • Added an offline process regression covering source immutability, two live branches, close-order independence, reopen behavior, input-buffer ownership, cache identity, transcript validity, and duplicate-destination races.
  • Recorded the clone-on-write identity contract in ADR 0042.

Why

Problem / failure mode

Two processes resuming the same named session continued writing the same .session.json, so autosaves and shutdown writes could silently replace one continuation with the other. The fullscreen TUI also did not start from the restored provider-native conversation or reliably return its final state to the root session, which made branching only the line REPL insufficient.

Reason for this approach

Clone-on-write gives each continuation an explicit durable identity while preserving the source as a stable common ancestor. A filesystem-exclusive destination claim closes the check-then-create race, and sharing one restore implementation across frontends keeps branch ownership, goal/todo state, compaction, transcripts, and final saves consistent.

Constraints and trade-offs

Branches deliberately do not merge automatically: provider-native tool/reasoning envelopes and compaction boundaries cannot be safely combined by concatenating message arrays. Peer cursor/inbox state is copied once, while git worktree isolation remains a separate user choice. Existing plain /resume SOURCE keeps its same-tip compatibility behavior and therefore remains unsuitable for concurrent continuation.

Rejected alternatives

A process-lifetime lock on the source would prevent corruption by rejecting the second user, but it would not support the requested concurrent work. Last-writer-wins merging was rejected because it preserves neither branch and can create invalid provider history.

Verification

  • Five independent TUI/runtime test agents exercised line REPL, scripted REPL, fullscreen TUI, ACP, one-shot, compaction, shutdown, metadata, malformed names, and concurrency edge cases.
  • python3 scripts/test-session-branching.py ./zig-out/bin/graff
  • Live fullscreen /resume SOURCE --branch DEST PTY regression
  • Fullscreen startup/close-order/duplicate-race stress (8 race rounds)
  • Fullscreen automatic and explicit compaction probes
  • scripts/eval-tier1.sh (1,754 unit tests passed, 1 skipped; 460/460 TUI tests; all 17 PTY guard probes; build/reachability/SDK/invariants green)

yxlyx added 2 commits August 31, 2026 09:16
Concurrent resumes previously shared one durable session identity, so autosaves and shutdown writes could overwrite another continuation. Add clone-on-write resume targets across line, scripted, ACP, and fullscreen TUI paths, claim destination names atomically, and keep provider-native history plus session metadata attached to the selected branch.\n\nRecord the identity contract in ADR 0042 and cover source immutability, branch isolation, ownership stability, cache identity, and destination races with an offline process regression.\n\nCo-Authored-By: Codegraff <blackfloofie@codegraff.com>
Resolve the ADR-number collision by moving the session branching decision to ADR 0048, and retain both the restored scripted-REPL conversation sync and main's usage footer.\n\nCo-Authored-By: Codegraff <blackfloofie@codegraff.com>
@justrach

Copy link
Copy Markdown
Owner

Folded into release/v0.0.282 (#696). ADR remapped 0042 → 0049 (0042 is TUI claims). Closing as superseded.

@yxlyx

yxlyx commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded because GitHub kept this PR pinned to the pre-fix SHA after its head branch was auto-deleted and recreated. Reopening against the current conflict-free head.

@yxlyx yxlyx closed this Aug 31, 2026
cursor Bot pushed a commit that referenced this pull request Aug 31, 2026
yxlyx: --resume SOURCE --branch DEST across REPL/TUI/ACP. ADR number
will be remapped off 0042 (TUI claims) to the next free slot.

# Conflicts:
#	docs/adr/README.md
#	src/main.zig
#	src/session_run.zig
cursor Bot pushed a commit that referenced this pull request Aug 31, 2026
Record the ADR remaps (0049 / 0050) and the extra #694 lifecycle
hardening. Still no tag.
cursor Bot pushed a commit that referenced this pull request Aug 31, 2026
…lose

#697 added one Agent field and tripped the ceiling. Move the worker-line
row test into agent_tests.zig. The grok-spec loopback was closing the
listen socket while accept still ran (BADF); wake, await, then deinit.
cursor Bot pushed a commit that referenced this pull request Aug 31, 2026
The remote advanced from da6511b with #695 while this tip already had
#697/#679/#694 follow-up and the 1848 ratchet.
cursor Bot pushed a commit that referenced this pull request Aug 31, 2026
Remote 282 advanced with the empty-tools serializer while this tip
already had #697/#679 and the 1848 floor. Notes and leftovers now
match the merged revision. No tag.
cursor Bot pushed a commit that referenced this pull request Aug 31, 2026
Same SuperGrok seat, jobs=1. Graff stays unique vs grok and OpenCode
on pass/wall/calls/tokens/list$/RSS. Calls still 52.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make /resume clone-on-write so concurrent TUI sessions can branch safely

2 participants