pi-subagents 0.64.0 → 0.65.1
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 +65 -0
- package/README.md +2 -2
- package/agents/reviewer.md +1 -1
- package/agents/scout.md +1 -1
- package/docs/agents.md +19 -17
- package/docs/configuration.md +23 -15
- package/docs/extension-api.md +18 -6
- package/docs/missions.md +2 -0
- package/docs/observability.md +10 -12
- package/docs/tool-reference.md +15 -8
- package/docs/watchdog.md +1 -1
- package/docs/workflows.md +13 -3
- package/package.json +5 -4
- package/runner-server-preload.mjs +13 -0
- package/skills/pi-subagents/SKILL.md +2 -1
- package/skills/pi-subagents/references/constraints-and-recipes.md +1 -1
- package/skills/pi-subagents/references/execution-controls.md +7 -3
- package/skills/pi-subagents/references/multi-lane-orchestration.md +2 -0
- package/src/agents/agent-management.ts +47 -15
- package/src/api/capability-ceiling.ts +0 -1
- package/src/api/{pi-args.ts → child-tool-plan.ts} +1 -1
- package/src/api/preflight.ts +7 -4
- package/src/extension/config.ts +4 -2
- package/src/extension/doctor.ts +2 -10
- package/src/extension/fanout-child.ts +9 -11
- package/src/extension/index.ts +58 -7
- package/src/extension/public-execution.ts +14 -0
- package/src/extension/rpc.ts +3 -2
- package/src/extension/schemas.ts +3 -2
- package/src/extension/tool-description.ts +13 -8
- package/src/integrations/pi-web-session-liveness.ts +73 -0
- package/src/intercom/native-supervisor-channel.ts +159 -95
- package/src/intercom/supervisor-ui.ts +244 -0
- package/src/missions/workflow-state.ts +37 -16
- package/src/runs/background/async-execution.ts +51 -25
- package/src/runs/background/async-job-tracker.ts +11 -0
- package/src/runs/background/async-resume.ts +14 -3
- package/src/runs/background/async-retention.ts +9 -0
- package/src/runs/background/control-channel.ts +2 -204
- package/src/runs/background/notify.ts +2 -0
- package/src/runs/background/process-terminal.ts +1 -1
- package/src/runs/background/retained-nested-route-tracker.ts +96 -0
- package/src/runs/background/run-child-session.ts +614 -0
- package/src/runs/background/run-status.ts +0 -1
- package/src/runs/background/runner-aliases.ts +152 -0
- package/src/runs/background/runner-child-sessions.ts +31 -0
- package/src/runs/background/scheduled-runs.ts +18 -4
- package/src/runs/background/subagent-runner.ts +203 -901
- package/src/runs/foreground/async-steering-action.ts +1 -17
- package/src/runs/foreground/execution.ts +204 -378
- package/src/runs/foreground/foreground-control.ts +4 -0
- package/src/runs/foreground/foreground-history.ts +3 -1
- package/src/runs/foreground/prompt-audit.ts +9 -5
- package/src/runs/foreground/subagent-executor.ts +161 -91
- package/src/runs/foreground/workflow-foreground-steering.ts +24 -98
- package/src/runs/shared/abort-recovery.ts +3 -3
- package/src/runs/shared/acceptance.ts +14 -1
- package/src/runs/shared/capability-ceiling.ts +1 -2
- package/src/runs/shared/child-hooks.ts +25 -0
- package/src/runs/shared/child-identity.ts +13 -2
- package/src/runs/shared/child-launch.ts +314 -0
- package/src/runs/shared/child-lifecycle.ts +25 -0
- package/src/runs/shared/child-runtime-config.ts +126 -0
- package/src/runs/shared/child-session.ts +337 -0
- package/src/runs/shared/child-tool-plan.ts +530 -0
- package/src/runs/shared/claude-code-adapter.ts +5 -1
- package/src/runs/shared/completion-guard.ts +1 -1
- package/src/runs/shared/external-cli-preflight.ts +16 -0
- package/src/runs/shared/llm-intent-arbiter.ts +20 -11
- package/src/runs/shared/mcp-direct-tool-allowlist.ts +5 -4
- package/src/runs/shared/model-exclusions.ts +84 -15
- package/src/runs/shared/model-fallback.ts +78 -6
- package/src/runs/shared/nested-events.ts +32 -48
- package/src/runs/shared/nested-path.ts +0 -14
- package/src/runs/shared/orca-progress-tabs.ts +12 -7
- package/src/runs/shared/parallel-utils.ts +1 -2
- package/src/runs/shared/permissions.ts +0 -13
- package/src/runs/shared/process-signal.ts +4 -1
- package/src/runs/shared/run-fanout-budget.ts +0 -13
- package/src/runs/shared/runtime-acknowledged-extensions.ts +0 -27
- package/src/runs/shared/structured-output.ts +17 -4
- package/src/runs/shared/subagent-control.ts +2 -0
- package/src/runs/shared/subagent-prompt-runtime.ts +87 -384
- package/src/runs/shared/tool-availability.ts +18 -62
- package/src/runs/shared/tool-budget.ts +0 -14
- package/src/runs/shared/worktree-cleanup-plan.ts +31 -9
- package/src/runs/shared/worktree.ts +192 -40
- package/src/shared/child-session-name.ts +1 -1
- package/src/shared/jsonl-writer.ts +11 -0
- package/src/shared/model-response-aliases.ts +13 -0
- package/src/shared/thinking-ceiling.ts +0 -6
- package/src/shared/types.ts +63 -28
- package/src/shared/utils.ts +6 -4
- package/src/shared/watch-strategy.ts +2 -0
- package/src/slash/slash-commands.ts +0 -6
- package/src/tui/fleet-status.ts +1 -1
- package/src/tui/fleet.ts +0 -1
- package/src/tui/render.ts +254 -41
- package/src/watchdog/child-status.ts +0 -1
- package/src/watchdog/register-child.ts +12 -12
- package/src/workflows/scripted-workflow.ts +80 -7
- package/src/workflows/workflow-checklist.ts +4 -3
- package/src/runs/shared/child-protocol.ts +0 -415
- package/src/runs/shared/pi-args.ts +0 -1059
- package/src/runs/shared/subagent-startup-retry.ts +0 -116
- package/src/shared/post-exit-stdio-guard.ts +0 -85
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,71 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.65.1] - 2026-09-04
|
|
6
|
+
|
|
7
|
+
### Highlights
|
|
8
|
+
- Background sessions stay alive until their work and result delivery finish.
|
|
9
|
+
- Background runs work on Pi 0.85.0 without missing-package errors.
|
|
10
|
+
- Custom-provider models and proxy connections work more reliably in background runs.
|
|
11
|
+
- Parallel children keep separate session logs, even with a shared log directory.
|
|
12
|
+
- Worktree cleanup preserves changes until a complete, usable patch has been saved.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Clarify that switching execution modes after a failed run requires your approval (#1879).
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- Accept configured model aliases returned by gateways without changing the requested model. Thanks to [@drudko-ias](https://github.com/drudko-ias) for #1897.
|
|
19
|
+
- Hide the empty, unlimited async capacity summary in Fleet. Thanks to [@youssefsiam38](https://github.com/youssefsiam38) for #1892.
|
|
20
|
+
- Fix missing-server import errors in Pi 0.85.0 background runs, including runs that load extensions.
|
|
21
|
+
- Remove repeated metadata and reply instructions from supervisor request cards. Thanks to [@youssefsiam38](https://github.com/youssefsiam38) for #1893.
|
|
22
|
+
- Stop foreground runs before contacting a provider when required tools are missing. Respect workflow async defaults and show each failure once. Thanks to [@youssefsiam38](https://github.com/youssefsiam38) for #1891.
|
|
23
|
+
- Keep pi-web parent sessions alive while subagent work or completion delivery remains active. Thanks to [@vcing](https://github.com/vcing) for #1857.
|
|
24
|
+
- Avoid unnecessary startup delays and preserve active locks when process IDs are reused. Thanks to [@ducaoya](https://github.com/ducaoya) for #1878.
|
|
25
|
+
- Make extension-provided models available before starting child sessions, including on Pi versions without native provider queues. Thanks to [@kevinkirkup](https://github.com/kevinkirkup) for #1885.
|
|
26
|
+
- Handle long or unusual workflow IDs without creating invalid file paths. Thanks to [@jstillwa](https://github.com/jstillwa) for #1875.
|
|
27
|
+
- Avoid startup import errors when optional Pi packages are not installed beside the extension. Thanks to [@VladimirGVP](https://github.com/VladimirGVP) for #1860.
|
|
28
|
+
- Use custom provider streams for task classification only when they match the selected model's API. Thanks to [@pwguler](https://github.com/pwguler) for #1874.
|
|
29
|
+
- Give concurrent children separate session files under an explicit `sessionDir`. Thanks to [@dat9uy](https://github.com/dat9uy) for #1859 and #1858.
|
|
30
|
+
- Honor proxy environment variables in detached background runs. Thanks to [@jasonrale](https://github.com/jasonrale) for #1867 and #1866.
|
|
31
|
+
- Allow previously unavailable models to run once they reappear in the model registry. Thanks to [@x1prog](https://github.com/x1prog) for #1862.
|
|
32
|
+
- Resolve Pi package imports correctly in detached runs, including subpath imports. Thanks to [@plopezlpz](https://github.com/plopezlpz) for #1871 and [@pwguler](https://github.com/pwguler) for #1880.
|
|
33
|
+
- Initialize the theme before child extensions access `ctx.ui.theme`. Thanks to [@danielmarbach](https://github.com/danielmarbach) for #1865.
|
|
34
|
+
- Save complete worktree patches, including binary changes, regardless of Git display settings. Validate them before removing worktrees. Thanks to [@jeanduplessis](https://github.com/jeanduplessis) for #1868.
|
|
35
|
+
- Accept `acceptance: false` alongside `gate`, treating it as omitted.
|
|
36
|
+
|
|
37
|
+
## [0.65.0] - 2026-09-04
|
|
38
|
+
|
|
39
|
+
### Highlights
|
|
40
|
+
- Subagents now run through native Pi sessions instead of spawning separate `pi` processes, making delegation simpler and less fragile.
|
|
41
|
+
- Workflow status is easier to scan with compact lane summaries and clearer supervisor messages.
|
|
42
|
+
- Model selection fails clearly when configured models are unavailable, instead of silently using a provider default.
|
|
43
|
+
- Managed worktrees are safer and more flexible, with validated `baseRef` support and per-project nesting.
|
|
44
|
+
- Background children can use provider-extension models reliably, including dynamically registered models such as router providers.
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
- Include sanitized model, provider, reason, and expiry details when no usable subagent model candidates remain. Thanks [@AlexKucera](https://github.com/AlexKucera) for #1841.
|
|
48
|
+
- Allow managed worktrees to start from a validated `baseRef` instead of always using `HEAD`. Thanks [@jaudiger](https://github.com/jaudiger) for #1842.
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
- Run subagents as native Pi `AgentSession`s instead of spawned `pi` CLI processes (#1844). Foreground children run in the parent process, and background children run in the detached runner.
|
|
52
|
+
- Foreground children no longer load ambient extensions. Use background children for agents that need MCP tools or provider-extension models. Background children require Pi from the installed `@earendil-works/pi-coding-agent` package, not a standalone `pi` binary.
|
|
53
|
+
- Rename package subpath `pi-subagents/pi-args` to `pi-subagents/child-tool-plan`; `PI_SUBAGENT_PI_BINARY` now applies only to Herdr project panes and the profile model probe.
|
|
54
|
+
- Replace collapsed async workflow role summaries with a compact lane view while keeping full details available when expanded (#1827).
|
|
55
|
+
- Add `contact_supervisor` to the bundled reviewer and scout tool allowlists without adding mutation tools (#1846).
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
- Drop only malformed persisted model-exclusion entries and rewrite the cleaned cache.
|
|
59
|
+
- Stop live workflow children when a run-level stop targets an in-memory async workflow controller.
|
|
60
|
+
- Fail closed when a fallback-only model configuration resolves no launch candidates. Thanks [@AdenosineTP](https://github.com/AdenosineTP) for #1853.
|
|
61
|
+
- Resolve native child models after child extensions register provider models. Thanks [@mystery4f](https://github.com/mystery4f) for #1855.
|
|
62
|
+
- Ignore stale authentication-related model exclusions after Pi's `auth.json` is refreshed, while preserving quota, rate-limit, overload, and model-unavailable exclusions. Thanks [@wesleyfei1](https://github.com/wesleyfei1) for #1835.
|
|
63
|
+
- Show native supervisor requests and outbound replies as bounded TUI cards in parent sessions (#1845).
|
|
64
|
+
- Suppress stale async supervisor-request notices after the native request has already been answered (#1838). Thanks [@VladimirGVP](https://github.com/VladimirGVP).
|
|
65
|
+
- Flush async workflow result assembly after session replacement when every child is already terminal, without permitting stale-context launches (#1833). Thanks [@redcomet168](https://github.com/redcomet168).
|
|
66
|
+
- Accept calendar/platform `claude --version` output during Claude Code adapter preflight while retaining required launch-flag validation. Thanks [@drouhard](https://github.com/drouhard).
|
|
67
|
+
- Show passive local command availability for external CLI agents in capability listings without replacing launch preflight (#1829). Thanks [@drouhard](https://github.com/drouhard).
|
|
68
|
+
- Nest native managed worktrees under per-project directories while preserving unsafe-location checks (#1831). Thanks [@moofone](https://github.com/moofone).
|
|
69
|
+
|
|
5
70
|
## [0.64.0] - 2026-09-02
|
|
6
71
|
|
|
7
72
|
### Highlights
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
pi install npm:pi-subagents
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
That is the only required step.
|
|
17
|
+
That is the only required step. Background children require pi installed as the npm package (`@earendil-works/pi-coding-agent`): the detached runner imports pi's packages from that package directory. A standalone single-file pi binary has no package directory and cannot run background children; foreground children (`async: false`) still work there.
|
|
18
18
|
|
|
19
19
|
## Try this first
|
|
20
20
|
|
|
@@ -42,7 +42,7 @@ That is enough to start. Pi decides whether to call the `subagent` tool, which a
|
|
|
42
42
|
|
|
43
43
|
Pi is the parent session. A subagent is a focused child Pi session with its own job.
|
|
44
44
|
|
|
45
|
-
When you ask for a subagent, Pi starts the child, gives it the task, and brings the result back. Foreground
|
|
45
|
+
When you ask for a subagent, Pi starts the child, gives it the task, and brings the result back. Foreground children run as sessions inside the parent Pi process and stream in the conversation. Background children run as sessions inside a detached runner process that keeps working and can be checked later.
|
|
46
46
|
|
|
47
47
|
Installing the extension does not start an automatic reviewer in the background. It gives Pi a delegation tool. If you want every implementation reviewed, say so in your prompt or project instructions:
|
|
48
48
|
|
package/agents/reviewer.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: reviewer
|
|
3
3
|
description: Versatile review specialist for code diffs, plans, proposed solutions, codebase health, and PR/issue validation
|
|
4
|
-
tools: read, grep, find, ls
|
|
4
|
+
tools: read, grep, find, ls, contact_supervisor
|
|
5
5
|
thinking: high
|
|
6
6
|
systemPromptMode: replace
|
|
7
7
|
inheritProjectContext: true
|
package/agents/scout.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: scout
|
|
3
3
|
description: Fast codebase recon that returns compressed context for handoff
|
|
4
|
-
tools: read, grep, find, ls, bash, write
|
|
4
|
+
tools: read, grep, find, ls, bash, write, contact_supervisor
|
|
5
5
|
thinking: low
|
|
6
6
|
systemPromptMode: replace
|
|
7
7
|
inheritProjectContext: true
|
package/docs/agents.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Agents
|
|
2
2
|
|
|
3
|
-
An agent is a markdown file: YAML frontmatter on top, a system prompt below. The frontmatter defines the specialist that runs
|
|
3
|
+
An agent is a markdown file: YAML frontmatter on top, a system prompt below. The frontmatter defines the specialist that runs as the child session.
|
|
4
4
|
|
|
5
5
|
```yaml
|
|
6
6
|
---
|
|
@@ -58,7 +58,7 @@ The Pi async run remains the source of truth for status, artifacts, wake/wait, m
|
|
|
58
58
|
|
|
59
59
|
### Advisory runner data boundary
|
|
60
60
|
|
|
61
|
-
External CLI agents use their own runner contract. Do not pass 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 adapter explicitly implements them.
|
|
61
|
+
External CLI agents use their own runner contract. They are deliberate execution modes, not implicit recovery paths for a failed native `subagent` workflow. For backlog lanes and other subagent-governed workflows, switching to an external, foreground, or CLI runner requires explicit owner approval after the exact failure/run/worktree state is recorded and the worktree is verified clean or its partial diff is captured. Do not pass 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 adapter explicitly implements them.
|
|
62
62
|
|
|
63
63
|
The built-in `codex-exec` and `codex-exec-writer` profiles are the supported Codex one-shot modes. Both require an installed and authenticated Codex CLI. The adapters own `codex exec --json` argv with ignored user config and rules, ephemeral sessions, approval policy `never`, and a final-message artifact.
|
|
64
64
|
|
|
@@ -77,7 +77,7 @@ Use codex-exec to analyze this change without editing files.
|
|
|
77
77
|
Use codex-exec-writer to make the requested workspace changes.
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
-
The adapter validates `codex --version` and `codex exec --help` only when a run launches. Discovery, list, status, and native Pi launches do not
|
|
80
|
+
The adapter validates `codex --version` and `codex exec --help` only when a run launches. Discovery, list, status, and native Pi launches do not execute Codex or its version/help probes. A capabilities listing performs only a passive PATH/PATHEXT/X_OK lookup and exposes the command as `runner.available`; that does not prove authentication or launch compatibility. JSONL, stderr, and stdout are untrusted. A run succeeds only after bounded valid JSONL contains one `turn.completed` event and the bounded final-message artifact is present.
|
|
81
81
|
|
|
82
82
|
Maintainers can collect real smoke evidence without making it part of the normal test suite:
|
|
83
83
|
|
|
@@ -112,7 +112,7 @@ Use claude-code to analyze this handoff without editing files.
|
|
|
112
112
|
Use claude-code-writer to make the requested file changes.
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
-
The adapter validates `claude --version` and `claude --help` only when a run launches. Discovery, list, status, and native Pi launches do not
|
|
115
|
+
The adapter validates `claude --version` and `claude --help` only when a run launches. Discovery, list, status, and native Pi launches do not execute Claude Code or probe authentication. A capabilities listing performs only a passive PATH/PATHEXT/X_OK lookup and exposes the command as `runner.available`; that does not prove authentication or launch compatibility. JSONL, stderr, and stdout are untrusted. A run succeeds only after bounded valid JSONL contains exactly one successful terminal `result` with non-empty final text. Missing or revoked local authentication, limit stops, malformed JSON, duplicate terminal results, and EOF before a terminal result fail closed.
|
|
116
116
|
|
|
117
117
|
Maintainers can opt in to separate read-only and writer canaries:
|
|
118
118
|
|
|
@@ -141,7 +141,7 @@ Both adapters use stream JSON, the enabled sandbox, and the primary workspace. T
|
|
|
141
141
|
|
|
142
142
|
The adapters do not pass force, yolo, auto-review, MCP approval, plugin, session resume, continue, worktree, or workspace trust flags. User profiles cannot add argv or workspace roots. The `cursor-agent` selection identity is reserved for the read-only adapter.
|
|
143
143
|
|
|
144
|
-
Launch preflight validates `cursor-agent --version` and `cursor-agent --help` only when a run starts. Discovery, list, status, and native Pi launches do not execute Cursor or probe authentication. A run succeeds only when bounded valid JSONL ends with one successful `result` event that has non-empty final text. Error events, failed results, malformed JSON, output after the terminal event, and EOF before a result fail closed.
|
|
144
|
+
Launch preflight validates `cursor-agent --version` and `cursor-agent --help` only when a run starts. Discovery, list, status, and native Pi launches do not execute Cursor or probe authentication. A capabilities listing performs only a passive PATH/PATHEXT/X_OK lookup and exposes the command as `runner.available`; that does not prove authentication or launch compatibility. A run succeeds only when bounded valid JSONL ends with one successful `result` event that has non-empty final text. Error events, failed results, malformed JSON, output after the terminal event, and EOF before a result fail closed.
|
|
145
145
|
|
|
146
146
|
These headless smokes rely on saved workspace trust. Cursor documents no passive command that checks workspace trust, so the smoke cannot verify it before launch. The operator must use Cursor's interactive trust flow for the exact disposable workspace and the exact derived prompt directory, `<state-root>/external-0.cursor-prompt`. Keep that prompt directory after the trust step. It must be empty, owned by the operator who runs the smoke, and must not be a symlink. The harness preserves this directory but creates its private handoff with exclusive `0600` access and removes the handoff after every run. Repeat the trust setup if either exact path changes.
|
|
147
147
|
|
|
@@ -214,7 +214,7 @@ Supported override fields: `description`, `output`, `outputMode`, `defaultReads`
|
|
|
214
214
|
|
|
215
215
|
- `description` replaces the discovered description for builtin and custom agents, which lets list output show deployment-specific routing or model metadata.
|
|
216
216
|
- Use `output: false`, `defaultReads: false`, `defaultContext: false`, or `acceptanceRole: false` to clear an inherited value.
|
|
217
|
-
- Use `tools: "inherit"` when that one role should omit its bundled or frontmatter tool allowlist and receive Pi's normal builtins
|
|
217
|
+
- Use `tools: "inherit"` when that one role should omit its bundled or frontmatter tool allowlist and receive Pi's normal builtins (plus ambient extensions when it runs as a background child).
|
|
218
218
|
- Project overrides beat user overrides.
|
|
219
219
|
- Matching package, user, and project agents also receive override fields, which replace the same fields declared in their frontmatter. This lets a shared agent keep its persona while local settings choose the effective model, context, tools, or other supported options.
|
|
220
220
|
|
|
@@ -303,10 +303,10 @@ Field notes:
|
|
|
303
303
|
| `package` | Optional package identifier. A file with `name: scout` and `package: code-analysis` registers as `code-analysis.scout`; serialization keeps `name` and `package` separate. |
|
|
304
304
|
| `aliases` | Optional comma-separated or block-list names that resolve to this agent for selection and explicit `agent` and task inputs. Runtime status, persistence, and config still use the canonical `name`. Exact canonical names take precedence over aliases, and alias collisions between distinct canonical agents fail as ambiguous. |
|
|
305
305
|
| `tools` | Strict child tool allowlist. Named extension tools must also have their provider loaded. `mcp:` entries select direct MCP tools when `pi-mcp-adapter` is installed. |
|
|
306
|
-
| `excludeTools` | Optional child tool deny-list applied after normal tool resolution. With an explicit `tools` allowlist, matching names are removed; when `tools` is omitted, the names are
|
|
306
|
+
| `excludeTools` | Optional child tool deny-list applied after normal tool resolution. With an explicit `tools` allowlist, matching names are removed; when `tools` is omitted, the names are excluded from the child session's default tool set. Unknown names are ignored by Pi without making the agent definition invalid. |
|
|
307
307
|
| `allowNestedSubagents` | Set `true` to authorize the child-safe nested `subagent` runtime without making omitted `tools` an allowlist. Inherited depth and capability ceilings remain authoritative. |
|
|
308
|
-
| `extensions` | Omitted means
|
|
309
|
-
| `subagentOnlyExtensions` | Extension paths loaded only in
|
|
308
|
+
| `extensions` | Omitted means a background child loads the parent's ambient extensions; empty means no ambient extensions; list values load exactly those extensions. Foreground children never load ambient extensions, so for them only listed values apply. |
|
|
309
|
+
| `subagentOnlyExtensions` | Extension paths loaded only in this agent's child sessions. Tools registered there are unavailable to the main agent unless also installed through normal Pi extension configuration. |
|
|
310
310
|
| `model` | Default model. Bare ids prefer the current provider when possible, then unique registry matches. |
|
|
311
311
|
| `fallbackModels` | Ordered backup models for provider/model failures such as quota, auth, provider-reported timeout, or unavailable model. Expiration of the run-level `timeoutMs` / `maxRuntimeMs` deadline is terminal and does not trigger fallback. Ordinary task failures do not trigger fallback. |
|
|
312
312
|
| `thinking` | Appended as a `:level` suffix at runtime unless a suffix is already present. |
|
|
@@ -383,14 +383,16 @@ How it works:
|
|
|
383
383
|
|
|
384
384
|
How `tools` behaves:
|
|
385
385
|
|
|
386
|
-
- `tools` omitted:
|
|
386
|
+
- `tools` omitted: the child session gets Pi's normal builtin tools.
|
|
387
387
|
- `tools` present: regular tool names become an explicit allowlist.
|
|
388
|
-
- `tools:` empty:
|
|
388
|
+
- `tools:` empty: the child session gets no tools.
|
|
389
389
|
- `allowNestedSubagents: true`: explicitly enables child-safe nested fanout without turning omitted `tools` into an allowlist. Depth and inherited capability ceilings still apply.
|
|
390
390
|
|
|
391
|
-
`excludeTools` is applied after this resolution. It can narrow an explicit `tools` allowlist or, when `tools` is omitted,
|
|
391
|
+
`excludeTools` is applied after this resolution. It can narrow an explicit `tools` allowlist or, when `tools` is omitted, remove names from Pi's default builtin tool set. Runtime-injected tools are excluded only when their exact names are listed. An empty `excludeTools` list has no effect.
|
|
392
392
|
|
|
393
|
-
An allowlisted name does not load the extension that registers it. Load that provider through
|
|
393
|
+
An allowlisted name does not load the extension that registers it. Load that provider through `extensions`, `subagentOnlyExtensions`, a path-like `tools` entry, or (background children only) normal Pi extension discovery.
|
|
394
|
+
|
|
395
|
+
Ambient extensions depend on where the child runs. Foreground children are sessions inside the parent Pi process and never load the parent's ambient extensions; otherwise the parent would start a second copy of each ambient extension, including this one. Background children are sessions inside the detached runner process and load the ambient extensions unless the agent sets `extensions` or the capability ceiling denies extensions. Agents that need MCP tools (`mcpDirectTools`, or MCP tools from an ambient adapter such as pi-mcp-adapter) or models from a provider extension must therefore run as background children (`async: true`). A foreground launch of such an agent fails with a diagnostic that says exactly that.
|
|
394
396
|
|
|
395
397
|
More rules:
|
|
396
398
|
|
|
@@ -402,14 +404,14 @@ More rules:
|
|
|
402
404
|
|
|
403
405
|
Examples:
|
|
404
406
|
|
|
405
|
-
- `tools` omitted and `extensions` omitted: normal builtins
|
|
407
|
+
- `tools` omitted and `extensions` omitted: normal builtins; a background child also loads the ambient extensions.
|
|
406
408
|
- `tools: mcp:chrome-devtools`: only the resolved direct Chrome DevTools MCP tools.
|
|
407
409
|
- `tools: read, bash, mcp:chrome-devtools`: only `read` and `bash` as builtins, plus direct Chrome DevTools MCP tools.
|
|
408
410
|
- `tools: subagent, read`: a child-safe `subagent` tool is available inside that child so it can run explicitly assigned nested fanout.
|
|
409
|
-
- `allowNestedSubagents: true` with `tools` omitted: normal builtin tools and ambient extensions remain inherited, and the child-safe nested `subagent` runtime is added.
|
|
410
|
-
- `tools: read, fixture_search` plus `subagentOnlyExtensions: ./tools/fixture-search.ts`: the provider loads only in this agent's child
|
|
411
|
+
- `allowNestedSubagents: true` with `tools` omitted: normal builtin tools (and, for background children, ambient extensions) remain inherited, and the child-safe nested `subagent` runtime is added.
|
|
412
|
+
- `tools: read, fixture_search` plus `subagentOnlyExtensions: ./tools/fixture-search.ts`: the provider loads only in this agent's child sessions, and the registered `fixture_search` name survives the strict allowlist.
|
|
411
413
|
|
|
412
|
-
Direct MCP tools require [pi-mcp-adapter](https://github.com/nicobailon/pi-mcp-adapter). Subagents only receive direct MCP tools when `mcp:` entries are listed in their frontmatter; global `directTools: true` in `mcp.json` is not enough by itself. The generic `mcp` proxy tool can still be used for discovery when available. The adapter caches tool metadata at startup, so after connecting a new MCP server for the first time, restart Pi before relying on direct tools. Server `includeTools` and `excludeTools` policies are enforced while resolving cached metadata for children: both accept exact names and `*`/`?` glob patterns against raw, generated-resource, and server/short/none-prefixed names, with `excludeTools` taking precedence. An `mcp:` entry named `subagent` does not authorize nested fanout; declare the builtin `subagent` tool or set `allowNestedSubagents: true`. If a resolved direct MCP name is missing from the child registry, pi-subagents keeps the launch failed under the strict allowlist and identifies the condition as a host/pi-mcp-adapter registration problem; verify that the adapter registers the selected tools before child startup.
|
|
414
|
+
Direct MCP tools require [pi-mcp-adapter](https://github.com/nicobailon/pi-mcp-adapter). Subagents only receive direct MCP tools when `mcp:` entries are listed in their frontmatter; global `directTools: true` in `mcp.json` is not enough by itself. The generic `mcp` proxy tool can still be used for discovery when available. The adapter caches tool metadata at startup, so after connecting a new MCP server for the first time, restart Pi before relying on direct tools. Server `includeTools` and `excludeTools` policies are enforced while resolving cached metadata for children: both accept exact names and `*`/`?` glob patterns against raw, generated-resource, and server/short/none-prefixed names, with `excludeTools` taking precedence. `mcp:` entries must name servers from the adapter's configuration files. A server that exists only in the adapter's runtime snapshot (registered at runtime, not persisted) cannot be provided to a child: children are pi sessions inside the parent or the runner process, not `pi` processes that could receive an MCP config argument, so such a launch fails with an error saying that MCP tools must come from an ambient adapter extension in a background child. An `mcp:` entry named `subagent` does not authorize nested fanout; declare the builtin `subagent` tool or set `allowNestedSubagents: true`. If a resolved direct MCP name is missing from the child registry, pi-subagents keeps the launch failed under the strict allowlist and identifies the condition as a host/pi-mcp-adapter registration problem; verify that the adapter registers the selected tools before child startup.
|
|
413
415
|
|
|
414
416
|
`extensions` controls child extension loading:
|
|
415
417
|
|
package/docs/configuration.md
CHANGED
|
@@ -32,6 +32,22 @@ Add recursive user or project agent roots with `subagents.agentScanDirs` in Pi s
|
|
|
32
32
|
|
|
33
33
|
Entries support `~` expansion. A single `*` path segment expands one directory level, so package-like folders can each expose an `agents/` directory. Missing directories are ignored. Fixed user/project agent directories still win over same-name agents from scan roots.
|
|
34
34
|
|
|
35
|
+
## `modelResponseAliases`
|
|
36
|
+
|
|
37
|
+
In `~/.pi/agent/extensions/subagent/config.json` (top-level, not under `subagents`):
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"modelResponseAliases": {
|
|
42
|
+
"databricks-bedrock/ias-claude-opus-5": ["claude-opus-5"]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Optionally accept exact response model IDs for an exact provider-qualified launch candidate. Keys use the resolved `provider/model` ID without its thinking suffix, including for fallback attempts; values are arrays of non-empty response ID strings. Alias matching is exact and case-sensitive, with no fuzzy or suffix matching. Empty arrays add no accepted IDs; malformed declarations fail config loading.
|
|
48
|
+
|
|
49
|
+
This is your explicit assertion that the declared response IDs identify the requested model, not proof from model output. It does not rewrite the outgoing model or provider route, authorize fallback models, or bypass verification for other routes. Foreground and background runs capture this declaration for launch and retain it on revival, including when no aliases were declared. Changing config affects new independent runs, not the retained declaration. Without a matching declaration, existing strict verification remains unchanged.
|
|
50
|
+
|
|
35
51
|
## `modelExclusions`
|
|
36
52
|
|
|
37
53
|
```json
|
|
@@ -42,7 +58,7 @@ Entries support `~` expansion. A single `*` path segment expands one directory l
|
|
|
42
58
|
}
|
|
43
59
|
```
|
|
44
60
|
|
|
45
|
-
Controls the duration, in milliseconds, for model exclusions. The default is `86400000` (24 hours), and the maximum is `8000000000000000` so generated expiry timestamps remain valid JavaScript dates. The extension applies this value when it starts or reloads. A lower configured value shortens active cached exclusions from their original `recordedAt`; it never extends an existing expiry. Launches also warn when a candidate is skipped, including the cached reason and expiry. `PI_MODEL_EXCLUSIONS_PATH` changes the exclusion-store path but does not change this TTL.
|
|
61
|
+
Controls the duration, in milliseconds, for model exclusions. The default is `86400000` (24 hours), and the maximum is `8000000000000000` so generated expiry timestamps remain valid JavaScript dates. The extension applies this value when it starts or reloads. A lower configured value shortens active cached exclusions from their original `recordedAt`; it never extends an existing expiry. Authentication-related exclusions are ignored when Pi's `auth.json` was modified after the exclusion was recorded; other exclusion types are unaffected. Launches also warn when a candidate is skipped, including the cached reason and expiry. `PI_MODEL_EXCLUSIONS_PATH` changes the exclusion-store path but does not change this TTL.
|
|
46
62
|
|
|
47
63
|
## `toolDescriptionMode`
|
|
48
64
|
|
|
@@ -111,7 +127,7 @@ Pi binds `Ctrl+B` to editor cursor-left by default. The extension shortcut takes
|
|
|
111
127
|
}
|
|
112
128
|
```
|
|
113
129
|
|
|
114
|
-
Opt in to a best-effort Orca observer that creates one Orca terminal tab for each top-level subagent call and mirrors the run's live tool
|
|
130
|
+
Opt in to a best-effort Orca observer that creates one Orca terminal tab for each top-level subagent call and mirrors the run's live tool and assistant progress. Parallel and chain children share that one tab, with child section headers in the mirrored log. Tab titles use a persistent worktree-local sequence (`subagents · <run-label> · 1`, `... · 2`, and so on), so separate top-level calls do not reuse the same number. For the same worktree, `orca terminal create` runs one at a time in that sequence so observer tabs appear from left to right as `1`, then `2`, then `3`. This does **not** replace Pi as the runner: native Pi children keep the same lifecycle, status, control, artifact, and result paths. External CLI profiles also keep their existing runner and can mirror their stdout/stderr.
|
|
115
131
|
|
|
116
132
|
The integration is off by default and supports macOS and Linux. It is disabled on Windows. When enabled, `pi-subagents` looks for executable `orca` on `PATH`, or uses the executable path in `PI_SUBAGENT_ORCA_BINARY`. If no executable is available, Orca is not running, the cwd is not an Orca-managed worktree, or `terminal create` fails, the authoritative subagent still runs normally. Tab creation is deliberately best-effort and never changes the child result. A passive observer manifest is also written under `<worktree>/.pi/subagents/views/orca/` when possible so future view surfaces can discover the Orca tab without making Orca authoritative.
|
|
117
133
|
|
|
@@ -354,7 +370,7 @@ Routes relative `output` paths for single-agent `/run` calls under this director
|
|
|
354
370
|
{ "maxSubagentDepth": 1 }
|
|
355
371
|
```
|
|
356
372
|
|
|
357
|
-
Controls nested delegation when no
|
|
373
|
+
Controls nested delegation when no stricter limit is inherited from the launching child's runtime config. Per-agent `maxSubagentDepth` can tighten the limit for that agent's child runs, but cannot relax an inherited stricter limit. This applies even to children that explicitly declare `tools: subagent` or `allowNestedSubagents: true`; at the cap, execution fanout is blocked instead of silently hiding nested work.
|
|
358
374
|
|
|
359
375
|
## `PI_SUBAGENT_PI_BINARY`
|
|
360
376
|
|
|
@@ -362,17 +378,7 @@ Controls nested delegation when no inherited `PI_SUBAGENT_MAX_DEPTH` is already
|
|
|
362
378
|
export PI_SUBAGENT_PI_BINARY=/path/to/pi-or-wrapper
|
|
363
379
|
```
|
|
364
380
|
|
|
365
|
-
Overrides the command
|
|
366
|
-
|
|
367
|
-
## `PI_SUBAGENT_TASK_DELIVERY`
|
|
368
|
-
|
|
369
|
-
```bash
|
|
370
|
-
export PI_SUBAGENT_TASK_DELIVERY=file # auto | file (default: auto)
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
Controls how the task text reaches the child Pi process. `auto` (default) passes short non-macOS tasks as an inline argv token, and writes macOS tasks plus tasks longer than 8000 characters to a temp `task.md` referenced as `@<path>`. `file` always uses a temp file, keeping the task out of argv entirely.
|
|
374
|
-
|
|
375
|
-
Use `file` on hosts where endpoint protection (EDR) pre-execution scanning denies child processes whose command line embeds a long natural-language task — that denial surfaces as an immediate zero-activity `SIGKILL`. Independently of this setting, startup retries automatically escalate to file delivery after an unexplained zero-activity `SIGKILL`. Empty, whitespace-only, or unrecognized values fall back to `auto`.
|
|
381
|
+
Overrides the `pi` command pi-subagents spawns for Herdr project panes (`action: "project.open"`) and for the profile model probe. Package wrappers can set this to their own `pi` binary so those launches inherit wrapper flags, environment setup, and bundled resources without relying on `PATH` ordering. Empty or whitespace-only values are ignored. It does not affect children: foreground children are sessions inside the parent Pi process and background children are sessions inside the detached runner process, and neither spawns a `pi` binary. Background children require pi installed as the npm package (`@earendil-works/pi-coding-agent`), because the runner imports pi's packages from that package directory; a standalone pi binary has no package directory, and background launches fail with an error saying so.
|
|
376
382
|
|
|
377
383
|
## `intercomBridge`
|
|
378
384
|
|
|
@@ -404,7 +410,9 @@ The default injected guidance tells children to use `contact_supervisor` with `r
|
|
|
404
410
|
{ "worktreeBaseDir": "/Users/matt/code/.worktrees/pi-subagents" }
|
|
405
411
|
```
|
|
406
412
|
|
|
407
|
-
Sets the
|
|
413
|
+
Sets the native dedicated root directory for `worktree: true` runs. Relative paths resolve from the repository root, `~/...` expands to your home directory, and `PI_SUBAGENTS_WORKTREE_DIR` is used when config is unset. When native allocation is used and both are unset, the dedicated root defaults to `{dirname(repoRoot)}/worktrees`, a `worktrees` directory alongside the repository checkout.
|
|
414
|
+
|
|
415
|
+
Each native worktree leaf is `{dedicatedRoot}/{projectName}/pi-worktree-{runId}-{index}`, where `{projectName}` is the repository directory name (`basename(repoRoot)`), `{runId}` identifies the run, and `{index}` counts the children within the run. `worktreeBaseDir` and `PI_SUBAGENTS_WORKTREE_DIR` override only the dedicated root; the `{projectName}/pi-worktree-{runId}-{index}` nesting under it always applies for native allocation. Unsafe locations are rejected instead of created: setup fails when the dedicated root sits inside the repository checkout or the Pi extensions directory, or when a worktree would land directly inside the repository parent.
|
|
408
416
|
|
|
409
417
|
## `worktreeProvider`
|
|
410
418
|
|
package/docs/extension-api.md
CHANGED
|
@@ -99,7 +99,7 @@ If `pi-subagents` is a resolvable dependency of the consumer package, `pi-subage
|
|
|
99
99
|
|
|
100
100
|
The installed owner applies the existing runtime-agent validation, collision checks, limits, runtime source metadata, and cleanup. If more than one owner listens, the first handler that writes `request.result` wins. Unsupported versions, malformed requests, and registration failures return `{ ok: false, error }`. No result means no compatible owner handled the event.
|
|
101
101
|
|
|
102
|
-
This contract is process-local. It does not register agents in child
|
|
102
|
+
This contract is process-local. It does not register agents in child sessions or other Pi processes, and it does not change package discovery or package resolution.
|
|
103
103
|
|
|
104
104
|
## External jobs in FleetView
|
|
105
105
|
|
|
@@ -309,7 +309,9 @@ Semantics:
|
|
|
309
309
|
- Providers share a registry through `Symbol.for("pi-subagents.background-work.v1")`, allowing independently loaded extension modules to meet in one Pi process.
|
|
310
310
|
- Registration is reload-safe: a new provider with the same name replaces the old callback, and the old disposer cannot remove the replacement. Call the disposer during extension shutdown when possible.
|
|
311
311
|
|
|
312
|
-
|
|
312
|
+
Children do not gain provider tools or extensions automatically. Add `bg_wait` to the child agent's `tools` allowlist and load each provider through `extensions` or `subagentOnlyExtensions`. The parent's effective `waitTool` setting reaches every child through its typed runtime config; `PI_SUBAGENT_WAIT_TOOL_ENABLED` keeps precedence in the parent.
|
|
313
|
+
|
|
314
|
+
Foreground children never load the parent's ambient extensions: they share the parent's process, and loading them would start a second copy of every ambient extension, including this one, inside it. Agents that need MCP tools (`mcpDirectTools`, or MCP tools from an ambient adapter such as pi-mcp-adapter) or models from a provider extension must run as background children (`async: true`), which load the ambient extensions inside the detached runner process unless the agent sets `extensions` or the capability ceiling denies extensions.
|
|
313
315
|
|
|
314
316
|
## External job provider bridge
|
|
315
317
|
|
|
@@ -363,7 +365,7 @@ subagent({ action: "inspector.status", id: "<run-id>", index: 0 })
|
|
|
363
365
|
subagent({ action: "inspector.close", id: "<run-id>", index: 0 })
|
|
364
366
|
```
|
|
365
367
|
|
|
366
|
-
The inspector is a raw dashboard pane, not the child
|
|
368
|
+
The inspector is a raw dashboard pane, not the child session and not a literal attach. It reads lifecycle/status/output/mission artifacts and sends `steer` or `stop` through pi-subagents' existing control inbox. Closing it never stops the run.
|
|
367
369
|
|
|
368
370
|
Herdr remains optional. Ordinary launches stay headless, and missing/older Herdr versions affect only Herdr-specific inspector and project-pane actions. FleetView opens the selected active async child with `H`. Use `focus` only with `inspector.open`; Herdr 0.7.5 cannot focus an arbitrary existing raw pane id.
|
|
369
371
|
|
|
@@ -412,6 +414,8 @@ Detached children do not stop when the session does. They are the host process's
|
|
|
412
414
|
|
|
413
415
|
This matters because "is the parent busy?" is the wrong idle signal. A parent that launches a detached run and hands control back — which is what the async launch output tells it to do — is not prompting, streaming, compacting, or running a shell command. A host that reaps sessions on those signals alone will dispose exactly the session that was waiting to be woken.
|
|
414
416
|
|
|
417
|
+
When pi-subagents runs inside a compatible pi-web host, it discovers the versioned `Symbol.for("@agegr/pi-web/session-liveness/v1")` registry and registers one provider for the current session. The provider reports live `queued`/`running` async jobs, active nested descendants (including foreground routes retained after their direct parent settles), foreground controls that still have a scheduling owner or active child, and completion notifications waiting for their batch-delivery timer. Retained terminal history, future schedules, and wait subscriptions do not make a session live by themselves. The registration is replaced on session changes and released during runtime shutdown or reload; other hosts remain unaffected.
|
|
418
|
+
|
|
415
419
|
If your host reclaims idle sessions, keep a session alive while it still has live detached work:
|
|
416
420
|
|
|
417
421
|
- Read run state from the status files under the async run directory rather than from event traffic. A long, quiet workflow sends almost nothing to the parent, so recent-activity heuristics conclude the wrong thing.
|
|
@@ -429,10 +433,18 @@ The main runtime files in this repository:
|
|
|
429
433
|
| File | Purpose |
|
|
430
434
|
|------|---------|
|
|
431
435
|
| `src/extension/index.ts` | Extension registration, tool registration, message/render wiring. |
|
|
436
|
+
| `src/integrations/pi-web-session-liveness.ts` | Optional pi-web idle-eviction liveness bridge. |
|
|
432
437
|
| `src/agents/agents.ts` | Agent and chain discovery, frontmatter parsing. |
|
|
433
438
|
| `src/runs/foreground/subagent-executor.ts` | Main execution routing for single, parallel, chain, management, status, interrupt, and doctor actions. |
|
|
434
|
-
| `src/runs/foreground/execution.ts` | Core foreground `runSync` handling. |
|
|
435
|
-
| `src/runs/
|
|
439
|
+
| `src/runs/foreground/execution.ts` | Core foreground `runSync` handling: drives one in-process child session per attempt. |
|
|
440
|
+
| `src/runs/shared/child-session.ts` | In-process child session factory (`createAgentSession` behind an injectable seam) and the shared model runtime; used by both launch paths. |
|
|
441
|
+
| `src/runs/shared/child-launch.ts` | Builds the tool plan, typed child runtime config, and session launch for a child in either host process. |
|
|
442
|
+
| `src/runs/shared/child-tool-plan.ts` | Tool, MCP, and extension resolution for a child launch. |
|
|
443
|
+
| `src/runs/shared/child-runtime-config.ts` | `ChildRuntimeConfig`: everything the child-side hooks need. |
|
|
444
|
+
| `src/runs/shared/child-hooks.ts` | The inline hook extensions every child gets (prompt runtime, fast mode, fanout). |
|
|
445
|
+
| `src/runs/background/subagent-runner.ts` | Detached async runner; hosts background child sessions in its own process. |
|
|
446
|
+
| `src/runs/background/run-child-session.ts` | Drives one background child session and mirrors its events into the run artifacts. |
|
|
447
|
+
| `src/runs/background/runner-aliases.ts` | Aliases the host peer packages to the installed pi package for the runner (`JITI_ALIAS`). |
|
|
436
448
|
| `src/runs/background/async-execution.ts` | Background launch support. |
|
|
437
449
|
| `src/runs/background/async-status.ts` | Status discovery and formatting for async runs. |
|
|
438
450
|
| `src/workflows/scripted-workflow.ts` / `src/runs/foreground/subagent-executor.ts` | Scripted workflow orchestration and child launch routing. |
|
|
@@ -440,4 +452,4 @@ The main runtime files in this repository:
|
|
|
440
452
|
| `src/runs/shared/worktree.ts` | Git worktree isolation. |
|
|
441
453
|
| `src/intercom/intercom-bridge.ts` | Runtime intercom bridge instructions and diagnostics. |
|
|
442
454
|
| `src/extension/schemas.ts` / `src/shared/types.ts` | Tool schemas, shared types, and event constants. |
|
|
443
|
-
| `test/unit/` / `test/integration/`
|
|
455
|
+
| `test/unit/` / `test/integration/` | Unit and loader-based integration tests. |
|
package/docs/missions.md
CHANGED
|
@@ -95,6 +95,7 @@ subagent({
|
|
|
95
95
|
id: "evening-review",
|
|
96
96
|
name: "Evening review",
|
|
97
97
|
at: "+30m",
|
|
98
|
+
baseRef: "refs/heads/release",
|
|
98
99
|
workflowScript: `return runs.run("main", { agent: "reviewer", task: "Review the current diff." })`
|
|
99
100
|
})
|
|
100
101
|
```
|
|
@@ -112,6 +113,7 @@ Manage schedules with `schedule.list`, `schedule.show`, `schedule.history`, `sch
|
|
|
112
113
|
Behavior:
|
|
113
114
|
|
|
114
115
|
- Runs always launch async with fresh context and disable automatic mission creation; mission attachment is deferred from this first slice.
|
|
116
|
+
- An optional top-level `baseRef` selects the safe Git ref used by managed worktrees (default `HEAD`); it is persisted with the schedule and forwarded on every fire. The source checkout must still be clean.
|
|
115
117
|
- Definitions, bounded history, append-only events, and per-run receipts are stored with mode `0600`.
|
|
116
118
|
- `overlap` is currently fixed to `skip`; `catchUp` supports `latest` (default) and `none`.
|
|
117
119
|
- `schedule.run-due` lets an external launcher start due project work without making `pi-subagents` a daemon.
|
package/docs/observability.md
CHANGED
|
@@ -6,6 +6,10 @@ Where running subagents show up, how to inspect them, and the files and events t
|
|
|
6
6
|
|
|
7
7
|
Foreground runs stream progress in the conversation while they run. They default to a generous 30-minute wall-clock timeout when neither the call nor the selected agent provides a timeout; a global [`timeoutMs`](configuration.md#timeoutms) config replaces that default, and explicit `timeoutMs`/`maxRuntimeMs` and agent defaults win.
|
|
8
8
|
|
|
9
|
+
A foreground child is a pi session created inside the parent Pi process, not a second `pi` process. A run timeout, tool timeout, interrupt, or stop aborts the child session and disposes it. Detach keeps the session running inside the parent and publishes the same receipt and completion notification as before.
|
|
10
|
+
|
|
11
|
+
A background child is a pi session created inside the detached runner process. The runner mirrors session events into `events.jsonl`, `output-<index>.log`, and the transcript. Interrupt and stop abort the child session; steer requests are delivered with the session's `steer` or `followUp`.
|
|
12
|
+
|
|
9
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.
|
|
10
14
|
|
|
11
15
|
Press Pi's configured expand key (`Ctrl+O` by default) to expand the full streaming view with complete output per step. Running-card hints also advertise `Ctrl+Alt+F` for the Fleet inspector.
|
|
@@ -56,7 +60,7 @@ After you expand it:
|
|
|
56
60
|
|
|
57
61
|
When the focused editor is empty, press `↓` or `←` to expand the summary into `main` plus active children with agent name, state, elapsed time, and token usage. When providers report usage, `window` is the latest assistant turn's input plus cache-read tokens, while `spent` keeps the cumulative input-plus-output total. Old run artifacts without window data keep the existing token-total label. The compact line counts active current-session work and Herdr project panes. Then use `↑`/`↓` or `j`/`k` to select a child and `Enter` to open the Fleet lobby; press `Enter` or `H` there to open its child-specific Herdr inspector. Printable navigation keys are never intercepted before activation.
|
|
58
62
|
|
|
59
|
-
FleetView replaces the legacy above-editor async widget by default. Successful background completions stay quiet so inactive Pi tabs are not marked unread, while failed or paused completions still notify the originating session. Parallel runs show every active child independently. Chains with parallel groups keep their grouped shape in progress and results, so failed or paused agents stay visible next to completed ones. When a child is explicitly allowed to fan out with `tools: subagent` or `allowNestedSubagents: true`, its nested runs appear under that parent child in the main status tree instead of being hidden inside the child
|
|
63
|
+
FleetView replaces the legacy above-editor async widget by default. Successful background completions stay quiet so inactive Pi tabs are not marked unread, while failed or paused completions still notify the originating session. Parallel runs show every active child independently. Chains with parallel groups keep their grouped shape in progress and results, so failed or paused agents stay visible next to completed ones. When a child is explicitly allowed to fan out with `tools: subagent` or `allowNestedSubagents: true`, its nested runs appear under that parent child in the main status tree instead of being hidden inside the child session.
|
|
60
64
|
|
|
61
65
|
## The fleet inspector
|
|
62
66
|
|
|
@@ -187,7 +191,7 @@ The status/result fields are: `lifecycleArtifactVersion`, `runId`/`id`, `session
|
|
|
187
191
|
|
|
188
192
|
### Runtime extension acknowledgement
|
|
189
193
|
|
|
190
|
-
Cooperating child extensions can acknowledge child-runtime registration by emitting `subagent:acknowledge-extension` on the child
|
|
194
|
+
Cooperating child extensions can acknowledge child-runtime registration by emitting `subagent:acknowledge-extension` on the child session's `pi.events` bus with payload `{ id: string }`. The process that hosts the child session (the parent for foreground children, the runner for background children) captures the acknowledgement in memory.
|
|
191
195
|
|
|
192
196
|
Acknowledgement ids are self-declared opaque strings. They must be non-empty, at most 128 characters, contain only `A-Z`, `a-z`, `0-9`, `.`, `_`, `:`, `@`, `+`, or `-`, and must not contain `/`, `\`, or `..`.
|
|
193
197
|
|
|
@@ -201,19 +205,13 @@ The reported `runtimeAcknowledgedExtensions` projection is `{ version: 1, source
|
|
|
201
205
|
|
|
202
206
|
Lifecycle artifact v3 adds `process-terminal-candidate.json` (private runner evidence) and `process-terminal.json` (the public proof projection).
|
|
203
207
|
|
|
204
|
-
A proof is `observed` only after the live parent observes the exact detached runner's `close` event
|
|
208
|
+
A proof is `observed` only after the live parent observes the exact detached runner's `close` event and any tracked canonical-session lease is free. Children run inside the runner process, so the candidate records no separate writer processes. If the observer is unavailable, the proof is `unknown`; do not infer process exit from `endedAt`, result-file existence, PID disappearance, or lease-directory absence.
|
|
205
209
|
|
|
206
210
|
The `subagent:process-terminal` event and RPC `ping.capabilities.processTerminalProof` expose this status. Process proof is point-in-time evidence and remains separate from execution success or stopped/non-resumable state.
|
|
207
211
|
|
|
208
|
-
### Child
|
|
209
|
-
|
|
210
|
-
Foreground and async runners share bounded child-protocol handling:
|
|
212
|
+
### Child session events
|
|
211
213
|
|
|
212
|
-
|
|
213
|
-
- Stderr retains only its latest 128 KiB.
|
|
214
|
-
- Split UTF-8 and final unterminated JSON events remain valid.
|
|
215
|
-
- `agent_end.willRetry` defers completion until the child settles.
|
|
216
|
-
- Current Pi builds use `agent_settled` as the terminal watermark; older builds retain the bounded terminal-message fallback.
|
|
214
|
+
Both launch paths subscribe to the child session's event stream directly; there is no stdout protocol. The `events.jsonl` artifact mirrors those events with `message_update` dropped, and the transcript records them with `message_update` projected the same way pi's JSON mode prints it. `agent_end.willRetry` defers completion until the child settles, and `agent_settled` is the terminal watermark; a child whose run does not settle shortly after its terminal event is aborted and finished without it.
|
|
217
215
|
|
|
218
216
|
## Workflow and debug artifacts
|
|
219
217
|
|
|
@@ -238,7 +236,7 @@ For npm package projects, project-scoped artifacts need a `.npmignore` rule (or
|
|
|
238
236
|
|
|
239
237
|
## Sessions
|
|
240
238
|
|
|
241
|
-
Session files are stored under a per-run session directory. With `context: "fork"`, each child starts
|
|
239
|
+
Session files are stored under a per-run session directory. With `context: "fork"`, each child starts from a branched session file produced from the parent's current leaf (foreground children open it in-process; background children receive it as `--session`). That is a real session fork, not an injected summary. An omitted launch `context` that resolves through `defaultContext: fork` uses the same branch when the parent session file and current leaf exist, and otherwise starts fresh.
|
|
242
240
|
|
|
243
241
|
## Completion notifications
|
|
244
242
|
|
package/docs/tool-reference.md
CHANGED
|
@@ -94,7 +94,7 @@ The complete plain-JSON inventory is validated before the first launch (maximum
|
|
|
94
94
|
| `missionId` | string | - | Attach a workflow to an existing project mission instead of creating its default enclosing mission. |
|
|
95
95
|
| `mission` | object/false | auto-create | Override the default enclosing mission with `{ title \| summary, objective?, goal?, budget?, labels? }`. Set exactly one non-empty `title` or `summary`; `objective` and `labels` are optional. `goal` may only be `true`, requires `budget.tokens`, and enables continuation notices. Pass `false` for an intentionally ephemeral workflow with no mission for it or its children and no `state` global. Explicit mission persistence failures are strict. |
|
|
96
96
|
| `handoffPath` | string | - | Aggregate handoff manifest for `action: "worktree.discard"` or lane evidence actions, or optional explicit metadata for `action: "worktree.cleanup"`. |
|
|
97
|
-
| `repo` | string | runtime cwd | Repository path for `action: "worktree.cleanup"`; plan mode only. The configured worktree base filters candidates but never discovers them. |
|
|
97
|
+
| `repo` | string | runtime cwd | Repository path for `action: "worktree.cleanup"`; plan mode only. The configured worktree base filters candidates by their per-project folder under it but never discovers them. |
|
|
98
98
|
| `planId` | string | - | Reserved for a future `worktree.cleanup` apply action; rejected by the current plan-only action. |
|
|
99
99
|
| `mode` | `steer \| follow_up \| auto \| plan \| apply` | - | Delivery mode for `action: "steer"`; `worktree.cleanup` currently accepts `plan` only. Apply/removal is reserved for a later change. |
|
|
100
100
|
| `laneId` | string | - | Exact `runId` stored in the handoff manifest for `lane.status`, `lane.recordMerge`, or `lane.recordSupersession`. |
|
|
@@ -104,10 +104,11 @@ The complete plain-JSON inventory is validated before the first launch (maximum
|
|
|
104
104
|
| `view` | `fleet \| transcript` | - | Optional `status` view for the active fleet surface or transcript tail inspection. |
|
|
105
105
|
| `lines` | number | `80` | Maximum transcript lines for `action: "status", view: "transcript"`; capped at 500. |
|
|
106
106
|
| `agentScope` | `user \| project \| both` | `both` | Agent discovery scope. Project wins on collisions. |
|
|
107
|
-
| `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. |
|
|
108
|
-
| `async` | boolean | default-on | Background execution. Workflows default to background. `async:false` blocks the parent until completion. |
|
|
107
|
+
| `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. |
|
|
108
|
+
| `async` | boolean | default-on | Background execution. Workflows default to background. `async:false` blocks the parent until completion and runs the child as a session inside the parent Pi process; such foreground children never load the parent's ambient extensions, so agents that need MCP tools (`mcpDirectTools`, or MCP tools from an ambient adapter such as pi-mcp-adapter) or models from a provider extension must run as background children, which load them inside the detached runner process. |
|
|
109
109
|
| `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. |
|
|
110
110
|
| `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. |
|
|
111
|
+
| `baseRef` | string | `HEAD` | Git ref used as the base commit for managed worktrees. It must be a safe Git ref that resolves to a commit; source-checkout cleanliness is still checked before allocation. For workflowScript, set it on the outer request as a default or on an individual `runs.run`/`runs.all` child to override it. |
|
|
111
112
|
| `timeoutMs` / `maxRuntimeMs` | number | config `timeoutMs`, else 30 min foreground / single-agent async | Optional run-level max runtime in milliseconds. When omitted, the global [`timeoutMs`](configuration.md#timeoutms) config provides the default; absent that, foreground and plain single-agent async runs fall back to 30 minutes, while composite async runs (chains, parallel tasks, workflows) stay unbounded at the top level. Expiration of this run-level deadline is terminal and does not trigger `fallbackModels`. |
|
|
112
113
|
| `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. |
|
|
113
114
|
| `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,7 +120,7 @@ The complete plain-JSON inventory is validated before the first launch (maximum
|
|
|
119
120
|
| `share` | boolean | false | Upload session export to GitHub Gist. |
|
|
120
121
|
| `sessionDir` | string | derived | Override session log directory. |
|
|
121
122
|
| `acceptance` | string/object/false | inferred | Configure evidence gates. See [Acceptance gates](#acceptance-gates). |
|
|
122
|
-
| `gate` | string | - | One host-run verification command, shorthand for `acceptance: { level: "verified", verify: [{ id: "gate", command }] }`. Also valid on individual `runs.run`/`runs.all` items.
|
|
123
|
+
| `gate` | string | - | One host-run verification command, shorthand for `acceptance: { level: "verified", verify: [{ id: "gate", command }] }`. Also valid on individual `runs.run`/`runs.all` items. Rejects `acceptance` except `false` (treated as omitted), and rejects retained `resume`. |
|
|
123
124
|
|
|
124
125
|
### Budget guidance for writers
|
|
125
126
|
|
|
@@ -139,7 +140,7 @@ In workflow runs that omit `context`, each `runs.run` child follows the global `
|
|
|
139
140
|
|
|
140
141
|
`runs.steer(key, message, options?)` targets a stable key already launched by `runs.run` or `runs.all`. It does not accept a raw run id. Options are `mode?: "steer" | "follow_up" | "auto"`, `index?: number`, and `ackTimeoutMs?: number`. The promise returns `{ key, state, requestId?, deliveryStatus?, targets?, error? }`, where `state` is `queued`, `delivered`, `missed`, or `failed`.
|
|
141
142
|
|
|
142
|
-
The workflow trace records the attempt and receipt. Always await, return, or include the promise in an awaited standard Promise combinator. Unawaited steering calls reject workflow completion after the side effect settles. `Promise.race` remains the rolling primitive.
|
|
143
|
+
The workflow trace records the attempt and receipt. Always await, return, or include the promise in an awaited standard Promise combinator. Unawaited steering calls reject workflow completion after the side effect settles. `Promise.race` remains the rolling primitive. Foreground children are steered through their in-process session (`steer` and `auto` interrupt at the next safe point and report `delivered`; `follow_up` queues until the run settles and reports `queued`). Async children use the file control inbox. Steering recovery is disabled in both cases.
|
|
143
144
|
|
|
144
145
|
For advanced rolling fanout, keep the launched `runs.run` promises in ordinary JavaScript data only when every promise is later observed with direct `await`, `Promise.race`, or `Promise.all`. `Promise.race` gives the next completed child, `runs.steer` can challenge a still-running keyed sibling, and `Promise.all` collects the rest. No separate `runs.start`, `runs.next`, or `runs.collect` API is exposed.
|
|
145
146
|
|
|
@@ -246,7 +247,7 @@ Agent definitions are not loaded into context by default. Management actions let
|
|
|
246
247
|
|
|
247
248
|
Rules:
|
|
248
249
|
|
|
249
|
-
- `capabilities: true` changes `action: "list"` to compact one-line rows and adds `details.agentCapabilities: { agents, restrictedCount, capabilityCeilingSources? }`. Each agent row includes source, aliases, runner type/capabilities, tools, MCP direct tools, mutation tools, model/thinking/fallbacks, default async/timeout, output path/mode, skills/extensions, and whether the current capability ceiling allows execution. It never includes an agent's system prompt. Rows show declared/default capabilities, not
|
|
250
|
+
- `capabilities: true` changes `action: "list"` to compact one-line rows and adds `details.agentCapabilities: { agents, restrictedCount, capabilityCeilingSources? }`. Each agent row includes source, aliases, runner type/capabilities, tools, MCP direct tools, mutation tools, model/thinking/fallbacks, default async/timeout, output path/mode, skills/extensions, and whether the current capability ceiling allows execution. External CLI rows include `runner.command`, `runner.available`, and a bounded `runner.unavailableReason` when passive PATH/PATHEXT/X_OK lookup cannot find the command. It never includes an agent's system prompt. Rows show declared/default capabilities and command discoverability, not authentication, version compatibility, or successful launch; launch preflight remains authoritative.
|
|
250
251
|
- `create` uses `config.scope`, not `agentScope`.
|
|
251
252
|
- `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.
|
|
252
253
|
- `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`.
|
|
@@ -297,6 +298,12 @@ The manifest stores one of these fail-closed eligibility states: `active` (an ow
|
|
|
297
298
|
|
|
298
299
|
## Status and control actions
|
|
299
300
|
|
|
301
|
+
### Failed lane recovery and execution-mode boundaries
|
|
302
|
+
|
|
303
|
+
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.
|
|
304
|
+
|
|
305
|
+
For backlog lanes and other subagent-governed workflows, external/foreground/CLI fallback requires explicit owner approval. Do not silently switch to `interactive_shell`, `pi -ne`, Codex/Claude/Cursor CLI, a foreground agent, or another external mode. `interactive_shell` remains valid when the user explicitly requests visible foreground/CLI work or the task is outside the governed subagent protocol. Pi core may print a generic `pi -ne` extension-load hint; that out-of-repo hint is not protocol-approved fallback. Configured native model/provider fallback remains governed by its own contract.
|
|
306
|
+
|
|
300
307
|
```ts
|
|
301
308
|
subagent({ action: "status" })
|
|
302
309
|
subagent({ action: "status", view: "fleet" })
|
|
@@ -332,7 +339,7 @@ subagent({ action: "doctor" })
|
|
|
332
339
|
- Multi-child async runs and remembered foreground single, parallel, or chain runs can be revived by passing `index` to choose the child.
|
|
333
340
|
- Nested runs can be resumed by nested id when their live route or persisted nested session metadata is available.
|
|
334
341
|
- Completed external-job runs can use the same `resume` action as a provider follow-up when the registered provider exposes `followUp(input)`. Running external-job parents fail closed with guidance to wait for completion. Unsupported providers fail with an update/reload message.
|
|
335
|
-
- Revive starts a new child
|
|
342
|
+
- Revive starts a new child session from the old session context; it does not resume the live session, and it requires the chosen child to have a persisted `.jsonl` session file.
|
|
336
343
|
- Direct revival takes an exclusive cross-process lease on the canonical session file until the new child finishes. A concurrent attempt fails before Pi is spawned and identifies the owning revived run; dead-owner leases are reclaimed only when staleness can be proved.
|
|
337
344
|
|
|
338
345
|
### stop
|
|
@@ -384,7 +391,7 @@ When one host-run command is the entire verification contract, use the `gate` sh
|
|
|
384
391
|
{ workflowScript: `return runs.run("impl", { agent: "worker", task: "Implement the fix", gate: "npm test" })` }
|
|
385
392
|
```
|
|
386
393
|
|
|
387
|
-
`gate` normalizes to verified acceptance with that single command, so the runtime executes it on the host and records the result as evidence. Verification results are memoized per tracked workspace state and effective environment, so an unchanged tree does not rerun the same command. Use explicit `acceptance.verify` when you need multiple commands, timeouts, or custom criteria. `gate`
|
|
394
|
+
`gate` normalizes to verified acceptance with that single command, so the runtime executes it on the host and records the result as evidence. Verification results are memoized per tracked workspace state and effective environment, so an unchanged tree does not rerun the same command. Use explicit `acceptance.verify` when you need multiple commands, timeouts, or custom criteria. `gate` rejects `acceptance` except `false` (treated as omitted), and rejects retained `resume` items. With `worktree: true`, the gate runs inside the child's managed worktree.
|
|
388
395
|
|
|
389
396
|
### Levels and inference
|
|
390
397
|
|
package/docs/watchdog.md
CHANGED
|
@@ -151,4 +151,4 @@ Values are `allow`, `ask`, and `deny`. Agent rules override global ones, omitted
|
|
|
151
151
|
|
|
152
152
|
`ask` pauses that exact tool call and sends a bounded, redacted preview to a one-call arbiter owned by the child watchdog, using the configured child-watchdog model. The arbiter returns only `approve` or `deny` and does not notify the parent. A disabled watchdog, missing model/auth, timeout, malformed response, or runtime error denies the call with a clear error. Requests and decisions are written to bounded audit JSONL. `contact_supervisor` and the optional `pi-intercom` extension are never permission-gated.
|
|
153
153
|
|
|
154
|
-
Bash is always passed through; bash rules are rejected. Use `pi-guard` for command-level policy.
|
|
154
|
+
Bash is always passed through; bash rules are rejected. Use `pi-guard` for command-level policy. Children are pi sessions inside the parent process (foreground) or the detached runner process (background), not separate `pi` binaries, so there is no per-child command wrapper; load `pi-guard` into a child through the agent's `extensions` or `subagentOnlyExtensions`, and background children also pick it up as an ambient extension. External CLI profiles are opaque processes, so native permissions cannot intercept their tools; launches with effective `ask` or `deny` rules are rejected for external CLI agents.
|