@selesai/code 0.12.0 → 0.13.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 (466) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/core/agent-session.d.ts +1 -1
  3. package/dist/core/agent-session.js +1 -1
  4. package/dist/core/sdk.d.ts +2 -2
  5. package/dist/core/sdk.js +1 -1
  6. package/dist/core/system-prompt.d.ts +1 -1
  7. package/dist/core/system-prompt.js +1 -1
  8. package/dist/core/usage-totals.d.ts +2 -0
  9. package/dist/core/usage-totals.js +10 -0
  10. package/dist/extensions/ascii.txt +9 -0
  11. package/dist/extensions/package.json +1 -2
  12. package/dist/extensions/pi-hermes-memory/CHANGELOG.md +371 -0
  13. package/dist/extensions/pi-hermes-memory/LICENSE +21 -0
  14. package/dist/extensions/pi-hermes-memory/README.md +643 -0
  15. package/dist/extensions/pi-hermes-memory/docs/0.1/TASKS.md +197 -0
  16. package/dist/extensions/pi-hermes-memory/docs/0.2/PLAN.md +290 -0
  17. package/dist/extensions/pi-hermes-memory/docs/0.2/TASKS.md +134 -0
  18. package/dist/extensions/pi-hermes-memory/docs/0.2/TEST-PLAN.md +216 -0
  19. package/dist/extensions/pi-hermes-memory/docs/0.3/PLAN.md +330 -0
  20. package/dist/extensions/pi-hermes-memory/docs/0.3/TASKS.md +125 -0
  21. package/dist/extensions/pi-hermes-memory/docs/0.4/PLAN.md +160 -0
  22. package/dist/extensions/pi-hermes-memory/docs/0.4/TASKS.md +113 -0
  23. package/dist/extensions/pi-hermes-memory/docs/0.6/CHANGELOG.md +57 -0
  24. package/dist/extensions/pi-hermes-memory/docs/0.6/PLAN.md +202 -0
  25. package/dist/extensions/pi-hermes-memory/docs/0.6/TASKS.md +144 -0
  26. package/dist/extensions/pi-hermes-memory/docs/0.7/PLAN.md +349 -0
  27. package/dist/extensions/pi-hermes-memory/docs/0.7/TASKS.md +110 -0
  28. package/dist/extensions/pi-hermes-memory/docs/PUBLISHING.md +149 -0
  29. package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +468 -0
  30. package/dist/extensions/pi-hermes-memory/docs/images/memory-architecture.svg +1 -0
  31. package/dist/extensions/pi-hermes-memory/docs/images/pi-logo.svg +22 -0
  32. package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.png +0 -0
  33. package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.svg +19 -0
  34. package/dist/extensions/pi-hermes-memory/docs/images/security-flow.svg +1 -0
  35. package/dist/extensions/pi-hermes-memory/docs/images/session-lifecycle.svg +1 -0
  36. package/dist/extensions/pi-hermes-memory/docs/images/source-architecture.svg +1 -0
  37. package/dist/extensions/pi-hermes-memory/docs/mermaid/memory-architecture.mmd +49 -0
  38. package/dist/extensions/pi-hermes-memory/docs/mermaid/security-flow.mmd +40 -0
  39. package/dist/extensions/pi-hermes-memory/docs/mermaid/session-lifecycle.mmd +56 -0
  40. package/dist/extensions/pi-hermes-memory/docs/mermaid/source-architecture.mmd +54 -0
  41. package/dist/extensions/pi-hermes-memory/package-lock.json +3799 -0
  42. package/dist/extensions/pi-hermes-memory/package.json +66 -0
  43. package/dist/extensions/pi-hermes-memory/scripts/check-min-sdk.mjs +99 -0
  44. package/dist/extensions/pi-hermes-memory/scripts/ensure-dev.mjs +57 -0
  45. package/dist/extensions/pi-hermes-memory/src/auto-consolidation-warning.ts +6 -0
  46. package/dist/extensions/pi-hermes-memory/src/config.ts +178 -0
  47. package/dist/extensions/pi-hermes-memory/src/constants.ts +424 -0
  48. package/dist/extensions/pi-hermes-memory/src/extension-root-migration.ts +639 -0
  49. package/dist/extensions/pi-hermes-memory/src/handlers/auto-consolidate.ts +401 -0
  50. package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +297 -0
  51. package/dist/extensions/pi-hermes-memory/src/handlers/child-process-watchdog.mjs +90 -0
  52. package/dist/extensions/pi-hermes-memory/src/handlers/correction-detector.ts +300 -0
  53. package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +86 -0
  54. package/dist/extensions/pi-hermes-memory/src/handlers/insights.ts +78 -0
  55. package/dist/extensions/pi-hermes-memory/src/handlers/interview.ts +37 -0
  56. package/dist/extensions/pi-hermes-memory/src/handlers/learn-memory.ts +186 -0
  57. package/dist/extensions/pi-hermes-memory/src/handlers/message-parts.ts +27 -0
  58. package/dist/extensions/pi-hermes-memory/src/handlers/pi-child-process.ts +485 -0
  59. package/dist/extensions/pi-hermes-memory/src/handlers/preview-context.ts +105 -0
  60. package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +506 -0
  61. package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +145 -0
  62. package/dist/extensions/pi-hermes-memory/src/handlers/session-flush.ts +151 -0
  63. package/dist/extensions/pi-hermes-memory/src/handlers/session-live-index.ts +94 -0
  64. package/dist/extensions/pi-hermes-memory/src/handlers/skills-command.ts +1334 -0
  65. package/dist/extensions/pi-hermes-memory/src/handlers/standing-pin.ts +111 -0
  66. package/dist/extensions/pi-hermes-memory/src/handlers/switch-project.ts +75 -0
  67. package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +266 -0
  68. package/dist/extensions/pi-hermes-memory/src/index.ts +378 -0
  69. package/dist/extensions/pi-hermes-memory/src/lifecycle-timing.ts +54 -0
  70. package/dist/extensions/pi-hermes-memory/src/paths.ts +61 -0
  71. package/dist/extensions/pi-hermes-memory/src/project-context.ts +13 -0
  72. package/dist/extensions/pi-hermes-memory/src/project-memory-migration.ts +93 -0
  73. package/dist/extensions/pi-hermes-memory/src/project.ts +157 -0
  74. package/dist/extensions/pi-hermes-memory/src/prompt-context.ts +55 -0
  75. package/dist/extensions/pi-hermes-memory/src/store/atomic-lock-coordinator.ts +375 -0
  76. package/dist/extensions/pi-hermes-memory/src/store/canonical-storage-path.ts +54 -0
  77. package/dist/extensions/pi-hermes-memory/src/store/content-scanner.ts +101 -0
  78. package/dist/extensions/pi-hermes-memory/src/store/db.ts +1180 -0
  79. package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +101 -0
  80. package/dist/extensions/pi-hermes-memory/src/store/markdown-mutation-lock.ts +38 -0
  81. package/dist/extensions/pi-hermes-memory/src/store/memory-lookup.ts +24 -0
  82. package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +1191 -0
  83. package/dist/extensions/pi-hermes-memory/src/store/recovery-maintenance.ts +66 -0
  84. package/dist/extensions/pi-hermes-memory/src/store/schema.ts +118 -0
  85. package/dist/extensions/pi-hermes-memory/src/store/session-anchor-search.ts +472 -0
  86. package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +511 -0
  87. package/dist/extensions/pi-hermes-memory/src/store/session-parser.ts +213 -0
  88. package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +234 -0
  89. package/dist/extensions/pi-hermes-memory/src/store/skill-store.ts +950 -0
  90. package/dist/extensions/pi-hermes-memory/src/store/skill-utils.ts +133 -0
  91. package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +1002 -0
  92. package/dist/extensions/pi-hermes-memory/src/store/sqlite-native.ts +241 -0
  93. package/dist/extensions/pi-hermes-memory/src/store/standing-instructions.ts +247 -0
  94. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +95 -0
  95. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +469 -0
  96. package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +246 -0
  97. package/dist/extensions/pi-hermes-memory/src/tools/shared-output-view.ts +170 -0
  98. package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +333 -0
  99. package/dist/extensions/pi-hermes-memory/src/tools/tool-result-views.ts +105 -0
  100. package/dist/extensions/pi-hermes-memory/src/types.ts +214 -0
  101. package/dist/extensions/pi-hermes-memory/tests/config.test.ts +434 -0
  102. package/dist/extensions/pi-hermes-memory/tests/extension-root-migration.test.ts +368 -0
  103. package/dist/extensions/pi-hermes-memory/tests/handlers/auto-consolidate.test.ts +984 -0
  104. package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +950 -0
  105. package/dist/extensions/pi-hermes-memory/tests/handlers/correction-detector.test.ts +671 -0
  106. package/dist/extensions/pi-hermes-memory/tests/handlers/insights.test.ts +157 -0
  107. package/dist/extensions/pi-hermes-memory/tests/handlers/interview.test.ts +127 -0
  108. package/dist/extensions/pi-hermes-memory/tests/handlers/pi-child-process.test.ts +905 -0
  109. package/dist/extensions/pi-hermes-memory/tests/handlers/preview-context.test.ts +152 -0
  110. package/dist/extensions/pi-hermes-memory/tests/handlers/prompt-context.test.ts +166 -0
  111. package/dist/extensions/pi-hermes-memory/tests/handlers/resources-discover.test.ts +71 -0
  112. package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +614 -0
  113. package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +192 -0
  114. package/dist/extensions/pi-hermes-memory/tests/handlers/session-flush.test.ts +677 -0
  115. package/dist/extensions/pi-hermes-memory/tests/handlers/session-live-index.test.ts +225 -0
  116. package/dist/extensions/pi-hermes-memory/tests/handlers/skills-command.test.ts +827 -0
  117. package/dist/extensions/pi-hermes-memory/tests/handlers/standing-pin.test.ts +134 -0
  118. package/dist/extensions/pi-hermes-memory/tests/handlers/sync-markdown-memories.test.ts +491 -0
  119. package/dist/extensions/pi-hermes-memory/tests/handlers/system-prompt.test.ts +199 -0
  120. package/dist/extensions/pi-hermes-memory/tests/handlers/thinking-max.test.ts +64 -0
  121. package/dist/extensions/pi-hermes-memory/tests/index.test.ts +30 -0
  122. package/dist/extensions/pi-hermes-memory/tests/integration/flow.test.ts +126 -0
  123. package/dist/extensions/pi-hermes-memory/tests/lifecycle-timing.test.ts +76 -0
  124. package/dist/extensions/pi-hermes-memory/tests/paths.test.ts +23 -0
  125. package/dist/extensions/pi-hermes-memory/tests/project-memory-migration.test.ts +80 -0
  126. package/dist/extensions/pi-hermes-memory/tests/project-rebinding.test.ts +115 -0
  127. package/dist/extensions/pi-hermes-memory/tests/project.test.ts +120 -0
  128. package/dist/extensions/pi-hermes-memory/tests/run-all-timeout.test.ts +107 -0
  129. package/dist/extensions/pi-hermes-memory/tests/run-all.sh +45 -0
  130. package/dist/extensions/pi-hermes-memory/tests/store/atomic-lock-coordinator.test.ts +381 -0
  131. package/dist/extensions/pi-hermes-memory/tests/store/content-scanner.test.ts +388 -0
  132. package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +1046 -0
  133. package/dist/extensions/pi-hermes-memory/tests/store/markdown-mutation-lock.test.ts +34 -0
  134. package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +2150 -0
  135. package/dist/extensions/pi-hermes-memory/tests/store/recovery-maintenance.test.ts +170 -0
  136. package/dist/extensions/pi-hermes-memory/tests/store/session-anchor-search.test.ts +210 -0
  137. package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +643 -0
  138. package/dist/extensions/pi-hermes-memory/tests/store/session-parser.test.ts +282 -0
  139. package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +287 -0
  140. package/dist/extensions/pi-hermes-memory/tests/store/skill-store.test.ts +678 -0
  141. package/dist/extensions/pi-hermes-memory/tests/store/skill-utils.test.ts +21 -0
  142. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-lazy-load.test.ts +78 -0
  143. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +543 -0
  144. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +164 -0
  145. package/dist/extensions/pi-hermes-memory/tests/store/standing-instructions.test.ts +171 -0
  146. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +84 -0
  147. package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +709 -0
  148. package/dist/extensions/pi-hermes-memory/tests/tools/session-search-tool.test.ts +345 -0
  149. package/dist/extensions/pi-hermes-memory/tests/tools/shared-output-view.test.ts +362 -0
  150. package/dist/extensions/pi-hermes-memory/tests/tools/skill-tool.test.ts +478 -0
  151. package/dist/extensions/pi-hermes-memory/tests/tools/tool-result-renderer-wiring.test.ts +40 -0
  152. package/dist/extensions/pi-hermes-memory/tsconfig.json +19 -0
  153. package/dist/extensions/pi-subagents/.oxlintrc.json +43 -0
  154. package/dist/extensions/pi-subagents/AGENTS.md +5 -0
  155. package/dist/extensions/pi-subagents/CHANGELOG.md +157 -0
  156. package/dist/extensions/pi-subagents/README.md +12 -6
  157. package/dist/extensions/pi-subagents/VISION.md +81 -0
  158. package/dist/extensions/pi-subagents/agents/claude-code-writer.md +15 -0
  159. package/dist/extensions/pi-subagents/agents/claude-code.md +15 -0
  160. package/dist/extensions/pi-subagents/agents/codex-exec-writer.md +15 -0
  161. package/dist/extensions/pi-subagents/agents/codex-exec.md +15 -0
  162. package/dist/extensions/pi-subagents/agents/cursor-agent-writer.md +14 -0
  163. package/dist/extensions/pi-subagents/agents/cursor-agent.md +14 -0
  164. package/dist/extensions/pi-subagents/agents/reviewer.md +1 -3
  165. package/dist/extensions/pi-subagents/docs/agents.md +488 -0
  166. package/dist/extensions/pi-subagents/docs/configuration.md +46 -9
  167. package/dist/extensions/pi-subagents/docs/extension-api.md +42 -3
  168. package/dist/extensions/pi-subagents/docs/models.md +27 -4
  169. package/dist/extensions/pi-subagents/docs/observability.md +10 -9
  170. package/dist/extensions/pi-subagents/docs/tool-reference.md +102 -6
  171. package/dist/extensions/pi-subagents/docs/workflows.md +135 -0
  172. package/dist/extensions/pi-subagents/package-lock.json +389 -2
  173. package/dist/extensions/pi-subagents/package.json +3 -1
  174. package/dist/extensions/pi-subagents/prompts/review-loop.md +2 -2
  175. package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +1 -1
  176. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +3 -1
  177. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +7 -3
  178. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
  179. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +26 -5
  180. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +41 -22
  181. package/dist/extensions/pi-subagents/src/agents/agent-refinements.ts +4 -4
  182. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +9 -2
  183. package/dist/extensions/pi-subagents/src/agents/agents.ts +322 -75
  184. package/dist/extensions/pi-subagents/src/agents/builtin-names.ts +6 -0
  185. package/dist/extensions/pi-subagents/src/agents/runtime-agent-events.ts +70 -0
  186. package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +27 -20
  187. package/dist/extensions/pi-subagents/src/api/agents.ts +10 -5
  188. package/dist/extensions/pi-subagents/src/api/background-work.ts +5 -1
  189. package/dist/extensions/pi-subagents/src/api/delegation.ts +0 -7
  190. package/dist/extensions/pi-subagents/src/api/preflight.ts +34 -12
  191. package/dist/extensions/pi-subagents/src/extension/config.ts +70 -0
  192. package/dist/extensions/pi-subagents/src/extension/doctor.ts +3 -3
  193. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +5 -3
  194. package/dist/extensions/pi-subagents/src/extension/index.ts +83 -30
  195. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +44 -15
  196. package/dist/extensions/pi-subagents/src/extension/rpc.ts +55 -19
  197. package/dist/extensions/pi-subagents/src/extension/schemas.ts +41 -15
  198. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +28 -31
  199. package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +2 -1
  200. package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +2 -10
  201. package/dist/extensions/pi-subagents/src/inspectors/herdr/session-roots-codec.ts +42 -0
  202. package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +51 -3
  203. package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +2 -0
  204. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +5 -6
  205. package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +77 -10
  206. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +176 -53
  207. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +19 -12
  208. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +29 -27
  209. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +20 -3
  210. package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +23 -261
  211. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +73 -7
  212. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +8 -3
  213. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +74 -8
  214. package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +37 -21
  215. package/dist/extensions/pi-subagents/src/runs/background/inspect-rpc.ts +8 -8
  216. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +184 -9
  217. package/dist/extensions/pi-subagents/src/runs/background/result-delivery-ownership.ts +45 -0
  218. package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +28 -14
  219. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +38 -15
  220. package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +1 -1
  221. package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +1 -1
  222. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +50 -13
  223. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +93 -8
  224. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +10 -4
  225. package/dist/extensions/pi-subagents/src/runs/background/steering.ts +4 -14
  226. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +549 -377
  227. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +58 -10
  228. package/dist/extensions/pi-subagents/src/runs/background/terminal-run-index.ts +1 -1
  229. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +26 -1
  230. package/dist/extensions/pi-subagents/src/runs/background/wait-config.ts +23 -9
  231. package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +9 -2
  232. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +2 -2
  233. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +204 -129
  234. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +9 -0
  235. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +23 -1
  236. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +773 -311
  237. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +140 -115
  238. package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +119 -0
  239. package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +463 -0
  240. package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +19 -4
  241. package/dist/extensions/pi-subagents/src/runs/shared/child-launch-plan.ts +151 -0
  242. package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +21 -7
  243. package/dist/extensions/pi-subagents/src/runs/shared/claude-code-adapter.ts +129 -0
  244. package/dist/extensions/pi-subagents/src/runs/shared/codex-exec-adapter.ts +129 -0
  245. package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +89 -0
  246. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +5 -4
  247. package/dist/extensions/pi-subagents/src/runs/shared/cursor-agent-adapter.ts +114 -0
  248. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +3 -3
  249. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-contract.ts +167 -0
  250. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +122 -0
  251. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +348 -55
  252. package/dist/extensions/pi-subagents/src/runs/shared/fast-mode-extension.ts +5 -5
  253. package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +230 -0
  254. package/dist/extensions/pi-subagents/src/runs/shared/lane-metadata.ts +105 -0
  255. package/dist/extensions/pi-subagents/src/runs/shared/launch-cwd.ts +16 -0
  256. package/dist/extensions/pi-subagents/src/runs/shared/long-running-guard.ts +2 -1
  257. package/dist/extensions/pi-subagents/src/runs/shared/mcp-config-sources.ts +422 -0
  258. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +221 -158
  259. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-grant.ts +197 -0
  260. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +69 -7
  261. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +47 -6
  262. package/dist/extensions/pi-subagents/src/runs/shared/mutation-evidence.ts +7 -2
  263. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +9 -3
  264. package/dist/extensions/pi-subagents/src/runs/shared/nested-render.ts +9 -5
  265. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +419 -7
  266. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +15 -1
  267. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +81 -8
  268. package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +13 -0
  269. package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +21 -1
  270. package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +44 -4
  271. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +98 -13
  272. package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +1 -1
  273. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +847 -0
  274. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +18 -0
  275. package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +46 -0
  276. package/dist/extensions/pi-subagents/src/shared/extension-context.ts +24 -0
  277. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +21 -0
  278. package/dist/extensions/pi-subagents/src/shared/formatters.ts +18 -3
  279. package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +5 -1
  280. package/dist/extensions/pi-subagents/src/shared/pruned-fork.ts +450 -0
  281. package/dist/extensions/pi-subagents/src/shared/session-file-trust.ts +19 -0
  282. package/dist/extensions/pi-subagents/src/shared/session-tokens.ts +14 -3
  283. package/dist/extensions/pi-subagents/src/shared/settings.ts +19 -105
  284. package/dist/extensions/pi-subagents/src/shared/shortcuts.ts +17 -0
  285. package/dist/extensions/pi-subagents/src/shared/types.ts +359 -40
  286. package/dist/extensions/pi-subagents/src/shared/utils.ts +41 -84
  287. package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +116 -0
  288. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +1 -9
  289. package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +0 -4
  290. package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +1 -2
  291. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +378 -88
  292. package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +22 -11
  293. package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +3 -0
  294. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +147 -79
  295. package/dist/extensions/pi-subagents/src/tui/fleet-transcript.ts +11 -5
  296. package/dist/extensions/pi-subagents/src/tui/fleet.ts +39 -18
  297. package/dist/extensions/pi-subagents/src/tui/render.ts +369 -46
  298. package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +1 -1
  299. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +6 -3
  300. package/dist/extensions/pi-subagents/src/workflows/host-command.ts +230 -0
  301. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +740 -58
  302. package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +121 -0
  303. package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +270 -0
  304. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +195 -6
  305. package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +246 -0
  306. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
  307. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +1114 -260
  308. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +34 -0
  309. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +150 -3
  310. package/dist/extensions/pi-subagents/test/integration/claude-code-smoke.test.ts +52 -0
  311. package/dist/extensions/pi-subagents/test/integration/claude-code-writer-smoke.test.ts +55 -0
  312. package/dist/extensions/pi-subagents/test/integration/codex-exec-smoke.test.ts +53 -0
  313. package/dist/extensions/pi-subagents/test/integration/codex-exec-writer-smoke.test.ts +57 -0
  314. package/dist/extensions/pi-subagents/test/integration/cursor-agent-smoke.test.ts +59 -0
  315. package/dist/extensions/pi-subagents/test/integration/cursor-agent-writer-smoke.test.ts +62 -0
  316. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +57 -1
  317. package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +1 -0
  318. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +20 -0
  319. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +4 -3
  320. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +2 -2
  321. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +54 -4
  322. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +482 -4
  323. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +157 -9
  324. package/dist/extensions/pi-subagents/test/integration/session-tokens.test.ts +5 -5
  325. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +1508 -291
  326. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +423 -1
  327. package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +8 -0
  328. package/dist/extensions/pi-subagents/test/support/cursor-smoke-inputs.ts +51 -0
  329. package/dist/extensions/pi-subagents/test/support/helpers.ts +2 -0
  330. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +5 -5
  331. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +6 -6
  332. package/dist/extensions/pi-subagents/test/unit/abort-recovery.test.ts +152 -0
  333. package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +48 -0
  334. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +184 -6
  335. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +66 -6
  336. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +77 -0
  337. package/dist/extensions/pi-subagents/test/unit/agent-refinements.test.ts +18 -0
  338. package/dist/extensions/pi-subagents/test/unit/anti-slop-oxlint.test.ts +86 -0
  339. package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +1 -1
  340. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +101 -1
  341. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +121 -0
  342. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +28 -0
  343. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +14 -7
  344. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +53 -0
  345. package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +190 -0
  346. package/dist/extensions/pi-subagents/test/unit/async-status-snapshot.test.ts +42 -0
  347. package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +8 -4
  348. package/dist/extensions/pi-subagents/test/unit/background-work.test.ts +23 -0
  349. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +78 -1
  350. package/dist/extensions/pi-subagents/test/unit/child-launch-plan.test.ts +94 -0
  351. package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +21 -0
  352. package/dist/extensions/pi-subagents/test/unit/child-session-name.test.ts +50 -0
  353. package/dist/extensions/pi-subagents/test/unit/claude-code-adapter.test.ts +245 -0
  354. package/dist/extensions/pi-subagents/test/unit/codex-exec-adapter.test.ts +192 -0
  355. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +27 -0
  356. package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +150 -0
  357. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +21 -0
  358. package/dist/extensions/pi-subagents/test/unit/cursor-agent-adapter.test.ts +259 -0
  359. package/dist/extensions/pi-subagents/test/unit/cursor-smoke-inputs.test.ts +77 -0
  360. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +1 -4
  361. package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +1 -1
  362. package/dist/extensions/pi-subagents/test/unit/extension-context.test.ts +27 -0
  363. package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +223 -0
  364. package/dist/extensions/pi-subagents/test/unit/fast-mode-extension.test.ts +27 -0
  365. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +208 -2
  366. package/dist/extensions/pi-subagents/test/unit/fleet-transcript.test.ts +29 -1
  367. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +110 -1
  368. package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +10 -0
  369. package/dist/extensions/pi-subagents/test/unit/formatters.test.ts +14 -0
  370. package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +18 -9
  371. package/dist/extensions/pi-subagents/test/unit/herdr-session-roots-codec.test.ts +63 -0
  372. package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +2 -2
  373. package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +132 -0
  374. package/dist/extensions/pi-subagents/test/unit/host-command.test.ts +156 -0
  375. package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +98 -0
  376. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +178 -26
  377. package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +2 -1
  378. package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +21 -0
  379. package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-grant.test.ts +138 -0
  380. package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +1 -1
  381. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +91 -0
  382. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +72 -7
  383. package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +21 -0
  384. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +1 -0
  385. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +20 -2
  386. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +129 -1
  387. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +2 -2
  388. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +4 -0
  389. package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +358 -0
  390. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +574 -21
  391. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +109 -1
  392. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +71 -1
  393. package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +7 -7
  394. package/dist/extensions/pi-subagents/test/unit/pruned-fork.test.ts +214 -0
  395. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +29 -8
  396. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +53 -0
  397. package/dist/extensions/pi-subagents/test/unit/result-delivery-ownership.test.ts +34 -0
  398. package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +101 -3
  399. package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +1 -0
  400. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +10 -8
  401. package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +71 -1
  402. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +41 -7
  403. package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +136 -2
  404. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +137 -0
  405. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +33 -12
  406. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +504 -1
  407. package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +8 -0
  408. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
  409. package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +12 -1
  410. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +3 -5
  411. package/dist/extensions/pi-subagents/test/unit/steering.test.ts +5 -6
  412. package/dist/extensions/pi-subagents/test/unit/subagent-action-recovery.test.ts +0 -8
  413. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +5 -0
  414. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +157 -2
  415. package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +1 -1
  416. package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +63 -4
  417. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +27 -23
  418. package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +44 -0
  419. package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +1 -0
  420. package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +7 -5
  421. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +106 -0
  422. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +484 -9
  423. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +38 -4
  424. package/dist/extensions/pi-subagents/test/unit/workflow-preflight.test.ts +155 -0
  425. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +318 -0
  426. package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +365 -0
  427. package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +349 -0
  428. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +21 -0
  429. package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +2 -7
  430. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/index.ts +13 -0
  431. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/rules/no-service-constructor-imports.ts +52 -0
  432. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/index.ts +41 -0
  433. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-chained-type-assertions.ts +77 -0
  434. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-conditional-empty-object-spread.ts +49 -0
  435. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-known-value-widening.ts +247 -0
  436. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-module-mocking.ts +91 -0
  437. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-object-parameters.ts +126 -0
  438. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-apply.ts +28 -0
  439. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-get.ts +28 -0
  440. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-runtime-typeof.ts +67 -0
  441. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-shape-in-symbol-names.ts +39 -0
  442. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-parameters.ts +83 -0
  443. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-returns.ts +115 -0
  444. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-type-aliases.ts +72 -0
  445. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unsafe-dictionary-type.ts +134 -0
  446. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-widen-then-assert.ts +366 -0
  447. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/require-safety-comment-for-type-assertion.ts +62 -0
  448. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/dictionary-types.ts +502 -0
  449. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/lexical-type-parameters.ts +60 -0
  450. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/reflect-method.ts +35 -0
  451. package/dist/extensions/pi-tool-display/tests/capabilities.test.ts +1 -1
  452. package/dist/extensions/pi-tool-display/tests/settings-inspector.test.ts +2 -2
  453. package/dist/extensions/pi-tool-display/tests/tool-overrides-mcp.test.ts +1 -1
  454. package/dist/extensions/pi-zentui/extensions/zentui/format.ts +2 -1
  455. package/dist/extensions/pi-zentui/test/format.test.ts +15 -1
  456. package/dist/modes/interactive/components/footer.js +2 -2
  457. package/dist/modes/interactive/interactive-mode.js +11 -11
  458. package/dist/skills/workflow/SKILL.md +65 -50
  459. package/package.json +112 -110
  460. package/dist/extensions/enable-readonly-tools.test.ts +0 -63
  461. package/dist/extensions/enable-readonly-tools.ts +0 -24
  462. package/dist/extensions/model-prompt-injector/config.json +0 -16
  463. package/dist/extensions/model-prompt-injector/index.test.ts +0 -102
  464. package/dist/extensions/model-prompt-injector/index.ts +0 -148
  465. package/dist/extensions/pi-subagents/src/runs/shared/turn-budget.ts +0 -98
  466. package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +0 -250
