diff --git a/docs/superpowers/specs/2026-06-20-pi-inspect-design.md b/docs/superpowers/specs/2026-06-20-pi-inspect-design.md new file mode 100644 index 0000000..910705b --- /dev/null +++ b/docs/superpowers/specs/2026-06-20-pi-inspect-design.md @@ -0,0 +1,287 @@ +# pi-inspect: dynamic workflow and subagent inspector design + +## Summary + +`pi-inspect` is a single pi package that provides a Claude-Code-style live inspector for running `workflow` and `subagent` tool calls. While work is running, it shows an ambient widget below the input. `Ctrl+G` opens a focusable full-screen overlay where the user can navigate running workflows/subagents, inspect a workflow's named phases and filtered subagents, or watch a subagent's live transcript. + +The package also includes augmented `workflow` and `subagent` tool extensions so the UI and tools ship together, share one in-process state registry, and are not vulnerable to pi auto-updating over local tool edits. + +## Goals + +- Show running workflows/subagents below the input while they are active. +- Use truthful navigation hints; the ambient widget says `Ctrl+G to inspect`, not `↓`, because the pi editor owns arrow keys. +- Provide a navigable overlay list of running items. +- For a standalone subagent, show a live streaming transcript. +- For a workflow, show a two-column full-screen view: phases on the left, subagents filtered by the selected phase on the right. +- Let `enter` on a workflow subagent swap in that subagent's transcript in-place; `esc` returns to the workflow view, then the list, then normal pi. +- Keep `esc` as pure navigation everywhere. +- Let `x` cancel an individual subagent from a subagent detail view. Workflow agents are not individually cancellable. +- Keep the implementation outside pi core. + +## Non-goals + +- Persist finished items after they stop running. Finished results continue to render through normal tool-result rendering. +- Cancel individual workflow agents. +- Patch pi core. +- Build a settings UI; configuration is file-based. +- Replicate Claude Code's exact arrow-down-from-input behavior. pi's widget API is display-only and the input editor owns arrow keys. + +## Packaging + +Everything ships as one pi package, tentatively named `pi-inspect`. + +```json +{ + "name": "pi-inspect", + "keywords": ["pi-package"], + "pi": { + "extensions": ["extensions/*.ts"] + }, + "peerDependencies": { + "@earendil-works/pi-coding-agent": "*", + "@earendil-works/pi-tui": "*", + "@earendil-works/pi-ai": "*", + "@earendil-works/pi-agent-core": "*", + "typebox": "*" + } +} +``` + +The package contains three loaded extension files: + +- `extensions/ui.ts` — inspector UI, event listeners, ambient widget, overlay, `/inspect`, `pi.registerShortcut("ctrl+g", ...)`, and cancel surface. +- `extensions/subagent.ts` — augmented `subagent` tool, forked from the stock extension and extended with structured progress plus per-subagent abort handles. +- `extensions/workflow.ts` — augmented `workflow` tool, forked from the stock extension and extended with structured phase/subagent progress. + +Because the augmented tools live inside the package, users load this package instead of the stock workflow/subagent extensions. The README must document how to disable stock copies or rely on verified load-order override if pi allows duplicate tool-name replacement. + +## Proposed file layout + +```text +pi-inspect/ + package.json + extensions/ + ui.ts + subagent.ts + workflow.ts + src/ + inspect-state.ts + cancel.ts + ui/ + ambient.ts + overlay.ts + workflow-view.ts + transcript.ts + components.ts + test/ + inspect-state.test.ts + render.test.ts + nav.test.ts + README.md +``` + +Responsibilities: + +- `inspect-state.ts`: single in-process registry of running inspectable items and subagent abort handles. +- `ui.ts`: registers pi event listeners and user-facing UI entry points (`/inspect` and `pi.registerShortcut("ctrl+g", ...)`). +- `ambient.ts`: renders the below-input widget. +- `overlay.ts`: renders and handles the level-1 running-item list. +- `workflow-view.ts`: renders and handles phase/subagent workflow inspection. +- `transcript.ts`: renders and handles live transcript views. +- `cancel.ts`: invokes a registered subagent abort handle by id. + +## Runtime data flow + +`ui.ts` listens to pi tool lifecycle events: + +- `tool_execution_start`: if `toolName` is `workflow` or `subagent`, register an item in `inspect-state` keyed by `toolCallId`. +- `tool_execution_update`: update the item from `partialResult.details`. +- `tool_execution_end`: mark the item done or errored, then remove it after a short grace period. + +The ambient widget and overlay read from `inspect-state`. After state changes, the extension requests a render. + +## Structured details + +### Subagent details + +The existing subagent extension already emits useful `details`: + +- `mode`: `single`, `parallel`, or `chain`. +- `results[]`: agent name, task, messages, usage, exit code, step, stderr, model, stop reason, and error message. + +`pi-inspect` augments this with: + +- `abortHandleId` on each cancellable result. +- `exitCode === -1` for running results, preserving the current convention. + +When a child subagent process starts, `extensions/subagent.ts` registers an abort function in `inspect-state` under `abortHandleId`. The function terminates that child process with the same SIGTERM-to-SIGKILL fallback used by the existing top-level abort handling. + +### Workflow details + +`extensions/workflow.ts` emits structured progress: + +```ts +type WorkflowInspectDetails = { + currentPhase?: string; + phases: Array<{ + id: string; + name: string; + status: "pending" | "running" | "done" | "error"; + subagents: Array<{ + id: string; + label: string; + agent?: string; + task: string; + status: "pending" | "running" | "done" | "error"; + messages?: Message[]; + summary?: string; + usage?: unknown; + }>; + }>; +}; +``` + +If the upstream workflow tool already emits a similar structure, adapt to it. If it does not, add this as the stable inspect schema. + +## UI behavior + +### Level 0: normal pi view + +While at least one workflow/subagent is running, `ui.ts` calls: + +```ts +ctx.ui.setWidget("pi-inspect", renderer, { placement: "belowEditor" }) +``` + +The widget shows compact rows and a truthful hint, for example: + +```text +⏳ workflow repo review · phase 2/4 · 3 agents running +⏳ subagent parallel · 2/4 done, 2 running +Ctrl+G to inspect +``` + +When no inspectable items are running, the widget is cleared. + +### Entering navigation + +`ui.ts` registers `pi.registerShortcut("ctrl+g", ...)` to open the inspector overlay. `/inspect` opens the same overlay for users who prefer commands or have shortcut conflicts. + +### Level 1: running item list + +The overlay shows a focusable list of running items. + +Keys: + +- `↑` / `↓`: move selection. +- `enter`: open selected item detail. +- `esc`: close overlay and return to normal pi. + +Footer hint: + +```text +↑↓ select · enter open · esc back +``` + +Rows include kind, status, title, and compact progress counts. + +### Level 2: standalone subagent transcript + +Opening a subagent item shows a live transcript view. + +Content: + +- Header: agent/mode/status/usage. +- Body: assistant text, tool calls, and tool results, updated live. +- Footer: `esc back · x cancel`. + +Keys: + +- `esc`: return to the running item list. +- `x`: cancel this subagent only. + +`esc` never cancels. + +### Level 2: workflow phase view + +Opening a workflow item shows a two-column view. + +Left column: + +- `All` entry. +- Named phases with status icons and subagent counts. + +Right column: + +- Subagents filtered by the selected phase. +- If `All` is selected, all subagents appear grouped or sorted by phase. + +Keys: + +- `↑` / `↓`: move within the focused column. +- `tab` or `→`: move focus from phases to subagents. +- `shift+tab` or `←`: move focus from subagents to phases. +- `enter` on a subagent: swap the overlay content in place to that subagent's transcript. +- `esc`: return to the level-1 running item list. + +Footer hints change with focus: + +```text +↑↓ phases · tab agents · enter open · esc back +↑↓ agents · enter open · esc back +``` + +### Workflow subagent transcript swap + +When `enter` opens a workflow subagent transcript, it uses the same `transcript.ts` renderer. This is not a deeper persistent overlay; it is an in-place mode inside the workflow detail view. + +Keys: + +- `esc`: return to the workflow phase view. +- No `x`; workflow agents are not individually cancellable. + +## Cancel semantics + +- `esc` is pure navigation everywhere. +- `x` only appears in standalone subagent transcript views. +- `x` looks up the selected result's `abortHandleId` in `inspect-state` and invokes the registered abort function. +- Workflow agents do not expose per-agent cancel. +- Normal pi abort behavior remains available outside the inspector. + +If per-subagent abort cannot be made reliable in the first implementation, `x` should be hidden rather than shown as a broken affordance. + +## Edge cases + +- If a viewed item finishes while open, keep rendering its last known state until the user backs out. The level-1 list may drop it after the configured grace period. +- If all items finish while the level-1 list is open, show `No running workflows or subagents` and `esc back`. +- If a workflow lacks structured details, show a degraded single-column view from available text and clearly mark `structured workflow details unavailable`. +- On narrow terminals, the workflow view collapses from two columns to stacked sections. +- Renderers must never emit a line wider than the provided width. +- Components must rebuild themed strings on `invalidate()`. +- Multiple simultaneous workflows/subagents are all listed; the ambient widget shows a configurable maximum and `+N more`. + +## Testing + +Unit tests: + +- `inspect-state`: register/update/end/drop, abort handle registration/removal, multiple concurrent items. +- Renderer width safety: no line exceeds width, hints are truthful, narrow fallback works. +- Navigation state machines: level-1 selection, workflow column focus, transcript swap-in-place, `esc` back behavior, `x` only in standalone subagent transcripts. + +Manual smoke tests: + +1. Install the local package with `pi install /path/to/pi-inspect`. +2. Ensure stock workflow/subagent tools are disabled or overridden. +3. Start a single subagent and verify ambient widget, `Ctrl+G`, transcript, `esc`, and `x` cancel. +4. Start a parallel subagent and verify each running child appears and can be cancelled independently. +5. Start a workflow with named phases and parallel agents; verify phase filtering, transcript swap, live updates, and no per-agent cancel. +6. Verify finished items disappear from the ambient widget. + +## Maintenance + +The package owns its augmented tool copies. When upstream pi changes the stock `workflow` or `subagent` tools, update `extensions/workflow.ts` and `extensions/subagent.ts` from upstream and reapply the small inspect-specific changes: + +- Structured inspect details for workflow. +- `abortHandleId` plus per-child abort registry for subagent. + +Keep these deltas isolated and documented at the top of each augmented tool file.