Skip to content

feat(server): package and apply a thread's git work - #16734

Draft
juliusmarminge wants to merge 1 commit into
t3code/peer/thread-importfrom
t3code/peer/handoff-git
Draft

juliusmarminge wants to merge 1 commit into
t3code/peer/thread-importfrom
t3code/peer/handoff-git

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Part of cross-environment orchestration. A handoff carries a thread's code as well as its conversation: commits not on any remote, plus uncommitted edits, deletes and new files. This PR adds the git half. The next PR wires it into the handoff.

Pack (on the sending side)

  • The working tree becomes a snapshot commit on the branch tip, made in a private index the way checkpoints are, so the user's own staging is untouched. Untracked files are included; ignored files such as .env stay behind. The staged/unstaged split is not kept: on arrival everything shows as unstaged.
  • The bundle holds only what no remote has (--not --remotes): unpushed commits plus the snapshot.
  • Size cap. Over 50 MiB, which is one upload, the handoff is refused with "Push the branch, then hand off again."

Apply (on the receiving side)

  • Base commits. If the bundle needs commits the receiving checkout lacks, it fetches origin and verifies again. If they're still missing, it refuses.
  • The work lands in a new worktree on the branch. The snapshot is restored and the index reset to the tip, so the commits are history and the edits are uncommitted.
  • Existing work is never overwritten.
    • An existing branch moves only forward, using a compare-and-swap update-ref.
    • A branch with commits the handoff lacks is refused as diverged.
    • A branch checked out in another worktree at a different commit is refused.
  • Any failing step undoes the ones before it: the branch ref, the worktree, and the temporary handoff refs.

Verification

  • peer/handoff/HandoffGit.test.ts runs on real git repos: a bare origin and two clones (the laptop and the box). The four tests:
    • Round trip. An unpushed commit plus a modified file, a deleted file, a new file and an ignored .env arrive exactly. The branch tip matches. Status is D old.ts, M app.ts, ?? new.ts, and .env is absent. The laptop's staging and refs are unchanged after packing.
    • Diverged branch. When the box has its own commit on the branch, apply is refused, and the branch, worktrees and refs are exactly as before.
    • Behind branch and rollback. A branch behind the tip moves forward. When a later step fails because the worktree path is taken, the branch is moved back and the user's file in that path is untouched.
    • Fetch and cap. A base pushed after the box cloned (absent from the bundle) is fetched from origin. An incompressible file over 50 MiB is refused, and no bundle is left behind.
  • Mutation-checked: each of these fails a test when removed:
    • the divergence check;
    • rollback;
    • including untracked files;
    • leaving changes uncommitted;
    • the size cap;
    • using a private index;
    • fetching a missing base.
  • Server typechecks clean; lint is clean.

Opus 5.5 via Claude Code.

🤖 Generated with Claude Code

@juliusmarminge
juliusmarminge added this pull request to stack #16656 October 7, 2026 05:41
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Oct 7, 2026
@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 7, 2026
@github-actions

github-actions Bot commented Oct 7, 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 — 5.0 KiB — 6.8 KiB ✅
Codex Thread snapshot wire — 3.8 KiB — 4.9 KiB ✅
Codex Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Codex Live turn WebSocket decoded — 20.9 KiB — 29.3 KiB ✅
Codex Live turn messages — 2 — 8 ✅
Claude Total thread wire — 5.0 KiB — 6.8 KiB ✅
Claude Thread snapshot wire — 3.8 KiB — 4.9 KiB ✅
Claude Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Claude Live turn WebSocket decoded — 21.2 KiB — 29.3 KiB ✅
Claude Live turn messages — 2 — 8 ✅

Baseline: unavailable · PR result: d319008 · Source CI: failure

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: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

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

A handoff has to carry the thread's code, not only its conversation:
commits not on any remote, plus uncommitted edits, deletes and new files.
HandoffGit packs that as one git bundle. The working tree goes in as a
snapshot commit on the branch tip, made in a private index as checkpoints
are, so the user's staging is untouched; ignored files stay behind. The
bundle holds only what no remote has, and over 50 MiB the handoff is
refused with "push the branch".

Applying it fetches the base from origin when the bundle needs it, creates
a new worktree on the branch, restores the snapshot and resets the index to
the tip so the changes show as uncommitted. An existing branch only moves
forward, with a compare-and-swap ref update, and never while another
checkout has it at a different commit. Any failing step undoes the ones
before it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@juliusmarminge
juliusmarminge force-pushed the t3code/peer/handoff-git branch from d319008 to aa1bad8 Compare October 7, 2026 08:24
@juliusmarminge

Copy link
Copy Markdown
Member Author

End-to-end run, two real servers

Two t3 serve processes from the top of this stack, each with its own data directory, on one machine. A laptop (port 3971) and a box (port 3972). Their projects are clones of one bare origin, so they share a repository. An outside agent (OAuth with a pairing code) drives the laptop's /mcp, and real Claude Sonnet 5.5 turns run on both sides. The last part repeats the run over Tailscale HTTPS (https://cups.tail131df4.ts.net:3972).

Git work round-trip: the laptop thread's worktree had an unpushed commit, a modified README.md and an untracked farewell.ts. After the move, the box's worktree had:

  • the same HEAD (005e661…);
  • the same git status --porcelain ( M README.md, ?? farewell.ts);
  • identical sha256 for all three files.

Over Tailscale, a 400 KB unpushed commit plus an edit also arrived with the same HEAD and matching file hashes.

Diverged branch: the box's feature/diverged had a commit the laptop lacked. The move was refused with "feature/diverged here has commits the handed-off work lacks. Reconcile the branches, then hand off again." Afterwards:

  • the box's branch tip was unchanged, and no worktree, refs/t3code/* ref or thread was created;
  • the laptop's HEAD and working tree were unchanged, and the thread was failed and took a new turn ("STILL HERE").

Opus 5.5 via Claude Code.

This branch has not been deployed

No deployments
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:L 100-499 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