Files
ClaudeDo/docs/superpowers/plans/2026-07-23-conpty-interactive-sessions.md

4.0 KiB
Raw Permalink Blame History

Plan — ConPTY Interactive Sessions

Spec: docs/superpowers/specs/2026-07-23-conpty-interactive-sessions-design.md Date: 2026-07-23

Execution: subagent-driven-development, sonnet model, TDD where meaningful, build + test + commit per task. Stage files explicitly by path (never git add -A). Terminal rendering is visual — flagged for the user's visual pass.

Task 0 — Spike: embed a ConPTY terminal running claude

Not TDD; a throwaway proof. Add a temporary window/view that embeds each candidate control and launches claude in a known worktree.

  • Evaluate SvcSystems.UI.Terminal and Iciclecreek.Avalonia.Terminal.
  • Acceptance: the real claude TUI renders correctly — colors, resize/reflow, and a live permission prompt is usable; input reaches the CLI.
  • Output: pick one library; note the control API (start with cwd/exe/args/env, process-exited event, dispose/kill). Record the decision in the spec.
  • Remove the throwaway harness before Task 1 (or keep as a manual dev sample, not wired into the app).

Stop for the user's visual verification of the spike before continuing.

Task 1 — Worker: interactive launch-spec endpoint

  • Add a Worker service/hub method that, given a taskId, prepares the worktree (session-skills seeding, agent files, MCP config, env — reuse the autonomous run prep path) and returns a LaunchSpec { cwd, exe, args, env }.
  • Reuse WindowsTerminalLauncher.BuildResumeCommand for exe/args.
  • Guards mirror ResumeTaskInTerminal (not Running/Queued, persisted SessionId, worktree Active/Kept). Never-run task → spec without --resume (fresh start).
  • Tests (Worker.Tests, real SQLite/git): guard cases, spec contents for a resumable task, fresh-start case. No real claude in tests.

Task 2 — Worker: ad-hoc launch-spec

  • Method to build a LaunchSpec for a free session in a given directory: MCP config + env set up, no task/session-skills seeding.
  • Tests: env/MCP presence, arbitrary cwd.

Task 3 — UI: terminal host control + view model

  • Wrap the chosen library in an app control/view (e.g. InteractiveTerminalView
    • InteractiveTerminalViewModel) that starts from a LaunchSpec and exposes running/exited state.
  • IWorkerClient: add methods to fetch the task and ad-hoc launch specs; wire the SignalR client + hub method.
  • Update hand-rolled IWorkerClient/hub fakes in BOTH test projects.
  • Tests: view model starts/stops lifecycle with a fake terminal backend; fake worker returns a spec.

Task 4 — Command Center: host interactive panes + entry points

  • MonitorPaneView: autonomous panes keep the streamed log; interactive panes host the terminal control.
  • Entry points: "Open interactive session" from a task (task-based) and a "New session" action (ad-hoc, pick directory).
  • Layout toggle: focus (tabs) ↔ overview (grid); reuse/extend the existing UniformGrid column logic for the grid mode.
  • Tests: view-model level (pane kind selection, layout toggle state). Rendering is a visual-pass item.

Task 5 — Remove the streaming interactive stack

Only after Tasks 14 land and the terminal path works.

  • Worker: delete StreamingClaudeSession, InteractiveSessionService, interactive WorkerHub methods + broadcast events, DI registrations. Verify LiveSessionRegistry / IdleSessionReaper usage first; remove only if unreferenced.
  • UI: remove composer bits on TaskMonitorViewModel, the composer/queued portion of SessionTerminalView, IWorkerClient interactive methods.
  • Update fakes and delete now-dead tests. Full build + all test projects green.

Task 6 — Docs

  • Update docs/open.md with visual-verification items (spike render, terminal resize/focus, grid vs tabs).
  • Update affected per-project CLAUDE.md (Worker interactive removal, UI new terminal host).

Verification gates

  • After Task 0: user visual pass on the spike.
  • After Task 4: user visual pass on Command Center (task + ad-hoc, tabs + grid, permission prompt round-trip).
  • Never claim the terminal UI works without the user running it.