@selesai/code 0.5.28 → 0.6.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 (341) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +1 -1
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +9 -1
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/config-selector.d.ts.map +1 -1
  7. package/dist/cli/config-selector.js +1 -1
  8. package/dist/cli/config-selector.js.map +1 -1
  9. package/dist/cli/credential-print.d.ts +23 -0
  10. package/dist/cli/credential-print.d.ts.map +1 -0
  11. package/dist/cli/credential-print.js +117 -0
  12. package/dist/cli/credential-print.js.map +1 -0
  13. package/dist/cli/startup-ui.d.ts.map +1 -1
  14. package/dist/cli/startup-ui.js +1 -1
  15. package/dist/cli/startup-ui.js.map +1 -1
  16. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  17. package/dist/core/agent-session-runtime.js +3 -0
  18. package/dist/core/agent-session-runtime.js.map +1 -1
  19. package/dist/core/agent-session.d.ts +12 -1
  20. package/dist/core/agent-session.d.ts.map +1 -1
  21. package/dist/core/agent-session.js +20 -14
  22. package/dist/core/agent-session.js.map +1 -1
  23. package/dist/core/compaction/compaction.d.ts.map +1 -1
  24. package/dist/core/compaction/compaction.js +11 -3
  25. package/dist/core/compaction/compaction.js.map +1 -1
  26. package/dist/core/extensions/runner.d.ts +1 -0
  27. package/dist/core/extensions/runner.d.ts.map +1 -1
  28. package/dist/core/extensions/runner.js +11 -0
  29. package/dist/core/extensions/runner.js.map +1 -1
  30. package/dist/core/extensions/types.d.ts +14 -1
  31. package/dist/core/extensions/types.d.ts.map +1 -1
  32. package/dist/core/extensions/types.js.map +1 -1
  33. package/dist/core/footer-data-provider.d.ts +10 -0
  34. package/dist/core/footer-data-provider.d.ts.map +1 -1
  35. package/dist/core/footer-data-provider.js +1 -1
  36. package/dist/core/footer-data-provider.js.map +1 -1
  37. package/dist/core/llama/provider.d.ts.map +1 -1
  38. package/dist/core/llama/provider.js +8 -3
  39. package/dist/core/llama/provider.js.map +1 -1
  40. package/dist/core/model-config.d.ts +30 -0
  41. package/dist/core/model-config.d.ts.map +1 -1
  42. package/dist/core/model-config.js +6 -0
  43. package/dist/core/model-config.js.map +1 -1
  44. package/dist/core/model-registry.d.ts.map +1 -1
  45. package/dist/core/model-registry.js +2 -2
  46. package/dist/core/model-registry.js.map +1 -1
  47. package/dist/core/model-resolver.d.ts +1 -0
  48. package/dist/core/model-resolver.d.ts.map +1 -1
  49. package/dist/core/model-resolver.js +20 -3
  50. package/dist/core/model-resolver.js.map +1 -1
  51. package/dist/core/model-runtime.d.ts +2 -0
  52. package/dist/core/model-runtime.d.ts.map +1 -1
  53. package/dist/core/model-runtime.js +5 -4
  54. package/dist/core/model-runtime.js.map +1 -1
  55. package/dist/core/package-manager.d.ts.map +1 -1
  56. package/dist/core/package-manager.js +13 -6
  57. package/dist/core/package-manager.js.map +1 -1
  58. package/dist/core/remote-catalog-provider.d.ts +1 -1
  59. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  60. package/dist/core/remote-catalog-provider.js +24 -11
  61. package/dist/core/remote-catalog-provider.js.map +1 -1
  62. package/dist/core/resource-loader.d.ts +15 -0
  63. package/dist/core/resource-loader.d.ts.map +1 -1
  64. package/dist/core/resource-loader.js +66 -9
  65. package/dist/core/resource-loader.js.map +1 -1
  66. package/dist/core/settings-manager.d.ts +1 -1
  67. package/dist/core/settings-manager.d.ts.map +1 -1
  68. package/dist/core/settings-manager.js.map +1 -1
  69. package/dist/core/system-prompt.d.ts.map +1 -1
  70. package/dist/core/system-prompt.js +19 -1
  71. package/dist/core/system-prompt.js.map +1 -1
  72. package/dist/core/system-prompt.test.d.ts +2 -0
  73. package/dist/core/system-prompt.test.d.ts.map +1 -0
  74. package/dist/core/system-prompt.test.js +89 -0
  75. package/dist/core/system-prompt.test.js.map +1 -0
  76. package/dist/core/tools/bash.d.ts +2 -0
  77. package/dist/core/tools/bash.d.ts.map +1 -1
  78. package/dist/core/tools/bash.js +34 -5
  79. package/dist/core/tools/bash.js.map +1 -1
  80. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  81. package/dist/core/tools/tool-definition-wrapper.js +3 -1
  82. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  83. package/dist/defaults/models.json +13 -45
  84. package/dist/defaults/settings.json +1 -2
  85. package/dist/extensions/copy-turn.test.ts +131 -0
  86. package/dist/extensions/copy-turn.ts +6 -1
  87. package/dist/extensions/package.json +0 -1
  88. package/dist/extensions/pi-intercom/CHANGELOG.md +249 -0
  89. package/dist/extensions/pi-intercom/README.md +102 -39
  90. package/dist/extensions/pi-intercom/broker/broker.ts +1233 -36
  91. package/dist/extensions/pi-intercom/broker/client.test.ts +83 -0
  92. package/dist/extensions/pi-intercom/broker/client.ts +315 -12
  93. package/dist/extensions/pi-intercom/broker/extension-state.ts +186 -0
  94. package/dist/extensions/pi-intercom/broker/extension.test.ts +387 -0
  95. package/dist/extensions/pi-intercom/broker/framing.test.ts +114 -0
  96. package/dist/extensions/pi-intercom/broker/framing.ts +82 -24
  97. package/dist/extensions/pi-intercom/broker/paths.test.ts +153 -0
  98. package/dist/extensions/pi-intercom/broker/paths.ts +117 -8
  99. package/dist/extensions/pi-intercom/broker/runtime-claim.test.ts +34 -0
  100. package/dist/extensions/pi-intercom/broker/runtime-claim.ts +21 -0
  101. package/dist/extensions/pi-intercom/broker/spawn.test.ts +160 -23
  102. package/dist/extensions/pi-intercom/broker/spawn.ts +113 -27
  103. package/dist/extensions/pi-intercom/config.test.ts +93 -0
  104. package/dist/extensions/pi-intercom/config.ts +55 -6
  105. package/dist/extensions/pi-intercom/cwd.test.ts +40 -0
  106. package/dist/extensions/pi-intercom/cwd.ts +31 -0
  107. package/dist/extensions/pi-intercom/extension-api.ts +44 -0
  108. package/dist/extensions/pi-intercom/format-context.test.ts +31 -0
  109. package/dist/extensions/pi-intercom/format-context.ts +32 -0
  110. package/dist/extensions/pi-intercom/index.ts +742 -145
  111. package/dist/extensions/pi-intercom/intercom.integration.test.ts +2646 -0
  112. package/dist/extensions/pi-intercom/package.json +15 -5
  113. package/dist/extensions/pi-intercom/reply-tracker.test.ts +134 -0
  114. package/dist/extensions/pi-intercom/reply-tracker.ts +31 -13
  115. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +13 -11
  116. package/dist/extensions/pi-intercom/test/inline-message.test.ts +184 -0
  117. package/dist/extensions/pi-intercom/test/overlay-width.test.ts +66 -0
  118. package/dist/extensions/pi-intercom/types.ts +94 -4
  119. package/dist/extensions/pi-intercom/ui/compose.ts +8 -4
  120. package/dist/extensions/pi-intercom/ui/inline-message.ts +61 -25
  121. package/dist/extensions/pi-intercom/ui/session-list.ts +7 -3
  122. package/dist/extensions/pi-subagents/CHANGELOG.md +88 -0
  123. package/dist/extensions/pi-subagents/LICENSE +21 -0
  124. package/dist/extensions/pi-subagents/README.md +158 -69
  125. package/dist/extensions/pi-subagents/agents/architect.md +5 -4
  126. package/dist/extensions/pi-subagents/agents/builder.md +6 -4
  127. package/dist/extensions/pi-subagents/agents/commentator.md +3 -2
  128. package/dist/extensions/pi-subagents/agents/explorer.md +3 -2
  129. package/dist/extensions/pi-subagents/agents/recapper.md +3 -2
  130. package/dist/extensions/pi-subagents/agents/researcher.md +4 -3
  131. package/dist/extensions/pi-subagents/package-lock.json +2 -2
  132. package/dist/extensions/pi-subagents/package.json +3 -3
  133. package/dist/extensions/pi-subagents/prompts/review-loop.md +1 -1
  134. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +22 -988
  135. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +257 -0
  136. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +431 -0
  137. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +144 -0
  138. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +281 -0
  139. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +125 -37
  140. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +4 -0
  141. package/dist/extensions/pi-subagents/src/agents/agents.ts +118 -9
  142. package/dist/extensions/pi-subagents/src/agents/skills.ts +14 -12
  143. package/dist/extensions/pi-subagents/src/agents/task-aware-routing.ts +125 -0
  144. package/dist/extensions/pi-subagents/src/api/delegation.ts +3 -0
  145. package/dist/extensions/pi-subagents/src/api/preflight.ts +17 -13
  146. package/dist/extensions/pi-subagents/src/extension/chain-validation.ts +17 -1
  147. package/dist/extensions/pi-subagents/src/extension/index.ts +22 -8
  148. package/dist/extensions/pi-subagents/src/extension/rpc.ts +248 -6
  149. package/dist/extensions/pi-subagents/src/extension/schemas.ts +33 -8
  150. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +32 -14
  151. package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +9 -4
  152. package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +33 -4
  153. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +86 -21
  154. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +24 -13
  155. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +7 -5
  156. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -2
  157. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +48 -5
  158. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +68 -1
  159. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +56 -5
  160. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +92 -11
  161. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +29 -3
  162. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +388 -29
  163. package/dist/extensions/pi-subagents/src/runs/foreground/async-stop-action.ts +65 -0
  164. package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +3 -3
  165. package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +214 -60
  166. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +546 -252
  167. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +42 -0
  168. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +553 -154
  169. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +19 -13
  170. package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +51 -19
  171. package/dist/extensions/pi-subagents/src/runs/shared/chain-outputs.ts +3 -1
  172. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +1 -1
  173. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +44 -11
  174. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +8 -0
  175. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +97 -20
  176. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +43 -12
  177. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +52 -4
  178. package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +19 -0
  179. package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +45 -9
  180. package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +71 -0
  181. package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +63 -9
  182. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +31 -1
  183. package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +101 -0
  184. package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +22 -1
  185. package/dist/extensions/pi-subagents/src/runs/shared/usage-budget.ts +65 -0
  186. package/dist/extensions/pi-subagents/src/runs/shared/workflow-graph.ts +26 -1
  187. package/dist/extensions/pi-subagents/src/shared/settings.ts +17 -1
  188. package/dist/extensions/pi-subagents/src/shared/types.ts +196 -12
  189. package/dist/extensions/pi-subagents/src/shared/utils.ts +102 -5
  190. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +10 -1
  191. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +46 -4
  192. package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +5 -3
  193. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +87 -24
  194. package/dist/extensions/pi-subagents/src/tui/fleet.ts +182 -9
  195. package/dist/extensions/pi-subagents/src/tui/render.ts +55 -34
  196. package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +14 -7
  197. package/dist/extensions/pi-subagents/src/watchdog/review.ts +5 -4
  198. package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +170 -17
  199. package/dist/extensions/pi-subagents/src/watchdog/scope.ts +62 -0
  200. package/dist/extensions/pi-subagents/src/watchdog/settings.ts +41 -1
  201. package/dist/extensions/pi-subagents/src/watchdog/types.ts +10 -0
  202. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +113 -8
  203. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +419 -47
  204. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +84 -0
  205. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +4 -2
  206. package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +51 -2
  207. package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +62 -22
  208. package/dist/extensions/pi-subagents/test/integration/detect-error.test.ts +48 -0
  209. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +8 -6
  210. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +231 -19
  211. package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +48 -7
  212. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +44 -0
  213. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +199 -17
  214. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +898 -16
  215. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +112 -23
  216. package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +17 -5
  217. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +2 -0
  218. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +18 -2
  219. package/dist/extensions/pi-subagents/test/support/register-loader.mjs +3 -3
  220. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +3 -1
  221. package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +1 -1
  222. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +198 -6
  223. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +161 -1
  224. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +47 -2
  225. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +60 -0
  226. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +8 -0
  227. package/dist/extensions/pi-subagents/test/unit/builtin-agent-documentation.test.ts +63 -0
  228. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +136 -0
  229. package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +1 -1
  230. package/dist/extensions/pi-subagents/test/unit/chain-append.test.ts +6 -0
  231. package/dist/extensions/pi-subagents/test/unit/chain-validation.test.ts +1 -1
  232. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +48 -48
  233. package/dist/extensions/pi-subagents/test/unit/config-dir-runtime.test.ts +23 -0
  234. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +27 -0
  235. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +28 -2
  236. package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +1 -0
  237. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +176 -8
  238. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +164 -5
  239. package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +41 -1
  240. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +17 -12
  241. package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +18 -2
  242. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +20 -1
  243. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +30 -2
  244. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +39 -2
  245. package/dist/extensions/pi-subagents/test/unit/parallel-utils.test.ts +22 -0
  246. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +103 -0
  247. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +18 -0
  248. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +48 -0
  249. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +13 -1
  250. package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +29 -4
  251. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +223 -4
  252. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +30 -0
  253. package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +52 -0
  254. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +46 -2
  255. package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +91 -1
  256. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
  257. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +1 -1
  258. package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +78 -0
  259. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +41 -0
  260. package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +77 -0
  261. package/dist/extensions/pi-subagents/test/unit/task-aware-routing.test.ts +213 -0
  262. package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +26 -1
  263. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +61 -10
  264. package/dist/extensions/pi-subagents/test/unit/total-cost.test.ts +1 -0
  265. package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +210 -1
  266. package/dist/extensions/pi-subagents/test/unit/watchdog-scope.test.ts +33 -0
  267. package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +32 -0
  268. package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +1 -1
  269. package/dist/main.d.ts.map +1 -1
  270. package/dist/main.js +43 -0
  271. package/dist/main.js.map +1 -1
  272. package/dist/modes/interactive/components/custom-message.d.ts +3 -1
  273. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  274. package/dist/modes/interactive/components/custom-message.js +10 -2
  275. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  276. package/dist/modes/interactive/components/extension-editor.d.ts +1 -2
  277. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  278. package/dist/modes/interactive/components/extension-editor.js +16 -46
  279. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  280. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  281. package/dist/modes/interactive/components/model-selector.js +4 -1
  282. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  283. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  284. package/dist/modes/interactive/components/scoped-models-selector.js +22 -13
  285. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  286. package/dist/modes/interactive/external-editor.d.ts +12 -0
  287. package/dist/modes/interactive/external-editor.d.ts.map +1 -0
  288. package/dist/modes/interactive/external-editor.js +37 -0
  289. package/dist/modes/interactive/external-editor.js.map +1 -0
  290. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  291. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  292. package/dist/modes/interactive/interactive-mode.js +72 -64
  293. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  294. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  295. package/dist/modes/rpc/rpc-mode.js +14 -0
  296. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  297. package/dist/skills/ponytail/SKILL.md +1 -3
  298. package/dist/utils/clipboard.d.ts.map +1 -1
  299. package/dist/utils/clipboard.js +19 -8
  300. package/dist/utils/clipboard.js.map +1 -1
  301. package/dist/utils/version-check.d.ts.map +1 -1
  302. package/dist/utils/version-check.js +1 -1
  303. package/dist/utils/version-check.js.map +1 -1
  304. package/docs/compaction.md +1 -1
  305. package/docs/custom-provider.md +14 -5
  306. package/docs/environment-variables.md +86 -0
  307. package/docs/extensions.md +15 -5
  308. package/docs/index.md +1 -0
  309. package/docs/models.md +9 -2
  310. package/docs/plans/subagent-delegation/phase-0-correctness.md +265 -0
  311. package/docs/plans/subagent-delegation/phase-1-behavioral-contract.md +486 -0
  312. package/docs/plans/subagent-delegation/phase-2-context-controls.md +282 -0
  313. package/docs/plans/subagent-delegation/phase-3-advisory-routing.md +362 -0
  314. package/docs/plans/subagent-delegation/phase-4-optional-enforcement.md +381 -0
  315. package/docs/providers.md +21 -2
  316. package/docs/rpc.md +23 -6
  317. package/docs/session-format.md +2 -0
  318. package/docs/settings.md +1 -1
  319. package/docs/usage.md +0 -13
  320. package/examples/extensions/custom-compaction.ts +5 -2
  321. package/examples/extensions/custom-provider-anthropic/index.ts +9 -3
  322. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  323. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  324. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  325. package/examples/extensions/gondolin/package-lock.json +2 -2
  326. package/examples/extensions/gondolin/package.json +1 -1
  327. package/examples/extensions/handoff.ts +11 -3
  328. package/examples/extensions/message-renderer.ts +3 -3
  329. package/examples/extensions/sandbox/package-lock.json +2 -2
  330. package/examples/extensions/sandbox/package.json +1 -1
  331. package/examples/extensions/summarize.ts +5 -2
  332. package/examples/extensions/with-deps/package-lock.json +2 -2
  333. package/examples/extensions/with-deps/package.json +1 -1
  334. package/examples/sdk/12-full-control.ts +3 -1
  335. package/package.json +16 -7
  336. package/dist/extensions/caveman/caveman-instructions.cjs +0 -11
  337. package/dist/extensions/caveman/index.js +0 -118
  338. package/dist/extensions/caveman/package.json +0 -8
  339. package/dist/extensions/caveman/test/extension.test.js +0 -203
  340. package/dist/extensions/caveman/test/helpers.test.js +0 -58
  341. package/dist/skills/caveman/SKILL.md +0 -50
