pi-subagents 0.70.0 → 0.70.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.
Files changed (127) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +1 -1
  3. package/agents/claude-code-writer.md +1 -0
  4. package/agents/codex-exec-writer.md +1 -0
  5. package/agents/cursor-agent-writer.md +1 -0
  6. package/agents/worker.md +1 -0
  7. package/docs/agents.md +6 -7
  8. package/docs/configuration.md +2 -0
  9. package/docs/extension-api.md +2 -0
  10. package/docs/models.md +1 -1
  11. package/docs/observability.md +1 -1
  12. package/docs/standalone-background.md +4 -4
  13. package/docs/tool-reference.md +3 -7
  14. package/inspector-runner.mjs +1 -1
  15. package/package.json +1 -1
  16. package/skills/pi-subagents/SKILL.md +1 -0
  17. package/skills/pi-subagents/references/management-authoring-rpc.md +1 -1
  18. package/skills/pi-subagents/references/multi-lane-orchestration.md +8 -0
  19. package/skills/pi-subagents/references/prompting-and-roles.md +14 -13
  20. package/src/agents/agent-management.d.ts.map +1 -1
  21. package/src/agents/agent-management.js +11 -25
  22. package/src/agents/agent-management.js.map +1 -1
  23. package/src/agents/agent-serializer.d.ts.map +1 -1
  24. package/src/agents/agent-serializer.js +0 -4
  25. package/src/agents/agent-serializer.js.map +1 -1
  26. package/src/agents/agents.d.ts +17 -4
  27. package/src/agents/agents.d.ts.map +1 -1
  28. package/src/agents/agents.js +39 -22
  29. package/src/agents/agents.js.map +1 -1
  30. package/src/agents/runtime-agent-registry.d.ts +8 -3
  31. package/src/agents/runtime-agent-registry.d.ts.map +1 -1
  32. package/src/agents/runtime-agent-registry.js +14 -9
  33. package/src/agents/runtime-agent-registry.js.map +1 -1
  34. package/src/extension/index.js +1 -1
  35. package/src/extension/index.js.map +1 -1
  36. package/src/runs/background/async-execution.d.ts.map +1 -1
  37. package/src/runs/background/async-execution.js +0 -34
  38. package/src/runs/background/async-execution.js.map +1 -1
  39. package/src/runs/background/async-resume.d.ts.map +1 -1
  40. package/src/runs/background/async-resume.js +1 -4
  41. package/src/runs/background/async-resume.js.map +1 -1
  42. package/src/runs/background/run-status.d.ts.map +1 -1
  43. package/src/runs/background/run-status.js +6 -4
  44. package/src/runs/background/run-status.js.map +1 -1
  45. package/src/runs/background/runner-aliases.d.ts.map +1 -1
  46. package/src/runs/background/runner-aliases.js +26 -15
  47. package/src/runs/background/runner-aliases.js.map +1 -1
  48. package/src/runs/background/subagent-runner.d.ts +1 -5
  49. package/src/runs/background/subagent-runner.d.ts.map +1 -1
  50. package/src/runs/background/subagent-runner.js +31 -113
  51. package/src/runs/background/subagent-runner.js.map +1 -1
  52. package/src/runs/foreground/execution.d.ts.map +1 -1
  53. package/src/runs/foreground/execution.js +0 -97
  54. package/src/runs/foreground/execution.js.map +1 -1
  55. package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  56. package/src/runs/foreground/subagent-executor.js +0 -2
  57. package/src/runs/foreground/subagent-executor.js.map +1 -1
  58. package/src/runs/shared/acceptance.d.ts.map +1 -1
  59. package/src/runs/shared/acceptance.js +7 -40
  60. package/src/runs/shared/acceptance.js.map +1 -1
  61. package/src/runs/shared/child-hooks.d.ts +1 -3
  62. package/src/runs/shared/child-hooks.d.ts.map +1 -1
  63. package/src/runs/shared/child-hooks.js +1 -16
  64. package/src/runs/shared/child-hooks.js.map +1 -1
  65. package/src/runs/shared/child-launch.d.ts +0 -2
  66. package/src/runs/shared/child-launch.d.ts.map +1 -1
  67. package/src/runs/shared/child-launch.js +1 -2
  68. package/src/runs/shared/child-launch.js.map +1 -1
  69. package/src/runs/shared/child-session.d.ts +8 -9
  70. package/src/runs/shared/child-session.d.ts.map +1 -1
  71. package/src/runs/shared/child-session.js +67 -2
  72. package/src/runs/shared/child-session.js.map +1 -1
  73. package/src/runs/shared/dynamic-fanout.js +1 -1
  74. package/src/runs/shared/dynamic-fanout.js.map +1 -1
  75. package/src/runs/shared/parallel-utils.d.ts +0 -1
  76. package/src/runs/shared/parallel-utils.d.ts.map +1 -1
  77. package/src/runs/shared/parallel-utils.js.map +1 -1
  78. package/src/runs/shared/single-output.d.ts.map +1 -1
  79. package/src/runs/shared/single-output.js +10 -2
  80. package/src/runs/shared/single-output.js.map +1 -1
  81. package/src/runs/shared/subagent-control.d.ts.map +1 -1
  82. package/src/runs/shared/subagent-control.js +6 -19
  83. package/src/runs/shared/subagent-control.js.map +1 -1
  84. package/src/shared/launch-contract.d.ts.map +1 -1
  85. package/src/shared/launch-contract.js +0 -1
  86. package/src/shared/launch-contract.js.map +1 -1
  87. package/src/shared/pruned-fork.d.ts +1 -1
  88. package/src/shared/pruned-fork.d.ts.map +1 -1
  89. package/src/shared/pruned-fork.js +2 -9
  90. package/src/shared/pruned-fork.js.map +1 -1
  91. package/src/shared/types.d.ts +3 -10
  92. package/src/shared/types.d.ts.map +1 -1
  93. package/src/shared/types.js.map +1 -1
  94. package/src/slash/slash-commands.js +1 -1
  95. package/src/slash/slash-commands.js.map +1 -1
  96. package/src/slash/subagents-admin.d.ts.map +1 -1
  97. package/src/slash/subagents-admin.js +4 -5
  98. package/src/slash/subagents-admin.js.map +1 -1
  99. package/src/tui/render.d.ts.map +1 -1
  100. package/src/tui/render.js +8 -7
  101. package/src/tui/render.js.map +1 -1
  102. package/src/watchdog/permission-arbiter.d.ts.map +1 -1
  103. package/src/watchdog/permission-arbiter.js +13 -8
  104. package/src/watchdog/permission-arbiter.js.map +1 -1
  105. package/src/watchdog/review.d.ts +2 -1
  106. package/src/watchdog/review.d.ts.map +1 -1
  107. package/src/watchdog/review.js +13 -6
  108. package/src/watchdog/review.js.map +1 -1
  109. package/src/workflows/scripted-workflow.d.ts.map +1 -1
  110. package/src/workflows/scripted-workflow.js +1 -3
  111. package/src/workflows/scripted-workflow.js.map +1 -1
  112. package/src/runs/shared/completion-evidence.d.ts +0 -31
  113. package/src/runs/shared/completion-evidence.d.ts.map +0 -1
  114. package/src/runs/shared/completion-evidence.js +0 -54
  115. package/src/runs/shared/completion-evidence.js.map +0 -1
  116. package/src/runs/shared/completion-guard.d.ts +0 -35
  117. package/src/runs/shared/completion-guard.d.ts.map +0 -1
  118. package/src/runs/shared/completion-guard.js +0 -214
  119. package/src/runs/shared/completion-guard.js.map +0 -1
  120. package/src/runs/shared/llm-intent-arbiter.d.ts +0 -48
  121. package/src/runs/shared/llm-intent-arbiter.d.ts.map +0 -1
  122. package/src/runs/shared/llm-intent-arbiter.js +0 -235
  123. package/src/runs/shared/llm-intent-arbiter.js.map +0 -1
  124. package/src/runs/shared/task-intent.d.ts +0 -38
  125. package/src/runs/shared/task-intent.d.ts.map +0 -1
  126. package/src/runs/shared/task-intent.js +0 -213
  127. package/src/runs/shared/task-intent.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.70.1] - 2026-09-20
