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.
- package/CHANGELOG.md +70 -0
- package/README.md +1 -1
- package/docs/agents.md +37 -12
- package/docs/configuration.md +61 -19
- package/docs/extension-api.md +5 -1
- package/docs/missions.md +2 -2
- package/docs/models.md +11 -79
- package/docs/observability.md +18 -8
- package/docs/standalone-background.md +13 -3
- package/docs/tool-reference.md +15 -12
- package/docs/watchdog.md +10 -12
- package/docs/workflows.md +11 -1
- package/index.ts +5 -2
- package/package.json +4 -2
- package/runner-peer-loader.mjs +24 -0
- package/runner-peer-preload.mjs +25 -11
- package/skills/pi-subagents/SKILL.md +18 -21
- package/skills/pi-subagents/references/constraints-and-recipes.md +3 -2
- package/skills/pi-subagents/references/execution-controls.md +4 -4
- package/skills/pi-subagents/references/management-authoring-rpc.md +0 -1
- package/skills/pi-subagents/references/multi-lane-orchestration.md +1 -1
- package/skills/pi-subagents/references/prompting-and-roles.md +16 -12
- package/skills/pi-subagents/references/review-and-validation.md +3 -3
- package/src/agents/agent-management.ts +57 -58
- package/src/agents/agent-serializer.ts +4 -3
- package/src/agents/agents.ts +184 -71
- package/src/agents/chain-serializer.ts +5 -0
- package/src/agents/runtime-agent-registry.ts +7 -6
- package/src/api/preflight.ts +20 -16
- package/src/api/required-child-extensions.ts +6 -0
- package/src/extension/config.ts +10 -37
- package/src/extension/fanout-child.ts +3 -0
- package/src/extension/herdr-pi-bridge.ts +160 -0
- package/src/extension/index.ts +42 -31
- package/src/extension/public-execution.ts +3 -3
- package/src/extension/schemas.ts +16 -5
- package/src/extension/tool-description.ts +8 -7
- package/src/intercom/native-supervisor-channel.ts +22 -18
- package/src/policy/authority.ts +4 -0
- package/src/profiles/profiles.ts +12 -6
- package/src/runs/background/active-run-index.ts +17 -1
- package/src/runs/background/async-execution.ts +309 -126
- package/src/runs/background/async-job-tracker.ts +8 -6
- package/src/runs/background/async-resume.ts +13 -4
- package/src/runs/background/async-status.ts +15 -4
- package/src/runs/background/auto-drain.ts +20 -10
- package/src/runs/background/binary-bootstrap.ts +5 -0
- package/src/runs/background/chain-append.ts +1 -1
- package/src/runs/background/chain-root-attachment.ts +14 -33
- package/src/runs/background/notify.ts +74 -6
- package/src/runs/background/result-files.ts +8 -4
- package/src/runs/background/result-watcher.ts +19 -2
- package/src/runs/background/run-child-session.ts +20 -29
- package/src/runs/background/runner-aliases.ts +4 -33
- package/src/runs/background/runner-child-launch.ts +4 -1
- package/src/runs/background/runner-child-sessions.ts +2 -2
- package/src/runs/background/runner-http-dispatcher.ts +119 -0
- package/src/runs/background/scheduled-runs.ts +11 -5
- package/src/runs/background/stale-run-reconciler.ts +35 -11
- package/src/runs/background/subagent-runner.ts +396 -275
- package/src/runs/background/subagent-wait.ts +128 -23
- package/src/runs/background/wait-completions.ts +75 -27
- package/src/runs/background/wait-subscriptions.ts +9 -3
- package/src/runs/background/wait-tool.ts +4 -2
- package/src/runs/foreground/async-stop-action.ts +93 -3
- package/src/runs/foreground/execution.ts +91 -218
- package/src/runs/foreground/foreground-history.ts +2 -1
- package/src/runs/foreground/subagent-executor.ts +266 -80
- package/src/runs/shared/acceptance.ts +34 -10
- package/src/runs/shared/async-status-projection.ts +123 -33
- package/src/runs/shared/child-launch-plan.ts +15 -3
- package/src/runs/shared/child-launch.ts +19 -6
- package/src/runs/shared/child-runtime-config.ts +5 -0
- package/src/runs/shared/child-session.ts +94 -50
- package/src/runs/shared/child-tool-plan.ts +28 -16
- package/src/runs/shared/dynamic-fanout.ts +2 -2
- package/src/runs/shared/external-cli-contract.ts +11 -1
- package/src/runs/shared/external-cli-preflight.ts +6 -2
- package/src/runs/shared/herdr-connection.ts +134 -0
- package/src/runs/shared/herdr-external-adapters.ts +169 -0
- package/src/runs/shared/herdr-machine.ts +279 -0
- package/src/runs/shared/herdr-pi-protocol.ts +59 -0
- package/src/runs/shared/herdr-placed-run.ts +263 -0
- package/src/runs/shared/model-resolution-diagnostic.ts +76 -0
- package/src/runs/shared/{model-fallback.ts → model-resolution.ts} +22 -237
- package/src/runs/shared/model-scope.ts +1 -1
- package/src/runs/shared/nested-events.ts +11 -2
- package/src/runs/shared/parallel-utils.ts +7 -2
- package/src/runs/shared/pi-spawn.ts +1 -1
- package/src/runs/shared/subagent-prompt-runtime.ts +4 -2
- package/src/runs/shared/worktree-setup-command.ts +27 -4
- package/src/runs/shared/worktree.ts +3 -3
- package/src/shared/child-cache-retention.ts +43 -0
- package/src/shared/launch-contract.ts +6 -9
- package/src/shared/pruned-fork.ts +1 -1
- package/src/shared/required-child-extensions.ts +81 -0
- package/src/shared/settings.ts +5 -2
- package/src/shared/shortcuts.ts +0 -4
- package/src/shared/types.ts +70 -29
- package/src/slash/slash-commands.ts +0 -6
- package/src/slash/subagents-admin.ts +13 -9
- package/src/tui/render.ts +20 -10
- package/src/watchdog/child-status.ts +28 -36
- package/src/watchdog/lsp-diagnostics.ts +1 -1
- package/src/watchdog/model-selection.ts +1 -1
- package/src/watchdog/register-child.ts +10 -3
- package/src/watchdog/register-main.ts +20 -20
- package/src/watchdog/render.ts +1 -1
- package/src/watchdog/review.ts +14 -30
- package/src/watchdog/rules.ts +1 -1
- package/src/watchdog/runtime.ts +23 -12
- package/src/watchdog/settings.ts +3 -6
- package/src/watchdog/types.ts +3 -5
- package/src/watchdog/warning-format.ts +1 -1
- package/src/workflows/scripted-workflow.ts +42 -3
- package/src/workflows/workflow-receipt.ts +21 -3
- package/src/workflows/workflow-resources.ts +13 -2
- package/src/runs/shared/model-exclusions.ts +0 -374
- package/src/runs/shared/readonly-model-continuation.ts +0 -69
- 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`)
|
|
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
|
|
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
|
|
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
|
-
|
|
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,
|
|
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
|
|
280
|
-
- Set `strict: true` with `enforce: true` to reject every resolved out-of-scope model
|
|
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
|
|
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
|
|
package/docs/observability.md
CHANGED
|
@@ -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.
|
|
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
|
|
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`
|
|
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`/`
|
|
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,
|
|
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
|
|
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.
|
|
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/
|
|
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.
|
package/docs/tool-reference.md
CHANGED
|
@@ -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
|
|
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
|
|
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.
|
|
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
|
|
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.
|
|
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
|
-
-
|
|
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
|
|
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 |
|
|
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
|
|
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:
|
|
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
|
-
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
|
|
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
|
-
|
|
12
|
+
registerExtension?.(pi);
|
|
10
13
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-subagents",
|
|
3
|
-
"version": "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
|
+
}
|