pi-remote-control/docs/PHASE-0.5-spike-tmux-contro...

5.2 KiB
Raw Permalink Blame History

Phase 0.5 — Spike: tmux Control Mode

Status: ready to start. Owner: single agent, end-to-end. Branch: feat/spike-tmux-cc. Estimated effort: ~2 hours. Trigger: Phase 0 found that tmux pipe-pane is not reliable across alternate-screen transitions. This phase evaluates the alternative.

Background

Phase 0 (PHASE-0-spike-stream.md, report at docs/reference/PHASE-0-report.md) validated the high-level design: pi-in-tmux works, ANSI streaming over WebSocket works, latency is excellent, SSH and WS stay in sync.

But: tmux pipe-pane is fragile. After alternate-screen usage (/settings, full-screen menus) the pipe can detach silently; the client sees a frozen stream. This is a Phase-1-blocker for the tmux/pipe.ts task.

Two known alternatives:

  • (A) Keep pipe-pane, add a watchdog that polls #{pane_pipe} and re-arms when it falls to 0. Simple but races: bytes produced between detach and detection are lost.
  • (B) Use tmux control mode (tmux -CC). tmux exposes a structured event stream to a control client; pane output arrives as framed events. This is the protocol iTerm2 uses for its tmux integration. Multi-client attach still works for normal SSH users.

This spike decides between A and B with evidence.

Goal

Verify that tmux control mode can reliably deliver pane bytes to a Node client across the conditions where pipe-pane fails. Produce a short report and a Go decision for one of the two paths.

Acceptance Criteria

  • A new branch feat/spike-tmux-cc with throwaway PoC code.
  • A Node script that:
    • Spawns a tmux session running pi.
    • Connects to that session as a control client (tmux -CC).
    • Parses the control-mode protocol enough to extract %output events from the pi pane.
    • Streams those bytes to stdout (no WebSocket needed for the spike — raw stdout is fine).
  • A test session that triggers the Phase-0 failure mode:
    1. Pi running normally → bytes flow.
    2. User runs /settings (alternate-screen) → bytes still flow.
    3. User exits settings → bytes still flow.
    4. Run for ≥5 minutes with mixed interactions.
  • Report docs/reference/PHASE-0.5-report.md answering:
    • R-CC-1. Does control mode deliver pane output reliably across alternate-screen transitions?
    • R-CC-2. Latency compared to pipe-pane (rough — same order of magnitude is enough)?
    • R-CC-3. Does a parallel tmux attach SSH client still work while a control-mode client is connected? (P-2 critical.)
    • R-CC-4. Is the control-mode protocol parser non-trivial? Order of complexity estimate.
    • R-CC-5. Verdict: Path B (control mode) or Path A (pipe-pane + watchdog) for Phase 1, with reasoning.

Out of Scope

  • No WebSocket layer (raw stdout suffices to prove the streaming).
  • No reconnect, sequence, snapshot, buffer.
  • No send-keys.
  • No reuse of Phase-0 spike code — start clean.
  • No production-quality parser — minimal viable parser for %output events is enough.

Implementation Notes

  • tmux control mode launch:
    tmux -CC new-session -s pi-cc 'pi'
    
    or attach to an existing detached session:
    tmux new-session -d -s pi-cc 'pi'
    tmux -CC attach -t pi-cc
    
  • Control-mode protocol overview (consult man tmux, search "CONTROL MODE"):
    • Server emits lines like %output %1 <octal-escaped-bytes> for pane output.
    • Other events: %session-changed, %window-add, %begin/%end, %layout-change, etc. — most can be ignored for the spike.
    • Client sends regular tmux commands as plain text; replies are framed by %begin <ts> <num> <flags>%end <ts> <num> <flags>.
  • Parse just %output lines, decode the octal escapes (\NNN in tmux's output → bytes), write bytes to stdout.
  • Spawn tmux as a child process from Node, talk via stdin/stdout pipes.

File Plan

  • New: extensions/remote-control/spike-cc.ts (or .js, whichever is faster). ~100200 lines.
  • New: docs/reference/PHASE-0.5-report.md.
  • No changes to Phase-0 spike files.

Test Protocol (the spike's own QA)

Run for ≥ 5 minutes, in parallel:

  1. Terminal A: npm run spike-cc (your spike runner).
  2. Terminal B: tmux attach -t pi-cc — verify normal SSH-style attach still works alongside the control client.
  3. Terminal A side: confirm bytes keep flowing through these events:
    • Type a prompt and let pi respond.
    • Run /settings, navigate around, exit.
    • Run a longer pi tool call.
    • Resize Terminal B and observe whether the stream stays clean.

If at any point bytes stop flowing without an obvious tmux process exit: the spike failed for Path B and the verdict is Path A.

Exit / Handover

  • Push branch, push report.
  • Update docs/SYNC.md:
    • Remove your active claim.
    • History entry.
    • Phase Gate Table: Phase 0.5 → done, with verdict noted.
  • Based on verdict:
    • If Path B: open follow-up note in SYNC about updating PHASE-1-sidecar.md T-1.1 to specify tmux control mode in tmux/pipe.ts.
    • If Path A: same, but specifying pipe-pane + watchdog.

In either case, do not modify PHASE-1-sidecar.md yourself — that's an orchestrator-level edit and triggers a contract change review.