@@ -0,0 +1,213 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import {
4
+ formatTaskAwareAgentRecommendation,
5
+ recommendTaskAwareAgent,
6
+ } from "../../src/agents/task-aware-routing.ts";
7
+ import type { AgentConfig } from "../../src/agents/agents.ts";
8
+
9
+ function agent(name: string, overrides: Partial<AgentConfig> = {}): AgentConfig {
10
+ return {
11
+ name,
12
+ description: `${name} agent`,
13
+ systemPrompt: `${name} prompt`,
14
+ systemPromptMode: "append",
15
+ inheritProjectContext: false,
16
+ inheritSkills: false,
17
+ source: "builtin",
18
+ filePath: `/tmp/${name}.md`,
19
+ ...overrides,
20
+ };
21
+ }
22
+
23
+ describe("recommendTaskAwareAgent", () => {
24
+ it("no-ops for empty or whitespace-only tasks", () => {
25
+ assert.equal(recommendTaskAwareAgent({ task: "", agents: [] }), undefined);
26
+ assert.equal(recommendTaskAwareAgent({ task: " \n\t ", agents: [] }), undefined);
27
+ });
28
+
29
+ it("recommends a canonical writer for an implementation task, never a read-only agent", () => {
30
+ const recommendation = recommendTaskAwareAgent({
31
+ task: "Implement the fix",
32
+ agents: [
33
+ agent("commentator", { tools: ["read", "grep"] }),
34
+ agent("builder"),
35
+ ],
36
+ });
37
+ assert.ok(recommendation);
38
+ assert.equal(recommendation.intent, "implementation");
39
+ assert.equal(recommendation.agent?.name, "builder");
40
+ assert.equal(recommendation.agent?.role, "writer");
41
+ assert.equal(recommendation.agent?.roleBasis, "inferred");
42
+ });
43
+
44
+ it("recommends a read-only agent without known write tools, never a writer", () => {
45
+ const recommendation = recommendTaskAwareAgent({
46
+ task: "Review only; do not edit files",
47
+ agents: [
48
+ agent("builder"),
49
+ agent("commentator", { tools: ["read", "grep", "find", "ls"] }),
50
+ ],
51
+ });
52
+ assert.ok(recommendation);
53
+ assert.equal(recommendation.intent, "read-only");
54
+ assert.equal(recommendation.agent?.name, "commentator");
55
+ assert.equal(recommendation.agent?.role, "read-only");
56
+ assert.equal(recommendation.agent?.roleBasis, "inferred");
57
+ });
58
+
59
+ it("never recommends a read-only agent whose tools are unset or include bash", () => {
60
+ for (const candidate of [
61
+ agent("commentator"),
62
+ agent("commentator", { tools: ["read", "bash"] }),
63
+ ]) {
64
+ const recommendation = recommendTaskAwareAgent({
65
+ task: "Review only; do not edit files",
66
+ agents: [candidate],
67
+ });
68
+ assert.ok(recommendation);
69
+ assert.equal(recommendation.agent, undefined);
70
+ assert.match(recommendation.next ?? "", /read-only role without known write tools/);
71
+ }
72
+ });
73
+
74
+ it("gives recovery guidance, not a guess, for unknown intent", () => {
75
+ const recommendation = recommendTaskAwareAgent({
76
+ task: "Look into this",
77
+ agents: [agent("builder"), agent("commentator", { tools: ["read", "grep"] })],
78
+ });
79
+ assert.ok(recommendation);
80
+ assert.equal(recommendation.intent, "unknown");
81
+ assert.equal(recommendation.agent, undefined);
82
+ assert.match(recommendation.next ?? "", /Clarify whether the task is read-only analysis\/review or implementation allowed to edit files/);
83
+ });
84
+
85
+ it("excludes disabled agents even when they match the task role", () => {
86
+ const recommendation = recommendTaskAwareAgent({
87
+ task: "Implement the fix",
88
+ agents: [
89
+ agent("builder", { disabled: true }),
90
+ agent("fixer", { source: "project", acceptanceRole: "writer", tools: ["edit"] }),
91
+ ],
92
+ });
93
+ assert.ok(recommendation);
94
+ assert.equal(recommendation.agent?.name, "fixer");
95
+ });
96
+
97
+ it("excludes agents denied by the capability ceiling allowedAgents", () => {
98
+ const recommendation = recommendTaskAwareAgent({
99
+ task: "Implement the fix",
100
+ agents: [agent("builder"), agent("fixer", { source: "project", acceptanceRole: "writer", tools: ["edit"] })],
101
+ capabilityCeiling: { version: 1, allowedAgents: ["builder"], denyExtensions: false, sources: ["plan"] },
102
+ });
103
+ assert.ok(recommendation);
104
+ assert.equal(recommendation.agent?.name, "builder");
105
+ });
106
+
107
+ it("refuses a writer recommendation when allowedTools has no writer tool", () => {
108
+ const recommendation = recommendTaskAwareAgent({
109
+ task: "Implement the fix",
110
+ agents: [agent("builder")],
111
+ capabilityCeiling: { version: 1, allowedTools: ["read", "grep"], denyExtensions: false, sources: ["plan"] },
112
+ });
113
+ assert.ok(recommendation);
114
+ assert.equal(recommendation.intent, "implementation");
115
+ assert.equal(recommendation.agent, undefined);
116
+ assert.match(recommendation.next ?? "", /capability ceiling/);
117
+ });
118
+
119
+ it("recommends a writer when allowedTools includes a writer tool", () => {
120
+ const recommendation = recommendTaskAwareAgent({
121
+ task: "Implement the fix",
122
+ agents: [agent("builder")],
123
+ capabilityCeiling: { version: 1, allowedTools: ["read", "edit"], denyExtensions: false, sources: ["plan"] },
124
+ });
125
+ assert.ok(recommendation);
126
+ assert.equal(recommendation.agent?.name, "builder");
127
+ });
128
+
129
+ it("prefers project over user, package, and builtin candidates", () => {
130
+ const recommendation = recommendTaskAwareAgent({
131
+ task: "Implement the fix",
132
+ agents: [
133
+ agent("builder", { source: "builtin" }),
134
+ agent("builder", { source: "package" }),
135
+ agent("builder", { source: "user" }),
136
+ agent("builder", { source: "project" }),
137
+ ],
138
+ });
139
+ assert.ok(recommendation);
140
+ assert.equal(recommendation.agent?.name, "builder");
141
+ assert.equal(recommendation.agent?.source, "project");
142
+ });
143
+
144
+ it("sorts equal candidates by canonical name", () => {
145
+ const recommendation = recommendTaskAwareAgent({
146
+ task: "Implement the fix",
147
+ agents: [
148
+ agent("zeta-builder", { source: "user", acceptanceRole: "writer", tools: ["edit"] }),
149
+ agent("alpha-builder", { source: "user", acceptanceRole: "writer", tools: ["edit"] }),
150
+ ],
151
+ });
152
+ assert.ok(recommendation);
153
+ assert.equal(recommendation.agent?.name, "alpha-builder");
154
+ });
155
+
156
+ it("prefers a declared role over an inferred role at the same source", () => {
157
+ const recommendation = recommendTaskAwareAgent({
158
+ task: "Implement the fix",
159
+ agents: [
160
+ agent("builder", { source: "user" }),
161
+ agent("fixer", { source: "user", acceptanceRole: "writer", tools: ["edit"] }),
162
+ ],
163
+ });
164
+ assert.ok(recommendation);
165
+ assert.equal(recommendation.agent?.name, "fixer");
166
+ assert.equal(recommendation.agent?.roleBasis, "declared");
167
+ });
168
+
169
+ it("never emits an alias as the recommended launch name", () => {
170
+ const recommendation = recommendTaskAwareAgent({
171
+ task: "Implement the fix",
172
+ agents: [
173
+ agent("canonical-builder", { aliases: ["developer"], source: "user", acceptanceRole: "writer", tools: ["edit"] }),
174
+ ],
175
+ });
176
+ assert.ok(recommendation);
177
+ assert.equal(recommendation.agent?.name, "canonical-builder");
178
+ });
179
+ });
180
+
181
+ describe("formatTaskAwareAgentRecommendation", () => {
182
+ it("renders nothing for an empty-task no-op", () => {
183
+ assert.deepEqual(formatTaskAwareAgentRecommendation(undefined), []);
184
+ });
185
+
186
+ it("renders a safe recommendation with the canonical agent and explicit-launch note", () => {
187
+ const lines = formatTaskAwareAgentRecommendation({
188
+ intent: "implementation",
189
+ agent: { name: "builder", source: "project", role: "writer", roleBasis: "declared", reason: "declared writer role with write tools" },
190
+ });
191
+ assert.deepEqual(lines, [
192
+ "Task-aware advisory routing:",
193
+ "- Intent: implementation",
194
+ "- Recommended: builder (project)",
195
+ "- Reason: declared writer role with write tools",
196
+ "- Advisory only: no subagent was launched. To proceed, explicitly call subagent with this canonical agent name and the task.",
197
+ ]);
198
+ });
199
+
200
+ it("renders recovery guidance without an agent name", () => {
201
+ const lines = formatTaskAwareAgentRecommendation({
202
+ intent: "unknown",
203
+ next: "Clarify whether the task is read-only analysis/review or implementation allowed to edit files.",
204
+ });
205
+ assert.deepEqual(lines, [
206
+ "Task-aware advisory routing:",
207
+ "- Intent: unknown",
208
+ "- Recommendation: none",
209
+ "- Next: Clarify whether the task is read-only analysis/review or implementation allowed to edit files.",
210
+ "- Advisory only: no subagent was launched.",
211
+ ]);
212
+ });
213
+ });
@@ -1,6 +1,6 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { describe, it } from "node:test";
3
- import { classifyTaskMutationIntent, expectsImplementationMutation, taskMayMutate } from "../../src/runs/shared/task-intent.ts";
3
+ import { classifyTaskMutationIntent, expectsImplementationMutation, resolveAgentRoutingRole, taskMayMutate } from "../../src/runs/shared/task-intent.ts";
4
4
 
