pi-subagents 0.38.0 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +85 -13
  3. package/agents/worker.md +1 -0
  4. package/package.json +1 -1
  5. package/prompts/review-loop.md +1 -1
  6. package/skills/pi-subagents/SKILL.md +4 -3
  7. package/skills/pi-subagents/references/execution-controls.md +22 -3
  8. package/skills/pi-subagents/references/management-authoring-rpc.md +5 -1
  9. package/skills/pi-subagents/references/prompting-and-roles.md +17 -3
  10. package/src/agents/agent-management.ts +71 -30
  11. package/src/agents/agent-serializer.ts +4 -0
  12. package/src/agents/agents.ts +60 -1
  13. package/src/api/preflight.ts +16 -12
  14. package/src/extension/chain-validation.ts +17 -1
  15. package/src/extension/rpc.ts +2 -0
  16. package/src/extension/schemas.ts +16 -3
  17. package/src/extension/tool-description.ts +6 -5
  18. package/src/intercom/result-intercom.ts +33 -4
  19. package/src/runs/background/async-execution.ts +63 -16
  20. package/src/runs/background/async-job-tracker.ts +5 -1
  21. package/src/runs/background/async-resume.ts +1 -0
  22. package/src/runs/background/async-status.ts +18 -2
  23. package/src/runs/background/chain-append.ts +48 -5
  24. package/src/runs/background/control-channel.ts +60 -0
  25. package/src/runs/background/notify.ts +26 -4
  26. package/src/runs/background/result-watcher.ts +20 -3
  27. package/src/runs/background/run-status.ts +29 -3
  28. package/src/runs/background/subagent-runner.ts +302 -18
  29. package/src/runs/foreground/async-stop-action.ts +65 -0
  30. package/src/runs/foreground/chain-execution.ts +143 -43
  31. package/src/runs/foreground/execution.ts +384 -202
  32. package/src/runs/foreground/foreground-control.ts +30 -0
  33. package/src/runs/foreground/subagent-executor.ts +314 -77
  34. package/src/runs/shared/capability-ceiling.ts +51 -19
  35. package/src/runs/shared/chain-outputs.ts +3 -1
  36. package/src/runs/shared/dynamic-fanout.ts +1 -1
  37. package/src/runs/shared/nested-events.ts +97 -20
  38. package/src/runs/shared/parallel-utils.ts +43 -12
  39. package/src/runs/shared/pi-args.ts +45 -3
  40. package/src/runs/shared/process-signal.ts +19 -0
  41. package/src/runs/shared/run-history.ts +45 -9
  42. package/src/runs/shared/runtime-acknowledged-extensions.ts +71 -0
  43. package/src/runs/shared/subagent-prompt-runtime.ts +30 -0
  44. package/src/runs/shared/usage-budget.ts +65 -0
  45. package/src/runs/shared/workflow-graph.ts +26 -1
  46. package/src/shared/settings.ts +17 -1
  47. package/src/shared/types.ts +124 -8
  48. package/src/shared/utils.ts +12 -1
  49. package/src/slash/slash-commands.ts +43 -1
  50. package/src/slash/slash-live-state.ts +5 -3
  51. package/src/tui/fleet-status.ts +12 -2
  52. package/src/tui/fleet.ts +181 -8
  53. package/src/tui/render.ts +4 -2
  54. package/src/watchdog/register-main.ts +14 -7
  55. package/src/watchdog/review.ts +4 -3
  56. package/src/watchdog/runtime.ts +170 -17
  57. package/src/watchdog/scope.ts +62 -0
  58. package/src/watchdog/settings.ts +41 -1
  59. package/src/watchdog/types.ts +10 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,44 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.40.0] - 2026-08-01
6
+
7
+ ### Added
8
+ - Documented an optional recommended model-tiering setup in the README: fast workhorse, standard well-scoped, deep-but-bounded, and taste/intent tiers, with cross-provider `fallbackModels` guidance for usage-limit resilience.
9
+ - Added `description` to `subagents.agentOverrides` so deployments can replace the discovered description for builtin and custom agents in list output. Thanks to @chronoAP for #724.
10
+
11
+ ### Changed
12
+ - Refreshed the bundled `pi-subagents` skill for the 0.39 surface: Fleet inspector live controls (`s` steer, `D` stop), the recommended model-tiering recipe, `agentOverrides.description`, `projectRootResolution: "git-root"`, running-card live-detail/model badges, and the newer extension RPC capability projections (`fleetStatus`, `launchResolvedExtensions`, `runtimeAcknowledgedExtensions`, `(runId, index)` correlation). Corrected the stale README "inspection-only" fleet inspector wording.
13
+
14
+ ### Fixed
15
+ - Grouped intercom results now report child process status separately from provenance-aware output availability, including salvage guidance when a failed process produced output. Thanks to @youlikemodernart for #727.
16
+ - Collapsed running foreground subagent rows now show the model and thinking level: single-result cards include the effective thinking suffix and parallel/chain rows show the per-child model badge, matching the async widget.
17
+
18
+ ## [0.39.0] - 2026-08-01
19
+
20
+ ### Added
21
+ - Added session-scoped `allowedAgents` capability ceilings for restricting launchable agent roles without global agent disabling. Thanks to @aoguai for #719.
22
+ - Added stable foreground result row indexes for correlating child progress and final results. Thanks to @rochecompaan (Patchmill) for #720.
23
+ - Added watchdog current-scope context, optional every-N-tools scope-monitor cadence, and visible main-session blocker auto-follow, inspired by Scopey (github.com/ArchAstro/scopey) by Calvin Grunewald (@CalvinGrunewald).
24
+ - Added optional `runtimeAcknowledgedExtensions` status/result/RPC metadata for cooperating child-runtime extensions that emit `subagent:acknowledge-extension`. Thanks to @saleemlala for #705.
25
+ - Added `/subagents-detach` for detaching the active foreground single-subagent run without terminating the child. Thanks to @magoz for #708/#711.
26
+ - Added agent frontmatter aliases and built-in worker aliases for `developer`, `coder`, `implementer`, and `develop`, while keeping canonical names in execution state. Thanks to @selimerunkut for #695.
27
+ - Added explicit chain approval checkpoints with `{ checkpoint, message? }`, `approve-checkpoint`/`reject-checkpoint` controls, persisted checkpoint status, and terminal `rejected` outcomes. Thanks to @saleemlala for #694.
28
+ - Added optional root `usageBudget` limits for reported token and cost totals, with soft status reporting and hard gating for later child launches without stopping already-running children. Thanks to @saleemlala for #693.
29
+ - Added optional `launchResolvedExtensions` status/result/RPC metadata with opaque launch-resolved child extension identifiers and ambient-extension state. Thanks to @saleemlala for #691.
30
+ - Added Fleet inspector controls to steer the selected live async child and stop its top-level async run with confirmation. Thanks to @saleemlala for #692.
31
+
32
+ ### Changed
33
+ - Reduced repeated runtime filesystem work by caching stable Pi config-directory resolution, incrementally sanitizing run history, and limiting nested control-result polling to files created for the active request.
34
+
35
+ ### Fixed
36
+ - Show per-child async task descriptions in the persistent running-subagents status widget instead of repeating the run-level description for every parallel child.
37
+ - Restored model and thinking-effort badges in the persistent running-subagents status widget.
38
+ - Retained foreground controls until scheduling owners and active children settle, keeping queued foreground work steerable after early result handling. Thanks to @magoz for #708/#709/#710.
39
+ - Render resolved model and thinking effort for active and recent foreground children in Fleet inspector summaries and details. Thanks to @saleemlala for #706.
40
+ - Resynchronized async job control-event scans that resume inside an oversized JSONL record, avoiding malformed-tail parse noise while preserving later control events. Thanks to @vicary for #700.
41
+ - Report signal-terminated child processes with a canonical signal error instead of stderr-tail noise and classify those results separately from ordinary task failures. Thanks to @cking000bigdemon for #688.
42
+
5
43
  ## [0.38.0] - 2026-07-30
6
44
 
7
45
  ### Added
package/README.md CHANGED
@@ -155,6 +155,31 @@ For a persistent override, edit settings. This example pins the reviewer everywh
155
155
  }
