Skip to content

fix(server): checkpoint restore ignores the cwd of a provider session shared across threads - #14502

Merged
juliusmarminge merged 1 commit into
t3code/codex-turn-mappingfrom
v2/restore-safety-shared-session
Oct 1, 2026
Merged

juliusmarminge merged 1 commit into
t3code/codex-turn-mappingfrom
v2/restore-safety-shared-session

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Problem

#14370 made isCheckpointRestoreIsolated treat the cwd of every non-stopped provider session bound to another thread as a folder that thread works in. Adapters with sessions.supportsMultipleProviderThreadsPerSession: true (Codex, and OpenCode 2) share one provider session per instance across all threads (providerSessionIdFor in Orchestrator.ts). That session keeps the cwd it was opened with, usually the first thread's folder. So when threads A and B both use Codex in separate worktrees, B's bound session reports A's folder, and A's Revert files too is refused with "File restore requires an isolated worktree". This was seen live on the OpenCode 2 stack: a thread forks, the fork moves to its own worktree, and the source's rollback is refused.

Fix

When collecting another thread's folders, skip sessions whose capabilities say they are shared across threads. Those sessions say nothing about where that thread works: every turn runs in the thread's runtimePolicy.cwd, which is its worktreePath or its project root. The check already collects both, plus its checkpoint scope cwds.

Single-thread sessions (Claude, Cursor, OpenCode 1, ACP, Pi, Grok) keep #14370's rule, including the errored session that still has a live event stream. The session already carries its capabilities, so this needs no new projection columns.

Verification

Run in a fresh worktree off t3code/codex-turn-mapping (f3eb99e83b, which includes the pid-1 guard from #14461). TMPDIR was under /home, and tests ran inside unshare -U --map-current-user -p -f --mount-proc.

  • New case CheckpointRestoreSafety.test.ts owner=shared-provider: the other thread is in a sibling worktree, bound to a running shared session whose cwd is this thread's worktree. It runs the real rollback service against a temp directory.
    • Fails on base with File restore requires an isolated worktree (1 failed, 11 passed).
    • Passes with the fix: the restore runs (["provider", "files"]).
  • vp test run CheckpointRestoreSafety.test.ts CheckpointRollbackService.test.ts runtimeLayer.test.ts: 3 files, 77 tests passed. That includes all of #14370's cases: nested, ancestor, archived-nested, aliased-nested, project, scope, provider, errored-provider, the sibling / stopped-provider / conversation controls, and the runtime-layer admission rejection.
  • vp exec tsc --noEmit -p . in apps/server: exit 0, no error TS.
  • vp lint and vp fmt on the two touched files: clean. No imports were added.

Not run: a live Codex or OpenCode 2 fork-then-rollback repro, or a replay fixture. Replay fixtures create threads with worktreePath: null and roll back with restoreFiles: false, so they never reach this check.

Model: Claude Opus 5.5 (Claude Code)

🤖 Generated with Claude Code


Devin Review

… shared across threads

Codex (and OpenCode 2) open one provider session per instance for every
thread. That session keeps the cwd it was opened with, usually the first
thread's folder, so another thread bound to it looked like it worked in
that folder and blocked its file restore. Skip shared sessions when
collecting another thread's folders; its worktree or project root and
checkpoint scopes already cover where its turns run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XS 0-9 changed lines (additions + deletions). labels Oct 1, 2026
@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 1, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 4154d99

Macroscope's review found this PR approvable — This is a narrowly scoped checkpoint-restore bug fix: pooled provider sessions are no longer treated as evidence of workspace overlap, while exclusive sessions and other isolation checks remain unchanged. A focused regression test covers the new behavior.

You can add or adjust custom eligibility rules. Learn more.

@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire — 4.9 KiB — 6.8 KiB ✅
Codex Thread snapshot wire — 3.7 KiB — 4.9 KiB ✅
Codex Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Codex Live turn WebSocket decoded — 20.4 KiB — 29.3 KiB ✅
Codex Live turn messages — 2 — 8 ✅
Claude Total thread wire — 4.9 KiB — 6.8 KiB ✅
Claude Thread snapshot wire — 3.7 KiB — 4.9 KiB ✅
Claude Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Claude Live turn WebSocket decoded — 20.8 KiB — 29.3 KiB ✅
Claude Live turn messages — 2 — 8 ✅

Baseline: unavailable · PR result: 4154d99 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 106.1 KiB
  • Claude decoded thread snapshot: 106.4 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@juliusmarminge
juliusmarminge merged commit f48d257 into t3code/codex-turn-mapping Oct 1, 2026
26 of 27 checks passed
@juliusmarminge
juliusmarminge deleted the v2/restore-safety-shared-session branch October 1, 2026 01:00
juliusmarminge added a commit that referenced this pull request Oct 1, 2026
Brings in f48d257 (#14502), which only touches CheckpointRestoreSafety.ts
and its test. No conflicts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:XS 0-9 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant