Skip to content

feat(pair): pair toolkit linking a lead thread to one executor - #628

Merged
rynfar merged 8 commits into
pylonfrom
feat/pair-toolkit
Sep 18, 2026
Merged

rynfar merged 8 commits into
pylonfrom
feat/pair-toolkit

Conversation

@rynfar

@rynfar rynfar commented Sep 18, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Fan-out delegation cold-starts a fresh child in a fresh worktree for every task, and parents poll for results. On 2026-09-17 and 18 that meant 33 Antigravity children and 84 child turns in two days, plus 304 status polls by parents in a week. The direction in #622 is one persistent executor per lead thread instead.

What this adds

A pair MCP toolkit beside the fan-out one. No contract, event, decider, projector, or migration changes.

  • Four tools. pair_start links an executor, pair_handoff sends it a brief, pair_await waits for it and returns its final message and changed files, pair_stop requests an interrupt.
  • Identity in the id. The executor is the delegated child for the reserved key pair, so its id is delegated:<lead>:<16 hex of sha256(lead + "\n" + "pair")>. Every client and the server compute it from the lead's id; nothing records the link. A pair is on when that thread exists and is not archived. The fan-out tools refuse the key with DelegationKeyReservedError.
  • One worktree. The executor is created with the lead's branch and worktreePath. No worktree is created or cleaned up, and there is nothing to merge back.
  • Always implements. The executor is created in the default interaction mode even when the lead is in plan mode.
  • Idle, not queued. An executor is created without a first message and reads as idle until it is briefed.
  • Steer once. A brief to a running executor is refused unless steer: true. The steer message id is derived from the turn id, so one steer per turn holds across restarts.
  • Waiting costs no tokens. pair_await blocks inside the tool call. The cap follows the lead's provider: 150 seconds where Pylon sets that provider's MCP tool timeout itself (Codex), 45 seconds elsewhere. Omitting maxSeconds does not wait.
  • Same kill switch. Every tool requires the existing delegation capability.

Not covered

  • No UI. A pair starts when an agent calls pair_start, normally because the user asked.
  • The lead's own subagents are not yet turned off while paired. That is Phase 1b.
  • No reaper, lifecycle, or rollback coupling between lead and executor. That is Phase 1c.
  • Pylon's MCP tool list is static, so these tools are listed for every session; the handlers refuse calls without the capability or without an executor.
  • No live provider run.

Verification

Run independently by the lead in the executor's worktree, not taken from its report:

  • vp test run apps/server/src/mcp/toolkits/pair apps/server/src/mcp/toolkits/delegation apps/server/src/mcp/McpHttpServer.test.ts packages/client-runtime/src/work-log/presentation.test.ts: 8 files, 221 tests passed.
  • vp run -F t3 typecheck and vp run -F @t3tools/client-runtime typecheck: exit 0.
  • vp run knip:check: clean.
  • The contract (pair/tools.ts) and the 37 pair tests were written by the lead before implementation and are byte-identical after it (blob hashes checked). All 37 failed against stubs first.
  • Guard-rail files untouched: decider.ts, projector.ts, migrations, packages/contracts, ws.ts.

Part of #622.

Contract, tests, docs, and review by Claude Fable 5.1 in Claude Code; handlers and rules implemented by Gemini 3.8 Flash (High) in Antigravity, as a Pylon delegated child.

@vercel

vercel Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
pylon-marketing Ready Ready Preview Sep 18, 2026 3:18pm UTC

@github-actions github-actions Bot added size:XXL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Sep 18, 2026
@rynfar rynfar changed the title feat(pair): the pair executor toolkit feat(pair): pair toolkit linking a lead thread to one executor Sep 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.9 KiB 13.9 KiB +1 B (+0.0%) 15.1 KiB ✅
Codex Thread snapshot wire 7.2 KiB 7.2 KiB +8 B (+0.1%) 7.3 KiB ✅
Codex Live turn WebSocket wire 6.7 KiB 6.7 KiB −7 B (−0.1%) 7.8 KiB ✅
Codex Live turn WebSocket decoded 58.0 KiB 58.0 KiB 0 B (0.0%) 66.4 KiB ✅
Codex Live turn messages 9 9 0 (0.0%) 21 ✅
Claude Total thread wire 14.0 KiB 13.9 KiB −31 B (−0.2%) 15.1 KiB ✅
Claude Thread snapshot wire 7.2 KiB 7.2 KiB −5 B (−0.1%) 7.3 KiB ✅
Claude Live turn WebSocket wire 6.7 KiB 6.7 KiB −26 B (−0.4%) 7.8 KiB ✅
Claude Live turn WebSocket decoded 58.9 KiB 58.8 KiB −44 B (−0.1%) 66.4 KiB ✅
Claude Live turn messages 9 8 −1 (−11.1%) 21 ✅

Baseline: 315445b · PR result: 23b3c0f · 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: 115.6 KiB
  • Claude decoded thread snapshot: 116.3 KiB

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

@rynfar
rynfar merged commit e22fa15 into pylon Sep 18, 2026
20 checks passed
@rynfar
rynfar deleted the feat/pair-toolkit branch September 18, 2026 15:33

This branch was successfully deployed

1 active deployment
Preview — 23b3c0f9 Deployed Sep 18, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 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