---
name: pi-subagents
description: |
  Delegate work to builtin or custom subagents with single-agent, chain,
  parallel, async, forked-context, and intercom-coordinated workflows. Use
  for advisory review, implementation handoffs, and multi-step tasks where a
  single agent should stay in control while other agents contribute context,
  planning, or execution.
---

# Pi Subagents

This skill is for the main parent orchestrator only. Do not inject or follow it inside spawned child subagents. The parent session owns delegation, orchestration, review fanout, and final fix-worker launches; child subagents should receive concrete role-specific tasks. Ordinary children should not run their own subagent workflows; the explicit exception is a delegated fanout child whose resolved builtin `tools` includes `subagent`, and that child may use `subagent` only for the fanout work the parent assigned.

Use this skill when the parent orchestrator needs to launch a specialized subagent, compose multiple agents into a workflow, or create/edit agents and chains on demand.

## When to Use

- **Complex work orchestration**: use Fable mode as the default parent-agent loop for complex work. Complex means the task has multiple moving parts, unclear acceptance, cross-cutting code, meaningful user-visible impact, expensive or irreversible validation, broad review surface, or the user asks for orchestration. Lightweight one-off delegation can stay lightweight.
- **Advisory review**: use fresh-context `reviewer` agents for adversarial code review, or fork to `oracle` when inherited decisions and drift matter
- **Implementation handoff**: have `oracle` advise, then `worker` implement only after an approved direction
- **Recon and planning**: use `scout` or `context-builder`, then `planner`
- **Parallel exploration**: run multiple non-conflicting tasks concurrently
- **Regular skill specialists**: when discovery shows proactive skill subagent suggestions and the current work is broad enough, launch a small fresh-context fanout that asks one subagent per relevant regularly used skill to apply that skill's perspective to the task
- **Long-running work**: launch async/background runs and inspect them later. For mutation-capable work, bound the delivery slice and elapsed runtime, then request checkpoints after active tool work returns. Reserve hard turn and tool-call caps for explicitly read-only children.
- **Subagent control**: watch needs-attention signals and soft-interrupt only when a delegated run is genuinely blocked
- **Agent authoring**: create, update, or override agents and chains for a project

## Tool vs Slash Commands

Agents can use the `subagent(...)` tool directly for execution, management, status, and control.
Humans often use the slash-command layer instead:

- `/run` — launch a single agent
- `/chain` — launch a chain of steps
- `/parallel` — launch top-level parallel tasks
- `/run-chain` — launch a saved `.chain.md` or `.chain.json` workflow
- `/subagent-cost` — show parent plus child token usage and cost for the session
- `/subagents-fleet` — open the live, inspection-only foreground/async fleet; `Ctrl+Alt+F` opens it during an active foreground turn, `↑↓`/`jk` selects children, and `PgUp`/`PgDn` scrolls transcript detail
- `/subagents-doctor` — diagnose setup, discovery, async paths, and intercom bridge state
- `/subagents-models [agent]` — show the live runtime-loaded builtin model mapping
- `/subagents-profiles`, `/subagents-load-profile`, `/subagents-refresh-provider-models`, `/subagents-generate-profiles`, `/subagents-check-profile` — manage model profiles and provider catalogs
- `/prompt-workflow` and `/chain-prompts` — run prompt templates through native subagent single/chain workflows

Prefer the tool when you are writing agent logic. Prefer the slash commands when
you are guiding a human through an interactive flow.

Packaged prompt shortcuts are also available for repeatable workflows. Treat them as reusable orchestration recipes, not just human slash commands. When the user asks for one of these shapes, or when the workflow clearly fits, apply the same pattern directly with `subagent(...)` and other tools:
- `/parallel-review` — fresh-context reviewers with distinct review angles, then synthesis
- `/review-loop` — parent-orchestrated worker, fresh-reviewer, and fix-worker cycles until clean or capped
- `/parallel-research` — combine `researcher` and `scout` for external evidence plus local code context
- `/parallel-context-build` — parallel `context-builder` passes that produce planning handoff context and meta-prompts
- `/parallel-handoff-plan` — external-reference research plus local `context-builder` passes, followed by a synthesis handoff plan and implementation-ready meta-prompt
- `/gather-context-and-clarify` — scout/research first, then ask the user clarifying questions with `interview`
- `/parallel-cleanup` — two fresh-context reviewers (deslop + verbosity passes) for an adversarial cleanup review of the current diff

## Applying Prompt Techniques Without Slash Commands

The prompt templates in `prompts/` encode workflows the parent agent can run on demand. If the user provides a URL, issue, PR, plan, local file, screenshot, or freeform target, treat that target as the primary scope: read or fetch it before launching children, then include it explicitly in every child task. Do not depend on the parent conversation history when the recipe calls for fresh context.

### Parallel review technique

Use this when the user wants adversarial review of a diff, plan, issue, file, or implemented work. Launch fresh-context `reviewer` agents with distinct angles generated from the actual target. Common angles are correctness/regressions, tests/validation, and simplicity/maintainability; adapt for TypeScript, UI, security, docs, or large structural changes. Reviewers should inspect files and diffs directly, return concise evidence-backed findings with file/line references, and avoid edits unless the user explicitly asks for a writer pass. The parent synthesizes fixes worth doing now, optional improvements, and feedback to ignore/defer before applying anything.

### Proactive skill-specialist technique

Use this when `{ action: "list" }` reports proactive skill subagent suggestions and the user's task would benefit from perspectives the parent regularly uses. These suggestions are conservative: a skill is recommended only when it is available and referenced repeatedly by configured agents or saved chains. Treat the list as an opt-in hint for the current task, not a command to always fan out.

Default guardrails:
- Keep the fanout small: usually one or two skill-specialist children, never more than the listed recommendations or configured cap.
- Prefer `context: "fresh"` and include only the files, diff, plan, URL, or request details each child needs. Use forked context only when private/session history is essential and appropriate to share.
- Use read-only agents for analysis/review unless implementation was explicitly requested; do not create several writers in the same worktree.
- Skip proactive skill subagents for tiny questions, direct commands, highly private requests, or when the user asks not to delegate.
- Make cost and concurrency visible by using an ordinary `subagent(...)` call rather than hidden/background automation.

Example shape:

```typescript
subagent({
  tasks: [
    { agent: "reviewer", task: "Apply the available 'deslop' skill to review the current diff for concrete cleanup findings only. Do not modify files.", skill: "deslop" },
    { agent: "reviewer", task: "Apply the available 'accessibility' skill to review the UI changes for concrete issues only. Do not modify files.", skill: "accessibility" }
  ],
  context: "fresh",
  concurrency: 2
})
```

### Review-loop technique

Use this when the user wants implementation or current diff review to continue until reviewers stop finding fixes worth doing now. Keep the loop in the parent session: one async `worker` implements or fixes, fresh-context `reviewer` agents inspect the actual repo and diff, the parent synthesizes accepted fixes, and one async forked `worker` applies them. The parent can express the sequence up front as an async/background chain when the workflow is known, or continue with explicit follow-up subagent runs after each async completion. For an initial chain, pass `async: true` so the main chat is unblocked; do not set `clarify: true` unless the user explicitly wants the foreground clarify UI. Treat an async implementation worker handoff as an intermediate state, not final completion, unless the user explicitly asked for worker-only work, review-only output, or to stop after implementation. Stop when reviewers find no blockers or fixes worth doing now, remaining feedback is optional or deferred, an unapproved product/scope/architecture decision appears, or the max review-round cap is reached. Default to 3 review rounds unless the user sets a different cap. Do not loop for optional polish, and do not let children launch subagents or decide the loop outcome.

As a conservative orchestration policy, do not pass `turnBudget` or a hard `toolBudget` to an implementation worker, fix worker, reviewer with edit authority, or other mutation-capable child. The default tool budget blocks read/search tools rather than mutation tools, but count limits still do not measure delivery safety. Use a narrow task plus an outer elapsed deadline with enough margin, then request a checkpoint after the current tool returns. The checkpoint should report changed files, build/test state, remaining work, and commit or PR state. An elapsed timeout is not a mutation-safe boundary and must not be used as the checkpoint trigger.

### Parallel research technique

Use this when the question needs both external evidence and local implications. Combine `researcher` for official docs, specs, ecosystem behavior, recent changes, benchmarks, and primary sources with `scout` for repository files, patterns, constraints, tests, and likely integration points. Give each child a distinct angle: external evidence, local code context, and practical tradeoffs. Ask for source links or file ranges, confidence level, gaps, and decision implications. Do not ask these children to edit unless implementation was explicitly requested.

### Parallel context-build technique

Use this before planning or implementation when a stronger handoff is needed. Run a chain with one parallel step of `context-builder` agents rather than top-level parallel tasks, so relative output files live under the temporary chain directory. Give every task a distinct output path such as `context-build/request-and-scope.md`, `context-build/codebase-and-patterns.md`, and `context-build/validation-and-risks.md`. Choose two or three builders: request/scope, codebase/patterns, and validation/risks. Each builder must read every relevant file needed to understand its slice, follow imports/callers/tests/docs/config, conduct tool-available web research when needed, and include a compact `meta-prompt` section. The parent synthesizes the outputs into important context, recommended next meta-prompt, open questions, assumptions, and artifact paths.

Example shape:

```typescript
subagent({
  chain: [{
    parallel: [
      { agent: "context-builder", task: "Build request/scope context for: ...", output: "context-build/request-and-scope.md" },
      { agent: "context-builder", task: "Build codebase/pattern context for: ...", output: "context-build/codebase-and-patterns.md" },
      { agent: "context-builder", task: "Build validation/risk context for: ...", output: "context-build/validation-and-risks.md" }
    ]
  }],
  context: "fresh"
})
```

### Parallel handoff-plan technique

Use this when the user needs a solution brief or implementation-ready handoff from an external reference plus local code context, such as “study this library behavior, inspect our codebase, then produce a worker prompt.” Run a chain with a first parallel group and a second synthesis `context-builder` step. The first group usually includes `researcher` for external projects/docs/prompt guidance and `context-builder` for local code context; add a second `context-builder` for implementation strategy only when the scope is large enough to benefit. Use distinct output paths under `handoff/`, then have the synthesis `context-builder` read those outputs and write `handoff/final-handoff-plan.md` with the recommended approach, likely files, constraints, non-goals, validation, risks, unresolved questions, and final compact implementation-ready meta-prompt.

Example shape:

```typescript
subagent({
  chain: [
    { parallel: [
      { agent: "researcher", task: "Research the external reference and transferable implementation ideas for: ...", output: "handoff/external-reference.md" },
      { agent: "context-builder", task: "Build local codebase context for: ...", output: "handoff/local-context.md" },
      { agent: "context-builder", task: "Compare evidence and propose implementation strategy for: ...", output: "handoff/implementation-strategy.md" }
    ] },
    { agent: "context-builder", task: "Read {previous} and synthesize the final handoff plan and implementation-ready meta-prompt.", output: "handoff/final-handoff-plan.md" }
  ],
  context: "fresh"
})
```

### Gather-context-and-clarify technique

Use this at the start of non-trivial work. Launch `scout` for local context and `researcher` only when external docs, recent sources, ecosystem context, or primary evidence would materially improve understanding. Ask children for concise findings plus remaining clarification questions. Then synthesize what is known and use `interview` to ask the unresolved questions needed for shared understanding before planning or implementing.

