Skip to content

feat(web): pair a thread with an executor from the composer - #636

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

rynfar merged 8 commits into
pylonfrom
feat/pair-control

Conversation

@rynfar

@rynfar rynfar commented Sep 18, 2026 •

Copy link
Copy Markdown
Collaborator

What

Adds the Pair control to the web composer, beside the model picker. One click opens it, one picks the executor's model, one turns the pair on.

  • Off: the trigger reads "Pair". The panel holds the switch, a one-line explanation, and the executor model picker. The picker starts from the project's default delegation model, or opens on the first provider that actually has models.
  • On: the trigger shows the executor's model, and a dot when the executor needs an approval or an answer. The panel shows what the executor is doing and links to its thread. The executor's model is fixed while the pair is on.
  • The switch says why it cannot change: the lead is mid-turn ("Changes apply between turns."), no executor model is chosen, the lead is on Antigravity, or Pylon delegation is off. The last one matters because the server only gives a lead its pair tools while delegation is on, so a pair started without it would create an executor nothing could brief. Turning a pair off is never blocked by it.
  • Turning on creates the executor thread under the deterministic pair id, in the lead's branch and worktree; if that id already exists as an archived executor it is unarchived instead. Turning off deletes an executor that was never briefed and archives one with history. An idle lead's session is stopped after a change so the next turn starts with the right tools and instructions.
  • The control is not shown on a delegated thread.

How

The client only dispatches existing thread commands (create, unarchive, archive, delete, stopSession); nothing on the server or in the contracts changes. Decisions live in pure functions (pairControl.logic.ts, initialExecutorInstanceId), the hook (usePairControl.ts) wires them to commands, and PairControl.tsx renders. ChatView.tsx is untouched.

Verification

  • vp test run on PairControl.test.tsx, pairControl.logic.test.ts, ProviderModelPicker.test.tsx: 36 passed.
  • Web typecheck: 0 errors. Lint on the changed files: no new warnings. vp run knip:check: clean.
  • In the browser against an isolated test server: the control renders beside the model picker; the panel opens; turning off deleted a never-briefed executor and the sidebar count dropped; the switch was blocked with "Choose an executor model first."; the picker opened on a provider with models; after choosing a model, turning on recreated the executor and the control read "Pair with Claude Sonnet 5: Waiting for a brief"; turning off again returned it to "Pair".
  • Not run: the delegation-off reason in the browser (covered by unit tests only), and the unarchive path for an executor with history.

Known limits

Part of #622.

Model: Claude Fable 5.1 (lead) with an Antigravity executor, in Pylon via the Claude Code harness.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

@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 4:48pm UTC

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XL labels 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 14.0 KiB 13.9 KiB −8 B (−0.1%) 15.1 KiB ✅
Codex Thread snapshot wire 7.2 KiB 7.2 KiB 0 B (0.0%) 7.3 KiB ✅
Codex Live turn WebSocket wire 6.7 KiB 6.7 KiB −8 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 −54 B (−0.4%) 15.1 KiB ✅
Claude Thread snapshot wire 7.2 KiB 7.2 KiB −9 B (−0.1%) 7.3 KiB ✅
Claude Live turn WebSocket wire 6.8 KiB 6.7 KiB −45 B (−0.7%) 7.8 KiB ✅
Claude Live turn WebSocket decoded 58.9 KiB 58.8 KiB −88 B (−0.1%) 66.4 KiB ✅
Claude Live turn messages 10 8 −2 (−20.0%) 21 ✅

Baseline: 2b6007f · PR result: d6dd251 · 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.7 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 8f2df02 into pylon Sep 18, 2026
19 checks passed
@rynfar
rynfar deleted the feat/pair-control branch September 18, 2026 19:49

This branch was successfully deployed

1 active deployment
Preview — d6dd2513 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:XL 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