pi-subagents 0.70.0 → 0.71.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/README.md +4 -2
  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 +3 -2
  7. package/docs/agents.md +7 -8
  8. package/docs/configuration.md +17 -1
  9. package/docs/extension-api.md +5 -1
  10. package/docs/models.md +1 -1
  11. package/docs/observability.md +17 -13
  12. package/docs/standalone-background.md +4 -4
  13. package/docs/tool-reference.md +9 -11
  14. package/docs/workflows.md +1 -1
  15. package/inspector-runner.mjs +1 -1
  16. package/package.json +2 -2
  17. package/skills/pi-subagents/SKILL.md +1 -0
  18. package/skills/pi-subagents/references/constraints-and-recipes.md +5 -2
  19. package/skills/pi-subagents/references/execution-controls.md +2 -2
  20. package/skills/pi-subagents/references/management-authoring-rpc.md +3 -3
  21. package/skills/pi-subagents/references/multi-lane-orchestration.md +8 -0
  22. package/skills/pi-subagents/references/prompting-and-roles.md +14 -13
  23. package/src/agents/agent-management.d.ts.map +1 -1
  24. package/src/agents/agent-management.js +11 -25
  25. package/src/agents/agent-management.js.map +1 -1
  26. package/src/agents/agent-serializer.d.ts.map +1 -1
  27. package/src/agents/agent-serializer.js +0 -4
  28. package/src/agents/agent-serializer.js.map +1 -1
  29. package/src/agents/agents.d.ts +17 -4
  30. package/src/agents/agents.d.ts.map +1 -1
  31. package/src/agents/agents.js +39 -22
  32. package/src/agents/agents.js.map +1 -1
  33. package/src/agents/proactive-skills.d.ts +1 -0
  34. package/src/agents/proactive-skills.d.ts.map +1 -1
  35. package/src/agents/proactive-skills.js +3 -1
  36. package/src/agents/proactive-skills.js.map +1 -1
  37. package/src/agents/runtime-agent-registry.d.ts +8 -3
  38. package/src/agents/runtime-agent-registry.d.ts.map +1 -1
  39. package/src/agents/runtime-agent-registry.js +14 -9
  40. package/src/agents/runtime-agent-registry.js.map +1 -1
  41. package/src/agents/skills.d.ts +2 -0
  42. package/src/agents/skills.d.ts.map +1 -1
  43. package/src/agents/skills.js +41 -8
  44. package/src/agents/skills.js.map +1 -1
  45. package/src/api/delegation.d.ts +14 -0
  46. package/src/api/delegation.d.ts.map +1 -1
  47. package/src/extension/index.d.ts.map +1 -1
  48. package/src/extension/index.js +5 -1
  49. package/src/extension/index.js.map +1 -1
  50. package/src/extension/rpc.d.ts +1 -1
  51. package/src/extension/rpc.d.ts.map +1 -1
  52. package/src/extension/rpc.js +11 -1
  53. package/src/extension/rpc.js.map +1 -1
  54. package/src/extension/tool-activation.d.ts +9 -0
  55. package/src/extension/tool-activation.d.ts.map +1 -0
  56. package/src/extension/tool-activation.js +172 -0
  57. package/src/extension/tool-activation.js.map +1 -0
  58. package/src/extension/tool-description.d.ts +4 -4
  59. package/src/extension/tool-description.d.ts.map +1 -1
  60. package/src/extension/tool-description.js +1 -1
  61. package/src/intercom/intercom-bridge.d.ts.map +1 -1
  62. package/src/intercom/intercom-bridge.js +2 -0
  63. package/src/intercom/intercom-bridge.js.map +1 -1
  64. package/src/runs/background/active-async-capacity.d.ts.map +1 -1
  65. package/src/runs/background/active-async-capacity.js +4 -33
  66. package/src/runs/background/active-async-capacity.js.map +1 -1
  67. package/src/runs/background/async-execution.d.ts.map +1 -1
  68. package/src/runs/background/async-execution.js +5 -67
  69. package/src/runs/background/async-execution.js.map +1 -1
  70. package/src/runs/background/async-job-tracker.d.ts.map +1 -1
  71. package/src/runs/background/async-job-tracker.js +25 -19
  72. package/src/runs/background/async-job-tracker.js.map +1 -1
  73. package/src/runs/background/async-resume.d.ts +1 -1
  74. package/src/runs/background/async-resume.d.ts.map +1 -1
  75. package/src/runs/background/async-resume.js +8 -6
  76. package/src/runs/background/async-resume.js.map +1 -1
  77. package/src/runs/background/async-status.d.ts +1 -0
  78. package/src/runs/background/async-status.d.ts.map +1 -1
  79. package/src/runs/background/async-status.js +1 -0
  80. package/src/runs/background/async-status.js.map +1 -1
  81. package/src/runs/background/binary-bootstrap.d.ts.map +1 -1
  82. package/src/runs/background/binary-bootstrap.js +28 -6
  83. package/src/runs/background/binary-bootstrap.js.map +1 -1
  84. package/src/runs/background/fleet-view.d.ts.map +1 -1
  85. package/src/runs/background/fleet-view.js +26 -7
  86. package/src/runs/background/fleet-view.js.map +1 -1
  87. package/src/runs/background/notify.d.ts +11 -0
  88. package/src/runs/background/notify.d.ts.map +1 -1
  89. package/src/runs/background/notify.js +71 -3
  90. package/src/runs/background/notify.js.map +1 -1
  91. package/src/runs/background/process-terminal-candidate.d.ts +18 -0
  92. package/src/runs/background/process-terminal-candidate.d.ts.map +1 -0
  93. package/src/runs/background/process-terminal-candidate.js +97 -0
  94. package/src/runs/background/process-terminal-candidate.js.map +1 -0
  95. package/src/runs/background/process-terminal.d.ts +3 -15
  96. package/src/runs/background/process-terminal.d.ts.map +1 -1
  97. package/src/runs/background/process-terminal.js +19 -96
  98. package/src/runs/background/process-terminal.js.map +1 -1
  99. package/src/runs/background/retained-children.d.ts.map +1 -1
  100. package/src/runs/background/retained-children.js +3 -2
  101. package/src/runs/background/retained-children.js.map +1 -1
  102. package/src/runs/background/run-child-session.d.ts +1 -0
  103. package/src/runs/background/run-child-session.d.ts.map +1 -1
  104. package/src/runs/background/run-child-session.js.map +1 -1
  105. package/src/runs/background/run-status.d.ts.map +1 -1
  106. package/src/runs/background/run-status.js +11 -5
  107. package/src/runs/background/run-status.js.map +1 -1
  108. package/src/runs/background/runner-aliases.d.ts.map +1 -1
  109. package/src/runs/background/runner-aliases.js +28 -16
  110. package/src/runs/background/runner-aliases.js.map +1 -1
  111. package/src/runs/background/runner-startup-failure.d.ts +14 -0
  112. package/src/runs/background/runner-startup-failure.d.ts.map +1 -0
  113. package/src/runs/background/runner-startup-failure.js +47 -0
  114. package/src/runs/background/runner-startup-failure.js.map +1 -0
  115. package/src/runs/background/stale-run-reconciler.d.ts.map +1 -1
  116. package/src/runs/background/stale-run-reconciler.js +9 -1
  117. package/src/runs/background/stale-run-reconciler.js.map +1 -1
  118. package/src/runs/background/subagent-runner-bootstrap.d.ts +14 -0
  119. package/src/runs/background/subagent-runner-bootstrap.d.ts.map +1 -0
  120. package/src/runs/background/subagent-runner-bootstrap.js +277 -0
  121. package/src/runs/background/subagent-runner-bootstrap.js.map +1 -0
  122. package/src/runs/background/subagent-runner.d.ts +5 -7
  123. package/src/runs/background/subagent-runner.d.ts.map +1 -1
  124. package/src/runs/background/subagent-runner.js +67 -274
  125. package/src/runs/background/subagent-runner.js.map +1 -1
  126. package/src/runs/background/workflow-terminal-proof.d.ts +18 -0
  127. package/src/runs/background/workflow-terminal-proof.d.ts.map +1 -0
  128. package/src/runs/background/workflow-terminal-proof.js +68 -0
  129. package/src/runs/background/workflow-terminal-proof.js.map +1 -0
  130. package/src/runs/foreground/execution.d.ts.map +1 -1
  131. package/src/runs/foreground/execution.js +43 -111
  132. package/src/runs/foreground/execution.js.map +1 -1
  133. package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  134. package/src/runs/foreground/subagent-executor.js +108 -17
  135. package/src/runs/foreground/subagent-executor.js.map +1 -1
  136. package/src/runs/shared/acceptance.d.ts.map +1 -1
  137. package/src/runs/shared/acceptance.js +7 -40
  138. package/src/runs/shared/acceptance.js.map +1 -1
  139. package/src/runs/shared/child-hooks.d.ts +1 -3
  140. package/src/runs/shared/child-hooks.d.ts.map +1 -1
  141. package/src/runs/shared/child-hooks.js +1 -16
  142. package/src/runs/shared/child-hooks.js.map +1 -1
  143. package/src/runs/shared/child-launch.d.ts +0 -2
  144. package/src/runs/shared/child-launch.d.ts.map +1 -1
  145. package/src/runs/shared/child-launch.js +4 -2
  146. package/src/runs/shared/child-launch.js.map +1 -1
  147. package/src/runs/shared/child-runtime-config.d.ts +4 -0
  148. package/src/runs/shared/child-runtime-config.d.ts.map +1 -1
  149. package/src/runs/shared/child-runtime-config.js.map +1 -1
  150. package/src/runs/shared/child-session.d.ts +8 -9
  151. package/src/runs/shared/child-session.d.ts.map +1 -1
  152. package/src/runs/shared/child-session.js +67 -2
  153. package/src/runs/shared/child-session.js.map +1 -1
  154. package/src/runs/shared/dynamic-fanout.js +1 -1
  155. package/src/runs/shared/dynamic-fanout.js.map +1 -1
  156. package/src/runs/shared/external-cli-runner.d.ts.map +1 -1
  157. package/src/runs/shared/external-cli-runner.js +3 -1
  158. package/src/runs/shared/external-cli-runner.js.map +1 -1
  159. package/src/runs/shared/git-environment.d.ts +3 -0
  160. package/src/runs/shared/git-environment.d.ts.map +1 -0
  161. package/src/runs/shared/git-environment.js +28 -0
  162. package/src/runs/shared/git-environment.js.map +1 -0
  163. package/src/runs/shared/mcp-config-sources.d.ts +3 -0
  164. package/src/runs/shared/mcp-config-sources.d.ts.map +1 -1
  165. package/src/runs/shared/mcp-config-sources.js.map +1 -1
  166. package/src/runs/shared/mcp-direct-tool-allowlist.js +1 -1
  167. package/src/runs/shared/mcp-direct-tool-allowlist.js.map +1 -1
  168. package/src/runs/shared/mcp-direct-tool-grant.d.ts +3 -1
  169. package/src/runs/shared/mcp-direct-tool-grant.d.ts.map +1 -1
  170. package/src/runs/shared/mcp-direct-tool-grant.js +19 -5
  171. package/src/runs/shared/mcp-direct-tool-grant.js.map +1 -1
  172. package/src/runs/shared/parallel-utils.d.ts +0 -1
  173. package/src/runs/shared/parallel-utils.d.ts.map +1 -1
  174. package/src/runs/shared/parallel-utils.js.map +1 -1
  175. package/src/runs/shared/pi-spawn.d.ts +10 -1
  176. package/src/runs/shared/pi-spawn.d.ts.map +1 -1
  177. package/src/runs/shared/pi-spawn.js +86 -7
  178. package/src/runs/shared/pi-spawn.js.map +1 -1
  179. package/src/runs/shared/single-output.d.ts.map +1 -1
  180. package/src/runs/shared/single-output.js +10 -2
  181. package/src/runs/shared/single-output.js.map +1 -1
  182. package/src/runs/shared/structured-output.d.ts +7 -0
  183. package/src/runs/shared/structured-output.d.ts.map +1 -1
  184. package/src/runs/shared/structured-output.js +74 -0
  185. package/src/runs/shared/structured-output.js.map +1 -1
  186. package/src/runs/shared/subagent-control.d.ts.map +1 -1
  187. package/src/runs/shared/subagent-control.js +6 -19
  188. package/src/runs/shared/subagent-control.js.map +1 -1
  189. package/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
  190. package/src/runs/shared/subagent-prompt-runtime.js +23 -7
  191. package/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
  192. package/src/runs/shared/tool-availability.js +1 -1
  193. package/src/runs/shared/tool-availability.js.map +1 -1
  194. package/src/shared/child-session-name.d.ts.map +1 -1
  195. package/src/shared/child-session-name.js +4 -2
  196. package/src/shared/child-session-name.js.map +1 -1
  197. package/src/shared/fork-context.d.ts +4 -0
  198. package/src/shared/fork-context.d.ts.map +1 -1
  199. package/src/shared/fork-context.js +9 -4
  200. package/src/shared/fork-context.js.map +1 -1
  201. package/src/shared/launch-contract.d.ts.map +1 -1
  202. package/src/shared/launch-contract.js +0 -1
  203. package/src/shared/launch-contract.js.map +1 -1
  204. package/src/shared/pruned-fork.d.ts +1 -1
  205. package/src/shared/pruned-fork.d.ts.map +1 -1
  206. package/src/shared/pruned-fork.js +70 -65
  207. package/src/shared/pruned-fork.js.map +1 -1
  208. package/src/shared/types.d.ts +32 -13
  209. package/src/shared/types.d.ts.map +1 -1
  210. package/src/shared/types.js +2 -0
  211. package/src/shared/types.js.map +1 -1
  212. package/src/slash/delegation-adapters.d.ts +7 -1
  213. package/src/slash/delegation-adapters.d.ts.map +1 -1
  214. package/src/slash/delegation-adapters.js +17 -0
  215. package/src/slash/delegation-adapters.js.map +1 -1
  216. package/src/slash/prompt-template-bridge.d.ts.map +1 -1
  217. package/src/slash/prompt-template-bridge.js +14 -1
  218. package/src/slash/prompt-template-bridge.js.map +1 -1
  219. package/src/slash/prompt-workflows.d.ts.map +1 -1
  220. package/src/slash/prompt-workflows.js +16 -2
  221. package/src/slash/prompt-workflows.js.map +1 -1
  222. package/src/slash/slash-commands.d.ts.map +1 -1
  223. package/src/slash/slash-commands.js +5 -251
  224. package/src/slash/slash-commands.js.map +1 -1
  225. package/src/slash/subagent-cost.d.ts +29 -0
  226. package/src/slash/subagent-cost.d.ts.map +1 -0
  227. package/src/slash/subagent-cost.js +271 -0
  228. package/src/slash/subagent-cost.js.map +1 -0
  229. package/src/slash/subagents-admin.d.ts.map +1 -1
  230. package/src/slash/subagents-admin.js +4 -5
  231. package/src/slash/subagents-admin.js.map +1 -1
  232. package/src/tui/fleet.d.ts.map +1 -1
  233. package/src/tui/fleet.js +4 -0
  234. package/src/tui/fleet.js.map +1 -1
  235. package/src/tui/render.d.ts.map +1 -1
  236. package/src/tui/render.js +16 -11
  237. package/src/tui/render.js.map +1 -1
  238. package/src/watchdog/diff-tool.d.ts +2 -1
  239. package/src/watchdog/diff-tool.d.ts.map +1 -1
  240. package/src/watchdog/diff-tool.js +9 -3
  241. package/src/watchdog/diff-tool.js.map +1 -1
  242. package/src/watchdog/permission-arbiter.d.ts.map +1 -1
  243. package/src/watchdog/permission-arbiter.js +12 -8
  244. package/src/watchdog/permission-arbiter.js.map +1 -1
  245. package/src/watchdog/register-child.d.ts +3 -1
  246. package/src/watchdog/register-child.d.ts.map +1 -1
  247. package/src/watchdog/register-child.js +12 -3
  248. package/src/watchdog/register-child.js.map +1 -1
  249. package/src/watchdog/review.d.ts +1 -0
  250. package/src/watchdog/review.d.ts.map +1 -1
  251. package/src/watchdog/review.js +12 -6
  252. package/src/watchdog/review.js.map +1 -1
  253. package/src/watchdog/runtime.d.ts +1 -1
  254. package/src/watchdog/runtime.d.ts.map +1 -1
  255. package/src/watchdog/runtime.js +2 -1
  256. package/src/watchdog/runtime.js.map +1 -1
  257. package/src/watchdog/turn-delta.d.ts +5 -1
  258. package/src/watchdog/turn-delta.d.ts.map +1 -1
  259. package/src/watchdog/turn-delta.js +9 -5
  260. package/src/watchdog/turn-delta.js.map +1 -1
  261. package/src/workflows/scripted-workflow.d.ts.map +1 -1
  262. package/src/workflows/scripted-workflow.js +1 -3
  263. package/src/workflows/scripted-workflow.js.map +1 -1
  264. package/src/runs/shared/completion-evidence.d.ts +0 -31
  265. package/src/runs/shared/completion-evidence.d.ts.map +0 -1
  266. package/src/runs/shared/completion-evidence.js +0 -54
  267. package/src/runs/shared/completion-evidence.js.map +0 -1
  268. package/src/runs/shared/completion-guard.d.ts +0 -35
  269. package/src/runs/shared/completion-guard.d.ts.map +0 -1
  270. package/src/runs/shared/completion-guard.js +0 -214
  271. package/src/runs/shared/completion-guard.js.map +0 -1
  272. package/src/runs/shared/llm-intent-arbiter.d.ts +0 -48
  273. package/src/runs/shared/llm-intent-arbiter.d.ts.map +0 -1
  274. package/src/runs/shared/llm-intent-arbiter.js +0 -235
  275. package/src/runs/shared/llm-intent-arbiter.js.map +0 -1
  276. package/src/runs/shared/task-intent.d.ts +0 -38
  277. package/src/runs/shared/task-intent.d.ts.map +0 -1
  278. package/src/runs/shared/task-intent.js +0 -213
  279. package/src/runs/shared/task-intent.js.map +0 -1
@@ -103,7 +103,7 @@ For a typed post-run check, pass the object form `gate: { command, output: "json
103
103
 
104
104
  If omitted, acceptance is inferred from role, mode, and risk. Use `level: "checked"` for ordinary writer evidence and `level: "verified"` when the runtime should run explicit validation commands. Independent review is orthogonal: use `review: { required: true, agent: "reviewer" }`; reviewer/read-only calls omit `acceptance`. `review-required` means evidence passed but review is pending; `reviewed` means an independent review found no blockers. Never request `level: "reviewed"`; it is recognized only so preflight can return an actionable correction. Disable gates with `{ level: "none", reason: "..." }`; bare `"none"` is rejected and `false` is only a deprecated shorthand. Child-reported command success is evidence, not runtime verification.
105
105
 
106
- Completed workflow children from this parent session stay addressable as retained children. `subagent({ action: "children.list" })` lists up to the last 10 with run ids and reports each row as `resumable` or `not resumable` with a reason. Resume only rows reported `resumable`. For a retained-child challenge, use `resume` instead of `steer` when the child is complete. If no retained child is resumable, launch a same-role fallback challenge and label it as fallback. A later workflow continues a resumable child with `runs.run(key, { resume: "<run-id>", task: "follow-up" })`. Inside `workflowScript`, awaiting that call waits for the revived child to finish and returns its completed output and new `runId`; top-level `{ action: "resume" }` remains detached. Pass explicit follow-up task text. Assign each returned child result back to the loop variable because every resume can return a new retained `runId`; always resume the latest returned id. `resume` and `agent` are mutually exclusive, the revived child keeps its stored agent/model/tool contract, and `gate` is rejected on retained resume items.
106
+ Completed workflow children from this parent session stay addressable as retained children. `subagent({ action: "children.list" })` lists up to the last 10 with run ids and reports each row as `resumable` or `not resumable` with a reason. This workflow-only roster is not an exhaustive list of direct native children. Resume only rows reported `resumable`. When the exact run id of an intended direct child is known, inspect it with `subagent({ action: "status", id: "<run-id>" })`; if status identifies the candidate, attempt `subagent({ action: "resume", id: "<run-id>", message: "..." })`. Resume performs the authoritative eligibility check and may reject the attempt. For a retained-child challenge, use `resume` instead of `steer` when the child is complete. Launch a same-role fallback challenge, labeled as fallback, only when no known candidate exists or resume rejects eligibility. A later workflow continues a resumable child with `runs.run(key, { resume: "<run-id>", task: "follow-up" })`. Inside `workflowScript`, awaiting that call waits for the revived child to finish and returns its completed output and new `runId`; top-level `{ action: "resume" }` remains detached. Pass explicit follow-up task text. Assign each returned child result back to the loop variable because every resume can return a new retained `runId`; always resume the latest returned id. `resume` and `agent` are mutually exclusive, the revived child keeps its stored agent/model/tool contract, and `gate` is rejected on retained resume items.
107
107
 
108
108
  Each workflow key identifies one result lane: use a new stable workflow key for every distinct retained resume pass; same-key calls are reused only when launch parameters are identical, and incompatible parameters are rejected.
109
109
 
@@ -493,7 +493,7 @@ subagent({
493
493
  workflowScript: `return runs.run("oracle-check", { agent: "oracle", task: "Review my current direction, challenge assumptions, and propose the best next move." })`
494
494
  })
495
495
 
496
- // Implementation only after explicit approval. Worker defaults to forked context.
496
+ // Implementation only after explicit approval. Worker defaults to fresh context.
497
497
  subagent({
498
498
  workflowScript: `return runs.run("implementation", { agent: "worker", task: "Implement the approved approach: ..." })`
499
499
  })
@@ -18,7 +18,7 @@ subagent({ action: "list" })
18
18
  subagent({ action: "children.list" })
19
19
  ```
