@selesai/code 0.13.15 → 0.13.18

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 (473) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +2 -14
  3. package/dist/bun/cli.d.ts +3 -1
  4. package/dist/bun/cli.js +3 -9
  5. package/dist/bun/{register-bedrock.js → runtime-setup.js} +5 -0
  6. package/dist/bun/sandbox-env-setup.d.ts +1 -0
  7. package/dist/bun/sandbox-env-setup.js +3 -0
  8. package/dist/cli/auth-command.d.ts +23 -0
  9. package/dist/cli/auth-command.js +102 -0
  10. package/dist/cli/config-selector.js +2 -1
  11. package/dist/cli/setup.d.ts +1 -0
  12. package/dist/cli/setup.js +11 -0
  13. package/dist/cli.js +2 -14
  14. package/dist/config.d.ts +3 -2
  15. package/dist/config.js +9 -4
  16. package/dist/core/agent-session-runtime.js +15 -7
  17. package/dist/core/agent-session.d.ts +2 -6
  18. package/dist/core/agent-session.js +15 -4
  19. package/dist/core/compaction/branch-summarization.d.ts +1 -1
  20. package/dist/core/compaction/branch-summarization.js +2 -1
  21. package/dist/core/extensions/loader.js +3 -0
  22. package/dist/core/extensions/types.d.ts +16 -2
  23. package/dist/core/http-dispatcher.js +2 -0
  24. package/dist/core/keybindings.d.ts +5 -0
  25. package/dist/core/keybindings.js +4 -0
  26. package/dist/core/messages.d.ts +1 -1
  27. package/dist/core/model-config.d.ts +15 -0
  28. package/dist/core/model-config.js +3 -0
  29. package/dist/core/model-runtime.d.ts +1 -0
  30. package/dist/core/model-runtime.js +5 -2
  31. package/dist/core/provider-composer.js +8 -2
  32. package/dist/core/session-export.d.ts +3 -0
  33. package/dist/core/session-export.js +31 -0
  34. package/dist/core/session-manager.d.ts +3 -2
  35. package/dist/core/session-manager.js +40 -13
  36. package/dist/core/skills.d.ts +1 -1
  37. package/dist/core/skills.js +4 -2
  38. package/dist/core/system-prompt.js +10 -10
  39. package/dist/core/tools/bash.js +3 -117
  40. package/dist/core/tools/edit.d.ts +1 -12
  41. package/dist/core/tools/edit.js +5 -163
  42. package/dist/core/tools/find.js +4 -55
  43. package/dist/core/tools/grep.js +4 -60
  44. package/dist/core/tools/ls.js +4 -49
  45. package/dist/core/tools/read.d.ts +4 -0
  46. package/dist/core/tools/read.js +10 -122
  47. package/dist/core/tools/renderers/bash.d.ts +11 -0
  48. package/dist/core/tools/renderers/bash.js +129 -0
  49. package/dist/core/tools/renderers/edit.d.ts +22 -0
  50. package/dist/core/tools/renderers/edit.js +166 -0
  51. package/dist/core/tools/renderers/find.d.ts +9 -0
  52. package/dist/core/tools/renderers/find.js +63 -0
  53. package/dist/core/tools/renderers/grep.d.ts +9 -0
  54. package/dist/core/tools/renderers/grep.js +68 -0
  55. package/dist/core/tools/renderers/index.d.ts +27 -0
  56. package/dist/core/tools/renderers/index.js +46 -0
  57. package/dist/core/tools/renderers/ls.d.ts +9 -0
  58. package/dist/core/tools/renderers/ls.js +57 -0
  59. package/dist/core/tools/renderers/read.d.ts +10 -0
  60. package/dist/core/tools/renderers/read.js +128 -0
  61. package/dist/core/tools/renderers/write.d.ts +9 -0
  62. package/dist/core/tools/renderers/write.js +152 -0
  63. package/dist/core/tools/write.js +5 -146
  64. package/dist/extensions/capability-gateway/index.ts +12 -1
  65. package/dist/extensions/capability-gateway/integration.test.ts +23 -0
  66. package/dist/extensions/pi-hermes-memory/CHANGELOG.md +18 -0
  67. package/dist/extensions/pi-hermes-memory/README.md +16 -12
  68. package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +1 -1
  69. package/dist/extensions/pi-hermes-memory/package-lock.json +587 -62
  70. package/dist/extensions/pi-hermes-memory/package.json +4 -4
  71. package/dist/extensions/pi-hermes-memory/src/config.ts +32 -0
  72. package/dist/extensions/pi-hermes-memory/src/constants.ts +12 -2
  73. package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +109 -51
  74. package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +9 -3
  75. package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +257 -98
  76. package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +9 -2
  77. package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +5 -0
  78. package/dist/extensions/pi-hermes-memory/src/index.ts +22 -2
  79. package/dist/extensions/pi-hermes-memory/src/paths.ts +1 -1
  80. package/dist/extensions/pi-hermes-memory/src/store/db.ts +6 -0
  81. package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +58 -1
  82. package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +60 -8
  83. package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +169 -7
  84. package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +7 -21
  85. package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +134 -15
  86. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +4 -2
  87. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +24 -9
  88. package/dist/extensions/pi-hermes-memory/src/types.ts +11 -0
  89. package/dist/extensions/pi-hermes-memory/tests/config.test.ts +42 -0
  90. package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +159 -3
  91. package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +452 -0
  92. package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +39 -0
  93. package/dist/extensions/pi-hermes-memory/tests/integration/corruption-recovery-integration.test.ts +91 -0
  94. package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +29 -0
  95. package/dist/extensions/pi-hermes-memory/tests/store/fts-query.test.ts +116 -0
  96. package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +163 -0
  97. package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +233 -0
  98. package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +12 -0
  99. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +175 -0
  100. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +2 -2
  101. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +22 -0
  102. package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +37 -1
  103. package/dist/extensions/pi-intercom/CHANGELOG.md +13 -0
  104. package/dist/extensions/pi-intercom/README.md +16 -2
  105. package/dist/extensions/pi-intercom/broker/spawn.test.ts +19 -2
  106. package/dist/extensions/pi-intercom/broker/spawn.ts +4 -4
  107. package/dist/extensions/pi-intercom/index.ts +1 -1
  108. package/dist/extensions/pi-intercom/intercom.integration.test.ts +121 -2
  109. package/dist/extensions/pi-intercom/package.json +1 -1
  110. package/dist/extensions/pi-intercom/project-agent.test.ts +1 -1
  111. package/dist/extensions/pi-intercom/project-agent.ts +1 -6
  112. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +7 -6
  113. package/dist/extensions/pi-rewind-hook/index.test.ts +7 -0
  114. package/dist/extensions/pi-subagents/.github/workflows/test.yml +36 -4
  115. package/dist/extensions/pi-subagents/CHANGELOG.md +120 -0
  116. package/dist/extensions/pi-subagents/README.md +3 -3
  117. package/dist/extensions/pi-subagents/agents/researcher.md +23 -13
  118. package/dist/extensions/pi-subagents/agents/reviewer.md +1 -1
  119. package/dist/extensions/pi-subagents/agents/scout.md +1 -1
  120. package/dist/extensions/pi-subagents/docs/agents.md +32 -16
  121. package/dist/extensions/pi-subagents/docs/configuration.md +41 -15
  122. package/dist/extensions/pi-subagents/docs/extension-api.md +109 -6
  123. package/dist/extensions/pi-subagents/docs/missions.md +2 -0
  124. package/dist/extensions/pi-subagents/docs/models.md +58 -1
  125. package/dist/extensions/pi-subagents/docs/observability.md +50 -12
  126. package/dist/extensions/pi-subagents/docs/tool-reference.md +17 -10
  127. package/dist/extensions/pi-subagents/docs/watchdog.md +1 -1
  128. package/dist/extensions/pi-subagents/docs/workflows.md +26 -9
  129. package/dist/extensions/pi-subagents/package-lock.json +747 -177
  130. package/dist/extensions/pi-subagents/package.json +6 -4
  131. package/dist/extensions/pi-subagents/runner-server-preload.mjs +13 -0
  132. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +2 -1
  133. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +1 -1
  134. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +21 -4
  135. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -1
  136. package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +2 -0
  137. package/dist/extensions/pi-subagents/src/agents/advertised-agent-prompt.ts +63 -0
  138. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +61 -16
  139. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +2 -0
  140. package/dist/extensions/pi-subagents/src/agents/agents.ts +8 -0
  141. package/dist/extensions/pi-subagents/src/api/capability-ceiling.ts +0 -1
  142. package/dist/extensions/pi-subagents/src/api/{pi-args.ts → child-tool-plan.ts} +1 -1
  143. package/dist/extensions/pi-subagents/src/api/preflight.ts +7 -4
  144. package/dist/extensions/pi-subagents/src/api/shared-types.ts +2 -2
  145. package/dist/extensions/pi-subagents/src/api/workflow-resources.ts +6 -0
  146. package/dist/extensions/pi-subagents/src/extension/config.ts +4 -2
  147. package/dist/extensions/pi-subagents/src/extension/doctor.ts +2 -10
  148. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +9 -11
  149. package/dist/extensions/pi-subagents/src/extension/index.ts +99 -10
  150. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +13 -0
  151. package/dist/extensions/pi-subagents/src/extension/rpc.ts +7 -23
  152. package/dist/extensions/pi-subagents/src/extension/schemas.ts +11 -8
  153. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +25 -7
  154. package/dist/extensions/pi-subagents/src/integrations/pi-web-session-liveness.ts +73 -0
  155. package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +228 -136
  156. package/dist/extensions/pi-subagents/src/intercom/supervisor-ui.ts +244 -0
  157. package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +37 -16
  158. package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +18 -18
  159. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +51 -25
  160. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +46 -3
  161. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +14 -3
  162. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +9 -0
  163. package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +10 -12
  164. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -15
  165. package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +40 -29
  166. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +8 -0
  167. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +79 -247
  168. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +88 -12
  169. package/dist/extensions/pi-subagents/src/runs/background/owned-process-tree.ts +6 -6
  170. package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +24 -24
  171. package/dist/extensions/pi-subagents/src/runs/background/retained-nested-route-tracker.ts +96 -0
  172. package/dist/extensions/pi-subagents/src/runs/background/run-child-session.ts +642 -0
  173. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +75 -6
  174. package/dist/extensions/pi-subagents/src/runs/background/runner-aliases.ts +163 -0
  175. package/dist/extensions/pi-subagents/src/runs/background/runner-child-launch.ts +86 -0
  176. package/dist/extensions/pi-subagents/src/runs/background/runner-child-sessions.ts +31 -0
  177. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +18 -4
  178. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +3 -1
  179. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +597 -1092
  180. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +3 -0
  181. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +4 -0
  182. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +20 -17
  183. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +296 -394
  184. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +4 -0
  185. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +3 -1
  186. package/dist/extensions/pi-subagents/src/runs/foreground/prompt-audit.ts +9 -5
  187. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +630 -283
  188. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +8 -5
  189. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +78 -98
  190. package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +3 -3
  191. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +16 -3
  192. package/dist/extensions/pi-subagents/src/runs/shared/agent-contract.ts +1 -1
  193. package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +47 -47
  194. package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +1 -2
  195. package/dist/extensions/pi-subagents/src/runs/shared/child-hooks.ts +174 -0
  196. package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +14 -3
  197. package/dist/extensions/pi-subagents/src/runs/shared/child-launch.ts +319 -0
  198. package/dist/extensions/pi-subagents/src/runs/shared/child-lifecycle.ts +25 -0
  199. package/dist/extensions/pi-subagents/src/runs/shared/child-runtime-config.ts +126 -0
  200. package/dist/extensions/pi-subagents/src/runs/shared/child-session.ts +373 -0
  201. package/dist/extensions/pi-subagents/src/runs/shared/child-tool-plan.ts +530 -0
  202. package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +2 -2
  203. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +2 -1
  204. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +16 -0
  205. package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +11 -11
  206. package/dist/extensions/pi-subagents/src/runs/shared/llm-intent-arbiter.ts +30 -20
  207. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +5 -4
  208. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +84 -15
  209. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +88 -12
  210. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +37 -53
  211. package/dist/extensions/pi-subagents/src/runs/shared/nested-path.ts +1 -1
  212. package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +18 -7
  213. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +57 -12
  214. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +3 -4
  215. package/dist/extensions/pi-subagents/src/runs/shared/permissions.ts +0 -11
  216. package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +4 -1
  217. package/dist/extensions/pi-subagents/src/runs/shared/readonly-drain-observation.ts +42 -0
  218. package/dist/extensions/pi-subagents/src/runs/shared/readonly-model-continuation.ts +69 -0
  219. package/dist/extensions/pi-subagents/src/runs/shared/readonly-session-evidence.ts +307 -0
  220. package/dist/extensions/pi-subagents/src/runs/shared/run-fanout-budget.ts +8 -21
  221. package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +3 -30
  222. package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +17 -4
  223. package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +2 -0
  224. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +99 -386
  225. package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +18 -62
  226. package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +0 -14
  227. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +31 -9
  228. package/dist/extensions/pi-subagents/src/runs/shared/worktree-setup-command.ts +190 -0
  229. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +506 -226
  230. package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +1 -1
  231. package/dist/extensions/pi-subagents/src/shared/jsonl-writer.ts +11 -0
  232. package/dist/extensions/pi-subagents/src/shared/model-response-aliases.ts +13 -0
  233. package/dist/extensions/pi-subagents/src/shared/thinking-ceiling.ts +0 -6
  234. package/dist/extensions/pi-subagents/src/shared/types.ts +145 -89
  235. package/dist/extensions/pi-subagents/src/shared/utils.ts +13 -6
  236. package/dist/extensions/pi-subagents/src/shared/watch-strategy.ts +2 -0
  237. package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +18 -13
  238. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +0 -6
  239. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +1 -1
  240. package/dist/extensions/pi-subagents/src/tui/fleet.ts +11 -6
  241. package/dist/extensions/pi-subagents/src/tui/render.ts +277 -46
  242. package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +0 -1
  243. package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +12 -12
  244. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +3 -3
  245. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +116 -15
  246. package/dist/extensions/pi-subagents/src/workflows/workflow-checklist.ts +15 -18
  247. package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +57 -8
  248. package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +19 -19
  249. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +3 -3
  250. package/dist/extensions/pi-subagents/src/workflows/workflow-resources.ts +97 -22
  251. package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +3 -0
  252. package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +336 -21
  253. package/dist/extensions/pi-subagents/test/integration/async-execution.part-1.test.ts +1181 -0
  254. package/dist/extensions/pi-subagents/test/integration/async-execution.part-2.test.ts +2240 -0
  255. package/dist/extensions/pi-subagents/test/integration/async-execution.part-3.test.ts +2268 -0
  256. package/dist/extensions/pi-subagents/test/integration/async-execution.part-4.test.ts +1512 -0
  257. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +231 -16
  258. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +4 -18
  259. package/dist/extensions/pi-subagents/test/integration/foreign-workflow-steering.test.ts +95 -0
  260. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +9 -15
  261. package/dist/extensions/pi-subagents/test/integration/in-process-child.test.ts +374 -0
  262. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +20 -10
  263. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +18 -6
  264. package/dist/extensions/pi-subagents/test/integration/recovered-assistant-error.test.ts +151 -0
  265. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +42 -1
  266. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +150 -25
  267. package/dist/extensions/pi-subagents/test/integration/result-publication.test.ts +354 -0
  268. package/dist/extensions/pi-subagents/test/integration/shared-cwd-terminal-evidence.test.ts +117 -0
  269. package/dist/extensions/pi-subagents/test/integration/single-execution.part-1.test.ts +3678 -0
  270. package/dist/extensions/pi-subagents/test/integration/{single-execution.test.ts → single-execution.part-2.test.ts} +500 -4207
  271. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +1 -2
  272. package/dist/extensions/pi-subagents/test/integration/workflow-result-publication.test.ts +127 -0
  273. package/dist/extensions/pi-subagents/test/integration/workflow-steer-inbox.test.ts +365 -0
  274. package/dist/extensions/pi-subagents/test/smoke/pi085-child.ts +31 -0
  275. package/dist/extensions/pi-subagents/test/smoke/pi085-clean-install.mjs +74 -0
  276. package/dist/extensions/pi-subagents/test/smoke/pi085-extension.ts +16 -0
  277. package/dist/extensions/pi-subagents/test/support/async-execution-fixture.ts +699 -0
  278. package/dist/extensions/pi-subagents/test/support/fake-child-session.ts +418 -0
  279. package/dist/extensions/pi-subagents/test/support/foreign-workflow-steer-host.mjs +13 -0
  280. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +30 -76
  281. package/dist/extensions/pi-subagents/test/support/notify-diagnostics-fixture.ts +84 -0
  282. package/dist/extensions/pi-subagents/test/support/result-publication-capacity-preload.mjs +70 -0
  283. package/dist/extensions/pi-subagents/test/support/runner-child-session-factory.ts +17 -0
  284. package/dist/extensions/pi-subagents/test/support/single-execution-fixture.ts +390 -0
  285. package/dist/extensions/pi-subagents/test/unit/acceptance-compaction.test.ts +120 -0
  286. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +24 -3
  287. package/dist/extensions/pi-subagents/test/unit/advertised-agent-prompt.test.ts +87 -0
  288. package/dist/extensions/pi-subagents/test/unit/advertised-agent-refresh.test.ts +163 -0
  289. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +70 -31
  290. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +78 -3
  291. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +2 -8
  292. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +1 -1
  293. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +73 -66
  294. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +51 -1
  295. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +49 -1
  296. package/dist/extensions/pi-subagents/test/unit/async-spawn-preload.test.ts +103 -0
  297. package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +3 -3
  298. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +9 -8
  299. package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +10 -7
  300. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +48 -6
  301. package/dist/extensions/pi-subagents/test/unit/child-runtime-config.test.ts +90 -0
  302. package/dist/extensions/pi-subagents/test/unit/{pi-args-permission-system.test.ts → child-tool-plan-permission-system.test.ts} +48 -86
  303. package/dist/extensions/pi-subagents/test/unit/child-tool-plan.test.ts +33 -0
  304. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +18 -18
  305. package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +9 -9
  306. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +8 -7
  307. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +225 -65
  308. package/dist/extensions/pi-subagents/test/unit/extension-bindings.test.ts +17 -22
  309. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +11 -1
  310. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +47 -3
  311. package/dist/extensions/pi-subagents/test/unit/foreign-workflow-steering.test.ts +74 -0
  312. package/dist/extensions/pi-subagents/test/unit/fork-cache-key.test.ts +23 -29
  313. package/dist/extensions/pi-subagents/test/unit/host-peer-runtime-imports.test.ts +96 -4
  314. package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +4 -4
  315. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +116 -55
  316. package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +58 -1
  317. package/dist/extensions/pi-subagents/test/unit/llm-intent-arbiter.test.ts +104 -3
  318. package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +10 -1
  319. package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +31 -1
  320. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +102 -51
  321. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +196 -6
  322. package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +181 -38
  323. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +62 -70
  324. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +58 -53
  325. package/dist/extensions/pi-subagents/test/unit/notify-diagnostics.test.ts +42 -0
  326. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +84 -0
  327. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +13 -5
  328. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +21 -5
  329. package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +5 -4
  330. package/dist/extensions/pi-subagents/test/unit/permissions.test.ts +2 -6
  331. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +28 -2
  332. package/dist/extensions/pi-subagents/test/unit/pi-web-session-liveness.test.ts +209 -0
  333. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +38 -1
  334. package/dist/extensions/pi-subagents/test/unit/prompt-audit-optional-peers.test.ts +43 -0
  335. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +24 -2
  336. package/dist/extensions/pi-subagents/test/unit/readonly-drain-observation.test.ts +174 -0
  337. package/dist/extensions/pi-subagents/test/unit/readonly-model-continuation.test.ts +94 -0
  338. package/dist/extensions/pi-subagents/test/unit/readonly-session-evidence.test.ts +1329 -0
  339. package/dist/extensions/pi-subagents/test/unit/recursion-guard.test.ts +29 -80
  340. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +11 -8
  341. package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +2 -2
  342. package/dist/extensions/pi-subagents/test/unit/retained-nested-route-tracker.test.ts +175 -0
  343. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +38 -12
  344. package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +2 -5
  345. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +89 -1
  346. package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +2 -16
  347. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +27 -3
  348. package/dist/extensions/pi-subagents/test/unit/scheduled-supervisor-demand.test.ts +215 -0
  349. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +15 -11
  350. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +237 -1
  351. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +2 -5
  352. package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +2 -2
  353. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +14 -1
  354. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +130 -739
  355. package/dist/extensions/pi-subagents/test/unit/supervisor-ask-registration.test.ts +682 -0
  356. package/dist/extensions/pi-subagents/test/unit/supervisor-ui.test.ts +137 -0
  357. package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +1 -11
  358. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +23 -3
  359. package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +8 -1
  360. package/dist/extensions/pi-subagents/test/unit/watchdog-tool-actions.test.ts +19 -1
  361. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +72 -4
  362. package/dist/extensions/pi-subagents/test/unit/workflow-checklist.test.ts +17 -3
  363. package/dist/extensions/pi-subagents/test/unit/workflow-child-summary.test.ts +34 -0
  364. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +12 -2
  365. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +46 -6
  366. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +3 -3
  367. package/dist/extensions/pi-subagents/test/unit/workflow-resources.test.ts +133 -1
  368. package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +53 -2
  369. package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +222 -14
  370. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +526 -85
  371. package/dist/extensions/pi-web-agent/src/backends/config.ts +1 -0
  372. package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +5 -3
  373. package/dist/extensions/pi-web-agent/src/search/tokenin.ts +7 -3
  374. package/dist/extensions/pi-web-agent/src/types.ts +1 -1
  375. package/dist/extensions/pi-zentui/README.md +17 -0
  376. package/dist/extensions/pi-zentui/assets/screenshots/footer-status-hyperlink.png +0 -0
  377. package/dist/extensions/pi-zentui/docs/configuration.md +71 -2
  378. package/dist/extensions/pi-zentui/extensions/zentui/config.ts +11 -0
  379. package/dist/extensions/pi-zentui/extensions/zentui/editor-transfer.ts +14 -0
  380. package/dist/extensions/pi-zentui/extensions/zentui/extension-status.ts +29 -13
  381. package/dist/extensions/pi-zentui/extensions/zentui/footer-layout.ts +5 -4
  382. package/dist/extensions/pi-zentui/extensions/zentui/footer-text.ts +11 -0
  383. package/dist/extensions/pi-zentui/extensions/zentui/footer.ts +11 -10
  384. package/dist/extensions/pi-zentui/extensions/zentui/index.ts +77 -3
  385. package/dist/extensions/pi-zentui/extensions/zentui/presets.ts +77 -0
  386. package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +103 -2
  387. package/dist/extensions/pi-zentui/extensions/zentui/working-line-extension-segments.ts +115 -0
  388. package/dist/extensions/pi-zentui/extensions/zentui/working-line.ts +87 -5
  389. package/dist/extensions/pi-zentui/package-lock.json +277 -517
  390. package/dist/extensions/pi-zentui/package.json +7 -4
  391. package/dist/extensions/pi-zentui/test/config-presets.test.ts +238 -0
  392. package/dist/extensions/pi-zentui/test/editor-transfer.test.ts +24 -1
  393. package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +570 -2
  394. package/dist/extensions/pi-zentui/test/extension-status.test.ts +90 -0
  395. package/dist/extensions/pi-zentui/test/footer-hyperlink.test.ts +243 -0
  396. package/dist/extensions/pi-zentui/test/package-contents.mjs +1 -0
  397. package/dist/extensions/pi-zentui/test/presets.test.ts +121 -0
  398. package/dist/extensions/pi-zentui/test/settings-command.test.ts +205 -1
  399. package/dist/extensions/pi-zentui/test/working-line-extension-segments.test.ts +139 -0
  400. package/dist/extensions/pi-zentui/test/working-line-lifecycle.integration.test.ts +237 -3
  401. package/dist/extensions/pi-zentui/test/working-line.test.ts +94 -2
  402. package/dist/index.d.ts +1 -1
  403. package/dist/main.js +4 -1
  404. package/dist/modes/interactive/chat-viewport.d.ts +19 -0
  405. package/dist/modes/interactive/chat-viewport.js +27 -0
  406. package/dist/modes/interactive/components/assistant-message.d.ts +6 -2
  407. package/dist/modes/interactive/components/assistant-message.js +30 -13
  408. package/dist/modes/interactive/components/custom-editor.d.ts +10 -1
  409. package/dist/modes/interactive/components/custom-editor.js +39 -1
  410. package/dist/modes/interactive/components/first-time-setup.js +1 -1
  411. package/dist/modes/interactive/components/index.d.ts +1 -1
  412. package/dist/modes/interactive/components/markdown-transform.d.ts +2 -0
  413. package/dist/modes/interactive/components/markdown-transform.js +18 -0
  414. package/dist/modes/interactive/components/model-selector.js +19 -17
  415. package/dist/modes/interactive/components/scoped-models-selector.js +21 -23
  416. package/dist/modes/interactive/components/settings-selector.d.ts +7 -1
  417. package/dist/modes/interactive/components/settings-selector.js +128 -20
  418. package/dist/modes/interactive/components/settings-submenu.d.ts +71 -0
  419. package/dist/modes/interactive/components/settings-submenu.js +164 -0
  420. package/dist/modes/interactive/components/status-indicator.d.ts +3 -1
  421. package/dist/modes/interactive/components/status-indicator.js +10 -3
  422. package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
  423. package/dist/modes/interactive/components/thinking-selector.js +75 -18
  424. package/dist/modes/interactive/components/tool-execution.d.ts +21 -4
  425. package/dist/modes/interactive/components/tool-execution.js +35 -33
  426. package/dist/modes/interactive/components/trust-selector.js +2 -2
  427. package/dist/modes/interactive/interactive-mode.d.ts +13 -15
  428. package/dist/modes/interactive/interactive-mode.js +144 -80
  429. package/dist/modes/interactive/session-share.d.ts +15 -0
  430. package/dist/modes/interactive/session-share.js +183 -0
  431. package/dist/modes/interactive/theme/dark.json +2 -1
  432. package/dist/modes/interactive/theme/light.json +2 -1
  433. package/dist/modes/interactive/theme/theme-controller.d.ts +1 -0
  434. package/dist/modes/interactive/theme/theme-controller.js +5 -0
  435. package/dist/modes/interactive/theme/theme-json.d.ts +83 -0
  436. package/dist/modes/interactive/theme/theme-json.js +129 -0
  437. package/dist/modes/interactive/theme/theme-schema.json +9 -1
  438. package/dist/modes/interactive/theme/theme.d.ts +14 -5
  439. package/dist/modes/interactive/theme/theme.js +18 -119
  440. package/dist/modes/interactive/tui-renderer.d.ts +20 -0
  441. package/dist/modes/interactive/tui-renderer.js +65 -0
  442. package/dist/utils/exif-orientation.js +2 -3
  443. package/dist/utils/management-http.d.ts +24 -0
  444. package/dist/utils/management-http.js +53 -0
  445. package/dist/utils/text.d.ts +7 -0
  446. package/dist/utils/text.js +8 -0
  447. package/dist/utils/tools-manager.d.ts +1 -0
  448. package/dist/utils/tools-manager.js +43 -21
  449. package/docs/docs.json +0 -4
  450. package/package.json +4 -4
  451. package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +0 -415
  452. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +0 -1059
  453. package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +0 -116
  454. package/dist/extensions/pi-subagents/src/shared/post-exit-stdio-guard.ts +0 -85
  455. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +0 -224
  456. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +0 -6986
  457. package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +0 -447
  458. package/dist/extensions/pi-subagents/test/support/real-session-child-cli.mjs +0 -185
  459. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +0 -311
  460. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-pi-args.test.ts +0 -84
  461. package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +0 -202
  462. package/dist/extensions/pi-subagents/test/unit/close-grace-timer.test.ts +0 -101
  463. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +0 -2347
  464. package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +0 -104
  465. package/dist/extensions/pi-subagents/test/unit/windows-hide-spawn.test.ts +0 -49
  466. package/dist/skills/imagegen-frontend-mobile/SKILL.md +0 -1465
  467. package/dist/skills/imagegen-frontend-web/SKILL.md +0 -987
  468. package/dist/skills/implanger/SKILL.md +0 -70
  469. package/dist/skills/output/SKILL.md +0 -49
  470. package/dist/skills/planger/SKILL.md +0 -167
  471. package/dist/skills/workflow/SKILL.md +0 -95
  472. package/docs/workflows.md +0 -18
  473. /package/dist/bun/{register-bedrock.d.ts → runtime-setup.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  import { sanitizeDisplayText, truncateDisplayText } from "../../shared/display-text.ts";
2
2
  import { formatModelThinking } from "../../shared/formatters.ts";
3
- import type { AsyncJobState, AsyncJobStep, HostStepFreshnessV1, HostStepMonitorKind, HostStepNodeV1, HostStepState, HostStepVerdict, NestedRunSummary, NestedStepSummary, SubagentRunMode, WorkflowGraphSnapshot, WorkflowPreflightLaneV1, WorkflowPreflightV1 } from "../../shared/types.ts";
3
+ import type { AsyncJobState, AsyncJobStep, HostStepFreshness, HostStepMonitorKind, HostStepNode, HostStepState, HostStepVerdict, NestedRunSummary, NestedStepSummary, SubagentRunMode, WorkflowGraphSnapshot, WorkflowPreflightLane, WorkflowPreflight } from "../../shared/types.ts";
4
4
  import { HOST_STEP_MAX_COUNT, HOST_STEP_MAX_DETAIL_CHARS, HOST_STEP_MAX_LABEL_CHARS, HOST_STEP_MAX_PROVIDER_CHARS, HOST_STEP_MAX_REASON_CHARS, HOST_STEP_MAX_REF_CHARS, HOST_STEP_MAX_ROLE_CHARS, HOST_STEP_MAX_TARGET_CHARS, hostStepReportName, parseHostStepNode, validHostStepNodes } from "./host-step-status.ts";
5
5
  import { workflowPreflightLaneForRuntimeKey } from "../../workflows/workflow-preflight.ts";
6
6
  import { workflowGraphStageNodes } from "./workflow-graph.ts";
@@ -32,7 +32,7 @@ function isAsyncStatusSnapshotState(value: string): value is AsyncStatusSnapshot
32
32
  return Object.hasOwn(ASYNC_STATUS_SNAPSHOT_STATES, value);
33
33
  }