### Parallel cleanup technique

Use this after implementation when the user wants cleanup review or when a final pass would reduce AI-slop. Launch two fresh-context `reviewer` tasks with `output: false` and `progress: false`: one deslop pass and one verbosity pass. If the `deslop` or `verbosity-cleaner` skills are available, pass the relevant skill to that reviewer; otherwise inline the criteria. Both reviewers are review-only and should flag concrete issues with severity, file/line references, and smallest safe fixes. Phrase the constraint as “Do not modify project/source files; returning findings through the configured output artifact is allowed” when you use `output` or `outputMode: "file-only"`. The parent decides what to apply and asks before making changes unless cleanup was already authorized.

### Staged fix orchestration technique

Use this when a broad diff has known reviewer findings across several items and the user wants the parent to “orchestrate subagents like a boss.” Keep the active worktree safe with a three-stage chain:

1. A parallel read-only planning fanout, one planner/reviewer per issue cluster. Each child inspects the real diff and returns exact files, line refs, proposed fixes, and focused validation. They must not edit.
2. One writer worker. It receives the planner summaries through `{previous}`, the parent’s accepted scope, stop rules, and verification contract. It is the only child allowed to edit the active worktree.
3. A parallel read-only validation fanout. Validators inspect the worker diff from fresh context with distinct angles, report pass/fail, remaining blockers, and missing verification.

Prefer `async: true`, `context: "fresh"` for planners/validators, `outputMode: "file-only"` for large summaries, and per-stage output names that will not collide. Add `phase` and `label` to make async status readable, and use `as` plus `{outputs.name}` when a later step needs a specific earlier result instead of the whole `{previous}` blob. Use this pattern instead of launching several writer workers into a dirty worktree. Include non-blocking suggestions in the writer prompt only when they are small, safe, and do not expand product scope; otherwise record them as deferred.

When the first step can return a structured target list, prefer dynamic fanout instead of hand-authoring a static parallel group. Use `outputSchema` and `as` on the producer, then an `expand` step with `from: { output, path }`, an explicit `maxItems`, one `parallel` child template, and `collect.as`. Item templates may use `{item}` or a named item such as `{target.path}`. Do not use dynamic fanout for prose outputs, nested fanout, dynamic agent selection, reducers, `when` conditions, or arbitrary expressions; `.chain.md` does not support this syntax, so use direct JSON or a saved `.chain.json`.

Example shape:

```typescript
subagent({
  async: true,
  context: "fresh",
  chain: [
    { parallel: [
      { agent: "reviewer", phase: "Planning", label: "Deploy docs", as: "deployPlan", task: "Plan fixes for deploy docs/workflow. Inspect the current diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/deploy.md", outputMode: "file-only" },
      { agent: "reviewer", phase: "Planning", label: "Scheduler contract", as: "schedulerPlan", task: "Plan fixes for scheduler contract. Inspect the current diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/scheduler.md", outputMode: "file-only" },
      { agent: "reviewer", phase: "Planning", label: "Sandbox/security", as: "sandboxPlan", task: "Plan fixes for sandbox/security. Inspect the current diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/sandbox.md", outputMode: "file-only" }
    ], concurrency: 3 },
    { agent: "worker", phase: "Implementation", label: "Apply accepted fixes", as: "workerResult", task: "Apply only the accepted fixes from these planning summaries. You are the sole writer for the active worktree. Run focused validation and report changed files, commands, failures, and remaining issues.\n\nDeploy plan:\n{outputs.deployPlan}\n\nScheduler plan:\n{outputs.schedulerPlan}\n\nSandbox plan:\n{outputs.sandboxPlan}", output: "worker/fixes.md", outputMode: "file-only", progress: true },
    { parallel: [
      { agent: "reviewer", phase: "Validation", label: "Deploy/scheduler validation", task: "Validate the post-worker diff for deploy and scheduler fixes. Start from the worker result: {outputs.workerResult}. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "validation/deploy-scheduler.md", outputMode: "file-only" },
      { agent: "reviewer", phase: "Validation", label: "Sandbox validation", task: "Validate the post-worker diff for sandbox/security fixes. Start from the worker result: {outputs.workerResult}. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "validation/sandbox.md", outputMode: "file-only" }
    ], concurrency: 2 }
  ]
})
```

## Builtin Agents

Builtin agents load at the lowest priority. Project agents override user agents,
and user/project agents override builtins with the same name.

| Agent | Purpose | Model | Typical output / role |
|-------|---------|-------|------------------------|
| `scout` | Fast codebase recon | inherits default | Writes `context.md` handoff material |
| `planner` | Creates implementation plans | inherits default | Writes `plan.md` |
| `worker` | Implementation and approved oracle handoffs | inherits default | Single-writer implementation with decision escalation |
| `reviewer` | Review-and-fix specialist | inherits default | Can edit/fix reviewed code |
| `context-builder` | Requirements/codebase handoff builder | inherits default | Writes structured context files |
| `researcher` | Web research brief generator | inherits default | Writes `research.md` |
| `delegate` | Lightweight generic delegate | inherits default | No fixed output; generic delegated work |
| `oracle` | Decision-consistency advisory review | inherits default | Advisory review, intercom coordination |

Builtin agents inherit the current Pi default model unless a run, user setting, project setting, or `subagents.defaultModel` overrides `model`. Set `subagents.defaultModel` when subagents should use a different default model than the parent session. Override builtin defaults before copying full agent files when a small tweak is enough.

For one run, use inline config:

```text
/run reviewer[model=anthropic/claude-sonnet-4] "Review this diff"
```

For persistent tweaks, edit `subagents.agentOverrides` in user or project settings. User overrides apply everywhere. Project overrides apply only in that repo and win over user overrides. Use `/subagents-models` or `subagent({ action: "models" })` to inspect the live mapping after settings and overrides load.

Model ids do not have to be exact. Separator variations (`claude-haiku-4.5` vs `claude-haiku-4-5`), case (`Claude-Sonnet-4`), and optional trailing date stamps (`claude-haiku-4-5-20251001`) all resolve to the same registry model. Exact `provider/id` wins; a qualified `provider/model` never switches providers. To constrain subagents to a budget or compliance profile, set `subagents.modelScope: { enforce: true, allow: ["anthropic/*", "openai/gpt-5-*"] }` in user or project settings. Out-of-scope models you pass explicitly error and abort; models inherited from frontmatter, `subagents.defaultModel`, agent frontmatter, or the parent session only warn.

For model fleets, use the profile commands instead of hand-editing repeated overrides: `/subagents-refresh-provider-models <provider>`, `/subagents-generate-profiles <provider>`, `/subagents-load-profile <name>`, and `/subagents-check-profile <name>`. Profiles live under `~/.pi/agent/profiles/pi-subagents/` and replace only `settings.subagents` when loaded.

## Prompting role subagents

Builtin role agents inherit the current Pi default model unless you override them. When launching them, write the task prompt as a compact contract, not a long procedural script. Define the destination and let the role choose the efficient path.

A strong subagent prompt usually includes:
- **Goal**: the concrete outcome the child should produce.
- **Context/evidence**: relevant plan paths, files, diffs, decisions, or user constraints already approved.
- **Success criteria**: what must be true before the child can finish.
- **Hard constraints**: true invariants only, such as no edits for review-only tasks, one writer thread, child must not run subagents unless it is an explicitly assigned `tools: subagent` fanout child, or escalation for unapproved decisions.
- **Validation**: targeted checks to run, or the next-best check when validation is impossible.
- **Output**: the expected summary shape, artifact path, or finding format.
- **Stop rules**: when to ask via `intercom`, when to stop after enough evidence, and when not to keep searching.

Avoid carrying over old prompt habits that over-specify every step. Use `must`, `always`, and `never` for real invariants; for judgment calls, give decision rules. For example, tell a reviewer to inspect the staged diff directly and report only evidence-backed findings, rather than prescribing every file or command. Tell a researcher the retrieval budget: start with broad targeted searches, fetch only the strongest sources, search again only when a required fact is missing, then stop.

For implementation handoffs, name the approved scope and success criteria more clearly than the process. Good prompts say what to change, what not to change, where the evidence lives, how to validate, and when to escalate. They should not ask the child to create another subagent plan or continue the parent conversation.

Settings locations:
- User scope: `~/.pi/agent/settings.json`
- Project scope: `.pi/settings.json`

Direct settings example:

```json
{
  "subagents": {
    "agentOverrides": {
      "reviewer": {
        "model": "anthropic/claude-sonnet-4",
        "thinking": "high",
        "fallbackModels": ["openai/gpt-5-mini"],
        "acceptanceRole": "read-only"
      }
    }
  }
}
```

Useful override fields: `model`, `fallbackModels`, `thinking`,
`systemPromptMode`, `inheritProjectContext`, `inheritSkills`, `defaultContext`,
`acceptanceRole`, `disabled`, `skills`, `tools`, and `systemPrompt`. Use
`acceptanceRole: false` to clear an override. Create a user or project
agent with the same name only when you want a substantially different agent.

If a provider rejects model IDs with thinking suffixes, use
`subagents.disableThinking: true` in user or project settings to clear bundled
builtin thinking defaults globally. A higher-precedence per-agent `thinking`
override can opt one builtin back in.

Tool description modes live in `~/.pi/agent/extensions/subagent/config.json`, not `subagents` settings. Set `toolDescriptionMode` to `compact` to reduce tool-description prompt cost while keeping the execution, async/`subagent_wait`, child-safety, one-writer, management/action, and artifact/status guardrails. Set it to `custom` to read `subagent-tool-description.md` from the project config dir or agent dir; invalid custom files fall back to full mode and the safety guidance is still appended.

## Discovery and Scope Rules

Agent files can live in:
- `~/.pi/agent/agents/**/*.md` — user scope
- `.pi/agents/**/*.md` — canonical project scope
- legacy `.agents/**/*.md` — still read for compatibility, but `.pi/agents/` wins on conflicts

Chains live in:
- `~/.pi/agent/chains/**/*.chain.md` and `~/.pi/agent/chains/**/*.chain.json` — user scope
- `.pi/chains/**/*.chain.md` and `.pi/chains/**/*.chain.json` — project scope

Discovery is recursive. `.chain.md` files do not define agents. Use `.chain.md` for simple saved chains and `.chain.json` for dynamic fanout or inline schema objects. Agents and chains can set optional frontmatter/package metadata; `name: scout` plus `package: code-analysis` registers as runtime name `code-analysis.scout` while serialization keeps `name` and `package` separate.

Precedence is by parsed runtime name:
1. project scope
2. user scope
3. builtin agents

## Running Subagents

### Single agent

```typescript
subagent({
  agent: "oracle",
  task: "Review my current direction and challenge assumptions."
})
```

### Forked context

```typescript
subagent({
  agent: "oracle",
  task: "Review my current direction and challenge assumptions."
})
```

`context: "fork"` creates a branched child session from the current persisted
parent session. It does **not** create a fresh minimal review context or filter
history down to only the relevant parts. Use it when you want a separate review
or execution thread that can still reference the parent session history.

### Parallel execution

```typescript
subagent({
  tasks: [
    { agent: "scout", task: "Explore the auth module" },
    { agent: "reviewer", task: "Review the API client" }
  ]
})
```

Top-level parallel tasks can override per-task behavior:

```typescript
subagent({
  tasks: [
    { agent: "scout", task: "Map auth", output: "auth-context.md", progress: true },
    { agent: "researcher", task: "Research OAuth best practices", output: "oauth-research.md" },
    { agent: "reviewer", task: "Review auth tests", model: "anthropic/claude-sonnet-4" }
  ],
  concurrency: 3
})
```

Avoid duplicate output paths in parallel tasks. Concurrent children should not write to the same file. For large saved outputs, set `outputMode: "file-only"` together with an `output` path. The parent result then contains only a compact reference like `Output saved to: /abs/report.md (48.2 KB, 2847 lines). Read this file if needed.` instead of the full saved content. Do not use `output: false` for this; `output: false` means no file output. Read-only children return the complete artifact in their final response and the runtime persists it, so missing write tools are not a supervisor blocker. Mutation-capable children still receive direct-write instructions. Failed runs and save errors still return inline details for debugging.

### Chain execution

```typescript
subagent({
  chain: [
    { agent: "scout", task: "Map the auth flow and summarize key files" },
    { agent: "planner", task: "Create an implementation plan from {previous}" },
    { agent: "worker", task: "Implement the approved plan based on {previous}" }
  ]
})
```

Chain steps can use templated variables such as `{task}`, `{previous}`,
`{chain_dir}`, and `{outputs.name}`. Use `as: "name"` on a successful step or
parallel task to make that output available to later steps. Prefer named outputs
when a later step needs one specific result; keep `{previous}` for simple linear
handoffs or full fan-in summaries. Use `phase` and `label` for status readability.
Use `outputSchema` when later steps need reliable structured data; the child must
call `structured_output` with schema-valid JSON, or the step fails.

### Async/background

Prefer async mode for every subagent launch. Set `async: true` no matter the task unless there is a specific reason to opt into a foreground/blocking run. This applies to scouts, researchers, workers, reviewers, validators, oracle checks, one-off delegates, chains, and parallel groups. Keep the write path single-threaded even when the run is async.

Async does not mean parallel writes. Do not edit the same active worktree while an async worker is changing it. Parent-side overlap should be reading, validation prep, synthesis, command planning, or review of unaffected context unless the writer is isolated in a separate worktree.

Do not end your turn immediately after launching an async child if you promised to keep working. Continue the local inspection, synthesis, or validation prep, then check the async run when its result is needed.

In an interactive chat, normally return control when ready to yield and let Pi wake the session on completion; do not call `subagent_wait()` merely to wait. Override that default and call it when the current request is run-to-completion — for example, the user asked you to report results back before continuing or a skill cannot return before its background work finishes. Headless sessions auto-drain exact current-session work at `agent_end`; call `subagent_wait()` when this turn must receive results before it ends. Never substitute sleep or status-polling loops.

`subagent_wait()` returns when the next initially active async run or registered provider item finishes or a subagent needs attention. Use `subagent_wait({ all: true })` for all work active at call time, `subagent_wait({ id: "..." })` for one async or remembered detached foreground run, and `subagent_wait({ timeoutMs })` to cap the block. If a foreground child detaches for supervisor coordination, reply first, then wait on its id; do not resume or launch a replacement while it remains detached. Headless sessions also auto-drain exact current-session work at `agent_end` as a final safeguard.

```typescript
subagent({
  agent: "worker",
  task: "Run the full test suite",
  async: true
})
```

File-only output mode also works for async single runs, top-level parallel task items, sequential chain steps, and chain parallel task items. In chains, `{previous}` receives the compact saved-file reference when the prior step used file-only mode.

For review fanout where the parent continues a local audit:

```typescript
const run = subagent({
  agent: "reviewer",
  task: "Review the current diff for correctness issues. Do not edit files.",
  async: true,
  context: "fresh"
})
// Continue local inspection, then later call status with the returned id.
```

Inspect async runs with `subagent({ action: "status", id: "..." })` or `subagent({ action: "status" })` for active runs. Use `subagent({ action: "status", view: "fleet" })` when supervising several active foreground/background runs and `subagent({ action: "status", id: "...", view: "transcript", index: 0 })` when you need the latest child output without digging through artifacts. If a delegated fanout child launches nested runs, the parent status view shows them as a tree and you can target a nested run directly with its nested id.

Use `steer` for top-level live async guidance and `resume` after a delegated run pauses or finishes. Routed nested runs retain their existing non-destructive live follow-up path:

```typescript
subagent({ action: "steer", id: "run-id", message: "Focus on the failing test." })
subagent({ action: "resume", id: "run-id", message: "Follow up on this point." })
subagent({ action: "resume", id: "run-id", index: 1, message: "Continue reviewer 2." })
subagent({ action: "resume", id: "nested-run-id", message: "Continue this nested reviewer." })
```

Resume behavior:
- `resume` revives paused, completed, or failed async/foreground children from persisted session files; stopped runs remain non-resumable, and it does not interrupt live top-level async children.
- Use `steer` for acknowledged guidance to a live top-level async child.
- A live nested run can still receive a non-destructive `resume` follow-up through its owner route.
- If an async child has completed, `resume` revives it by starting a new async child from the persisted child session file.
- Multi-child async runs require `index` unless only one running child is selectable.
- Completed foreground single, parallel, and chain runs can also be revived by `index` while their run metadata remains in extension state.

[581 more lines in file. Use offset=401 to continue.]


The skill file confirms the `subagent` tool schema. I can use `chain: [...]`, `async: false`, etc. Good.

Now, the router design. The router subagent will use `subagent({ chain: [...], async: false })`. Each step will be `agent: "delegate"` with a task derived from the p-*.md body.

But I need to make sure the router can read the p-*.md files. It will be invoked from a subagent, which has its own cwd. The prompt files live at `~/.pi/agent/prompts/`. The router can use absolute paths.

Also, the router needs to know which p-*.md maps to each step. The c-*.md chain frontmatter tells it.

Let me write the router agent. It should be concise but clear.

Also, I should add `c-auto.md`? Hmm, the user didn't ask for it, but it would make the router usable via `/prompt-workflow c-auto "task"`. But `/prompt-workflow` expects the workflow to be a prompt template, not an agent. If I create `c-auto.md` as a chain recipe with `chain: workflow-router`, that won't work because `workflow-router` is an agent, not a prompt template. The `/prompt-workflow` command resolves names to prompt templates in the prompts dir, not agents. So `c-auto.md` would need to use a different approach.

Actually, the user can invoke the router via `/run workflow-router "task"` or `subagent({ agent: "workflow-router", task: "..." })`. That's fine.

But the user asked for an "automatic tool". A slash command like `/run workflow-router "task"` is good. Or the parent can naturally invoke it.

OK, let me proceed with:
1. Edit 4 c-*.md files.
2. Edit Doc/chain-commands.md.
3. Edit Doc/prompts.md chain recipes section.
4. Create agents/workflow-router.md.

I also need to make sure the workflow-router.md uses the right name and is discoverable. The file should be at `/home/liph/dotfiles/pi/.pi/agent/agents/workflow-router.md`.

Let me also check if there are any tests that validate the c-*.md frontmatter. The session history mentioned `test/chain-workflow.test.ts`. I should run or at least check it to make sure my changes don't break tests.


total 52
drwxr-xr-x 4 liph liph  4096 Jul 24 18:08 .
drwxr-xr-x 5 liph liph  4096 Jul 24 18:02 ..
-rw-r--r-- 1 liph liph 17965 Jul 24 18:03 chain-workflow.test.ts
drwxr-xr-x 2 liph liph  4096 Jul 24 18:00 fixtures
-rw-r--r-- 1 liph liph   356 Jul 24 18:01 package.json
-rw-r--r-- 1 liph liph 11881 Jul 24 18:08 rate-limit.design.md
drwxr-xr-x 2 liph liph  4096 Jul 24 18:00 support


/**
 * Tests for the prompt workflow chain under `.pi/agent/prompts/`.
 *
 * Scope (static, no LLM):
 *   - Frontmatter of every `c-*.md` recipe and `p-*.md` step is well-formed
 *     and contains the keys the pi-subagents adapter requires.
 *   - Every step named in a `chain:` resolves to an existing `p-*.md` file.
 *   - Every step has `subagent: true` and `fork: true`, which `Doc/chain-commands.md`
 *     calls out as required for `p-*.md` chain steps.
 *   - The Doc pages describe the same recipes / sequences that exist on disk.
 *
 * These tests do not exercise the LLM. They are independent, deterministic,
 * and fast (run against the on-disk tree only).
 */

import { describe, it, before } from "node:test";
import assert from "node:assert/strict";
import { readFileSync, readdirSync } from "node:fs";
import { join, resolve, dirname } from "node:path";
import { fileURLToPath } from "node:url";

import { parseFrontmatter, parseChain } from "./support/frontmatter.ts";

// ---------------------------------------------------------------------------
// Locating the prompts directory
// ---------------------------------------------------------------------------

const here = dirname(fileURLToPath(import.meta.url));
// test/ -> .pi/agent/prompts/
const PROMPTS_DIR = resolve(here, "..");

function readUtf8(path: string): string {
	return readFileSync(path, "utf8");
}

function readDoc(path: string): { frontmatter: Record<string, string>; body: string } {
	return parseFrontmatter(readUtf8(path));
}

let chainFiles: string[] = [];
let promptFiles: string[] = [];
let docFiles: string[] = [];

before(() => {
	chainFiles = readdirSync(PROMPTS_DIR)
		.filter((n) => n.startsWith("c-") && n.endsWith(".md"))
		.sort()
		.map((n) => join(PROMPTS_DIR, n));
	promptFiles = readdirSync(PROMPTS_DIR)
		.filter((n) => n.startsWith("p-") && n.endsWith(".md"))
		.sort()
		.map((n) => join(PROMPTS_DIR, n));
	docFiles = readdirSync(join(PROMPTS_DIR, "Doc"))
		.filter((n) => n.endsWith(".md"))
		.sort()
		.map((n) => join(PROMPTS_DIR, "Doc", n));
});

function readChain(name: string) {
	const path = join(PROMPTS_DIR, name);
	return { path, name, ...readDoc(path) };
}

function readPrompt(step: string) {
	// Accept both `p-brainstorm` and `p-brainstorm.md`; the actual files
	// end in `.md` but the chain frontmatter references them without it.
	const fileName = step.endsWith(".md") ? step : `${step}.md`;
	const path = join(PROMPTS_DIR, fileName);
	return { path, step, ...readDoc(path) };
}

// ---------------------------------------------------------------------------
// Test data
// ---------------------------------------------------------------------------

const EXPECTED_CHAINS: Record<string, string[]> = {
	"c-design-build.md": ["p-brainstorm", "p-plan", "p-test", "p-commit"],
	"c-fix-commit.md": ["p-summarize", "p-diagnose", "p-debug", "p-test"],
	"c-refactor-commit.md": ["p-refactor", "p-test", "p-review", "p-commit"],
	"c-security-loop.md": ["p-secaudit", "p-review", "p-test"],
};

const PROMPTS_USED_IN_CHAINS = new Set<string>(
	Object.values(EXPECTED_CHAINS).flat(),
);

// ---------------------------------------------------------------------------
// 1. Self-tests for the frontmatter/chain helpers (the test infra must work)
// ---------------------------------------------------------------------------