20
20
 
21
- Lists up to the last 10 retained workflow children from this parent session with explicit `resumable` or `not resumable` rows. Resume only rows reported `resumable`. Send a simple follow-up or implementation challenge with `subagent({ action: "resume", id: "<run-id>", message: "..." })`. Continue one inside a workflow with `runs.run(key, { resume: "<run-id>", task: "follow-up" })`; each workflow key identifies one result lane, so use a new stable workflow key for every distinct retained resume pass. Same-key calls are reused only when launch parameters are identical, and incompatible parameters are rejected. The revived child keeps its stored agent, model, and tool contract. If no resumable child is listed, start a same-role fallback challenge and label it as fallback. `steer` with `mode: "follow_up"` only queues text for the next `resume` when the child has already completed.
21
+ Lists up to the last 10 retained workflow children from this parent session with explicit `resumable` or `not resumable` rows. This workflow-only roster is not an exhaustive list of direct native children. Resume only rows reported `resumable`. When the exact run id of an intended direct child is known, inspect it with `subagent({ action: "status", id: "<run-id>" })`; if status identifies the candidate, attempt `subagent({ action: "resume", id: "<run-id>", message: "..." })`. Resume performs the authoritative eligibility check and may reject the attempt. Continue one inside a workflow with `runs.run(key, { resume: "<run-id>", task: "follow-up" })`; each workflow key identifies one result lane, so use a new stable workflow key for every distinct retained resume pass. Same-key calls are reused only when launch parameters are identical, and incompatible parameters are rejected. The revived child keeps its stored agent, model, and tool contract. Start a same-role fallback challenge, labeled as fallback, only when no known candidate exists or resume rejects eligibility. `steer` with `mode: "follow_up"` only queues text for the next `resume` when the child has already completed.
22
22
 
23
23
  ### Refinement overlays
24
24
 
@@ -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
 
@@ -158,4 +158,4 @@ Additional user prompt templates can delegate into `pi-subagents` through the na
158
158
 
159
159
  Other Pi extensions can call `pi-subagents` through the in-process event bus. The RPC channels are `subagents:rpc:v1:ready`, `subagents:rpc:v1:request`, and per-request replies at `subagents:rpc:v1:reply:<requestId>`. Envelopes use `{ version: 1, requestId, method, params }`, and replies use `{ version: 1, requestId, success, data | error }`. `ping` advertises the exact process-local async completion event as `events.asyncComplete` for RPC-spawn consumers.
160
160
 
161
- Methods: `ping`, `status`, `spawn`, `steer`, `interrupt`, `resume`, and `stop`. `ping` capability metadata advertises optional projections: `capabilities.fleetStatus: { version: 1 }` adds bounded current-session `data.fleet` records (opaque reconciliation `key`, resolved `agent`, optional `role`, `model`, `effort`, caller-facing `goal`, `startedAt`, split `{ input, output, total }` tokens, plus `totalActive`/`omitted` overflow counts) to successful `status` replies; `capabilities.launchResolvedExtensions` advertises parent-resolved opaque launch-extension identifiers in status details; `capabilities.runtimeAcknowledgedExtensions` advertises the best-effort child-runtime acknowledgement projection fed by cooperating extensions emitting `subagent:acknowledge-extension`. Foreground `details.results[]` rows carry a stable numeric `index`; correlate children by `(runId, index)` rather than row position. Consumers should read status/result artifacts and RPC projections instead of scraping terminal output and must ignore unknown fields. `spawn` requires `workflowScript`, is async-only, and rejects management actions, `async: false`, or `clarify: true`; it reuses the normal executor, so discovery, validation, session attribution, configured spawn caps, child-safety depth, artifacts, and async status are shared with the `subagent` tool. `status`, acknowledged async `steer`, and `interrupt` map to the normal control actions. RPC steer disables pause-and-revive recovery and advertises `capabilities.nonRecoveringSteer`, preserving the caller's authority over the exact spawned child. `resume` requires a target plus non-empty message and delegates to the package-owned revival path; it may set a caller-owned `file-only` output path but cannot override the persisted child model, tools, budgets, session ownership, or exclusive session lease. For retained-child workflows, list children first and resume only rows reported `resumable`; otherwise start a same-role fallback challenge and label it as fallback. `stop` targets running async runs through the existing timeout control channel. `pi.events` is process-local, so separate Pi processes and child subagents need lifecycle artifact files or `pi-intercom` instead.
161
+ Methods: `ping`, `status`, `manage`, `spawn`, `steer`, `interrupt`, `resume`, `stop`, and `cost`. `ping` capability metadata advertises optional projections: `capabilities.fleetStatus: { version: 1 }` adds bounded current-session `data.fleet` records (opaque reconciliation `key`, resolved `agent`, optional `role`, `model`, `effort`, caller-facing `goal`, `startedAt`, split `{ input, output, total }` tokens, plus `totalActive`/`omitted` overflow counts) to successful `status` replies; `capabilities.launchResolvedExtensions` advertises parent-resolved opaque launch-extension identifiers in status details; `capabilities.runtimeAcknowledgedExtensions` advertises the best-effort child-runtime acknowledgement projection fed by cooperating extensions emitting `subagent:acknowledge-extension`; `capabilities.cost: { version: 1 }` advertises parent-plus-child accounting as data. Foreground `details.results[]` rows carry a stable numeric `index`; correlate children by `(runId, index)` rather than row position. Consumers should read status/result artifacts and RPC projections instead of scraping terminal output and must ignore unknown fields. `spawn` accepts either `{ agent, task? }`, an inline `workflowScript`, or `workflowScriptPath`; it is async-only and rejects management actions, `async: false`, or `clarify: true`. It reuses the normal executor, so discovery, validation, session attribution, configured spawn caps, child-safety depth, artifacts, and async status are shared with the `subagent` tool. `manage` accepts only the schedule actions advertised by `ping.capabilities.managementActions`. `status`, acknowledged async `steer`, and `interrupt` map to the normal control actions. RPC steer disables pause-and-revive recovery and advertises `capabilities.nonRecoveringSteer`, preserving the caller's authority over the exact spawned child. `resume` requires a target plus non-empty message and delegates to the package-owned revival path; it may set a caller-owned `file-only` output path but cannot override the persisted child model, tools, budgets, session ownership, or exclusive session lease. For retained-child workflows, resume only roster rows reported `resumable`; because that workflow-only roster is not exhaustive, inspect the exact status of a known direct-run candidate and attempt the authoritative resume when status identifies it. Start a labeled same-role fallback only when there is no known candidate or resume rejects eligibility. `stop` targets running async runs through the existing timeout control channel. `pi.events` is process-local, so separate Pi processes and child subagents need lifecycle artifact files or `pi-intercom` instead.
@@ -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
  }