Skip to content

relay#529: one Chief of Staff start path; closing a drop-in terminal hands the session back - #570

Merged
barelyworkingcode merged 5 commits into
epic/525-session-adoptionfrom
feat/529-swap
Oct 21, 2026
Merged

barelyworkingcode merged 5 commits into
epic/525-session-adoptionfrom
feat/529-swap

Conversation

@barelyworkingcode

Copy link
Copy Markdown
Owner

Closes #529

One Chief of Staff start path, and closing a drop-in terminal hands the session back headless at once. The tmux respawn-pane swap is split into relay#543 (after relay#536).

What changed

  • Chief of Staff start: every start is headless; the prompt goes through the send door. An old mode: "terminal" request runs the same start and answers mode: "headless". terminal_on_host, terminal_needs_claude and the entry/terminal refusals are gone. Any other mode is still 400 mode_invalid.
  • Hand back: a swap table in cmd/relay/session_swap.go links a drop-in terminal to its held session. When the terminal has ended and the session reads dormant, relay resumes it on the drop-in caller's behalf (resumeSession, the existing path). Local runner sessions and host sessions both start a new generation.
  • Audit: each direction writes a session_swap intent row before it acts and a durable completion row after. With auditing off, drop-in answers 503 audit_unavailable and stops nothing.
  • Event: session.hand_back, with a stable resume code as reason on refusal.
  • fakerelay parity; docs (routes, session-host, audit-log, events, cli, fakerelay, FEATURES G1.16/G1.26/G4.09, threat model 3a and row TM3a.3).

Harness change (reported as a gate change)

cos-start (screen phase, nightly) terminal leg now asserts mode: terminal answers 201 mode: headless, a session row and no terminal row. The terminal argv check and terminal cleanup are gone: the behaviour they checked was removed by the contract (decision 1). New api-phase journey session-swap-back on the local model endpoint.

Notes from review (round 1: no blocking findings)

  • Minor: TestSwapRefusedWhenAuditOff's CLI leg checks only a non-zero exit; the HTTP leg asserts 503 audit_unavailable exactly.
  • Minor: an empty case in the CoS start's kind switch reads awkwardly.
  • docs/FEATURES.md row TM3a.3 is edited because threat-model 3a changed (contract: "3a and its promise row").
  • Theoretical, recorded in the run report, not built: a terminal that exits before the swap link is added is never handed back; a nil session ledger reaching startHandBack; a hand back under a credential revoked while the terminal was open; a slow-host transport error resuming while the terminal may run.

Proof

  • e2e features suite green on 5a49db9 (ok relaye2e/features 235.194s, -race -parallel 32); contract TestSessionsDropIn|TestChiefOfStaffStartEntry green on relay and fakerelay.
  • Stack run r529, api phase, at 5a49db9: pass=8 fail=0 notrun=2; session-swap-back and session-detached-host PASS, local model endpoint only.
  • Real-app check on the stack's signed Relay bundle at 5a49db9: a local headless runner session on the local model; relay drop-in in a real Terminal window opened the same conversation; a send while held answered dropped_in; /exit gave session.hand_back ok; the next message was answered with no Resume; four session_swap rows (pending, ok per direction).
  • Fix attempts: one (journey read id instead of terminalId; caught by the stack run). Review rounds: one. Tokens: about 1.4M across agents.

Review: no blocking findings (round 1, default model)
Journey: session-swap-back PASS on stack r529 at 5a49db9 (api phase, local model endpoint)
Real-app check: stack r529 bundle at 5a49db9: relay drop-in in a real Terminal, send while held dropped_in, /exit handed back (session.hand_back ok), next message answered, four session_swap rows
Harness weakening: no loosening of a kept claim; cos-start terminal leg asserts the new contract (decision 1); new journey session-swap-back
Main harness vs head: epic-branch harness against head 5a49db9 on stack r529, api phase: pass=7 fail=0 blocked=0 notrun=2
Break-and-restore: swapTable.exited made to never report both halves: e2e TestSwapBackResumesAtOnce red and journey session-swap-back FAIL (no session.hand_back); restored byte for byte (sha matches)
Weakening reviewed: TestTerminalList, TestDropInHandsOver, TestChiefOfStaffStart, TestCosStartEntryRefusals, TestChiefOfStaffStartRows/hosted changed assertions only where contract decisions 1, 2 and 7 removed the claim; reviewer confirmed each

🤖 Generated with Claude Code

barelyworkingcode and others added 5 commits October 20, 2026 14:17
…resumes the session at once

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…t yet reviewed)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…re durable

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@barelyworkingcode
barelyworkingcode merged commit 49e2279 into epic/525-session-adoption Oct 21, 2026
@barelyworkingcode
barelyworkingcode deleted the feat/529-swap branch October 21, 2026 06:06
@barelyworkingcode

Copy link
Copy Markdown
Owner Author

merge-check: merged. approved, target, contract, evidence, owner, weakening

@barelyworkingcode

Copy link
Copy Markdown
Owner Author

Merged by merge-check into epic/525-session-adoption: approved, target, contract, evidence, owner, weakening PASS; ci and verified NA.

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.

1 participant