describe("support: frontmatter parser", () => {
	it("parses a simple key: value block", () => {
		const { frontmatter, body } = parseFrontmatter(
			'---\nfoo: bar\nbaz: "qux"\n---\nhello',
		);
		assert.equal(frontmatter.foo, "bar");
		assert.equal(frontmatter.baz, "qux");
		assert.equal(body, "hello");
	});

	it("returns empty frontmatter when the file has no fence", () => {
		const { frontmatter } = parseFrontmatter("no fence here");
		assert.deepEqual(frontmatter, {});
	});

	it("returns empty frontmatter when the fence is unterminated", () => {
		const { frontmatter } = parseFrontmatter("---\nfoo: bar\nstill going");
		assert.deepEqual(frontmatter, {});
	});

	it("de-indents a block scalar and trims leading newlines", () => {
		const { frontmatter } = parseFrontmatter(
			"---\nbody: |\n  line one\n  line two\n  line three\n---\n",
		);
		assert.equal(frontmatter.body, "line one\nline two\nline three");
	});

	it("strips full-line comments and ignores empty lines between keys", () => {
		const { frontmatter } = parseFrontmatter(
			"---\nfoo: bar\n# full-line comment\nbaz: qux\n---\n",
		);
		assert.equal(frontmatter.foo, "bar");
		assert.equal(frontmatter.baz, "qux");
		// Inline `#` after a value is left in the value (matches the
		// upstream `parseFrontmatter` in `pi-subagents`). This protects
		// against accidental whitespace stripping.
		const inline = parseFrontmatter("---\nfoo: bar  # trailing\n---\n");
		assert.equal(inline.frontmatter.foo, "bar  # trailing");
	});

	it("normalizes CRLF line endings", () => {
		const { frontmatter, body } = parseFrontmatter(
			"---\r\nfoo: bar\r\n---\r\nbody",
		);
		assert.equal(frontmatter.foo, "bar");
		assert.equal(body, "body");
	});
});

describe("support: chain parser", () => {
	it("splits on ' -> ' and trims", () => {
		assert.deepEqual(parseChain("a -> b -> c"), ["a", "b", "c"]);
	});

	it("returns [] for undefined", () => {
		assert.deepEqual(parseChain(undefined), []);
	});

	it("returns [] for an empty string", () => {
		assert.deepEqual(parseChain(""), []);
	});

	it("drops empty parts from extra spaces", () => {
		assert.deepEqual(parseChain("a ->  -> b"), ["a", "b"]);
	});

	it("does not split on a single dash", () => {
		// A chain value should not use `-` as a separator; the actual
		// recipes use ` -> `. This protects against future drift.
		assert.deepEqual(parseChain("a-b-c"), ["a-b-c"]);
	});
});

// ---------------------------------------------------------------------------
// 2. Happy path — the on-disk tree matches what we expect
// ---------------------------------------------------------------------------

describe("happy path: chain recipes are present and well-formed", () => {
	for (const [name, expectedSteps] of Object.entries(EXPECTED_CHAINS)) {
		it(`loads ${name}`, () => {
			assert.ok(
				chainFiles.includes(join(PROMPTS_DIR, name)),
				`missing chain recipe: ${name}`,
			);
		});

		it(`${name} has description, argument-hint, and chain fields`, () => {
			const { frontmatter } = readChain(name);
			assert.ok(frontmatter.description, "missing description");
			assert.ok(frontmatter["argument-hint"], "missing argument-hint");
			assert.ok(frontmatter.chain, "missing chain");
		});

		it(`${name}.chain parses to ${expectedSteps.join(" -> ")}`, () => {
			const { frontmatter } = readChain(name);
			assert.deepEqual(parseChain(frontmatter.chain), expectedSteps);
		});

		it(`${name} contains a $@ placeholder for the user argument`, () => {
			const { body } = readChain(name);
			assert.ok(
				body.includes("$@"),
				"chain recipe body must use $@ for the user-supplied argument",
			);
		});
	}
});

describe("happy path: every prompt step resolves to a real file", () => {
	for (const step of PROMPTS_USED_IN_CHAINS) {

[293 more lines in file. Use offset=201 to continue.]


The tests check:
- c-*.md have description, argument-hint, chain.
- chain parses to expected steps.
- body contains `$@`.
- p-*.md have `subagent: true` and `fork: true`.
- Doc pages describe the same recipes/sequences.

My changes to c-*.md must preserve `$@` in the body (which I will do). They must keep description, argument-hint, chain. So they should pass.

I should read the rest of the test to see if it checks for specific text in docs.


		it(`step ${step} exists as a p-*.md file`, () => {
			assert.ok(
				promptFiles.includes(join(PROMPTS_DIR, `${step}.md`)),
				`chain references ${step} but no such p-*.md exists`,
			);
		});
	}
});

describe("happy path: every p-*.md has the required chain-step shape", () => {
	for (const step of PROMPTS_USED_IN_CHAINS) {
		it(`${step} declares subagent: true`, () => {
			const { frontmatter } = readPrompt(step);
			assert.equal(frontmatter.subagent, "true");
		});

		it(`${step} declares fork: true`, () => {
			const { frontmatter } = readPrompt(step);
			assert.equal(frontmatter.fork, "true");
		});

		it(`${step} has description and argument-hint`, () => {
			const { frontmatter } = readPrompt(step);
			assert.ok(frontmatter.description, "missing description");
			assert.ok(frontmatter["argument-hint"], "missing argument-hint");
		});

		it(`${step} body references $@`, () => {
			const { body } = readPrompt(step);
			assert.ok(body.includes("$@"), "p-* body must use $@ for arguments");
		});
	}
});

// ---------------------------------------------------------------------------
// 3. Edge cases — boundaries of the format
// ---------------------------------------------------------------------------

describe("edge cases: chain format boundaries", () => {
	it("every chain has at least one step", () => {
		for (const name of Object.keys(EXPECTED_CHAINS)) {
			const steps = parseChain(readChain(name).frontmatter.chain);
			assert.ok(steps.length > 0, `${name} chain is empty`);
		}
	});

	it("no chain has a duplicate step", () => {
		for (const name of Object.keys(EXPECTED_CHAINS)) {
			const steps = parseChain(readChain(name).frontmatter.chain);
			assert.equal(
				new Set(steps).size,
				steps.length,
				`${name} contains a duplicate step`,
			);
		}
	});

	it("every chain step is lowercase kebab-case starting with 'p-'", () => {
		for (const name of Object.keys(EXPECTED_CHAINS)) {
			const steps = parseChain(readChain(name).frontmatter.chain);
			for (const step of steps) {
				assert.match(step, /^p-[a-z0-9][a-z0-9-]*$/, `${name} step '${step}' is not p-kebab-case`);
			}
		}
	});

	it("chain frontmatter uses ' -> ' (single space) and not '->' or ' - >'", () => {
		// This is the format the pi-subagents adapter's `splitPromptChain`
		// actually understands.
		for (const name of Object.keys(EXPECTED_CHAINS)) {
			const raw = readChain(name).frontmatter.chain;
			assert.ok(raw, `${name} has no chain value`);
			assert.doesNotMatch(raw, /[^ ]->/, `${name} uses bare '->' which the adapter will not split on`);
		}
	});

	it("every chain ends with a real prompt file, not a typo", () => {
		for (const name of Object.keys(EXPECTED_CHAINS)) {
			const last = parseChain(readChain(name).frontmatter.chain).at(-1);
			assert.ok(last && promptFiles.includes(join(PROMPTS_DIR, `${last}.md`)),
				`${name} last step '${last}' does not exist on disk`);
		}
	});
});

describe("edge cases: argument-hint style", () => {
	it("every argument-hint is non-empty", () => {
		for (const name of Object.keys(EXPECTED_CHAINS)) {
			const hint = readChain(name).frontmatter["argument-hint"];
			assert.ok(hint && hint.length > 0, `${name} has empty argument-hint`);
		}
		for (const step of PROMPTS_USED_IN_CHAINS) {
			const hint = readPrompt(step).frontmatter["argument-hint"];
			assert.ok(hint && hint.length > 0, `${step} has empty argument-hint`);
		}
	});

	it("argument-hints are wrapped in [...] to match the documented convention", () => {
		// Doc/chain-commands.md and the existing recipes all use `[hint]`.
		const bracket = /^\[.+\]$/;
		for (const name of Object.keys(EXPECTED_CHAINS)) {
			const hint = readChain(name).frontmatter["argument-hint"];
			assert.match(hint, bracket, `${name} argument-hint not wrapped in []`);
		}
		for (const step of PROMPTS_USED_IN_CHAINS) {
			const hint = readPrompt(step).frontmatter["argument-hint"];
			assert.match(hint, bracket, `${step} argument-hint not wrapped in []`);
		}
	});
});

// ---------------------------------------------------------------------------
// 4. Error cases — malformed / missing / inconsistent input
// ---------------------------------------------------------------------------

describe("error cases: malformed frontmatter", () => {
	it("rejects a chain file with no closing fence", () => {
		const { frontmatter } = parseFrontmatter(
			"---\ndescription: broken\nchain: a -> b\n",
		);
		// Without a closing fence, the parser should return no frontmatter
		// (mirroring the real adapter), so the chain is empty.
		assert.deepEqual(frontmatter, {});
	});

	it("rejects a chain value with no separator at all", () => {
		assert.deepEqual(parseChain("only-one-step"), ["only-one-step"]);
		assert.equal(parseChain("only-one-step").length, 1);
	});

	it("flags a chain step that does not exist on disk", () => {
		// Simulate what the adapter does: build a fake chain value and
		// confirm we'd catch the missing file.
		const fakeStep = "p-does-not-exist";
		const steps = parseChain(`p-brainstorm -> ${fakeStep}`);
		assert.ok(steps.includes(fakeStep));
		assert.ok(
			!promptFiles.includes(join(PROMPTS_DIR, `${fakeStep}.md`)),
			"sanity: the fake step should not exist on disk",
		);
	});
});

describe("error cases: required keys", () => {
	it("every chain recipe has a non-empty description", () => {
		for (const name of Object.keys(EXPECTED_CHAINS)) {
			const d = readChain(name).frontmatter.description;
			assert.ok(d && d.trim().length > 0, `${name} has empty description`);
		}
	});

	it("no p-* used in a chain is missing the subagent/fork flags", () => {
		// This is the failure mode Doc/chain-commands.md calls out:
		// "fork: true is required on each p-*.md. Check frontmatter."
		for (const step of PROMPTS_USED_IN_CHAINS) {
			const fm = readPrompt(step).frontmatter;
			assert.equal(fm.subagent, "true", `${step} missing subagent: true`);
			assert.equal(fm.fork, "true", `${step} missing fork: true`);
		}
	});
});