34
34
 
35
- export interface AsyncStatusSnapshotActivityV1 {
35
+ export interface AsyncStatusSnapshotActivity {
36
36
  state?: string;
37
37
  currentTool?: string;
38
38
  lastActivityAt?: number;
@@ -41,7 +41,7 @@ export interface AsyncStatusSnapshotActivityV1 {
41
41
  toolCount?: number;
42
42
  }
43
43
 
44
- export interface AsyncStatusSnapshotHostStepV1 {
44
+ export interface AsyncStatusSnapshotHostStep {
45
45
  kind: HostStepMonitorKind;
46
46
  provider?: string;
47
47
  role?: string;
@@ -54,7 +54,7 @@ export interface AsyncStatusSnapshotHostStepV1 {
54
54
  report?: string;
55
55
  }
56
56
 
57
- export interface AsyncStatusSnapshotNodeV1 {
57
+ export interface AsyncStatusSnapshotNode {
58
58
  id: string;
59
59
  kind: AsyncStatusSnapshotKind | "host-step";
60
60
  label: string;
@@ -62,12 +62,12 @@ export interface AsyncStatusSnapshotNodeV1 {
62
62
  startedAt?: number;
63
63
  updatedAt?: number;
64
64
  endedAt?: number;
65
- activity?: AsyncStatusSnapshotActivityV1;
66
- hostStep?: AsyncStatusSnapshotHostStepV1;
67
- children?: AsyncStatusSnapshotNodeV1[];
65
+ activity?: AsyncStatusSnapshotActivity;
66
+ hostStep?: AsyncStatusSnapshotHostStep;
67
+ children?: AsyncStatusSnapshotNode[];
68
68
  }
69
69
 
70
- export interface AsyncStatusSnapshotCapsV1 {
70
+ export interface AsyncStatusSnapshotCaps {
71
71
  maxRuns: number;
72
72
  maxChildrenPerNode: number;
73
73
  maxDepth: number;
@@ -75,19 +75,19 @@ export interface AsyncStatusSnapshotCapsV1 {
75
75
  maxSerializedBytes: number;
76
76
  }
77
77
 
78
- export interface AsyncStatusSnapshotOmittedV1 {
78
+ export interface AsyncStatusSnapshotOmitted {
79
79
  runs: number;
80
80
  children: number;
81
81
  byteLimitExceeded: boolean;
82
82
  }
83
83
 
84
- export interface AsyncStatusSnapshotV1 {
84
+ export interface AsyncStatusSnapshot {
85
85
  kind: typeof ASYNC_STATUS_SNAPSHOT_KIND;
86
86
  version: typeof ASYNC_STATUS_SNAPSHOT_VERSION;
87
87
  generatedAt: number;
88
- caps: AsyncStatusSnapshotCapsV1;
89
- omitted: AsyncStatusSnapshotOmittedV1;
90
- runs: AsyncStatusSnapshotNodeV1[];
88
+ caps: AsyncStatusSnapshotCaps;
89
+ omitted: AsyncStatusSnapshotOmitted;
90
+ runs: AsyncStatusSnapshotNode[];
91
91
  }
92
92
 
93
93
  export interface AsyncStatusSnapshotOptions {
@@ -117,19 +117,19 @@ export interface AsyncStatusWorkflowRow {
117
117
  reasonCode?: string;
118
118
  detail?: string;
119
119
  target?: string;
120
- freshness?: HostStepFreshnessV1;
120
+ freshness?: HostStepFreshness;
121
121
  reportPath?: string;
122
- preflight?: WorkflowPreflightLaneV1;
122
+ preflight?: WorkflowPreflightLane;
123
123
  }
124
124
 
125
125
  interface ProjectionContext {
126
- caps: AsyncStatusSnapshotCapsV1;
127
- omitted: AsyncStatusSnapshotOmittedV1;
126
+ caps: AsyncStatusSnapshotCaps;
127
+ omitted: AsyncStatusSnapshotOmitted;
128
128
  }
129
129
 
130
- function validHostStepList(source: readonly HostStepNodeV1[] | WorkflowGraphSnapshot | undefined): HostStepNodeV1[] {
130
+ function validHostStepList(source: readonly HostStepNode[] | WorkflowGraphSnapshot | undefined): HostStepNode[] {
131
131
  if (source && "nodes" in source) return validHostStepNodes(source);
132
- const hostSteps: HostStepNodeV1[] = [];
132
+ const hostSteps: HostStepNode[] = [];
133
133
  for (const [index, value] of (source ?? []).slice(0, HOST_STEP_MAX_COUNT).entries()) {
134
134
  try {
135
135
  hostSteps.push(parseHostStepNode(value, `hostSteps[${index}]`));
@@ -140,7 +140,7 @@ function validHostStepList(source: readonly HostStepNodeV1[] | WorkflowGraphSnap
140
140
  return hostSteps;
141
141
  }
142
142
 
143
- function resolveCaps(options: AsyncStatusSnapshotOptions): AsyncStatusSnapshotCapsV1 {
143
+ function resolveCaps(options: AsyncStatusSnapshotOptions): AsyncStatusSnapshotCaps {
144
144
  return {
145
145
  maxRuns: Math.max(0, Math.floor(options.maxRuns ?? DEFAULT_MAX_RUNS)),
146
146
  maxChildrenPerNode: Math.max(0, Math.floor(options.maxChildrenPerNode ?? DEFAULT_MAX_CHILDREN_PER_NODE)),
@@ -199,13 +199,13 @@ function activityFor(source: {
199
199
  currentToolStartedAt?: unknown;
200
200
  turnCount?: unknown;
201
201
  toolCount?: unknown;
202
- }, ctx: ProjectionContext): AsyncStatusSnapshotActivityV1 | undefined {
202
+ }, ctx: ProjectionContext): AsyncStatusSnapshotActivity | undefined {
203
203
  const currentTool = publicOptionalText(source.currentTool, ctx.caps.maxStringLength);
204
204
  const lastActivityAt = publicTime(source.lastActivityAt);
205
205
  const currentToolStartedAt = publicTime(source.currentToolStartedAt);
206
206
  const turnCount = publicCount(source.turnCount);
207
207
  const toolCount = publicCount(source.toolCount);
208
- const activity: AsyncStatusSnapshotActivityV1 = {
208
+ const activity: AsyncStatusSnapshotActivity = {
209
209
  ...(typeof source.activityState === "string" ? { state: publicText(source.activityState, "unknown", ctx.caps.maxStringLength) } : {}),
210
210
  ...(currentTool ? { currentTool } : {}),
211
211
  ...(lastActivityAt !== undefined ? { lastActivityAt } : {}),
@@ -216,19 +216,19 @@ function activityFor(source: {
216
216
  return Object.keys(activity).length ? activity : undefined;
217
217
  }
218
218
 
219
- function appendBoundedChildren(children: AsyncStatusSnapshotNodeV1[], source: readonly AsyncStatusSnapshotNodeV1[], ctx: ProjectionContext): void {
219
+ function appendBoundedChildren(children: AsyncStatusSnapshotNode[], source: readonly AsyncStatusSnapshotNode[], ctx: ProjectionContext): void {
220
220
  const remaining = Math.max(0, ctx.caps.maxChildrenPerNode - children.length);
221
221
  children.push(...source.slice(0, remaining));
222
222
  ctx.omitted.children += Math.max(0, source.length - remaining);
223
223
  }
224
224
 
225
- function projectStep(step: AsyncJobStep | NestedStepSummary, index: number, depth: number, ctx: ProjectionContext): AsyncStatusSnapshotNodeV1 {
225
+ function projectStep(step: AsyncJobStep | NestedStepSummary, index: number, depth: number, ctx: ProjectionContext): AsyncStatusSnapshotNode {
226
226
  const state = normalizeState(step.status);
227
227
  const startedAt = publicTime(step.startedAt);
228
228
  const endedAt = publicTime(step.endedAt);
229
229
  const updatedAt = endedAt ?? publicTime(step.lastActivityAt) ?? startedAt;
230
230
  const activity = activityFor(step, ctx);
231
- const node: AsyncStatusSnapshotNodeV1 = {
231
+ const node: AsyncStatusSnapshotNode = {
232
232
  id: publicText("workflowKey" in step && step.workflowKey ? step.workflowKey : "runId" in step && step.runId ? step.runId : `step:${index}`, `step:${index}`, ctx.caps.maxStringLength),
233
233
  kind: "step",
234
234
  label: publicText("label" in step && step.label ? step.label : step.agent, "step", ctx.caps.maxStringLength),
@@ -240,7 +240,7 @@ function projectStep(step: AsyncJobStep | NestedStepSummary, index: number, dept
240
240
  };
241
241
  if (depth < ctx.caps.maxDepth && step.children?.length) {
242
242
  const nested = step.children.map((child, childIndex) => projectNestedRun(child, childIndex, depth + 1, ctx));
243
- const bounded: AsyncStatusSnapshotNodeV1[] = [];
243
+ const bounded: AsyncStatusSnapshotNode[] = [];
244
244
  appendBoundedChildren(bounded, nested, ctx);
245
245
  if (bounded.length) node.children = bounded;
246
246
  } else if (step.children?.length) {
@@ -249,7 +249,7 @@ function projectStep(step: AsyncJobStep | NestedStepSummary, index: number, dept
249
249
  return node;
250
250
  }
251
251
 
252
- function projectWorkflowGraphNode(node: WorkflowGraphSnapshot["nodes"][number], index: number, depth: number, ctx: ProjectionContext): AsyncStatusSnapshotNodeV1 {
252
+ function projectWorkflowGraphNode(node: WorkflowGraphSnapshot["nodes"][number], index: number, depth: number, ctx: ProjectionContext): AsyncStatusSnapshotNode {
253
253
  const step: AsyncJobStep = {
254
254
  agent: node.agent ?? node.label,
255
255
  status: workflowGraphStepStatus(node.status),
@@ -259,13 +259,13 @@ function projectWorkflowGraphNode(node: WorkflowGraphSnapshot["nodes"][number],
259
259
  return projectStep(step, node.flatIndex ?? index, depth, ctx);
260
260
  }
261
261
 
262
- function projectNestedRun(child: NestedRunSummary, index: number, depth: number, ctx: ProjectionContext): AsyncStatusSnapshotNodeV1 {
262
+ function projectNestedRun(child: NestedRunSummary, index: number, depth: number, ctx: ProjectionContext): AsyncStatusSnapshotNode {
263
263
  const state = normalizeState(child.state);
264
264
  const startedAt = publicTime(child.startedAt);
265
265
  const endedAt = publicTime(child.endedAt);
266
266
  const updatedAt = publicTime(child.lastUpdate) ?? endedAt ?? publicTime(child.lastActivityAt) ?? startedAt;
267
267
  const activity = activityFor(child, ctx);
268
- const node: AsyncStatusSnapshotNodeV1 = {
268
+ const node: AsyncStatusSnapshotNode = {
269
269
  id: publicText(child.id, `nested:${index}`, ctx.caps.maxStringLength),
270
270
  kind: kindForMode(child.mode),
271
271
  label: child.agent ? publicText(child.agent, "subagent", ctx.caps.maxStringLength) : labelForAgents(child.agents, child.mode ?? "subagent", ctx.caps.maxStringLength),
@@ -278,7 +278,7 @@ function projectNestedRun(child: NestedRunSummary, index: number, depth: number,
278
278
  if (depth < ctx.caps.maxDepth) {
279
279
  const nestedSteps = child.steps?.map((step, stepIndex) => projectStep(step, stepIndex, depth + 1, ctx)) ?? [];
280
280
  const nestedChildren = child.children?.map((nested, childIndex) => projectNestedRun(nested, childIndex, depth + 1, ctx)) ?? [];
281
- const bounded: AsyncStatusSnapshotNodeV1[] = [];
281
+ const bounded: AsyncStatusSnapshotNode[] = [];
282
282
  appendBoundedChildren(bounded, [...nestedSteps, ...nestedChildren], ctx);
283
283
  if (bounded.length) node.children = bounded;
284
284
  } else {
@@ -295,11 +295,11 @@ function hostStepSnapshotState(state: HostStepState, verdict: HostStepVerdict |
295
295
  return verdict === undefined || verdict === "inconclusive" ? "partial" : "complete";
296
296
  }
297
297
 
298
- function projectHostStep(hostStep: HostStepNodeV1, ctx: ProjectionContext): AsyncStatusSnapshotNodeV1 {
298
+ function projectHostStep(hostStep: HostStepNode, ctx: ProjectionContext): AsyncStatusSnapshotNode {
299
299
  const state = hostStepSnapshotState(hostStep.state, hostStep.verdict);
300
300
  const detail = publicOptionalText(hostStep.detail, ctx.caps.maxStringLength);
301
301
  const report = publicOptionalText(hostStepReportName(hostStep.reportPath), ctx.caps.maxStringLength);
302
- const hostMetadata: AsyncStatusSnapshotHostStepV1 = {
302
+ const hostMetadata: AsyncStatusSnapshotHostStep = {
303
303
  kind: hostStep.monitorKind,
304
304
  state: hostStep.state,
305
305
  ...(hostStep.provider ? { provider: publicText(hostStep.provider, "provider", ctx.caps.maxStringLength) } : {}),
@@ -322,12 +322,12 @@ function projectHostStep(hostStep: HostStepNodeV1, ctx: ProjectionContext): Asyn
322
322
  };
323
323
  }
324
324
 
325
- function projectRun(job: AsyncJobState, ctx: ProjectionContext): AsyncStatusSnapshotNodeV1 {
325
+ function projectRun(job: AsyncJobState, ctx: ProjectionContext): AsyncStatusSnapshotNode {
326
326
  const state = normalizeState(job.status);
327
327
  const startedAt = publicTime(job.startedAt);
328
328
  const updatedAt = publicTime(job.updatedAt) ?? startedAt;
329
329
  const activity = activityFor(job, ctx);
330
- const node: AsyncStatusSnapshotNodeV1 = {
330
+ const node: AsyncStatusSnapshotNode = {
331
331
  id: publicText(job.asyncId, "async", ctx.caps.maxStringLength),
332
332
  kind: kindForMode(job.mode),
333
333
  label: labelForAgents(job.agents, job.mode ?? "subagent", ctx.caps.maxStringLength),
@@ -349,7 +349,7 @@ function projectRun(job: AsyncJobState, ctx: ProjectionContext): AsyncStatusSnap
349
349
  const ordinaryChildren = [...stepChildren, ...graphChildren, ...nestedChildren];
350
350
  const retainedHostSteps = hostStepChildren.slice(0, ctx.caps.maxChildrenPerNode);
351
351
  const retainedOrdinaryChildren = ordinaryChildren.slice(0, ctx.caps.maxChildrenPerNode - retainedHostSteps.length);
352
- const bounded: AsyncStatusSnapshotNodeV1[] = [];
352
+ const bounded: AsyncStatusSnapshotNode[] = [];
353
353
  bounded.push(...retainedOrdinaryChildren, ...retainedHostSteps);
354
354
  ctx.omitted.children += ordinaryChildren.length - retainedOrdinaryChildren.length + hostStepChildren.length - retainedHostSteps.length;
355
355
  if (bounded.length) node.children = bounded;
@@ -362,11 +362,11 @@ function projectRun(job: AsyncJobState, ctx: ProjectionContext): AsyncStatusSnap
362
362
  return node;
363
363
  }
364
364
 
365
- function snapshotBytes(snapshot: AsyncStatusSnapshotV1): number {
365
+ function snapshotBytes(snapshot: AsyncStatusSnapshot): number {
366
366
  return Buffer.byteLength(JSON.stringify(snapshot), "utf8");
367
367
  }
368
368
 
369
- function enforceByteLimit(snapshot: AsyncStatusSnapshotV1): void {
369
+ function enforceByteLimit(snapshot: AsyncStatusSnapshot): void {
370
370
  if (snapshotBytes(snapshot) <= snapshot.caps.maxSerializedBytes) return;
371
371
  snapshot.omitted.byteLimitExceeded = true;
372
372
  const runs = snapshot.runs;
@@ -401,7 +401,7 @@ function workflowStepName(step: AsyncJobStep, index: number): string {
401
401
  return `${phase}${key}${label} (${step.agent})`;
402
402
  }
403
403
 
404
- function hostStepRow(hostStep: HostStepNodeV1): AsyncStatusWorkflowRow {
404
+ function hostStepRow(hostStep: HostStepNode): AsyncStatusWorkflowRow {
405
405
  const freshness = hostStep.freshness
406
406
  ? {
407
407
  expectedRef: publicText(hostStep.freshness.expectedRef, "ref", HOST_STEP_MAX_REF_CHARS),
@@ -425,11 +425,11 @@ function hostStepRow(hostStep: HostStepNodeV1): AsyncStatusWorkflowRow {
425
425
  }
426
426
 
427
427
 
428
- function isWorkflowPreflight(value: readonly HostStepNodeV1[] | WorkflowGraphSnapshot | WorkflowPreflightV1 | undefined): value is WorkflowPreflightV1 {
428
+ function isWorkflowPreflight(value: readonly HostStepNode[] | WorkflowGraphSnapshot | WorkflowPreflight | undefined): value is WorkflowPreflight {
429
429
  return value !== undefined && !Array.isArray(value) && "lanes" in value;
430
430
  }
431
431
 
432
- function isWorkflowGraph(value: readonly HostStepNodeV1[] | WorkflowGraphSnapshot | WorkflowPreflightV1 | undefined): value is WorkflowGraphSnapshot {
432
+ function isWorkflowGraph(value: readonly HostStepNode[] | WorkflowGraphSnapshot | WorkflowPreflight | undefined): value is WorkflowGraphSnapshot {
433
433
  return value !== undefined && !Array.isArray(value) && "nodes" in value;
434
434
  }
435
435
 
@@ -465,7 +465,7 @@ function workflowGraphRowName(node: WorkflowGraphSnapshot["nodes"][number]): str
465
465
  return `${phase ? `${phase}: ` : ""}${key}${label && label !== node.id ? ` · ${label}` : ""}${agent ? ` (${agent})` : ""}`;
466
466
  }
467
467
 
468
- function projectWorkflowGraphRow(node: WorkflowGraphSnapshot["nodes"][number], preflight?: WorkflowPreflightLaneV1): AsyncStatusWorkflowRow {
468
+ function projectWorkflowGraphRow(node: WorkflowGraphSnapshot["nodes"][number], preflight?: WorkflowPreflightLane): AsyncStatusWorkflowRow {
469
469
  return {
470
470
  name: workflowGraphRowName(node),
471
471
  state: workflowGraphRowState(node.status),
@@ -476,14 +476,14 @@ function projectWorkflowGraphRow(node: WorkflowGraphSnapshot["nodes"][number], p
476
476
  /** Project authoritative workflow facts into compact rows, annotated by preflight hints. */
477
477
  export function projectAsyncWorkflowRows(
478
478
  steps: readonly AsyncJobStep[] | undefined,
479
- hostStepsOrPreflight?: readonly HostStepNodeV1[] | WorkflowGraphSnapshot | WorkflowPreflightV1,
480
- preflightOverride?: WorkflowPreflightV1,
479
+ hostStepsOrPreflight?: readonly HostStepNode[] | WorkflowGraphSnapshot | WorkflowPreflight,
480
+ preflightOverride?: WorkflowPreflight,
481
481
  ): AsyncStatusWorkflowRow[] {
482
482
  const preflight = preflightOverride ?? (isWorkflowPreflight(hostStepsOrPreflight) ? hostStepsOrPreflight : undefined);
483
483
  const graph = isWorkflowGraph(hostStepsOrPreflight) ? hostStepsOrPreflight : undefined;
484
484
  const hostSteps = isWorkflowPreflight(hostStepsOrPreflight) || graph ? undefined : hostStepsOrPreflight;
485
485
  const loaded = steps ?? [];
486
- const preflightForKey = (key: string, groupKeys: readonly (string | undefined)[] = []): WorkflowPreflightLaneV1 | undefined =>
486
+ const preflightForKey = (key: string, groupKeys: readonly (string | undefined)[] = []): WorkflowPreflightLane | undefined =>
487
487
  workflowPreflightLaneForRuntimeKey(preflight, key, groupKeys);
488
488
  if (graph) {
489
489
  const loadedIndexesByKey = new Map<string, number[]>();
@@ -526,7 +526,7 @@ export function projectAsyncWorkflowRows(
526
526
  ];
527
527
  }
528
528
 
529
- function projectLoadedWorkflowRow(step: AsyncJobStep, index: number, preflight?: WorkflowPreflightLaneV1): AsyncStatusWorkflowRow {
529
+ function projectLoadedWorkflowRow(step: AsyncJobStep, index: number, preflight?: WorkflowPreflightLane): AsyncStatusWorkflowRow {
530
530
  const modelThinking = formatModelThinking(step.model, step.thinking) || undefined;
531
531
  const activity = workflowStepActivity(step);
532
532
  return {
@@ -543,7 +543,7 @@ function projectLoadedWorkflowRow(step: AsyncJobStep, index: number, preflight?:
543
543
  }
544
544
 
545
545
  /** Project already-loaded async status facts into the bounded public snapshot shape. */
546
- export function projectAsyncStatusSnapshot(jobs: Iterable<AsyncJobState>, options: AsyncStatusSnapshotOptions = {}): AsyncStatusSnapshotV1 {
546
+ export function projectAsyncStatusSnapshot(jobs: Iterable<AsyncJobState>, options: AsyncStatusSnapshotOptions = {}): AsyncStatusSnapshot {
547
547
  const caps = resolveCaps(options);
548
548
  const ctx: ProjectionContext = { caps, omitted: { runs: 0, children: 0, byteLimitExceeded: false } };
549
549
  const sorted = [...jobs].sort((left, right) => {
@@ -552,7 +552,7 @@ export function projectAsyncStatusSnapshot(jobs: Iterable<AsyncJobState>, option
552
552
  return rightUpdated - leftUpdated || left.asyncId.localeCompare(right.asyncId);
553
553
  });
554
554
  ctx.omitted.runs += Math.max(0, sorted.length - caps.maxRuns);
555
- const snapshot: AsyncStatusSnapshotV1 = {
555
+ const snapshot: AsyncStatusSnapshot = {
556
556
  kind: ASYNC_STATUS_SNAPSHOT_KIND,
557
557
  version: ASYNC_STATUS_SNAPSHOT_VERSION,
558
558
  generatedAt: options.generatedAt ?? Date.now(),
@@ -2,7 +2,6 @@ import { Buffer } from "node:buffer";
2
2
 
3
3
  export const SUBAGENT_CAPABILITY_CEILING_VERSION = 1 as const;
4
4
  export const SUBAGENT_CAPABILITY_CEILING_REGISTRY_KEY = "pi-subagents.capability-ceiling.v1";
5
- export const SUBAGENT_CAPABILITY_CEILING_ENV = "SELESAI_SUBAGENT_CAPABILITY_CEILING_V1";
6
5
 
7
6
  export type SubagentCapabilityCeiling =
8
7
  | { allowedTools: readonly string[]; allowedAgents?: readonly string[]; denyExtensions?: boolean }
@@ -167,7 +166,7 @@ export function resolveSubagentCapabilityCeiling(sessionId: string | undefined,
167
166
  }
168
167
 
169
168
  export function resolveCurrentSubagentCapabilityCeiling(sessionId: string | undefined): ResolvedSubagentCapabilityCeiling | undefined {
170
- return resolveSubagentCapabilityCeiling(sessionId, decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]));
169
+ return resolveSubagentCapabilityCeiling(sessionId, undefined);
171
170
  }
172
171
 
173
172
  export function isAgentAllowedByCapabilityCeiling(agentName: string, ceiling: ResolvedSubagentCapabilityCeiling | undefined): boolean {
@@ -0,0 +1,174 @@
1
+ import type { ExtensionAPI, ExtensionContext } from "@selesai/code";
2
+ import { listBackgroundWorkProviders } from "../../api/background-work.ts";
3
+ import { ReadonlyDrainObservation } from "./readonly-drain-observation.ts";
4
+ import registerFanoutChildSubagentExtension from "../../extension/fanout-child.ts";
5
+ import registerSubagentFastModeExtension from "./fast-mode-extension.ts";
6
+ import registerSubagentPromptRuntime from "./subagent-prompt-runtime.ts";
7
+ import type { ChildRuntimeConfig } from "./child-runtime-config.ts";
8
+ import type { ChildToolDiagnostic } from "./tool-availability.ts";
9
+ import type { ChildSessionLaunch } from "./child-session.ts";
10
+ import type { ChildTranscriptWriter } from "../../shared/child-transcript.ts";
11
+ import { projectRuntimeAcknowledgedExtensions } from "./runtime-acknowledged-extensions.ts";
12
+
13
+ /** Inline extension shape accepted by pi's resource loader (`extensionFactories`). */
14
+ export interface ChildHookExtension {
15
+ name: string;
16
+ factory: (pi: ExtensionAPI) => void;
17
+ }
18
+
19
+ type OwnedCapture = Required<Pick<ChildRuntimeConfig, "toolDiagnostic" | "runtimeAcknowledgements">>;
20
+ type PromptProof = { config: ChildRuntimeConfig; snapshot: string; factories?: ChildHookExtension["factory"][]; observeNext?: ReadonlyDrainObservation; observation?: ReadonlyDrainObservation; capture?: OwnedCapture; reporting?: { launch: ChildSessionLaunch; callback: ChildSessionLaunch["onExtensionError"] } };
21
+ const promptProofs = new WeakMap<ChildHookExtension["factory"], PromptProof>();
22
+
23
+ function ownedProof(hooks: ChildHookExtension[]): PromptProof | undefined {
24
+ const proof = hooks[0] && promptProofs.get(hooks[0].factory);
25
+ return proof?.factories?.length === hooks.length && proof.factories.every((factory, index) => hooks[index]?.factory === factory) ? proof : undefined;
26
+ }
27
+
28
+ /** The host's mandatory transcript reporting, owned by the existing hook certificate. */
29
+ export function withChildSessionErrorReporting(session: Omit<ChildSessionLaunch, "onExtensionError">, transcriptWriter: ChildTranscriptWriter | undefined): ChildSessionLaunch {
30
+ const launch: ChildSessionLaunch = { ...session, onExtensionError: (error) => {
31
+ transcriptWriter?.writeStderrLine(`Extension error (${error.extensionPath}, ${error.event}): ${error.error instanceof Error ? error.error.message : String(error.error)}`);
32
+ } };
33
+ const proof = ownedProof(launch.hooks);
34
+ if (proof?.capture && proof.config === launch.runtime) proof.reporting = { launch, callback: launch.onExtensionError };
35
+ return launch;
36
+ }
37
+
38
+ export function isReadonlyChildSessionReporting(launch: ChildSessionLaunch): boolean {
39
+ const proof = ownedProof(launch.hooks);
40
+ const descriptor = Object.getOwnPropertyDescriptor(launch, "onExtensionError");
41
+ if (descriptor && (!descriptor.enumerable || !("value" in descriptor))) return false;
42
+ return proof?.reporting ? proof.reporting.launch === launch && proof.reporting.callback === descriptor?.value : !descriptor && !("onExtensionError" in launch);
43
+ }
44
+
45
+ /** Admit only own enumerable data: inspecting descriptors must not invoke getters. */
46
+ function dataKeys(value: unknown): string[] | undefined {
47
+ if (!value || typeof value !== "object" || Object.getPrototypeOf(value) !== Object.prototype) return undefined;
48
+ const keys = Reflect.ownKeys(value);
49
+ for (const key of keys) {
50
+ const descriptor = Object.getOwnPropertyDescriptor(value, key)!;
51
+ if (typeof key !== "string" || !descriptor.enumerable || !("value" in descriptor)) return undefined;
52
+ }
53
+ return keys as string[];
54
+ }
55
+
56
+ /** Only reviewed data and the capture callbacks constructed below; no caller callback opt-in. */
57
+ function readonlyConfig(config: ChildRuntimeConfig, capture?: OwnedCapture): string | undefined {
58
+ const strings = ["runId", "agent", "sessionName", "forkCacheKey", "parentSessionId", "orchestratorSessionId"];
59
+ const numbers = ["childIndex", "depth", "maxDepth"];
60
+ const booleans = ["inheritProjectContext", "inheritGlobalContext", "inheritSkills"];
61
+ const keys = dataKeys(config);
62
+ if (!keys) return undefined;
63
+ if (capture && (config.toolDiagnostic !== capture.toolDiagnostic || config.runtimeAcknowledgements !== capture.runtimeAcknowledgements)) return undefined;
64
+ const waitKeys = dataKeys(config.waitTool);
65
+ if (!waitKeys || waitKeys.some((key) => key !== "enabled")) return undefined;
66
+ if (config.fast !== false || config.fanoutChild !== false || config.waitTool.enabled !== false) return undefined;
67
+ for (const key of keys) {
68
+ const value = Object.getOwnPropertyDescriptor(config, key)!.value;
69
+ if (["fast", "fanoutChild", "waitTool"].includes(key)) continue;
70
+ if (capture && (key === "toolDiagnostic" || key === "runtimeAcknowledgements")) continue;
71
+ if (capture && key === "requiredTools" && Array.isArray(value) && Object.getPrototypeOf(value) === Array.prototype) {
72
+ const descriptors = Object.getOwnPropertyDescriptors(value);
73
+ if (Reflect.ownKeys(descriptors).length !== value.length + 1) return undefined;
74
+ for (let i = 0; i < value.length; i++) {
75
+ const descriptor = descriptors[String(i)];
76
+ if (!descriptor?.enumerable || !("value" in descriptor) || !["read", "ls"].includes(descriptor.value)) return undefined;
77
+ }
78
+ continue;
79
+ }
80
+ if (strings.includes(key) && (value === undefined || typeof value === "string")) continue;
81
+ if (numbers.includes(key) && (value === undefined || (typeof value === "number" && Number.isInteger(value) && value >= 0))) continue;
82
+ if (booleans.includes(key) && (value === undefined || typeof value === "boolean")) continue;
83
+ return undefined;
84
+ }
85
+ return JSON.stringify(config);
86
+ }
87
+
88
+ function noBackgroundProviders(): boolean {
89
+ try {
90
+ return listBackgroundWorkProviders().length === 0;
91
+ } catch { return false; }
92
+ }
93
+
94
+ /** Internal proof of the captured closure/config, not its caller-controlled display name. */
95
+ export function isReadonlyChildHookProfile(hooks: ChildHookExtension[], config: ChildRuntimeConfig): boolean {
96
+ const proof = ownedProof(hooks);
97
+ if (!proof) return false;
98
+ const valid = proof.config === config && readonlyConfig(config, proof.capture) === proof.snapshot && noBackgroundProviders();
99
+ if (!valid) proof.observation?.deny();
100
+ return valid && (proof.observation?.check() ?? true);
101
+ }
102
+
103
+ /** Arm just the next installation; ordinary installations retain the original API/handlers. */
104
+ export function observeReadonlyChildHookDrain(hooks: ChildHookExtension[], enabled: boolean, sessionFile: string): void {
105
+ const proof = ownedProof(hooks);
106
+ if (!proof) return;
107
+ if (enabled) {
108
+ proof.observation?.deny();
109
+ proof.observation = undefined;
110
+ }
111
+ proof.observeNext = enabled ? new ReadonlyDrainObservation(sessionFile, () => readonlyConfig(proof.config, proof.capture) === proof.snapshot && noBackgroundProviders()) : undefined;
112
+ }
113
+
114
+ export function captureReadonlyChildDrain(hooks: ChildHookExtension[]): (() => boolean) {
115
+ const proof = ownedProof(hooks);
116
+ const observation = proof?.observation;
117
+ return () => !!observation && proof?.observation === observation && observation.settled();
118
+ }
119
+
120
+ /**
121
+ * The child-side hooks pi-subagents installs in every child, keyed off the
122
+ * launch config. The registrations live in `subagent-prompt-runtime.ts`,
123
+ * `fast-mode-extension.ts`, and `fanout-child.ts`.
124
+ */
125
+ export function createChildHooks(config: ChildRuntimeConfig): ChildHookExtension[] {
126
+ return childHooks(config);
127
+ }
128
+
129
+ /** Launch-owned bookkeeping, paired with the same private hook certificate (no callback registration API). */
130
+ export function createCapturedChildHooks(config: ChildRuntimeConfig, runner = false) {
131
+ let diagnostic: ChildToolDiagnostic | undefined;
132
+ let acknowledgedIds: string[] | undefined;
133
+ let completionIntentContext: Pick<ExtensionContext, "model" | "modelRegistry"> | undefined;
134
+ const capture: OwnedCapture = {
135
+ toolDiagnostic: (value) => { diagnostic = value; },
136
+ runtimeAcknowledgements: (ids) => { acknowledgedIds = ids; },
137
+ };
138
+ Object.assign(config, capture);
139
+ const hooks = childHooks(config, capture);
140
+ if (runner) {
141
+ hooks.push({ name: "pi-subagents:completion-intent", factory: (pi) => pi.on("session_start", (_event, childCtx) => {
142
+ // Retain only attempt model services, not the live child session.
143
+ completionIntentContext = { model: childCtx.model, modelRegistry: childCtx.modelRegistry };
144
+ }) });
145
+ const proof = promptProofs.get(hooks[0]!.factory);
146
+ if (proof) proof.factories = hooks.map((hook) => hook.factory);
147
+ }
148
+ return {
149
+ hooks,
150
+ completionIntentContext: () => completionIntentContext,
151
+ toolDiagnostic: () => diagnostic,
152
+ runtimeAcknowledgedExtensions: () => acknowledgedIds ? projectRuntimeAcknowledgedExtensions(acknowledgedIds) : undefined,
153
+ };
154
+ }
155
+
156
+ function childHooks(config: ChildRuntimeConfig, capture?: OwnedCapture): ChildHookExtension[] {
157
+ const snapshot = readonlyConfig(config, capture);
158
+ const proof: PromptProof | undefined = snapshot === undefined ? undefined : { config, snapshot, capture };
159
+ const hooks: ChildHookExtension[] = [
160
+ { name: "pi-subagents:prompt-runtime", factory: function promptRuntime(pi) {
161
+ if (!proof?.observeNext) return registerSubagentPromptRuntime(pi, config);
162
+ proof.observation = proof.observeNext;
163
+ proof.observeNext = undefined;
164
+ registerSubagentPromptRuntime(pi, config, proof.observation);
165
+ } },
166
+ ];
167
+ if (proof) {
168
+ proof.factories = hooks.map((hook) => hook.factory);
169
+ promptProofs.set(hooks[0]!.factory, proof);
170
+ }
171
+ if (config.fast) hooks.push({ name: "pi-subagents:fast-mode", factory: (pi) => registerSubagentFastModeExtension(pi) });
172
+ if (config.fanoutChild) hooks.push({ name: "pi-subagents:fanout-child", factory: (pi) => registerFanoutChildSubagentExtension(pi, config) });
173
+ return hooks;
174
+ }
@@ -14,11 +14,11 @@ export type AsyncStatusChildResolution =
14
14
  | { ok: false; code: "not_found" | "ambiguous"; message: string };
15
15
 
16
16
  export function asyncStatusChildIdentity(step: AsyncStatusStep, index: number): string {
17
- return step.workflowKey ?? step.runId ?? `step:${index}`;
17
+ return asyncStatusChildIdentityCandidates(step, index)[0]!;
18
18
  }
19
19
 
20
20
  export function asyncStatusChildIdentityCandidates(step: AsyncStatusStep, index: number): string[] {
21
- return [...new Set([step.workflowKey, step.runId, `step:${index}`].filter((value): value is string => typeof value === "string" && value.length > 0))];
21
+ return [...new Set([step.childId, step.workflowKey, step.runId, `step:${index}`].filter((value): value is string => typeof value === "string" && value.length > 0))];
22
22
  }
23
23
 
24
24
  export function resolveAsyncStatusChild(
@@ -48,4 +48,15 @@ export function resolveAsyncStatusChild(
48
48
 
49
49
  export function isStoppableAsyncStatusStep(step: AsyncStatusStep): boolean {
50
50
  return step.status === "pending" || step.status === "running";
51
- }
51
+ }
52
+
53
+ export function stopStoppableAsyncStatusChildren(
54
+ status: Pick<AsyncStatus, "steps">,
55
+ stopChild: ((childId: string, message?: string) => boolean) | undefined,
56
+ message: string,
57
+ ): void {
58
+ if (!stopChild) return;
59
+ for (const [index, step] of (status.steps ?? []).entries()) {
60
+ if (isStoppableAsyncStatusStep(step)) stopChild(asyncStatusChildIdentity(step, index), message);
61
+ }
62
+ }