156
156
  ```
157
157
 
158
+ ### Recommended model tiering (optional)
159
+
160
+ A setup that works well in practice is routing agents by task shape instead of running everything on one model. Four tiers:
161
+
162
+ 1. **Fast workhorse** — the cheapest capable model at low thinking, for recon, lookups, and mechanical edits. Example: `openai-codex/gpt-5.6-luna:low` on `scout`.
163
+ 2. **Standard well-scoped** — a mid-tier model at medium thinking, for most delegations: routine multi-file edits, focused reviews, straightforward implementation. Example: `openai-codex/gpt-5.6-terra:medium` on `worker`, `reviewer`, and a lightweight `delegate` agent.
164
+ 3. **Deep but bounded** — a top reasoning model at high thinking, only for hard tasks that arrive with explicit goals and completion criteria. These models tend to loop on vague goals, so keep them off open-ended work. Example: `openai-codex/gpt-5.6-sol:high` on `planner` and oracle-style agents.
165
+ 4. **Taste and intent** — a model that reads human intent well and makes judgment calls without looping, for ambiguous work: UX and design decisions, product tradeoffs, planning from vague requirements, writing quality. Example: `anthropic/claude-fable-5` at `low` for lighter passes and `medium` for harder ones.
166
+
167
+ The routing rule: use the capability tiers (1–3) when the task is well-scoped, and the intent tier (4) when scoping or judging is the task itself.
168
+
169
+ Give tier-4 agents cross-provider `fallbackModels` so subscription usage limits degrade gracefully instead of failing the run — fallback triggers on rate-limit and overload errors automatically:
170
+
171
+ ```yaml
172
+ ---
173
+ name: shaper
174
+ description: Open-ended design/UX/product/planning agent for ambiguous tasks
175
+ model: anthropic/claude-fable-5
176
+ thinking: medium
177
+ fallbackModels: openai-codex/gpt-5.5:high
178
+ ---
179
+ ```
180
+
181
+ One more interaction worth knowing for tier 4: forked context over an Anthropic parent transcript with signed thinking blocks forces the child's thinking off, so intent-tier agents work best with fresh context.
182
+
158
183
  Use `~/.pi/agent/settings.json` for a user override or the project config settings file (`.pi/settings.json` in standard Pi) for a project override. `subagents.defaultModel` applies to builtin, package, user, and project agents that do not set `model` in frontmatter. Per-run model overrides and `agentOverrides.<name>.model` still win, and explicit agent frontmatter still wins over the global default. The same `agentOverrides` block can change `tools`, `skills`, inherited context, prompt text, or disable a builtin. Matching user and project agents also receive override fields that their frontmatter leaves unset, so a shared project config agent can keep the persona while local settings choose the model.
159
184
 
160
185
  By default, project settings resolve from the nearest parent directory that contains `.pi` or `.agents`, preserving existing nested-project behavior. In monorepos or git worktrees where an incidental nested `.pi` directory should not shadow the repository-level config, set this in the repository root `.pi/settings.json`:
@@ -218,6 +243,12 @@ The subagent watchdog is not the `reviewer` subagent. `subagents.defaultModel` a
218
243
 
219
244
  The watchdog reviews repo edits, not ordinary conversation. It runs at the safe `agent_end` boundary only when the current agent or child writer changed the final repo state since the start of that turn. Multiple edits in one turn are coalesced into one review of the final changed state, unchanged/reverted diffs are skipped, and generated `.pi-subagents/` or `tmp/` artifacts do not trigger review. In orchestrated runs, each writing child can review its own edited worktree, and the parent can still review the aggregate repo diff after child changes are applied.
220
245
 
246
+ When enabled, the watchdog also keeps a bounded in-memory current-scope artifact from real user prompts and prepends it to review input by default (`subagents.watchdog.scope.enabled`). Newer prompts supersede and mutate older prompts, so the reviewer can flag work that no longer serves the current scope as `scope-drift`. Watchdog auto-follow prompts are not recorded as scope.
247
+
248
+ You can opt into Scopey-style scope monitoring, inspired by [Scopey](https://github.com/ArchAstro/scopey), by setting `subagents.watchdog.cadence.everyNTools` to run additional non-blocking reviews every N tool results. Cadence warnings are transcript-visible and delivered with Pi's `steer` mode after the current tool boundary; they are never hidden. The same configured watchdog model is used for all checks, so choose a cheap model for frequent monitoring or a strong model for rarer adversarial review.
249
+
250
+ When the watchdog displays a blocker at `agent_end`, the existing `subagents.watchdog.autoFollow` policy can queue a visible follow-up user message asking the agent to address it. Auto-follow only runs while the watchdog is enabled, respects `maxAttempts`, and stops on repeated identical blockers using `stalemateRepeats`.
251
+
221
252
  When the watchdog is enabled, it also checks changed TypeScript and JavaScript files for fresh language-server diagnostics before the model review. It auto-detects `typescript-language-server` from the project `node_modules/.bin` or `PATH`; it never installs tools or scans the whole workspace. LSP errors surface as watchdog blockers, warnings as concerns, and info/hints stay in status details. Slow or missing servers are reported in `/subagents-watchdog status` without blocking the turn or emitting late mid-turn warnings. Configure the bounds with `subagents.watchdog.lsp.enabled`, `timeoutMs`, `maxFiles`, and `maxDiagnostics`.
222
253
 
223
254
  Use `/subagents-watchdog recommend-model` to ask pi-subagents for the current strong pairing. The current recommendation policy is Opus 4.8 with thinking high or GPT 5.5 with thinking high. If your main session is using one, the watchdog should use the other when that model is authenticated.
@@ -241,6 +272,8 @@ You can also set the model explicitly:
241
272
 
242
273
  For settings files, use `subagents.watchdog.main.model` and `subagents.watchdog.main.thinking` for the main watchdog. If `main.model` is omitted, the main watchdog uses the current session model and thinking level. If `main.model` is set without a thinking suffix or `main.thinking`, it runs with thinking off, so prefer `:high` or `"thinking": "high"` for the strong-watchdog pairing.
243
274
 
275
+ Default strong-reviewer profile:
276
+
244
277
  ```json