describe("error cases: cross-doc consistency", () => {
	// These tests catch the realistic drift bug: someone adds a new chain
	// recipe and forgets to add a row to the table in the Doc page. The
	// table is the canonical description, so we look for a row, not just
	// any mention of the name (the docs also reference recipes in
	// `/prompt-workflow <name>` examples, which would mask a missing row).
	//
	// chain-commands.md table uses the form  | `c-design-build.md` | ... |
	// prompts.md table uses the form        | **`c-design-build`** | ... |

	it("Doc/chain-commands.md has a table row for every chain recipe", () => {
		const text = readUtf8(join(PROMPTS_DIR, "Doc", "chain-commands.md"));
		for (const name of Object.keys(EXPECTED_CHAINS)) {
			// The chain-commands.md table uses the full filename in
			// backticks (e.g. `c-design-build.md`).
			const re = new RegExp(`^\\|\\s*\`${name}\`\\s*\\|`, "m");
			assert.ok(
				re.test(text),
				`Doc/chain-commands.md is missing a table row for ${name}`,
			);
		}
	});

	it("Doc/chain-commands.md table rows show the actual chain sequence", () => {
		const text = readUtf8(join(PROMPTS_DIR, "Doc", "chain-commands.md"));
		for (const [name, steps] of Object.entries(EXPECTED_CHAINS)) {
			const re = new RegExp(`^\\|\\s*\`${name}\`\\s*\\|[^|]*\\|[^|]*\\|`, "m");
			const row = text.match(re);
			assert.ok(row, `Doc/chain-commands.md is missing a row for ${name}`);
			const rowAscii = row[0].replace(/→/g, "->");
			for (const step of steps) {
				assert.ok(
					rowAscii.includes(step),
					`Doc/chain-commands.md row for ${name} does not list ${step}`,
				);
			}
		}
	});

[93 more lines in file. Use offset=401 to continue.]


	it("Doc/prompts.md has a table row for every chain recipe", () => {
		const text = readUtf8(join(PROMPTS_DIR, "Doc", "prompts.md"));
		for (const name of Object.keys(EXPECTED_CHAINS)) {
			// The prompts.md table uses the base name in backticks
			// surrounded by `**` (e.g. `**`c-design-build`**`).
			const base = name.replace(/\.md$/, "");
			const re = new RegExp(`^\\|\\s*\\*\\*\`${base}\`\\*\\*\\s*\\|`, "m");
			assert.ok(
				re.test(text),
				`Doc/prompts.md is missing a table row for ${base}`,
			);
		}
	});

	it("Doc/prompts.md table rows show the actual chain sequence", () => {
		const text = readUtf8(join(PROMPTS_DIR, "Doc", "prompts.md"));
		for (const [name, steps] of Object.entries(EXPECTED_CHAINS)) {
			const base = name.replace(/\.md$/, "");
			const re = new RegExp(`^\\|\\s*\\*\\*\`${base}\`\\*\\*\\s*\\|[^|]*\\|`, "m");
			const row = text.match(re);
			assert.ok(row, `Doc/prompts.md is missing a row for ${base}`);
			const rowAscii = row[0].replace(/→/g, "->");
			for (const step of steps) {
				assert.ok(
					rowAscii.includes(step),
					`Doc/prompts.md row for ${base} does not list ${step}`,
				);
			}
		}
	});

	it("Doc/chain-commands.md documents ' -> ' as the chain separator", () => {
		const text = readUtf8(join(PROMPTS_DIR, "Doc", "chain-commands.md"));
		assert.ok(
			text.includes("->") || text.includes("→"),
			"Doc/chain-commands.md should describe the chain arrow separator",
		);
	});

	it("Doc/prompts.md mentions every prompt used in any chain", () => {
		const text = readUtf8(join(PROMPTS_DIR, "Doc", "prompts.md"));
		for (const step of PROMPTS_USED_IN_CHAINS) {
			assert.ok(
				text.includes(step),
				`Doc/prompts.md does not mention prompt ${step}`,
			);
		}
	});
});

// ---------------------------------------------------------------------------
// 5. Directory-level sanity — catches accidental deletions
// ---------------------------------------------------------------------------

describe("directory sanity", () => {
	it("has at least one chain recipe", () => {
		assert.ok(chainFiles.length > 0, "no c-*.md files found");
	});

	it("has at least one p-*.md prompt", () => {
		assert.ok(promptFiles.length > 0, "no p-*.md files found");
	});

	it("has both Doc pages", () => {
		assert.ok(docFiles.some((p) => p.endsWith("chain-commands.md")));
		assert.ok(docFiles.some((p) => p.endsWith("prompts.md")));
	});

	it("Doc/ has no extra markdown files we did not expect", () => {
		// If a new doc page is added, the cross-doc tests above should
		// grow with it. Catches accidental orphans in the other direction.
		const known = new Set(["chain-commands.md", "prompts.md"]);
		for (const p of docFiles) {
			const base = p.split(/[/\\]/).pop()!;
			assert.ok(known.has(base), `unexpected Doc file: ${base}`);
		}
	});

	it("every file in the prompts root is a recognized c-*, p-*, or Doc entry", () => {
		const entries = readdirSync(PROMPTS_DIR);
		const allowed = (n: string) =>
			n.startsWith("c-") || n.startsWith("p-") || n === "Doc" || n === "test";
		for (const e of entries) {
			if (e.startsWith(".")) continue; // .pi-subagents, etc.
			assert.ok(
				allowed(e),
				`unexpected top-level entry in prompts dir: ${e}`,
			);
		}
	});
});


The tests are fairly specific. They check:
- c-*.md table rows in chain-commands.md with filename in backticks.
- c-*.md table rows in prompts.md with `**`c-name`**`.
- Rows include the chain sequence (steps).
- Body contains `$@`.
- Description, argument-hint, chain fields.

My changes to the docs must preserve the table rows with the expected format and include the chain steps. The current docs already have this. I can modify surrounding text, but keep the table rows intact.

Also, the test checks `argument-hint` is wrapped in `[...]`. The current c-*.md have `argument-hint: "[task or feature]"`. Good.

Now let me proceed to make the edits.

I'll use the `edit` tool for the 4 c-*.md files, Doc/chain-commands.md, Doc/prompts.md, and `write` for the new agents/workflow-router.md (since the file doesn't exist).

Let me draft each edit carefully.

### c-design-build.md

Old:
```markdown
---
description: Brainstorm → plan → test → commit in one background chain
argument-hint: "[task or feature]"
chain: p-brainstorm -> p-plan -> p-test -> p-commit
---
Run the design → plan → test → commit chain for: $@

Invoke with:
/prompt-workflow c-design-build --bg "add a rate-limiter to the API"
```

New:
```markdown
---
description: Brainstorm → plan → test → commit in one chain
argument-hint: "[task or feature]"
chain: p-brainstorm -> p-plan -> p-test -> p-commit
---
Run the design → plan → test → commit chain for: $@

Run in the current Pi session (foreground, stop with Esc/Ctrl+C):
/prompt-workflow c-design-build "<task>"

Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):
/prompt-workflow c-design-build --bg "<task>"
```

Similarly for others, with appropriate descriptions.

### c-fix-commit.md

Old description: "Summarize → diagnose → debug → test in one background chain"
New: "Summarize → diagnose → debug → test in one chain"

Body:
```markdown
Run the understand → diagnose → fix → regression-test chain for: $@

Run in the current Pi session (foreground, stop with Esc/Ctrl+C):
/prompt-workflow c-fix-commit "<task>"

Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):
/prompt-workflow c-fix-commit --bg "<task>"
```

### c-refactor-commit.md

Old: "Refactor → test → review → commit in one background chain"
New: "Refactor → test → review → commit in one chain"

Body:
```markdown
Run the safe refactor → validate → review → commit chain for: $@

Run in the current Pi session (foreground, stop with Esc/Ctrl+C):
/prompt-workflow c-refactor-commit "<task>"

Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):
/prompt-workflow c-refactor-commit --bg "<task>"
```

### c-security-loop.md

Old: "Security audit → review → test in one background chain"
New: "Security audit → review → test in one chain"

Body:
```markdown
Run the security-first review loop for: $@

Run in the current Pi session (foreground, stop with Esc/Ctrl+C):
/prompt-workflow c-security-loop "<task>"

Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):
/prompt-workflow c-security-loop --bg "<task>"
```

### Doc/chain-commands.md

Current relevant sections:

"## How to run a chain"
```markdown
Chains are not invoked with `/c-...` in the editor, because normal slash expansion just pastes the file body into the chat. Instead, run them through the `pi-subagents` adapter with `/prompt-workflow`:

```text
/prompt-workflow c-design-build "add a rate-limiter to the API"
/prompt-workflow c-fix-commit "the checkout intermittently times out"
/prompt-workflow c-refactor-commit "src/utils.ts"
/prompt-workflow c-security-loop "auth endpoint"
```

Each chain runs asynchronously by default. Check progress with:

```text
/subagents-fleet
```

or inspect a specific run with:

```text
subagent({ action: "status" })
```
```

I need to change this to foreground default. The code examples currently don't have `--bg` in the "How to run a chain" section, but earlier the user had them. Wait, looking at the current Doc/chain-commands.md, the examples do NOT have `--bg`. But the text says "Each chain runs asynchronously by default." That's inconsistent. The actual c-*.md files had `--bg` in their examples. So the doc is already partly foreground in examples but text says async default.

I should update the text to "Each chain runs in the foreground by default; add `--bg` to run detached." and add a stop section.

Also, I should maybe add a section about the workflow-router agent.

Let me rewrite the relevant part:

```markdown
## How to run a chain

Chains are not invoked with `/c-...` in the editor, because normal slash expansion just pastes the file body into the chat. Instead, run them through the `pi-subagents` adapter with `/prompt-workflow`:

```text
/prompt-workflow c-design-build "add a rate-limiter to the API"
/prompt-workflow c-fix-commit "the checkout intermittently times out"
/prompt-workflow c-refactor-commit "src/utils.ts"
/prompt-workflow c-security-loop "auth endpoint"
```

Each chain runs in the foreground by default. That means it stays in the current Pi session and you can cancel the current turn with `Esc` or `Ctrl+C`.

Add `--bg` (or `--async`) to detach the chain and keep working in the main chat while it runs:

```text
/prompt-workflow c-design-build --bg "add a rate-limiter to the API"
```

Stop or inspect a background run:

```text
/subagents-fleet           # live inspector
/subagents-stop <run-id>   # kill a specific run
subagent({ action: "stop", id: "<run-id>" })
```

You can also inspect a specific run with:

```text
subagent({ action: "status" })
```
```

I also need to keep the table rows intact. The table is:

```markdown
| Command file | Sequence | Use it when |
|---|---|---|
| `c-design-build.md` | `p-brainstorm → p-plan → p-test → p-commit` | ... |
...
```

I will keep the table as is, or maybe update the descriptions. But the tests check the table rows include the steps. I should not change the step sequences.

Actually, the table rows can be updated, but the format must remain: `| `c-design-build.md` | `p-brainstorm → ...` | ... |`. The tests use regex `^\|\s*`c-design-build.md`\s*\|` and check the row includes each step. So I can change the last column (Use it when) but keep the first two columns. I'll keep them mostly the same.

I might also add a section about the workflow-router agent.

### Doc/prompts.md

Update the chain recipes section to remove `--bg` from examples and note foreground default.

Current:
```markdown
Invoke a chain with `/prompt-workflow`, not `/c-recipe`:

```text
/prompt-workflow c-design-build --bg "add a rate-limiter to the API"
/prompt-workflow c-fix-commit --bg "the checkout intermittently times out"
/prompt-workflow c-refactor-commit --bg "src/utils.ts"
/prompt-workflow c-security-loop --bg "auth endpoint"
```

Each chain runs in the background. Watch it with `/subagents-fleet` or check status with `subagent({ action: "status" })`. If you want to run the same sequence ad-hoc, use `/chain-prompts`:
```

