Skip to content

feat(orchestration-v2): import an existing Claude Code or Codex session by id, with two-way transcript sync - #5499

Closed
Bil0000 wants to merge 215 commits into
pingdotgg:t3code/codex-turn-mappingfrom
Bil0000:feat/import-session-v2
Closed

feat(orchestration-v2): import an existing Claude Code or Codex session by id, with two-way transcript sync#5499
Bil0000 wants to merge 215 commits into
pingdotgg:t3code/codex-turn-mappingfrom
Bil0000:feat/import-session-v2

Conversation

@Bil0000

@Bil0000 Bil0000 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Reimplements #4617 against the orchestration V2 runtime, as requested in #4617 (comment) — plus a safe two-way sync between the imported thread and the provider's own on-disk transcript.

Why

T3 Code can only continue sessions it started. A Claude Code CLI session or a codex thread already on the machine is fully resumable, but there was no way to open it here. The V1 attempt (#4617) was closed because #2829 replaced the orchestration layer it was built on; this is the V2 reimplementation, targeting the #2829 branch.

What

Import session... in the command palette takes one session id.

  • Resolve first. orchestration.resolveImportSession reads the session's working directory and title before anything is created. If a project covers that directory, the thread lands there regardless of which project is open; if not, the dialog relabels to Add project & import and nothing is created without a second press. Unlike V1, Codex sessions resolve too (workspace + title come from the rollout file).
  • Import is all-or-nothing. The transcript is read before anything is written — Claude via the agent SDK (getSessionInfo/getSessionMessages), Codex from its rollout .jsonl under $CODEX_HOME/sessions (no live app-server needed). History is appended as synthetic message.updated/turn-item.updated pairs with deterministic ids — the same mechanism as the legacy V1 thread importer — under a new historyOrigin: "provider_import". There is no create-then-compensate dance: a failed import leaves nothing behind.
  • The next turn resumes the real session. The import synthesizes a provider thread whose nativeThreadRef is the external session id (strength: "strong"; for Claude, nativeConversationHeadRef is set to the last transcript message so the adapter takes the resume path instead of colliding on sessionId). ProviderTurnStartService then resumes natively — the model keeps its full context; nothing is replayed.

Two-way sync

  • T3 → provider comes free. Because the thread resumes the original native session, Claude appends every T3 turn to the original ~/.claude/projects/**/<id>.jsonl, and Codex to its own rollout.
  • Provider → T3 is a lazy sync. On thread reads, ensureSynced re-reads the transcript (throttled by source mtime, serialized per thread, skipped while a run is active) and appends turns made outside T3. Idempotency and safety come from three dedupe layers: deterministic event ids, provider-native item ids already present as turn items, and exact role+text match against native run messages — so T3's own turns echoed back by the provider are never re-imported. Sync state lives in orchestration_v2_session_imports (migration 046).

Verification

  • 8 new server tests: pure transcript-mapper tests plus an integration test that imports a real on-disk Codex rollout into an in-memory V2 store, checks the projection (history origin, messages, provider thread binding), refuses duplicates, and round-trips the provider→T3 sync.
  • 6 new CommandPalette.logic tests (17/17 in the file).
  • fmt, lint, typecheck clean across contracts, server, client-runtime, web (pre-existing @cursor/sdk-related failures unaffected).
  • Live, against a real Claude Code session:
    1. claude -p "Remember this fact for later: the import canary code is FERRET-4413. Reply with exactly: OK" in a project directory.
    2. Palette → Import session... → paste id → thread appears with both prior messages rendered.
    3. Ask "What is the import canary code?" — the resumed session answers FERRET-4413. The canary only exists in the on-disk transcript, so the real session resumed rather than the history being replayed.
    4. The question and answer from step 3 appear in the original ~/.claude/projects/**/<id>.jsonl (T3 → provider).
    5. claude -p --resume <id> "…second canary is BADGER-7788…" in the terminal, reopen the thread in T3 — the CLI turn appears (provider → T3), and T3's own turns are not duplicated.

Demo

https://drive.google.com/file/d/16rBmArbhFZyHfzLWxNY7pxJNyqt7D9hs/view?usp=sharing

Known limits

  • Only plain user/assistant text is imported Solved: tool activity now survives the import — Claude thinking blocks become reasoning items, Bash calls become command items paired with their results, Edit/Write calls become file-change items (other tools get a compact command rendering); same for Codex rollouts (reasoning summaries, function calls paired by call id). Verified live against a real session with tool use.
  • Turns synced from the CLI render above native T3 runs Solved: sync-appended entries take position ordinals after the thread's current maximum, so CLI turns made after T3 turns render chronologically. Verified live (CLI turn after a native T3 turn lands at the bottom).
  • $CODEX_HOME only Solved: rollout discovery resolves the codex instance's configured home from its resolved home layout first, then $CODEX_HOME, then ~/.codex.
  • Codex live resume remains unexercised end-to-end (no Codex auth on the test machine); transcript parsing, resolve, import and sync are covered by the integration test against a real rollout file, and resume goes through the existing thread/resume adapter path.

Note

Add import and two-way sync of Claude Code and Codex sessions into orchestration-v2 threads

  • Adds a full import workflow (SessionImportService) that reads an external Claude Code or Codex session, maps its transcript to deterministic OrchestrationV2 events, and stores it as a new thread with historyOrigin: 'provider_import'.
  • Adds incremental sync (ensureSynced) that detects provider-side conversation added after import, backfills command outputs, and is called automatically on getThreadProjection and subscribeThread.
  • Adds two new WS RPC endpoints (resolveImportSession, importSession) with auth scopes and client-runtime command functions, plus an ImportSessionDialog UI accessible from the command palette.
  • Extends ProjectionStore ordinal logic so that provider-imported runless items are only included in history up to the correct run band when forking.
  • Adds migration 046 creating the orchestration_v2_session_imports tracking table with a unique index on (driver, external_id).
  • Risk: getThreadProjection and subscribeThread now perform a file-system or network read (ensureSynced) on every call for imported threads; failures are swallowed with a warning but add latency.

Macroscope summarized d265cee.

juliusmarminge and others added 30 commits August 5, 2026 15:51
Co-authored-by: codex <codex@users.noreply.github.com>
- Initialize provider as unchecked in a pending state
- Update initial probe message to reflect session-local status
- Type the runtime effect with `Scope`
- Build the ACP session runtime without wrapping it in `Effect.scoped`
- Use strict TurnId and ProviderItemId parsing in Codex session routing
- Decode in-memory stdio chunks in streaming mode to avoid split UTF-8 corruption
- Transfer session-owned scopes into adapter state
- Ensure runtime scopes close on stop and startup failure
- Add regression coverage for scoped lifecycle cleanup
- Close the managed native event logger when the adapter layer tears down
- Make session runtime close idempotent with an atomic closed flag
- Add coverage for flushing thread native logs on shutdown
- Use codex app-server snapshots for auth, models, and skills
- Remove legacy CLI/config discovery paths and related helpers
- Update tests for the new provider status flow
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
- Document the target orchestration graph, IDs, lifecycles, and capability model
- Add Codex app-server probe fixtures and update the probe test harness
- Introduce orchestration v2 service interfaces and error types
- Add replay runtime, fixtures, and integration coverage
- Update shared contracts and probe transcripts

Co-authored-by: codex <codex@users.noreply.github.com>
- Add Codex adapter and replay harness wiring
- Introduce in-memory orchestration projections and provider registry
- Expand orchestration contracts for turn and runtime events
Co-authored-by: codex <codex@users.noreply.github.com>
- Add context transfer IDs, schemas, and projections
- Support cheap fork creation and Codex native fork rollback
- Cover fork idempotency and replay behavior in tests
- Track remaining projection, context transfer, rollback, capability, and subagent work
- Clarify current V2 baseline and debugger-only follow-ups
- Map fork and merge-back turns into stored handoffs and transfer resolutions
- Add shell snapshot projection support plus coverage tests
- Update replay fixtures and web contracts for the new turn flow
Co-authored-by: codex <codex@users.noreply.github.com>
- Move Codex replay recording into `apps/server`
- Add Claude Agent SDK replay fixtures and test harness
- Update orchestration-v2 fixture scenarios and docs
- Move Claude provider runtime logic into its own module
- Share the SDK query runner between live and replay paths
- Add replay driver error wrapping for unexpected failures
- persist the selected model on run records
- surface run model selection in the debug UI
- update replay fixtures and contracts for the new field
- Record Claude SDK transcripts across multiple prompts and restart/query modes
- Add approval and tool-call replay coverage for new orchestration fixtures
- Update Claude adapter testkit to model open/prompt/permission frames
- Derive Claude SDK query options from runtime policy
- Add read-only replay fixture and policy mapping tests
- Reuse shared approval-policy fixtures across orchestrator tests

Co-authored-by: codex <codex@users.noreply.github.com>
- add active steering and interrupt-restart replay fixtures
- update Claude adapter/orchestrator turn handling for steering
- refresh replay and integration test coverage
- add interrupt and mid-tool replay fixtures for Claude and Codex
- log Claude Agent SDK protocol frames to native event traces
- project Codex commandExecution start events into orchestration updates
- Map Cursor SDK agents and runs to V2 thread and turn lifecycles
- Update MCP capability, tool, and testing guidance for SDK-based injection
Co-authored-by: codex <codex@users.noreply.github.com>
@Bil0000
Bil0000 marked this pull request as draft August 14, 2026 11:17
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. and removed vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 14, 2026
@juliusmarminge
juliusmarminge force-pushed the t3code/codex-turn-mapping branch 2 times, most recently from 519c42a to 4c55679 Compare August 17, 2026 10:28
@juliusmarminge
juliusmarminge force-pushed the t3code/codex-turn-mapping branch from 2d623ac to 37f40d9 Compare August 28, 2026 03:30
@YoungPhlo

Copy link
Copy Markdown

Not exactly a helpful comment but I am so excited to see this land and can test on Win11/Linux/macOS for Codex and Claude Code if at all helpful, will otherwise stay out of the way - just really excited.

@juliusmarminge
juliusmarminge force-pushed the t3code/codex-turn-mapping branch 13 times, most recently from 9eeed8c to 8af5734 Compare September 4, 2026 18:23
@juliusmarminge
juliusmarminge force-pushed the t3code/codex-turn-mapping branch 3 times, most recently from b82facd to 2ac9bfe Compare September 5, 2026 04:56
@juliusmarminge

Copy link
Copy Markdown
Member

Closing as part of the open-PR backlog sweep (wave 1).

Reason: Abandoned draft XXL rebuild of closed #4617; import path moved on
Related: #8066 / #10386

Reopen if this is still wanted and you’re willing to rebase onto current main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ 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.

8 participants