5
5
  describe("classifyTaskMutationIntent", () => {
6
6
  it("keeps write imperatives despite investigative wording", () => {
@@ -38,6 +38,9 @@ describe("classifyTaskMutationIntent", () => {
38
38
  assert.equal(classifyTaskMutationIntent("builder", "Do not edit files. Tell me how to fix the bug.").kind, "read-only");
39
39
  assert.equal(classifyTaskMutationIntent("builder", "Report on the extraction pipeline. Do not modify project/source files.").kind, "read-only");
40
40
  assert.equal(classifyTaskMutationIntent("commentator", "Final correctness review after prior fixes. Inspect all changed files and tests. Do not modify project/source files. Report findings.").kind, "read-only");
41
+ assert.equal(classifyTaskMutationIntent("builder", `Verification-only task. Do not edit product/source/config files.
42
+ Run a disposable check, delete its temporary harness, and retain only
43
+ a sanitized report at an explicitly named artifact path.`).kind, "read-only");
41
44
  });
42
45
 
43
46
  it("strips repeated prohibition phrases before testing write intent", () => {
@@ -66,6 +69,28 @@ describe("classifyTaskMutationIntent", () => {
66
69
  });
67
70
  });
68
71
 
72
+ describe("resolveAgentRoutingRole", () => {
73
+ it("lets a declared acceptanceRole override name heuristics", () => {
74
+ assert.equal(resolveAgentRoutingRole("commentator", "writer"), "writer");
75
+ assert.equal(resolveAgentRoutingRole("builder", "read-only"), "read-only");
76
+ assert.equal(resolveAgentRoutingRole("custom-agent", "writer"), "writer");
77
+ assert.equal(resolveAgentRoutingRole("custom-agent", "read-only"), "read-only");
78
+ });
79
+
80
+ it("infers writer for builder-named agents and read-only for reviewer-style names", () => {
81
+ assert.equal(resolveAgentRoutingRole("builder"), "writer");
82
+ assert.equal(resolveAgentRoutingRole("package.builder"), "writer");
83
+ for (const name of ["architect", "commentator", "explorer", "recapper", "researcher", "analyst"]) {
84
+ assert.equal(resolveAgentRoutingRole(name), "read-only", name);
85
+ }
86
+ });
87
+
88
+ it("returns undefined for names without an established role", () => {
89
+ assert.equal(resolveAgentRoutingRole("custom-agent"), undefined);
90
+ assert.equal(resolveAgentRoutingRole("reviewer"), undefined);
91
+ });
92
+ });
93
+
69
94
  describe("taskMayMutate", () => {
70
95
  it("treats any bare write verb as write-capable", () => {
71
96
  for (const task of ["Write the code", "Commit the changes", "Delete temporary data", "Remove obsolete assets", "Update dependencies"]) {
@@ -9,8 +9,10 @@ import {
9
9
  buildSubagentToolDescription,
10
10
  COMPACT_SUBAGENT_TOOL_DESCRIPTION,
11
11
  FULL_SUBAGENT_TOOL_DESCRIPTION,
12
+ SUBAGENT_PARENT_ROUTING_GUIDANCE,
12
13
  SUBAGENT_SAFETY_GUIDANCE,
13
14
  } from "../../src/extension/tool-description.ts";
15
+ import { BUILTIN_AGENT_NAMES } from "../../src/agents/agents.ts";
14
16
  import { SUBAGENT_CHILD_ENV, SUBAGENT_FANOUT_CHILD_ENV } from "../../src/runs/shared/pi-args.ts";
15
17
 
16
18
  const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
@@ -31,9 +33,12 @@ describe("registered subagent tool description", () => {
31
33
  it("keeps full mode safe and free of hardcoded builtin agent names", () => {
32
34
  const description = buildSubagentToolDescription();
33
35
 
34
- for (const builtinName of ["scout", "worker", "planner"]) {
36
+ for (const builtinName of BUILTIN_AGENT_NAMES) {
35
37
  assert.doesNotMatch(description, new RegExp(`\\b${builtinName}\\b`));
36
38
  }
39
+ for (const legacyName of ["scout", "worker", "planner"]) {
40
+ assert.doesNotMatch(description, new RegExp(`\\b${legacyName}\\b`));
41
+ }
37
42
  assert.match(description, /^To delegate work, call with \{ agent, task \}, \{ tasks \}, or \{ chain \}; omit action\./i);
38
43
  assert.match(description, /Use action only for management\/control actions listed below/i);
39
44
  assert.match(description, /use \{ action: "list" \} to inspect configured agents\/chains/i);
@@ -50,6 +55,11 @@ describe("registered subagent tool description", () => {
50
55
  assert.doesNotMatch(description, /only for foreground runs/i);
51
56
  assert.doesNotMatch(description, /omit for async\/background runs/i);
52
57
  assert.match(description, /SAFETY-CRITICAL SUBAGENT GUIDANCE/);
58
+ assert.match(description, /PARENT-ONLY SUBAGENT ROUTING/);
59
+ assert.match(description, /call \{ action: "list" \} and select only an executable entry using its current role, context, and tool metadata/i);
60
+ assert.match(description, /Keep tiny targeted reads and simple answers local/i);
61
+ assert.match(description, /broad local investigation, external research, and mutation\/implementation work/i);
62
+ assert.match(description, /parent remains the decision-maker and normally the sole writer/i);
53
63
  assert.match(description, /Do not sleep or poll status just to wait/i);
54
64
  assert.match(description, /use subagent_wait/i);
55
65
  assert.match(description, /interactive session.*normally return control/i);
@@ -62,6 +72,10 @@ describe("registered subagent tool description", () => {
62
72
  assert.match(description, /action: "steer"/);
63
73
  assert.match(description, /schedule-list/);
64
74
  assert.match(description, /action: "eject"/);
75
+ assert.match(description, /action: "eject", agent: "agent-name"/);
76
+ assert.match(description, /action: "disable", agent: "agent-name"/);
77
+ assert.match(description, /action: "enable", agent: "agent-name"/);
78
+ assert.match(description, /action: "reset", agent: "agent-name"/);
65
79
  assert.match(description, /action: "disable"/);
66
80
  assert.match(description, /action: "grant-spawn-budget"/);
67
81
  assert.match(description, /root interactive parent/i);
@@ -97,6 +111,14 @@ describe("registered subagent tool description", () => {
97
111
  assert.match(description, /PARALLEL/);
98
112
  assert.match(description, /CHAIN/);
99
113
  assert.match(description, /action without execution fields/i);
114
+ assert.match(description, /Parent-only routing/);
115
+ assert.match(description, /select only an executable entry using its current role, context, and tool metadata/i);
116
+ assert.match(description, /Keep tiny targeted reads and simple answers local/i);
117
+ assert.match(description, /broad local investigation, external research, and mutation\/implementation work/i);
118
+ assert.match(description, /parent remains the decision-maker and normally the sole writer/i);
119
+ for (const builtinName of BUILTIN_AGENT_NAMES) {
120
+ assert.doesNotMatch(description, new RegExp(`\\b${builtinName}\\b`));
121
+ }
100
122
  assert.match(description, /subagent_wait/i);
101
123
  assert.match(description, /interactive session.*normally return control/i);
102
124
  assert.match(description, /Non-interactive runs.*auto-drain current-session work at agent_end/i);
@@ -127,6 +149,15 @@ describe("registered subagent tool description", () => {
127
149
  assert.match(description, /count:/);
128
150
  });
129
151
 
152
+ it("documents task-aware list advice as explicit-only in both modes", () => {
153
+ for (const description of [FULL_SUBAGENT_TOOL_DESCRIPTION, COMPACT_SUBAGENT_TOOL_DESCRIPTION]) {
154
+ assert.match(description, /\{ action: "list", task: "\.\.\." \}/);
155
+ assert.match(description, /advisory/i);
156
+ assert.match(description, /never launches/i);
157
+ assert.match(description, /explicitly call subagent|execute the recommended agent explicitly/i);
158
+ }
159
+ });
160
+
130
161
  it("renders a custom project description with placeholders and mandatory safety guidance", () => {
131
162
  const cwd = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-project-"));
132
163
  const agentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-agent-"));
@@ -148,6 +179,8 @@ describe("registered subagent tool description", () => {
148
179
  assert.match(description, new RegExp(escapeRegex(agentDir)));
149
180
  assert.match(description, new RegExp(escapeRegex(projectConfigDir)));
150
181
  assert.match(description, /SAFETY-CRITICAL SUBAGENT GUIDANCE/);
182
+ assert.match(description, /PARENT-ONLY SUBAGENT ROUTING/);
183
+ assert.match(description, /select only an executable entry using its current role, context, and tool metadata/i);
151
184
  assert.equal(warnings.length, 0);
152
185
  });
153
186
 
@@ -213,7 +246,7 @@ describe("registered subagent tool description", () => {
213
246
  assert.ok(warnings.some((message) => message.includes("Ignoring invalid toolDescriptionMode")));
214
247
  });
215
248
 
216
- function readRegisteredDescription(agentDir: string): string {
249
+ function readRegisteredTool(agentDir: string): { description: string; promptGuidelines?: string[] } {
217
250
  const script = String.raw`
218
251
  import registerSubagentExtension from "./src/extension/index.ts";
219
252
  const events = { on() { return () => {}; }, emit() {} };
@@ -234,12 +267,15 @@ describe("registered subagent tool description", () => {
234
267
  });
235
268
  registerSubagentExtension(fakePi);
236
269
  if (!registeredTool) throw new Error("tool not registered");
237
- process.stdout.write(JSON.stringify(registeredTool.description));
270
+ process.stdout.write(JSON.stringify({
271
+ description: registeredTool.description,
272
+ promptGuidelines: registeredTool.promptGuidelines ?? null,
273
+ }));
238
274
  `;
239
275
  const output = execFileSync(
240
276
  process.execPath,
241
277
  [
242
- "--experimental-transform-types",
278
+ "--experimental-strip-types",
243
279
  "--import",
244
280
  "./test/support/register-loader.mjs",
245
281
  "--input-type=module",
@@ -248,7 +284,7 @@ describe("registered subagent tool description", () => {
248
284
  ],
249
285
  { cwd: projectRoot, env: parentToolEnv(agentDir), encoding: "utf-8" },
250
286
  );
251
- return JSON.parse(output) as string;
287
+ return JSON.parse(output) as { description: string; promptGuidelines?: string[] };
252
288
  }
253
289
 
254
290
  function writeExtensionConfig(agentDir: string, config: Record<string, unknown>): void {
@@ -259,25 +295,40 @@ describe("registered subagent tool description", () => {
259
295
 
260
296
  it("registers full, compact, custom, and fallback descriptions from extension config", () => {
261
297
  const defaultAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-default-"));
262
- assert.equal(readRegisteredDescription(defaultAgentDir), FULL_SUBAGENT_TOOL_DESCRIPTION);
298
+ assert.equal(readRegisteredTool(defaultAgentDir).description, FULL_SUBAGENT_TOOL_DESCRIPTION);
263
299
 
264
300
  const compactAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-compact-"));
265
301
  writeExtensionConfig(compactAgentDir, { toolDescriptionMode: "compact" });
266
- assert.equal(readRegisteredDescription(compactAgentDir), COMPACT_SUBAGENT_TOOL_DESCRIPTION);
302
+ assert.equal(readRegisteredTool(compactAgentDir).description, COMPACT_SUBAGENT_TOOL_DESCRIPTION);
267
303
 
268
304
  const customAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-custom-"));
269
305
  writeExtensionConfig(customAgentDir, { toolDescriptionMode: "custom" });
270
306
  fs.writeFileSync(path.join(customAgentDir, "subagent-tool-description.md"), "Registered custom description.", "utf-8");
271
- const customDescription = readRegisteredDescription(customAgentDir);
307
+ const customDescription = readRegisteredTool(customAgentDir).description;
272
308
  assert.match(customDescription, /Registered custom description/);
273
309
  assert.match(customDescription, /SAFETY-CRITICAL SUBAGENT GUIDANCE/);
274
310
 
275
311
  const missingCustomAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-missing-"));
276
312
  writeExtensionConfig(missingCustomAgentDir, { toolDescriptionMode: "custom" });
277
- assert.equal(readRegisteredDescription(missingCustomAgentDir), FULL_SUBAGENT_TOOL_DESCRIPTION);
313
+ assert.equal(readRegisteredTool(missingCustomAgentDir).description, FULL_SUBAGENT_TOOL_DESCRIPTION);
278
314
 
279
315
  const invalidAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-invalid-"));
280
316
  writeExtensionConfig(invalidAgentDir, { toolDescriptionMode: "tiny" });
281
- assert.equal(readRegisteredDescription(invalidAgentDir), FULL_SUBAGENT_TOOL_DESCRIPTION);
317
+ assert.equal(readRegisteredTool(invalidAgentDir).description, FULL_SUBAGENT_TOOL_DESCRIPTION);
318
+ });
319
+
320
+ it("registers parent-only routing guidance as promptGuidelines on the parent tool", () => {
321
+ const defaultAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-guidelines-"));
322
+ const registered = readRegisteredTool(defaultAgentDir);
323
+
324
+ assert.ok(Array.isArray(registered.promptGuidelines), "parent subagent tool must expose promptGuidelines");
325
+ assert.equal(registered.promptGuidelines!.length, 1);
326
+ assert.equal(registered.promptGuidelines![0], SUBAGENT_PARENT_ROUTING_GUIDANCE);
327
+ assert.doesNotMatch(SUBAGENT_PARENT_ROUTING_GUIDANCE, new RegExp(BUILTIN_AGENT_NAMES.join("|")));
328
+ assert.match(SUBAGENT_PARENT_ROUTING_GUIDANCE, /\{ action: "list" \}/);
329
+ assert.match(SUBAGENT_PARENT_ROUTING_GUIDANCE, /executable entry/i);
330
+ assert.match(SUBAGENT_PARENT_ROUTING_GUIDANCE, /tiny targeted reads and simple answers local/i);
331
+ assert.match(SUBAGENT_PARENT_ROUTING_GUIDANCE, /broad local investigation, external research, and mutation\/implementation work/i);
332
+ assert.match(SUBAGENT_PARENT_ROUTING_GUIDANCE, /decision-maker and normally the sole writer/i);
282
333
  });
283
334
  });
@@ -7,6 +7,7 @@ function resultWithUsage(usage: Usage): SingleResult {
7
7
  return {
8
8
  agent: "agent",
9
9
  task: "task",
10
+ index: 0,
10
11
  exitCode: 0,
11
12
  messages: [],
12
13
  usage,