Change to:
```markdown
Invoke a chain with `/prompt-workflow`, not `/c-recipe`:

```text
/prompt-workflow c-design-build "add a rate-limiter to the API"
/prompt-workflow c-fix-commit "the checkout intermittently times out"
/prompt-workflow c-refactor-commit "src/utils.ts"
/prompt-workflow c-security-loop "auth endpoint"
```

Each chain runs in the foreground by default, so you can stop it with `Esc` or `Ctrl+C`. Add `--bg` to detach it; then watch with `/subagents-fleet`, stop with `/subagents-stop <id>`, or check status with `subagent({ action: "status" })`. If you want to run the same sequence ad-hoc, use `/chain-prompts`:
```

Keep the table rows intact (they are tested).

### agents/workflow-router.md

Create new file.

I want to make this robust. Let me think about the prompt carefully.

The router will be invoked as a subagent with a task. It needs to:
1. Choose the best c-* chain based on the task.
2. Read the c-*.md to get the chain list.
3. Read each p-*.md to get the body.
4. Call `subagent({ chain: [...], async: false })` with delegate steps.

But there's a problem: the p-*.md files have frontmatter. The body starts after `---`. The router needs to extract the body and substitute `$@` with the task.

The router can do this as an LLM. The prompt will instruct it. But to make it reliable, maybe I should include the actual mappings in the router prompt rather than relying on reading files? That way it doesn't need to parse frontmatter. But if the user changes the p-* prompts later, the router would be stale. Reading is better.

Actually, the p-*.md files are simple; the frontmatter is small. The LLM can read them and use the body. I'll instruct it to ignore frontmatter and use the body after the second `---`.

But the router is an LLM subagent; it might not follow instructions perfectly. However, this is a reasonable design.

Alternatively, I can make the router prompt include the exact body of each p-* prompt inline, but that's long and duplicates content. Not ideal.

Another approach: the router can just output the chain name, and then a parent-level wrapper (like a slash command or a parent prompt) runs `/prompt-workflow`. But the user chose subagent router.

Wait, maybe the simplest robust design is: the router subagent picks the best c-* recipe and returns the recommended `/prompt-workflow` command. Then the user (or parent) runs it. This is less automatic but more reliable. However, the user wants automatic.

I think I can combine: the router picks, reads the p-* files, and runs the chain via `subagent`. I'll write clear instructions and include examples.

Let me draft `agents/workflow-router.md`:

```yaml
---
name: workflow-router
description: Pick the best c-* chain for a task and run it in the foreground
tools: read, subagent
systemPromptMode: append
inheritProjectContext: true
inheritSkills: false
---

You are a workflow router. Given the user's task, choose and execute the single most appropriate c-* chain from `~/.pi/agent/prompts/`.

Available chains:

| Chain | Steps | Use it when |
|---|---|---|
| `c-design-build` | p-brainstorm → p-plan → p-test → p-commit | Designing or adding a new feature from a vague requirement. |
| `c-fix-commit` | p-summarize → p-diagnose → p-debug → p-test | A bug, failure, error, or regression. |
| `c-refactor-commit` | p-refactor → p-test → p-review → p-commit | Restructuring existing code without changing behavior. |
| `c-security-loop` | p-secaudit → p-review → p-test | Auth, input handling, secrets, network, deserialization, or trust boundaries. |

Steps:
1. Decide which chain is the best fit for: {task}
2. Read the selected `~/.pi/agent/prompts/c-<name>.md` file and note the `chain:` frontmatter value.
3. For each `p-*.md` step in that chain, read `~/.pi/agent/prompts/<step>.md`, ignore its frontmatter, and take the body text (everything after the second `---`).
4. Run the chain with the `subagent` tool:
   - `async: false` so the user can stop it with `Esc`/`Ctrl+C`.
   - Each step uses `agent: "delegate"`.
   - The step `task` is the prompt body with `$@` replaced by the user's original task.
   - Use `label` and `phase` for readability.
5. Report which chain you chose and why.

Do not ask the user before running. Pick exactly one chain and execute it. If the task truly does not fit any chain, run `c-design-build` as the safest default.
```

This looks good. But the `{task}` variable - does the subagent tool substitute `{task}`? Yes, chain variables include `{task}`. But this is in the system prompt, not in a chain task. The router receives the task as its initial prompt. The `{task}` here is just a placeholder in the system prompt. The LLM will see the actual task in the conversation. So it's fine.

Actually, I should use `{{task}}` or just say "the user's task" to avoid confusion with chain variables. I'll use "the user's task" instead of `{task}`.

Also, I should mention that the router can use `contact_supervisor` if it needs a decision, but it shouldn't. Actually, with `tools: read, subagent`, it doesn't have `contact_supervisor`. The delegate agent has it. But the router doesn't need it.

Wait, `tools: read, subagent` means the router only has those two tools. The `subagent` tool is child-safe. Good.

Now, one issue: the router will be a subagent with `tools: subagent`. But child subagents by default do not receive the `subagent` tool unless their resolved `tools` includes `subagent`. The frontmatter `tools: read, subagent` should grant it. Good.

But will the router be able to run `subagent` with `async: false`? The `subagent` tool in a child should support the same params. The skill says "child-safe `subagent` tool for the fanout work the parent assigned." It should support chain, async, etc.

Also, the `delegate` agent is a builtin. It will be available.

OK, let me make the edits.

But first, I should consider whether to also update the tests. My changes don't require test updates because they preserve the tested properties. But adding `agents/workflow-router.md` is in a different directory, so the prompt dir tests won't be affected. Good.

Now, one more thing: the user also asked about "an automatic tool that would just use whatever subagent or prompt is the most fitting". My router agent is exactly that. I should mention it in the final response.

Let me now execute the edits. I'll do multiple edits in one call for the 4 c-*.md files. But since they are separate files, I need separate edit calls (one per file). The `edit` tool takes one path and multiple edits. So I'll make 4 edit calls.

Then edit Doc/chain-commands.md and Doc/prompts.md.

Then write agents/workflow-router.md.

After edits, run the tests to verify.

Let me proceed.

edit

---
description: Summarize → diagnose → debug → test in one chain
argument-hint: "[symptom, error, or observed behavior]"
chain: p-summarize -> p-diagnose -> p-debug -> p-test
---
Run the understand → diagnose → fix → regression-test chain for: $@

Run in the current Pi session (foreground, stop with Esc/Ctrl+C):
/prompt-workflow c-fix-commit "<task>"

Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):
/prompt-workflow c-fix-commit --bg "<task>"

---
description: Summarize → diagnose → debug → test in one background chain
argument-hint: "[symptom, error, or observed behavior]"
chain: p-summarize -> p-diagnose -> p-debug -> p-test
---
Run the understand → diagnose → fix → regression-test chain for: $@

Invoke with:
/prompt-workflow c-fix-commit --bg "the checkout intermittently times out"

---
description: Refactor → test → review → commit in one chain
argument-hint: "[file path or symbol to refactor]"
chain: p-refactor -> p-test -> p-review -> p-commit
---
Run the safe refactor → validate → review → commit chain for: $@

Run in the current Pi session (foreground, stop with Esc/Ctrl+C):
/prompt-workflow c-refactor-commit "<task>"

Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):
/prompt-workflow c-refactor-commit --bg "<task>"

---
description: Refactor → test → review → commit in one background chain
argument-hint: "[file path or symbol to refactor]"
chain: p-refactor -> p-test -> p-review -> p-commit
---
Run the safe refactor → validate → review → commit chain for: $@

Invoke with:
/prompt-workflow c-refactor-commit --bg "src/utils.ts"

---
description: Security audit → review → test in one chain
argument-hint: "[file path, diff, or feature to audit]"
chain: p-secaudit -> p-review -> p-test
---
Run the security-first review loop for: $@

Run in the current Pi session (foreground, stop with Esc/Ctrl+C):
/prompt-workflow c-security-loop "<task>"

Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):
/prompt-workflow c-security-loop --bg "<task>"

---
description: Security audit → review → test in one background chain
argument-hint: "[file path, diff, or feature to audit]"
chain: p-secaudit -> p-review -> p-test
---
Run the security-first review loop for: $@

Invoke with:
/prompt-workflow c-security-loop --bg "auth endpoint"


Successfully replaced 1 block(s) in /home/liph/dotfiles/pi/.pi/agent/prompts/c-design-build.md.

  1 ---
- 2 description: Brainstorm → plan → test → commit in one background chain
+ 2 description: Brainstorm → plan → test → commit in one chain
  3 argument-hint: "[task or feature]"
  4 chain: p-brainstorm -> p-plan -> p-test -> p-commit
  5 ---
  6 Run the design → plan → test → commit chain for: $@
  7
- 8 Invoke with:
- 9 /prompt-workflow c-design-build --bg "add a rate-limiter to the API"
+ 8 Run in the current Pi session (foreground, stop with Esc/Ctrl+C):
+ 9 /prompt-workflow c-design-build "<task>"
+10
+11 Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):
+12 /prompt-workflow c-design-build --bg "<task>"

--- /home/liph/dotfiles/pi/.pi/agent/prompts/c-design-build.md
+++ /home/liph/dotfiles/pi/.pi/agent/prompts/c-design-build.md
@@ -1,9 +1,12 @@
 ---
-description: Brainstorm → plan → test → commit in one background chain
+description: Brainstorm → plan → test → commit in one chain
 argument-hint: "[task or feature]"
 chain: p-brainstorm -> p-plan -> p-test -> p-commit
 ---
 Run the design → plan → test → commit chain for: $@

-Invoke with:
-/prompt-workflow c-design-build --bg "add a rate-limiter to the API"
+Run in the current Pi session (foreground, stop with Esc/Ctrl+C):
+/prompt-workflow c-design-build "<task>"
+
+Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):
+/prompt-workflow c-design-build --bg "<task>"


Successfully replaced 1 block(s) in /home/liph/dotfiles/pi/.pi/agent/prompts/c-fix-commit.md.

  1 ---
- 2 description: Summarize → diagnose → debug → test in one background chain
+ 2 description: Summarize → diagnose → debug → test in one chain
  3 argument-hint: "[symptom, error, or observed behavior]"
  4 chain: p-summarize -> p-diagnose -> p-debug -> p-test
  5 ---
  6 Run the understand → diagnose → fix → regression-test chain for: $@
  7
- 8 Invoke with:
- 9 /prompt-workflow c-fix-commit --bg "the checkout intermittently times out"
+ 8 Run in the current Pi session (foreground, stop with Esc/Ctrl+C):
+ 9 /prompt-workflow c-fix-commit "<task>"
+10
+11 Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):
+12 /prompt-workflow c-fix-commit --bg "<task>"

--- /home/liph/dotfiles/pi/.pi/agent/prompts/c-fix-commit.md
+++ /home/liph/dotfiles/pi/.pi/agent/prompts/c-fix-commit.md
@@ -1,9 +1,12 @@
 ---
-description: Summarize → diagnose → debug → test in one background chain
+description: Summarize → diagnose → debug → test in one chain
 argument-hint: "[symptom, error, or observed behavior]"
 chain: p-summarize -> p-diagnose -> p-debug -> p-test
 ---
 Run the understand → diagnose → fix → regression-test chain for: $@

-Invoke with:
-/prompt-workflow c-fix-commit --bg "the checkout intermittently times out"
+Run in the current Pi session (foreground, stop with Esc/Ctrl+C):
+/prompt-workflow c-fix-commit "<task>"
+
+Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):
+/prompt-workflow c-fix-commit --bg "<task>"