245
278
  {
246
279
  "subagents": {
@@ -255,6 +288,29 @@ For settings files, use `subagents.watchdog.main.model` and `subagents.watchdog.
255
288
  }
256
289
  ```
257
290
 
291
+ Scopey-style scope monitoring profile:
292
+
293
+ ```json
294
+ {
295
+ "subagents": {
296
+ "watchdog": {
297
+ "enabled": true,
298
+ "main": {
299
+ "model": "anthropic/claude-haiku-4-5",
300
+ "thinking": "medium"
301
+ },
302
+ "scope": { "enabled": true },
303
+ "cadence": { "everyNTools": 10 },
304
+ "autoFollow": {
305
+ "blockers": true,
306
+ "maxAttempts": 3,
307
+ "stalemateRepeats": 3
308
+ }
309
+ }
310
+ }
311
+ }
312
+ ```
313
+
258
314
  For child subagent watchdogs, use `subagents.watchdog.children.model` as the default child watchdog model, or `subagents.watchdog.children.overrides.<agent>.model` for a specific child role. Child watchdogs are still opt-in and follow the same edit-gated rule: read-only children do not trigger watchdog reviews, while writer children are reviewed at their own `agent_end` if their worktree changed.
259
315
 
260
316
  Agents can configure the same values through the tool when you ask them to set up the watchdog:
@@ -288,7 +344,7 @@ Foreground runs stream progress in the conversation while they run. They default
288
344
 
289
345
  Background runs keep working after control returns to you. Inspect active runs with `subagent({ action: "status" })`, or a specific run with `subagent({ action: "status", id: "..." })`. In the TUI, a persistent FleetView below the editor by default shows `main` plus active children with task, elapsed time, and token totals. Set `fleetViewPlacement` to `"aboveEditor"` to move it above the editor. When the focused editor is empty, press `↓` or `←` to activate FleetView, then use `↑`/`↓` or `j`/`k` to select a child and `Enter` to inspect it; printable navigation keys are never intercepted before activation.
290
346
 
291
- `/subagents-fleet` opens the live, inspection-only fleet inspector with current-session foreground work, recent async children, structured Markdown/tool transcripts, and completed output/session paths. Use `↑`/`↓` or `j`/`k` to select a child, `Shift+K`/`Shift+J` to scroll one line, `PgUp`/`PgDn` to scroll one page, `x`/`Ctrl+O` to toggle tool details, `r` to refresh, and `Esc` to close. `Ctrl+Alt+F` opens the same inspector even while a foreground turn is active and slash input is queued. Without a TUI, `/subagents-fleet` retains the textual `subagent({ action: "status", view: "fleet" })` fallback. Mutations stay in explicit commands: run `/subagents-stop` and pick from the selector, or use `/subagents-stop <run-id>` / `subagent({ action: "stop", id: "..." })` when you already know the id. To inspect one background child in text, use `subagent({ action: "status", id: "...", view: "transcript" })`; add `index` for a specific child in a parallel or chain run.
347
+ `/subagents-fleet` opens the live fleet inspector with current-session foreground work, recent async children, structured Markdown/tool transcripts, and completed output/session paths. Use `↑`/`↓` or `j`/`k` to select a child, `Shift+K`/`Shift+J` to scroll one line, `PgUp`/`PgDn` to scroll one page, `x`/`Ctrl+O` to toggle tool details, `r` to refresh, and `Esc` to close. For a selected live async child, `s` sends an acknowledged steer message and `D` stops its top-level async run after confirmation. `Ctrl+Alt+F` opens the same inspector even while a foreground turn is active and slash input is queued. Without a TUI, `/subagents-fleet` retains the textual `subagent({ action: "status", view: "fleet" })` fallback, and mutations use explicit commands: run `/subagents-stop` and pick from the selector, or use `/subagents-stop <run-id>` / `subagent({ action: "stop", id: "..." })` when you already know the id. Use `/subagents-detach [run-id]` only for an active foreground single-subagent run you want to leave running without terminating; the eventual result remains available through status/wait. To inspect one background child in text, use `subagent({ action: "status", id: "...", view: "transcript" })`; add `index` for a specific child in a parallel or chain run.
292
348
 
293
349
  FleetView replaces the legacy above-editor async widget by default, while completion notifications remain enabled. Parallel runs show every active child independently. Chains with parallel groups keep their grouped shape in progress and results, so failed or paused agents stay visible next to completed ones. When a child is explicitly allowed to fan out with `tools: subagent`, its nested runs appear under that parent child in the main status tree instead of being hidden inside the child process.
294
350
 
@@ -304,9 +360,9 @@ Async runs also write machine-readable lifecycle artifacts for observability and
304
360
 
305
361
  Foreground and async runners share bounded child-protocol handling. A child JSONL line above 4 MiB fails with structured `protocolError` code `protocol_output_limit`, stderr retains only its latest 128 KiB, split UTF-8 and final unterminated JSON events remain valid, and `agent_end.willRetry` defers completion until the child settles. Current Pi builds use `agent_settled` as the terminal watermark; older builds retain the bounded terminal-message fallback.
306
362
 
307
- The stable v1 status/result fields are `lifecycleArtifactVersion`, `runId`/`id`, `sessionId`, `mode`, `state`, `startedAt`, `lastUpdate`, `endedAt`, `durationMs`, `cwd`, `asyncDir`, `sessionFile`, `outputFile`, `workflowGraph`, `steps`, `results`, `totalTokens`, `totalCost`, `model`/`attemptedModels`/`modelAttempts`, `toolCount`, `turnCount`, and nested `children` when a child is allowed to launch subagents. `events.jsonl` records lifecycle transitions such as `subagent.run.started`, `subagent.step.started`, `subagent.step.completed`/`failed`/`paused`/`stopped`, control attention events, nested interrupt failures, and `subagent.run.completed`/`stopped`; run boundary events include the lifecycle artifact version. Consumers should read these JSON files instead of scraping terminal output; unknown fields and event types should be ignored for forward compatibility.
363
+ The stable v1 status/result fields are `lifecycleArtifactVersion`, `runId`/`id`, `sessionId`, `mode`, `state`, `startedAt`, `lastUpdate`, `endedAt`, `durationMs`, `cwd`, `asyncDir`, `sessionFile`, `outputFile`, `workflowGraph`, `steps`, `results`, `totalTokens`, `totalCost`, `model`/`attemptedModels`/`modelAttempts`, `toolCount`, `turnCount`, optional `launchResolvedExtensions`, optional `runtimeAcknowledgedExtensions`, and nested `children` when a child is allowed to launch subagents. `launchResolvedExtensions` is parent-resolved launch intent only: it reports opaque extension identifiers and whether ambient extensions were disabled, without exposing raw extension paths or claiming the child runtime acknowledged that those extensions loaded. Cooperating child extensions can acknowledge child-runtime registration by emitting `subagent:acknowledge-extension` on the child process `pi.events` bus with payload `{ id: string }`. Acknowledgement ids are self-declared opaque strings, must be non-empty, at most 128 characters, contain only `A-Z`, `a-z`, `0-9`, `.`, `_`, `:`, `@`, `+`, or `-`, and must not contain `/`, `\\`, or `..`. The reported `runtimeAcknowledgedExtensions` projection is `{ version: 1, source: "child-runtime", ids, omitted }`, deduplicates ids, keeps at most 32 ids, and counts additional valid unique ids in `omitted`. It is best-effort observability only: absence means no cooperating extension acknowledged, and presence means only that the extension registered in the child runtime, not that its tools, health checks, or features succeeded. Late acknowledgements after terminal serialization are ignored. `events.jsonl` records lifecycle transitions such as `subagent.run.started`, `subagent.step.started`, `subagent.step.completed`/`failed`/`paused`/`stopped`, control attention events, nested interrupt failures, and `subagent.run.completed`/`stopped`; run boundary events include the lifecycle artifact version. Consumers should read these JSON files instead of scraping terminal output; unknown fields and event types should be ignored for forward compatibility.
308
364
 
309
- Other Pi extensions can use the versioned in-process event-bus RPC instead of scraping slash output or calling internal modules. Listen for `subagents:rpc:v1:ready`, send requests on `subagents:rpc:v1:request`, and read replies from `subagents:rpc:v1:reply:<requestId>`. The `ping` capability metadata also advertises `events.asyncComplete` for exact process-local completion correlation after RPC `spawn`. Delegation v1/v2 progress updates carry `runId` as soon as foreground execution allocates it, so a caller can retain the package-owned revival target even if its own tool turn is interrupted before the terminal response.
365
+ Other Pi extensions can use the versioned in-process event-bus RPC instead of scraping slash output or calling internal modules. Listen for `subagents:rpc:v1:ready`, send requests on `subagents:rpc:v1:request`, and read replies from `subagents:rpc:v1:reply:<requestId>`. The `ping` capability metadata also advertises `events.asyncComplete` for exact process-local completion correlation after RPC `spawn`. Delegation v1/v2 progress updates carry `runId` as soon as foreground execution allocates it, so a caller can retain the package-owned revival target even if its own tool turn is interrupted before the terminal response. Foreground `details.results[]` rows also include a numeric `index` that is unique within the run and stable across partial progress snapshots and the final result; use `(runId, index)` instead of row position to correlate single, counted parallel, and chain children.
310
366
 
311
367
  ```typescript
312
368
  const requestId = crypto.randomUUID();
@@ -322,7 +378,7 @@ pi.events.emit("subagents:rpc:v1:request", {
322
378
  });
323
379
  ```
324
380
 
325
- The v1 methods are `ping`, `status`, `spawn`, `steer`, `interrupt`, `stop`, and `resume`. `status`, `steer`, `interrupt`, and `resume` reuse the normal package-owned actions. When `ping.capabilities.fleetStatus` is `{ version: 1 }`, successful `status` replies additionally include `data.fleet`: `{ version: 1, entries, totalActive, omitted }`. Entries are bounded, current-session public display records with an opaque reconciliation `key`, resolved `agent`, optional `role`, `model`, `effort`, caller-facing `goal`, safe `startedAt`, and `{ input, output, total }` tokens. `totalActive` and `omitted` preserve overflow information beyond the bounded entry window. The DTO intentionally never exposes run, async, or tool IDs; clients must ignore unknown fields and fall back to status text when the capability is absent. `steer` requires an async run `id` (plus optional child `index`) and a non-empty `message`; its reply preserves the normal acknowledged-delivery result. RPC steering disables the direct tool's pause-and-revive recovery so an extension keeps authority over the exact child it spawned; `ping.capabilities.nonRecoveringSteer` advertises this guarantee. `resume` requires a run target and non-empty `message`; it delegates to the existing revival path, which validates current-session ownership, persisted session/recovery metadata, stopped/live state, capability ceilings, and the exclusive session lease before returning the new async run details. Callers may request a `file-only` output path for the revived result without overriding its model, tools, or budgets. `ping.capabilities.resume` advertises this seam. `spawn` is async-only: omit `async` or set `async: true`, omit `clarify` or set `clarify: false`, and do not pass management `action` values. It goes through the same executor as the `subagent` tool, so agent discovery, validation, session attribution, configured spawn caps, child-safety depth, artifacts, and async status all behave the same. `stop` targets current-session top-level async runs through the stop control channel and records a `stopped` lifecycle instead of reporting a timeout.
381
+ The v1 methods are `ping`, `status`, `spawn`, `steer`, `interrupt`, `stop`, and `resume`. `status`, `steer`, `interrupt`, and `resume` reuse the normal package-owned actions. `ping.capabilities.launchResolvedExtensions` advertises the optional launch-resolved extension projection in status details. `ping.capabilities.runtimeAcknowledgedExtensions` advertises the optional child-runtime acknowledgement projection and event name. When `ping.capabilities.fleetStatus` is `{ version: 1 }`, successful `status` replies additionally include `data.fleet`: `{ version: 1, entries, totalActive, omitted }`. Entries are bounded, current-session public display records with an opaque reconciliation `key`, resolved `agent`, optional `role`, `model`, `effort`, caller-facing `goal`, safe `startedAt`, and `{ input, output, total }` tokens. `totalActive` and `omitted` preserve overflow information beyond the bounded entry window. The DTO intentionally never exposes run, async, or tool IDs; clients must ignore unknown fields and fall back to status text when the capability is absent. `steer` requires an async run `id` (plus optional child `index`) and a non-empty `message`; its reply preserves the normal acknowledged-delivery result. RPC steering disables the direct tool's pause-and-revive recovery so an extension keeps authority over the exact child it spawned; `ping.capabilities.nonRecoveringSteer` advertises this guarantee. `resume` requires a run target and non-empty `message`; it delegates to the existing revival path, which validates current-session ownership, persisted session/recovery metadata, stopped/live state, capability ceilings, and the exclusive session lease before returning the new async run details. Callers may request a `file-only` output path for the revived result without overriding its model, tools, or budgets. `ping.capabilities.resume` advertises this seam. `spawn` is async-only: omit `async` or set `async: true`, omit `clarify` or set `clarify: false`, and do not pass management `action` values. It goes through the same executor as the `subagent` tool, so agent discovery, validation, session attribution, configured spawn caps, child-safety depth, artifacts, and async status all behave the same. `stop` targets current-session top-level async runs through the stop control channel and records a `stopped` lifecycle instead of reporting a timeout.
326
382
 
327
383
  `pi.events` is in-process only. It does not reach separate Pi processes or child subagents; use the file lifecycle artifacts or `pi-intercom` for cross-process coordination.
328
384
 
@@ -487,6 +543,7 @@ Skip this section until you want exact syntax.
487
543
  | `/subagent-cost` | Show parent plus child subagent token usage and cost for this session |
488
544
  | `/subagents [agent] [model\|thinking\|prompt\|details]` | Interactively inspect or edit an agent's model, thinking level, or system prompt |
489
545
  | `/subagents-doctor` | Show read-only setup diagnostics |
546
+ | `/subagents-detach [run-id]` | Detach an active foreground single-subagent run without terminating its child |
490
547
  | `/subagents-models [agent]` | Show the runtime-loaded builtin model mapping, optionally filtered to one builtin |
491
548
  | `/subagents-watchdog [status|on|off|recommend-model|model ...|session model ...|check]` | Show or configure the opt-in watchdog; use a strong complementary model such as Opus 4.8 high or GPT 5.5 high |
492
549
  | `/subagents-profiles` | List saved subagent profiles from `~/.pi/agent/profiles/pi-subagents/` |
@@ -704,6 +761,7 @@ Example:
704
761
  "subagents": {
705
762
  "agentOverrides": {
706
763
  "reviewer": {
764
+ "description": "Independent review tier",
707
765
  "inheritProjectContext": false
708
766
  }
709
767
  }
@@ -711,7 +769,7 @@ Example:
711
769
  }
712
770
  ```
713
771
 
714
- Supported override fields are `model`, `fallbackModels`, `thinking`, `systemPromptMode`, `inheritProjectContext`, `inheritSkills`, `defaultContext`, `acceptanceRole`, `disabled`, `skills`, `tools`, and `systemPrompt`. Use `defaultContext: false` or `acceptanceRole: false` to clear an inherited override. Project overrides beat user overrides.
772
+ Supported override fields are `description`, `model`, `fallbackModels`, `thinking`, `systemPromptMode`, `inheritProjectContext`, `inheritSkills`, `defaultContext`, `acceptanceRole`, `disabled`, `skills`, `tools`, and `systemPrompt`. `description` replaces the discovered description for builtin and custom agents, which lets list output show deployment-specific routing or model metadata. Use `defaultContext: false` or `acceptanceRole: false` to clear an inherited override. Project overrides beat user overrides.
715
773
 
716
774
  Set `subagents.defaultModel` to give all subagents without an explicit model their own default model, separate from the parent session model. Per-agent model overrides and agent frontmatter still win.
717
775
 
@@ -744,6 +802,7 @@ name: scout
744
802
  # Optional: registers this as code-analysis.scout while preserving name: scout
745
803
  package: code-analysis
746
804
  description: Fast codebase recon
805
+ aliases: explorer, code-scout
747
806
  tools: read, grep, find, ls, bash, mcp:chrome-devtools
748
807
  extensions:
749
808
  subagentOnlyExtensions: ./tools/child-only-search.ts
@@ -787,6 +846,7 @@ Important fields:
787
846
  | Field | Notes |
788
847
  |-------|-------|
789
848
  | `package` | Optional package identifier. A file with `name: scout` and `package: code-analysis` registers as `code-analysis.scout`; serialization keeps `name` and `package` separate. |
849
+ | `aliases` | Optional comma-separated or block-list names that resolve to this agent for selection and explicit `agent`/chain/task inputs. Runtime status, persistence, and config still use the canonical `name`; exact canonical names take precedence over aliases, and alias collisions between distinct canonical agents fail as ambiguous. |
790
850
  | `tools` | Strict child tool allowlist. Named extension tools must also have their provider loaded. `mcp:` entries select direct MCP tools when `pi-mcp-adapter` is installed. |
791
851
  | `extensions` | Omitted means normal extensions; empty means no extensions; list values allowlist specific extensions. |
792
852
  | `subagentOnlyExtensions` | Extension paths loaded only in spawned child sessions for this agent. Tools registered there are unavailable to the main agent unless also installed through normal Pi extension configuration. |
@@ -1188,13 +1248,17 @@ import { registerSubagentCapabilityCeiling } from "pi-subagents/capability-ceili
1188
1248
  const restriction = registerSubagentCapabilityCeiling({
1189
1249
  sessionId: ctx.sessionManager.getSessionId(),
1190
1250
  source: "plan-mode",
1191
- ceiling: { allowedTools: ["read", "grep", "find", "ls"], denyExtensions: true },
1251
+ ceiling: {
1252
+ allowedAgents: ["plan-scout", "plan-researcher", "plan-reviewer"],
1253
+ allowedTools: ["read", "grep", "find", "ls"],
1254
+ denyExtensions: true,
1255
+ },
1192
1256
  });
1193
1257
  // restriction.update(...) replaces this provider's policy atomically.
1194
1258
  // restriction.dispose() removes only this provider's registration.
1195
1259
  ```
1196
1260
 
1197
- Active registrations intersect their `allowedTools` sets and OR `denyExtensions`; an explicit empty list means no caller-facing tools, while an omitted list does not restrict names. The resolved snapshot is propagated monotonically to nested and async children and is retained for recovery. `structured_output` may remain as a package-owned internal protocol tool when an output schema requires it; it is not a caller capability. A denied lazy-skill `read` requirement fails before spawn rather than widening the ceiling.
1261
+ Active registrations intersect their `allowedTools` and `allowedAgents` sets and OR `denyExtensions`; an explicit empty list means no caller-facing tools or launchable agents for that field, while an omitted list does not restrict names. `allowedAgents` entries are canonical agent names and are case-sensitive. Launching a non-allowlisted agent fails before spawn, and `{ action: "list" }` keeps restricted agents visible in a separate non-executable section instead of silently hiding them. The resolved snapshot is propagated monotonically to nested and async children and is retained for recovery. `structured_output` may remain as a package-owned internal protocol tool when an output schema requires it; it is not a caller capability. A denied lazy-skill `read` requirement fails before spawn rather than widening the ceiling.
1198
1262
 
1199
1263
  `denyExtensions` suppresses ambient, configured, and MCP provider extensions while retaining the package runtime needed for child protocol enforcement. This is a same-process policy boundary, not a sandbox against malicious code already running in the parent process. Schedules created while a ceiling is active are rejected until durable schedule persistence is available; unrestricted schedules remain subject to any policy active when they fire. Public status exposes bounded audit counts and sources, never full extension paths.
1200
1264
 
@@ -1246,6 +1310,7 @@ These are the parameters the LLM passes when it calls the `subagent` tool. Most
1246
1310
  { chain: [
1247
1311
  { agent: "scout", task: "Gather context for auth refactor" },
1248
1312
  { agent: "planner" },
1313
+ { checkpoint: "implementation", message: "Approve implementation before review?" },
1249
1314
  { agent: "worker" },
1250
1315
  { agent: "reviewer" }
1251
1316
  ]}
@@ -1364,7 +1429,7 @@ Agent definitions are not loaded into context by default. Management actions let
1364
1429
  { action: "reset", agent: "reviewer" }
1365
1430
  ```
1366
1431
 
1367
- `create` uses `config.scope`, not `agentScope`. `config.name` is the local frontmatter name; optional `config.package` registers the runtime name as `{package}.{name}` and is saved as separate `name` and `package` frontmatter. `update` and `delete` use the runtime name and `agentScope` only when the same runtime name exists in multiple scopes. To clear optional string fields, including `package`, set them to `false` or `""`.
1432
+ `create` uses `config.scope`, not `agentScope`. `config.name` is the local frontmatter name; optional `config.package` registers the runtime name as `{package}.{name}` and is saved as separate `name` and `package` frontmatter. `config.aliases` accepts a comma-separated string, string array, or `false` to clear aliases; aliases resolve to the canonical agent name for execution and are shown by `list`/`get`. `update` and `delete` use the runtime name and `agentScope` only when the same runtime name exists in multiple scopes. To clear optional string fields, including `package`, set them to `false` or `""`.
1368
1433
 
1369
1434
  `eject` copies a bundled builtin or package agent verbatim into the user or project agent dir (default `user`) as an editable custom file that shadows the original, so you can customize a builtin without hunting package files. `disable` writes a reversible `agentOverrides.<name>.disabled: true` entry to the user or project settings file (default `user`); the agent stays on disk but is hidden from runtime discovery and `list`. `enable` removes that `disabled` field while preserving any other override fields on the same entry. `reset` deletes the scope's custom agent file and/or settings override entry, restoring the bundled default; it refuses if no bundled default exists (use `delete` for purely custom agents). All four accept `agentScope: "user" | "project"` and operate in one scope at a time; project overrides still win over user ones, so a project-scope disable survives a user-scope `enable` until you target the project scope.
1370
1435
 
@@ -1372,9 +1437,9 @@ Agent definitions are not loaded into context by default. Management actions let
1372
1437
 
1373
1438
  | Param | Type | Default | Description |
1374
1439
  |-------|------|---------|-------------|
1375
- | `agent` | string | - | Agent name for single mode, or target for management actions. |
1440
+ | `agent` | string | - | Agent name or alias for single mode, or target for management actions. Execution records use the canonical agent name. |
1376
1441
  | `task` | string | - | Task string for single mode. |
1377
- | `action` | string | - | `list`, `get`, `create`, `update`, `delete`, `status`, `interrupt`, `stop`, `resume`, `steer`, `append-step`, or `doctor`. |
1442
+ | `action` | string | - | `list`, `get`, `create`, `update`, `delete`, `status`, `interrupt`, `stop`, `resume`, `steer`, `append-step`, `approve-checkpoint`, `reject-checkpoint`, or `doctor`. |
1378
1443
  | `chainName` | string | - | Chain name for management actions. |
1379
1444
  | `config` | object/string | - | Agent or chain config for create/update. |
1380
1445
  | `output` | `string \| false` | agent default | Override single-agent output file. |
@@ -1386,7 +1451,7 @@ Agent definitions are not loaded into context by default. Management actions let
1386
1451
  | `tasks` | array | - | Top-level parallel tasks. Supports `agent`, `task`, `cwd`, `count`, `output`, `outputMode`, `outputSchema`, `reads`, `progress`, `skill`, `model`, `toolBudget`, `acceptance`, and `agentContract`. |
1387
1452
  | `concurrency` | number | config or `4` | Top-level parallel concurrency. |
1388
1453
  | `worktree` | boolean | false | Create isolated git worktrees for parallel tasks. |
1389
- | `chain` | array | - | Sequential, static parallel, and dynamic fanout chain steps. Steps and chain parallel tasks support `phase`, `label`, `as`, `outputSchema`, `acceptance`, `agentContract`, and v1-only `gateOn` in addition to the usual execution fields. Dynamic fanout uses `expand`, one child `parallel` template, and `collect`. With `action: "append-step"`, pass exactly one step to append to a running async chain. |
1454
+ | `chain` | array | - | Sequential, checkpoint, static parallel, and dynamic fanout chain steps. Steps and chain parallel tasks support `phase`, `label`, `as`, `outputSchema`, `acceptance`, `agentContract`, and v1-only `gateOn` in addition to the usual execution fields. Dynamic fanout uses `expand`, one child `parallel` template, and `collect`. With `action: "append-step"`, pass exactly one step to append to a running async chain. |
1390
1455
  | `context` | `fresh \| fork` | per-agent default or `fresh` | Explicit `fresh` or `fork` overrides every child. When omitted, each agent uses its own `defaultContext`; `fork` creates real branched sessions from the parent leaf. Packaged `planner`, `worker`, `oracle`, and `advisor` default to `fork`. |
1391
1456
  | `chainDir` | string | temp chain dir | Persistent directory for chain artifacts. Relative chain `output`, `reads`, and `progress` paths live under this directory. |
1392
1457
  | `view` | `fleet \| transcript` | - | Optional `status` view for the active fleet surface or transcript tail inspection. |
@@ -1397,6 +1462,7 @@ Agent definitions are not loaded into context by default. Management actions let
1397
1462
  | `timeoutMs` / `maxRuntimeMs` | number | 30 min foreground; none async | Optional run-level max runtime in milliseconds. Foreground uses 30 minutes only when neither the call nor selected agent provides a timeout. |
1398
1463
  | `turnBudget` | object | none | Optional assistant-turn budget `{ maxTurns, graceTurns }`. At `maxTurns` the child is warned to wrap up. After the grace window (default 1), termination occurs at the next assistant boundary; a response that starts tool work records `termination-deferred` until a later boundary. Partial output is returned on abort. |
1399
1464
  | `toolBudget` | object | none | Optional child tool-call budget `{ soft?, hard, block? }`. At `soft` the child is nudged to finalize. After `hard`, configured tools are blocked; `block` defaults to `read`, `grep`, `find`, and `ls`, while `"*"` blocks every tool call. Final assistant text is never blocked. |
1465
+ | `usageBudget` | object | none | Optional root-only reported-usage budget `{ tokens?: { soft?, hard }, costUsd?: { soft?, hard } }`. Soft limits are status-only. Hard limits prevent later child launches after reported usage is reconciled; already-running children are not stopped and no reservations are made. |
1400
1466
  | `cwd` | string | runtime cwd | Override working directory. |
1401
1467
  | `maxOutput` | object | 200KB, 5000 lines | Final output truncation limits. |
1402
1468
  | `artifacts` | boolean | true | Write debug artifacts. |
@@ -1407,7 +1473,9 @@ Agent definitions are not loaded into context by default. Management actions let
1407
1473
 
1408
1474
  `agentContract: { version: 1 }` keeps existing fields and artifacts but adds derived `execution`, `acceptance`, `review`, and `effects` projections. In v1, acceptance failures do not rewrite execution success, and an explicit completion guard reports `effects.fileMutation` instead of failing the run by itself. Chain steps default to advancing on execution under v1; set `gateOn: "acceptance"` on a v1 step or parallel task when rejected acceptance should stop the chain.
1409
1475
 
1410
- As a conservative orchestration policy, do not set `turnBudget` or a hard `toolBudget` on implementation workers, fix workers, reviewers with edit authority, or other mutation-capable children. A default tool budget blocks read/search tools rather than mutation tools, but neither assistant turns nor tool-call counts measure whether a delivery slice is buildable or safe to hand off. Hard count caps remain appropriate for explicitly read-only scouts, reviewers, and validators.
1476
+ Checkpoint steps use `{ checkpoint: "stable-name", message?: "..." }`. A checkpoint does not launch a child, consume spawn budget, or produce an output reference. Foreground chains return a paused result at the checkpoint so the current parent can explicitly choose the next action. Async chains persist `checkpoint` in status/details and pause before the next step; approve with `subagent({ action: "approve-checkpoint", id: "<run-id>" })` or reject with `subagent({ action: "reject-checkpoint", id: "<run-id>" })`. Approval resumes from that boundary without rerunning completed steps. Rejection is terminal with `state: "rejected"`.
1477
+
1478
+ As a conservative orchestration policy, do not set `turnBudget`, a hard `toolBudget`, or a tight `usageBudget` on implementation workers, fix workers, reviewers with edit authority, or other mutation-capable children. A default tool budget blocks read/search tools rather than mutation tools, and reported usage has no reservation model, so neither assistant turns, tool-call counts, nor token/cost totals measure whether a delivery slice is buildable or safe to hand off. Hard caps remain appropriate for explicitly read-only scouts, reviewers, and validators.
1411
1479
 
1412
1480
  Bound writer work with a narrow task and an outer `timeoutMs` or `maxRuntimeMs` that leaves enough margin for the slice. An elapsed timeout is not a mutation-safe boundary and may still signal a child during tool work. Before the deadline, use `steer` or an attention notice to request a checkpoint after the current tool returns, including changed files, build/test state, remaining work, and commit or PR state.
1413
1481
 
@@ -1434,6 +1502,8 @@ subagent({ action: "resume", id: "<nested-run-id>", message: "follow-up for a ne
1434
1502
  subagent({ action: "steer", id: "<run-id>", message: "guidance for the running child" })
1435
1503
  subagent({ action: "steer", id: "<run-id>", index: 1, message: "guidance for child 2" })
1436
1504
  subagent({ action: "append-step", id: "<run-id>", chain: [{ agent: "worker", task: "Continue from {previous}" }] })
1505
+ subagent({ action: "approve-checkpoint", id: "<run-id>" })
1506
+ subagent({ action: "reject-checkpoint", id: "<run-id>" })
1437
1507
  subagent({ action: "doctor" })
1438
1508
  ```
1439
1509
 
@@ -1445,7 +1515,7 @@ subagent({ action: "doctor" })
1445
1515
 
1446
1516
  `steer` waits up to three seconds for a correlated child-Pi input acceptance and returns a request id with `delivered`, `scheduled`, `pending`, `partial`, `recovered`, or `failed` plus per-child states. Delivery means Pi accepted the user message, not model compliance. A pending indexed child returns `scheduled`. Only a top-level single run may interrupt after the acknowledgment deadline and recover after a further 15-second pause/revival bound; chain, parallel, and nested runs never auto-interrupt. Recovery launches a replacement only after the source is confirmed paused, a valid persisted session exists, and deadline, turn, and tool budgets remain. It preserves the original child contract and remaining limits; otherwise the source stays paused with an explicit failure. Late acceptance is recorded but cannot cancel committed recovery. The persisted `steering` ledger retains 20 requests and replaces the old `steerCount`/`lastSteerAt` fields.
1447
1517
 
1448
- `append-step` accepts exactly one sequential, static parallel, or dynamic fanout chain step for a top-level async chain whose status is still `running`. The step is persisted in the run directory and becomes eligible only after the chain's already-queued steps finish; completed, failed, paused, foreground, single, and top-level parallel runs reject appends.
1518
+ `append-step` accepts exactly one sequential, checkpoint, static parallel, or dynamic fanout chain step for a top-level async chain whose status is still `running`. The step is persisted in the run directory and becomes eligible only after the chain's already-queued steps finish; completed, failed, rejected, paused, foreground, single, and top-level parallel runs reject appends.
1449
1519
 
1450
1520
  ## Worktree isolation
1451
1521
 
@@ -1475,6 +1545,8 @@ Requirements:
1475
1545
  - task-level `cwd` overrides must be omitted or match the shared cwd
1476
1546
  - configured `worktreeSetupHook` must return valid JSON before timeout
1477
1547
 
1548
+ Git worktrees start from tracked files, so ignored dependency state may be absent. `pi-subagents` attempts the `node_modules` symlink above, but if module resolution fails in a fresh worktree, first confirm dependencies were linked, installed, or provisioned by `worktreeSetupHook` before treating it as a code failure.
1549
+
1478
1550
  By default, worktrees are created under the system temp directory. Set `worktreeBaseDir` in config, or `PI_SUBAGENTS_WORKTREE_DIR` when config is unset, to put them under a stable trusted directory. Missing base directories are created automatically.
1479
1551
 
1480
1552
  After a worktree parallel step completes, per-agent diff stats are appended to the output and full patch files are written to artifacts. The runtime also writes a versioned aggregate handoff manifest: foreground runs use the artifact directory's `handoffs/<run-id>.json`, while async runs use `<async-dir>/handoff.json`. The manifest records each child's terminal status, summary, output/session/structured-output references, patch stats and path, and whether its worktree and temporary branch were actually removed. Foreground `details`, async `status.json` and result files, status output, intercom delivery, and completion notifications expose the manifest path. Worktrees and temp branches still receive best-effort fallback cleanup if handoff finalization cannot run.
package/agents/worker.md CHANGED
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: worker
3
3
  description: Implementation agent for normal tasks and approved oracle handoffs
4
+ aliases: developer, coder, implementer, develop
4
5
  thinking: high
5
6
  systemPromptMode: replace
6
7
  inheritProjectContext: true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-subagents",
3
- "version": "0.38.0",
3
+ "version": "0.40.0",
4
4
  "description": "Pi extension for delegating tasks to subagents with chains, parallel execution, and TUI clarification",
5
5
  "author": "Nico Bailon",
6
6
  "license": "MIT",
@@ -10,7 +10,7 @@ Default to a maximum of 3 review rounds unless I specify a different cap. Count
10
10
 
11
11
  If the invocation includes an implementation request, first launch one async `worker` to implement the approved scope. If the current diff is already the target, start with review. The sequence can be launched up front as an async/background chain when the workflow is already clear, or continued as 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 I explicitly want the foreground clarify UI. Use only one writer against the active worktree at a time unless I explicitly ask for isolated worktrees.
12
12
 
13
- As a conservative orchestration policy, do not set `turnBudget` or a hard `toolBudget` on implementation or fix workers. A default tool budget blocks read/search tools rather than mutation tools, but count limits still do not measure delivery safety. Give each writer a narrow delivery slice and an outer elapsed deadline with enough margin. Before that deadline, request a checkpoint after the current tool returns with 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 the checkpoint trigger.
13
+ As a conservative orchestration policy, do not set `turnBudget`, a hard `toolBudget`, or a tight `usageBudget` on implementation or fix workers. A default tool budget blocks read/search tools rather than mutation tools, and reported usage has no reservation model, so count or usage limits still do not measure delivery safety. Give each writer a narrow delivery slice and an outer elapsed deadline with enough margin. Before that deadline, request a checkpoint after the current tool returns with 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 the checkpoint trigger.
14
14
 
15
15
  For each review round, launch fresh-context `reviewer` agents in parallel. Reviewers must inspect the repository, relevant instructions, and current diff directly from files and commands. They must not rely on the main conversation history and must not edit files.
16
16
 
@@ -31,8 +31,9 @@ For broad or uncertain requests, read more than one reference. For complex work,
31
31
 
32
32
  - Keep the parent as orchestrator and final decision-maker.
33
33
  - Use one writer per cwd/worktree unless isolated worktrees are intentional.
34
+ - For parallel fanout, compare child prompts before launch. Do not send clone prompts with only issue numbers, titles, or broad file globs swapped; each child needs a lane-specific task, source seam, prior evidence, and decision that remains distinct without the item number.
34
35
  - Prefer fresh-context review/validation fanout, then synthesize and apply fixes in the parent.
35
- - Use async/background only when work can proceed independently; do not poll just to wait.
36
- - Preserve capability ceilings and child tool restrictions; role selection is not enforcement.
36
+ - Use async/background only when work can proceed independently; do not poll just to wait. For planned human gates in chains, use `{ checkpoint: "name", message?: "..." }` and approve or reject paused async checkpoints with `approve-checkpoint` / `reject-checkpoint`.
37
+ - Preserve capability ceilings, including child tool restrictions and session-scoped allowed-agent restrictions.
37
38
  - Escalate unresolved product, architecture, or safety decisions upward instead of letting a child decide silently.
38
- - As a conservative orchestration policy, do not pass `turnBudget` or a hard `toolBudget` to mutation-capable workers. The default tool budget blocks read/search tools rather than mutation tools. If a worker is interrupted after a tool call starts, checkpoint after the current tool returns with changed files, build/test state, and commit or PR state.
39
+ - As a conservative orchestration policy, do not pass `turnBudget`, a hard `toolBudget`, or a tight `usageBudget` to mutation-capable workers. The default tool budget blocks read/search tools rather than mutation tools, and reported usage has no reservation model. If a worker is interrupted after a tool call starts, checkpoint after the current tool returns with changed files, build/test state, and commit or PR state.
@@ -20,6 +20,8 @@ Precedence is by parsed runtime name:
20
20
  2. user scope
21
21
  3. builtin agents
22
22
 
23
+ Project settings resolve from the nearest parent directory containing `.pi` or `.agents` by default. In monorepos or git worktrees where an incidental nested `.pi` directory should not shadow the repository config, set `subagents.projectRootResolution: "git-root"` in the repository root `.pi/settings.json`; a nested project can opt back with `"nearest"` in its own settings.
24
+
23
25
  ## Running Subagents
24
26
 
25
27
  ### Single agent
@@ -149,17 +151,21 @@ const run = subagent({
149
151
  // Continue local inspection, then later call status with the returned id.
150
152
  ```
151
153
 
154
+ While children run, the persistent FleetView and the collapsed foreground tool-result card show live per-child detail: resolved model and thinking level, `[fresh]`/`[fork]` context, tool/token/elapsed counters, and current activity. The collapsed running card also prints the configured expand-key hint ("Press … for live detail"); expanding it shows nested children, recent tools, and recent output. Model badges appear once the child's model resolves at first attempt start. `/subagents-fleet` opens the live fleet inspector, which also has per-child controls (`s` steer, `D` stop with confirmation).
155
+
152
156
  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.
153
157
 
154
- Stop a current-session top-level async run with `stop` (or `/subagents-stop`). Stopped runs finish as `stopped`/cancelled and are not resumable. Append one more step to the tail of a still-running async chain with `append-step` (`chain` must contain exactly one step):
158
+ Stop a current-session top-level async run with `stop` (or `/subagents-stop`). Stopped runs finish as `stopped`/cancelled and are not resumable. For an active foreground single-subagent run, `/subagents-detach [run-id]` leaves the child running without terminating it and returns the eventual result through status/wait. Append one more step to the tail of a still-running async chain with `append-step` (`chain` must contain exactly one step). Use checkpoint steps for planned human gates; they pause without launching a child and are approved or rejected through current-session control actions:
155
159
 
156
160
  ```typescript
157
161
  subagent({ action: "stop", id: "run-id" })
158
162
  subagent({
159
163
  action: "append-step",
160
164
  id: "run-id",
161
- chain: [{ agent: "reviewer", task: "Re-check the worker diff after the fix pass. Do not modify files." }]
165
+ chain: [{ checkpoint: "review", message: "Approve the next implementation step?" }]
162
166
  })
167
+ subagent({ action: "approve-checkpoint", id: "run-id" })
168
+ subagent({ action: "reject-checkpoint", id: "run-id" })
163
169
  ```
164
170
 
165
171
  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:
@@ -214,7 +220,7 @@ Humans can use `/subagents-doctor` for the same read-only report. It checks runt
214
220
 
215
221
  ### Subagent control
216
222
 
217
- Subagent control is the runtime visibility and intervention layer for delegated runs. It is separate from lifecycle status. Lifecycle status says whether a child is `queued`, `running`, `paused`, `complete`, `stopped`, or `failed`. Activity reporting is factual: it tracks the last observed activity time and the current tool when known. It does not pretend to know that a child is truly stuck. Manual top-level async cancellation uses `stop` / `/subagents-stop`; a live async chain can gain one more tail step via `append-step`.
223
+ Subagent control is the runtime visibility and intervention layer for delegated runs. It is separate from lifecycle status. Lifecycle status says whether a child is `queued`, `running`, `paused`, `complete`, `stopped`, `failed`, or `rejected`. Activity reporting is factual: it tracks the last observed activity time and the current tool when known. It does not pretend to know that a child is truly stuck. Manual top-level async cancellation uses `stop` / `/subagents-stop`; a live async chain can gain one more tail step via `append-step`, and a paused async chain checkpoint can be decided with `approve-checkpoint` or `reject-checkpoint`.
218
224
 
219
225
  Default behavior is intentionally conservative. When no activity has been observed past the configured threshold, the run emits a `needs_attention` control event. Foreground runs can push this as a `subagent:control-event` event, and async runs persist it to `events.jsonl` so the parent tracker can surface it without constant manual polling. Notification-worthy control events are also inserted into the visible transcript so both the user and the parent agent can see them, with a proactive hint plus concrete `nudge`, `status`, and `interrupt` options. Visible notifications fire once per child run and attention state.
220
226
 
@@ -268,6 +274,11 @@ generated `.pi-subagents/` / temp artifacts do not trigger review. Writing child
268
274
  can review their own worktree; the parent can still review the aggregate diff after
269
275
  child changes land. Enabled watchdogs also run changed-file TypeScript/JavaScript
270
276
  LSP diagnostics before the model pass when `typescript-language-server` is available.
277
+ They keep bounded current-scope context from real user prompts (`watchdog.scope.enabled`)
278
+ and can optionally run non-blocking Scopey-style cadence reviews every N tool results
279
+ (`watchdog.cadence.everyNTools`). Cadence corrections and blocker auto-follow prompts
280
+ are always transcript-visible; choose the watchdog model that matches the desired
281
+ cheap-monitor vs strong-reviewer policy.
271
282
 
272
283
  Prefer a strong complementary model (for example Opus 4.8 high paired against a
273
284
  GPT 5.5 main session, or the reverse). Recommendation and configuration:
@@ -331,6 +342,14 @@ patch paths and stats, and whether each temporary worktree and branch was
331
342
  removed. If you want one writer thread and several advisory agents, prefer a
332
343
  single-writer pattern instead.
333
344
 
345
+ Git worktrees start from tracked files, so ignored or untracked build state
346
+ such as `node_modules` may be absent. `pi-subagents` attempts to symlink the
347
+ root checkout's `node_modules` into each managed worktree when it exists, but
348
+ agents should still treat dependency setup as an explicit bootstrap step before
349
+ running tests, typecheck, or builds. If module resolution fails in a fresh
350
+ worktree, first confirm dependencies were linked, installed, or provisioned by
351
+ `worktreeSetupHook` before treating it as a code failure.
352
+
334
353
  ## The Oracle Workflow
335
354
 
336
355
  The intended oracle loop is:
@@ -78,6 +78,7 @@ A minimal agent file looks like this:
78
78
  name: my-agent
79
79
  package: code-analysis
80
80
  description: What this agent does
81
+ aliases: developer, coder
81
82
  model: openai-codex/gpt-5.4
82
83
  thinking: high
83
84
  tools: read, grep, find, ls, bash
@@ -95,6 +96,7 @@ That is only a starting point. Omit `package` for the traditional unqualified ru
95
96
  - `defaultProgress`
96
97
  - `defaultReads`
97
98
  - `output`
99
+ - `aliases`
98
100
  - `fallbackModels`
99
101
  - `subagentOnlyExtensions`
100
102
  - `skills`
@@ -107,6 +109,8 @@ That is only a starting point. Omit `package` for the traditional unqualified ru
107
109
  - `timeoutMs` — single-agent default run-level max runtime in ms; foreground calls use a 30-minute package default only when neither the call nor agent provides one (tool alias `maxRuntimeMs` is also accepted)
108
110
  - `turnBudget` — single-agent default `{ maxTurns, graceTurns? }` JSON object
109
111
 
112
+ `aliases` is an optional comma-separated or block-list set of alternate names for selecting an agent. Aliases resolve to the canonical `name` for execution, status, persistence, and config. Exact canonical names take precedence over aliases, and alias collisions between distinct canonical agents fail as ambiguous. Management create/update accepts a comma-separated string, string array, or `false`/empty string to clear aliases.
113
+
110
114
  `acceptance` is a single-agent launch default. Use a scalar level such as `checked` or an inline/block YAML map such as `{ level: "none", reason: "lightweight lookup" }`. An explicit tool-call value wins; chain and parallel acceptance remains configured on the task or step. Management create/update accepts the same policy object, and `acceptance: ""` clears the frontmatter default (`false` remains the deprecated disabled-policy shorthand).
111
115
 
112
116
  `acceptanceRole` is `read-only` or `writer` and controls automatic acceptance inference only. Explicit task mutation or no-edit intent wins; otherwise the role replaces agent-name guessing. Omission preserves the current name heuristics. The field does not grant or revoke tools. Management accepts `false` or an empty string to clear it.
@@ -137,4 +141,4 @@ Additional user prompt templates can delegate into `pi-subagents` through the na
137
141
 
138
142
  Other Pi extensions can call `pi-subagents` through the in-process event bus. The stable v1 channels are `subagents:rpc:v1:ready`, `subagents:rpc:v1:request`, and per-request replies at `subagents:rpc:v1:reply:<requestId>`. Envelopes use `{ version: 1, requestId, method, params }`, and replies use `{ version: 1, requestId, success, data | error }`. `ping` advertises the exact process-local async completion event as `events.asyncComplete` for RPC-spawn consumers.
139
143
 
140
- Methods: `ping`, `status`, `spawn`, `steer`, `interrupt`, `resume`, and `stop`. `spawn` is async-only and rejects management actions, `async: false`, or `clarify: true`; it reuses the normal executor, so discovery, validation, session attribution, configured spawn caps, child-safety depth, artifacts, and async status are shared with the `subagent` tool. `status`, acknowledged async `steer`, and `interrupt` map to the normal control actions. RPC steer disables pause-and-revive recovery and advertises `capabilities.nonRecoveringSteer`, preserving the caller's authority over the exact spawned child. `resume` requires a target plus non-empty message and delegates to the package-owned revival path; it may set a caller-owned `file-only` output path but cannot override the persisted child model, tools, budgets, session ownership, or exclusive session lease. `stop` targets running async runs through the existing timeout control channel. `pi.events` is process-local, so separate Pi processes and child subagents need lifecycle artifact files or `pi-intercom` instead.
144
+ Methods: `ping`, `status`, `spawn`, `steer`, `interrupt`, `resume`, and `stop`. `ping` capability metadata advertises optional projections: `capabilities.fleetStatus: { version: 1 }` adds bounded current-session `data.fleet` records (opaque reconciliation `key`, resolved `agent`, optional `role`, `model`, `effort`, caller-facing `goal`, `startedAt`, split `{ input, output, total }` tokens, plus `totalActive`/`omitted` overflow counts) to successful `status` replies; `capabilities.launchResolvedExtensions` advertises parent-resolved opaque launch-extension identifiers in status details; `capabilities.runtimeAcknowledgedExtensions` advertises the best-effort child-runtime acknowledgement projection fed by cooperating extensions emitting `subagent:acknowledge-extension`. Foreground `details.results[]` rows carry a stable numeric `index`; correlate children by `(runId, index)` rather than row position. Consumers should read status/result artifacts and RPC projections instead of scraping terminal output and must ignore unknown fields. `spawn` is async-only and rejects management actions, `async: false`, or `clarify: true`; it reuses the normal executor, so discovery, validation, session attribution, configured spawn caps, child-safety depth, artifacts, and async status are shared with the `subagent` tool. `status`, acknowledged async `steer`, and `interrupt` map to the normal control actions. RPC steer disables pause-and-revive recovery and advertises `capabilities.nonRecoveringSteer`, preserving the caller's authority over the exact spawned child. `resume` requires a target plus non-empty message and delegates to the package-owned revival path; it may set a caller-owned `file-only` output path but cannot override the persisted child model, tools, budgets, session ownership, or exclusive session lease. `stop` targets running async runs through the existing timeout control channel. `pi.events` is process-local, so separate Pi processes and child subagents need lifecycle artifact files or `pi-intercom` instead.
@@ -4,7 +4,7 @@ This file is a detailed reference loaded from `skills/pi-subagents/SKILL.md`.
4
4
 
5
5
  ## Capability ceilings
6
6
 
7
- Parent extensions may register a session-scoped, out-of-band ceiling through `pi-subagents/capability-ceiling`. Child tools are intersected with every active registration and inherited snapshot; `denyExtensions` removes ambient/provider extension loading while retaining package protocol runtime. Do not add a model-visible ceiling field or rely on role selection for enforcement. Restricted schedules are rejected until their ceiling can be persisted safely.
7
+ Parent extensions may register a session-scoped, out-of-band ceiling through `pi-subagents/capability-ceiling`. Child tools and eligible canonical agent names are intersected with every active registration and inherited snapshot; `denyExtensions` removes ambient/provider extension loading while retaining package protocol runtime. `{ action: "list" }` marks non-allowlisted agents as restricted, and launch rejects them before spawn. Do not add a model-visible ceiling field or rely on unrestricted role selection for enforcement. Restricted schedules are rejected until their ceiling can be persisted safely.
8
8
 
9
9
  ## When to Use
10
10
 
@@ -29,8 +29,9 @@ Humans often use the slash-command layer instead:
29
29
  - `/run-chain` — launch a saved `.chain.md` or `.chain.json` workflow
30
30
  - `/subagents` — interactive admin for inspecting agents and editing model, thinking, or system prompt
31
31
  - `/subagents-stop [run-id]` — stop a current-session top-level async run; opens a selector when no id is given
32
+ - `/subagents-detach [run-id]` — detach an active foreground single-subagent run without terminating its child
32
33
  - `/subagent-cost` — show parent plus child token usage and cost for the session
33
- - `/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
34
+ - `/subagents-fleet` — open the live fleet inspector with per-child controls; `Ctrl+Alt+F` opens it during an active foreground turn, `↑↓`/`jk` selects children, `PgUp`/`PgDn` scrolls transcript detail, `s` steers the selected live async child, and `D` stops its top-level async run after confirmation
34
35
  - `/subagents-watchdog` — inspect or configure the opt-in adversarial change watchdog (model, on/off, recommend-model, check)
35
36
  - `/subagents-doctor` — diagnose setup, discovery, async paths, and intercom bridge state
36
37
  - `/subagents-models [agent]` — show the live runtime-loaded builtin model mapping
@@ -252,12 +253,25 @@ Direct settings example:
252
253
  }
253
254
  ```
254
255
 
255
- Useful override fields: `model`, `fallbackModels`, `thinking`,
256
+ Useful override fields: `description`, `model`, `fallbackModels`, `thinking`,
256
257
  `systemPromptMode`, `inheritProjectContext`, `inheritSkills`, `defaultContext`,
257
258
  `acceptanceRole`, `disabled`, `skills`, `tools`, `extensions`, and `systemPrompt`.
259
+ `description` replaces the discovered description for builtin and custom agents
260
+ in `list` output, which is useful for deployment-specific routing notes.
258
261
  Use `acceptanceRole: false` to clear an override. Create a user or project
259
262
  agent with the same name only when you want a substantially different agent.
260
263
 
264
+ ### Recommended model tiering (optional)
265
+
266
+ When several providers are available, route agents by task shape instead of one model for everything:
267
+
268
+ 1. **Fast workhorse** — cheapest capable model at low thinking for recon, lookups, and mechanical edits (for example on `scout`).
269
+ 2. **Standard well-scoped** — mid-tier model at medium thinking for most delegations: routine multi-file edits, focused reviews, straightforward implementation (for example on `worker`, `reviewer`, `delegate`).
270
+ 3. **Deep but bounded** — top reasoning model at high thinking only for hard tasks that arrive with explicit goals and completion criteria; these models loop on vague goals (for example on `planner` and oracle-style agents).
271
+ 4. **Taste and intent** — a model that reads human intent well for ambiguous work: UX/design judgment, product tradeoffs, planning from vague requirements, writing quality.
272
+
273
+ Routing rule: use tiers 1–3 when the task is well-scoped; use tier 4 when scoping or judging is the task itself. Give tier-4 agents cross-provider `fallbackModels` so subscription usage limits degrade gracefully; fallback triggers automatically on rate-limit and overload errors. Note that forked context over an Anthropic parent transcript with signed thinking blocks forces the child's thinking off, so intent-tier agents work best with fresh context.
274
+
261
275
  If a provider rejects model IDs with thinking suffixes, use
262
276
  `subagents.disableThinking: true` in user or project settings to clear bundled
263
277
  builtin thinking defaults globally. A higher-precedence per-agent `thinking`