6
+
7
+ ### Highlights
8
+
9
+ - Delegated tasks no longer fail solely because they finish without editing files.
10
+ - Runtime-added agents now honor configured model, provider, and thinking preferences.
11
+ - Foreground children launch reliably when Pi is installed outside the extension's own dependency tree.
12
+ - Pi 0.86.1 support improves watchdog checks, provider-backed summaries, packaging, and standalone use.
13
+
14
+ ### Changed
15
+
16
+ - Stop guessing whether task wording requires file edits. Successful tasks now follow their process result and explicitly configured output and acceptance checks. The `completionGuard` setting and `PI_SUBAGENTS_LLM_INTENT_ARBITER` switch have been removed. Thanks to [@SuTang-vain](https://github.com/SuTang-vain) for the reproduction that led to this change in [#2351](https://github.com/nicobailon/pi-subagents/issues/2351).
17
+ - Clarify that a custom agent file fully replaces a bundled agent with the same name. Custom implementation agents must declare `acceptanceRole: writer` to receive writer acceptance defaults.
18
+ - Update delegation guidance so large changes are split only when they contain independently testable parts.
19
+
20
+ ### Fixed
21
+
22
+ - Apply `subagents.defaultModel`, `defaultProvider`, `defaultThinking`, and model-tier overrides to runtime-registered agents. Thanks to [@bioShaun](https://github.com/bioShaun) for [#2368](https://github.com/nicobailon/pi-subagents/pull/2368).
23
+ - Show each workflow child's resolved model and thinking level in parent status output. Thanks to [@grahama1970](https://github.com/grahama1970) for [#2364](https://github.com/nicobailon/pi-subagents/pull/2364).
24
+ - Preserve watchdog working-directory context and authenticated provider behavior for pruned-fork overflow summaries on Pi 0.86.1. Thanks to [@chem](https://github.com/chem) for [#2362](https://github.com/nicobailon/pi-subagents/issues/2362).
25
+ - Launch the packaged inspector bootstrap from its compiled JavaScript instead of an absent TypeScript source. Thanks to [@pablog12](https://github.com/pablog12) for [#2360](https://github.com/nicobailon/pi-subagents/issues/2360).
26
+ - Resolve the host `pi-coding-agent` package and its exports from the Pi installation that owns the session, so foreground children work across npm-hosted layouts without loading a second SDK instance. Thanks to [@nazerim](https://github.com/nazerim) for [#2348](https://github.com/nicobailon/pi-subagents/issues/2348).
27
+ - Show an actionable expand shortcut when a host cannot provide its configured keybinding label.
28
+ - Stop test-only background runners when their owning test process exits, and isolate test temporary data to reduce filesystem and Spotlight load.
29
+
5
30
  ## [0.70.0] - 2026-09-19
6
31
 
7
32
  ### 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. Background children use the host's SDK: npm Pi keeps its detached Node runner; the official Pi 0.85.1 Linux x64 standalone release loads the same runner through Pi's embedded SDK, without a separate SDK install. See [Standalone background execution](docs/standalone-background.md) for the supported boundary and validation gate.
17
+ That is the only required step. Background children use the host's SDK: npm Pi keeps its detached Node runner; the official Pi 0.86.1 Linux x64 standalone release loads the same runner through Pi's embedded SDK, without a separate SDK install. See [Standalone background execution](docs/standalone-background.md) for the supported boundary and validation gate.
18
18
 
19
19
  ## Try this first
20
20
 
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: claude-code-writer
3
3
  description: Explicit file-writing Claude Code CLI mode; requires local authentication and trusted user settings/hooks
4
+ acceptanceRole: writer
4
5
  runner:
5
6
  type: external-cli
6
7
  adapter: claude-code-writer
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: codex-exec-writer
3
3
  description: Explicit workspace-writing one-shot execution through the installed Codex CLI
4
+ acceptanceRole: writer
4
5
  runner:
5
6
  type: external-cli
6
7
  adapter: codex-exec-writer
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: cursor-agent-writer
3
3
  description: Explicit workspace-writing one-shot execution through the installed Cursor CLI
4
+ acceptanceRole: writer
4
5
  runner:
5
6
  type: external-cli
6
7
  adapter: cursor-agent-writer
package/agents/worker.md CHANGED
@@ -2,6 +2,7 @@
2
2
  name: worker
3
3
  description: Implementation agent for normal tasks and approved oracle handoffs
4
4
  aliases: developer, coder, implementer, develop
5
+ acceptanceRole: writer
5
6
  thinking: high
6
7
  systemPromptMode: replace
7
8
  inheritProjectContext: true
package/docs/agents.md CHANGED
@@ -236,6 +236,8 @@ Disable and restore:
236
236
  - `subagent({ action: "eject", agent: "reviewer" })` copies a bundled builtin or package agent verbatim into the user or project agent dir (default `user`) as an editable custom file that shadows the original.
237
237
  - `subagent({ action: "reset", agent: "reviewer" })` deletes the scope's custom agent file and/or settings override entry, restoring the bundled default. It refuses if no bundled default exists (use `delete` for purely custom agents).
238
238
 
239
+ A custom agent file that shadows a bundled agent replaces the bundled definition wholesale; it does not inherit omitted frontmatter, including `acceptanceRole`. Custom implementation profiles must declare `acceptanceRole: writer` explicitly when writer acceptance inference is intended. Without it, automatic acceptance uses lightweight attestation as described in the [frontmatter reference](#frontmatter-reference).
240
+
239
241
  `eject`, `disable`, `enable`, and `reset` accept `agentScope: "user" | "project"` and operate in one scope at a time. Project overrides still win over user ones, so a project-scope disable survives a user-scope `enable` until you target the project scope.
240
242
 
241
243
  ## Running external CLI agents on a Herdr saved machine
@@ -317,7 +319,6 @@ timeoutMs: 900000
317
319
  toolTimeoutMs: 600000
318
320
  acceptance: {"level":"none","reason":"lightweight lookup"}
319
321
  acceptanceRole: read-only
320
- completionGuard: false
321
322
  interactive: true
322
323
  maxSubagentDepth: 1
323
324
  allowNestedSubagents: true
@@ -364,9 +365,8 @@ Field notes:
364
365
  | `timeoutMs` | Positive integer default runtime deadline in milliseconds for single-agent launches. Foreground launches use 30 minutes when neither the call nor agent provides a timeout; explicit `timeoutMs`/`maxRuntimeMs` and agent defaults win. |
365
366
  | `toolTimeoutMs` | Optional positive integer hard per-tool-call deadline in milliseconds. An explicit call value wins, then this agent default, global `toolTimeoutMs`, and `PI_SUBAGENT_TOOL_TIMEOUT_MS`. When omitted, known-fast built-in tools get a five-minute default; long-running tools get attention notices but no hard default. It does not extend the run-level deadline; `contact_supervisor`, `intercom`, and `bg_wait` are exempt. |
366
367
  | `acceptance` | Acceptance default for single-agent launches. Use a scalar level such as `checked` or an inline/block YAML map such as `{ level: "none", reason: "lightweight lookup" }`. Explicit call values win; chain and parallel acceptance remains task/step configuration. |
367
- | `acceptanceRole` | Optional `read-only` or `writer` role for automatic acceptance inference. Explicit task mutation or no-edit intent wins; otherwise the declared role replaces agent-name guessing. This does not grant or revoke tools. |
368
- | `mutationTools` | Comma-separated extension tool names whose calls count as mutation attempts for the completion guard. This declares evidence only; list and load each tool through `tools` and its extension provider as usual. |
369
- | `completionGuard` | Set `false` only for non-implementation agents that may mention implementation words while using mutation-capable tools such as `bash`. |
368
+ | `acceptanceRole` | Optional `read-only` or `writer` role for automatic acceptance inference. When omitted, automatic acceptance uses lightweight attestation; task wording and agent names do not escalate it. This does not grant or revoke tools. |
369
+ | `mutationTools` | Comma-separated extension tool names treated as mutating activity for runtime diagnostics, long-running-tool status, and timeout recovery. This is diagnostic only and never determines successful completion. List and load each tool through `tools` and its extension provider as usual. |
370
370
  | `interactive` | Parsed for compatibility but not currently enforced. |
371
371
  | `maxSubagentDepth` | Tightens nested delegation for this agent's children. |
372
372
  | `memory` | Opt-in role-specific persistent memory. See below. |
@@ -377,7 +377,7 @@ Hosts can import `registerRequiredChildExtensions` from `pi-subagents/required-c
377
377
 
378
378
  Required paths follow ordinary extension resolution and survive agent defaults and `extensions: []` across native foreground, detached, nested, and recovery launches. A `capabilityCeiling.denyExtensions` conflict or required load/provider-registration failure rejects before model resolution. External runners are excluded, and status/watch paths do not query the registry.
379
379
 
380
- When the completion guard would flag missing edits, a model intent arbiter can rescue only a confident read-only task. Foreground uses the parent model; native background uses the child attempt's existing model services after child shutdown. Ordinary completions do not invoke classification or resolve arbiter auth. Disabled arbitration (`PI_SUBAGENTS_LLM_INTENT_ARBITER=0`), unavailable model/auth, errors, ambiguous intent, and tasks over 8,000 characters keep the guard result. The classification prompt has a 10-second timeout; preceding auth and module loading are outside that bound. This does not change capability limits or the v1 contract's default-off guard and explicit missing-effect semantics.
380
+ Successful completion is determined by observable gates such as process outcome, required outputs, explicit acceptance, verification commands, independent review, and staged-index integrity. Best-effort mutation observations remain diagnostic: unchanged or unknown evidence does not fail a run, and observed changes do not prove correctness.
381
381
 
382
382
  ## Per-agent persistent memory
383
383
 
@@ -449,8 +449,7 @@ More rules:
449
449
  - `mcp:` entries are split out and forwarded as direct MCP selections without granting normal builtins unless those builtins are also listed.
450
450
  - Path-like `tools` entries, such as extension paths or `.ts`/`.js` files, are treated as tool-extension paths rather than tool names.
451
451
  - Internal runtime tools such as `structured_output` are added to an explicit allowlist only when their contract is active.
452
- - Unknown extension tool calls count as mutation attempts only when their names are listed in `mutationTools`; undeclared unknown tools keep the no-edit guard active.
453
- - Agents that declare only known read-only builtin tools skip the implementation completion guard. `bash`, unknown tools, and MCP tools stay mutation-capable. Use `completionGuard: false` for bash-enabled validators or advisors that should never be judged as implementation agents.
452
+ - Unknown extension tool calls are treated as mutating diagnostic activity only when their names are listed in `mutationTools`.
454
453
 
455
454
  Examples:
456
455
 
@@ -420,6 +420,8 @@ export PI_SUBAGENTS_PI_CODING_AGENT_PACKAGE_ROOT=/path/to/pi-coding-agent-packag
420
420
 
421
421
  Overrides host-package discovery for spawned children. Foreground CLI resolution uses this root to locate the `pi` CLI script, and the detached background runner uses it for jiti host resolution and peer-package aliases, so both child kinds agree on one host. It is consulted when argv-based automatic discovery cannot identify the host, such as a wrapper install or a non-standard layout. The value must be the root of a canonical `@earendil-works/pi-coding-agent` installation (the directory containing its `package.json`, with that package name); both child kinds still validate the package name and its peer packages from that install tree, so a package whose manifest carries a different name is rejected even with the override set. Empty or whitespace-only values are ignored.
422
422
 
423
+ The default in-process child session loader consults the same discovery. Before falling back to a bare `@earendil-works/pi-coding-agent` import, it resolves the host package root (the running pi process's location, then this override, then pi-subagents' own install tree as a last fallback) and imports the host's entry file directly, so children share the host's single SDK instance instead of a second copy. Roots whose `package.json` name is not `@earendil-works/pi-coding-agent` are rejected. When this override is selected, an unimportable root is reported instead of falling back to a bare import from a different tree.
424
+
423
425
  ## `intercomBridge`
424
426
 
425
427
  ```json
@@ -188,6 +188,8 @@ const registration = request.result.registration;
188
188
 
189
189
  If `pi-subagents` is a resolvable dependency of the consumer package, `pi-subagents/agents` exports `RUNTIME_AGENT_REGISTER_EVENT`, the request/result types, and `registerAgentViaEvents()` for the same contract. A separately installed Pi package is not automatically a Node dependency of another package. In that case, use the event contract directly instead of a runtime import. A type-only development dependency is optional.
190
190
 
191
+ A registered agent follows the operator's subagent model settings like any other agent: `subagents.defaultModel`, `defaultProvider`, and `defaultThinking` fill a definition that omits `model` or `thinking`, and the `model`, `defaultProvider`, `fast`, and `thinking` fields of `agentOverrides.<name>` win over the definition. Every other definition field stays extension-owned, and other override fields are ignored for runtime agents. Set `model` in the definition only when the agent must not follow operator model settings; `model: "inherit"` selects the parent session model explicitly.
192
+
191
193
  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.
192
194
 
193
195
  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.
package/docs/models.md CHANGED
@@ -82,7 +82,7 @@ For a persistent role override:
82
82
  }
83
83
  ```
84
84
 
85
- `subagents.defaultModel` and `subagents.defaultProvider` apply to builtin, package, user, and project agents. `defaultModel` fills only agents that do not set `model` in frontmatter. `defaultProvider` is also applied to frontmatter and override models so bare ids resolve against the intended provider. Per-run model overrides and `agentOverrides.<name>.model` win over frontmatter and the global default. The same `agentOverrides` block can change `tools`, `skills`, inherited context, prompt text, or disable an agent (see [agents.md](agents.md)); matching custom-agent frontmatter is replaced for any field set by the override.
85
+ `subagents.defaultModel` and `subagents.defaultProvider` apply to builtin, package, user, project, and runtime-registered agents. `defaultModel` fills only agents that do not set `model` in frontmatter or in their runtime definition. `defaultProvider` is also applied to frontmatter and override models so bare ids resolve against the intended provider. Per-run model overrides and `agentOverrides.<name>.model` win over frontmatter and the global default. The same `agentOverrides` block can change `tools`, `skills`, inherited context, prompt text, or disable an agent (see [agents.md](agents.md)); matching custom-agent frontmatter is replaced for any field set by the override. Runtime-registered agents take only `model`, `defaultProvider`, `fast`, and `thinking` from `agentOverrides.<name>`; their other definition fields stay owned by the registering extension.
86
86
 
87
87
  ## Fast mode
88
88
 
@@ -46,7 +46,7 @@ async subagent worker · background
46
46
 
47
47
  To inspect one background child in text, use `subagent({ action: "status", id: "...", view: "transcript" })`; add `index` for a specific child in a parallel or chain run.
48
48
 
49
- In Pi fullscreen mode with mouse dispatch (verified with Pi TUI 0.85.1), left-click
49
+ In Pi fullscreen mode with mouse dispatch, left-click
50
50
  anywhere on the async widget's header row to fold it into a live one-line status
51
51
  summary. Click again to restore the usual layout. No knowledge of extension commands
52
52
  or keyboard shortcuts is needed. The summary counts the widget's tracked runs,
@@ -1,6 +1,6 @@
1
1
  # Standalone background execution
2
2
 
3
- Supported standalone target: **official Pi 0.85.1, Linux x64**. Keep its adjacent release assets with the executable. Other versions, operating systems, architectures and packagers are outside the fully validated support target; limited experimental Windows coverage is described below.
3
+ Supported standalone target: **official Pi 0.86.1, Linux x64**. Keep its adjacent release assets with the executable. Other versions, operating systems, architectures and packagers are outside the fully validated support target; limited experimental Windows coverage is described below.
4
4
 
5
5
  Pi's extension loader supplies its embedded SDK to `binary-bootstrap.ts`, which awaits the existing configured runner before exiting. Startup authorization, revival leases, controls, disposal and process-close observation remain shared with npm. Each independent run has its own host; native sessions inside that run share it. No per-session CLI protocol, runtime download/install, alternate SDK or foreground fallback is introduced. Npm Pi keeps its Node runner, peer aliases and detected npm `PI_PACKAGE_DIR` override (including refusal when no npm root exists).
6
6
 
@@ -10,7 +10,7 @@ Implementation and lifecycle fixtures derive from [@xz-dev](https://github.com/x
10
10
 
11
11
  The resolver recognizes Bun's Windows virtual entrypoint prefixes, `B:/~BUN/` and `B:\~BUN\`, alongside `/$bunfs/`. It launches the real `process.execPath` (or the existing executable override). The `B:` prefix is virtual, not the installation drive; `pi-native.exe` is not a required executable name.
12
12
 
13
- A local Windows x64 smoke passed with **xz-dev/pi `0.85.1-xz.169.1.gb5f4d0ff`, Bun 1.4.2**: a fresh async worker executed a read-only Git command, returned its result, delivered the native completion notification, and exited with code 0 and no remaining runner process. This is not validation of the official Windows distribution or every Bun-compiled Pi host. Windows remains **experimental**: the full standalone lifecycle matrix has not been validated there.
13
+ Windows remains **experimental**: the full standalone lifecycle matrix has not been validated there or for every Bun-compiled Pi host.
14
14
 
15
15
  Node-hosted npm Pi keeps its existing runner path and is not affected by this virtual-entrypoint detection defect. Installing only the pi-subagents extension through npm does not change a Bun-compiled Pi host into an npm Pi host.
16
16
 
@@ -39,11 +39,11 @@ For a focused diagnostic, use `node test/smoke/standalone-background.mjs "$relea
39
39
 
40
40
  ## Npm regressions and local trial
41
41
 
42
- Existing npm clean-install CI covers real SDK 0.85.1. The standalone CI job also checks the public npm launch path without execution-time network:
42
+ Existing npm clean-install CI covers real SDK 0.86.1. The standalone CI job also checks the public npm launch path without execution-time network:
43
43
 
44
44
  ```bash
45
45
  npm_checks="$(mktemp -d)"
46
- node test/smoke/clean-install.mjs "$npm_checks/sdk" 0.85.1
46
+ node test/smoke/clean-install.mjs "$npm_checks/sdk" 0.86.1
47
47
  node test/smoke/npm-background.mjs "$npm_checks/sdk" "$npm_checks/launch"
48
48
  ```
49
49
 
@@ -242,7 +242,7 @@ Agent definitions are not loaded into context by default. Management actions let
242
242
 
243
243
  { action: "update", agent: "code-analysis.scout", config: { model: "openai/gpt-4o" } }
244
244
  { action: "update", agent: "code-analysis.scout", config: { acceptance: "" } } // clear the frontmatter default
245
- { action: "update", agent: "code-analysis.scout", config: { acceptanceRole: false } } // restore inferred name fallback
245
+ { action: "update", agent: "code-analysis.scout", config: { acceptanceRole: false } } // restore default lightweight attestation
246
246
  { action: "delete", agent: "scout" }
247
247
 
248
248
  { action: "eject", agent: "reviewer" }
@@ -431,13 +431,9 @@ A gate given as `{ command, output: "json" }` runs like a string gate, and then
431
431
 
432
432
  Acceptance evidence levels are `auto`, `none`, `attested`, `checked`, and `verified`. `acceptance: "auto"` is the default.
433
433
 
434
- Review is a separate gate configured with `acceptance.review`:
434
+ Automatic inference uses only the declared structured role: `acceptanceRole: "writer"` infers checked evidence, with `review: { agent: "reviewer", required: true }` for async and dynamic writers; `"read-only"` infers none; and an omitted role infers lightweight attestation. Task wording, risk vocabulary, and agent names do not affect inference. Explicit acceptance can raise or add policy, while `{ level: "none", reason: "..." }` disables inferred gates according to the existing policy rules.
435
435
 
436
- - Async, risky, and dynamic writer contexts infer checked evidence plus `review: { agent: "reviewer", required: true }`.
437
- - Tasks classified as read-only infer no acceptance by default, including reviews of release, migration, or security work; those topics do not turn a read-only task into implementation. With role metadata omitted, unknown risk-topic tasks retain their gate even when the agent name suggests a reviewer. Explicit acceptance requests still apply.
438
- - Normal writer tasks infer checked evidence without review.
439
-
440
- Agent frontmatter or `subagents.agentOverrides` may set `acceptanceRole: "read-only" | "writer"` for ambiguous tasks. Explicit task mutation or no-edit intent wins over that role, while omitted metadata preserves the existing reviewer/scout/worker name heuristics. The role affects acceptance inference only and does not change tool access.
436
+ Agent frontmatter or `subagents.agentOverrides` may set `acceptanceRole`. The role affects acceptance inference only and does not change tool access. Review is a separate gate configured with `acceptance.review`.
441
437
 
442
438
  Edge cases:
443
439
 
@@ -1,7 +1,7 @@
1
1
  import { createJiti } from "jiti";
2
2
 
3
3
  const jiti = createJiti(import.meta.url);
4
- const { runInspector } = await jiti.import("./src/inspectors/inspector-runner.ts");
4
+ const { runInspector } = await jiti.import("./src/inspectors/inspector-runner.js");
5
5
 
6
6
  try {
7
7
  runInspector();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "pi-subagents",
4
- "version": "0.70.0",
4
+ "version": "0.70.1",
5
5
  "description": "Pi extension for single-agent delegation and scripted multi-agent workflows",
6
6
  "author": "Nico Bailon",
7
7
  "license": "MIT",
@@ -101,6 +101,7 @@ For an authorized complex delegated workflow, read `prompting-and-roles.md` and
101
101
  - Keep the parent on the ordinary strong default model. Route workers/scouts to a fast capable tier, serious reviews to a strong tier, and top reasoning to bounded read-only critique.
102
102
  - Exact model names are deployment policy. Put them in user/project settings or profiles, not package guidance.
103
103
  - Give every child a compact meta-prompt checklist: objective; repo/cwd/ref; authority/edit boundary; relevant files/contracts and constraints; success/acceptance criteria; validation; expected output/report; and stop/ask conditions. See `references/prompting-and-roles.md`.
104
+ - Before launching a writer for substantial mutation work, classify it as single-seam or multi-seam and partition multi-seam work across exclusive component owners, gates, and durable handoffs before an integration-only owner. See `references/multi-lane-orchestration.md`.
104
105
  - For mutation work, use an isolated lane/worktree when isolation, overlap, or concurrent juggling matters; keep one writer per cwd/worktree. See `references/multi-lane-orchestration.md` for lane mechanics.
105
106
  - Keep long/high-output validation out of chat: prefer `interactive_shell` dispatch/background monitors, bounded logs, or subagent-owned reports; return a concise summary plus report path unless same-turn output is required. Do not use `interactive_shell` as an implicit fallback for a failed `subagent` lane; see `references/execution-controls.md`.
106
107
  - Treat subagent workflow, child launch, prompt runtime, extension load, and child tooling setup failures as lane infrastructure blockers. Stop, report the exact failure and run/worktree state, verify a clean worktree or capture a partial diff, and use only a clear same-protocol retry or an owner-approved execution-mode fallback.
@@ -131,7 +131,7 @@ That is only a starting point. Omit `package` for the traditional unqualified ru
131
131
 
132
132
  `acceptance` is a single-agent launch default. Use a scalar level such as `checked` or an inline/block YAML map such as `{ level: "none", reason: "lightweight lookup" }`. An explicit tool-call value wins; scripted workflow child acceptance remains configured on the `runs.run` or `runs.all` item. Management create/update accepts the same policy object, and `acceptance: ""` clears the frontmatter default (`false` remains the deprecated disabled-policy shorthand).
133
133
 
134
- `acceptanceRole` is `read-only` or `writer` and controls automatic acceptance inference only. Explicit task mutation or no-edit intent wins; otherwise the role replaces agent-name guessing. Omission preserves the current name heuristics. The field does not grant or revoke tools. Management accepts `false` or an empty string to clear it.
134
+ `acceptanceRole` is `read-only` or `writer` and controls automatic acceptance inference only. The structured role is authoritative; task wording and agent names do not escalate acceptance. Omission uses lightweight attestation. The field does not grant or revoke tools. Management accepts `false` or an empty string to clear it.
135
135
 
136
136
  `tools` is a strict child allowlist, not an extension loader. For a named extension tool, keep its registered name in `tools` and load its provider through normal Pi discovery, `extensions`, a path-like `tools` entry, or `subagentOnlyExtensions`. For example, pair `tools: read, fixture_search` with `subagentOnlyExtensions: ./tools/fixture-search.ts` when the provider should exist only in that agent's child sessions. The child now fails with the unavailable names and provider-loading guidance instead of silently continuing when a requested tool is absent; internal `structured_output` is allowed automatically when an output schema requires it.
137
137
 
@@ -4,6 +4,14 @@ Use this reference when several independent tasks need coordinated workers, work
4
4
 
5
5
  Create lanes only after delegation is operator-authorized and each lane materially improves evidence, independent review, specialization, useful parallelism, or isolated execution. Do not manufacture parallelism: keep dependent work serial, and only split work when each lane has a distinct decision and useful output.
6
6
 
7
+ ## Mandatory implementation-topology preflight
8
+
9
+ Before launching a writer for substantial mutation work, classify the implementation as **single-seam** or **multi-seam**. Two or more independently testable contracts or source boundaries make it multi-seam. One PR does not imply one writer, and the one-writer-per-worktree rule prevents concurrent ownership conflicts; it does not authorize an issue-wide commission.
10
+
11
+ Record the classification and evidence on a lane board before writer launch. For multi-seam work, give each isolated component writer exclusive file or contract ownership and focused validation gates. Require every component to produce a committed or otherwise durable handoff, then start a separate integration-only owner after the component handoffs are ready. Mechanically reject and repartition a writer prompt if it owns all major outcomes across multiple independent boundaries.
12
+
13
+ A single complete writer remains valid only when the board records evidence that the work is genuinely one seam or that splitting it would create overlapping ownership or artificial handoffs. This preflight must not manufacture parallelism: do not split tightly coupled work merely to increase the lane count.
14
+
7
15
  ## Lane board and authority
8
16
 
9
17
  Before multiple mutation-capable lanes start, record this board in the parent context:
@@ -118,7 +118,7 @@ Use this after implementation when the user or applicable instructions request d
118
118
 
119
119
  ### Staged fix orchestration technique
120
120
 
121
- Use this when a broad diff has known reviewer findings across several items and the user wants the parent to “orchestrate subagents like a boss.” Keep the active worktree safe with a three-stage `workflowScript`:
121
+ Use this when a broad diff has known reviewer findings across several items and the user wants the parent to “orchestrate subagents like a boss.” Keep mutation ownership explicit in the `workflowScript`:
122
122
 
123
123
  When staged seams are available, a low-tier writer should not receive the
124
124
  end-to-end issue. Use `runs.lanes` inside `workflowScript` to keep stages narrow:
@@ -126,44 +126,45 @@ a scout/red test, helper-only change, one render seam, validation, minimality
126
126
  challenge, or fresh review. Give the writer only its assigned implementation
127
127
  stage; keep sequencing and synthesis with the parent.
128
128
 
129
- 1. A parallel read-only planning fanout, one reviewer per issue cluster. Each child inspects the real diff and returns exact files, line refs, proposed fixes, and focused validation. They must not edit.
130
- 2. One writer worker. It receives the reviewer summaries as the awaited planning results (or their durable output paths) interpolated into its task, plus the parent’s accepted scope, stop rules, and verification contract. It is the only child allowed to edit the active worktree.
131
- 3. A parallel read-only validation fanout. Validators inspect the worker diff from fresh context with distinct angles, report pass/fail, remaining blockers, and missing verification.
129
+ 1. A parallel read-only planning fanout, one reviewer per issue cluster or review angle. Each child inspects the real diff and returns exact files, line refs, proposed fixes, and focused validation. They must not edit.
130
+ 2. Classify the accepted fixes on the lane board before writer launch. If issue clusters are independently testable source or contract boundaries, use isolated component writers with exclusive file/contract ownership and focused gates. Each component must commit or produce another durable handoff; only after those handoffs are ready, start one integration-only owner.
131
+ 3. Use one writer for the complete fix only when the accepted fixes are one tightly coupled existing diff/seam and the lane board records evidence that splitting would create overlapping ownership or artificial handoffs. Give that writer the planning summaries, accepted scope, stop rules, and verification contract.
132
+ 4. Run fresh-context, read-only validation against the integrated or single-seam result. Validators use distinct angles and report pass/fail, remaining blockers, and missing verification.
132
133
 
133
134
  Prefer `async: true`, `context: "fresh"` for reviewers/validators, `outputMode: "file-only"` for large summaries, and per-stage output names that will not collide. Use stable `runs` keys plus `phase` and `label` on each launch item to make async status readable, and hold each awaited result in an ordinary JavaScript variable when a later step needs that specific result — interpolate it (or the durable output path you declared for that child) into the later task text instead of passing a whole aggregate blob. Use this pattern instead of launching several writer workers into a dirty worktree. Include non-blocking suggestions in the writer prompt only when they are small, safe, and do not expand product scope; otherwise record them as deferred.
134
135
 
135
136
  When one child returns a structured target list, use ordinary JavaScript to validate/filter it and map bounded entries into `runs.all`; do not use the removed chain fanout DSL.
136
137
 
137
- Example shape:
138
+ Single-seam example shape (the lane board records that these are review angles on one tightly coupled deployment-lifecycle diff, not independent implementation contracts):
138
139
 
139
140
  ```typescript
140
141
  subagent({
141
142
  async: true,
142
143
  context: "fresh",
143
144
  workflowScript: `
144
- // Stage 1: parallel read-only planning fanout (stable keys, one per issue cluster)
145
+ // Stage 1: parallel read-only review angles on one recorded single seam
145
146
  const plans = await runs.all([
146
- { key: "deploy-plan", agent: "reviewer", phase: "Planning", label: "Deploy docs", task: "Plan fixes for deploy docs/workflow. Inspect the current diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/deploy.md", outputMode: "file-only" },
147
- { key: "scheduler-plan", agent: "reviewer", phase: "Planning", label: "Scheduler contract", task: "Plan fixes for scheduler contract. Inspect the current diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/scheduler.md", outputMode: "file-only" },
148
- { key: "sandbox-plan", agent: "reviewer", phase: "Planning", label: "Sandbox/security", task: "Plan fixes for sandbox/security. Inspect the current diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/sandbox.md", outputMode: "file-only" }
147
+ { key: "correctness-plan", agent: "reviewer", phase: "Planning", label: "Review lifecycle correctness", task: "Plan correctness fixes for the same deployment-lifecycle diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/correctness.md", outputMode: "file-only" },
148
+ { key: "regression-plan", agent: "reviewer", phase: "Planning", label: "Review lifecycle regressions", task: "Plan regression coverage for the same deployment-lifecycle diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/regressions.md", outputMode: "file-only" },
149
+ { key: "minimality-plan", agent: "reviewer", phase: "Planning", label: "Review lifecycle minimality", task: "Plan minimality fixes for the same deployment-lifecycle diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/minimality.md", outputMode: "file-only" }
149
150
  ]);
150
151
 
151
- // Stage 2: single writer — the only child allowed to edit the active worktree.
152
+ // Stage 2: one writer for this lane-board-recorded single seam.
152
153
  // Under outputMode "file-only" the awaited .output is the saved-output
153
154
  // reference, so pass those managed artifact references to the writer.
154
155
  const worker = await runs.run("apply-fixes", {
155
156
  agent: "worker",
156
157
  phase: "Implementation",
157
158
  label: "Apply accepted fixes",
158
- task: "Apply only the accepted fixes from these planning summaries. You are the sole writer for the active worktree. Run focused validation and report changed files, commands, failures, and remaining issues.\\n\\nDeploy plan: " + plans[0].output + "\\n\\nScheduler plan: " + plans[1].output + "\\n\\nSandbox plan: " + plans[2].output,
159
+ task: "Apply only the accepted fixes to the one deployment-lifecycle seam. The lane board records that splitting this existing diff would create overlapping ownership. You are the sole writer for this seam. Run focused validation and report changed files, commands, failures, and remaining issues.\\n\\nCorrectness plan: " + plans[0].output + "\\n\\nRegression plan: " + plans[1].output + "\\n\\nMinimality plan: " + plans[2].output,
159
160
  output: "worker/fixes.md",
160
161
  outputMode: "file-only"
161
162
  });
162
163
 
163
164
  // Stage 3: parallel read-only validation fanout
164
165
  const validations = await runs.all([
165
- { key: "validate-deploy-scheduler", agent: "reviewer", phase: "Validation", label: "Deploy/scheduler validation", task: "Validate the post-worker diff for deploy and scheduler fixes. Start from the worker result: " + worker.output + ". Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "validation/deploy-scheduler.md", outputMode: "file-only" },
166
- { key: "validate-sandbox", agent: "reviewer", phase: "Validation", label: "Sandbox validation", task: "Validate the post-worker diff for sandbox/security fixes. Start from the worker result: " + worker.output + ". Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "validation/sandbox.md", outputMode: "file-only" }
166
+ { key: "validate-behavior", agent: "reviewer", phase: "Validation", label: "Validate lifecycle behavior", task: "Validate behavior in the post-worker deployment-lifecycle diff. Start from the worker result: " + worker.output + ". Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "validation/behavior.md", outputMode: "file-only" },
167
+ { key: "validate-minimality", agent: "reviewer", phase: "Validation", label: "Validate lifecycle minimality", task: "Validate minimality in the same post-worker deployment-lifecycle diff. Start from the worker result: " + worker.output + ". Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "validation/minimality.md", outputMode: "file-only" }
167
168
  ]);
168
169
 
169
170
  return { worker: worker.output, validations: validations.map(v => v.output) };
@@ -1 +1 @@
1
- {"version":3,"file":"agent-management.d.ts","sourceRoot":"","sources":["../../../src/agents/agent-management.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EACN,KAAK,WAAW,EAgBhB,MAAM,aAAa,CAAC;AAcrB,OAAO,KAAK,EAAkE,OAAO,EAAE,eAAe,EAAoB,MAAM,oBAAoB,CAAC;AAIrJ,OAAO,EAAsB,KAAK,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAKzF,KAAK,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,EAAE,KAAK,GAAG,eAAe,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC;AAE3O,UAAU,gBAAgB;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AA+LD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAgFnE;AAWD,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CA0D7G;AAokBD,wBAAgB,UAAU,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,iBAAiB,GAAG,eAAe,CAAC,OAAO,CAAC,CAuCrG;AAmID,wBAAgB,YAAY,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,iBAAiB,GAAG,eAAe,CAAC,OAAO,CAAC,CAiDvG;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,iBAAiB,GAAG,eAAe,CAAC,OAAO,CAAC,CA+DvG;AAoJD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,iBAAiB,GAAG,eAAe,CAAC,OAAO,CAAC,CAcjI"}
1
+ {"version":3,"file":"agent-management.d.ts","sourceRoot":"","sources":["../../../src/agents/agent-management.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EACN,KAAK,WAAW,EAiBhB,MAAM,aAAa,CAAC;AAcrB,OAAO,KAAK,EAAkE,OAAO,EAAE,eAAe,EAAoB,MAAM,oBAAoB,CAAC;AAIrJ,OAAO,EAAsB,KAAK,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAKzF,KAAK,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,EAAE,KAAK,GAAG,eAAe,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC;AAE3O,UAAU,gBAAgB;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAoMD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CA8EnE;AAWD,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAsD7G;AA8jBD,wBAAgB,UAAU,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,iBAAiB,GAAG,eAAe,CAAC,OAAO,CAAC,CAuCrG;AAmID,wBAAgB,YAAY,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,iBAAiB,GAAG,eAAe,CAAC,OAAO,CAAC,CAiDvG;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,iBAAiB,GAAG,eAAe,CAAC,OAAO,CAAC,CA+DvG;AAoJD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,iBAAiB,GAAG,eAAe,CAAC,OAAO,CAAC,CAcjI"}
@@ -86,24 +86,24 @@ function parsePackageConfig(value) {
86
86
  function allAgents(d) {
87
87
  return [...d.builtin, ...d.package, ...d.user, ...d.project];
88
88
  }
89
- function effectiveAgentsForScope(scope, d, runtimeAgentOwner) {
89
+ function effectiveAgentsForScope(scope, d, runtimeAgentOwner, preferredModelProvider) {
90
90
  let agents = mergeAgentsForScope(scope, d.user, d.project, d.builtin, d.package);
91
91
  if (runtimeAgentOwner) {
92
- agents = mergeRuntimeAgents(runtimeAgentOwner, { agents }, allAgents(d)).agents;
92
+ agents = mergeRuntimeAgents(runtimeAgentOwner, { agents }, allAgents(d), { cwd: d.cwd, scope, preferredModelProvider }).agents;
93
93
  }
94
94
  return agents;
95
95
  }
96
- function availableAgentNamesFromDiscovery(d, runtimeAgentOwner) {
97
- const agents = runtimeAgentOwner ? effectiveAgentsForScope("both", d, runtimeAgentOwner) : allAgents(d);
96
+ function availableAgentNamesFromDiscovery(d, runtimeAgentOwner, preferredModelProvider) {
97
+ const agents = runtimeAgentOwner ? effectiveAgentsForScope("both", d, runtimeAgentOwner, preferredModelProvider) : allAgents(d);
98
98
  return [...new Set(agents.map((agent) => agent.name))].sort((a, b) => a.localeCompare(b));
99
99
  }
100
100
  function availableAgentNames(cwd) {
101
101
  return availableAgentNamesFromDiscovery(discoverAgentsAll(cwd));
102
102
  }
103
- function findAgentsInDiscovery(name, d, scope = "both", runtimeAgentOwner) {
103
+ function findAgentsInDiscovery(name, d, scope = "both", runtimeAgentOwner, preferredModelProvider) {
104
104
  const raw = name.trim();
105
105
  const sanitized = sanitizeName(raw);
106
- const scoped = effectiveAgentsForScope(scope, d, runtimeAgentOwner);
106
+ const scoped = effectiveAgentsForScope(scope, d, runtimeAgentOwner, preferredModelProvider);
107
107
  let resolved = resolveAgentName(raw, scoped);
108
108
  if (!resolved.agent && !resolved.error && sanitized !== raw)
109
109
  resolved = resolveAgentName(sanitized, scoped);
@@ -194,7 +194,7 @@ export function editableAgentConfig(agent) {
194
194
  delete next.thinking;
195
195
  return next;
196
196
  };
197
- const { override: _override, description: _description, output: _output, outputMode: _outputMode, defaultReads: _defaultReads, model: _model, fast: _fast, thinking: _thinking, systemPromptMode: _systemPromptMode, inheritProjectContext: _inheritProjectContext, inheritGlobalContext: _inheritGlobalContext, inheritSkills: _inheritSkills, defaultContext: _defaultContext, acceptanceRole: _acceptanceRole, disabled: _disabled, systemPrompt: _systemPrompt, skills: _skills, skillPath: _skillPath, tools: _tools, excludeTools: _excludeTools, mcpDirectTools: _mcpDirectTools, allowNestedSubagents: _allowNestedSubagents, allowedAgents: _allowedAgents, subagentOnlyExtensions: _subagentOnlyExtensions, mutationTools: _mutationTools, completionGuard: _completionGuard, toolBudget: _toolBudget, ...editable } = withoutExtensions;
197
+ const { override: _override, description: _description, output: _output, outputMode: _outputMode, defaultReads: _defaultReads, model: _model, fast: _fast, thinking: _thinking, systemPromptMode: _systemPromptMode, inheritProjectContext: _inheritProjectContext, inheritGlobalContext: _inheritGlobalContext, inheritSkills: _inheritSkills, defaultContext: _defaultContext, acceptanceRole: _acceptanceRole, disabled: _disabled, systemPrompt: _systemPrompt, skills: _skills, skillPath: _skillPath, tools: _tools, excludeTools: _excludeTools, mcpDirectTools: _mcpDirectTools, allowNestedSubagents: _allowNestedSubagents, allowedAgents: _allowedAgents, subagentOnlyExtensions: _subagentOnlyExtensions, mutationTools: _mutationTools, toolBudget: _toolBudget, ...editable } = withoutExtensions;
198
198
  if (!base) {
199
199
  return withDeclaredExtensionPaths(withoutSettingsDefaults({
200
200
  ...withoutExtensions,
@@ -228,7 +228,6 @@ export function editableAgentConfig(agent) {
228
228
  ...(base.extensions !== undefined ? { extensions: [...base.extensions] } : {}),
229
229
  ...(base.subagentOnlyExtensions !== undefined ? { subagentOnlyExtensions: [...base.subagentOnlyExtensions] } : {}),
230
230
  ...(base.mutationTools !== undefined ? { mutationTools: [...base.mutationTools] } : {}),
231
- ...(base.completionGuard !== undefined ? { completionGuard: base.completionGuard } : {}),
232
231
  ...(base.toolBudget !== undefined ? { toolBudget: base.toolBudget } : {}),
233
232
  }, agent.filePath);
234
233
  }
@@ -318,11 +317,6 @@ export function preservedAgentFrontmatterFields(agent, cfg) {
318
317
  changed("defaultProgress");
319
318
  if (hasKey(cfg, "maxSubagentDepth"))
320
319
  changed("maxSubagentDepth");
321
- if (hasKey(cfg, "completionGuard")) {
322
- changed("completionGuard");
323
- if (cfg.completionGuard === true)
324
- fields.add("completionGuard");
325
- }
326
320
  if (hasKey(cfg, "toolBudget"))
327
321
  changed("toolBudget");
328
322
  return fields;
@@ -642,11 +636,6 @@ function applyAgentConfig(target, cfg) {
642
636
  else
643
637
  return "config.maxSubagentDepth must be an integer >= 0 or false when provided.";
644
638
  }
645
- if (hasKey(cfg, "completionGuard")) {
646
- if (typeof cfg.completionGuard !== "boolean")
647
- return "config.completionGuard must be a boolean when provided.";
648
- target.completionGuard = cfg.completionGuard;
649
- }
650
639
  if (hasKey(cfg, "toolBudget")) {
651
640
  if (cfg.toolBudget === false || cfg.toolBudget === "")
652
641
  delete target.toolBudget;
@@ -668,7 +657,6 @@ function applyAgentConfig(target, cfg) {
668
657
  target.mutationTools?.length ? "mutationTools" : undefined,
669
658
  target.skills?.length || target.skillPath?.length ? "skills" : undefined,
670
659
  target.maxSubagentDepth !== undefined ? "maxSubagentDepth" : undefined,
671
- target.completionGuard !== undefined ? "completionGuard" : undefined,
672
660
  target.toolBudget ? "toolBudget" : undefined,
673
661
  ].filter((field) => Boolean(field));
674
662
  if (unsupported.length > 0)
@@ -1019,8 +1007,6 @@ function formatAgentDetail(agent) {
1019
1007
  lines.push("Progress: true");
1020
1008
  if (agent.maxSubagentDepth !== undefined)
1021
1009
  lines.push(`Max subagent depth: ${agent.maxSubagentDepth}`);
1022
- if (agent.completionGuard === false)
1023
- lines.push("Completion guard: false");
1024
1010
  if (agent.toolBudget)
1025
1011
  lines.push(`Tool budget: ${JSON.stringify(agent.toolBudget)}`);
1026
1012
  if (agent.memory)
@@ -1032,7 +1018,7 @@ function formatAgentDetail(agent) {
1032
1018
  export function handleList(params, ctx) {
1033
1019
  const scope = normalizeListScope(params.agentScope) ?? "both";
1034
1020
  const d = discoverAgentsAll(ctx.cwd, ctx.model?.provider);
1035
- let scopedAgents = effectiveAgentsForScope(scope, d, ctx.runtimeAgentOwner);
1021
+ let scopedAgents = effectiveAgentsForScope(scope, d, ctx.runtimeAgentOwner, ctx.model?.provider);
1036
1022
  scopedAgents = scopedAgents
1037
1023
  .sort((a, b) => a.name.localeCompare(b.name));
1038
1024
  const capabilityCeiling = resolveCurrentSubagentCapabilityCeiling(ctx.currentSessionId);
@@ -1089,7 +1075,7 @@ function handleModels(params, ctx) {
1089
1075
  if (!scope)
1090
1076
  return result("agentScope must be 'user', 'project', or 'both' for models.", true);
1091
1077
  const discovered = discoverAgentsAll(ctx.cwd, ctx.model?.provider);
1092
- const effectiveAgents = effectiveAgentsForScope(scope, discovered, ctx.runtimeAgentOwner)
1078
+ const effectiveAgents = effectiveAgentsForScope(scope, discovered, ctx.runtimeAgentOwner, ctx.model?.provider)
1093
1079
  .sort((a, b) => a.name.localeCompare(b.name));
1094
1080
  const availableModels = ctx.modelRegistry.getAvailable().map(toModelInfo);
1095
1081
  const currentModel = ctx.model ? { provider: ctx.model.provider, id: ctx.model.id } : undefined;
@@ -1097,7 +1083,7 @@ function handleModels(params, ctx) {
1097
1083
  const capabilityCeiling = resolveCurrentSubagentCapabilityCeiling(ctx.currentSessionId);
1098
1084
  let selectedAgents = effectiveAgents;
1099
1085
  if (requestedAgent) {
1100
- const matches = findAgentsInDiscovery(requestedAgent, discovered, scope, ctx.runtimeAgentOwner);
1086
+ const matches = findAgentsInDiscovery(requestedAgent, discovered, scope, ctx.runtimeAgentOwner, ctx.model?.provider);
1101
1087
  const diagnostics = diagnosticsForScope(discovered.agentDiagnostics, scope);
1102
1088
  const normalizedName = sanitizeName(requestedAgent);
1103
1089
  const diagnostic = findBlockingAgentDiagnostic(requestedAgent, matches, diagnostics)
@@ -1108,7 +1094,7 @@ function handleModels(params, ctx) {
1108
1094
  if (distinctNames.length > 1)
1109
1095
  return result(`Ambiguous agent alias or name '${params.agent}': ${distinctNames.sort((a, b) => a.localeCompare(b)).join(", ")}`, true);
1110
1096
  if (!matches.length) {
1111
- return result(`Agent '${params.agent}' not found. Available: ${availableAgentNamesFromDiscovery(discovered, ctx.runtimeAgentOwner).join(", ") || "none"}.`, true);
1097
+ return result(`Agent '${params.agent}' not found. Available: ${availableAgentNamesFromDiscovery(discovered, ctx.runtimeAgentOwner, ctx.model?.provider).join(", ") || "none"}.`, true);
1112
1098
  }
1113
1099
  selectedAgents = [matches[0]];
1114
1100
  }