pi-subagents 0.66.0 → 0.67.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 +68 -0
- package/README.md +4 -3
- package/agents/evidence-auditor.md +34 -0
- package/agents/reviewer.md +3 -2
- package/docs/agents.md +6 -3
- package/docs/configuration.md +7 -5
- package/docs/extension-api.md +33 -18
- package/docs/missions.md +8 -0
- package/docs/models.md +1 -1
- package/docs/observability.md +4 -4
- package/docs/standalone-background.md +49 -0
- package/docs/tool-reference.md +18 -8
- package/docs/watchdog.md +35 -4
- package/docs/workflows.md +26 -12
- package/inspector-runner.mjs +2 -2
- package/package.json +1 -1
- package/prompts/parallel-review.md +1 -1
- package/{runner-server-preload.mjs → runner-peer-preload.mjs} +8 -3
- package/skills/pi-subagents/SKILL.md +14 -0
- package/skills/pi-subagents/references/execution-controls.md +7 -5
- package/skills/pi-subagents/references/prompting-and-roles.md +2 -2
- package/src/agents/advertised-agent-prompt.ts +34 -3
- package/src/agents/agents.ts +6 -0
- package/src/agents/builtin-names.ts +1 -0
- package/src/api/delegation.ts +4 -0
- package/src/api/preflight.ts +76 -45
- package/src/api/shared-types.ts +2 -0
- package/src/extension/fanout-child.ts +63 -4
- package/src/extension/index.ts +20 -8
- package/src/extension/public-execution.ts +4 -2
- package/src/extension/rpc.ts +4 -0
- package/src/extension/schemas.ts +67 -78
- package/src/extension/tool-description.ts +29 -82
- package/src/inspectors/actions.ts +148 -0
- package/src/inspectors/ghostty/actions.ts +74 -0
- package/src/inspectors/ghostty/plugin.ts +17 -0
- package/src/inspectors/herdr/actions.ts +99 -179
- package/src/inspectors/herdr/plugin.ts +20 -0
- package/src/inspectors/herdr/project-panes.ts +1 -1
- package/src/inspectors/{herdr/inspector-runner.ts → inspector-runner.ts} +12 -12
- package/src/inspectors/plugins.ts +8 -0
- package/src/inspectors/{herdr/session-roots-codec.ts → session-roots-codec.ts} +3 -14
- package/src/inspectors/types.ts +51 -0
- package/src/intercom/intercom-bridge.ts +50 -8
- package/src/intercom/native-supervisor-channel.ts +22 -13
- package/src/runs/background/active-async-capacity.ts +4 -0
- package/src/runs/background/async-execution.ts +45 -56
- package/src/runs/background/async-resume.ts +5 -9
- package/src/runs/background/auto-drain.ts +6 -3
- package/src/runs/background/binary-bootstrap.ts +33 -0
- package/src/runs/background/fleet-view.ts +30 -2
- package/src/runs/background/notify.ts +31 -1
- package/src/runs/background/owned-process-tree.ts +29 -2
- package/src/runs/background/run-child-session.ts +61 -4
- package/src/runs/background/run-status.ts +3 -0
- package/src/runs/background/runner-aliases.ts +11 -3
- package/src/runs/background/runner-child-launch.ts +2 -0
- package/src/runs/background/runner-child-sessions.ts +5 -4
- package/src/runs/background/scheduled-runs.ts +40 -13
- package/src/runs/background/steering.ts +20 -2
- package/src/runs/background/subagent-runner.ts +47 -31
- package/src/runs/background/subagent-wait.ts +51 -8
- package/src/runs/background/wait-tool.ts +1 -1
- package/src/runs/foreground/async-steering-action.ts +18 -7
- package/src/runs/foreground/execution.ts +44 -31
- package/src/runs/foreground/prompt-audit.ts +3 -1
- package/src/runs/foreground/subagent-executor.ts +110 -100
- package/src/runs/foreground/workflow-detach-reconcile.ts +2 -0
- package/src/runs/foreground/workflow-foreground-steering.ts +2 -1
- package/src/runs/shared/acceptance.ts +5 -2
- package/src/runs/shared/async-status-projection.ts +4 -0
- package/src/runs/shared/capability-ceiling.ts +2 -0
- package/src/runs/shared/child-hooks.ts +25 -10
- package/src/runs/shared/child-launch.ts +12 -2
- package/src/runs/shared/child-lifecycle.ts +6 -3
- package/src/runs/shared/child-runtime-config.ts +3 -1
- package/src/runs/shared/child-session.ts +33 -2
- package/src/runs/shared/child-tool-plan.ts +122 -3
- package/src/runs/shared/completion-guard.ts +5 -3
- package/src/runs/shared/effective-system-prompt.ts +33 -0
- package/src/runs/shared/external-cli-runner.ts +9 -7
- package/src/runs/shared/llm-intent-arbiter.ts +12 -3
- package/src/runs/shared/model-fallback.ts +2 -0
- package/src/runs/shared/orca-progress-tabs.ts +1 -1
- package/src/runs/shared/pi-spawn.ts +10 -0
- package/src/runs/shared/subagent-prompt-runtime.ts +9 -3
- package/src/runs/shared/task-intent.ts +46 -13
- package/src/runs/shared/workflow-async-child-guidance.ts +18 -0
- package/src/runs/shared/worktree.ts +42 -12
- package/src/shared/fork-context.ts +15 -72
- package/src/shared/launch-contract.ts +65 -2
- package/src/shared/opencode-session-headers.ts +30 -0
- package/src/shared/types.ts +4 -1
- package/src/slash/delegation-adapters.ts +3 -1
- package/src/slash/delegation-request.ts +14 -0
- package/src/slash/slash-commands.ts +2 -1
- package/src/slash/subagents-admin.ts +11 -4
- package/src/tui/fleet-status.ts +164 -19
- package/src/tui/fleet.ts +16 -14
- package/src/tui/render.ts +149 -28
- package/src/watchdog/child-status.ts +8 -0
- package/src/watchdog/model-selection.ts +20 -0
- package/src/watchdog/permission-arbiter.ts +3 -1
- package/src/watchdog/register-child.ts +1 -0
- package/src/watchdog/register-main.ts +31 -27
- package/src/watchdog/review.ts +132 -67
- package/src/watchdog/runtime.ts +82 -20
- package/src/watchdog/scope.ts +1 -1
- package/src/watchdog/settings.ts +9 -3
- package/src/watchdog/tool-actions.ts +13 -12
- package/src/watchdog/turn-delta.ts +23 -0
- package/src/watchdog/types.ts +4 -0
- package/src/workflows/scripted-workflow.ts +237 -7
- package/src/workflows/workflow-checklist.ts +2 -2
- /package/src/inspectors/{herdr/shell-command.ts → shell-command.ts} +0 -0
package/docs/watchdog.md
CHANGED
|
@@ -7,10 +7,11 @@ The watchdog is an opt-in second model that reviews what the agent just did and
|
|
|
7
7
|
| Timing | Trigger | Gate | Delivery |
|
|
8
8
|
|---|---|---|---|
|
|
9
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 |
|
|
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 |
|
|
10
11
|
| Cadence review | Every `cadence.everyNTools` tool results, minimum 5 | Opt-in | Steered after the current tool, before the next step |
|
|
11
12
|
| LSP pre-pass | Before boundary review | Changed TypeScript/JavaScript files | Diagnostics become watchdog findings without a model call |
|
|
12
13
|
|
|
13
|
-
Boundary reviews coalesce a turn's edits into one final-state review. Unchanged or reverted diffs are skipped
|
|
14
|
+
Boundary reviews coalesce a turn's edits into one final-state review. Unchanged or reverted diffs are skipped unless the main-only activity opt-in below admits new evidence; `.pi/subagents/` and `tmp/` artifacts remain excluded. In orchestrated runs, each writing child reviews its own worktree and the parent reviews the aggregate diff after child changes land. There are no idle timer reviews. Cadence monitoring is inspired by [Scopey](https://github.com/ArchAstro/scopey).
|
|
14
15
|
|
|
15
16
|
Children get the same boundary, cadence, and LSP behavior. Child cadence resolves from `children.overrides.<agent>.cadence`, then `children.cadence`, then top-level `cadence`:
|
|
16
17
|
|
|
@@ -67,7 +68,7 @@ Child watchdog findings are lifted into the parent in three ways:
|
|
|
67
68
|
## What the reviewer is given
|
|
68
69
|
|
|
69
70
|
- **Turn delta** with changed repo paths. Over-long input keeps the first 6,000 characters and the tail.
|
|
70
|
-
- **Current scope** (`scope.enabled`, default on): bounded real user prompts
|
|
71
|
+
- **Current scope** (`scope.enabled`, default on): bounded real user prompts. Side questions are additive; only explicit changes supersede older requirements.
|
|
71
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`.
|
|
72
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.
|
|
73
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.
|
|
@@ -87,7 +88,9 @@ One model setting serves both boundary and cadence reviews per endpoint. Use a s
|
|
|
87
88
|
/subagents-watchdog on
|
|
88
89
|
```
|
|
89
90
|
|
|
90
|
-
|
|
91
|
+
When a main watchdog model is configured (including a session override), recommendations keep that model and its effective thinking level rather than judging its strength or independence. An unavailable or unauthenticated configured model is reported, not replaced. Without a configured main model, the recommendation remains Opus 4.8 or GPT 5.5 at thinking high, whichever your main session is not using and is authenticated.
|
|
92
|
+
|
|
93
|
+
`session model recommended` changes only this session. `model recommended` explicitly saves the recommendation to **user settings**, affecting other projects without overrides; it does not change project settings. Project and session overrides still take precedence. Use an explicit model to replace a configured choice. Saving a model does not enable the watchdog; use `on` separately.
|
|
91
94
|
|
|
92
95
|
```json
|
|
93
96
|
{
|
|
@@ -105,11 +108,39 @@ The recommendation is Opus 4.8 or GPT 5.5 at thinking high, whichever your main
|
|
|
105
108
|
|
|
106
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.
|
|
107
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.
|
|
114
|
+
|
|
108
115
|
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.
|
|
109
116
|
|
|
117
|
+
## Optional main-session clarification
|
|
118
|
+
|
|
119
|
+
Use `watchdog_warn` directly for evidence-backed reminders of forgotten authorized work; a question is not a prerequisite. Distinguish forgotten work from dependencies still pending or explicit holds. Use clarification when task status or intent is genuinely unclear. The orchestrator remains owner of its task/lane board.
|
|
120
|
+
|
|
121
|
+
With this opt-in, completed `turn_end` events retain a recent actual-activity tail: paired calls/results for `subagent` dispatch (no action), `subagent` actions `status`, `resume`, `interrupt`, `steer`, `stop`, `bg_wait`, and `subagent_supervisor` actions `pending`, `list`, `reply`. Pairing requires the same tool name and exact tool-call ID; raw results, unrelated tool names and watchdog management actions do not qualify. Each activity entry is bounded to 3,000 characters, with a 6,000-character recent tail retained across ordinary new prompts and skipped edit boundaries. Session replacement, compaction, shutdown or disabling clears it. This is observed text, not an inferred task board.
|
|
122
|
+
|
|
123
|
+
New unreviewed activity permits at most one additional boundary review per user prompt even with no local edit. Side questions keep earlier authorized task evidence available; they do not themselves trigger a model call. Activity gathered after that prompt's extra review remains available for the next prompt. Warning continuations cannot supply fresh triggering activity. No polling, task scheduling, cross-worktree scans or idle calls are added.
|
|
124
|
+
|
|
125
|
+
**Visibility limit:** external task/gate completions are visible when returned through those parent tool results. Standalone native completion notifications, arbitrary custom messages, direct shell/CI output, and events not delivered to the parent through these contracts are not ingested by this activity tail. Existing scope retains at most eight prompts (2,000 characters each); new streaming user input cancels an active review but is not added to scope unless `before_agent_start` fires. Reminders depend on retained evidence and model judgment, not an exhaustive view of running work.
|
|
126
|
+
|
|
127
|
+
Set `subagents.watchdog.clarification: true` in Pi settings alongside `enabled: true`. It defaults to `false` and applies **only to the main watchdog**, not child watchdogs or child permission arbitration.
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{ "subagents": { "watchdog": { "enabled": true, "clarification": true } } }
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
At an eligible activity or repo-edit boundary, the reviewer may use `watchdog_ask` for one focused question when missing orchestrator context prevents a concrete judgment. It cannot ask during cadence reviews, after an accepted warning, or during stalemate. There is at most one question per real user prompt.
|
|
134
|
+
|
|
135
|
+
The tool **yields and ends that review**. A visible question with concrete evidence steers the main session into Pi's native automatic continuation after the boundary hook returns. The orchestrator handles the context as needed and continues; no answer, receipt, deadline or follow-up review is required or tracked. Questions are **not approval, permission, or warnings**.
|
|
136
|
+
|
|
137
|
+
Asking consumes the current review evidence, so an unchanged Git-backed boundary does not immediately review it again. Later reviews use the normal edit, cadence and bounded activity triggers, with the same read-only tools, warning thresholds, budgets and stalemate protections. Non-Git observed edits can also prompt a question: there is no cross-answer evidence guarantee to verify. Disabling watchdog or clarification, new user input, model changes and session lifecycle resets cancel applicable active reviews and suppress stale results; already delivered questions remain ordinary transcript messages.
|
|
138
|
+
|
|
139
|
+
Reviews retain the existing `agentEndTimeoutMs`. Questions and evidence are capped at 1,000 and 2,000 characters; scope, activity and delta share the existing 24,000-character input limit. Enabled cost adds at most one activity boundary review and one question-triggered continuation per prompt, not a dedicated answer review. Disabled execution does not collect activity or add polling, model calls or reviewer prompt/tool content. Child warning messaging and permission decisions remain unchanged.
|
|
140
|
+
|
|
110
141
|
## Child watchdogs
|
|
111
142
|
|
|
112
|
-
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.
|
|
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.
|
|
113
144
|
|
|
114
145
|
## Launch rules
|
|
115
146
|
|
package/docs/workflows.md
CHANGED
|
@@ -45,6 +45,10 @@ Add `autofix` to `/parallel-review` or `/parallel-cleanup` to apply only the syn
|
|
|
45
45
|
|
|
46
46
|
Use direct `{ agent, task }` for one bounded child. Use `workflowScript` when the parent needs a stable keyed child, sequence, fanout, steering, retry, or aggregation. For ordinary parallel fanout, use `await runs.all([{ key, agent, task }, ...])`. It resolves to an ordered array, not a key map, so use indexes, destructuring, or `.map(...)`, not `results.<key>`. Do not read `.output` from unawaited `runs.run` launches. Store a `runs.run` promise only when the script later observes it with `await`, `Promise.race`, or `Promise.all`, such as steering a live child before awaiting its result. Scripts are ordinary JavaScript statement bodies. Use an explicit `return` for a useful result:
|
|
47
47
|
|
|
48
|
+
For multi-step or parallel work, make exactly one top-level `subagent` workflow call with `async:true` and launch children only inside it. Read this guide for recipes rather than constructing a second top-level orchestration. Available sandbox helpers include `runs.run`, `runs.all`, `runs.lanes`, `runs.steer`, `runs.status`, `runs.ref`/`runs.refs`, `emit`, `console`, standard JavaScript, and mission `state` when enabled. No filesystem, shell, arbitrary Pi tools, or host globals are available; named resources alone may grant `runs.host` authority.
|
|
49
|
+
|
|
50
|
+
Workflow-level child controls default onto each `runs.run`/`runs.all` launch; explicit child fields override them. See [retained children](tool-reference.md#retained-children) for follow-up challenges, [output binding](tool-reference.md#output-mode-details) for durable artifacts, and [schedules](missions.md#schedules) for delayed/recurring scripts.
|
|
51
|
+
|
|
48
52
|
Child results cross into the script as plain JSON data. Non-JSON host metadata is omitted, so use returned fields such as `runId`, `ok`, `output`, and `structuredOutput` for workflow control.
|
|
49
53
|
|
|
50
54
|
Validate a script without launching children:
|
|
@@ -104,10 +108,10 @@ The result is `{ ok, errors }`. Invalid scripts return a tool error and include
|
|
|
104
108
|
|
|
105
109
|
```js
|
|
106
110
|
subagent({ workflowScript: `
|
|
107
|
-
const scan = await runs.run("scan", { agent: "scout", task: "Scan the codebase" });
|
|
111
|
+
const scan = await runs.run("scan", { label: "Map codebase behavior", agent: "scout", task: "Scan the codebase" });
|
|
108
112
|
const reviews = await runs.all([
|
|
109
|
-
{ key: "correctness", agent: "reviewer", task: "Review correctness: " + scan.output },
|
|
110
|
-
{ key: "tests", agent: "reviewer", task: "Review tests: " + scan.output }
|
|
113
|
+
{ key: "correctness", label: "Review codebase correctness", agent: "reviewer", task: "Review correctness: " + scan.output },
|
|
114
|
+
{ key: "tests", label: "Review test coverage", agent: "reviewer", task: "Review tests: " + scan.output }
|
|
111
115
|
]);
|
|
112
116
|
return reviews.map(result => result.output);
|
|
113
117
|
` });
|
|
@@ -118,7 +122,7 @@ Keep helper functions portable across Node and Bun. Use top-level `await`, plain
|
|
|
118
122
|
```js
|
|
119
123
|
subagent({ workflowScript: `
|
|
120
124
|
function scan() {
|
|
121
|
-
return runs.run("scan", { agent: "scout", task: "Scan the codebase" });
|
|
125
|
+
return runs.run("scan", { label: "Map codebase behavior", agent: "scout", task: "Scan the codebase" });
|
|
122
126
|
}
|
|
123
127
|
const result = await scan();
|
|
124
128
|
return result.output;
|
|
@@ -129,8 +133,8 @@ Chaining is still supported. The supported form is scripted chaining: await one
|
|
|
129
133
|
|
|
130
134
|
```js
|
|
131
135
|
subagent({ workflowScript: `
|
|
132
|
-
const plan = await runs.run("plan", { agent: "scout", task: "Plan the migration" });
|
|
133
|
-
const patch = await runs.run("patch", { agent: "worker", task: "Implement this plan:\n" + plan.output });
|
|
136
|
+
const plan = await runs.run("plan", { label: "Plan migration behavior", agent: "scout", task: "Plan the migration" });
|
|
137
|
+
const patch = await runs.run("patch", { label: "Implement migration behavior", agent: "worker", task: "Implement this plan:\n" + plan.output });
|
|
134
138
|
return patch.output;
|
|
135
139
|
` });
|
|
136
140
|
```
|
|
@@ -145,16 +149,16 @@ subagent({ workflowScript: `
|
|
|
145
149
|
{
|
|
146
150
|
key: "api",
|
|
147
151
|
stages: [
|
|
148
|
-
{ key: "writer", agent: "worker", task: "Implement the API change" },
|
|
149
|
-
{ key: "challenge", resume: "previous", task: "Challenge the API implementation" },
|
|
150
|
-
{ key: "review", agent: "reviewer", task: "Review the API lane" }
|
|
152
|
+
{ key: "writer", label: "Implement API behavior", agent: "worker", task: "Implement the API change" },
|
|
153
|
+
{ key: "challenge", label: "Challenge API behavior", resume: "previous", task: "Challenge the API implementation" },
|
|
154
|
+
{ key: "review", label: "Review API behavior", agent: "reviewer", task: "Review the API lane" }
|
|
151
155
|
]
|
|
152
156
|
},
|
|
153
157
|
{
|
|
154
158
|
key: "ui",
|
|
155
159
|
stages: [
|
|
156
|
-
{ key: "writer", agent: "worker", task: "Implement the UI change" },
|
|
157
|
-
{ key: "review", agent: "reviewer", task: "Review the UI lane" }
|
|
160
|
+
{ key: "writer", label: "Implement UI behavior", agent: "worker", task: "Implement the UI change" },
|
|
161
|
+
{ key: "review", label: "Review UI behavior", agent: "reviewer", task: "Review the UI lane" }
|
|
158
162
|
]
|
|
159
163
|
}
|
|
160
164
|
]);
|
|
@@ -203,7 +207,7 @@ subagent({ workflowScript: `
|
|
|
203
207
|
` });
|
|
204
208
|
```
|
|
205
209
|
|
|
206
|
-
The receipt state is `queued`, `delivered`, `missed`, or `failed`. `delivered` means the child Pi
|
|
210
|
+
The receipt state is `queued`, `delivered`, `missed`, or `failed`. For an async child, `delivered` means it consumed the correlated user input; for a foreground child, it means the in-process Pi transport accepted the input. It does not mean the model followed it. `missed` means the keyed child became terminal or had no live route before delivery. This first slice uses the existing foreground and async steering transports but does not start steering recovery. Workflow traces include one steering attempt entry and one receipt entry.
|
|
207
211
|
|
|
208
212
|
Always await or return a `runs.steer` promise. The workflow waits for an observed steering side effect to settle before it exits and rejects fire-and-forget calls. Use ordinary `Promise.race` when the first child or steering receipt should advance the script. There is no callback API or child inbox access.
|
|
209
213
|
|
|
@@ -380,6 +384,8 @@ Each child uses the existing worktree lifecycle: it branches from clean HEAD, jo
|
|
|
380
384
|
|
|
381
385
|
A top-level `{ workflowScript, worktree: true }` makes isolation the default for every workflow child. An individual child can override that default with `worktree: false`. Keep one writer when parallel writes are not intentionally isolated.
|
|
382
386
|
|
|
387
|
+
Before a materialized `runs.run` or `runs.all` group dispatches fresh children, isolated sources must be Git repositories with clean working trees (excluding `.pi/subagents/` runtime state). A rejected group dispatches no children and spends no fan-out slots or child output claims; key-level failure traces can remain. Checks are shared only within that group, are cancellable, and run again at allocation because sources can change. Retained resumes keep their stored contracts. Select the correct cwd or arrange an operator-approved commit/stash; isolation is never dropped automatically.
|
|
388
|
+
|
|
383
389
|
Use `baseRef` to branch managed worktrees from `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. For example, `{ workflowScript, worktree: true, baseRef: "refs/heads/release" }` applies the release ref to children unless a child supplies its own `baseRef`. If omitted, the default `HEAD` is resolved at worktree allocation, not when the script is validated or a schedule is created. The source checkout must still be clean, and the ref must resolve to a commit before any worktree is allocated.
|
|
384
390
|
|
|
385
391
|
Configure the worktree provider, native path layout, base directory, and setup hook in [configuration.md](configuration.md).
|
|
@@ -439,6 +445,14 @@ Children should not ask for clarification when the only conflict is review-only/
|
|
|
439
445
|
|
|
440
446
|
The parent replies with `subagent_supervisor({ action: "reply", replyTo, message })` or checks pending requests with `subagent_supervisor({ action: "pending" })`. Supervisor messages are scoped to the exact Pi session id that spawned the child. A second Pi session in the same repository does not receive those requests.
|
|
441
447
|
|
|
448
|
+
A nested coordinator needs both directions of coordination. If its agent declares an explicit `tools` allowlist, include `subagent_supervisor` to answer its own children, alongside `subagent` for delegation and `contact_supervisor` for asking its parent:
|
|
449
|
+
|
|
450
|
+
```yaml
|
|
451
|
+
tools: read, subagent, contact_supervisor, subagent_supervisor
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
For A → B → C, C's request belongs to B, not A. B can escalate a separate question to A with `contact_supervisor`, then answer C using C's original `replyTo` request id. A's reply to B does not resolve C's request, and steering is not a substitute for replying. Only fanout-authorized children get the downward supervisor provider; explicit tool exclusions and capability ceilings still apply, and ordinary leaves do not gain delegation or reply tools. Requesting `subagent_supervisor` without fanout authorization fails at launch with an actionable error. A coordinator that excludes the reply tool does not start downward supervision or receive prompts to use it. Explicitly selected native coordination tools survive host-builtin filtering because their providers are child runtime hooks, not host builtins.
|
|
455
|
+
|
|
442
456
|
Child-side routine completion handoffs are not expected. If a child appears stalled, needs-attention notices show up in the parent session with useful next actions, such as checking `subagent({ action: "status" })`, interrupting the run, or nudging the child.
|
|
443
457
|
|
|
444
458
|
If a `workflowScript` child detaches through `contact_supervisor`, the enclosing async workflow stays `paused` until that child exits. Then the extension reconciles it to `complete` or `failed`. Wait on the child until that happens.
|
package/inspector-runner.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createJiti } from "jiti";
|
|
2
2
|
|
|
3
3
|
const jiti = createJiti(import.meta.url);
|
|
4
|
-
const { runInspector } = await jiti.import("./src/inspectors/
|
|
4
|
+
const { runInspector } = await jiti.import("./src/inspectors/inspector-runner.ts");
|
|
5
5
|
|
|
6
6
|
try {
|
|
7
7
|
runInspector();
|
|
8
8
|
} catch (cause) {
|
|
9
|
-
process.stderr.write(`
|
|
9
|
+
process.stderr.write(`Inspector failed: ${cause instanceof Error ? cause.message : String(cause)}\n`);
|
|
10
10
|
process.exitCode = 1;
|
|
11
11
|
}
|
package/package.json
CHANGED
|
@@ -28,7 +28,7 @@ Choose or adapt angles when the work calls for it:
|
|
|
28
28
|
|
|
29
29
|
Prefer three strong reviewers over many vague reviewers.
|
|
30
30
|
|
|
31
|
-
Give every reviewer a specific task prompt naming its angle. Ask reviewers to return concise, evidence-backed findings with file/line references and suggested fixes. Filter on evidence, not severity: a finding must be concrete
|
|
31
|
+
Give every reviewer a specific task prompt naming its angle. Ask reviewers to return concise, evidence-backed findings with file/line references and suggested fixes. Filter on evidence, not severity: a finding must be concrete and current within the named review target, and supported by source proof, a test or repro, or a contract contradiction. For a diff review, require that the issue is caused or made reachable by that diff. Label findings P0/P1/P2. P0 blocks merge. P1 should be fixed before release. P2 is report-only. End each review with `Merge verdict: BLOCK`, `Merge verdict: OK`, or `Merge verdict: OK with notes`. If nothing qualifies, ask the reviewer to say exactly `No issues found.` The response should be review feedback, not a context summary. Reviewers must not edit files unless I explicitly ask for a writer pass.
|
|
32
32
|
|
|
33
33
|
Do not default first-pass reviews to `blockers only`. That phrase is valid only for final pre-merge re-checks after P1/P2 findings are already inventoried, or for explicit emergency hotfix lanes where non-blocking findings are intentionally deferred.
|
|
34
34
|
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
// Only loaded when the parent supplies Pi 0.85.0's missing server exports.
|
|
2
1
|
import { registerHooks } from "node:module";
|
|
3
2
|
import { pathToFileURL } from "node:url";
|
|
4
3
|
|
|
5
|
-
const aliases = JSON.parse(process.env.JITI_ALIAS);
|
|
4
|
+
const aliases = JSON.parse(process.env.JITI_ALIAS ?? "{}");
|
|
5
|
+
const redirected = new Set([
|
|
6
|
+
"@earendil-works/pi-server",
|
|
7
|
+
"@earendil-works/pi-server/unix",
|
|
8
|
+
"@earendil-works/pi-tui",
|
|
9
|
+
]);
|
|
10
|
+
|
|
6
11
|
registerHooks({
|
|
7
12
|
resolve(specifier, context, nextResolve) {
|
|
8
|
-
if (specifier
|
|
13
|
+
if (redirected.has(specifier) && aliases[specifier]) {
|
|
9
14
|
return nextResolve(pathToFileURL(aliases[specifier]).href, context);
|
|
10
15
|
}
|
|
11
16
|
return nextResolve(specifier, context);
|
|
@@ -50,6 +50,18 @@ use ordinary `runs.run(...)` / `runs.all(...)`. See the [canonical staged-lane
|
|
|
50
50
|
example](../../docs/workflows.md#parallel-sequential-lanes). Keep assignments
|
|
51
51
|
bounded, but do not add stages or ceremony just to satisfy this skill.
|
|
52
52
|
|
|
53
|
+
When composing `runs.run(...)`, `runs.all(...)`, or `runs.lanes(...)`, always
|
|
54
|
+
supply a short verb + behavior display `label` derived from the task, unless
|
|
55
|
+
the user supplied an explicit label; preserve that label. Keep the stable
|
|
56
|
+
machine `key` independent (for example, `issue2011-writer` with
|
|
57
|
+
`label: "Fix workflow steering"`). For `runs.lanes`, put labels on stage
|
|
58
|
+
items, not lane objects. Use stage-appropriate labels for reviews and retained-child
|
|
59
|
+
follow-ups too (for example, `Review workflow steering`). Generate labels in
|
|
60
|
+
the orchestrator while composing the launch—no extra model call, runtime
|
|
61
|
+
generator, or schema change. Native direct `{ agent, task }` calls have no
|
|
62
|
+
top-level `label` parameter; do not invent one or wrap a tiny single task in
|
|
63
|
+
a workflow just to label it.
|
|
64
|
+
|
|
53
65
|
Use async/background by default. Set `async:false` only when the parent must
|
|
54
66
|
block. Final reviews, validation gates, oracle checks, and publication checks
|
|
55
67
|
stay async.
|
|
@@ -71,6 +83,8 @@ that runner explicitly supports the option.
|
|
|
71
83
|
|
|
72
84
|
## Read the reference for the branch
|
|
73
85
|
|
|
86
|
+
For exact API fields and worked examples, call `subagent({action:"guide",topic:"tool-reference"})` or `topic:"workflows"`. The compact tool definition is not the recipe catalog; use `topic:"missions"` for mission updates and schedules.
|
|
87
|
+
|
|
74
88
|
| Branch | Read |
|
|
75
89
|
| --- | --- |
|
|
76
90
|
| Delegate or choose roles, prompts, models, or slash commands | `references/prompting-and-roles.md` |
|
|
@@ -83,10 +83,10 @@ lanes, or a fanout that the parent will consume together.
|
|
|
83
83
|
```js
|
|
84
84
|
subagent({
|
|
85
85
|
workflowScript: `
|
|
86
|
-
const scan = await runs.run("scan", { agent: "scout", task: "Map the target" });
|
|
86
|
+
const scan = await runs.run("scan", { label: "Map target behavior", agent: "scout", task: "Map the target" });
|
|
87
87
|
const reviews = await runs.all([
|
|
88
|
-
{ key: "correctness", agent: "reviewer", task: "Review correctness: " + scan.output },
|
|
89
|
-
{ key: "tests", agent: "reviewer", task: "Review tests: " + scan.output }
|
|
88
|
+
{ key: "correctness", label: "Review target correctness", agent: "reviewer", task: "Review correctness: " + scan.output },
|
|
89
|
+
{ key: "tests", label: "Review target test coverage", agent: "reviewer", task: "Review tests: " + scan.output }
|
|
90
90
|
]);
|
|
91
91
|
return reviews.map(result => result.output);
|
|
92
92
|
`
|
|
@@ -109,6 +109,7 @@ Terminal async workflows also persist `workflow-receipt.json` beside `status.jso
|
|
|
109
109
|
|
|
110
110
|
```js
|
|
111
111
|
return runs.run("cross-oracle", {
|
|
112
|
+
label: "Challenge proposed direction",
|
|
112
113
|
resume: { workflowRunId: "<pass-1-workflow-id>", key: "advisor-oracle", latest: true },
|
|
113
114
|
task: "Review the focused challenge packet."
|
|
114
115
|
});
|
|
@@ -120,7 +121,8 @@ Keyed resume reads that one exact receipt and revalidates the retained run at la
|
|
|
120
121
|
|
|
121
122
|
For a broad plan with a known set of narrow, visible stages per lane, use
|
|
122
123
|
`runs.lanes(...)` inside a `workflowScript`; it is a nested helper, not a
|
|
123
|
-
top-level `subagent` mode. Give each lane and stage a stable key
|
|
124
|
+
top-level `subagent` mode. Give each lane and stage a stable key; give stage
|
|
125
|
+
items a short verb + behavior `label`, preserving explicit user labels. The first
|
|
124
126
|
stage from every lane is launched together, then later stages sequence per lane.
|
|
125
127
|
`resume: "previous"` requires the retained predecessor, and a failed or blocked
|
|
126
128
|
stage blocks only that lane. The returned board exposes lane/stage results for
|
|
@@ -338,7 +340,7 @@ subagent({ action: "steer", id: "abc123", mode: "follow_up", message: "After thi
|
|
|
338
340
|
subagent({ action: "steer", id: "abc123", mode: "auto", message: "Switch to the failing test now." })
|
|
339
341
|
```
|
|
340
342
|
|
|
341
|
-
|
|
343
|
+
For async runs, `delivered` records that the child consumed the correlated user input; foreground `delivered` records in-process transport acceptance. Neither is proof of model compliance. A live foreground follow-up acknowledgment reports `queued`, meaning Pi accepted it into its follow-up queue, not that it was delivered. The foreground transport does not provide a later correlated queued-to-delivered receipt.
|
|
342
344
|
|
|
343
345
|
## Watchdog
|
|
344
346
|
|
|
@@ -63,7 +63,7 @@ Council advisors are read-only. User or project `council-*` profiles choose allo
|
|
|
63
63
|
|
|
64
64
|
### Parallel review technique
|
|
65
65
|
|
|
66
|
-
Use this when the user wants adversarial review of a diff, plan, issue, file, or implemented work. Launch fresh-context `reviewer` agents with distinct angles generated from the actual target. Common angles are correctness/regressions, tests/validation, and simplicity/maintainability; adapt for TypeScript, UI, security, docs, or large structural changes. Reviewers should inspect files and diffs directly, return concise evidence-backed findings with file/line references, and avoid edits unless the user explicitly asks for a writer pass. Filter on evidence, not severity: report
|
|
66
|
+
Use this when the user wants adversarial review of a diff, plan, issue, file, or implemented work. Launch fresh-context `reviewer` agents with distinct angles generated from the actual target. Common angles are correctness/regressions, tests/validation, and simplicity/maintainability; adapt for TypeScript, UI, security, docs, or large structural changes. Reviewers should inspect files and diffs directly, return concise evidence-backed findings with file/line references, and avoid edits unless the user explicitly asks for a writer pass. Filter on evidence, not severity: report concrete current issues within the named review target, with source proof, a test or repro, or a contract contradiction. For a diff review, require that the issue is caused or made reachable by that diff. Label findings P0/P1/P2 and end with `Merge verdict: BLOCK`, `Merge verdict: OK`, or `Merge verdict: OK with notes`. Use `blockers only` only for final pre-merge re-checks after P1/P2 findings are already captured, or for explicit emergency hotfix lanes where non-blocking findings are intentionally deferred. For targeted follow-up, ask only whether the named finding was resolved, whether the fix introduced a new defect in the fix blast radius, and whether prior P1/P2 notes still stand. For bot or PR-comment triage, classify each comment as VALID, STALE, INVALID, or OUT-OF-POLICY against current HEAD, then assign P0/P1/P2 only to VALID comments. The parent synthesizes fixes worth doing now, optional improvements, and feedback to ignore/defer before applying anything.
|
|
67
67
|
|
|
68
68
|
### Proactive skill-specialist technique
|
|
69
69
|
|
|
@@ -283,7 +283,7 @@ Keep the parent/orchestrator on the ordinary strong default model because omissi
|
|
|
283
283
|
|
|
284
284
|
Examples are illustrative, not requirements. Map these tiers to concrete models in user/project settings or a profile. A non-OpenAI setup should choose comparable available models by capability.
|
|
285
285
|
|
|
286
|
-
Use `fallbackModels` when a tier has provider quota or availability risk.
|
|
286
|
+
Use `fallbackModels` when a tier has provider quota or availability risk. Forked children keep their requested thinking level even when provider-specific reasoning blocks are stripped from the inherited transcript.
|
|
287
287
|
|
|
288
288
|
If a provider rejects model IDs with thinking suffixes, use
|
|
289
289
|
`subagents.disableThinking: true` in user or project settings to clear bundled
|
|
@@ -57,7 +57,38 @@ export function buildAdvertisedAgentPrompt(
|
|
|
57
57
|
return render(entries);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
export function appendAdvertisedAgentPrompt(systemPrompt: string, advertisedPrompt: string | undefined): string
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
export function appendAdvertisedAgentPrompt(systemPrompt: string, advertisedPrompt: string | undefined): string;
|
|
61
|
+
export function appendAdvertisedAgentPrompt(systemPrompt: string[], advertisedPrompt: string | undefined): string[];
|
|
62
|
+
export function appendAdvertisedAgentPrompt(systemPrompt: undefined, advertisedPrompt: string | undefined): string | undefined;
|
|
63
|
+
export function appendAdvertisedAgentPrompt(
|
|
64
|
+
systemPrompt: string | string[] | undefined,
|
|
65
|
+
advertisedPrompt: string | undefined,
|
|
66
|
+
): string | string[] | undefined;
|
|
67
|
+
export function appendAdvertisedAgentPrompt(
|
|
68
|
+
systemPrompt: string | string[] | undefined,
|
|
69
|
+
advertisedPrompt: string | undefined,
|
|
70
|
+
): string | string[] | undefined {
|
|
71
|
+
if (Array.isArray(systemPrompt)) {
|
|
72
|
+
let changed = false;
|
|
73
|
+
const cleaned = systemPrompt
|
|
74
|
+
.map((part) => {
|
|
75
|
+
if (typeof part !== "string") return part;
|
|
76
|
+
const stripped = part.replace(ADVERTISED_AGENTS_BLOCK, "");
|
|
77
|
+
if (stripped !== part) changed = true;
|
|
78
|
+
return stripped;
|
|
79
|
+
})
|
|
80
|
+
.filter((b) => typeof b === "string" && b.length > 0);
|
|
81
|
+
|
|
82
|
+
if (advertisedPrompt) {
|
|
83
|
+
return [...cleaned, advertisedPrompt];
|
|
84
|
+
}
|
|
85
|
+
return changed ? cleaned : systemPrompt;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (typeof systemPrompt === "string") {
|
|
89
|
+
const base = systemPrompt.replace(ADVERTISED_AGENTS_BLOCK, "");
|
|
90
|
+
return advertisedPrompt ? (base.trim() ? `${base.trimEnd()}\n\n${advertisedPrompt}` : advertisedPrompt) : base;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return advertisedPrompt;
|
|
63
94
|
}
|
package/src/agents/agents.ts
CHANGED
|
@@ -181,6 +181,12 @@ export interface AgentConfig {
|
|
|
181
181
|
override?: BuiltinAgentOverrideInfo;
|
|
182
182
|
modelSource?: AgentModelSourceInfo;
|
|
183
183
|
maxThinking?: ThinkingLevel;
|
|
184
|
+
/**
|
|
185
|
+
* Digest of the parsed definition, set when a runtime overlay such as the
|
|
186
|
+
* Intercom bridge rewrites launch-affecting fields. Launch identity reads
|
|
187
|
+
* this instead of re-hashing the overlaid copy.
|
|
188
|
+
*/
|
|
189
|
+
definitionDigest?: string;
|
|
184
190
|
}
|
|
185
191
|
|
|
186
192
|
type ProjectRootResolution = "nearest" | "git-root";
|
package/src/api/delegation.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { IntercomBridgeConfig } from "../shared/types.ts";
|
|
2
|
+
|
|
1
3
|
// This is the established extension-to-extension transport. The structured
|
|
2
4
|
// delegation API intentionally reuses it instead of adding a second event
|
|
3
5
|
// protocol. Unstructured legacy direct payloads are rejected.
|
|
@@ -35,6 +37,8 @@ export interface SubagentDelegationRequest {
|
|
|
35
37
|
toolBudget?: SubagentDelegationToolBudget;
|
|
36
38
|
skill?: string | string[] | boolean;
|
|
37
39
|
artifacts?: boolean;
|
|
40
|
+
/** Per-launch bridge config; replaces the global `intercomBridge` config. Pass the same value to preflight to compare digests. */
|
|
41
|
+
intercomBridge?: IntercomBridgeConfig;
|
|
38
42
|
result: SubagentDelegationResultRequest;
|
|
39
43
|
}
|
|
40
44
|
|