Skip to content

feat: route teleport through disponent local backend#185

Merged
zmaril merged 2 commits into
mainfrom
feat/teleport-via-disponent-v2
Jul 21, 2026
Merged

feat: route teleport through disponent local backend#185
zmaril merged 2 commits into
mainfrom
feat/teleport-via-disponent-v2

Conversation

@zmaril

@zmaril zmaril commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Second pm piece of the disponent migration (pm#152). Stacked on #184 (base = feat/attach-disponent-terminal), so this diff shows only the teleport change. Builds against current disponent main (d77a34e), which has both fields merged: #33 agentCmd (per-dispatch verbatim startup, brief-suppressed) and #74 fetchRemote (fetch gitRef off the clone's origin).

What & why

When PM_LOCAL_BACKEND=disponent, teleport now rides disponent's local tmux backend instead of pm's legacy pm-owned worktree code. Until now the backend gate excluded teleport (!opts.fetchRemote && !opts.startup), because the disponent local backend couldn't fetch a remote branch or run a bespoke startup. Both capabilities are on disponent main now, so teleport's two needs — fetch the cloud worker's pushed branch, and resume the run via claude --teleport <id> — map straight onto them.

Still opt-in; the default PM_LOCAL_BACKEND and the legacy path are untouched (a later stage flips the default + retires the legacy code — not this PR).

Before / After

  • Before (backend on): a plain start-local rode disponent, but teleport fell back to pm's own git worktree + PTY — the disponent path couldn't fetch the cloud branch or run claude --teleport.
  • After (backend on): teleport rides disponent too. disponent fetches the cloud worker's branch off the clone's origin, cuts the worktree at its pushed tip, and runs claude --teleport <id> verbatim in its own dsp-<uid> tmux. The browser terminal (the descriptor-driven attach from feat: attach browser terminal to disponent's transport-neutral terminal #184) attaches straight to that session — no pm-owned worktree/PTY.

How

Verify

  • bun run check, bun run typecheck, full bun test — green, except the one known pre-existing dispatch.test.ts github-proxy env failure, unrelated to this diff.
  • New unit test (tests/local-disponent.test.ts): teleport-shaped opts route through disponent and fetchRemote + startup land on the dispatch spec as fetchRemote / agentCmd / gitRef (spied on the engine's dispatch); a plain start-local leaves both unset.

Rendered proof — honest scope

A true cloud teleport is not reproducible in-container (no real session_… id, no authed claude --teleport <id> resume). So the proof uses an honest substitute: a REAL local tmux dispatch driven through the actual startLocalSession teleport path, with a bare "origin" repo holding a distinctive commit on pm/task-1-demo (reachable only via fetch) and a marker startup standing in for claude --teleport <id>.

What it proves: the loosened gate routes teleport through disponent; fetchRemote checks the worktree out at the fetched remote tip (worktree HEAD 6c2e4e4 == the pushed commit, distinctive remote file present, not local main); agentCmd runs the startup verbatim (capture-pane shows TELEPORT_V2_9f3a); and the browser terminal attaches to the dsp-<uid> session (screenshot: panel shows the marker, tmux status line dsp-019f80:sleep — disponent's session, not pm-session-1).

What it does not prove: the real cloud claude --teleport <id> conversation resume — that needs a live cloud session and is exercised end-to-end only outside the container.

DISPONENT_REF stays at d77a34e (from #184; both fields are on that main).

🤖 Generated with Claude Code

https://claude.ai/code/session_018L3HzzZcSFo8PmygtQZT3M


Generated by Claude Code

When PM_LOCAL_BACKEND=disponent, teleport now rides disponent's local tmux
backend instead of pm's legacy pm-owned worktree code — using the two
per-dispatch fields on current disponent main: fetchRemote (#74, fetch
gitRef off the clone's origin) and agentCmd (#33, a startup run verbatim
with no brief appended).

Previously the backend gate excluded teleport (!opts.fetchRemote &&
!opts.startup), because the disponent local backend couldn't fetch a remote
branch or run a bespoke startup. Both capabilities are on disponent main
now, so teleport's two needs — fetch the cloud worker's pushed branch, and
resume the run via `claude --teleport <id>` — map straight onto them.

How:
- worktree.ts: loosen the gate to `viaDisponent = localDisponentEnabled()`;
  thread opts.fetchRemote / opts.startup through startLocalViaDisponent.
- local-disponent.ts: LocalProvisionArgs gains fetchRemote? / startup?,
  mapped onto the dispatch spec's fetchRemote / agentCmd. A plain
  start-local leaves both unset, so its spec is byte-identical to before.
- The teleport session is just another disponent-local session, so the
  descriptor-driven browser terminal attach from #184 covers its terminal —
  no extra wiring.

Still opt-in behind PM_LOCAL_BACKEND=disponent; the legacy
startLocalViaWorktree path and the default are untouched (a later stage
flips the default and retires the legacy code).

Builds on #184. Part of pm#152.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018L3HzzZcSFo8PmygtQZT3M
Base automatically changed from feat/attach-disponent-terminal to main July 21, 2026 20:59
@zmaril
zmaril marked this pull request as ready for review July 21, 2026 21:03
@zmaril
zmaril enabled auto-merge July 21, 2026 21:03
@zmaril
zmaril merged commit d7244bb into main Jul 21, 2026
10 checks passed
@zmaril
zmaril deleted the feat/teleport-via-disponent-v2 branch July 21, 2026 21:07
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.

2 participants