pi-subagents 0.53.0 → 0.55.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 (76) hide show
  1. package/CHANGELOG.md +66 -5
  2. package/README.md +1 -1
  3. package/agents/reviewer.md +12 -2
  4. package/docs/agents.md +4 -4
  5. package/docs/configuration.md +6 -6
  6. package/docs/extension-api.md +14 -4
  7. package/docs/models.md +41 -6
  8. package/docs/observability.md +14 -3
  9. package/docs/tool-reference.md +21 -6
  10. package/docs/workflows.md +7 -1
  11. package/index.ts +10 -1
  12. package/package.json +1 -1
  13. package/prompts/council.md +19 -7
  14. package/prompts/parallel-review.md +5 -1
  15. package/prompts/review-loop.md +9 -5
  16. package/skills/council-mode/SKILL.md +50 -26
  17. package/skills/pi-subagents/SKILL.md +5 -1
  18. package/skills/pi-subagents/references/constraints-and-recipes.md +16 -1
  19. package/skills/pi-subagents/references/execution-controls.md +13 -4
  20. package/skills/pi-subagents/references/multi-lane-orchestration.md +3 -3
  21. package/skills/pi-subagents/references/prompting-and-roles.md +14 -7
  22. package/src/agents/agent-management.ts +115 -14
  23. package/src/agents/agent-serializer.ts +2 -2
  24. package/src/agents/agents.ts +195 -47
  25. package/src/api/external-job-provider.ts +10 -1
  26. package/src/api/preflight.ts +33 -19
  27. package/src/api/project-panes.ts +2 -0
  28. package/src/extension/doctor.ts +10 -0
  29. package/src/extension/fanout-child.ts +3 -2
  30. package/src/extension/index.ts +24 -4
  31. package/src/extension/public-execution.ts +12 -9
  32. package/src/extension/rpc.ts +77 -3
  33. package/src/extension/schemas.ts +2 -1
  34. package/src/extension/tool-description.ts +9 -6
  35. package/src/extension/tool-result.ts +19 -0
  36. package/src/inspectors/herdr/client.ts +3 -3
  37. package/src/inspectors/herdr/focus.ts +55 -0
  38. package/src/inspectors/herdr/project-panes.ts +228 -44
  39. package/src/integrations/herdr-status.ts +26 -4
  40. package/src/runs/background/async-execution.ts +112 -13
  41. package/src/runs/background/async-job-tracker.ts +33 -14
  42. package/src/runs/background/async-resume.ts +20 -2
  43. package/src/runs/background/async-retention.ts +1 -1
  44. package/src/runs/background/async-status.ts +10 -0
  45. package/src/runs/background/chain-root-attachment.ts +5 -0
  46. package/src/runs/background/control-channel.ts +98 -10
  47. package/src/runs/background/notify.ts +62 -1
  48. package/src/runs/background/result-watcher.ts +4 -3
  49. package/src/runs/background/run-status.ts +15 -1
  50. package/src/runs/background/stale-run-reconciler.ts +3 -0
  51. package/src/runs/background/subagent-runner.ts +251 -38
  52. package/src/runs/background/wait-completions.ts +2 -0
  53. package/src/runs/background/wait-tool.ts +4 -3
  54. package/src/runs/foreground/async-stop-action.ts +23 -2
  55. package/src/runs/foreground/execution.ts +110 -8
  56. package/src/runs/foreground/subagent-executor.ts +361 -45
  57. package/src/runs/foreground/workflow-detach-reconcile.ts +3 -0
  58. package/src/runs/shared/acceptance.ts +1 -0
  59. package/src/runs/shared/child-identity.ts +36 -0
  60. package/src/runs/shared/completion-guard.ts +50 -1
  61. package/src/runs/shared/external-job-bridge.ts +53 -37
  62. package/src/runs/shared/external-job-runner.ts +126 -23
  63. package/src/runs/shared/model-fallback.ts +46 -15
  64. package/src/runs/shared/model-scope.ts +106 -39
  65. package/src/runs/shared/orca-progress-tabs.ts +71 -9
  66. package/src/runs/shared/parallel-utils.ts +12 -0
  67. package/src/runs/shared/pi-args.ts +31 -1
  68. package/src/runs/shared/subagent-prompt-runtime.ts +39 -10
  69. package/src/runs/shared/tool-availability.ts +1 -3
  70. package/src/shared/launch-contract.ts +6 -5
  71. package/src/shared/thinking-ceiling.ts +52 -0
  72. package/src/shared/types.ts +72 -5
  73. package/src/tui/fleet-status.ts +66 -13
  74. package/src/tui/render.ts +5 -4
  75. package/src/watchdog/permission-arbiter.ts +59 -51
  76. package/src/workflows/scripted-workflow.ts +107 -10
package/CHANGELOG.md CHANGED
@@ -1,14 +1,77 @@
1
1
  # Changelog
2
2
 
3
- ## [Unreleased]
3
+ ## [0.55.0] - 2026-08-23
4
+
5
+ ### Highlights
6
+ - Stop a single stuck child in an async workflow without stopping the whole run.
7
+ - Continue finished external jobs, like Surf's `gpt-pro`, with follow-up requests through `resume`.
8
+ - Cap child thinking with `subagents.maxThinking` and set a preferred default provider for bare model ids.
9
+ - Scripted workflow outputs now land in the run's managed artifact directory instead of the repository root.
10
+ - Child launches fail fast with clear reasons when requested models or write tools are unavailable.
11
+
12
+ ### Added
13
+ - Add `subagents.maxThinking` to enforce a thinking ceiling across native subagent launches. Thanks to [@alex-real14](https://github.com/alex-real14) for #1397.
14
+ - Add `subagents.defaultProvider` and per-agent `defaultProvider` overrides so bare subagent model ids can prefer a configured provider. Thanks to [@swingtempo](https://github.com/swingtempo) for #1393.
15
+ - Add external-job follow-ups through `subagent({ action: "resume" })` for completed provider jobs that expose `followUp(input)`, with duplicate request dedupe, durable parent-job lineage (#1381), and clearer errors when a follow-up cannot start.
16
+ - Add child-scoped stop support and child stop observer events for async/workflow runs. Malformed child stop requests are rejected instead of widening to a run-level stop. Thanks to [@yanqianglu](https://github.com/yanqianglu) for #1367.
17
+ - Create one passive Orca observer tab per top-level subagent call, with shared chain/parallel progress and project-local observer manifests. Thanks to [@hyein-cbio](https://github.com/hyein-cbio) for #1360.
18
+ - Count Herdr project panes in inline status and report compact Herdr pane title suffixes for active subagent work.
19
+ - Let `agentOverrides` set or clear default `output` paths and `defaultReads`, while preserving explicit custom-agent frontmatter and preventing settings-derived values from being serialized into custom definitions. Thanks to [@mevatron](https://github.com/mevatron) for #1349.
20
+ - Surface copyable `provider/id` model selectors from `{ action: "models" }` and point invalid model warnings at that discovery path. Thanks to [@lixinglong27](https://github.com/lixinglong27) for #1365.
21
+ - Add bundled skill guidance for lightweight task profiles before subagent fanout. Thanks to [@srcKod](https://github.com/srcKod) for #1395.
22
+ - Add delegated review guidance that separates evidence requirements from severity labels so first-pass reviews do not default to `blockers only`.
23
+
24
+ ### Fixed
25
+ - Route relative `workflowScript` output paths through managed artifacts instead of creating report files in the repository root.
26
+ - Keep the async widget spinner and elapsed timer moving while the parent is idle by routing animation ticks through the live widget rebuild path. Thanks to [@0xFlo](https://github.com/0xFlo) for #1390.
27
+ - Slow async widget animation rerenders to 1 Hz so quiet running jobs do not repaint the full TUI at the liveness tick rate. Thanks to [@0xFlo](https://github.com/0xFlo) for #1376.
28
+ - Fail a Pi child launch when the child reports a different provider/model than the resolved requested model. Thanks to [@zzzubair](https://github.com/zzzubair) for #1377.
29
+ - Render detached workflow supervisor handoffs as paused/waiting and include workflow and child run ids in completion notifications.
30
+ - Report implementation runs blocked by missing child tools as blocked mutation effects instead of no-edit completion guard failures.
31
+ - Fail child launch attempts when the runtime lacks requested core write tools or an implementation worker has only read-only launch tools, including workflow children that inherit a read-only capability ceiling.
32
+ - Let read-only reviewer acceptance rely on the parent-side staged-file check instead of requiring child-reported `noStagedFiles` evidence.
33
+ - Run public single-child launches directly instead of wrapping them in a workflow, so async external-job agents do not show a completed workflow before the real provider job finishes.
34
+ - Start omitted-`async` public external-runner single-child launches in the supported background mode, so package agents such as Surf's `gpt-pro` do not fail as foreground requests.
35
+ - Let workflow scripts await omitted-`async` external-runner children by launching them in the background internally and returning their terminal result.
36
+ - Report helpful workflow errors when `runs.all(...)` results are read as keyed objects instead of ordered arrays. Thanks to [@ravshansbox](https://github.com/ravshansbox) for #1351.
37
+ - Clarify that Council Mode can include installed external-runner advisors such as Surf's `gpt-pro` when the `surf-cli` Pi extension has registered `surf-oracle`, with text JSON reports instead of `outputSchema`.
38
+
39
+ ## [0.54.0] - 2026-08-21
40
+
41
+ ### Highlights
42
+ - Subagent model selection is more precise with per-agent restrictions and an `inherit` shortcut for the current parent model.
43
+ - Package agents are easier to discover because list and detail output now shows where they come from and whether their external provider is ready.
44
+ - Workflow runs are less fragile: tool-result backfill, context-overflow handling, resumed children, and permission asks now behave more predictably.
45
+ - Child launches are lighter and safer because subagent processes avoid loading the parent extension graph and avoid unnecessary permission bridge setup.
46
+ - Council Mode is easier to use from natural language and no longer requires invented advisor role labels.
47
+
48
+ ### Added
49
+ - Add per-agent model restrictions and a current-parent `inherit` allow-list alias. Thanks to [@hieudmg](https://github.com/hieudmg) for #1328.
50
+
51
+ ### Changed
52
+ - Show package names, versions, and external-job provider status in subagent list and detail output so package agents such as Surf's `gpt-pro` are easier to find and use.
53
+ - Make scripted workflow helper support and stale-session recovery easier to see in `doctor` and the workflow guide (#1344).
54
+ - Keep structured single-child execution receipts quieter by removing an internal conversion log from public workflow output.
55
+ - Route natural-language requests for advisor councils, plan critique, cross-exam, or multiple model perspectives to the Council Mode protocol.
56
+ - Simplify Council Mode advisor selection so model-based profiles provide the perspective and the question supplies the decision frame.
57
+
58
+ ### Fixed
59
+ - Layer custom-agent user and project overrides without dropping user-only fields, while preserving project precedence. Thanks to [@jagaliano](https://github.com/jagaliano) for #1348.
60
+ - Avoid child tool-call hangs by loading the external permission-system bridge only for explicit native permission rules and by failing stalled ask decisions closed. Thanks to [@moekyo](https://github.com/moekyo) for #1339.
61
+ - Keep foreground workflow children from timing out after a tool result is backfilled without a separate execution-end event. Thanks to [@moekyo](https://github.com/moekyo) for #1339.
62
+ - Mark completed foreground workflow children as resumable in keyed receipts when their persisted session file is available (#1335).
63
+ - Avoid loading the parent extension graph in subagent child processes. Thanks to [@ccharname](https://github.com/ccharname) for #1330.
64
+ - Stop model fallback on context-overflow failures and surface `contextOverflow`. Thanks to [@srcKod](https://github.com/srcKod) for #1323.
65
+ - Stop empty slow result scans from spamming the session transcript. Thanks to [@afrodao2394](https://github.com/afrodao2394) for #1329.
66
+ - Surface logical tool failures so subagent tool results backfill correctly. Thanks to [@abdwhb-png](https://github.com/abdwhb-png) for #1332 and [@moekyo](https://github.com/moekyo) for #1331.
4
67
 
5
68
  ## [0.53.0] - 2026-08-20
6
69
 
7
70
  ### Highlights
71
+ - New `/council` mode helps with material decisions by running a small, bounded group of advisors and ending with a parent-written decision memo.
8
72
  - Pi extensions can now register runtime agents without writing user or project config.
9
73
  - Async workflows are easier to resume because completed children now have durable keyed receipts.
10
74
  - Model fallback is less noisy and less wasteful when a model fails or the prompt is too large.
11
- - Fleet and `/council` now give clearer supervision cues while keeping control in the parent session.
12
75
  - Extension RPC hosts can safely inspect status, launch async work, steer children, and manage schedules.
13
76
 
14
77
  ### Added
@@ -23,9 +86,7 @@
23
86
  - Add durable keyed async workflow receipts and resume-by-key selectors for
24
87
  retained workflow children (#1302).
25
88
  - Add the `resultScanLogging` config to control result scan logging. Thanks to [@apoapostolov](https://github.com/apoapostolov) for #1293.
26
- - Add packaged `/council` and `council-mode` resources for a bounded,
27
- supervisor-mediated advisor loop, plus documented model-based `council-*`
28
- profile examples (#1295).
89
+ - Add `/council` and `council-mode` for bounded advisor councils. Use it for material decisions that need multiple perspectives: the parent picks 2–3 advisors, collects independent reports, optionally runs one cross-exam pass, and writes the final decision memo. The package also documents model-based `council-*` profile examples (#1295).
29
90
 
30
91
  ### Changed
31
92
  - Show bounded workflow progress in Fleet detail views while keeping workflow
package/README.md CHANGED
@@ -76,7 +76,7 @@ The package includes `/council` and `council-mode`, plus documented model-based
76
76
  | Solve a hard problem | "Use oracle to investigate this bug before we edit." |
77
77
  | Review a diff | "Use reviewer to review this diff." |
78
78
  | Run parallel reviewers | "Run reviewers for correctness, tests, and cleanup." |
79
- | Debate a material decision | "Use `/council` to convene architect and skeptic advisors." |
79
+ | Debate a material decision | "Use `/council` with model-based advisors to compare this decision." |
80
80
  | Implement then review | "Implement this, then review it." |
81
81
  | Review until clean | "Run a review loop on this change with a max of 3 rounds." |
82
82
  | Execute a plan carefully | "Have worker implement this approved plan, then run reviewers and apply the feedback." |
@@ -72,8 +72,18 @@ Structure your findings clearly:
72
72
  ## Review
73
73
  - Correct: what is already good (with evidence)
74
74
  - Fixed: issue, location, and resolution (if you applied a fix)
75
- - Blocker: critical issue that must be resolved before proceeding
76
- - Note: observation, risk, or follow-up item
75
+ - Finding: P0/P1/P2, issue, location, evidence, and smallest fix
76
+ - Merge verdict: BLOCK, OK, or OK with notes
77
77
  ```
78
78
 
79
79
  When reviewing code, cite file paths and line numbers. When reviewing plans, cite specific sections and assumptions.
80
+
81
+ Filter findings by evidence, not by severity. Report only concrete current issues
82
+ that are caused or made reachable by the target diff, and support each one with
83
+ source proof, a test or repro, or a contract contradiction. Use P0 for issues
84
+ that block merge, P1 for issues that should be fixed before release, and P2 for
85
+ report-only notes. Say exactly `No issues found.` when nothing qualifies.
86
+
87
+ Use `blockers only` only for a final pre-merge re-check after the P1/P2
88
+ inventory is already captured, or for an explicit emergency hotfix where the
89
+ parent intentionally defers non-blocking findings.
package/docs/agents.md CHANGED
@@ -80,9 +80,9 @@ Native `oracle` runs inside Pi and can use its configured read tools. `claude-ad
80
80
 
81
81
  | Durable file | Owner | States | Release predicate | Rollback predicate | Stale-head behavior | Fail-closed cases |
82
82
  |--------------|-------|--------|-------------------|--------------------|---------------------|-------------------|
83
- | `status.json` step `runner` and `externalJob` | pi-subagents async runner | `queued`, `running`, `completed`, `failed`, `stopped`, `blocked` | Provider `result` returns terminal data and the async result is written | Provider start/status/result/reattach returns an error | If a status file already has a provider job id, recovery calls `reattach` and `result`; it refuses to start a new prompt when the provider or prompt digest differs | Missing provider, capacity conflict, malformed provider response, bridge timeout, prompt digest mismatch |
83
+ | `status.json` step `runner` and `externalJob` | pi-subagents async runner | `queued`, `running`, `completed`, `failed`, `stopped`, `blocked` | Provider `result` returns terminal data and the async result is written | Provider start/follow-up/status/result/reattach returns an error | If a status file already has a provider job id, recovery calls `reattach` and `result`; it refuses to start a new prompt when the provider, prompt digest, parent job id, request id, request digest, or options differ | Missing provider, unsupported follow-up provider, capacity conflict, malformed provider response, bridge timeout, prompt digest mismatch, parent conversation missing |
84
84
  | `result.json` or session result payload | pi-subagents async runner | `complete`, `failed`, `stopped` | All steps reach terminal state and result publication succeeds or is recoverably indexed | Result write fails and pending result repair records the terminal state | Stale status can repair from an existing result file | Unindexed sessionless stale failure |
85
- | `external-job-requests/` and `external-job-responses/` | Host-mediated provider bridge | pending request, terminal response | Host process writes a matching response and removes the request | Bridge timeout or malformed request response | Requests are operation-scoped. Recovery sends `reattach`/`result`, not `start`, when job metadata exists | Provider not registered, host bridge not loaded, malformed request, provider exception |
85
+ | `external-job-requests/` and `external-job-responses/` | Host-mediated provider bridge | pending request, terminal response | Host process writes a matching response and removes the request | Bridge timeout or malformed request response | Requests are operation-scoped. Recovery sends `reattach`/`result`, not `start` or `follow-up`, when job metadata exists. `start` and `follow-up` use durable dispatch claims | Provider not registered, host bridge not loaded, malformed request, provider exception, ambiguous dispatch without a provider job id |
86
86
  | Provider artifact path | External provider | provider-defined terminal artifact | Provider returns `artifactPath`, or Pi writes returned text to `external-job-<index>.result.md` | Provider reports failure or no result | Existing artifact path is retained in `status.json` | Missing artifact with no text output returns a terminal message instead of inventing content |
87
87
 
88
88
  The `researcher` builtin uses `web_search`, `fetch_content`, and `get_search_content`. Those require [pi-web-access](https://github.com/nicobailon/pi-web-access):
@@ -111,10 +111,10 @@ You can override selected builtin fields without copying the whole agent. Overri
111
111
  }
112
112
  ```
113
113
 
114
- Supported override fields: `description`, `model`, `fallbackModels`, `thinking`, `systemPromptMode`, `inheritProjectContext`, `inheritSkills`, `defaultContext`, `acceptanceRole`, `disabled`, `skills`, `tools`, and `systemPrompt`.
114
+ Supported override fields: `description`, `output`, `outputMode`, `defaultReads`, `model`, `defaultProvider`, `fallbackModels`, `thinking`, `systemPromptMode`, `inheritProjectContext`, `inheritSkills`, `defaultContext`, `acceptanceRole`, `disabled`, `skills`, `tools`, and `systemPrompt`.
115
115
 
116
116
  - `description` replaces the discovered description for builtin and custom agents, which lets list output show deployment-specific routing or model metadata.
117
- - Use `defaultContext: false` or `acceptanceRole: false` to clear an inherited override.
117
+ - Use `output: false`, `defaultReads: false`, `defaultContext: false`, or `acceptanceRole: false` to clear an inherited value.
118
118
  - Use `tools: "inherit"` on a builtin when that one role should omit its bundled tool allowlist and receive Pi's normal builtins and ambient extensions. This keeps strict tools as the default for other builtins.
119
119
  - Project overrides beat user overrides.
120
120
  - 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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  `pi-subagents` reads optional JSON config from `~/.pi/agent/extensions/subagent/config.json`. This page lists every key, plus the environment variables and the settings-file keys that affect config resolution.
4
4
 
5
- Settings-level keys (`subagents.defaultModel`, `defaultThinking`, `defaultExtensions`, `agentOverrides`, `modelScope`, `disableThinking`, `disableBuiltins`, watchdog settings) live in Pi settings files, not this config file. See [models.md](models.md), [agents.md](agents.md), and [watchdog.md](watchdog.md).
5
+ Settings-level keys (`subagents.defaultModel`, `defaultProvider`, `defaultThinking`, `defaultExtensions`, `agentOverrides`, `modelScope`, `disableThinking`, `disableBuiltins`, watchdog settings) live in Pi settings files, not this config file. `modelScope.agents.<name>` adds per-agent restrictions, and `allow: ["inherit"]` permits the current parent model. See [models.md](models.md), [agents.md](agents.md), and [watchdog.md](watchdog.md).
6
6
 
7
7
  ## Project root resolution (settings)
8
8
 
@@ -85,11 +85,11 @@ Pi binds `Ctrl+B` to editor cursor-left by default. The extension shortcut takes
85
85
  }
86
86
  ```
87
87
 
88
- Opt in to a best-effort Orca observer that creates one Orca terminal tab for each subagent child and mirrors its live tool, assistant, stdout, and stderr progress. Tab titles use a persistent worktree-local sequence (`subagent · <agent> · 1`, `... · 2`, and so on), so separate workflows and concurrent children do not reuse the same number. For the same worktree, `orca terminal create` runs one at a time in that sequence so the UI can append tabs from left to right as `1`, then `2`, then `3`. This does **not** replace Pi as the child runner: native Pi children keep the same process, lifecycle, status, control, artifact, and result paths. External CLI profiles also keep their existing runner and can mirror their stdout/stderr.
88
+ Opt in to a best-effort Orca observer that creates one Orca terminal tab for each top-level subagent call and mirrors the run's live tool, assistant, stdout, and stderr progress. Parallel and chain children share that one tab, with child section headers in the mirrored log. Tab titles use a persistent worktree-local sequence (`subagents · <run-label> · 1`, `... · 2`, and so on), so separate top-level calls do not reuse the same number. For the same worktree, `orca terminal create` runs one at a time in that sequence so observer tabs appear from left to right as `1`, then `2`, then `3`. This does **not** replace Pi as the runner: native Pi children keep the same process, lifecycle, status, control, artifact, and result paths. External CLI profiles also keep their existing runner and can mirror their stdout/stderr.
89
89
 
90
- The integration is off by default and supports macOS and Linux. It is disabled on Windows. When enabled, `pi-subagents` looks for executable `orca` on `PATH`, or uses the executable path in `PI_SUBAGENT_ORCA_BINARY`. If no executable is available, Orca is not running, the cwd is not an Orca-managed worktree, or `terminal create` fails, the authoritative subagent still runs normally. Tab creation is deliberately best-effort and never changes the child result.
90
+ The integration is off by default and supports macOS and Linux. It is disabled on Windows. When enabled, `pi-subagents` looks for executable `orca` on `PATH`, or uses the executable path in `PI_SUBAGENT_ORCA_BINARY`. If no executable is available, Orca is not running, the cwd is not an Orca-managed worktree, or `terminal create` fails, the authoritative subagent still runs normally. Tab creation is deliberately best-effort and never changes the child result. A passive observer manifest is also written under `<worktree>/.pi/subagents/views/orca/` when possible so future view surfaces can discover the Orca tab without making Orca authoritative.
91
91
 
92
- Set `enabled` to `false` (or remove the block) as a kill switch. In that state, `pi-subagents` does not invoke `orca` and creates no Orca tabs. The temporary mirror files contain child output, use private file modes where supported, and are removed shortly after the child finishes. Each mirror is capped at 1 MiB. The observer stops accepting progress when the cap or stream backpressure is reached and appends a truncation notice. The viewer removes terminal control sequences with parser state that persists across file reads. On completion, the viewer exits back to the Orca terminal's shell prompt; the tab and its terminal scrollback remain open until the user closes the tab. A successfully completed native Pi child with a recorded session ends with a safely quoted `rm -- <exact-session-path>` command; failed, stopped, timed-out, and sessionless children do not show the removal command.
92
+ Set `enabled` to `false` (or remove the block) as a kill switch. In that state, `pi-subagents` does not invoke `orca` and creates no Orca tabs. The temporary mirror files contain child output, use private file modes where supported, and are removed shortly after the run finishes. Each mirror is capped at 1 MiB. The observer stops accepting progress when the cap or stream backpressure is reached and appends a truncation notice. The viewer removes terminal control sequences with parser state that persists across file reads. On completion, the viewer exits back to the Orca terminal's shell prompt; the tab and its terminal scrollback remain open until the user closes the tab. A successfully completed native Pi run with a recorded session ends with a safely quoted `rm -- <exact-session-path>` command; failed, stopped, timed-out, and sessionless runs do not show the removal command.
93
93
 
94
94
  ## `asyncByDefault`
95
95
 
@@ -170,9 +170,9 @@ This is different from `waitTool.enabled=false`, which returns immediately witho
170
170
  { "resultScanLogging": "activity" }
171
171
  ```
172
172
 
173
- Controls how slow result-index scans are logged. Defaults to `"all"`; valid values are `"all"`, `"activity"`, and `"off"`.
173
+ Controls how slow result-index scans are logged. Defaults to `"activity"`; valid values are `"all"`, `"activity"`, and `"off"`.
174
174
 
175
- The watcher logs `Subagent result scan inspected … scheduled …` through `console.error` whenever a result-index scan passes the slow threshold (500ms). With `"all"` (default) every slow scan is logged, including the periodic healthy rescan that inspects zero files while no async runs are pending. Those empty scans add noise to the session transcript with no signal; choose `"activity"` to log only scans that inspected or scheduled actual work, or `"off"` to silence slow-scan logging entirely. `"off"` does not disable result delivery or the watcher itself, only its slow-scan log line.
175
+ The watcher logs `Subagent result scan inspected … scheduled …` through `console.error` whenever a result-index scan passes the slow threshold (500ms). With `"activity"` (default), it logs only scans that inspected or scheduled actual work. Use `"all"` to log every slow scan, including the periodic healthy rescan that inspects zero files while no async runs are pending, or `"off"` to silence slow-scan logging entirely. `"off"` does not disable result delivery or the watcher itself, only its slow-scan log line.
176
176
 
177
177
  ## `forceTopLevelAsync`
178
178
 
@@ -28,7 +28,7 @@ The RPC methods are `ping`, `status`, `manage`, `spawn`, `steer`, `interrupt`, `
28
28
  Method notes:
29
29
 
30
30
  - `manage` exposes a narrow schedule-only allowlist: `schedule.list`, `schedule.show`, `schedule.history`, `schedule.pause`, `schedule.resume`, `schedule.run`, and `schedule.delete`. All actions except `schedule.list` require `id`. Mission, agent, config, worktree, and arbitrary management actions are rejected before executor dispatch. `ping.capabilities.managementActions` advertises the exact allowlist.
31
- - `spawn` requires `workflowScript` and is async-only: omit `async` or set `async: true`, omit `clarify`, 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.
31
+ - `spawn` accepts structured single-child execution (`agent`, `task?`) or `workflowScript` and is async-only: omit `async` or set `async: true`, omit `clarify`, 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.
32
32
  - `steer` requires an async run `id` (plus optional child `index`) and a non-empty `message`; its reply preserves the normal acknowledged-delivery result. Optional `mode` values are `steer` (default), `follow_up`, and `auto`, and receipts include `deliveryStatus: "delivered" | "queued"`. RPC steering disables the direct tool's pause-and-revive recovery in every mode so an extension keeps authority over the exact child it spawned; `ping.capabilities.nonRecoveringSteer` advertises this guarantee.
33
33
  - `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.
34
34
  - `stop` targets current-session top-level async runs through the stop control channel and records a `stopped` lifecycle instead of reporting a timeout.
@@ -275,6 +275,7 @@ import { registerExternalJobProvider } from "pi-subagents/external-job-provider"
275
275
  const dispose = registerExternalJobProvider({
276
276
  name: "surf-oracle",
277
277
  start: ({ prompt, promptDigest, cwd, runId, stepIndex, agent, options }) => startSurfJob({ prompt, promptDigest, cwd, runId, stepIndex, agent, options }),
278
+ followUp: ({ prompt, parentProviderJobId, requestId, requestDigest, options }) => followUpSurfJob({ prompt, parentProviderJobId, requestId, requestDigest, options }),
278
279
  status: (providerJobId) => getSurfJobStatus(providerJobId),
279
280
  result: (providerJobId) => getSurfJobResult(providerJobId),
280
281
  reattach: (providerJobId) => reattachSurfJob(providerJobId),
@@ -283,7 +284,9 @@ const dispose = registerExternalJobProvider({
283
284
 
284
285
  The provider returns handles with `providerJobId`, `state`, optional `handleUrl`/`conversationUrl`, optional `failureCode`/`failureMessage`, and optional `blockingJobId` for capacity conflicts. `result` can also return `output` and/or `artifactPath`.
285
286
 
286
- The async runner process does not import provider internals. It writes operation requests into its async run directory. The parent Pi process services those requests against the registered provider and writes operation responses. If the provider is not registered, the bridge fails closed with an actionable error. If a run is recovered after provider job metadata exists, the runner calls `reattach` and `result`; it does not call `start` again.
287
+ `followUp(input)` is optional. When it is present, a completed external-job run can be continued with `subagent({ action: "resume", id: "<run>", message: "..." })`. Pi sends the completed parent provider job id plus a stable `requestId` and `requestDigest`. The provider must continue that parent conversation or fail closed. It must not open a fresh thread when the parent conversation is missing.
288
+
289
+ The async runner process does not import provider internals. It writes operation requests into its async run directory. The parent Pi process services those requests against the registered provider and writes operation responses. If the provider is not registered, the bridge fails closed with an actionable error. If a run is recovered after provider job metadata exists, the runner calls `reattach` and `result`; it does not call `start` or `follow-up` again.
287
290
 
288
291
  ## Herdr integration
289
292
 
@@ -292,6 +295,7 @@ When Pi runs inside [Herdr](https://herdr.dev), pi-subagents automatically repor
292
295
  - The bridge is enabled only when Herdr supplies `HERDR_ENV=1` and `HERDR_PANE_ID`; outside Herdr it registers no listeners or timers.
293
296
  - It restores current-session active runs after `/reload` or `/resume`, refreshes metadata while work is active, and clears it on completion or shutdown.
294
297
  - The bridge uses Herdr's existing `herdr:blocked` sibling event when an async child needs attention, and emits `herdr:busy` while async work remains. Herdr versions that support the sibling event keep the pane's semantic state `working`; older versions ignore it safely and still display the metadata label while the Pi integration remains the lifecycle authority.
298
+ - The owning Pi session is the only publisher for its own pane metadata. While active subagents exist, it reports a compact `title-suffix` token: one active run uses that agent name, two or more use the active-run count, and attention adds `⚠`. The suffix is cleared when active work reaches zero.
295
299
 
296
300
  To show the reported label in the expanded Agent sidebar, include `state_text` or `$summary` in its row layout:
297
301
 
@@ -327,7 +331,7 @@ subagent({ action: "project.status", cwd: "/path/to/repo" })
327
331
  subagent({ action: "project.close", cwd: "/path/to/repo" })
328
332
  ```
329
333
 
330
- A project pane runs its own Pi session in the target directory, so subagents launched from that pane use that project's config, agents, skills, files, git state, and missions. The parent session keeps coordination authority; existing headless runs are not moved into the pane. Pane bindings live under `<projectRoot>/.pi/subagents/project-panes/herdr.json` and are only a local pointer to the Herdr pane.
334
+ A project pane runs its own Pi session in the target directory, so subagents launched from that pane use that project's config, agents, skills, files, git state, and missions. The parent session keeps coordination authority, but it does not own or control the subagents inside the peer pane. Existing headless runs are not moved into the pane. Pane bindings live under `<projectRoot>/.pi/subagents/project-panes/herdr.json` and are only a local pointer to the Herdr pane.
331
335
 
332
336
  Other Pi extensions should use the versioned public TypeScript surface instead of invoking the model-facing tool or importing inspector internals:
333
337
 
@@ -336,15 +340,21 @@ import {
336
340
  PROJECT_PANES_API_VERSION,
337
341
  openProjectPane,
338
342
  getProjectPaneStatus,
343
+ focusProjectPane,
339
344
  closeProjectPane,
340
345
  } from "pi-subagents/project-panes";
341
346
 
342
347
  const opened = await openProjectPane({ cwd: "/path/to/repo", focus: false });
343
348
  const status = await getProjectPaneStatus({ cwd: "/path/to/repo" });
349
+ const focused = await focusProjectPane({ cwd: "/path/to/repo" });
344
350
  const closed = await closeProjectPane({ cwd: "/path/to/repo", requireIdle: true });
345
351
  ```
346
352
 
347
- The API returns discriminated structured results with canonical project root, binding path, pane identity, bounded Herdr runtime fields, and stable error codes. `requireIdle: true` fails closed unless Herdr explicitly reports `agent_status: "idle"`; use it when an owning extension must not close a working or blocked pane. The API deliberately reports `trust: "human-verification-required"`: it never bypasses or claims to attest Pi's project-trust prompt. `PROJECT_PANES_API_VERSION` is currently `1`.
353
+ The API returns discriminated structured results with canonical project root, binding path, pane identity, bounded Herdr runtime fields, stable error codes, and `PROJECT_PANES_API_VERSION: 1`.
354
+
355
+ - Close fails closed unless the saved pane id is still verified for that project and Herdr explicitly reports `agent_status: "idle"`. `requireIdle` is retained for callers that already pass it, but it cannot weaken that rule.
356
+ - Focus uses the saved pane id, asks Herdr for its `tab_id` or `workspace_id`, and then calls the matching Herdr focus command.
357
+ - The API reports `trust: "human-verification-required"`. It never bypasses or claims to attest Pi's project-trust prompt.
348
358
 
349
359
  ## Host session lifetime and completion wakes
350
360
 
package/docs/models.md CHANGED
@@ -5,10 +5,14 @@ How subagents pick models, and how to change that.
5
5
  Builtin agents inherit your current Pi default model. This keeps new installs from depending on a provider you may not have configured. From there you can layer defaults and overrides:
6
6
 
7
7
  - `subagents.defaultModel` — a default for every subagent that does not set its own model.
8
+ - `subagents.defaultProvider` — a provider preference for bare model ids, such as `llama-3`, when multiple providers expose the same id.
8
9
  - `subagents.agentOverrides.<name>.model` — pin one role.
10
+ - `subagents.agentOverrides.<name>.defaultProvider` — choose or clear the provider preference for one role.
9
11
  - Per-run overrides — for one launch only.
10
12
 
11
- Precedence, strongest first: per-run override → agent frontmatter `model` → `agentOverrides.<name>.model` → `subagents.defaultModel` → the parent session model.
13
+ Precedence, strongest first: per-run override → agent frontmatter `model` → `agentOverrides.<name>.model` → `subagents.defaultModel` → the parent session model. A provider preference does not replace this order; it only resolves bare model ids when the active registry has more than one match. Fully qualified `provider/model` strings still win exactly.
14
+
15
+ Use `model: "inherit"` in agent frontmatter or `agentOverrides.<name>.model` to select the current parent session model explicitly.
12
16
 
13
17
  ## Setting defaults and overrides
14
18
 
@@ -19,9 +23,13 @@ In `~/.pi/agent/settings.json` (user) or the project config settings file (`.pi/
19
23
  "defaultModel": "deepseek-v4-pro",
20
24
  "subagents": {
21
25
  "defaultModel": "deepseek-v4-flash",
26
+ "defaultProvider": "gpu-a",
22
27
  "agentOverrides": {
23
28
  "oracle": {
24
29
  "model": "deepseek-v4-pro"
30
+ },
31
+ "worker": {
32
+ "defaultProvider": "gpu-b"
25
33
  }
26
34
  }
27
35
  }
@@ -50,14 +58,14 @@ For a persistent role override with a backup model for provider failures:
50
58
  }
51
59
  ```
52
60
 
53
- `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 (see [agents.md](agents.md)). 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.
61
+ `subagents.defaultModel` and `subagents.defaultProvider` apply to builtin, package, user, and project agents. `defaultModel` fills only agents that do not set `model` in frontmatter. `defaultProvider` is also applied to frontmatter and override models so bare ids resolve against the intended provider. 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 (see [agents.md](agents.md)). 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 or provider.
54
62
 
55
63
  ## Recommended model tiering (optional)
56
64
 
57
65
  A setup that works well in practice: route agents by task shape instead of running everything on one model. Four tiers:
58
66
 
59
67
  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`.
60
- 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.
68
+ 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-luna:max` on `worker`, `reviewer`, and a lightweight `delegate` agent.
61
69
  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 oracle-style agents.
62
70
  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.
63
71
 
@@ -94,6 +102,21 @@ Set `subagents.defaultThinking` to give builtin, package, user, and project agen
94
102
 
95
103
  If your provider rejects model IDs with thinking suffixes, set `subagents.disableThinking: true` in user or project settings. That clears bundled builtin thinking defaults in one place. An explicit higher-precedence `agentOverrides.<name>.thinking` value can opt a role back in. Existing custom-agent frontmatter remains authoritative.
96
104
 
105
+ ### Thinking ceiling
106
+
107
+ Set `subagents.maxThinking` to enforce a hard maximum for every native Pi child. The supported levels, from least to most thinking, are `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`:
108
+
109
+ ```json
110
+ {
111
+ "subagents": {
112
+ "defaultThinking": "medium",
113
+ "maxThinking": "xhigh"
114
+ }
115
+ }
116
+ ```
117
+
118
+ Requests above the ceiling fail before child startup; the setting covers frontmatter, `agentOverrides`, per-run overrides, fallback models, parallel/chain children, nested launches, and resumed children. Project settings take precedence over user settings. External runners retain their existing behavior.
119
+
97
120
  ## Extension defaults
98
121
 
99
122
  Set `subagents.defaultExtensions` to give builtin, package, user, and project agents without an `extensions` field a shared extension allowlist:
@@ -153,17 +176,29 @@ To keep subagents inside a budget or compliance profile, enforce a model scope.
153
176
  "modelScope": {
154
177
  "enforce": true,
155
178
  "strict": true,
156
- "allow": ["anthropic/*", "openai/gpt-5-*"]
179
+ "allow": ["inherit", "openai/gpt-5-*"],
180
+ "agents": {
181
+ "worker": { "allow": ["openai/gpt-5-mini"] },
182
+ "reviewer": { "allow": ["inherit"] }
183
+ }
157
184
  }
158
185
  }
159
186
  }
160
187
  ```
161
188
 
162
- - `allow` is a list of glob patterns matched against the resolved `provider/id` (only `*` is special, case-insensitive). A resolved model that matches none of the patterns is rejected.
189
+ - `allow` is a list of glob patterns matched against the resolved `provider/id` (only `*` is special, case-insensitive). The literal `inherit` means the current parent session model.
190
+ - `agents.<name>` adds a second allow-list for that agent. The model must pass both the global list and the matching agent list, so an agent rule cannot weaken the global rule. Agent rules inherit `enforce` and `strict` when those fields are absent.
191
+ - A top-level `enforce: true` with only agent allow-lists restricts only those named agents. Unknown names are allowed so settings can be shared across projects and machines.
163
192
  - Models you pass explicitly — the tool-call `model`, `--model`, or a clarify pick — error and abort the run.
164
193
  - By default, models from agent frontmatter, `subagents.defaultModel`, the inherited parent session model, or fallback chains only warn and remain available, so existing configurations keep working while you tighten the scope.
165
194
  - Set `strict: true` with `enforce: true` to reject every resolved out-of-scope model. This includes inherited models and fallback candidates. An invalid fallback fails the run instead of being removed from the candidate chain.
166
- - `enforce: true` requires a non-empty `allow` list; otherwise the config is rejected at load time.
195
+ - `enforce: true` requires at least one non-empty global or agent `allow` list; otherwise the config is rejected at load time.
196
+
197
+ Model scope is policy only. It rejects or warns; it does not select a cheaper model. Set `agentOverrides.worker.model` to choose a worker model and use `modelScope.agents.worker` to prevent a per-run override or fallback from escaping that restriction.
198
+
199
+ `inherit` expands in the parent process at each launch. It is never sent to the child as a model id. A nested child therefore inherits its immediate parent's current model, not the original top-level model. If no parent model is available, an enforced `inherit` entry does not match and fails closed.
200
+
201
+ Project `modelScope` settings replace the complete user `modelScope`, as with the existing project-over-user settings precedence. Project settings are trusted and can therefore replace user restrictions.
167
202
 
168
203
  ## Profiles and provider model catalogs
169
204
 
@@ -40,7 +40,7 @@ To inspect one background child in text, use `subagent({ action: "status", id: "
40
40
  In the TUI, a persistent FleetView below the editor keeps active work visible as a compact summary. Set `fleetViewPlacement` to `"aboveEditor"` to move it above the editor.
41
41
 
42
42
  ```text
43
- 2 active agents · ↓ 4.2k tokens · ↓/← to inspect
43
+ 2 active agents · 1 pane · ↓ 4.2k tokens · ↓/← to inspect
44
44
  ```
45
45
 
46
46
  After you expand it:
@@ -53,7 +53,7 @@ After you expand it:
53
53
  reviewer · running 38s · ↓ 1.4k tokens
54
54
  ```
55
55
 
56
- When the focused editor is empty, press `↓` or `←` to expand the summary into `main` plus active children with agent name, state, elapsed time, and token totals. Then use `↑`/`↓` or `j`/`k` to select a child and `Enter` to inspect it. Printable navigation keys are never intercepted before activation.
56
+ When the focused editor is empty, press `↓` or `←` to expand the summary into `main` plus active children with agent name, state, elapsed time, and token totals. The compact line counts active current-session work and Herdr project panes. Then use `↑`/`↓` or `j`/`k` to select a child and `Enter` to inspect it. Printable navigation keys are never intercepted before activation.
57
57
 
58
58
  FleetView replaces the legacy above-editor async widget by default. Successful background completions stay quiet so inactive Pi tabs are not marked unread, while failed or paused completions still notify the originating session. 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.
59
59
 
@@ -164,6 +164,17 @@ Nested fanout status is stored as compact sidecar event/registry metadata and me
164
164
 
165
165
  Consumers should read these JSON files instead of scraping terminal output. Unknown fields and event types should be ignored for forward compatibility.
166
166
 
167
+ RPC hosts that need low-latency child-stop UI hints can subscribe to the
168
+ `subagent:child-status` event advertised by RPC `ping` as `events.childStatus`.
169
+ The payload uses `type: "subagent.child-status"`, `version: 1`, `runId`,
170
+ `childId`, `status` (`"stopping"` or `"stopped"`), `ts`, and optional child
171
+ metadata such as `stepIndex`, `agent`, `childRunId`, `workflowKey`, `phase`, and
172
+ `label`. These events are observer hints only. They can duplicate across RPC and
173
+ async replay paths, and they are not replayed after a host restart. Status
174
+ snapshots remain authoritative for recovery and final state. Child stop control
175
+ still uses the normal `stop` request with `childId`; there is no separate child
176
+ stop API.
177
+
167
178
  ### Status and result fields
168
179
 
169
180
  The 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.
@@ -210,7 +221,7 @@ Each scripted workflow stores runtime artifacts under a workflow artifact direct
210
221
 
211
222
  A run directory may contain files such as `context.md`, `plan.md`, `progress.md`, and `parallel-{stepIndex}/.../output.md`. User-scoped temp workflow artifact directories older than 24 hours are cleaned up on extension startup; project-local and explicit persistent roots are not age-scanned.
212
223
 
213
- Debug artifacts live under `{sessionDir}/subagent-artifacts/`, `.pi/subagents/artifacts/` for project-scoped runs, or a user-scoped temp artifact directory. Single-run relative `output` files are saved under `{artifactsDir}/outputs/{runId}/` unless `singleRunOutputBaseDir` is configured. Per task you may see:
224
+ Debug artifacts live under `{sessionDir}/subagent-artifacts/`, `.pi/subagents/artifacts/` for project-scoped runs, or a user-scoped temp artifact directory. Single-run relative `output` files are saved under `{artifactsDir}/outputs/{runId}/` unless `singleRunOutputBaseDir` is configured. For lane, review, council, and gate reports, prefer these managed artifacts or the aggregate workflow result instead of repo-root `reports/` files. Copy only final durable evidence to session memory, a mission artifact, a PR/comment, or an approved docs path. Per task you may see:
214
225
 
215
226
  - `{runId}_{agent}_input.md`
216
227
  - `{runId}_{agent}_output.md`
@@ -4,7 +4,7 @@ Parameters and actions for the `subagent` tool. These are what the LLM passes wh
4
4
 
5
5
  ## Execution examples
6
6
 
7
- Chaining is code-driven through `workflowScript`. Use `await runs.run(...)` for sequential steps and `await runs.all([{ key, agent, task }, ...])` for ordinary parallel fanout. Do not read `.output` from an unawaited `runs.run` launch. Stored `runs.run` promises are only for the advanced rolling fanout pattern under [Workflow steering](#workflow-steering), where every promise is later observed with direct `await`, `Promise.race`, or `Promise.all`. Legacy top-level `chain`, `tasks`, and `parallel` inputs are not supported. Helper functions must be plain functions or explicit Promise chains. Nested `async function` helpers, async arrows, and async methods are rejected so child-launch tracking stays portable across Node and Bun.
7
+ Chaining is code-driven through `workflowScript`. Use `await runs.run(...)` for sequential steps and `await runs.all([{ key, agent, task }, ...])` for ordinary parallel fanout. `runs.all` resolves to an ordered array, not a key map, so use indexes, destructuring, or `.map(...)`, not `results.<key>`. Do not read `.output` from an unawaited `runs.run` launch. Stored `runs.run` promises are only for the advanced rolling fanout pattern under [Workflow steering](#workflow-steering), where every promise is later observed with direct `await`, `Promise.race`, or `Promise.all`. Legacy top-level `chain`, `tasks`, and `parallel` inputs are not supported. Helper functions must be plain functions or explicit Promise chains. Nested `async function` helpers, async arrows, and async methods are rejected so child-launch tracking stays portable across Node and Bun.
8
8
 
9
9
  ```js
10
10
  // One child; return the child promise explicitly
@@ -31,14 +31,14 @@ Chaining is code-driven through `workflowScript`. Use `await runs.run(...)` for
31
31
  | Param | Type | Default | Description |
32
32
  |-------|------|---------|-------------|
33
33
  | `agent` | string | - | Agent target for management actions. Workflow child agents are set inside `runs.run` or `runs.all`. |
34
- | `action` | string | - | Agent management (including `guide`, `children.list`, and `refine`/`refine.show`/`refine.rollback`), mission (`mission.create/list/show/update/resolve-decision/attach-run/close`), Herdr inspector (`inspector.open/status/close`), status/control, schedule, watchdog, or doctor action. |
34
+ | `action` | string | - | Agent management (including `guide`, `children.list`, and `refine`/`refine.show`/`refine.rollback`), mission (`mission.create/list/show/update/resolve-decision/attach-run/close`), Herdr inspector (`inspector.open/status/close`), Herdr project pane (`project.open/status/close`), status/control, schedule, watchdog, or doctor action. |
35
35
  | `topic` | `overview \| workflows \| agents \| missions \| observability \| tool-reference \| configuration \| models \| watchdog \| extension-api` | `overview` | Packaged guide topic for `action: "guide"`. |
36
36
  | `config` | object/string | - | Agent config for management create/update. |
37
37
  | `context` | `fresh \| fork` | global or per-agent default, else `fresh` | Explicit `fresh` or `fork` overrides every workflow child. When omitted, [`defaultSubagentContext`](configuration.md#defaultsubagentcontext) wins over each agent's `defaultContext`; `"fork"` creates a real branched session when the parent session file and current leaf exist, otherwise it falls back to `fresh`. Packaged `worker`, `oracle`, and `advisor` default to `fork`. |
38
38
  | `missionId` | string | - | Attach a workflow to an existing project mission instead of creating its default enclosing mission. |
39
39
  | `mission` | object/false | auto-create | Override the default enclosing mission with `{ title \| summary, objective?, goal?, budget?, labels? }`. Set exactly one non-empty `title` or `summary`; `objective` and `labels` are optional. `goal` may only be `true`, requires `budget.tokens`, and enables continuation notices. Pass `false` for an intentionally ephemeral workflow with no mission for it or its children and no `state` global. Explicit mission persistence failures are strict. |
40
40
  | `handoffPath` | string | - | Aggregate handoff manifest required by `action: "worktree.discard"`. |
41
- | `focus` | boolean | false | Focus the newly split pane for `action: "inspector.open"` or `action: "project.open"`; not a standalone action. Panes open in the background unless you set `focus: true`. |
41
+ | `focus` | boolean | false | Focus the newly split pane for `action: "inspector.open"` or `action: "project.open"`; not a standalone action. Panes open in the background unless you set `focus: true`. Existing saved project panes can be focused through the public project-pane API when Herdr reports a tab or workspace id. |
42
42
  | `view` | `fleet \| transcript` | - | Optional `status` view for the active fleet surface or transcript tail inspection. |
43
43
  | `lines` | number | `80` | Maximum transcript lines for `action: "status", view: "transcript"`; capped at 500. |
44
44
  | `agentScope` | `user \| project \| both` | `both` | Agent discovery scope. Project wins on collisions. |
@@ -226,6 +226,7 @@ subagent({ action: "doctor" })
226
226
 
227
227
  - Multi-child async runs and remembered foreground single, parallel, or chain runs can be revived by passing `index` to choose the child.
228
228
  - Nested runs can be resumed by nested id when their live route or persisted nested session metadata is available.
229
+ - Completed external-job runs can use the same `resume` action as a provider follow-up when the registered provider exposes `followUp(input)`. Running external-job parents fail closed with guidance to wait for completion. Unsupported providers fail with an update/reload message.
229
230
  - 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.
230
231
  - 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.
231
232
 
@@ -317,6 +318,20 @@ The parser canonicalizes known enum synonyms, snake_case report keys and wrapper
317
318
 
318
319
  Acceptance fences are removed from normal output artifacts, while the raw child transcript remains intact and per-child metadata stores the complete acceptance ledger and parsed report. Explicit failed gates fail the run. Inferred gates remain observable without failing the run.
319
320
 
321
+ ## Herdr project panes
322
+
323
+ Herdr project panes are peer Pi sessions opened by this Pi session:
324
+
325
+ ```ts
326
+ subagent({ action: "project.open", cwd: "/path/to/repo", message: "Start in this project." })
327
+ subagent({ action: "project.status", cwd: "/path/to/repo" })
328
+ subagent({ action: "project.close", cwd: "/path/to/repo" })
329
+ ```
330
+
331
+ The saved pane binding is pane-level only. The parent can refresh status, focus the saved pane when Herdr reports a tab or workspace id, or close it after Herdr verifies ownership and `agent_status: "idle"`. It cannot inspect, steer, or stop subagents inside that peer session. Stale or opaque Herdr metadata stays unknown and fails closed.
332
+
333
+ Inline status counts active current-session work and Herdr project panes. Use Herdr itself or the project-pane API to focus or close project panes.
334
+
320
335
  ## Orca progress tabs (experimental observer)
321
336
 
322
337
  Orca progress tabs are a global, opt-in observer, not an agent runner. Enable them in the extension config:
@@ -325,11 +340,11 @@ Orca progress tabs are a global, opt-in observer, not an agent runner. Enable th
325
340
  { "orcaProgressTabs": { "enabled": true } }
326
341
  ```
327
342
 
328
- Every foreground or background child keeps running through its normal native Pi or `external-cli` path. For each logical child, the observer asks Orca to create a background terminal tab in that child's current worktree and mirrors progress into it. Titles receive a persistent worktree-local sequence number, including across separate workflow calls. Creates for the same worktree are serialized in that sequence so tabs appear to the right in order (`1`, then `2`, then `3`) instead of racing. Model/startup retries reuse the same tab. Parallel and chain children each receive their own tab; attaching an already-running async root does not create a duplicate. Terminal control sequences are removed at the viewer sink across read boundaries. Each mirror is capped at 1 MiB and truncates when the cap or stream backpressure is reached. After the child finishes, its viewer returns to the terminal shell instead of ending the terminal session, so the tab and scrollback remain until the user closes them. Successful native Pi children with a known session append a safely quoted removal command for the exact verified session path; unsuccessful and sessionless children append only their terminal status.
343
+ Foreground and background children keep running through their normal native Pi or `external-cli` path. For each top-level subagent call, the observer asks Orca to create one background terminal tab in the owning worktree and mirrors progress into it. Parallel and chain children share that tab and are separated by child headers. Titles receive a persistent worktree-local sequence number, including across separate workflow calls. Creates for the same worktree are serialized in that sequence so tabs appear to the right in order (`1`, then `2`, then `3`) instead of racing. Model/startup retries reuse the same observer. Attaching an already-running async root does not create a duplicate child tab. Terminal control sequences are removed at the viewer sink across read boundaries. Each mirror is capped at 1 MiB and truncates when the cap or stream backpressure is reached. After the run finishes, its viewer returns to the terminal shell instead of ending the terminal session, so the tab and scrollback remain until the user closes them. Successful native Pi runs with a known session append a safely quoted removal command for the exact verified session path; unsuccessful and sessionless runs append only their terminal status.
329
344
 
330
- The observer supports macOS and Linux and is disabled on Windows. It requires executable `orca` on `PATH` (or `PI_SUBAGENT_ORCA_BINARY`) and a running Orca runtime that recognizes the child cwd. Availability and tab creation are best-effort: failures never fail, stop, or delay the subagent. Set `orcaProgressTabs.enabled` to `false` to guarantee that no Orca command or tab is created.
345
+ The observer supports macOS and Linux and is disabled on Windows. It requires executable `orca` on `PATH` (or `PI_SUBAGENT_ORCA_BINARY`) and a running Orca runtime that recognizes the cwd. Availability and tab creation are best-effort: failures never fail, stop, or delay the subagent. When possible, the observer writes a passive manifest under `<worktree>/.pi/subagents/views/orca/`; the manifest is display metadata only, not a lifecycle or control source. Set `orcaProgressTabs.enabled` to `false` to guarantee that no Orca command or tab is created.
331
346
 
332
- Agent profile `runner.type` supports native Pi (the default), `external-cli`, and `external-job`. Orca is intentionally not a profile runner and does not own subagent execution, completion, cancellation, artifacts, or result delivery.
347
+ Agent profile `runner.type` supports native Pi (the default), `external-cli`, and `external-job`. Orca is intentionally not a profile runner and does not own subagent execution, completion, cancellation, artifacts, or result delivery. External-job providers can optionally expose `followUp(input)` so a completed provider job can continue its parent conversation through `subagent({ action: "resume", id: "<run>", message: "..." })`.
333
348
 
334
349
  ## External CLI agent profiles
335
350
 
package/docs/workflows.md CHANGED
@@ -35,7 +35,7 @@ Add `autofix` to `/parallel-review` or `/parallel-cleanup` to apply only the syn
35
35
 
36
36
  ## Scripted workflows (workflowScript)
37
37
 
38
- All model-facing subagent execution is expressed through `workflowScript` in the `subagent` tool. Use stable keys and ordinary JavaScript for one child, sequence, and parallelism. For ordinary parallel fanout, use `await runs.all([{ key, agent, task }, ...])`; do not read `.output` from unawaited `runs.run` launches. Store a `runs.run` promise only when the script later observes it with `await`, `Promise.race`, or `Promise.all`, such as steering a live child before awaiting its result. Scripts are ordinary JavaScript statement bodies. Use an explicit `return` for a useful result:
38
+ All model-facing subagent execution is expressed through `workflowScript` in the `subagent` tool. Use stable keys and ordinary JavaScript for one child, sequence, and parallelism. For ordinary parallel fanout, use `await runs.all([{ key, agent, task }, ...])`. It resolves to an ordered array, not a key map, so use indexes, destructuring, or `.map(...)`, not `results.<key>`. Do not read `.output` from unawaited `runs.run` launches. Store a `runs.run` promise only when the script later observes it with `await`, `Promise.race`, or `Promise.all`, such as steering a live child before awaiting its result. Scripts are ordinary JavaScript statement bodies. Use an explicit `return` for a useful result:
39
39
 
40
40
  Child results cross into the script as plain JSON data. Non-JSON host metadata is omitted, so use returned fields such as `runId`, `ok`, `output`, and `structuredOutput` for workflow control.
41
41
 
@@ -226,6 +226,12 @@ fresh: true
226
226
  Review $@. Return concrete findings with source proof, or state that no issue was found.
227
227
  ```
228
228
 
229
+ For first-pass review prompts, filter by evidence rather than by severity. Ask the
230
+ reviewer to label concrete current findings P0/P1/P2 and end with `Merge verdict:
231
+ BLOCK`, `Merge verdict: OK`, or `Merge verdict: OK with notes`. Reserve
232
+ `blockers only` for final pre-merge re-checks after P1/P2 findings are already
233
+ known, or for explicit emergency hotfix lanes.
234
+
229
235
  ```text
230
236
  /prompt-workflow review-release-candidate v0.51.0
231
237
  ```
package/index.ts CHANGED
@@ -1 +1,10 @@
1
- export { default } from "./src/extension/index.ts";
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import type {} from "./src/types/pi-runtime-compat.d.ts";
3
+
4
+ const registerParentExtension = process.env.PI_SUBAGENT_CHILD === "1"
5
+ ? undefined
6
+ : (await import("./src/extension/index.ts")).default;
7
+
8
+ export default function registerSubagentExtension(pi: ExtensionAPI): void {
9
+ registerParentExtension?.(pi);
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-subagents",
3
- "version": "0.53.0",
3
+ "version": "0.55.0",
4
4
  "description": "Pi extension for single-agent delegation and scripted multi-agent workflows",
5
5
  "author": "Nico Bailon",
6
6
  "license": "MIT",