@@ -106,18 +106,15 @@ describe("steering lifecycle ledger", () => {
106
106
  assert.equal(result?.targets[0]?.lateDeliveredAt, 5);
107
107
  });
108
108
 
109
- it("preserves only remaining deadline, turn, and tool budgets", () => {
109
+ it("preserves only remaining deadline and tool budgets", () => {
110
110
  assert.deepEqual(remainingSteeringRecoveryLimits({
111
111
  absoluteDeadlineAt: 10_000,
112
- initialTurnBudget: { maxTurns: 20, graceTurns: 3 },
113
112
  initialToolBudget: { soft: 45, hard: 65, block: ["read"] },
114
113
  }, {
115
- turnBudget: { maxTurns: 20, graceTurns: 3, turnCount: 21, outcome: "wrap-up-requested" },
116
114
  toolBudget: { soft: 45, hard: 65, block: ["read"], toolCount: 50, outcome: "soft-reached" },
117
115
  }, 4_000), {
118
116
  timeoutMs: 6_000,
119
117
  absoluteDeadlineAt: 10_000,
120
- turnBudget: { maxTurns: 1, graceTurns: 1 },
121
118
  toolBudget: { hard: 15, block: ["read"] },
122
119
  });
123
120
  });
@@ -130,6 +127,7 @@ describe("steering lifecycle ledger", () => {
130
127
  fallbackModels: ["current/fallback"],
131
128
  thinking: "high",
132
129
  tools: ["write"],
130
+ allowNestedSubagents: true,
133
131
  extensions: ["current-extension"],
134
132
  subagentOnlyExtensions: ["current-child-extension"],
135
133
  mcpDirectTools: ["current_mcp"],
@@ -153,6 +151,7 @@ describe("steering lifecycle ledger", () => {
153
151
  cwd: "/original",
154
152
  model: "original/model",
155
153
  tools: ["read"],
154
+ allowNestedSubagents: false,
156
155
  systemPrompt: "original prompt",
157
156
  systemPromptMode: "replace",
158
157
  inheritProjectContext: false,
@@ -164,6 +163,7 @@ describe("steering lifecycle ledger", () => {
164
163
  });
165
164
  assert.equal(recovered.model, "original/model");
166
165
  assert.deepEqual(recovered.tools, ["read"]);
166
+ assert.equal(recovered.allowNestedSubagents, false);
167
167
  assert.equal(recovered.systemPrompt, "original prompt");
168
168
  assert.equal(recovered.inheritProjectContext, false);
169
169
  assert.deepEqual(recovered.toolBudget, { hard: 7, block: ["read"] });
@@ -204,9 +204,8 @@ describe("steering lifecycle ledger", () => {
204
204
  assert.equal(recovered.maxThinking, "low");
205
205
  });
206
206
 
207
- it("rejects recovery when any configured hard budget is exhausted", () => {
207
+ it("rejects recovery when a configured deadline or tool budget is exhausted", () => {
208
208
  assert.throws(() => remainingSteeringRecoveryLimits({ absoluteDeadlineAt: 5 }, {}, 5), /deadline budget/);
209
- assert.throws(() => remainingSteeringRecoveryLimits({ initialTurnBudget: { maxTurns: 2, graceTurns: 1 } }, { turnCount: 3 }), /turn budget/);
210
209
  assert.throws(() => remainingSteeringRecoveryLimits({ initialToolBudget: { hard: 2, block: "*" } }, { toolCount: 2 }), /tool budget/);
211
210
  });
212
211
  });
@@ -54,14 +54,6 @@ describe("subagent action recovery", () => {
54
54
  assert.match(message, /Valid: .*status/);
55
55
  });
56
56
 
57
- it("does not list removed legacy controls", () => {
58
- const message = unknownSubagentActionMessage("not-a-real-action");
59
-
60
- assert.doesNotMatch(message, /append-step/);
61
- assert.doesNotMatch(message, /approve-checkpoint/);
62
- assert.doesNotMatch(message, /reject-checkpoint/);
63
- });
64
-
65
57
  it("does not suggest a destructive near-miss", () => {
66
58
  const message = unknownSubagentActionMessage("del");
67
59
 
@@ -21,4 +21,9 @@ describe("subagent guide", () => {
21
21
  it("registers the guide action for action recovery", () => {
22
22
  assert.ok(SUBAGENT_ACTIONS.includes("guide"));
23
23
  });
24
+
25
+ it("documents external CLI runner limits in packaged guide topics", () => {
26
+ assert.match(readSubagentGuide("tool-reference"), /External CLI agent profiles[\s\S]*native Pi child options[\s\S]*model override[\s\S]*native Pi tools/);
27
+ assert.match(readSubagentGuide("agents"), /External CLI agents use their own runner contract[\s\S]*native Pi child options/);
28
+ });
24
29
  });
@@ -19,6 +19,7 @@ import {
19
19
  import { RUNTIME_EXTENSION_ACK_EVENT, RUNTIME_EXTENSION_ACK_PATH_ENV } from "../../src/runs/shared/runtime-acknowledged-extensions.ts";
20
20
  import { STRUCTURED_OUTPUT_CAPTURE_ENV, STRUCTURED_OUTPUT_SCHEMA_ENV } from "../../src/runs/shared/structured-output.ts";
21
21
  import { TOOL_BUDGET_ENV } from "../../src/runs/shared/tool-budget.ts";
22
+ import { getAgentDir } from "../../src/shared/utils.ts";
22
23
  import { PERMISSION_POLICY_ENV } from "../../src/runs/shared/permissions.ts";
23
24
  import { CHILD_TOOL_DIAGNOSTIC_PATH_ENV, formatChildToolDiagnostic, MCP_DIRECT_CHILD_TOOLS_ENV, readChildToolDiagnostic, REQUIRED_CHILD_TOOLS_ENV } from "../../src/runs/shared/tool-availability.ts";
24
25
  import { CHILD_WATCHDOG_CONFIG_ENV } from "../../src/watchdog/child-status.ts";
@@ -30,6 +31,7 @@ import registerSubagentPromptRuntime, {
30
31
  registerPermissionGate,
31
32
  registerSteeringInbox,
32
33
  rewriteSubagentPrompt,
34
+ stripGlobalContext,
33
35
  stripInheritedSkills,
34
36
  stripParentOnlySubagentMessages,
35
37
  stripProjectContext,
@@ -38,6 +40,7 @@ import registerSubagentPromptRuntime, {
38
40
 
39
41
  const envSnapshot = {
40
42
  SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT: process.env.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT,
43
+ SELESAI_SUBAGENT_INHERIT_GLOBAL_CONTEXT: process.env.SELESAI_SUBAGENT_INHERIT_GLOBAL_CONTEXT,
41
44
  SELESAI_SUBAGENT_INHERIT_SKILLS: process.env.SELESAI_SUBAGENT_INHERIT_SKILLS,
42
45
  SELESAI_SUBAGENT_INTERCOM_SESSION_NAME: process.env.SELESAI_SUBAGENT_INTERCOM_SESSION_NAME,
43
46
  SELESAI_SUBAGENT_FANOUT_CHILD: process.env.SELESAI_SUBAGENT_FANOUT_CHILD,
@@ -59,6 +62,7 @@ const envSnapshot = {
59
62
  SELESAI_SUBAGENT_CHILD_AGENT: process.env.SELESAI_SUBAGENT_CHILD_AGENT,
60
63
  SELESAI_SUBAGENT_CHILD_INDEX: process.env.SELESAI_SUBAGENT_CHILD_INDEX,
61
64
  SELESAI_SUBAGENT_WATCHDOG_CHILD_CONFIG: process.env.SELESAI_SUBAGENT_WATCHDOG_CHILD_CONFIG,
65
+ PI_SUBAGENT_SESSION_NAME: process.env.PI_SUBAGENT_SESSION_NAME,
62
66
  };
63
67
 
64
68
  const SKILLS_SECTION = "\n\nThe following skills provide specialized instructions for specific tasks.\nUse the read tool to load a skill's file when the task matches its description.\nWhen a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\n\n<available_skills>\n <skill>\n <name>safe-bash</name>\n <description>desc</description>\n <location>/tmp/SKILL.md</location>\n </skill>\n <skill>\n <name>pi-subagents</name>\n <description>delegate to subagents</description>\n <location>/tmp/pi-subagents/SKILL.md</location>\n </skill>\n</available_skills>";
@@ -83,6 +87,8 @@ const CONFIGURED_SKILLS_SECTION = "\n\nThe following configured skills are avail
83
87
  afterEach(() => {
84
88
  if (envSnapshot.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT === undefined) delete process.env.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT;
85
89
  else process.env.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT = envSnapshot.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT;
90
+ if (envSnapshot.SELESAI_SUBAGENT_INHERIT_GLOBAL_CONTEXT === undefined) delete process.env.SELESAI_SUBAGENT_INHERIT_GLOBAL_CONTEXT;
91
+ else process.env.SELESAI_SUBAGENT_INHERIT_GLOBAL_CONTEXT = envSnapshot.SELESAI_SUBAGENT_INHERIT_GLOBAL_CONTEXT;
86
92
  if (envSnapshot.SELESAI_SUBAGENT_INHERIT_SKILLS === undefined) delete process.env.SELESAI_SUBAGENT_INHERIT_SKILLS;
87
93
  else process.env.SELESAI_SUBAGENT_INHERIT_SKILLS = envSnapshot.SELESAI_SUBAGENT_INHERIT_SKILLS;
88
94
  if (envSnapshot.SELESAI_SUBAGENT_INTERCOM_SESSION_NAME === undefined) delete process.env.SELESAI_SUBAGENT_INTERCOM_SESSION_NAME;
@@ -125,6 +131,8 @@ afterEach(() => {
125
131
  else process.env[SUBAGENT_CHILD_INDEX_ENV] = envSnapshot.SELESAI_SUBAGENT_CHILD_INDEX;
126
132
  if (envSnapshot.SELESAI_SUBAGENT_WATCHDOG_CHILD_CONFIG === undefined) delete process.env[CHILD_WATCHDOG_CONFIG_ENV];
127
133
  else process.env[CHILD_WATCHDOG_CONFIG_ENV] = envSnapshot.SELESAI_SUBAGENT_WATCHDOG_CHILD_CONFIG;
134
+ if (envSnapshot.PI_SUBAGENT_SESSION_NAME === undefined) delete process.env.PI_SUBAGENT_SESSION_NAME;
135
+ else process.env.PI_SUBAGENT_SESSION_NAME = envSnapshot.PI_SUBAGENT_SESSION_NAME;
128
136
  });
129
137
 
130
138
  function setSupervisorEnv(): void {
@@ -785,6 +793,126 @@ describe("subagent prompt runtime", () => {
785
793
  assert.ok(rewritten.includes("Current date: 2026-04-16"));
786
794
  });
787
795
 
796
+ it("strips an XML <project_context> block as full project context removal", () => {
797
+ const globalDir = getAgentDir();
798
+ const prompt = [
799
+ "You are a subagent.",
800
+ "\n\n<project_context>\n\nProject-specific instructions and guidelines:\n\n",
801
+ `<project_instructions path="${globalDir}/AGENTS.md">\nGlobal rules\n</project_instructions>\n\n`,
802
+ "<project_instructions path=\"/repo/AGENTS.md\">\nRepo rules\n</project_instructions>\n\n",
803
+ "</project_context>\n\n",
804
+ "Current working directory: /repo",
805
+ ].join("");
806
+ const rewritten = stripProjectContext(prompt);
807
+ assert.ok(!rewritten.includes("<project_context>"));
808
+ assert.ok(!rewritten.includes("<project_instructions"));
809
+ assert.ok(rewritten.includes("Current working directory: /repo"));
810
+ });
811
+
812
+ it("strips only global context files while preserving repository context", () => {
813
+ const globalDir = getAgentDir();
814
+ const prompt = [
815
+ "You are a subagent.",
816
+ "\n\n<project_context>\n\nProject-specific instructions and guidelines:\n\n",
817
+ `<project_instructions path="${globalDir}/AGENTS.md">\nGlobal rules\n</project_instructions>\n\n`,
818
+ "<project_instructions path=\"/repo/AGENTS.md\">\nRepo rules\n</project_instructions>\n\n",
819
+ "</project_context>\n\n",
820
+ "Current working directory: /repo",
821
+ ].join("");
822
+ const rewritten = stripGlobalContext(prompt);
823
+ assert.ok(!rewritten.includes("Global rules"));
824
+ assert.ok(rewritten.includes("Repo rules"));
825
+ assert.ok(rewritten.includes("</project_context>"));
826
+ });
827
+
828
+ it("strips only global context files from legacy Markdown while preserving repository context", () => {
829
+ const globalDir = getAgentDir();
830
+ const prompt = [
831
+ "You are a subagent.",
832
+ "\n\n# Project Context\n\nProject-specific instructions and guidelines:\n\n",
833
+ `## ${globalDir}/AGENTS.md\n\nGlobal rules\n\n`,
834
+ "## /repo/AGENTS.md\n\nRepo rules\n\n",
835
+ SKILLS_SECTION,
836
+ "\nCurrent date: 2026-04-16",
837
+ ].join("");
838
+ const rewritten = rewriteSubagentPrompt(prompt, {
839
+ inheritProjectContext: true,
840
+ inheritGlobalContext: false,
841
+ inheritSkills: true,
842
+ });
843
+ assert.ok(!rewritten.includes("Global rules"));
844
+ assert.ok(rewritten.includes("## /repo/AGENTS.md"));
845
+ assert.ok(rewritten.includes("Repo rules"));
846
+ });
847
+
848
+ it("recognizes Pi context filenames case-insensitively", () => {
849
+ const globalDir = getAgentDir();
850
+ const prompt = [
851
+ "You are a subagent.",
852
+ "\n\n<project_context>\n\nProject-specific instructions and guidelines:\n\n",
853
+ `<project_instructions path="${globalDir}/AGENTS.MD">\nGlobal rules\n</project_instructions>\n\n`,
854
+ "<project_instructions path=\"/repo/AGENTS.MD\">\nRepo rules\n</project_instructions>\n\n",
855
+ "</project_context>\n\n",
856
+ "Current working directory: /repo",
857
+ ].join("");
858
+ const rewritten = stripGlobalContext(prompt);
859
+ assert.ok(!rewritten.includes("Global rules"));
860
+ assert.ok(rewritten.includes("Repo rules"));
861
+ });
862
+
863
+ for (const [label, prompt] of [
864
+ ["CRLF context", `<project_context>\r\n<project_instructions path="${getAgentDir()}/AGENTS.md">\r\nGlobal rules\r\n</project_instructions>\r\n<project_instructions path="/repo/AGENTS.md">\r\nRepo rules\r\n</project_instructions>\r\n</project_context>`],
865
+ ["content without a trailing newline", `<project_context><project_instructions path="${getAgentDir()}/AGENTS.md">Global rules</project_instructions><project_instructions path="/repo/AGENTS.md">Repo rules</project_instructions></project_context>`],
866
+ ["same-line content", `<project_context><project_instructions path="${getAgentDir()}/CLAUDE.md">Global rules</project_instructions><project_instructions path="/repo/CLAUDE.md">Repo rules</project_instructions></project_context>`],
867
+ ] as const) {
868
+ it(`strips global instructions from ${label}`, () => {
869
+ const rewritten = stripGlobalContext(prompt);
870
+ assert.ok(!rewritten.includes("Global rules"));
871
+ assert.ok(rewritten.includes("Repo rules"));
872
+ });
873
+ }
874
+
875
+ it("does not strip matching examples outside project context", () => {
876
+ const example = `<project_instructions path="${getAgentDir()}/AGENTS.md">Example only</project_instructions>`;
877
+ assert.equal(stripGlobalContext(example), example);
878
+ });
879
+
880
+ it("inherits global context when inheritGlobalContext is true", () => {
881
+ const globalDir = getAgentDir();
882
+ const prompt = [
883
+ "You are a subagent.",
884
+ "\n\n<project_context>\n\nProject-specific instructions and guidelines:\n\n",
885
+ `<project_instructions path="${globalDir}/AGENTS.md">\nGlobal rules\n</project_instructions>\n\n`,
886
+ "</project_context>\n\n",
887
+ "Current working directory: /repo",
888
+ ].join("");
889
+ const rewritten = rewriteSubagentPrompt(prompt, {
890
+ inheritProjectContext: true,
891
+ inheritGlobalContext: true,
892
+ inheritSkills: true,
893
+ });
894
+ assert.ok(rewritten.includes("Global rules"));
895
+ });
896
+
897
+ it("removes global context files while keeping repository context via rewriteSubagentPrompt", () => {
898
+ const globalDir = getAgentDir();
899
+ const prompt = [
900
+ "You are a subagent.",
901
+ "\n\n<project_context>\n\nProject-specific instructions and guidelines:\n\n",
902
+ `<project_instructions path="${globalDir}/AGENTS.md">\nGlobal rules\n</project_instructions>\n\n`,
903
+ "<project_instructions path=\"/repo/AGENTS.md\">\nRepo rules\n</project_instructions>\n\n",
904
+ "</project_context>\n\n",
905
+ "Current working directory: /repo",
906
+ ].join("");
907
+ const rewritten = rewriteSubagentPrompt(prompt, {
908
+ inheritProjectContext: true,
909
+ inheritGlobalContext: false,
910
+ inheritSkills: true,
911
+ });
912
+ assert.ok(!rewritten.includes("Global rules"));
913
+ assert.ok(rewritten.includes("Repo rules"));
914
+ });
915
+
788
916
  it("strips only the inherited skills block", () => {
789
917
  const rewritten = stripInheritedSkills(BASE_PROMPT);
790
918
  assert.ok(rewritten.includes("# Project Context"));
@@ -795,6 +923,7 @@ describe("subagent prompt runtime", () => {
795
923
  it("can strip both inherited sections together", () => {
796
924
  const rewritten = rewriteSubagentPrompt(BASE_PROMPT, {
797
925
  inheritProjectContext: false,
926
+ inheritGlobalContext: false,
798
927
  inheritSkills: false,
799
928
  });
800
929
  assert.ok(!rewritten.includes("# Project Context"));
@@ -805,6 +934,7 @@ describe("subagent prompt runtime", () => {
805
934
  it("injects a child-only boundary that forbids proposing or running subagents", () => {
806
935
  const rewritten = rewriteSubagentPrompt(BASE_PROMPT, {
807
936
  inheritProjectContext: true,
937
+ inheritGlobalContext: true,
808
938
  inheritSkills: true,
809
939
  });
810
940
 
@@ -813,14 +943,15 @@ describe("subagent prompt runtime", () => {
813
943
  assert.ok(rewritten.includes("If you need to edit files, use the available editing tools."));
814
944
  assert.ok(!rewritten.includes("call the actual edit/write tools"));
815
945
  assert.ok(rewritten.includes("Do not print tool-call syntax, patches, or pseudo-tool calls as text."));
816
- assert.equal(rewriteSubagentPrompt(rewritten, { inheritProjectContext: true, inheritSkills: true }).indexOf(CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS), 0);
817
- assert.equal(rewriteSubagentPrompt(rewritten, { inheritProjectContext: true, inheritSkills: true }).lastIndexOf(CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS), 0);
946
+ assert.equal(rewriteSubagentPrompt(rewritten, { inheritProjectContext: true, inheritGlobalContext: true, inheritSkills: true }).indexOf(CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS), 0);
947
+ assert.equal(rewriteSubagentPrompt(rewritten, { inheritProjectContext: true, inheritGlobalContext: true, inheritSkills: true }).lastIndexOf(CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS), 0);
818
948
  });
819
949
 
820
950
  it("replaces inherited child boundaries with the fanout boundary when authorized", () => {
821
951
  const strictPrompt = `${CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS}\n\n${BASE_PROMPT}`;
822
952
  const rewritten = rewriteSubagentPrompt(strictPrompt, {
823
953
  inheritProjectContext: true,
954
+ inheritGlobalContext: true,
824
955
  inheritSkills: true,
825
956
  fanoutChild: true,
826
957
  });
@@ -837,6 +968,7 @@ describe("subagent prompt runtime", () => {
837
968
  const fanoutPrompt = `${CHILD_FANOUT_BOUNDARY_INSTRUCTIONS}\n\n${BASE_PROMPT}`;
838
969
  const rewritten = rewriteSubagentPrompt(fanoutPrompt, {
839
970
  inheritProjectContext: true,
971
+ inheritGlobalContext: true,
840
972
  inheritSkills: true,
841
973
  });
842
974
 
@@ -848,6 +980,7 @@ describe("subagent prompt runtime", () => {
848
980
  it("keeps explicitly injected skill content when inherited skills are stripped", () => {
849
981
  const rewritten = rewriteSubagentPrompt(PROMPT_WITH_EXPLICIT_SKILL, {
850
982
  inheritProjectContext: false,
983
+ inheritGlobalContext: false,
851
984
  inheritSkills: false,
852
985
  });
853
986
  assert.ok(rewritten.includes("<skill name=\"explicit\">"));
@@ -865,6 +998,7 @@ describe("subagent prompt runtime", () => {
865
998
  ].join("");
866
999
  const rewritten = rewriteSubagentPrompt(prompt, {
867
1000
  inheritProjectContext: false,
1001
+ inheritGlobalContext: false,
868
1002
  inheritSkills: false,
869
1003
  });
870
1004
 
@@ -877,6 +1011,7 @@ describe("subagent prompt runtime", () => {
877
1011
  it("strips the subagent orchestration skill even when inherited skills remain", () => {
878
1012
  const rewritten = rewriteSubagentPrompt(BASE_PROMPT, {
879
1013
  inheritProjectContext: true,
1014
+ inheritGlobalContext: true,
880
1015
  inheritSkills: true,
881
1016
  });
882
1017
 
@@ -1336,6 +1471,26 @@ describe("subagent prompt runtime", () => {
1336
1471
  assert.equal(contextHandler?.({ messages }, { model: { api: "openai-responses" } }), undefined);
1337
1472
  });
1338
1473
 
1474
+ it("preserves composite tool ids for cursor-native children", () => {
1475
+ let contextHandler: ((event: { messages: unknown[] }, ctx: { model?: { api: string } }) => { messages: unknown[] } | undefined) | undefined;
1476
+ registerSubagentPromptRuntime({
1477
+ on(event: string, handler: (payload: { messages: unknown[] }, ctx: { model?: { api: string } }) => { messages: unknown[] } | undefined) {
1478
+ if (event === "context") contextHandler = handler;
1479
+ },
1480
+ } as { on(event: string, handler: (payload: { messages: unknown[] }, ctx: { model?: { api: string } }) => { messages: unknown[] } | undefined): void });
1481
+
1482
+ const toolCallId = "call_7XJjvAJfk07117JO8LgBCZjY\nfc_0e92b09b28010bac016a756e9e79cc8197b01825a5dc3d9eaa";
1483
+ const messages = [
1484
+ { role: "user", content: "Task" },
1485
+ { role: "assistant", content: [{ type: "toolCall", id: toolCallId, name: "read", input: { path: "README.md" } }] },
1486
+ { role: "toolResult", toolName: "read", toolCallId, content: "file" },
1487
+ ];
1488
+
1489
+ assert.equal(contextHandler?.({ messages }, { model: { api: "cursor-native" } }), undefined);
1490
+ assert.equal((messages[1] as { content: Array<{ id?: unknown }> }).content[0]?.id, toolCallId);
1491
+ assert.equal((messages[2] as { toolCallId?: unknown }).toolCallId, toolCallId);
1492
+ });
1493
+
1339
1494
  it("does not rewrite child context when no parent-only artifacts are present", () => {
1340
1495
  let contextHandler: ((event: { messages: unknown[] }, ctx: { model?: { api: string } }) => { messages: unknown[] } | undefined) | undefined;
1341
1496
  registerSubagentPromptRuntime({
@@ -78,7 +78,7 @@ describe("subagent startup retry", () => {
78
78
  });
79
79
 
80
80
  assert.match(formatted ?? "", /loaded conflicting ambient Pi extensions/);
81
- assert.match(formatted ?? "", /\.pi\/settings\.json/);
81
+ assert.match(formatted ?? "", /\.selesai[\\/]settings\.json/);
82
82
  assert.match(formatted ?? "", /\{"subagents":\{"agentOverrides":\{"reviewer":\{"extensions":\[\]\}\}\}\}/);
83
83
  assert.equal(formatSubagentExtensionConflictError(conflict, { agent: "reviewer", ambientExtensionsEnabled: false }), conflict);
84
84
  assert.equal(formatSubagentExtensionConflictError("authentication failed", { agent: "reviewer", ambientExtensionsEnabled: true }), "authentication failed");
@@ -6,7 +6,7 @@ import { describe, it } from "node:test";
6
6
  import { updateActiveRunIndex } from "../../src/runs/background/active-run-index.ts";
7
7
  import { writeAsyncResultFile } from "../../src/runs/background/result-files.ts";
8
8
  import { createRunFanoutBudget } from "../../src/runs/shared/run-fanout-budget.ts";
9
- import { WAIT_TOOL_ENABLED_ENV, resolveWaitToolConfig, waitForSubagents, type SubagentWaitDeps } from "../../src/runs/background/subagent-wait.ts";
9
+ import { WAIT_TOOL_DEFAULT_TIMEOUT_MS_ENV, WAIT_TOOL_ENABLED_ENV, resolveWaitToolConfig, waitForSubagents, type SubagentWaitDeps } from "../../src/runs/background/subagent-wait.ts";
10
10
  import { recordWaitCompletion } from "../../src/runs/background/wait-completions.ts";
11
11
  import type { AsyncStatus, SubagentState } from "../../src/shared/types.ts";
12
12
 
@@ -41,6 +41,7 @@ function writeRecoveryDescriptor(asyncRoot: string, runId: string, agent: string
41
41
  cwd,
42
42
  systemPromptMode: "append",
43
43
  outputMode: "inline",
44
+ inheritGlobalContext: false,
44
45
  inheritProjectContext: false,
45
46
  inheritSkills: false,
46
47
  maxSubagentDepth: 0,
@@ -88,10 +89,15 @@ describe("subagent_wait tool", () => {
88
89
  assert.deepEqual(resolveWaitToolConfig(undefined, {}), { enabled: true });
89
90
  assert.deepEqual(resolveWaitToolConfig(false, {}), { enabled: false });
90
91
  assert.deepEqual(resolveWaitToolConfig({ enabled: false }, {}), { enabled: false });
92
+ assert.deepEqual(resolveWaitToolConfig({ defaultTimeoutMs: 120_000 }, {}), { enabled: true, defaultTimeoutMs: 120_000 });
93
+ assert.deepEqual(resolveWaitToolConfig({ defaultTimeoutMs: 120_000 }, { [WAIT_TOOL_DEFAULT_TIMEOUT_MS_ENV]: "3000" }), { enabled: true, defaultTimeoutMs: 3_000 });
91
94
  assert.deepEqual(resolveWaitToolConfig({ enabled: false }, { [WAIT_TOOL_ENABLED_ENV]: "true" }), { enabled: true });
92
95
  assert.deepEqual(resolveWaitToolConfig(true, { [WAIT_TOOL_ENABLED_ENV]: "off" }), { enabled: false });
93
96
  assert.throws(() => resolveWaitToolConfig("false" as never, {}), /config\.waitTool/);
94
97
  assert.throws(() => resolveWaitToolConfig({ enabled: "false" } as never, {}), /config\.waitTool\.enabled/);
98
+ assert.throws(() => resolveWaitToolConfig({ defaultTimeoutMs: 0 }, {}), /config\.waitTool\.defaultTimeoutMs/);
99
+ assert.throws(() => resolveWaitToolConfig({ defaultTimeoutMs: 1.5 }, {}), /config\.waitTool\.defaultTimeoutMs/);
100
+ assert.throws(() => resolveWaitToolConfig(undefined, { [WAIT_TOOL_DEFAULT_TIMEOUT_MS_ENV]: "0" }), /SELESAI_SUBAGENT_WAIT_TOOL_DEFAULT_TIMEOUT_MS/);
95
101
  assert.throws(() => resolveWaitToolConfig(undefined, { [WAIT_TOOL_ENABLED_ENV]: "maybe" }), /SELESAI_SUBAGENT_WAIT_TOOL_ENABLED/);
96
102
  });
97
103
 
@@ -335,6 +341,7 @@ describe("subagent_wait tool", () => {
335
341
  success: true,
336
342
  outputState: "present",
337
343
  output: "full output text stays out of details",
344
+ usage: { input: 100, output: 50, cacheRead: 25, cacheWrite: 5, cost: 0.001, turns: 1 },
338
345
  artifactPaths: {
339
346
  outputPath: "/tmp/a1b2c3d4_reviewer_0_output.md",
340
347
  metadataPath: "/tmp/a1b2c3d4_reviewer_0_meta.json",
@@ -350,6 +357,7 @@ describe("subagent_wait tool", () => {
350
357
  assert.equal(completions![0]!.runId, "run-a");
351
358
  assert.equal(completions![0]!.mode, "workflow");
352
359
  assert.equal(completions![0]!.success, true);
360
+ assert.deepEqual(result.usage, { input: 100, output: 50, cacheRead: 25, cacheWrite: 5, totalTokens: 180, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0.001 } });
353
361
  const child = completions![0]!.results?.[0];
354
362
  assert.equal(child?.agent, "reviewer");
355
363
  assert.equal(child?.runId, "a1b2c3d4");
@@ -1145,11 +1153,62 @@ describe("subagent_wait tool", () => {
1145
1153
  clock += ms + 10_000;
1146
1154
  };
1147
1155
 
1148
- const result = await waitForSubagents({ timeoutMs: 5_000 }, undefined, baseDeps(root, state, { now, sleep }));
1149
- assert.equal(result.isError, true);
1156
+ const result = await waitForSubagents({ timeoutMs: 5_000 }, undefined, baseDeps(root, state, { now, sleep, defaultTimeoutMs: 1_000 }));
1157
+ assert.equal(result.isError, undefined);
1150
1158
  const text = textOf(result);
1151
- assert.match(text, /timed out/i);
1159
+ assert.match(text, /window elapsed after 5\.0s/i, "explicit timeoutMs must override the configured default");
1152
1160
  assert.match(text, /run-stuck \(running\)/);
1161
+ assert.deepEqual(result.details.wait, {
1162
+ reason: "window_elapsed",
1163
+ timedOut: true,
1164
+ activeRunIds: ["run-stuck"],
1165
+ activeProviderItems: [],
1166
+ });
1167
+ } finally {
1168
+ fs.rmSync(root, { recursive: true, force: true });
1169
+ }
1170
+ });
1171
+
1172
+ it("uses the configured wait window when timeoutMs is omitted", async () => {
1173
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), "pi-wait-config-timeout-"));
1174
+ try {
1175
+ const asyncRoot = path.join(root, "runs");
1176
+ const state = makeState("sess-1");
1177
+ writeStatus(asyncRoot, "run-configured", "running", { sessionId: "sess-1", pid: 999999 });
1178
+ let clock = 0;
1179
+ const result = await waitForSubagents({}, undefined, baseDeps(root, state, {
1180
+ now: () => clock,
1181
+ sleep: async (ms) => { clock += ms + 10_000; },
1182
+ defaultTimeoutMs: 2_000,
1183
+ }));
1184
+
1185
+ assert.equal(result.isError, undefined);
1186
+ assert.match(textOf(result), /window elapsed after 2\.0s/i);
1187
+ assert.equal(result.details.wait?.reason, "window_elapsed");
1188
+ } finally {
1189
+ fs.rmSync(root, { recursive: true, force: true });
1190
+ }
1191
+ });
1192
+
1193
+ it("reports still-active provider identities when the wait window elapses", async () => {
1194
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), "pi-wait-provider-timeout-"));
1195
+ try {
1196
+ const state = makeState("sess-1");
1197
+ let clock = 0;
1198
+ const result = await waitForSubagents({ timeoutMs: 1_000 }, undefined, baseDeps(root, state, {
1199
+ now: () => clock,
1200
+ sleep: async (ms) => { clock += ms + 10_000; },
1201
+ backgroundWork: {
1202
+ snapshot: () => ({
1203
+ providers: ["herdr"],
1204
+ items: [{ provider: "herdr", id: "pane-1", sessionId: "sess-1" }],
1205
+ }),
1206
+ wakeChannels: () => [],
1207
+ },
1208
+ }));
1209
+
1210
+ assert.equal(result.isError, undefined);
1211
+ assert.deepEqual(result.details.wait?.activeProviderItems, [{ provider: "herdr", id: "pane-1" }]);
1153
1212
  } finally {
1154
1213
  fs.rmSync(root, { recursive: true, force: true });
1155
1214
  }
@@ -9,11 +9,8 @@ import {
9
9
  buildSubagentToolDescription,
10
10
  buildSubagentToolPromptMetadata,
11
11
  COMPACT_SUBAGENT_TOOL_DESCRIPTION,
12
- DEFAULT_SUBAGENT_TOOL_DESCRIPTION,
13
12
  FULL_SUBAGENT_TOOL_DESCRIPTION,
14
13
  SUBAGENT_SAFETY_GUIDANCE,
15
- SUBAGENT_TOOL_PROMPT_GUIDELINES,
16
- SUBAGENT_TOOL_PROMPT_SNIPPET,
17
14
  } from "../../src/extension/tool-description.ts";
18
15
  import { SUBAGENT_CHILD_ENV, SUBAGENT_FANOUT_CHILD_ENV } from "../../src/runs/shared/pi-args.ts";
19
16
 
@@ -32,31 +29,26 @@ function parentToolEnv(agentDir?: string): NodeJS.ProcessEnv {
32
29
  }
33
30
 
34
31
  describe("registered subagent tool description", () => {
35
- it("uses split metadata by default", () => {
32
+ it("uses the full description by default", () => {
36
33
  const description = buildSubagentToolDescription();
37
34
  const metadata = buildSubagentToolPromptMetadata();
38
- assert.equal(description, DEFAULT_SUBAGENT_TOOL_DESCRIPTION);
39
- assert.equal(Buffer.byteLength(description), 712);
40
- assert.equal(metadata.promptSnippet, SUBAGENT_TOOL_PROMPT_SNIPPET);
41
- assert.equal(Buffer.byteLength(metadata.promptSnippet!), 62);
42
- assert.deepEqual(metadata.promptGuidelines, SUBAGENT_TOOL_PROMPT_GUIDELINES);
43
- assert.equal(Buffer.byteLength(metadata.promptGuidelines!.join("\n")), 1249);
44
- assert.match(metadata.promptGuidelines!.join("\n"), /Use subagent only when delegation is needed/i);
45
- assert.match(metadata.promptGuidelines!.join("\n"), /action: \"list\".*executable, non-disabled/i);
46
- assert.match(metadata.promptGuidelines!.join("\n"), /workflowScript for multi-step or parallel work/i);
47
- assert.match(metadata.promptGuidelines!.join("\n"), /workflowScript means exactly one top-level subagent tool call with async:true/i);
48
- assert.match(metadata.promptGuidelines!.join("\n"), /Inside it, use runs\.run\/runs\.all to launch children/i);
49
- assert.match(metadata.promptGuidelines!.join("\n"), /do not make another top-level subagent call for those children/i);
50
- assert.match(metadata.promptGuidelines!.join("\n"), /await runs\.all.*do not read \.output from unawaited runs\.run launches/i);
35
+ assert.equal(description, FULL_SUBAGENT_TOOL_DESCRIPTION);
36
+ assert.equal(metadata.promptSnippet, undefined);
37
+ assert.equal(metadata.promptGuidelines, undefined);
38
+ assert.match(description, /^Run one child with \{ agent, task\? \}; use \{ workflowScript \} for inline orchestration/i);
39
+ assert.match(description, /SAFETY-CRITICAL SUBAGENT GUIDANCE/);
51
40
  });
52
41
 
53
42
  it("keeps the full description when configured", () => {
54
43
  const description = buildSubagentToolDescription({ toolDescriptionMode: "full" });
55
44
  assert.equal(buildSubagentToolPromptMetadata({ toolDescriptionMode: "full" }).promptSnippet, undefined);
56
- assert.match(description, /^Run one child with \{ agent, task\? \}; use \{ workflowScript \} for orchestration/i);
45
+ assert.match(description, /^Run one child with \{ agent, task\? \}; use \{ workflowScript \} for inline orchestration or \{ workflowScriptPath \}/i);
46
+ assert.match(description, /workflowScriptPath:"workflows\/review\.js".*host reads the file.*sandbox/i);
57
47
  assert.match(description, /SINGLE CHILD:.*starts exactly one direct child/i);
58
- assert.match(description, /Do not combine agent\/task with action or workflowScript/i);
48
+ assert.match(description, /lane\.status.*lane\.recordMerge.*lane\.recordSupersession/i);
49
+ assert.match(description, /Do not combine agent\/task with action, workflowScript, or workflowScriptPath/i);
59
50
  assert.match(description, /runs\.run for one child and await runs\.all.*ordinary parallel children/i);
51
+ assert.match(description, /runs\.lanes\(\[\{key,stages:.*later stages sequence per lane/i);
60
52
  assert.match(description, /do not read \.output from unawaited runs\.run launches/i);
61
53
  assert.match(description, /runs\.steer\(key, message, \{mode\?, index\?, ackTimeoutMs\?\}\).*prior keyed child.*without exposing its run id/i);
62
54
  assert.match(description, /receipts are queued, delivered, missed, or failed/i);
@@ -74,19 +66,26 @@ describe("registered subagent tool description", () => {
74
66
  assert.match(description, /continue independent work only until its next dependency barrier; consume the result before work that depends on it/i);
75
67
  assert.match(description, /children\.list.*resumable\/not-resumable reasons/i);
76
68
  assert.match(description, /Resume only rows reported resumable/i);
69
+ assert.match(description, /Each workflow key identifies one result lane.*new stable workflow key.*retained resume pass/i);
70
+ assert.match(description, /output.*not an output declaration.*outputReference.*outputPathMapping.*artifactPaths/i);
77
71
  assert.match(description, /implementation challenge.*\{action:\"resume\", id:\"run-id\", message:\"\.\.\.\"\}/i);
78
72
  assert.match(description, /Resume keeps the stored agent\/model\/tool contract/i);
79
73
  assert.match(description, /Oracle\/advisor consultations should use supervisor dialogue for material unknowns when available/i);
80
74
  assert.match(description, /same-role fallback challenge and label it as fallback/i);
81
75
  assert.match(description, /status\.json/);
76
+ assert.match(description, /suffix on the model string.*off\/minimal\/low\/medium\/high\/xhigh\/max/i);
77
+ assert.match(description, /suffix wins over the agent's thinking default/i);
78
+ assert.match(description, /watchdog\.configure' and is ignored on dispatch/i);
82
79
  });
83
80
 
84
81
  it("offers a compact mode that keeps the two-tier contract and safety guidance", () => {
85
82
  const description = buildSubagentToolDescription({ toolDescriptionMode: "compact" });
86
83
  assert.equal(description, COMPACT_SUBAGENT_TOOL_DESCRIPTION);
87
- assert.match(description, /^Run one child with \{ agent, task\? \}; use \{ workflowScript \} for orchestration/i);
84
+ assert.match(description, /^Run one child with \{ agent, task\? \}; use \{ workflowScript \} for inline orchestration or \{ workflowScriptPath \}/i);
85
+ assert.match(description, /workflowScriptPath:"workflows\/review\.js".*request cwd.*sandbox/i);
88
86
  assert.match(description, /SINGLE .*starts exactly one direct child/i);
89
87
  assert.match(description, /runs\.run for one child and await runs\.all.*ordinary parallel work/i);
88
+ assert.match(description, /runs\.lanes\(\[\{key,stages:.*later stages sequence per lane/i);
90
89
  assert.match(description, /do not read \.output from unawaited runs\.run launches/i);
91
90
  assert.match(description, /runs\.steer\(key,message,options\?\).*prior keyed child/i);
92
91
  assert.match(description, /never accepts a raw run id/i);
@@ -95,12 +94,17 @@ describe("registered subagent tool description", () => {
95
94
  assert.match(description, /subagent_wait/i);
96
95
  assert.match(description, /continue independent work only until its next dependency barrier; consume the result before work that depends on it/i);
97
96
  assert.match(description, /children\.list.*resume only rows reported resumable/i);
97
+ assert.match(description, /Each workflow key identifies one result lane.*new stable workflow key.*retained resume pass/i);
98
+ assert.match(description, /output.*not an output declaration.*outputReference.*outputPathMapping.*artifactPaths/i);
98
99
  assert.match(description, /\{action:\"resume\",id:\"run-id\",message:\"\.\.\.\"\} for a simple follow-up or challenge/i);
99
100
  assert.match(description, /resume keeps the stored agent\/model\/tool contract/i);
100
101
  assert.match(description, /Oracle\/advisor consultations use available supervisor dialogue/i);
101
102
  assert.match(description, /same-role fallback challenge and label it as fallback/i);
102
103
  assert.match(description, /exactly one non-empty title or summary/i);
103
104
  assert.match(description, /goal may only be true and requires budget:\{tokens\}/i);
105
+ assert.match(description, /Per-run thinking is a suffix on the model string.*off\/minimal\/low\/medium\/high\/xhigh\/max/i);
106
+ assert.match(description, /suffix wins over the agent's thinking default/i);
107
+ assert.match(description, /watchdog\.configure' and is ignored on dispatch/i);
104
108
  assert.ok(description.length < FULL_SUBAGENT_TOOL_DESCRIPTION.length);
105
109
  });
106
110
 
@@ -258,9 +262,9 @@ describe("registered subagent tool description", () => {
258
262
  const defaultAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-default-"));
259
263
  writeExtensionConfig(defaultAgentDir, {});
260
264
  const defaultTool = readRegisteredTool(defaultAgentDir);
261
- assert.equal(defaultTool.description, DEFAULT_SUBAGENT_TOOL_DESCRIPTION);
262
- assert.equal(defaultTool.promptSnippet, SUBAGENT_TOOL_PROMPT_SNIPPET);
263
- assert.deepEqual(defaultTool.promptGuidelines, SUBAGENT_TOOL_PROMPT_GUIDELINES);
265
+ assert.equal(defaultTool.description, FULL_SUBAGENT_TOOL_DESCRIPTION);
266
+ assert.equal(defaultTool.promptSnippet, undefined);
267
+ assert.equal(defaultTool.promptGuidelines, undefined);
264
268
 
265
269
  const fullAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-full-"));
266
270
  writeExtensionConfig(fullAgentDir, { toolDescriptionMode: "full" });
@@ -0,0 +1,44 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import { toWaitCompletion } from "../../src/runs/background/wait-completions.ts";
4
+
5
+ describe("workflow wait completion projection", () => {
6
+ it("retains the bounded workflow-child summary and excludes result output", () => {
7
+ const completion = toWaitCompletion({
8
+ agent: "workflow",
9
+ mode: "workflow",
10
+ state: "complete",
11
+ success: true,
12
+ workflowChildren: {
13
+ version: 1,
14
+ parentToolCallId: "tool-1",
15
+ workflowRunId: "workflow-1",
16
+ inventoryComplete: true,
17
+ workflowState: "completed",
18
+ children: [{ childId: "review", runId: "run-1", agent: "reviewer", model: "openai-codex/gpt", thinking: "high", state: "completed" }],
19
+ },
20
+ results: [{
21
+ agent: "reviewer",
22
+ runId: "run-1",
23
+ success: true,
24
+ sessionFile: "/sessions/run-1.jsonl",
25
+ usage: { input: 10, output: 2, cacheRead: 30, cacheWrite: 0, cost: 0.04, turns: 1 },
26
+ output: "must not be copied",
27
+ task: "must not be copied",
28
+ }],
29
+ }, "workflow-1");
30
+
31
+ assert.equal(completion.workflowChildren?.children[0]?.childId, "review");
32
+ assert.deepEqual(completion.results?.[0]?.usage, { input: 10, output: 2, cacheRead: 30, cacheWrite: 0, cost: 0.04, turns: 1 });
33
+ assert.equal(completion.results?.[0]?.sessionFile, "/sessions/run-1.jsonl");
34
+ assert.doesNotMatch(JSON.stringify(completion), /must not be copied/);
35
+ });
36
+
37
+ it("rejects unbounded or unknown summary fields at the replay boundary", () => {
38
+ assert.throws(() => toWaitCompletion({ workflowChildren: { version: 1, parentToolCallId: "tool", workflowRunId: "run", inventoryComplete: true, workflowState: "completed", children: [], output: "secret" } }, "run"), /unsupported fields/);
39
+ });
40
+
41
+ it("rejects a summary bound to another completion", () => {
42
+ assert.throws(() => toWaitCompletion({ workflowChildren: { version: 1, parentToolCallId: "tool", workflowRunId: "other", inventoryComplete: true, workflowState: "completed", children: [] } }, "run"), /does not match its completion run id/);
43
+ });
44
+ });
@@ -35,6 +35,7 @@ function writeRecoveryDescriptor(asyncRoot: string, runId: string, agent: string
35
35
  cwd,
36
36
  systemPromptMode: "append",
37
37
  outputMode: "inline",
38
+ inheritGlobalContext: false,
38
39
  inheritProjectContext: false,
39
40
  inheritSkills: false,
40
41
  maxSubagentDepth: 0,