Successfully replaced 1 block(s) in /home/liph/dotfiles/pi/.pi/agent/prompts/c-refactor-commit.md.

  1 ---
- 2 description: Refactor → test → review → commit in one background chain
+ 2 description: Refactor → test → review → commit in one chain
  3 argument-hint: "[file path or symbol to refactor]"
  4 chain: p-refactor -> p-test -> p-review -> p-commit
  5 ---
  6 Run the safe refactor → validate → review → commit chain for: $@
  7
- 8 Invoke with:
- 9 /prompt-workflow c-refactor-commit --bg "src/utils.ts"
+ 8 Run in the current Pi session (foreground, stop with Esc/Ctrl+C):
+ 9 /prompt-workflow c-refactor-commit "<task>"
+10
+11 Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):
+12 /prompt-workflow c-refactor-commit --bg "<task>"

--- /home/liph/dotfiles/pi/.pi/agent/prompts/c-refactor-commit.md
+++ /home/liph/dotfiles/pi/.pi/agent/prompts/c-refactor-commit.md
@@ -1,9 +1,12 @@
 ---
-description: Refactor → test → review → commit in one background chain
+description: Refactor → test → review → commit in one chain
 argument-hint: "[file path or symbol to refactor]"
 chain: p-refactor -> p-test -> p-review -> p-commit
 ---
 Run the safe refactor → validate → review → commit chain for: $@

-Invoke with:
-/prompt-workflow c-refactor-commit --bg "src/utils.ts"
+Run in the current Pi session (foreground, stop with Esc/Ctrl+C):
+/prompt-workflow c-refactor-commit "<task>"
+
+Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):
+/prompt-workflow c-refactor-commit --bg "<task>"


Successfully replaced 1 block(s) in /home/liph/dotfiles/pi/.pi/agent/prompts/c-security-loop.md.

  1 ---
- 2 description: Security audit → review → test in one background chain
+ 2 description: Security audit → review → test in one chain
  3 argument-hint: "[file path, diff, or feature to audit]"
  4 chain: p-secaudit -> p-review -> p-test
  5 ---
  6 Run the security-first review loop for: $@
  7
- 8 Invoke with:
- 9 /prompt-workflow c-security-loop --bg "auth endpoint"
+ 8 Run in the current Pi session (foreground, stop with Esc/Ctrl+C):
+ 9 /prompt-workflow c-security-loop "<task>"
+10
+11 Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):
+12 /prompt-workflow c-security-loop --bg "<task>"

--- /home/liph/dotfiles/pi/.pi/agent/prompts/c-security-loop.md
+++ /home/liph/dotfiles/pi/.pi/agent/prompts/c-security-loop.md
@@ -1,9 +1,12 @@
 ---
-description: Security audit → review → test in one background chain
+description: Security audit → review → test in one chain
 argument-hint: "[file path, diff, or feature to audit]"
 chain: p-secaudit -> p-review -> p-test
 ---
 Run the security-first review loop for: $@

-Invoke with:
-/prompt-workflow c-security-loop --bg "auth endpoint"
+Run in the current Pi session (foreground, stop with Esc/Ctrl+C):
+/prompt-workflow c-security-loop "<task>"
+
+Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):
+/prompt-workflow c-security-loop --bg "<task>"


Good. Now edit Doc/chain-commands.md. I need to preserve the table rows. Let me read it again to make precise edits.


# Chain Commands Reference

This file documents how to invoke the `c-*` chain recipes defined in `~/.pi/agent/prompts/`.

## What the chains are

The `c-*` files are orchestration recipes. They do not contain new prompts; they reuse the existing `p-*` prompts and run them in sequence through the `pi-subagents` prompt-workflow adapter. Each step is executed as a forked-context subagent, so later steps can see the outputs from earlier steps.

## Available chains

| Command file | Sequence | Use it when |
|---|---|---|
| `c-design-build.md` | `p-brainstorm → p-plan → p-test → p-commit` | You want to design a feature, plan it, add tests, and commit in one go. |
| `c-fix-commit.md` | `p-summarize → p-diagnose → p-debug → p-test` | You need to understand a bug, diagnose it, fix it, and add regression tests. |
| `c-refactor-commit.md` | `p-refactor → p-test → p-review → p-commit` | You want a safe refactor with tests, review, and a commit. |
| `c-security-loop.md` | `p-secaudit → p-review → p-test` | You need a security-first review plus tests before proceeding. |

## How to run a chain

Chains are not invoked with `/c-...` in the editor, because normal slash expansion just pastes the file body into the chat. Instead, run them through the `pi-subagents` adapter with `/prompt-workflow`:

```text
/prompt-workflow c-design-build "add a rate-limiter to the API"
/prompt-workflow c-fix-commit "the checkout intermittently times out"
/prompt-workflow c-refactor-commit "src/utils.ts"
/prompt-workflow c-security-loop "auth endpoint"
```

Each chain runs asynchronously by default. Check progress with:

```text
/subagents-fleet
```

or inspect a specific run with:

```text
subagent({ action: "status" })
```

## Ad-hoc chains

You can also run the same sequence on the fly without creating a recipe file:

```text
/chain-prompts p-brainstorm -> p-plan -> p-test -> p-commit -- "add a rate-limiter"
/chain-prompts p-summarize -> p-diagnose -> p-debug -> p-test -- "intermittent timeout"
/chain-prompts p-refactor -> p-test -> p-review -> p-commit -- "src/utils.ts"
/chain-prompts p-secaudit -> p-review -> p-test -- "auth endpoint"
```

Use `--bg` or `--async` to detach an ad-hoc chain:

```text
/chain-prompts p-refactor -> p-test -> p-review -> p-commit --bg -- "src/utils.ts"
```

## Why individual prompts are the subagents

Only the `p-*.md` files are marked with `subagent: true` and `fork: true`. The `c-*.md` recipe files are pure wrappers. When `/prompt-workflow` loads a recipe:

1. It sees the `chain:` frontmatter.
2. It resolves each named step to a `p-*.md` file.
3. It runs that prompt as a forked-context subagent (`delegate` by default).
4. The output of each step is passed to the next step via the chain runner.

This keeps the chain recipes small and the individual prompts reusable as both standalone slash templates and chain steps.

## Context flow

Because each `p-*` step uses `fork: true`, every subagent inherits the parent session history. That means later steps naturally see what earlier steps produced, without needing explicit `{previous}` placeholders inside the prompt bodies.

The trade-off is higher per-step context usage. If token cost becomes an issue, a future migration could switch the `p-*` prompts to `fresh: true` and introduce explicit `{previous}` handling inside their bodies.

## Troubleshooting

| Symptom | What to check |
|---|---|
| `/c-design-build` just pastes text | Use `/prompt-workflow c-design-build ...` instead. |
| Chain step fails with “Unknown prompt workflow” | Run `/reload`, then `/prompt-workflow list` and confirm each `p-*` in the chain appears. |
| Chain does not run in background | Confirm the recipe has `async: true` in frontmatter, or add `--bg` to the command. |
| Steps seem disconnected | `fork: true` is required on each `p-*.md`. Check frontmatter. |


I need to update:
1. The "How to run a chain" section to foreground default and add stop commands.
2. The troubleshooting row "Chain does not run in background" should be updated because the new default is foreground. Maybe change to "Chain does not detach" or keep it.
3. Add a section about workflow-router.

Let me make the edits. I'll replace the "How to run a chain" section and the troubleshooting row, and add a router section.

Actually, the troubleshooting row "Chain does not run in background" says "Confirm the recipe has async: true in frontmatter, or add --bg to the command." This is still valid if someone wants background. But the title is misleading. I can change it to "Chain does not detach / run in background".

Also, I should add a section about workflow-router agent. Maybe "## Automatic routing" after "Ad-hoc chains".

Let me write the edits.

For "How to run a chain":
Replace from "Each chain runs asynchronously by default..." to the end of that paragraph with new text.

For troubleshooting row:
Replace "Chain does not run in background" with "Want the chain to run in background".

Add new section after "Ad-hoc chains" about workflow-router.

Let me do the edits.

Each chain runs in the foreground by default, so it stays in the current Pi session and you can cancel the current turn with `Esc` or `Ctrl+C`.

Add `--bg` (or `--async`) to detach the chain and keep working in the main chat while it runs in the background:

```text
/prompt-workflow c-design-build --bg "add a rate-limiter to the API"
```

Stop or inspect a background run:

```text
/subagents-fleet           # live inspector (Ctrl+Alt+F also opens it)
/subagents-stop <run-id>   # kill a specific run
subagent({ action: "stop", id: "<run-id>" })
```

Inspect any run (foreground or background):

```text
subagent({ action: "status" })
```

Each chain runs asynchronously by default. Check progress with:

```text
/subagents-fleet
```

or inspect a specific run with:

```text
subagent({ action: "status" })
```

## Automatic routing

If you don't want to pick the recipe manually, use the `workflow-router` agent:

```text
/run workflow-router "add a rate-limiter to the API"
```

The router reads the task, chooses the best `c-*` chain, and runs it in the foreground (`async: false`) so you can stop it with `Esc`/`Ctrl+C`. It dispatches through the `subagent` tool using the same `p-*` prompt bodies the chain recipes use.

You can also invoke it from another agent or prompt:

```text
subagent({ agent: "workflow-router", task: "the checkout intermittently times out" })
```

## Why individual prompts are the subagents

| Want the chain to run in background | Add `--bg` or `--async` to the `/prompt-workflow` command. |

| Chain does not run in background | Confirm the recipe has `async: true` in frontmatter, or add `--bg` to the command. |


Successfully replaced 3 block(s) in /home/liph/dotfiles/pi/.pi/agent/prompts/Doc/chain-commands.md.

     ...
  25 /prompt-workflow c-refactor-commit "src/utils.ts"
  26 /prompt-workflow c-security-loop "auth endpoint"
  27 ```
  28
- 29 Each chain runs asynchronously by default. Check progress with:
+ 29 Each chain runs in the foreground by default, so it stays in the current Pi session and you can cancel the current turn with `Esc` or `Ctrl+C`.
  30
+ 31 Add `--bg` (or `--async`) to detach the chain and keep working in the main chat while it runs in the background:
+ 32
  31 ```text
- 32 /subagents-fleet
+ 34 /prompt-workflow c-design-build --bg "add a rate-limiter to the API"
  33 ```
  34
- 35 or inspect a specific run with:
+ 37 Stop or inspect a background run:
  36
  37 ```text
