diff --git a/AGENTS.md b/AGENTS.md index d988925..b27ec65 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -21,8 +21,8 @@ Applies to entire `pi-subagents` package in this repo root. - `src/tool.ts` / `src/schema.ts` — tool contract and parameter/result types. - `src/wrapper/cli.mjs` — child-session wrapper that writes artifacts/results. - `src/*.test.ts`, `src/wrapper/*.test.ts` — regression tests. -- `docs/specs/` — design docs created during brainstorming before implementation. -- `docs/plans/` — implementation plans and migration notes. +- `docs/superpowers/specs/` — design docs created during brainstorming before implementation. +- `docs/superpowers/plans/` — implementation plans and migration notes. ## Working rules diff --git a/docs/superpowers/specs/2026-04-12-subagent-live-progress-design.md b/docs/superpowers/specs/2026-04-12-subagent-live-progress-design.md new file mode 100644 index 0000000..6c425d1 --- /dev/null +++ b/docs/superpowers/specs/2026-04-12-subagent-live-progress-design.md @@ -0,0 +1,175 @@ +# Subagent Live Progress Rendering Design + +**Date:** 2026-04-12 +**Package:** `pi-subagents` + +## Goal + +Make a running subagent show what the child agent is actually doing instead of collapsing every live update to raw event names like `tool_call` and `tool_result`. + +## Current state + +Today `src/tool.ts` handles every child event with the same parent-facing update: + +- `Running subagent: ${event.type}` + +That loses the useful semantics already present in normalized events: + +- assistant turns may already contain human-readable status text +- tool calls carry actionable args like file paths and commands +- tool results can tell whether a step finished or failed + +`src/wrapper/render.mjs` already renders transcript lines, but its tool fallback is still JSON-shaped and the parent live UI does not reuse it. As a result, the live progress display is much less informative than the underlying event stream. + +## Chosen approach + +Use a **shared progress formatter**. + +Behavior order: + +1. prefer child `assistant_text` when it contains non-empty text +2. otherwise render humanized tool activity from normalized tool events +3. use concise completion/failure wording for tool results based on remembered tool context + +Use the same formatter for: + +- parent live progress updates in `src/tool.ts` +- transcript event rendering in `src/wrapper/render.mjs` + +Keep the wrapper event protocol, runner behavior, artifacts, and `result.json` semantics unchanged. + +## Scope + +### Modify + +- `src/tool.ts` +- `src/wrapper/render.mjs` +- new shared formatter module for normalized progress events +- `src/tool.test.ts` +- `src/wrapper/render.test.ts` + +### Do not modify + +- `index.ts` +- `src/process-runner.ts` +- `src/tmux-runner.ts` +- `src/wrapper/cli.mjs` event/result lifecycle +- `src/wrapper/normalize.mjs` +- artifact layout or `result.json` fields + +## Design + +### 1. Progress priority + +When a normalized event is `assistant_text` and `text` is non-empty: + +- show that text to the parent as the live status +- render that same text in the transcript as today +- do not replace it with a generic tool label + +This matches the product goal best because the child assistant can express intent directly, for example: + +- `I’m inspecting the auth flow now.` +- `I found the schema; next I’m checking validation.` + +Blank assistant text should not generate a noisy no-op status line. + +### 2. Tool activity fallback + +When there is no usable assistant text, render normalized tool events into action text. + +Examples of desired fallback wording: + +- `read` -> `Reading src/auth.ts` +- `grep` -> `Searching code for auth` +- `find` -> `Scanning for *.test.ts` +- `ls` -> `Listing src/` +- `edit` -> `Editing src/tool.ts` +- `write` -> `Writing README.md` +- `bash` -> keep the shortened shell command, because the command already states the action +- unknown tool -> `Running ` + +The formatter should use available arguments conservatively: + +- prefer exact paths, patterns, and commands already present in the event +- do not invent missing detail +- if args are absent, fall back to a generic tool name message instead of guessing + +### 3. Tool result wording + +`tool_result` should not surface as bare `tool_result`. + +Instead, it should render a concise completion/failure message tied to the most recent relevant tool context when available, for example: + +- `Finished reading src/auth.ts` +- `Search finished` +- `Edit failed: src/tool.ts` + +If no matching prior tool context is available, use a conservative generic result line such as: + +- `read finished` +- `grep failed` + +This keeps progress understandable without requiring protocol changes. + +### 4. Shared rendering boundary + +The new shared formatter module owns conversion from normalized child events to user-facing progress text. + +Responsibilities: + +- map known tools to humanized action strings +- preserve assistant text when present +- derive concise result wording from recent tool context +- keep unknown tools conservative + +`src/tool.ts` should use this formatter for parent `onUpdate` messages. + +`src/wrapper/render.mjs` should use the same formatter for transcript event lines so live UI and transcript do not drift. + +The existing transcript header stays unchanged and generic. + +### 5. Failure and noise handling + +Keep behavior minimal and predictable: + +- blank assistant text -> emit nothing +- unknown tool -> generic `Running ` / ` finished` / ` failed` +- no tool context for a result -> generic result wording +- artifact/result writing behavior stays unchanged +- no new event types, no wrapper protocol expansion + +## Testing strategy + +Follow TDD. + +### First failing tests + +1. `src/tool.test.ts` + - assistant text is surfaced directly when present + - fallback tool updates are humanized + - parent progress no longer shows raw `tool_call` / `tool_result` + +2. `src/wrapper/render.test.ts` + - known tools render as action text instead of JSON-shaped fallback lines + - result lines use completion/failure wording + - bash still renders as shortened command text + +### Verification after implementation + +Run at least: + +- targeted test files for touched units +- full package suite: `npm test` + +## Non-goals + +- changing child wrapper completion behavior +- changing normalized event schema +- adding runner-specific progress logic +- redesigning artifact files or transcript headers +- inventing semantic summaries beyond the data already present in events + +## Expected outcome + +After the change, a running subagent will show meaningful status like assistant intent text or readable tool activity instead of raw event-type labels. The parent live UI and saved transcript will use the same progress language while keeping runner behavior, wrapper semantics, and result artifacts stable.