pi-subagents 0.67.0 → 0.68.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 (120) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/README.md +1 -1
  3. package/docs/agents.md +37 -12
  4. package/docs/configuration.md +61 -19
  5. package/docs/extension-api.md +5 -1
  6. package/docs/missions.md +2 -2
  7. package/docs/models.md +11 -79
  8. package/docs/observability.md +18 -8
  9. package/docs/standalone-background.md +13 -3
  10. package/docs/tool-reference.md +15 -12
  11. package/docs/watchdog.md +10 -12
  12. package/docs/workflows.md +11 -1
  13. package/index.ts +5 -2
  14. package/package.json +4 -2
  15. package/runner-peer-loader.mjs +24 -0
  16. package/runner-peer-preload.mjs +25 -11
  17. package/skills/pi-subagents/SKILL.md +18 -21
  18. package/skills/pi-subagents/references/constraints-and-recipes.md +3 -2
  19. package/skills/pi-subagents/references/execution-controls.md +4 -4
  20. package/skills/pi-subagents/references/management-authoring-rpc.md +0 -1
  21. package/skills/pi-subagents/references/multi-lane-orchestration.md +1 -1
  22. package/skills/pi-subagents/references/prompting-and-roles.md +16 -12
  23. package/skills/pi-subagents/references/review-and-validation.md +3 -3
  24. package/src/agents/agent-management.ts +57 -58
  25. package/src/agents/agent-serializer.ts +4 -3
  26. package/src/agents/agents.ts +184 -71
  27. package/src/agents/chain-serializer.ts +5 -0
  28. package/src/agents/runtime-agent-registry.ts +7 -6
  29. package/src/api/preflight.ts +20 -16
  30. package/src/api/required-child-extensions.ts +6 -0
  31. package/src/extension/config.ts +10 -37
  32. package/src/extension/fanout-child.ts +3 -0
  33. package/src/extension/herdr-pi-bridge.ts +160 -0
  34. package/src/extension/index.ts +42 -31
  35. package/src/extension/public-execution.ts +3 -3
  36. package/src/extension/schemas.ts +16 -5
  37. package/src/extension/tool-description.ts +8 -7
  38. package/src/intercom/native-supervisor-channel.ts +22 -18
  39. package/src/policy/authority.ts +4 -0
  40. package/src/profiles/profiles.ts +12 -6
  41. package/src/runs/background/active-run-index.ts +17 -1
  42. package/src/runs/background/async-execution.ts +309 -126
  43. package/src/runs/background/async-job-tracker.ts +8 -6
  44. package/src/runs/background/async-resume.ts +13 -4
  45. package/src/runs/background/async-status.ts +15 -4
  46. package/src/runs/background/auto-drain.ts +20 -10
  47. package/src/runs/background/binary-bootstrap.ts +5 -0
  48. package/src/runs/background/chain-append.ts +1 -1
  49. package/src/runs/background/chain-root-attachment.ts +14 -33
  50. package/src/runs/background/notify.ts +74 -6
  51. package/src/runs/background/result-files.ts +8 -4
  52. package/src/runs/background/result-watcher.ts +19 -2
  53. package/src/runs/background/run-child-session.ts +20 -29
  54. package/src/runs/background/runner-aliases.ts +4 -33
  55. package/src/runs/background/runner-child-launch.ts +4 -1
  56. package/src/runs/background/runner-child-sessions.ts +2 -2
  57. package/src/runs/background/runner-http-dispatcher.ts +119 -0
  58. package/src/runs/background/scheduled-runs.ts +11 -5
  59. package/src/runs/background/stale-run-reconciler.ts +35 -11
  60. package/src/runs/background/subagent-runner.ts +396 -275
  61. package/src/runs/background/subagent-wait.ts +128 -23
  62. package/src/runs/background/wait-completions.ts +75 -27
  63. package/src/runs/background/wait-subscriptions.ts +9 -3
  64. package/src/runs/background/wait-tool.ts +4 -2
  65. package/src/runs/foreground/async-stop-action.ts +93 -3
  66. package/src/runs/foreground/execution.ts +91 -218
  67. package/src/runs/foreground/foreground-history.ts +2 -1
  68. package/src/runs/foreground/subagent-executor.ts +266 -80
  69. package/src/runs/shared/acceptance.ts +34 -10
  70. package/src/runs/shared/async-status-projection.ts +123 -33
  71. package/src/runs/shared/child-launch-plan.ts +15 -3
  72. package/src/runs/shared/child-launch.ts +19 -6
  73. package/src/runs/shared/child-runtime-config.ts +5 -0
  74. package/src/runs/shared/child-session.ts +94 -50
  75. package/src/runs/shared/child-tool-plan.ts +28 -16
  76. package/src/runs/shared/dynamic-fanout.ts +2 -2
  77. package/src/runs/shared/external-cli-contract.ts +11 -1
  78. package/src/runs/shared/external-cli-preflight.ts +6 -2
  79. package/src/runs/shared/herdr-connection.ts +134 -0
  80. package/src/runs/shared/herdr-external-adapters.ts +169 -0
  81. package/src/runs/shared/herdr-machine.ts +279 -0
  82. package/src/runs/shared/herdr-pi-protocol.ts +59 -0
  83. package/src/runs/shared/herdr-placed-run.ts +263 -0
  84. package/src/runs/shared/model-resolution-diagnostic.ts +76 -0
  85. package/src/runs/shared/{model-fallback.ts → model-resolution.ts} +22 -237
  86. package/src/runs/shared/model-scope.ts +1 -1
  87. package/src/runs/shared/nested-events.ts +11 -2
  88. package/src/runs/shared/parallel-utils.ts +7 -2
  89. package/src/runs/shared/pi-spawn.ts +1 -1
  90. package/src/runs/shared/subagent-prompt-runtime.ts +4 -2
  91. package/src/runs/shared/worktree-setup-command.ts +27 -4
  92. package/src/runs/shared/worktree.ts +3 -3
  93. package/src/shared/child-cache-retention.ts +43 -0
  94. package/src/shared/launch-contract.ts +6 -9
  95. package/src/shared/pruned-fork.ts +1 -1
  96. package/src/shared/required-child-extensions.ts +81 -0
  97. package/src/shared/settings.ts +5 -2
  98. package/src/shared/shortcuts.ts +0 -4
  99. package/src/shared/types.ts +70 -29
  100. package/src/slash/slash-commands.ts +0 -6
  101. package/src/slash/subagents-admin.ts +13 -9
  102. package/src/tui/render.ts +20 -10
  103. package/src/watchdog/child-status.ts +28 -36
  104. package/src/watchdog/lsp-diagnostics.ts +1 -1
  105. package/src/watchdog/model-selection.ts +1 -1
  106. package/src/watchdog/register-child.ts +10 -3
  107. package/src/watchdog/register-main.ts +20 -20
  108. package/src/watchdog/render.ts +1 -1
  109. package/src/watchdog/review.ts +14 -30
  110. package/src/watchdog/rules.ts +1 -1
  111. package/src/watchdog/runtime.ts +23 -12
  112. package/src/watchdog/settings.ts +3 -6
  113. package/src/watchdog/types.ts +3 -5
  114. package/src/watchdog/warning-format.ts +1 -1
  115. package/src/workflows/scripted-workflow.ts +42 -3
  116. package/src/workflows/workflow-receipt.ts +21 -3
  117. package/src/workflows/workflow-resources.ts +13 -2
  118. package/src/runs/shared/model-exclusions.ts +0 -374
  119. package/src/runs/shared/readonly-model-continuation.ts +0 -69
  120. package/src/runs/shared/readonly-session-evidence.ts +0 -307
package/docs/models.md CHANGED
@@ -13,6 +13,8 @@ Builtin agents inherit your current Pi default model. This keeps new installs fr
13
13
 
14
14
  Precedence, strongest first: per-run override → provider-scoped role override → `agentOverrides.<name>.model` → agent frontmatter `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.
15
15
 
16
+ Each launch resolves one model. Provider errors, including HTTP 429 responses, are returned from that model rather than selecting another one. Separately, a verified compaction abort after useful progress may continue the retained child session once on the same resolved model; this lifecycle recovery preserves work and is not model fallback.
17
+
16
18
  Use `model: "inherit"` in agent frontmatter or `agentOverrides.<name>.model` to select the current parent session model explicitly.
17
19
 
18
20
  ## Setting defaults and overrides
@@ -57,7 +59,7 @@ To keep one role definition but configure it differently for work and personal p
57
59
  }
58
60
  ```
59
61
 
60
- The provider key comes from the active parent session model (or an explicit host `preferredProvider`) before fallback selection. Provider-scoped fields layer over the ordinary override in the same settings file; project settings still win over user settings. A fallback attempt does not switch the selected provider configuration.
62
+ The provider key comes from the active parent session model (or an explicit host `preferredProvider`). Provider-scoped fields layer over the ordinary override in the same settings file; project settings still win over user settings.
61
63
 
62
64
  For one run, put the override in the command:
63
65
 
@@ -65,7 +67,7 @@ For one run, put the override in the command:
65
67
  /run reviewer[model=anthropic/claude-sonnet-4:high] "Review this diff"
66
68
  ```
67
69
 
68
- For a persistent role override with a backup model for provider failures:
70
+ For a persistent role override:
69
71
 
70
72
  ```json
71
73
  {
@@ -73,8 +75,7 @@ For a persistent role override with a backup model for provider failures:
73
75
  "agentOverrides": {
74
76
  "reviewer": {
75
77
  "model": "anthropic/claude-sonnet-4",
76
- "thinking": "high",
77
- "fallbackModels": ["openai-codex/gpt-5.6-luna:low"]
78
+ "thinking": "high"
78
79
  }
79
80
  }
80
81
  }
@@ -87,7 +88,7 @@ For a persistent role override with a backup model for provider failures:
87
88
 
88
89
  Set `fast: true` on a run, in agent frontmatter, or in `subagents.agentOverrides.<name>.fast` to request the OpenAI priority service tier for supported native OpenAI-Codex children. This can use a higher quota tier or cost more. It is off by default.
89
90
 
90
- Fast mode fails before launch unless every resolved model candidate is on the allowlist. The current allowlist is `openai-codex/gpt-5.6-luna` and `openai-codex/gpt-5.6-sol`. External runners, Anthropic models, and other providers do not use fast mode.
91
+ Fast mode fails before launch unless the resolved model is on the allowlist. The current allowlist is `openai-codex/gpt-5.6-luna` and `openai-codex/gpt-5.6-sol`. External runners, Anthropic models, and other providers do not use fast mode.
91
92
 
92
93
  ## Recommended model tiering (optional)
93
94
 
@@ -100,76 +101,7 @@ A setup that works well in practice: route agents by task shape instead of runni
100
101
 
101
102
  The routing rule: use the capability tiers (1–3) when the task is well-scoped, and the intent tier (4) when scoping or judging is the task itself.
102
103
 
103
- Give tier-4 agents `fallbackModels` for retryable provider/model failures such as rate-limit, overload, unavailable-model, and provider-reported timeout errors **before any tool activity**. After tool activity, failures remain terminal except for the narrow native read-only HTTP 429 continuation below; the task is never automatically replayed after tool work. Ordinary task failures and the outer run-level `timeoutMs` / `maxRuntimeMs` deadline do not trigger fallback.
104
-
105
- Fallback uses native Pi sessions, not fresh `pi` CLI processes. Even when an exact session file is reopened, normal fallback resubmits the original task; retained history alone does not make automatic continuation after tool work safe.
106
-
107
- Example fallback configuration:
108
-
109
- ```yaml
110
- ---
111
- name: shaper
112
- description: Open-ended design/UX/product/planning agent for ambiguous tasks
113
- model: anthropic/claude-fable-5
114
- thinking: medium
115
- fallbackModels: openai-codex/gpt-5.5:high
116
- ---
117
- ```
118
-
119
- One interaction worth knowing for tier 4: forked context over an Anthropic parent transcript strips the parent's signed thinking blocks from the child session, because a thinking signature cannot be replayed into a branch. The child still runs at its requested thinking level and reasons fresh from its first turn.
120
-
121
- ### Native read-only continuation after HTTP 429
122
-
123
- A native foreground or background child can continue once on an eligible later `fallbackModels` entry after completed read-only tool work and an observed HTTP 429. This is not general mid-run fallback and does not apply to external runners. Current coverage is Pi SDK **0.85.1**, the configured **`baseten` / `openai-completions`** provider and its observed request path, not arbitrary providers, APIs, provider extensions, or error text containing “429”.
124
-
125
- Admission requires the default child factory's owned profile: an explicit allowlist containing only builtin `read` and/or `ls`, no ambient or custom extensions/tools or registered background-work providers, and verified idle settlement and shutdown. Wait, supervisor coordination, nested/fanout work, permissions/watchdogs, structured output, fast mode and configured tool budgets exclude this continuation on both hosts. A read-only role name or prompt alone is not enough; default coordinated profiles are excluded.
126
-
127
- Usage-budget admission differs by host:
128
-
129
- - **Foreground:** any configured usage budget, including a workflow-owned budget, denies continuation because this host does not certify remaining allowance.
130
- - **Native background:** an unexhausted token-only budget can qualify only when the run owner's authoritative ledger has received the current attempt's events and has complete coverage, including concurrent work. Configured cost budgets, missing/unknown usage, or unsupported external/import/dynamic coverage deny continuation. This does not introduce new accounting or renew allowances.
131
-
132
- The child must have an **exact assigned session file**: either valid persisted history or an initially absent assigned file that the SDK initializes and persists during this attempt. In-memory or directory-only storage is insufficient. A missing or changed checkpoint at handoff fails closed; recovery never repairs it or promotes storage. Normal executor launches assign the child file and pass it to the native host; lower-level directory-only launches remain ineligible. No new storage option is needed.
133
-
134
- The next model must resolve through the same configured provider runtime, have the same provider/API and a different, untried model identity, and pass conservative retained-input compatibility checks. Cross-provider candidates are skipped without launch; unknown resolution or unsupported/unknown capacity denies continuation. Both hosts reject images and unknown content; these are conservative checks, not exact token estimates:
135
-
136
- - **Foreground:** accepts text and supported assistant tool-call/result history. Its UTF-8 byte ceiling includes retained history, actual system prompt and tool definitions, 4096 bytes of framing/continuation headroom, and the candidate's full output allowance. Equal-window models can qualify if this bound fits.
137
- - **Native background:** resolves exact registry identities and accepts retained text, thinking and tool-call blocks. It reserves the entire source context window plus retained-context UTF-8 bytes and fixed-prompt bytes, and requires the candidate's positive output allowance to be no larger than the source's. Equal/smaller context windows therefore deny continuation; choose a sufficiently larger same-provider sibling.
138
-
139
- The sibling reopens the **same session/file**, preserving the original task, completed tool results and terminal provider error. Its new prompt is a fixed instruction to continue from those results without restarting or repeating completed work; it does not resubmit the original task. One recovery allowance is shared with compaction-abort recovery and consumed before sibling creation. Any sibling outcome ends recovery, including startup failure, abort or another 429; it cannot cascade into startup fallback or change model exclusions. Cancellation, stop/detach and the original run deadline remain authoritative and are rechecked at handoff. Newly billed attempt usage is aggregated, not historical usage restored from the file.
140
-
141
- For a deliberately non-coordinated reader, merge these existing keys into `~/.pi/agent/extensions/subagent/config.json` (see [configuration.md](configuration.md)):
142
-
143
- ```json
144
- {
145
- "waitTool": { "enabled": false },
146
- "intercomBridge": { "mode": "off" }
147
- }
148
- ```
149
-
150
- These settings affect other children too; do not disable required coordination just to obtain recovery. Define a custom agent using existing frontmatter (replace `model-a` and `model-b` with actual text-capable models in your configured Baseten catalog):
151
-
152
- ```yaml
153
- ---
154
- name: reader
155
- description: Read-only file analysis without coordination
156
- tools: read, ls
157
- extensions:
158
- model: baseten/model-a
159
- fallbackModels: baseten/model-b
160
- systemPromptMode: append
161
- inheritProjectContext: false
162
- inheritGlobalContext: false
163
- inheritSkills: false
164
- allowNestedSubagents: false
165
- async: false
166
- ---
167
- Read the assigned files and return your findings without editing.
168
- ```
169
-
170
- Launch with `subagent({ agent: "reader", task: "Read README.md and summarize it", async: false, context: "fresh", output: false })`. Keep `forceTopLevelAsync` disabled and omit tool/usage budgets and the excluded runtime features above. No new recovery flag is required: these settings make the profile eligible, but continuation still requires actual completed read-only work, observed 429 and all checkpoint/provider/lifecycle checks. This is a trusted-host compatibility boundary, not sandboxing or universal provider attestation.
171
-
172
- For native background execution, use the same call with `async: true`, which overrides the agent's foreground default. Keep the explicit empty `extensions:` field: omitting it allows ambient extensions in background children and does not certify this profile. Select a fallback model satisfying the stricter background capacity bound above; unconfigured budgets are simplest, while token-only budgets still require the authoritative allowance check. Do not disable needed coordination or ambient capabilities merely to obtain continuation.
104
+ Each launch resolves one model and starts the child once. Provider, authentication, quota, rate-limit, stream, empty-response, context-overflow, and provisioning failures are returned from that attempt. To try another model, the parent or operator must issue a later explicit launch.
173
105
 
174
106
  ## Thinking level defaults
175
107
 
@@ -201,7 +133,7 @@ Set `subagents.maxThinking` to enforce a hard maximum for every native Pi child.
201
133
  }
202
134
  ```
203
135
 
204
- 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.
136
+ Requests above the ceiling fail before child startup; the setting covers frontmatter, `agentOverrides`, per-run overrides, parallel/chain children, nested launches, and resumed children. Project settings take precedence over user settings. External runners retain their existing behavior.
205
137
 
206
138
  ## Extension defaults
207
139
 
@@ -276,11 +208,11 @@ To keep subagents inside a budget or compliance profile, enforce a model scope.
276
208
  - `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.
277
209
  - 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.
278
210
  - Models you pass explicitly — the tool-call `model`, `--model`, or a clarify pick — error and abort the run.
279
- - 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.
280
- - 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.
211
+ - By default, models from agent frontmatter, `subagents.defaultModel`, or the inherited parent session model only warn and remain available, so existing configurations keep working while you tighten the scope.
212
+ - Set `strict: true` with `enforce: true` to reject every resolved out-of-scope model, including inherited models.
281
213
  - `enforce: true` requires at least one non-empty global or agent `allow` list; otherwise the config is rejected at load time.
282
214
 
283
- 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.
215
+ 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 from escaping that restriction.
284
216
 
285
217
  `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.
286
218
 
@@ -12,7 +12,7 @@ A background child is a pi session created inside the detached runner process. T
12
12
 
13
13
  Live progress shows compact detail for single, chain, and parallel modes: a bounded one-line task, current tool, recent output, token counts, aggregate cost, duration, activity freshness, current-tool duration, and chain graph metadata when available. Workflow `label` metadata wins over raw task text in compact multi-child cards.
14
14
 
15
- Press Pi's configured expand key (`Ctrl+O` by default) to expand the full streaming view with complete output per step. Running-card hints also advertise `Ctrl+Alt+F` for the Fleet inspector.
15
+ Press Pi's configured expand key (`Ctrl+O` by default) to expand the full streaming view with complete output per step.
16
16
 
17
17
  Sequential chains show a flow line like `done scout → running worker`. Chains with parallel steps show per-step cards instead. Chain status uses `label` and `phase` metadata when present, while falling back to agent names for older chains.
18
18
 
@@ -35,11 +35,22 @@ async subagent worker · background
35
35
  ● Step 1/1: worker · running
36
36
  task: Review authentication boundaries
37
37
  ⎿ read: src/auth.ts | 2.0s
38
- Press configured-expand-key for live detail · Ctrl+Alt+F Fleet
38
+ Press configured-expand-key for live detail
39
39
  ```
40
40
 
41
41
  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.
42
42
 
43
+ In Pi fullscreen mode with mouse dispatch (verified with Pi TUI 0.85.1), left-click
44
+ anywhere on the async widget's header row to fold it into a live one-line status
45
+ summary. Click again to restore the usual layout. No knowledge of extension commands
46
+ or keyboard shortcuts is needed. The summary counts the widget's tracked runs,
47
+ including workflow parents and children, rather than unique agents.
48
+
49
+ Folding stays in effect across progress updates and does not change Pi's global
50
+ expand setting, run execution, or completion notifications. Task rows, drag and
51
+ wheel events, and modifier clicks are left unhandled. The state resets when the
52
+ widget is removed or Pi reloads. Regular mode keeps the existing keyboard controls.
53
+
43
54
  ### Reducing status display noise
44
55
 
45
56
  Chat records tool-call history; FleetView and the async widget show live run/child updates. Separate `subagent({ action: "status", id: "..." })` calls leave separate historical entries even when their `Status target: run …` labels match. A matching run ID identifies the queried run, not the tool call, and is not evidence of duplicate execution. Live Fleet/widget refreshes do not merge those entries.
@@ -55,7 +66,7 @@ For compact chat results with FleetView as the only live editor surface, merge t
55
66
  ```
56
67
 
57
68
  - `inlineToolDisplay: "summary"` keeps one static result row per call, alongside its call heading. A completed status query is not proof that the queried child has finished.
58
- - `fleetView: true` retains live progress. Open `/subagents-fleet` or press `Ctrl+Alt+F` for details instead of repeatedly requesting status just to watch progress. Pi's expand key does not expand summary results; keep `"rich"` if you want expandable inline output.
69
+ - `fleetView: true` retains live progress. Open `/subagents-fleet` for details instead of repeatedly requesting status just to watch progress. Pi's expand key does not expand summary results; keep `"rich"` if you want expandable inline output.
59
70
  - `asyncWidget: false` hides only the additional under-editor async widget, leaving FleetView available. This configuration reduces visible surfaces; it does not guarantee ordering relative to other extensions.
60
71
 
61
72
  Thanks to [DraconDev](https://github.com/DraconDev) for reporting the display noise and suggesting summary mode in [#1931](https://github.com/nicobailon/pi-subagents/issues/1931).
@@ -101,8 +112,6 @@ Default keys:
101
112
 
102
113
  Set `fleetKeybindings` in the extension config to replace inspector-level keys when a terminal intercepts keys such as `PgUp`, `PgDn`, `Home`, or `End`. Prompt modes keep fixed keys such as `Esc`, `Enter`, `Tab`, and stop-confirmation `Y`/`N`.
103
114
 
104
- `Ctrl+Alt+F` opens the same inspector even while a foreground turn is active and slash input is queued.
105
-
106
115
  Enter and `H` use the available Inspect plugin. On macOS with Ghostty 1.3+ (TERM_PROGRAM=ghostty), this includes the other bundled open-only plugin using Ghostty's preview AppleScript API; status and close are unavailable because no binding is written. In a child-specific inspector, type ordinary guidance and press Enter to send it through the acknowledged steer channel; `steer <message>`, `status`, and `stop` remain available as explicit controls. The bundled Herdr plugin uses Herdr 0.7.5+.
107
116
 
108
117
  Without a TUI, `/subagents-fleet` retains the textual `subagent({ action: "status", view: "fleet" })` fallback, and mutations use explicit commands: run `/subagents-stop` and pick from the selector, or use `/subagents-stop <run-id>` / `subagent({ action: "stop", id: "..." })` when you already know the id.
@@ -178,7 +187,6 @@ Async runs write machine-readable lifecycle artifacts for observability and work
178
187
  - `status.json` powers the widget and `subagent({ action: "status" })` output.
179
188
  - `events.jsonl` contains wrapper events plus child Pi JSON events annotated with run and step metadata, including correlated `subagent.steer.requested`, `scheduled`, `routed`, `queued`, `delivered`, `failed`, and `recovered` events plus failure/partial/recovery notices.
180
189
  - `output-<n>.log` is a live human-readable tail.
181
- - Fallback information is persisted so background runs are debuggable after completion.
182
190
 
183
191
  For a top-level async run, `details.asyncDir` points at that directory; the final summary is written to Pi's subagent results directory as `<runId>.json`. Nested async runs use the same shape under the nested async root and are discoverable through status projections that read the nested-run registry. These files are append/update artifacts only; interactive foreground behavior is unchanged.
184
192
 
@@ -205,7 +213,9 @@ stop API.
205
213
 
206
214
  ### Status and result fields
207
215
 
208
- 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.
216
+ 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`/`requestedModel`, `toolCount`, `turnCount`, optional `launchResolvedExtensions`, optional `runtimeAcknowledgedExtensions`, and nested `children` when a child is allowed to launch subagents.
217
+
218
+ `requestedModel` records the launch's requested model (the explicit `--model` override, else the agent's configured model) before registry normalization.
209
219
 
210
220
  `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.
211
221
 
@@ -270,7 +280,7 @@ Debug artifacts live under `{sessionDir}/subagent-artifacts/`, `.pi/subagents/ar
270
280
  - `{runId}_{agent}.jsonl`
271
281
  - `{runId}_{agent}_meta.json`
272
282
 
273
- Metadata records timing, usage, exit code, final model, attempted models, fallback attempt outcomes, and the resolved acceptance ledger with its parsed child report.
283
+ Metadata records timing, usage, exit code, the resolved model, and the resolved acceptance ledger with its parsed child report. A strictly guarded retained-session recovery after a verified compaction abort may continue once on that same model; it never selects another model.
274
284
 
275
285
  For npm package projects, project-scoped artifacts need a `.npmignore` rule (or `.gitignore` when no `.npmignore` exists) or a `files` allowlist that does not include `.pi/subagents/`. pi-subagents warns at launch when these package settings can include the artifacts. Use `artifactDir: "session"` or `"temp"` to keep them outside the package worktree.
276
286
 
@@ -1,11 +1,19 @@
1
1
  # Standalone background execution
2
2
 
3
- Supported standalone target: **official Pi 0.85.1, Linux x64**. Keep its adjacent release assets with the executable. Other versions, operating systems, architectures and packagers are not covered.
3
+ Supported standalone target: **official Pi 0.85.1, Linux x64**. Keep its adjacent release assets with the executable. Other versions, operating systems, architectures and packagers are outside the fully validated support target; limited experimental Windows coverage is described below.
4
4
 
5
5
  Pi's extension loader supplies its embedded SDK to `binary-bootstrap.ts`, which awaits the existing configured runner before exiting. Startup authorization, revival leases, controls, disposal and process-close observation remain shared with npm. Each independent run has its own host; native sessions inside that run share it. No per-session CLI protocol, runtime download/install, alternate SDK or foreground fallback is introduced. Npm Pi keeps its Node runner, peer aliases and detected npm `PI_PACKAGE_DIR` override (including refusal when no npm root exists).
6
6
 
7
7
  Implementation and lifecycle fixtures derive from [@xz-dev](https://github.com/xz-dev)'s [PR #2049](https://github.com/nicobailon/pi-subagents/pull/2049), source commit `910807bfefcf9ee41d73fa25ec86dcd75ab8f4b2` (Xiangzhe, `xiangzhedev@gmail.com`). Integration retains the lifecycle contract and reduces commentary rather than removing its evidence gates.
8
8
 
9
+ ## Experimental Windows host recognition
10
+
11
+ The resolver recognizes Bun's Windows virtual entrypoint prefixes, `B:/~BUN/` and `B:\~BUN\`, alongside `/$bunfs/`. It launches the real `process.execPath` (or the existing executable override). The `B:` prefix is virtual, not the installation drive; `pi-native.exe` is not a required executable name.
12
+
13
+ A local Windows x64 smoke passed with **xz-dev/pi `0.85.1-xz.169.1.gb5f4d0ff`, Bun 1.4.2**: a fresh async worker executed a read-only Git command, returned its result, delivered the native completion notification, and exited with code 0 and no remaining runner process. This is not validation of the official Windows distribution or every Bun-compiled Pi host. Windows remains **experimental**: the full standalone lifecycle matrix has not been validated there.
14
+
15
+ Node-hosted npm Pi keeps its existing runner path and is not affected by this virtual-entrypoint detection defect. Installing only the pi-subagents extension through npm does not change a Bun-compiled Pi host into an npm Pi host.
16
+
9
17
  ## Official binary gate
10
18
 
11
19
  On Linux x64 with Node, npm, tar and bubblewrap installed, provision dependencies and the checksum-pinned release separately from execution:
@@ -31,11 +39,11 @@ For a focused diagnostic, use `node test/smoke/standalone-background.mjs "$relea
31
39
 
32
40
  ## Npm regressions and local trial
33
41
 
34
- Existing npm clean-install CI covers real SDK 0.85.0 and 0.85.1. The standalone CI job also checks the public npm launch path without execution-time network:
42
+ Existing npm clean-install CI covers real SDK 0.85.1. The standalone CI job also checks the public npm launch path without execution-time network:
35
43
 
36
44
  ```bash
37
45
  npm_checks="$(mktemp -d)"
38
- node test/smoke/pi085-clean-install.mjs "$npm_checks/sdk" 0.85.1
46
+ node test/smoke/clean-install.mjs "$npm_checks/sdk" 0.85.1
39
47
  node test/smoke/npm-background.mjs "$npm_checks/sdk" "$npm_checks/launch"
40
48
  ```
41
49
 
@@ -46,4 +54,6 @@ PI_CODING_AGENT_DIR="$(mktemp -d)" "$release_dir/pi/pi" \
46
54
  --no-extensions --no-skills --no-prompt-templates --extension "$PWD/index.ts"
47
55
  ```
48
56
 
57
+ This command targets a source checkout. The published npm package uses the compiled `index.js` entry instead.
58
+
49
59
  Configure a provider in that isolated session, ask for a read-only background child and inspect its notification/run artifacts. This loads only the checkout for that process; it does not install the candidate or reuse normal credentials. Keep the parent alive for notifications.
@@ -12,6 +12,8 @@ Use `{ action: "validate", workflowScript }` to check statically decidable synta
12
12
 
13
13
  Use `workflowScriptPath` instead of `workflowScript` to load the same JavaScript statement body from a file. The two fields are mutually exclusive. Relative paths resolve against the request `cwd`, and absolute paths pass through. The host reads the file before validation, scheduling, or sandbox execution. The workflow sandbox still has no filesystem access. Missing, unreadable, and empty files fail as file input errors.
14
14
 
15
+ Raw inline and file-backed scripts accept bounded plain-JSON `args`, including during `validate` and `schedule.create`. Omitted raw args become `{}`; supplied args are deeply frozen in the sandbox. Normalized args persist in run and schedule evidence for diagnosis and exact replay, so never include secrets. Args are data only and do not grant `runs.host` authority.
16
+
15
17
  For permission-extension interoperability, use one of the package-owned named resources with bounded `args` instead of caller-supplied workflow text:
16
18
 
17
19
  ```js
@@ -22,9 +24,9 @@ For permission-extension interoperability, use one of the package-owned named re
22
24
  The host resolves the script and authority internally and records bounded provenance in workflow details and receipts. Named resources cannot be combined with `agent`, `task`, `workflowScript`, or `workflowScriptPath`; user/project resource registries are not part of this first slice.
23
25
 
24
26
  ```js
25
- { workflowScriptPath: "workflows/review.js", cwd: "/path/to/project" }
26
- { action: "validate", workflowScriptPath: "workflows/review.js" }
27
- { action: "schedule.create", every: "6h", workflowScriptPath: "workflows/review.js" }
27
+ { workflowScriptPath: "workflows/review.js", args: { target: "src/workflows" }, cwd: "/path/to/project" }
28
+ { action: "validate", workflowScriptPath: "workflows/review.js", args: { target: "src/workflows" } }
29
+ { action: "schedule.create", every: "6h", workflowScriptPath: "workflows/review.js", args: { target: "src/workflows" } }
28
30
  ```
29
31
 
30
32
  ```js
@@ -109,15 +111,17 @@ The complete plain-JSON inventory is validated before the first launch (maximum
109
111
  | `lines` | number | `80` | Maximum transcript lines for `action: "status", view: "transcript"`; capped at 500. |
110
112
  | `agentScope` | `user \| project \| both` | `both` | Agent discovery scope. Project wins on collisions. |
111
113
  | `capabilities` | boolean | `false` | With `action: "list"`, return compact prompt-free rows and `details.agentCapabilities` machine-readable records for each agent's declared/default routing capabilities. External CLI rows also include their command and passive local availability. |
112
- | `async` | boolean | default-on | Background execution. Workflows default to background. `async:false` blocks the parent until completion and runs the child as a session inside the parent Pi process; such foreground children never load the parent's ambient extensions, so agents that need MCP tools (`mcpDirectTools`, or MCP tools from an ambient adapter such as pi-mcp-adapter) or models from a provider extension must run as background children, which load them inside the detached runner process. |
114
+ | `async` | boolean | default-on | Background execution. Workflows default to background. `async:false` blocks the parent until completion. A local foreground child runs inside the parent Pi process and never loads the parent's ambient extensions, but it does inherit the providers those extensions registered. A pane-native remote foreground child instead uses the remote machine's provider discovery and configuration. Agents that need MCP tools (`mcpDirectTools`, or MCP tools from an ambient adapter such as pi-mcp-adapter) must run as background children, which load them inside the detached runner process. |
113
115
  | `chatProgress` | `auto \| off \| live-card` | `auto` | WorkflowScript chat projection. `auto` renders a live in-chat card only for watched foreground workflows in the same Git repository, including managed worktrees; it is off otherwise. Explicit `live-card` requires `async:false` and the same Git repository. Async workflows have no inline live card, so omit `chatProgress` or use `auto`/`off`; use `async:false` only when the parent must block. |
114
116
  | `isolation` | `none \| worktree` | - | Workflow child isolation. `none` runs in the shared cwd and does not need Git. `worktree` requires a managed Git worktree. Do not combine it with a contradictory `worktree` value. |
115
117
  | `baseRef` | string | `HEAD` | `HEAD` or a supported named ref such as `refs/heads/release`, `refs/tags/v1`, or `origin/main`. Full 40/64-character commit IDs and revision expressions such as `HEAD~1` are unsupported. The ref must resolve to a commit at worktree allocation; omitted values default to `HEAD` resolved at that time. Source-checkout cleanliness is still checked. For workflowScript, set it on the outer request as a default or on an individual `runs.run`/`runs.all` child to override it. |
116
- | `timeoutMs` / `maxRuntimeMs` | number | config `timeoutMs`, else 30 min foreground / single-agent async | Optional run-level max runtime in milliseconds. When omitted, the global [`timeoutMs`](configuration.md#timeoutms) config provides the default; absent that, foreground and plain single-agent async runs fall back to 30 minutes, while composite async runs (chains, parallel tasks, workflows) stay unbounded at the top level. Expiration of this run-level deadline is terminal and does not trigger `fallbackModels`. |
118
+ | `timeoutMs` / `maxRuntimeMs` | number | config `timeoutMs`, else 30 min foreground / single-agent async | Optional run-level max runtime in milliseconds. When omitted, the global [`timeoutMs`](configuration.md#timeoutms) config provides the default; absent that, foreground and plain single-agent async runs fall back to 30 minutes, while composite async runs (chains, parallel tasks, workflows) stay unbounded at the top level. Expiration of this run-level deadline is terminal. |
117
119
  | `toolTimeoutMs` | number | fast-tool default | Optional positive hard per-tool-call deadline in milliseconds. Precedence: call value → agent frontmatter → config → `PI_SUBAGENT_TOOL_TIMEOUT_MS`. The timer starts on `tool_execution_start`, clears on the matching `tool_execution_end`, and terminates the run with `timedOut: true` if the tool remains open. When omitted, known-fast built-in tools get a five-minute default; long-running tools get attention notices but no hard default. It never extends the run deadline; `contact_supervisor`, `intercom`, and `bg_wait` are exempt. |
120
+ | `checkpointBeforeDeadlineMs` | number | none | Async single-agent runs only. The runner requests that the child "checkpoint and stop" this many milliseconds before the run deadline (finish the current tool call, report changed files, build/test state, remaining work, commit/PR state; start no new work). This best-effort steer uses the normal steering lifecycle at the next tool boundary, so the receipt is visible in status and events; the ordinary deadline kill still applies. Precedence: call value → config `checkpointBeforeDeadlineMs`. Disarmed when the deadline leaves under one second before the checkpoint. |
118
121
  | `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. |
119
122
  | `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. |
120
- | `cwd` | string | runtime cwd | Override working directory. |
123
+ | `cwd` | string | runtime cwd | Override working directory. With `machine`, the directory on that machine. |
124
+ | `machine` | string | - | Herdr saved machine (label or profile id) for external-cli agents; see [agents.md](agents.md#running-external-cli-agents-on-a-herdr-saved-machine). |
121
125
  | `maxOutput` | object | 200KB, 5000 lines | Final output truncation limits. |
122
126
  | `artifacts` | boolean | true | Write debug artifacts. |
123
127
  | `includeProgress` | boolean | false | Include full progress in result. |
@@ -130,7 +134,7 @@ The complete plain-JSON inventory is validated before the first launch (maximum
130
134
 
131
135
  As a conservative orchestration policy, do not set a hard `toolBudget` or 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 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.
132
136
 
133
- 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.
137
+ 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. Request a checkpoint after the current tool returns that records changed files, build/test state, and commit or PR state; for async single-agent runs, set `checkpointBeforeDeadlineMs`, otherwise steer by hand.
134
138
 
135
139
  ### Fork context details
136
140
 
@@ -224,7 +228,6 @@ Agent definitions are not loaded into context by default. Management actions let
224
228
  inheritGlobalContext: false,
225
229
  inheritSkills: false,
226
230
  model: "anthropic/claude-sonnet-4",
227
- fallbackModels: ["openai-codex/gpt-5.6-luna:low", "anthropic/claude-haiku-4-5"],
228
231
  tools: "read, bash, mcp:github/search_repositories",
229
232
  extensions: "",
230
233
  skills: "parallel-scout",
@@ -251,7 +254,7 @@ Agent definitions are not loaded into context by default. Management actions let
251
254
 
252
255
  Rules:
253
256
 
254
- - `capabilities: true` changes `action: "list"` to compact one-line rows and adds `details.agentCapabilities: { agents, restrictedCount, capabilityCeilingSources? }`. Each agent row includes source, aliases, runner type/capabilities, tools, MCP direct tools, mutation tools, model/thinking/fallbacks, default async/timeout, output path/mode, skills/extensions, and whether the current capability ceiling allows execution. External CLI rows include `runner.command`, `runner.available`, and a bounded `runner.unavailableReason` when passive PATH/PATHEXT/X_OK lookup cannot find the command. It never includes an agent's system prompt. Rows show declared/default capabilities and command discoverability, not authentication, version compatibility, or successful launch; launch preflight remains authoritative.
257
+ - `capabilities: true` changes `action: "list"` to compact one-line rows and adds `details.agentCapabilities: { agents, restrictedCount, capabilityCeilingSources? }`. Each agent row includes source, aliases, runner type/capabilities, tools, MCP direct tools, mutation tools, model/thinking, default async/timeout, declared acceptance policy/role, output path/mode, skills/extensions, and whether the current capability ceiling allows execution. External CLI rows include `runner.command`, `runner.available`, and a bounded `runner.unavailableReason` when passive PATH/PATHEXT/X_OK lookup cannot find the command. It never includes an agent's system prompt. Rows show declared/default capabilities and command discoverability, not authentication, version compatibility, or successful launch; launch preflight remains authoritative.
255
258
  - `create` uses `config.scope`, not `agentScope`.
256
259
  - `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.
257
260
  - `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`.
@@ -310,7 +313,7 @@ The manifest stores one of these fail-closed eligibility states: `active` (an ow
310
313
 
311
314
  A failure in the subagent workflow, child launch, prompt runtime, extension loading, or child tooling setup is a lane infrastructure blocker, not permission to silently change execution mode. Stop and report the exact failure, run/status, and repo/cwd/worktree/branch/ref state. Before a same-protocol retry or asking the owner, verify the worktree is clean or capture the partial diff. Retry or fix the `subagent` path only through a clear same-protocol action.
312
315
 
313
- For backlog lanes and other subagent-governed workflows, external/foreground/CLI fallback requires explicit owner approval. Do not silently switch to `interactive_shell`, `pi -ne`, Codex/Claude/Cursor CLI, a foreground agent, or another external mode. `interactive_shell` remains valid when the user explicitly requests visible foreground/CLI work or the task is outside the governed subagent protocol. Pi core may print a generic `pi -ne` extension-load hint; that out-of-repo hint is not protocol-approved fallback. Configured native model/provider fallback remains governed by its own contract.
316
+ For backlog lanes and other subagent-governed workflows, external/foreground/CLI fallback requires explicit owner approval. Do not silently switch to `interactive_shell`, `pi -ne`, Codex/Claude/Cursor CLI, a foreground agent, or another external mode. `interactive_shell` remains valid when the user explicitly requests visible foreground/CLI work or the task is outside the governed subagent protocol. Pi core may print a generic `pi -ne` extension-load hint; that out-of-repo hint is not protocol-approved fallback. A verified compaction abort may continue the retained child once on its already resolved model; it never selects another model.
314
317
 
315
318
  ```ts
316
319
  subagent({ action: "status" })
@@ -410,7 +413,7 @@ Acceptance evidence levels are `auto`, `none`, `attested`, `checked`, and `verif
410
413
  Review is a separate gate configured with `acceptance.review`:
411
414
 
412
415
  - Async, risky, and dynamic writer contexts infer checked evidence plus `review: { agent: "reviewer", required: true }`.
413
- - Reviewer/read-only calls infer no acceptance by default; explicit acceptance requests still apply.
416
+ - Tasks classified as read-only infer no acceptance by default, including reviews of release, migration, or security work; those topics do not turn a read-only task into implementation. With role metadata omitted, unknown risk-topic tasks retain their gate even when the agent name suggests a reviewer. Explicit acceptance requests still apply.
414
417
  - Normal writer tasks infer checked evidence without review.
415
418
 
416
419
  Agent frontmatter or `subagents.agentOverrides` may set `acceptanceRole: "read-only" | "writer"` for ambiguous tasks. Explicit task mutation or no-edit intent wins over that role, while omitted metadata preserves the existing reviewer/scout/worker name heuristics. The role affects acceptance inference only and does not change tool access.
@@ -486,7 +489,7 @@ async: true
486
489
 
487
490
  Supported: status artifacts, stdout/stderr logs, timeout, and stop. Full stdout and stderr are written to log files, while the in-memory final stdout response and stderr error are limited to their last 64 KiB.
488
491
 
489
- Intentionally unsupported: native Pi child options such as model override, structured output, acceptance/agent contract, tool budgets, fast mode, fork context, skills, or native Pi tools unless the runner explicitly implements them. Foreground/clarify, steer/resume/interrupt-as-pause, nested subagents, and fallback models are also unsupported.
492
+ Intentionally unsupported: native Pi child options such as model override, structured output, acceptance/agent contract, tool budgets, fast mode, fork context, skills, or native Pi tools unless the runner explicitly implements them. Foreground/clarify, steer/resume/interrupt-as-pause, and nested subagents are also unsupported.
490
493
 
491
494
  ## Session sharing
492
495
 
package/docs/watchdog.md CHANGED
@@ -6,7 +6,7 @@ The watchdog is an opt-in second model that reviews what the agent just did and
6
6
 
7
7
  | Timing | Trigger | Gate | Delivery |
8
8
  |---|---|---|---|
9
- | Boundary review | `agent_end` of every main or child turn | Repo changed | Steered into the transcript; the agent gets one continuation, then that turn is reviewed again |
9
+ | Boundary review | `agent_end` of every main or child turn | Repo changed | Routed by finding importance; high is steered to the model, low/medium are persisted for the user only |
10
10
  | Main activity review | `agent_end`, with `clarification: true` | New delivered orchestration evidence; at most one additional review per user prompt | Same warning/clarification path, even without local edits |
11
11
  | Cadence review | Every `cadence.everyNTools` tool results, minimum 5 | Opt-in | Steered after the current tool, before the next step |
12
12
  | LSP pre-pass | Before boundary review | Changed TypeScript/JavaScript files | Diagnostics become watchdog findings without a model call |
@@ -38,37 +38,37 @@ That means: main every 10 tools, worker every 5, other children every 20, review
38
38
 
39
39
  ## What you see
40
40
 
41
- Every finding is an ordinary transcript message: expandable, scrollable, and persisted in session JSONL. A clean review shows nothing.
41
+ Every finding requires `importance: low | medium | high`. Low and medium are persisted for the user but excluded from model context and continuations. High findings retain model-visible delivery. Severity independently controls thresholds and acceptance, so a low-importance blocker still blocks acceptance. Clean reviews show nothing.
42
42
 
43
43
  ```
44
44
  you ─▶ agent turn ─▶ edits repo ─▶ agent_end ─▶ watchdog review
45
45
  ├─ clean: turn ends
46
- └─ warning: steered in; agent continues once
46
+ └─ warning: low/medium user entry, or high steered message
47
47
  ```
48
48
 
49
- Collapsed warnings show the title and evidence line. Expanded warnings show evidence, recommended action, category, and source:
49
+ Collapsed warnings show the title and evidence line. Expanded warnings show evidence, recommended action, importance, category, and source:
50
50
 
51
51
  ```
52
52
  ● Subagent watchdog Blocker (displayed): Claims tests passed without running them
53
53
  Evidence: The transcript claims `npm test` passed but no test command appears in the tool log.
54
54
  Recommended action: Run the focused test before finishing.
55
- Category: Test Gap · Source: main
55
+ Importance: High · Category: Test Gap · Source: main
56
56
  ```
57
57
 
58
58
  When consecutive boundary reviews raise the same warning, the agent is not making progress. After `stalemateRepeats` identical warnings in a row (default 3), the warning is shown as `stalemate`, no continuation is triggered, and the turn ends. Your next prompt resets the count.
59
59
 
60
60
  Child watchdog findings are lifted into the parent in three ways:
61
61
 
62
- - The result envelope contains `watchdog.warnings` with severity, category, summary, evidence, recommended action, `addressed`, and `stalemate`, bounded to the last 20.
62
+ - Internal/user inspection retains the last 20 findings, including importance and full details. Parent model results may include only high-importance findings.
63
63
  - The acceptance runtime check `watchdog-blocker` fails on blockers that are unaddressed or stalemate.
64
- - Completion notices include `Watchdog blockers:` lines, and Fleet/status views show `wd:<n>` plus `resolve watchdog blockers`.
64
+ - Completion notices may include high-importance concerns and blockers; low/medium finding text is omitted.
65
65
 
66
66
  `/subagents-watchdog status` shows setting sources, enabled state, runtime state, review trigger, scope, cadence, LSP status, selected model/thinking, child overrides, timeout, stalemate count, launch-rule count, review backend, last warning, changed paths, and config errors when present.
67
67
 
68
68
  ## What the reviewer is given
69
69
 
70
70
  - **Turn delta** with changed repo paths. Over-long input keeps the first 6,000 characters and the tail.
71
- - **Current scope** (`scope.enabled`, default on): bounded real user prompts. Side questions are additive; only explicit changes supersede older requirements.
71
+ - **Current scope** (`scope.enabled`, default on): bounded real user prompts. Side questions are additive; only explicit changes supersede older requirements. Scope survives compaction within the current session.
72
72
  - **`watchdog_diff`** when inside git: diff since the session-start commit, including later commits, plus untracked paths to inspect with `read`; accepts `path` and `stat:true`.
73
73
  - **`WATCHDOG.md`** standing instructions, read fresh on every review: `<project>/.pi/WATCHDOG.md` first, then `~/.pi/agent/WATCHDOG.md`, capped at 8,000 characters. Set `guidance.watchdogMd: false` to ignore them.
74
74
  - **LSP diagnostics** from `typescript-language-server`, auto-detected in `node_modules/.bin` or `PATH`; it is never installed and never run over the whole workspace. Errors become blockers, warnings concerns, and info/hints stay in status.
@@ -108,9 +108,7 @@ When a main watchdog model is configured (including a session override), recomme
108
108
 
109
109
  Omit `main.model` to inherit the session model and thinking level. A `main.model` without a thinking suffix or `main.thinking` runs with thinking off, so prefer `:high` for the strong pairing.
110
110
 
111
- Set `fallbackModels` in JSON settings on `main`, `children`, or `children.overrides.<agent>` to opt into an ordered fallback chain, for example `"fallbackModels": ["openai-codex/gpt-5.5:high"]`. Child overrides win over `children.fallbackModels`; neither inherits the main watchdog's chain. Arrays replace across user project session settings, and `[]` clears an inherited chain. Status shows configured chains.
112
-
113
- Unavailable configured candidates are skipped and resolved duplicates are tried once. Each attempt uses a fresh reviewer with its own model auth, provider stream, and thinking; an inherited primary keeps the actual session model/thinking, while fallbacks use explicit-model thinking rules. Fallback follows normal subagent provider-failure semantics (including rate limits, quota, auth, unavailability, and provider timeouts), **only before any tool work**, including read-only inspection. Clean/normal completion, length limits, findings, clarification, cancellation, and the overall watchdog deadline never trigger fallback. All attempts share the original deadline; exhaustion remains a failed review. With no fallback chain, existing single-model behavior is unchanged.
111
+ The watchdog resolves one reviewer model and makes one review call. Unavailable models fail visibly; rate limits, quota, authentication, provider timeouts, findings, clarification, cancellation, and the overall watchdog deadline never switch models automatically. An inherited model keeps the current session model and thinking level.
114
112
 
115
113
  Agents can call `subagent({ action: "watchdog.recommend-model" })` and `subagent({ action: "watchdog.configure", model: "recommended", scope: "session" | "user" | "project" })`. They should use `scope: "session"` unless you ask for a lasting default.
116
114
 
@@ -140,7 +138,7 @@ Reviews retain the existing `agentEndTimeoutMs`. Questions and evidence are capp
140
138
 
141
139
  ## Child watchdogs
142
140
 
143
- Opt in under `subagents.watchdog.children`. `model`, `fallbackModels`, and `thinking` set the default child watchdog; `overrides.<agent>` can set `model`, `fallbackModels`, `thinking`, `enabled`, or `cadence` per role.
141
+ Opt in under `subagents.watchdog.children`. `model` and `thinking` set the default child watchdog; `overrides.<agent>` can set `model`, `thinking`, `enabled`, or `cadence` per role.
144
142
 
145
143
  ## Launch rules
146
144
 
package/docs/workflows.md CHANGED
@@ -25,7 +25,7 @@ A failure in the subagent workflow, child launch, prompt runtime, extension load
25
25
 
26
26
  Stop and report the exact failure, run/status, and repository/cwd/worktree/branch/ref state. Before a same-protocol retry or asking the owner, verify the worktree is clean or capture the partial diff. Retry or fix the `subagent` path only through a clear same-protocol action. For backlog lanes and other subagent-governed workflows, external/foreground/CLI fallback requires explicit owner approval. `interactive_shell` remains valid when the user explicitly requests visible foreground/CLI work or the task is outside the governed subagent protocol.
27
27
 
28
- Pi core may print a generic `pi -ne` extension-load hint; that out-of-repo hint is not protocol-approved fallback. Configured native model/provider fallback remains governed by its own contract and does not authorize an execution-mode switch.
28
+ Pi core may print a generic `pi -ne` extension-load hint; that out-of-repo hint is not protocol-approved fallback. A verified compaction abort may continue the retained child once on its already resolved model; it does not authorize an execution-mode or model switch.
29
29
 
30
30
  ## Prompt shortcuts
31
31
 
@@ -69,6 +69,16 @@ subagent({ action: "validate", workflowScriptPath: "workflows/review.js" });
69
69
 
70
70
  The fields are mutually exclusive. Relative paths resolve against the request `cwd`; absolute paths pass through. The host reads the file before validation, schedule creation, or workflow sandbox execution. The sandbox still has no filesystem access. Missing, unreadable, and empty files return file input errors instead of script syntax errors.
71
71
 
72
+ Inline and file-backed scripts accept bounded plain-JSON `args`:
73
+
74
+ ```js
75
+ subagent({ workflowScriptPath: "workflows/review.js", args: { target: "src/workflows" } });
76
+ // workflows/review.js
77
+ return runs.run("review", { agent: "reviewer", task: `Review ${args.target}` });
78
+ ```
79
+
80
+ Omitted arguments are an empty object. The `args` object, its nested objects, and its arrays are frozen in the sandbox. Arguments are data only: they do not grant `runs.host` or other authority. Normalized arguments are persisted with workflow and schedule evidence for replay and diagnosis, so do not put secrets in them. Routine status text does not render argument values.
81
+
72
82
  ### Named workflow resources for permission extensions
73
83
 
74
84
  Use a named workflow resource when a permission or policy extension needs to distinguish extension-resolved workflow content from raw model-authored scripts:
package/index.ts CHANGED
@@ -1,10 +1,13 @@
1
1
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
2
  import type {} from "./src/types/pi-runtime-compat.d.ts";
3
+ import { HERDR_PI_MODE_ENV } from "./src/runs/shared/herdr-pi-protocol.ts";
3
4
 
4
- const registerParentExtension = process.env.PI_SUBAGENT_CHILD === "1"
5
+ const registerExtension = process.env[HERDR_PI_MODE_ENV] === "1"
6
+ ? (await import("./src/extension/herdr-pi-bridge.ts")).default
7
+ : process.env.PI_SUBAGENT_CHILD === "1"
5
8
  ? undefined
6
9
  : (await import("./src/extension/index.ts")).default;
7
10
 
8
11
  export default function registerSubagentExtension(pi: ExtensionAPI): void {
9
- registerParentExtension?.(pi);
12
+ registerExtension?.(pi);
10
13
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-subagents",
3
- "version": "0.67.0",
3
+ "version": "0.68.0",
4
4
  "description": "Pi extension for single-agent delegation and scripted multi-agent workflows",
5
5
  "author": "Nico Bailon",
6
6
  "license": "MIT",
@@ -14,6 +14,7 @@
14
14
  "./delegation": "./src/api/delegation.ts",
15
15
  "./capability-ceiling": "./src/api/capability-ceiling.ts",
16
16
  "./workflow-resources": "./src/api/workflow-resources.ts",
17
+ "./required-child-extensions": "./src/api/required-child-extensions.ts",
17
18
  "./preflight": "./src/api/preflight.ts",
18
19
  "./control-channel": "./src/api/control-channel.ts",
19
20
  "./intercom-bridge": "./src/api/intercom-bridge.ts",
@@ -53,6 +54,8 @@
53
54
  "CHANGELOG.md"
54
55
  ],
55
56
  "scripts": {
57
+ "build:pkg": "node scripts/build-package.mjs",
58
+ "pack:pkg": "npm run build:pkg && npm pack ./dist-pkg",
56
59
  "typecheck": "tsc --noEmit",
57
60
  "test": "npm run test:unit",
58
61
  "test:unit": "node --experimental-strip-types --import ./test/support/isolated-temp-root.mjs --test test/unit/*.test.ts",
@@ -91,7 +94,6 @@
91
94
  }
92
95
  },
93
96
  "dependencies": {
94
- "@earendil-works/pi-server": "0.85.0",
95
97
  "acorn": "8.18.0",
96
98
  "jiti": "2.7.0",
97
99
  "typebox": "1.1.38",
@@ -0,0 +1,24 @@
1
+ import { pathToFileURL } from "node:url";
2
+
3
+ let aliases = {};
4
+ let nativeRunner = false;
5
+ let compiledRunner = false;
6
+ let packageRootUrl;
7
+ const redirected = new Set([
8
+ "@earendil-works/pi-tui",
9
+ ]);
10
+
11
+ export function initialize(data) {
12
+ aliases = data?.aliases ?? {};
13
+ nativeRunner = data?.nativeRunner === true;
14
+ compiledRunner = data?.compiledRunner === true;
15
+ packageRootUrl = data?.packageRootUrl;
16
+ }
17
+
18
+ export function resolve(specifier, context, nextResolve) {
19
+ const packageImport = typeof packageRootUrl === "string" && context.parentURL?.startsWith(packageRootUrl) === true;
20
+ if (nativeRunner && (!compiledRunner || packageImport) ? aliases[specifier] : redirected.has(specifier) && aliases[specifier]) {
21
+ return nextResolve(pathToFileURL(aliases[specifier]).href, context);
22
+ }
23
+ return nextResolve(specifier, context);
24
+ }