+ 40 /subagents-fleet           # live inspector (Ctrl+Alt+F also opens it)
+ 41 /subagents-stop <run-id>   # kill a specific run
+ 42 subagent({ action: "stop", id: "<run-id>" })
+ 43 ```
+ 44
+ 45 Inspect any run (foreground or background):
+ 46
+ 47 ```text
  38 subagent({ action: "status" })
  39 ```
  40
  41 ## Ad-hoc chains
     ...
  54 ```text
  55 /chain-prompts p-refactor -> p-test -> p-review -> p-commit --bg -- "src/utils.ts"
  56 ```
  57
+ 68 ## Automatic routing
+ 69
+ 70 If you don't want to pick the recipe manually, use the `workflow-router` agent:
+ 71
+ 72 ```text
+ 73 /run workflow-router "add a rate-limiter to the API"
+ 74 ```
+ 75
+ 76 The router reads the task, chooses the best `c-*` chain, and runs it in the foreground (`async: false`) so you can stop it with `Esc`/`Ctrl+C`. It dispatches through the `subagent` tool using the same `p-*` prompt bodies the chain recipes use.
+ 77
+ 78 You can also invoke it from another agent or prompt:
+ 79
+ 80 ```text
+ 81 subagent({ agent: "workflow-router", task: "the checkout intermittently times out" })
+ 82 ```
+ 83
  58 ## Why individual prompts are the subagents
  59
  60 Only the `p-*.md` files are marked with `subagent: true` and `fork: true`. The `c-*.md` recipe files are pure wrappers. When `/prompt-workflow` loads a recipe:
  61
     ...
  77 | Symptom | What to check |
  78 |---|---|
  79 | `/c-design-build` just pastes text | Use `/prompt-workflow c-design-build ...` instead. |
  80 | Chain step fails with “Unknown prompt workflow” | Run `/reload`, then `/prompt-workflow list` and confirm each `p-*` in the chain appears. |
- 81 | Chain does not run in background | Confirm the recipe has `async: true` in frontmatter, or add `--bg` to the command. |
+107 | Want the chain to run in background | Add `--bg` or `--async` to the `/prompt-workflow` command. |
  82 | Steps seem disconnected | `fork: true` is required on each `p-*.md`. Check frontmatter. |

--- /home/liph/dotfiles/pi/.pi/agent/prompts/Doc/chain-commands.md
+++ /home/liph/dotfiles/pi/.pi/agent/prompts/Doc/chain-commands.md
@@ -25,17 +25,27 @@
 /prompt-workflow c-refactor-commit "src/utils.ts"
 /prompt-workflow c-security-loop "auth endpoint"
 ```

-Each chain runs asynchronously by default. Check progress with:
+Each chain runs in the foreground by default, so it stays in the current Pi session and you can cancel the current turn with `Esc` or `Ctrl+C`.

+Add `--bg` (or `--async`) to detach the chain and keep working in the main chat while it runs in the background:
+
 ```text
-/subagents-fleet
+/prompt-workflow c-design-build --bg "add a rate-limiter to the API"
 ```

-or inspect a specific run with:
+Stop or inspect a background run:

 ```text
+/subagents-fleet           # live inspector (Ctrl+Alt+F also opens it)
+/subagents-stop <run-id>   # kill a specific run
+subagent({ action: "stop", id: "<run-id>" })
+```
+
+Inspect any run (foreground or background):
+
+```text
 subagent({ action: "status" })
 ```

 ## Ad-hoc chains
@@ -54,8 +64,24 @@
 ```text
 /chain-prompts p-refactor -> p-test -> p-review -> p-commit --bg -- "src/utils.ts"
 ```

+## Automatic routing
+
+If you don't want to pick the recipe manually, use the `workflow-router` agent:
+
+```text
+/run workflow-router "add a rate-limiter to the API"
+```
+
+The router reads the task, chooses the best `c-*` chain, and runs it in the foreground (`async: false`) so you can stop it with `Esc`/`Ctrl+C`. It dispatches through the `subagent` tool using the same `p-*` prompt bodies the chain recipes use.
+
+You can also invoke it from another agent or prompt:
+
+```text
+subagent({ agent: "workflow-router", task: "the checkout intermittently times out" })
+```
+
 ## Why individual prompts are the subagents

 Only the `p-*.md` files are marked with `subagent: true` and `fork: true`. The `c-*.md` recipe files are pure wrappers. When `/prompt-workflow` loads a recipe:

@@ -77,6 +103,6 @@
 | Symptom | What to check |
 |---|---|
 | `/c-design-build` just pastes text | Use `/prompt-workflow c-design-build ...` instead. |
 | Chain step fails with “Unknown prompt workflow” | Run `/reload`, then `/prompt-workflow list` and confirm each `p-*` in the chain appears. |
-| Chain does not run in background | Confirm the recipe has `async: true` in frontmatter, or add `--bg` to the command. |
+| Want the chain to run in background | Add `--bg` or `--async` to the `/prompt-workflow` command. |
 | Steps seem disconnected | `fork: true` is required on each `p-*.md`. Check frontmatter. |


Now edit Doc/prompts.md. Let me read it again to find the exact text to replace.


# Prompts

Slash-style prompts for the interactive pi session. Each file is a `p-<verb>.md` template with a frontmatter `description` + `argument-hint` and a structured body. Invoke with `:p-<verb> [arg]` or via the `:prompts` TUI picker.

## When to use which

| Prompt             | Use it when…                                                                                | Pairs well with                                         |
| ------------------ | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| **`p-plan`**       | You're about to start a non-trivial change and want a structured plan before coding.                            | `p-brainstorm` (first), then `p-refactor` / `p-test`    |
| **`p-brainstorm`** | You have a problem but no chosen approach yet; want 3–5 alternatives with trade-offs.                           | `p-plan` (after picking one)                            |
| **`p-explain`**    | You don't understand a piece of code, a concept, or an error message.                                           | `p-debug` / `p-diagnose` (if it's a problem)            |
| **`p-debug`**      | A test, build, or command is failing with a clear error. You have the error in hand.                            | `p-test` (add a regression test after the fix)          |
| **`p-diagnose`**   | Nothing is "failing" but behavior is wrong — wrong values, races, perf drift, "passes locally, broken in prod." | `p-debug` (if you find a hard failure)                  |
| **`p-review`**     | You want a code review of a diff, file, or staged change. General quality feedback.                             | `p-secaudit` (security subset)                          |
| **`p-secaudit`**   | Touching auth, input handling, secrets, network, deserialization, or any trust boundary.                        | `p-review` (broader quality), `p-test`                  |
| **`p-refactor`**   | Restructuring code without changing behavior. Safety-first, mechanical steps.                                   | `p-test` (first, as the safety net), `p-review` (after) |
| **`p-test`**       | You need to write or expand tests for existing or new code.                                                     | `p-debug` (after a failure), `p-refactor` (before)      |
| **`p-doc`**        | Writing or improving README, docstrings, JSDoc, godoc, or ADRs.                                                 | `p-summarize` (skim the code first)                     |
| **`p-commit`**     | About to commit. You want a conventional message and (optionally) a PR description.                             | `p-review` (final check before committing)              |
| **`p-summarize`**  | A file, log, diff, or document is too long to read in full. You need the gist + key details.                    | `p-plan` / `p-debug` (then dive into specifics)         |

## Decision flow

```
Got an idea or vague problem?
└─ Yes → p-brainstorm  →  pick an approach  →  p-plan  →  implement
                                                          └─ p-test  →  p-commit
Touching existing code that needs to change?
└─ p-refactor (after p-test confirms a safety net)  →  p-review  →  p-commit
Something is broken?
├─ Hard failure (error message, failing test)  →  p-debug
└─ Soft failure (wrong output, race, perf)      →  p-diagnose
                                       →  fix  →  p-test (regression)  →  p-commit
Touching a trust boundary, auth, secrets, or untrusted input?
└─ p-secaudit  (then p-review for general quality)
Need to understand a long file/log/diff quickly?
└─ p-summarize
Need to write or update docs?
└─ p-doc
Don't know what something does or what an error means?
└─ p-explain
```

## Chain recipes

The `c-*` files are not prompts you run directly in the editor. They are orchestration recipes that run a sequence of `p-*` prompts through the `pi-subagents` prompt-workflow adapter. Each `p-*` step is executed as a forked-context subagent, so later steps can see earlier outputs. Chains run asynchronously by default.

| Recipe             | Sequence                                  | Use it when…                                                               |
| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------- |
| **`c-design-build`** | `p-brainstorm → p-plan → p-test → p-commit` | You want to design a feature, plan it, add tests, and commit in one go.    |
| **`c-fix-commit`** | `p-summarize → p-diagnose → p-debug → p-test` | You need to understand a bug, diagnose it, fix it, and add regression tests. |
| **`c-refactor-commit`** | `p-refactor → p-test → p-review → p-commit` | You want a safe refactor with tests, review, and a commit.                  |
| **`c-security-loop`** | `p-secaudit → p-review → p-test`           | You need a security-first review plus tests before proceeding.             |

Invoke a chain with `/prompt-workflow`, not `/c-recipe`:

```text
/prompt-workflow c-design-build --bg "add a rate-limiter to the API"
/prompt-workflow c-fix-commit --bg "the checkout intermittently times out"
/prompt-workflow c-refactor-commit --bg "src/utils.ts"
/prompt-workflow c-security-loop --bg "auth endpoint"
```

Each chain runs in the background. Watch it with `/subagents-fleet` or check status with `subagent({ action: "status" })`. If you want to run the same sequence ad-hoc, use `/chain-prompts`:

```text
/chain-prompts p-brainstorm -> p-plan -> p-test -> p-commit -- "add a rate-limiter"
```

## Conventions

- Every prompt uses `$@` for the user-supplied argument. Pass an argument at invocation time; if the request is under-specified, the prompt will ask clarifying questions.
- Output is structured (numbered sections, fixed categories) so the result is diff-friendly and skim-friendly.
- Prompts intentionally do **not** overlap with subagent workflows (`agents/`, `chains/`, `skills/`) — those are for orchestration; these are for interactive turns.
- Prefer one prompt per turn. Chain them yourself (`p-brainstorm` → `p-plan` → `p-refactor`) rather than asking one prompt to do everything.


I need to update:
1. "Chains run asynchronously by default" to foreground.
2. The examples to remove `--bg`.
3. The text after examples to mention foreground/background.
4. Optionally add a note about workflow-router.

I must preserve the table rows. The table is fine. I'll only change the surrounding text.

Let me make the edits.

The `c-*` files are not prompts you run directly in the editor. They are orchestration recipes that run a sequence of `p-*` prompts through the `pi-subagents` prompt-workflow adapter. Each `p-*` step is executed as a forked-context subagent, so later steps can see earlier outputs. Chains run in the foreground by default (stop with `Esc`/`Ctrl+C`); add `--bg` to detach them.

The `c-*` files are not prompts you run directly in the editor. They are orchestration recipes that run a sequence of `p-*` prompts through the `pi-subagents` prompt-workflow adapter. Each `p-*` step is executed as a forked-context subagent, so later steps can see earlier outputs. Chains run asynchronously by default.

Invoke a chain with `/prompt-workflow`, not `/c-recipe`:

```text
/prompt-workflow c-design-build "add a rate-limiter to the API"
/prompt-workflow c-fix-commit "the checkout intermittently times out"
/prompt-workflow c-refactor-commit "src/utils.ts"
/prompt-workflow c-security-loop "auth endpoint"
```

Add `--bg` to run detached; then watch with `/subagents-fleet`, stop with `/subagents-stop <id>`, or check status with `subagent({ action: "status" })`. To let the agent pick the chain for you, use `/run workflow-router "<task>"`. If you want to run the same sequence ad-hoc, use `/chain-prompts`:

Invoke a chain with `/prompt-workflow`, not `/c-recipe`:

```text
/prompt-workflow c-design-build --bg "add a rate-limiter to the API"
/prompt-workflow c-fix-commit --bg "the checkout intermittently times out"
/prompt-workflow c-refactor-commit --bg "src/utils.ts"
/prompt-workflow c-security-loop --bg "auth endpoint"
```

Each chain runs in the background. Watch it with `/subagents-fleet` or check status with `subagent({ action: "status" })`. If you want to run the same sequence ad-hoc, use `/chain-prompts`: