pi-subagents 0.37.2 → 0.39.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 (64) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/LICENSE +21 -0
  3. package/README.md +73 -15
  4. package/agents/worker.md +1 -0
  5. package/package.json +1 -1
  6. package/prompts/review-loop.md +1 -1
  7. package/skills/pi-subagents/SKILL.md +4 -3
  8. package/skills/pi-subagents/references/execution-controls.md +18 -3
  9. package/skills/pi-subagents/references/management-authoring-rpc.md +4 -0
  10. package/skills/pi-subagents/references/prompting-and-roles.md +2 -1
  11. package/src/agents/agent-management.ts +71 -30
  12. package/src/agents/agent-serializer.ts +4 -0
  13. package/src/agents/agents.ts +96 -8
  14. package/src/api/preflight.ts +16 -12
  15. package/src/extension/chain-validation.ts +17 -1
  16. package/src/extension/index.ts +3 -0
  17. package/src/extension/rpc.ts +223 -4
  18. package/src/extension/schemas.ts +29 -4
  19. package/src/extension/tool-description.ts +6 -5
  20. package/src/intercom/intercom-bridge.ts +4 -2
  21. package/src/intercom/result-intercom.ts +9 -2
  22. package/src/runs/background/async-execution.ts +63 -16
  23. package/src/runs/background/async-job-tracker.ts +5 -1
  24. package/src/runs/background/async-resume.ts +1 -0
  25. package/src/runs/background/async-status.ts +18 -2
  26. package/src/runs/background/chain-append.ts +48 -5
  27. package/src/runs/background/control-channel.ts +68 -1
  28. package/src/runs/background/notify.ts +26 -4
  29. package/src/runs/background/result-watcher.ts +13 -1
  30. package/src/runs/background/run-status.ts +29 -3
  31. package/src/runs/background/subagent-runner.ts +356 -28
  32. package/src/runs/foreground/async-stop-action.ts +65 -0
  33. package/src/runs/foreground/chain-clarify.ts +3 -3
  34. package/src/runs/foreground/chain-execution.ts +143 -43
  35. package/src/runs/foreground/execution.ts +524 -247
  36. package/src/runs/foreground/foreground-control.ts +42 -0
  37. package/src/runs/foreground/subagent-executor.ts +312 -77
  38. package/src/runs/shared/acceptance.ts +15 -7
  39. package/src/runs/shared/capability-ceiling.ts +51 -19
  40. package/src/runs/shared/chain-outputs.ts +3 -1
  41. package/src/runs/shared/dynamic-fanout.ts +1 -1
  42. package/src/runs/shared/nested-events.ts +97 -20
  43. package/src/runs/shared/parallel-utils.ts +43 -12
  44. package/src/runs/shared/pi-args.ts +49 -3
  45. package/src/runs/shared/process-signal.ts +19 -0
  46. package/src/runs/shared/run-history.ts +45 -9
  47. package/src/runs/shared/runtime-acknowledged-extensions.ts +71 -0
  48. package/src/runs/shared/subagent-prompt-runtime.ts +30 -0
  49. package/src/runs/shared/subagent-startup-retry.ts +101 -0
  50. package/src/runs/shared/usage-budget.ts +65 -0
  51. package/src/runs/shared/workflow-graph.ts +26 -1
  52. package/src/shared/settings.ts +17 -1
  53. package/src/shared/types.ts +133 -8
  54. package/src/shared/utils.ts +55 -1
  55. package/src/slash/slash-commands.ts +45 -3
  56. package/src/slash/slash-live-state.ts +5 -3
  57. package/src/tui/fleet-status.ts +25 -8
  58. package/src/tui/fleet.ts +181 -8
  59. package/src/watchdog/register-main.ts +14 -7
  60. package/src/watchdog/review.ts +4 -3
  61. package/src/watchdog/runtime.ts +170 -17
  62. package/src/watchdog/scope.ts +62 -0
  63. package/src/watchdog/settings.ts +41 -1
  64. package/src/watchdog/types.ts +10 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,49 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.39.0] - 2026-08-01
6
+
7
+ ### Added
8
+ - Added session-scoped `allowedAgents` capability ceilings for restricting launchable agent roles without global agent disabling. Thanks to @aoguai for #719.
9
+ - Added stable foreground result row indexes for correlating child progress and final results. Thanks to @rochecompaan (Patchmill) for #720.
10
+ - 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).
11
+ - Added optional `runtimeAcknowledgedExtensions` status/result/RPC metadata for cooperating child-runtime extensions that emit `subagent:acknowledge-extension`. Thanks to @saleemlala for #705.
12
+ - Added `/subagents-detach` for detaching the active foreground single-subagent run without terminating the child. Thanks to @magoz for #708/#711.
13
+ - 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.
14
+ - 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.
15
+ - 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.
16
+ - Added optional `launchResolvedExtensions` status/result/RPC metadata with opaque launch-resolved child extension identifiers and ambient-extension state. Thanks to @saleemlala for #691.
17
+ - 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.
18
+
19
+ ### Changed
20
+ - 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.
21
+
22
+ ### Fixed
23
+ - Show per-child async task descriptions in the persistent running-subagents status widget instead of repeating the run-level description for every parallel child.
24
+ - Restored model and thinking-effort badges in the persistent running-subagents status widget.
25
+ - 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.
26
+ - Render resolved model and thinking effort for active and recent foreground children in Fleet inspector summaries and details. Thanks to @saleemlala for #706.
27
+ - 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.
28
+ - 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.
29
+
30
+ ## [0.38.0] - 2026-07-30
31
+
32
+ ### Added
33
+ - Added `j`/`k` navigation aliases to the non-filterable `/subagents-stop` selector and clarify step list while preserving text input in editor and search modes. Thanks to @magoz for #686.
34
+ - Added the optional versioned `fleetStatus` RPC capability with bounded, current-session child roles, goals, model/effort, split token usage, elapsed timestamps, stable opaque reconciliation keys, and explicit overflow counts. Thanks to @neumie for #682.
35
+
36
+ ### Fixed
37
+ - Enabled the advertised `j`/`k` navigation aliases after activating the persistent FleetView while leaving printable editor input untouched before activation. Thanks to @magoz for #685.
38
+ - Added opt-in `subagents.projectRootResolution: "git-root"` so monorepos and git worktrees can keep the default nearest-root behavior unless they choose to resolve project packages and `agentOverrides` from the git root. Thanks to @klajdo-f for #677.
39
+ - Recognized structurally compatible custom editors in FleetView focus detection, restoring FleetView arrow-key activation and navigation when a custom editor has focus. Thanks to @magoz for #679.
40
+ - Scoped foreground fleet records to their originating parent session and propagated resolved model, thinking effort, and split input/output usage through live foreground controls.
41
+ - Matched fleet RPC filtering to the canonical session-file identity used by live async and foreground state.
42
+ - Kept pi-intercom stable IDs from leaking into child sessions and used the current intercom runtime ID for unnamed supervisor targets.
43
+ - Improved acceptance policy validation errors and tool-schema guidance for invalid evidence kinds. Thanks to @atimofeev for #672.
44
+ - Tolerated temporary steering inbox scan failures so pending steer requests can be retried on the next poll. Thanks to @hughcars for #670.
45
+ - Retried short, zero-activity child startup exits on the same model with bounded backoff, reducing concurrent subagent launch races without replaying model or tool work. Thanks to @felipeteodorocw for #671.
46
+ - Bounded streamed subagent progress snapshots so a long or deeply nested fan-out no longer emits a `tool_execution_update` line above the child-stdout protocol cap and gets the child killed with `protocol_output_limit`. Streamed `onUpdate` snapshots now carry compact tool-call summaries instead of the full message transcript, cap `recentTools`, and truncate `recentOutput` line length; the returned result and detached-exit recovery keep the full transcript. Thanks to @shaharmor for #680/#681.
47
+
5
48
  ## [0.37.2] - 2026-07-28
6
49
 
7
50
  ### Changed
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nico Bailon
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -157,6 +157,18 @@ For a persistent override, edit settings. This example pins the reviewer everywh
157
157
 
158
158
  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
159
 
160
+ 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`:
161
+
162
+ ```json
163
+ {
164
+ "subagents": {
165
+ "projectRootResolution": "git-root"
166
+ }
167
+ }
168
+ ```
169
+
170
+ `"git-root"` keeps package discovery, project agents, chains, and `agentOverrides` anchored to the git worktree root when that root also has Pi project config. A nested project can still opt back into nearest-root behavior by setting `"projectRootResolution": "nearest"` in its own `.pi/settings.json`.
171
+
160
172
  Set `subagents.defaultThinking` to give builtin, package, user, and project agents without a `thinking` value a shared thinking level, independent of the parent session's default. Project settings win over user settings. Explicit frontmatter, `agentOverrides.<name>.thinking`, and per-run thinking overrides still win; `thinking: false` remains an explicit opt-out:
161
173
 
162
174
  ```json
@@ -206,6 +218,12 @@ The subagent watchdog is not the `reviewer` subagent. `subagents.defaultModel` a
206
218
 
207
219
  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.
208
220
 
221
+ 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.
222
+
223
+ 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.
224
+
225
+ 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`.
226
+
209
227
  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`.
210
228
 
211
229
  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.
@@ -229,6 +247,8 @@ You can also set the model explicitly:
229
247
 
230
248
  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.
231
249
 
250
+ Default strong-reviewer profile:
251
+
232
252
  ```json
233
253
  {
234
254
  "subagents": {
@@ -243,6 +263,29 @@ For settings files, use `subagents.watchdog.main.model` and `subagents.watchdog.
243
263
  }
244
264
  ```
245
265
 
266
+ Scopey-style scope monitoring profile:
267
+
268
+ ```json
269
+ {
270
+ "subagents": {
271
+ "watchdog": {
272
+ "enabled": true,
273
+ "main": {
274
+ "model": "anthropic/claude-haiku-4-5",
275
+ "thinking": "medium"
276
+ },
277
+ "scope": { "enabled": true },
278
+ "cadence": { "everyNTools": 10 },
279
+ "autoFollow": {
280
+ "blockers": true,
281
+ "maxAttempts": 3,
282
+ "stalemateRepeats": 3
283
+ }
284
+ }
285
+ }
286
+ }
287
+ ```
288
+
246
289
  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.
247
290
 
248
291
  Agents can configure the same values through the tool when you ask them to set up the watchdog:
@@ -274,9 +317,9 @@ To keep subagents inside a budget or compliance profile, enforce a model scope.
274
317
 
275
318
  Foreground runs stream progress in the conversation while they run. They default to a generous 30-minute wall-clock timeout when neither the call nor the selected agent provides a timeout; explicit `timeoutMs`/`maxRuntimeMs` and agent defaults win.
276
319
 
277
- 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, use `↑`/`↓` or `j`/`k` to select a child and `Enter` to inspect it; normal editor input is never intercepted.
320
+ 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.
278
321
 
279
- `/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.
322
+ `/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. 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.
280
323
 
281
324
  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.
282
325
 
@@ -292,9 +335,9 @@ Async runs also write machine-readable lifecycle artifacts for observability and
292
335
 
293
336
  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.
294
337
 
295
- 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.
338
+ 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.
296
339
 
297
- 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.
340
+ 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.
298
341
 
299
342
  ```typescript
300
343
  const requestId = crypto.randomUUID();
@@ -310,7 +353,7 @@ pi.events.emit("subagents:rpc:v1:request", {
310
353
  });
311
354
  ```
312
355
 
313
- The v1 methods are `ping`, `status`, `spawn`, `steer`, `interrupt`, `stop`, and `resume`. `status`, `steer`, `interrupt`, and `resume` reuse the normal package-owned actions. `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.
356
+ 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.
314
357
 
315
358
  `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.
316
359
 
@@ -475,6 +518,7 @@ Skip this section until you want exact syntax.
475
518
  | `/subagent-cost` | Show parent plus child subagent token usage and cost for this session |
476
519
  | `/subagents [agent] [model\|thinking\|prompt\|details]` | Interactively inspect or edit an agent's model, thinking level, or system prompt |
477
520
  | `/subagents-doctor` | Show read-only setup diagnostics |
521
+ | `/subagents-detach [run-id]` | Detach an active foreground single-subagent run without terminating its child |
478
522
  | `/subagents-models [agent]` | Show the runtime-loaded builtin model mapping, optionally filtered to one builtin |
479
523
  | `/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 |
480
524
  | `/subagents-profiles` | List saved subagent profiles from `~/.pi/agent/profiles/pi-subagents/` |
@@ -644,7 +688,7 @@ Common clarify keys:
644
688
 
645
689
  - `Enter` runs in the foreground, or in the background if background is toggled on
646
690
  - `Esc` cancels or backs out
647
- - `↑↓` moves between steps or tasks
691
+ - `↑↓` or `j`/`k` moves between steps or tasks
648
692
  - `e` edits the task/template
649
693
  - `m` selects a model
650
694
  - `t` selects thinking level
@@ -732,6 +776,7 @@ name: scout
732
776
  # Optional: registers this as code-analysis.scout while preserving name: scout
733
777
  package: code-analysis
734
778
  description: Fast codebase recon
779
+ aliases: explorer, code-scout
735
780
  tools: read, grep, find, ls, bash, mcp:chrome-devtools
736
781
  extensions:
737
782
  subagentOnlyExtensions: ./tools/child-only-search.ts
@@ -775,6 +820,7 @@ Important fields:
775
820
  | Field | Notes |
776
821
  |-------|-------|
777
822
  | `package` | Optional package identifier. A file with `name: scout` and `package: code-analysis` registers as `code-analysis.scout`; serialization keeps `name` and `package` separate. |
823
+ | `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. |
778
824
  | `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. |
779
825
  | `extensions` | Omitted means normal extensions; empty means no extensions; list values allowlist specific extensions. |
780
826
  | `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. |
@@ -1176,13 +1222,17 @@ import { registerSubagentCapabilityCeiling } from "pi-subagents/capability-ceili
1176
1222
  const restriction = registerSubagentCapabilityCeiling({
1177
1223
  sessionId: ctx.sessionManager.getSessionId(),
1178
1224
  source: "plan-mode",
1179
- ceiling: { allowedTools: ["read", "grep", "find", "ls"], denyExtensions: true },
1225
+ ceiling: {
1226
+ allowedAgents: ["plan-scout", "plan-researcher", "plan-reviewer"],
1227
+ allowedTools: ["read", "grep", "find", "ls"],
1228
+ denyExtensions: true,
1229
+ },
1180
1230
  });
1181
1231
  // restriction.update(...) replaces this provider's policy atomically.
1182
1232
  // restriction.dispose() removes only this provider's registration.
1183
1233
  ```
1184
1234
 
1185
- 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.
1235
+ 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.
1186
1236
 
1187
1237
  `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.
1188
1238
 
@@ -1234,6 +1284,7 @@ These are the parameters the LLM passes when it calls the `subagent` tool. Most
1234
1284
  { chain: [
1235
1285
  { agent: "scout", task: "Gather context for auth refactor" },
1236
1286
  { agent: "planner" },
1287
+ { checkpoint: "implementation", message: "Approve implementation before review?" },
1237
1288
  { agent: "worker" },
1238
1289
  { agent: "reviewer" }
1239
1290
  ]}
@@ -1352,7 +1403,7 @@ Agent definitions are not loaded into context by default. Management actions let
1352
1403
  { action: "reset", agent: "reviewer" }
1353
1404
  ```
1354
1405
 
1355
- `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 `""`.
1406
+ `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 `""`.
1356
1407
 
1357
1408
  `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.
1358
1409
 
@@ -1360,9 +1411,9 @@ Agent definitions are not loaded into context by default. Management actions let
1360
1411
 
1361
1412
  | Param | Type | Default | Description |
1362
1413
  |-------|------|---------|-------------|
1363
- | `agent` | string | - | Agent name for single mode, or target for management actions. |
1414
+ | `agent` | string | - | Agent name or alias for single mode, or target for management actions. Execution records use the canonical agent name. |
1364
1415
  | `task` | string | - | Task string for single mode. |
1365
- | `action` | string | - | `list`, `get`, `create`, `update`, `delete`, `status`, `interrupt`, `stop`, `resume`, `steer`, `append-step`, or `doctor`. |
1416
+ | `action` | string | - | `list`, `get`, `create`, `update`, `delete`, `status`, `interrupt`, `stop`, `resume`, `steer`, `append-step`, `approve-checkpoint`, `reject-checkpoint`, or `doctor`. |
1366
1417
  | `chainName` | string | - | Chain name for management actions. |
1367
1418
  | `config` | object/string | - | Agent or chain config for create/update. |
1368
1419
  | `output` | `string \| false` | agent default | Override single-agent output file. |
@@ -1374,7 +1425,7 @@ Agent definitions are not loaded into context by default. Management actions let
1374
1425
  | `tasks` | array | - | Top-level parallel tasks. Supports `agent`, `task`, `cwd`, `count`, `output`, `outputMode`, `outputSchema`, `reads`, `progress`, `skill`, `model`, `toolBudget`, `acceptance`, and `agentContract`. |
1375
1426
  | `concurrency` | number | config or `4` | Top-level parallel concurrency. |
1376
1427
  | `worktree` | boolean | false | Create isolated git worktrees for parallel tasks. |
1377
- | `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. |
1428
+ | `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. |
1378
1429
  | `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`. |
1379
1430
  | `chainDir` | string | temp chain dir | Persistent directory for chain artifacts. Relative chain `output`, `reads`, and `progress` paths live under this directory. |
1380
1431
  | `view` | `fleet \| transcript` | - | Optional `status` view for the active fleet surface or transcript tail inspection. |
@@ -1385,6 +1436,7 @@ Agent definitions are not loaded into context by default. Management actions let
1385
1436
  | `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. |
1386
1437
  | `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. |
1387
1438
  | `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. |
1439
+ | `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. |
1388
1440
  | `cwd` | string | runtime cwd | Override working directory. |
1389
1441
  | `maxOutput` | object | 200KB, 5000 lines | Final output truncation limits. |
1390
1442
  | `artifacts` | boolean | true | Write debug artifacts. |
@@ -1395,7 +1447,9 @@ Agent definitions are not loaded into context by default. Management actions let
1395
1447
 
1396
1448
  `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.
1397
1449
 
1398
- 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.
1450
+ 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"`.
1451
+
1452
+ 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.
1399
1453
 
1400
1454
  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.
1401
1455
 
@@ -1422,6 +1476,8 @@ subagent({ action: "resume", id: "<nested-run-id>", message: "follow-up for a ne
1422
1476
  subagent({ action: "steer", id: "<run-id>", message: "guidance for the running child" })
1423
1477
  subagent({ action: "steer", id: "<run-id>", index: 1, message: "guidance for child 2" })
1424
1478
  subagent({ action: "append-step", id: "<run-id>", chain: [{ agent: "worker", task: "Continue from {previous}" }] })
1479
+ subagent({ action: "approve-checkpoint", id: "<run-id>" })
1480
+ subagent({ action: "reject-checkpoint", id: "<run-id>" })
1425
1481
  subagent({ action: "doctor" })
1426
1482
  ```
1427
1483
 
@@ -1429,11 +1485,11 @@ subagent({ action: "doctor" })
1429
1485
 
1430
1486
  `resume` revives a paused, completed, or failed async/foreground child by starting a new child from its stored session file; stopped runs remain non-resumable, and it does not interrupt a live top-level async child. Use `steer` for acknowledged live async guidance. Multi-child async runs and remembered foreground single, parallel, or chain runs can be revived by passing `index` to choose the child. Nested runs can be resumed by nested id when their live route or persisted nested session metadata is available. Revive starts a new child process from the old session context; it does not restart the same OS process, and it requires the chosen child to have a persisted `.jsonl` session file. Direct revival takes an exclusive cross-process lease on the canonical session file until the new child finishes. A concurrent attempt fails before Pi is spawned and identifies the owning revived run; dead-owner leases are reclaimed only when staleness can be proved.
1431
1487
 
1432
- `stop` ends a current-session top-level async run. It is deliberately stronger than `interrupt`: it is not a resumable pause, stopped runs should be restarted as new runs, foreground and nested targets are rejected, direct id calls execute immediately, and `/subagents-stop` without an id opens a selector with confirmation when a TUI is available. In non-TUI contexts the slash command prints exact `subagent({ action: "stop", id })` and `/subagents-stop <id>` commands. Scheduled jobs can appear in the selector, but they are labeled as scheduled cancellations and route through `schedule-cancel`, not `stop`.
1488
+ `stop` ends a current-session top-level async run. It is deliberately stronger than `interrupt`: it is not a resumable pause, stopped runs should be restarted as new runs, foreground and nested targets are rejected, direct id calls execute immediately, and `/subagents-stop` without an id opens a selector with confirmation when a TUI is available. Use `↑`/`↓` or `j`/`k` to move through that selector. In non-TUI contexts the slash command prints exact `subagent({ action: "stop", id })` and `/subagents-stop <id>` commands. Scheduled jobs can appear in the selector, but they are labeled as scheduled cancellations and route through `schedule-cancel`, not `stop`.
1433
1489
 
1434
1490
  `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.
1435
1491
 
1436
- `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.
1492
+ `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.
1437
1493
 
1438
1494
  ## Worktree isolation
1439
1495
 
@@ -1463,6 +1519,8 @@ Requirements:
1463
1519
  - task-level `cwd` overrides must be omitted or match the shared cwd
1464
1520
  - configured `worktreeSetupHook` must return valid JSON before timeout
1465
1521
 
1522
+ 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.
1523
+
1466
1524
  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.
1467
1525
 
1468
1526
  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.37.2",
3
+ "version": "0.39.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.
@@ -151,15 +151,17 @@ const run = subagent({
151
151
 
152
152
  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
153
 
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):
154
+ 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
155
 
156
156
  ```typescript
157
157
  subagent({ action: "stop", id: "run-id" })
158
158
  subagent({
159
159
  action: "append-step",
160
160
  id: "run-id",
161
- chain: [{ agent: "reviewer", task: "Re-check the worker diff after the fix pass. Do not modify files." }]
161
+ chain: [{ checkpoint: "review", message: "Approve the next implementation step?" }]
162
162
  })
163
+ subagent({ action: "approve-checkpoint", id: "run-id" })
164
+ subagent({ action: "reject-checkpoint", id: "run-id" })
163
165
  ```
164
166
 
165
167
  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 +216,7 @@ Humans can use `/subagents-doctor` for the same read-only report. It checks runt
214
216
 
215
217
  ### Subagent control
216
218
 
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`.
219
+ 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
220
 
219
221
  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
222
 
@@ -268,6 +270,11 @@ generated `.pi-subagents/` / temp artifacts do not trigger review. Writing child
268
270
  can review their own worktree; the parent can still review the aggregate diff after
269
271
  child changes land. Enabled watchdogs also run changed-file TypeScript/JavaScript
270
272
  LSP diagnostics before the model pass when `typescript-language-server` is available.
273
+ They keep bounded current-scope context from real user prompts (`watchdog.scope.enabled`)
274
+ and can optionally run non-blocking Scopey-style cadence reviews every N tool results
275
+ (`watchdog.cadence.everyNTools`). Cadence corrections and blocker auto-follow prompts
276
+ are always transcript-visible; choose the watchdog model that matches the desired
277
+ cheap-monitor vs strong-reviewer policy.
271
278
 
272
279
  Prefer a strong complementary model (for example Opus 4.8 high paired against a
273
280
  GPT 5.5 main session, or the reverse). Recommendation and configuration:
@@ -331,6 +338,14 @@ patch paths and stats, and whether each temporary worktree and branch was
331
338
  removed. If you want one writer thread and several advisory agents, prefer a
332
339
  single-writer pattern instead.
333
340
 
341
+ Git worktrees start from tracked files, so ignored or untracked build state
342
+ such as `node_modules` may be absent. `pi-subagents` attempts to symlink the
343
+ root checkout's `node_modules` into each managed worktree when it exists, but
344
+ agents should still treat dependency setup as an explicit bootstrap step before
345
+ running tests, typecheck, or builds. If module resolution fails in a fresh
346
+ worktree, first confirm dependencies were linked, installed, or provisioned by
347
+ `worktreeSetupHook` before treating it as a code failure.
348
+
334
349
  ## The Oracle Workflow
335
350
 
336
351
  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.
@@ -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,6 +29,7 @@ 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
34
  - `/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
35
  - `/subagents-watchdog` — inspect or configure the opt-in adversarial change watchdog (model, on/off, recommend-model, check)