@selesai/code 0.8.3 → 0.8.4

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 (493) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/dist/extensions/handoff-new.ts +1 -1
  3. package/dist/extensions/inline-skills.test.ts +1 -0
  4. package/dist/extensions/inline-skills.ts +1 -1
  5. package/dist/extensions/pi-intercom/CHANGELOG.md +25 -3
  6. package/dist/extensions/pi-intercom/README.md +34 -15
  7. package/dist/extensions/pi-intercom/broker/broker.ts +38 -141
  8. package/dist/extensions/pi-intercom/broker/client-liveness.test.ts +173 -0
  9. package/dist/extensions/pi-intercom/broker/client.ts +78 -150
  10. package/dist/extensions/pi-intercom/broker/extension-state.ts +18 -7
  11. package/dist/extensions/pi-intercom/broker/framing.ts +1 -1
  12. package/dist/extensions/pi-intercom/broker/protocol.ts +182 -0
  13. package/dist/extensions/pi-intercom/broker/spawn.test.ts +106 -7
  14. package/dist/extensions/pi-intercom/broker/spawn.ts +37 -11
  15. package/dist/extensions/pi-intercom/config.test.ts +8 -10
  16. package/dist/extensions/pi-intercom/config.ts +3 -3
  17. package/dist/extensions/pi-intercom/index.ts +218 -147
  18. package/dist/extensions/pi-intercom/intercom.integration.test.ts +891 -103
  19. package/dist/extensions/pi-intercom/package.json +3 -2
  20. package/dist/extensions/pi-intercom/project-agent.test.ts +145 -0
  21. package/dist/extensions/pi-intercom/project-agent.ts +324 -0
  22. package/dist/extensions/pi-intercom/reply-tracker.test.ts +86 -1
  23. package/dist/extensions/pi-intercom/reply-tracker.ts +41 -9
  24. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +49 -9
  25. package/dist/extensions/pi-intercom/test/inline-message.test.ts +9 -9
  26. package/dist/extensions/pi-intercom/types.ts +3 -1
  27. package/dist/extensions/pi-intercom/ui/inline-message.ts +7 -7
  28. package/dist/extensions/pi-powerline-footer/.github/workflows/test.yml +2 -2
  29. package/dist/extensions/pi-powerline-footer/CHANGELOG.md +14 -1
  30. package/dist/extensions/pi-powerline-footer/README.md +20 -37
  31. package/dist/extensions/pi-powerline-footer/bash-mode/completion.ts +40 -25
  32. package/dist/extensions/pi-powerline-footer/bash-mode/editor.ts +149 -18
  33. package/dist/extensions/pi-powerline-footer/bash-mode/types.ts +1 -0
  34. package/dist/extensions/pi-powerline-footer/editor-performance.ts +99 -0
  35. package/dist/extensions/pi-powerline-footer/git-status.ts +15 -0
  36. package/dist/extensions/pi-powerline-footer/index.ts +394 -317
  37. package/dist/extensions/pi-powerline-footer/package.json +1 -1
  38. package/dist/extensions/pi-powerline-footer/powerline-config.ts +0 -12
  39. package/dist/extensions/pi-powerline-footer/queue/store.ts +8 -56
  40. package/dist/extensions/pi-powerline-footer/queue/types.ts +1 -2
  41. package/dist/extensions/pi-powerline-footer/segments.ts +0 -3
  42. package/dist/extensions/pi-powerline-footer/tests/bash-mode.test.ts +231 -1
  43. package/dist/extensions/pi-powerline-footer/tests/custom-items.test.ts +5 -19
  44. package/dist/extensions/pi-powerline-footer/tests/editor-performance.test.ts +43 -0
  45. package/dist/extensions/pi-powerline-footer/tests/git-optional-locks.test.ts +64 -0
  46. package/dist/extensions/pi-powerline-footer/tests/jump-shortcuts.test.ts +116 -0
  47. package/dist/extensions/pi-powerline-footer/tests/queue-store.test.ts +19 -149
  48. package/dist/extensions/pi-powerline-footer/tests/remaining-regressions.test.ts +6 -0
  49. package/dist/extensions/pi-powerline-footer/tests/usage-display.test.ts +5 -5
  50. package/dist/extensions/pi-powerline-footer/types.ts +1 -2
  51. package/dist/extensions/pi-subagents/CHANGELOG.md +202 -14
  52. package/dist/extensions/pi-subagents/README.md +65 -1614
  53. package/dist/extensions/pi-subagents/agents/builder.md +0 -1
  54. package/dist/extensions/pi-subagents/agents/delegate.md +14 -0
  55. package/dist/extensions/pi-subagents/agents/oracle.md +74 -0
  56. package/dist/extensions/pi-subagents/agents/reviewer.md +78 -0
  57. package/dist/extensions/pi-subagents/agents/scout.md +50 -0
  58. package/dist/extensions/pi-subagents/agents/worker.md +58 -0
  59. package/dist/extensions/pi-subagents/docs/configuration.md +328 -0
  60. package/dist/extensions/pi-subagents/docs/extension-api.md +308 -0
  61. package/dist/extensions/pi-subagents/docs/missions.md +119 -0
  62. package/dist/extensions/pi-subagents/docs/models.md +192 -0
  63. package/dist/extensions/pi-subagents/docs/observability.md +174 -0
  64. package/dist/extensions/pi-subagents/docs/tool-reference.md +343 -0
  65. package/dist/extensions/pi-subagents/docs/watchdog.md +176 -0
  66. package/dist/extensions/pi-subagents/docs/workflows.md +163 -0
  67. package/dist/extensions/pi-subagents/inspector-runner.mjs +11 -0
  68. package/dist/extensions/pi-subagents/package-lock.json +152 -194
  69. package/dist/extensions/pi-subagents/package.json +9 -10
  70. package/dist/extensions/pi-subagents/prompts/gather-context-and-clarify.md +1 -1
  71. package/dist/extensions/pi-subagents/prompts/parallel-cleanup.md +9 -9
  72. package/dist/extensions/pi-subagents/prompts/parallel-research.md +6 -6
  73. package/dist/extensions/pi-subagents/prompts/parallel-review.md +8 -8
  74. package/dist/extensions/pi-subagents/prompts/review-loop.md +12 -12
  75. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +22 -17
  76. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +77 -72
  77. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +177 -69
  78. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +28 -8
  79. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +88 -66
  80. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +3 -3
  81. package/dist/extensions/pi-subagents/src/agents/agent-refinements.ts +624 -0
  82. package/dist/extensions/pi-subagents/src/agents/agents.ts +29 -16
  83. package/dist/extensions/pi-subagents/src/agents/frontmatter.ts +7 -3
  84. package/dist/extensions/pi-subagents/src/agents/proactive-skills.ts +2 -2
  85. package/dist/extensions/pi-subagents/src/agents/skills.ts +2 -9
  86. package/dist/extensions/pi-subagents/src/api/delegation.ts +1 -2
  87. package/dist/extensions/pi-subagents/src/api/project-panes.ts +30 -0
  88. package/dist/extensions/pi-subagents/src/extension/config.ts +56 -8
  89. package/dist/extensions/pi-subagents/src/extension/control-notices.ts +2 -2
  90. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +51 -26
  91. package/dist/extensions/pi-subagents/src/extension/index.ts +119 -50
  92. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +72 -0
  93. package/dist/extensions/pi-subagents/src/extension/rpc.ts +15 -15
  94. package/dist/extensions/pi-subagents/src/extension/schemas.ts +58 -21
  95. package/dist/extensions/pi-subagents/src/extension/subagent-guide.ts +39 -0
  96. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +47 -25
  97. package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +3 -3
  98. package/dist/extensions/pi-subagents/src/inspectors/herdr/project-panes.ts +460 -64
  99. package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +102 -4
  100. package/dist/extensions/pi-subagents/src/missions/actions.ts +77 -16
  101. package/dist/extensions/pi-subagents/src/missions/goal-driver.ts +162 -0
  102. package/dist/extensions/pi-subagents/src/missions/lifecycle.ts +65 -14
  103. package/dist/extensions/pi-subagents/src/missions/store.ts +147 -5
  104. package/dist/extensions/pi-subagents/src/missions/types.ts +58 -3
  105. package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +256 -0
  106. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +8 -8
  107. package/dist/extensions/pi-subagents/src/runs/background/active-run-index.ts +42 -0
  108. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +41 -7
  109. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +294 -134
  110. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +19 -3
  111. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +39 -6
  112. package/dist/extensions/pi-subagents/src/runs/background/completion-replay.ts +267 -0
  113. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +145 -60
  114. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +114 -6
  115. package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +33 -0
  116. package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +68 -0
  117. package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +71 -0
  118. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +21 -2
  119. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +42 -14
  120. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +12 -24
  121. package/dist/extensions/pi-subagents/src/runs/background/steering.ts +7 -5
  122. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +152 -68
  123. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +17 -4
  124. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +146 -0
  125. package/dist/extensions/pi-subagents/src/runs/background/wait-subscriptions.ts +21 -5
  126. package/dist/extensions/pi-subagents/src/runs/foreground/async-dismiss-action.ts +85 -0
  127. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +43 -18
  128. package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +20 -19
  129. package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +3 -0
  130. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +55 -26
  131. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +137 -0
  132. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +798 -112
  133. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +187 -0
  134. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +165 -22
  135. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +1 -1
  136. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +2 -0
  137. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +9 -5
  138. package/dist/extensions/pi-subagents/src/runs/shared/model-scope.ts +12 -2
  139. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +1 -0
  140. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +465 -116
  141. package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +10 -10
  142. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +189 -32
  143. package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +2 -2
  144. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +3 -3
  145. package/dist/extensions/pi-subagents/src/shared/artifacts.ts +128 -3
  146. package/dist/extensions/pi-subagents/src/shared/display-text.ts +100 -0
  147. package/dist/extensions/pi-subagents/src/shared/file-coalescer.ts +9 -0
  148. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +13 -0
  149. package/dist/extensions/pi-subagents/src/shared/formatters.ts +4 -6
  150. package/dist/extensions/pi-subagents/src/shared/prompt-resources.ts +51 -0
  151. package/dist/extensions/pi-subagents/src/shared/settings.ts +41 -11
  152. package/dist/extensions/pi-subagents/src/shared/types.ts +100 -3
  153. package/dist/extensions/pi-subagents/src/shared/utf8.ts +11 -0
  154. package/dist/extensions/pi-subagents/src/shared/utils.ts +43 -33
  155. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +1 -14
  156. package/dist/extensions/pi-subagents/src/slash/inline-subagents.ts +1 -1
  157. package/dist/extensions/pi-subagents/src/slash/prompt-template-bridge.ts +14 -12
  158. package/dist/extensions/pi-subagents/src/slash/prompt-workflows.ts +176 -21
  159. package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +12 -6
  160. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +52 -18
  161. package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +36 -5
  162. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +30 -16
  163. package/dist/extensions/pi-subagents/src/tui/fleet.ts +151 -31
  164. package/dist/extensions/pi-subagents/src/tui/render.ts +201 -68
  165. package/dist/extensions/pi-subagents/src/types/pi-runtime-compat.d.ts +0 -6
  166. package/dist/extensions/pi-subagents/src/watchdog/change-signature.ts +5 -4
  167. package/dist/extensions/pi-subagents/src/watchdog/lsp-diagnostics.ts +0 -1
  168. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +313 -25
  169. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +15 -15
  170. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/cli.d.ts +3 -0
  171. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/register-bedrock.d.ts +2 -0
  172. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/restore-sandbox-env.d.ts +17 -0
  173. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/args.d.ts +57 -0
  174. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/config-selector.d.ts +16 -0
  175. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/file-processor.d.ts +15 -0
  176. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/initial-message.d.ts +18 -0
  177. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/list-models.d.ts +9 -0
  178. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/project-trust.d.ts +10 -0
  179. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/session-picker.d.ts +10 -0
  180. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/startup-ui.d.ts +20 -0
  181. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli.d.ts +3 -0
  182. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/config.d.ts +96 -0
  183. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-runtime.d.ts +119 -0
  184. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-services.d.ts +85 -0
  185. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session.d.ts +620 -0
  186. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-guidance.d.ts +5 -0
  187. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-storage.d.ts +56 -0
  188. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/bash-executor.d.ts +32 -0
  189. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/cache-stats.d.ts +49 -0
  190. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/branch-summarization.d.ts +93 -0
  191. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/compaction.d.ts +128 -0
  192. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/index.d.ts +7 -0
  193. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/utils.d.ts +38 -0
  194. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/defaults.d.ts +3 -0
  195. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/diagnostics.d.ts +15 -0
  196. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/event-bus.d.ts +9 -0
  197. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/exec.d.ts +29 -0
  198. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/experimental.d.ts +2 -0
  199. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/ansi-to-html.d.ts +22 -0
  200. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/index.d.ts +37 -0
  201. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/tool-renderer.d.ts +34 -0
  202. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/index.d.ts +12 -0
  203. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/loader.d.ts +23 -0
  204. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/runner.d.ts +171 -0
  205. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/types.d.ts +1261 -0
  206. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/wrapper.d.ts +20 -0
  207. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/footer-data-provider.d.ts +54 -0
  208. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/http-dispatcher.d.ts +22 -0
  209. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/index.d.ts +13 -0
  210. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/keybindings.d.ts +358 -0
  211. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/messages.d.ts +77 -0
  212. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-config.d.ts +512 -0
  213. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-registry.d.ts +43 -0
  214. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-resolver.d.ts +121 -0
  215. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-runtime.d.ts +82 -0
  216. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/models-store.d.ts +17 -0
  217. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/output-guard.d.ts +7 -0
  218. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/package-manager.d.ts +210 -0
  219. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/project-trust.d.ts +15 -0
  220. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/prompt-templates.d.ts +54 -0
  221. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-attribution.d.ts +4 -0
  222. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-composer.d.ts +55 -0
  223. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/radius.d.ts +2 -0
  224. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/remote-catalog-provider.d.ts +5 -0
  225. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resolve-config-value.d.ts +30 -0
  226. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resource-loader.d.ts +206 -0
  227. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/runtime-credentials.d.ts +15 -0
  228. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/sdk.d.ts +106 -0
  229. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-cwd.d.ts +19 -0
  230. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-manager.d.ts +356 -0
  231. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/settings-manager.d.ts +297 -0
  232. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/skills.d.ts +60 -0
  233. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/slash-commands.d.ts +15 -0
  234. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/source-info.d.ts +18 -0
  235. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/system-prompt.d.ts +28 -0
  236. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/telemetry.d.ts +3 -0
  237. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/timings.d.ts +10 -0
  238. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/bash.d.ts +68 -0
  239. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit-diff.d.ts +106 -0
  240. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit.d.ts +51 -0
  241. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/file-mutation-queue.d.ts +6 -0
  242. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/find.d.ts +35 -0
  243. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/grep.d.ts +37 -0
  244. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/index.d.ts +40 -0
  245. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/ls.d.ts +37 -0
  246. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/output-accumulator.d.ts +52 -0
  247. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/path-utils.d.ts +10 -0
  248. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/read.d.ts +35 -0
  249. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/render-utils.d.ts +24 -0
  250. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
  251. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/truncate.d.ts +70 -0
  252. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/write.d.ts +26 -0
  253. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/trust-manager.d.ts +36 -0
  254. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/usage-totals.d.ts +19 -0
  255. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/index.d.ts +3 -0
  256. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/client.d.ts +61 -0
  257. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/huggingface.d.ts +23 -0
  258. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/index.d.ts +3 -0
  259. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/provider.d.ts +10 -0
  260. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/ui.d.ts +42 -0
  261. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/index.d.ts +35 -0
  262. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/main.d.ts +12 -0
  263. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/migrations.d.ts +33 -0
  264. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/index.d.ts +9 -0
  265. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/armin.d.ts +34 -0
  266. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/assistant-message.d.ts +22 -0
  267. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bash-execution.d.ts +34 -0
  268. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
  269. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
  270. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
  271. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/config-selector.d.ts +102 -0
  272. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
  273. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-editor.d.ts +21 -0
  274. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-entry.d.ts +19 -0
  275. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-message.d.ts +20 -0
  276. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/daxnuts.d.ts +23 -0
  277. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/diff.d.ts +12 -0
  278. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
  279. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
  280. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-editor.d.ts +22 -0
  281. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-input.d.ts +23 -0
  282. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-selector.d.ts +26 -0
  283. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/first-time-setup.d.ts +25 -0
  284. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/footer.d.ts +32 -0
  285. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/index.d.ts +34 -0
  286. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/keybinding-hints.d.ts +13 -0
  287. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/login-dialog.d.ts +52 -0
  288. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/model-selector.d.ts +54 -0
  289. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/oauth-selector.d.ts +33 -0
  290. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/scoped-models-selector.d.ts +42 -0
  291. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
  292. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector.d.ts +95 -0
  293. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/settings-selector.d.ts +77 -0
  294. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
  295. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
  296. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/status-indicator.d.ts +28 -0
  297. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/theme-selector.d.ts +11 -0
  298. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
  299. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tool-execution.d.ts +63 -0
  300. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tree-selector.d.ts +94 -0
  301. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/trust-selector.d.ts +23 -0
  302. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
  303. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message.d.ts +14 -0
  304. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
  305. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/interactive-mode.d.ts +394 -0
  306. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/model-search.d.ts +12 -0
  307. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme-controller.d.ts +29 -0
  308. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme.d.ts +120 -0
  309. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/print-mode.d.ts +28 -0
  310. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/jsonl.d.ts +17 -0
  311. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-client.d.ts +246 -0
  312. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-mode.d.ts +20 -0
  313. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-types.d.ts +457 -0
  314. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/package-manager-cli.d.ts +8 -0
  315. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/rpc-entry.d.ts +3 -0
  316. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/ansi.d.ts +2 -0
  317. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/changelog.d.ts +22 -0
  318. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/child-process.d.ts +18 -0
  319. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-image.d.ts +11 -0
  320. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-native.d.ts +11 -0
  321. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard.d.ts +4 -0
  322. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/deprecation.d.ts +4 -0
  323. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/exif-orientation.d.ts +5 -0
  324. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/frontmatter.d.ts +8 -0
  325. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/fs-watch.d.ts +5 -0
  326. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/git.d.ts +26 -0
  327. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/html.d.ts +7 -0
  328. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-convert.d.ts +10 -0
  329. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-process.d.ts +18 -0
  330. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-core.d.ts +30 -0
  331. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-worker.d.ts +2 -0
  332. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize.d.ts +16 -0
  333. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/json.d.ts +3 -0
  334. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/mime.d.ts +3 -0
  335. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/open-browser.d.ts +9 -0
  336. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/paths.d.ts +31 -0
  337. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/photon.d.ts +21 -0
  338. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/pi-user-agent.d.ts +2 -0
  339. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/shell.d.ts +31 -0
  340. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/sleep.d.ts +5 -0
  341. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/syntax-highlight.d.ts +12 -0
  342. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/tools-manager.d.ts +3 -0
  343. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/version-check.d.ts +15 -0
  344. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/windows-self-update.d.ts +3 -0
  345. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/index.mjs +84 -0
  346. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/package.json +14 -0
  347. package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +15 -15
  348. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +411 -300
  349. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +309 -123
  350. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +99 -56
  351. package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +62 -16
  352. package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +159 -108
  353. package/dist/extensions/pi-subagents/test/integration/detect-error.test.ts +1 -1
  354. package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +4 -2
  355. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +56 -56
  356. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +114 -45
  357. package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +57 -19
  358. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +106 -106
  359. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +416 -106
  360. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +287 -17
  361. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +809 -87
  362. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +107 -20
  363. package/dist/extensions/pi-subagents/test/integration/slash-live-state.test.ts +9 -9
  364. package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +26 -6
  365. package/dist/extensions/pi-subagents/test/integration/top-level-async.test.ts +2 -2
  366. package/dist/extensions/pi-subagents/test/support/helpers.ts +2 -0
  367. package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +1 -1
  368. package/dist/extensions/pi-subagents/test/support/ts-loader.mjs +0 -8
  369. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +163 -58
  370. package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +15 -15
  371. package/dist/extensions/pi-subagents/test/unit/agent-eject-disable.test.ts +66 -66
  372. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +334 -248
  373. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +52 -52
  374. package/dist/extensions/pi-subagents/test/unit/agent-memory.test.ts +26 -26
  375. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +99 -99
  376. package/dist/extensions/pi-subagents/test/unit/agent-refinements.test.ts +160 -0
  377. package/dist/extensions/pi-subagents/test/unit/agent-selection.test.ts +9 -9
  378. package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +43 -1
  379. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +36 -10
  380. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +387 -30
  381. package/dist/extensions/pi-subagents/test/unit/async-permission-session.test.ts +9 -9
  382. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +2 -2
  383. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +94 -40
  384. package/dist/extensions/pi-subagents/test/unit/background-work.test.ts +5 -3
  385. package/dist/extensions/pi-subagents/test/unit/builtin-agent-documentation.test.ts +7 -7
  386. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +19 -19
  387. package/dist/extensions/pi-subagents/test/unit/chain-append.test.ts +19 -19
  388. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +9 -9
  389. package/dist/extensions/pi-subagents/test/unit/chain-serializer.test.ts +20 -20
  390. package/dist/extensions/pi-subagents/test/unit/child-transcript.test.ts +9 -9
  391. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +35 -5
  392. package/dist/extensions/pi-subagents/test/unit/completion-dedupe.test.ts +2 -2
  393. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +52 -52
  394. package/dist/extensions/pi-subagents/test/unit/completion-replay.test.ts +187 -0
  395. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +125 -71
  396. package/dist/extensions/pi-subagents/test/unit/control-notices.test.ts +18 -3
  397. package/dist/extensions/pi-subagents/test/unit/default-extensions.test.ts +12 -12
  398. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +17 -23
  399. package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +1 -1
  400. package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +25 -25
  401. package/dist/extensions/pi-subagents/test/unit/extra-agent-dirs.test.ts +3 -3
  402. package/dist/extensions/pi-subagents/test/unit/file-coalescer.test.ts +15 -0
  403. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +62 -44
  404. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +329 -37
  405. package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +4 -4
  406. package/dist/extensions/pi-subagents/test/unit/foreground-tool-call-compaction.test.ts +37 -0
  407. package/dist/extensions/pi-subagents/test/unit/herdr-inspector-bootstrap.test.ts +69 -0
  408. package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +79 -2
  409. package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +102 -49
  410. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +98 -32
  411. package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +5 -5
  412. package/dist/extensions/pi-subagents/test/unit/mission-goal-driver.test.ts +116 -0
  413. package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +55 -7
  414. package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +289 -13
  415. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +28 -1
  416. package/dist/extensions/pi-subagents/test/unit/model-scope-settings.test.ts +2 -2
  417. package/dist/extensions/pi-subagents/test/unit/model-scope.test.ts +11 -2
  418. package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +84 -10
  419. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +122 -8
  420. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +8 -8
  421. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +24 -24
  422. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +16 -2
  423. package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +7 -7
  424. package/dist/extensions/pi-subagents/test/unit/parallel-utils.test.ts +10 -10
  425. package/dist/extensions/pi-subagents/test/unit/path-handling.test.ts +3 -3
  426. package/dist/extensions/pi-subagents/test/unit/path-resolution.test.ts +26 -17
  427. package/dist/extensions/pi-subagents/test/unit/pi-args-permission-system.test.ts +405 -0
  428. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +357 -92
  429. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +22 -6
  430. package/dist/extensions/pi-subagents/test/unit/pi-spawn.test.ts +6 -6
  431. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +43 -43
  432. package/dist/extensions/pi-subagents/test/unit/proactive-skills.test.ts +13 -13
  433. package/dist/extensions/pi-subagents/test/unit/process-terminal.test.ts +4 -4
  434. package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +19 -19
  435. package/dist/extensions/pi-subagents/test/unit/project-panes-public-api.test.ts +243 -0
  436. package/dist/extensions/pi-subagents/test/unit/prompt-template-bridge.test.ts +68 -168
  437. package/dist/extensions/pi-subagents/test/unit/prompt-workflows.test.ts +58 -15
  438. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +40 -0
  439. package/dist/extensions/pi-subagents/test/unit/reads-resolution.test.ts +66 -0
  440. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +47 -28
  441. package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +12 -12
  442. package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +57 -0
  443. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +107 -27
  444. package/dist/extensions/pi-subagents/test/unit/run-id-resolver.test.ts +1 -1
  445. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +56 -50
  446. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +69 -28
  447. package/dist/extensions/pi-subagents/test/unit/scheduled-store-root.test.ts +67 -0
  448. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +59 -44
  449. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +424 -49
  450. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +23 -1
  451. package/dist/extensions/pi-subagents/test/unit/slash-bridge.test.ts +32 -5
  452. package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +13 -13
  453. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +120 -91
  454. package/dist/extensions/pi-subagents/test/unit/steering.test.ts +2 -2
  455. package/dist/extensions/pi-subagents/test/unit/subagent-action-recovery.test.ts +85 -0
  456. package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +35 -35
  457. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +24 -0
  458. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +312 -22
  459. package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +150 -15
  460. package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +26 -26
  461. package/dist/extensions/pi-subagents/test/unit/timeout-defaults.test.ts +73 -0
  462. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +76 -25
  463. package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +5 -5
  464. package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +55 -6
  465. package/dist/extensions/pi-subagents/test/unit/watchdog-child-status.test.ts +13 -13
  466. package/dist/extensions/pi-subagents/test/unit/watchdog-lsp-diagnostics.test.ts +1 -1
  467. package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +1 -1
  468. package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +8 -8
  469. package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +6 -6
  470. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +138 -11
  471. package/dist/extensions/pi-subagents/test/unit/workflow-graph.test.ts +8 -8
  472. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +113 -0
  473. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +7 -7
  474. package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +6 -6
  475. package/dist/extensions/workflow/extension.ts +21 -19
  476. package/dist/extensions/workflow/modes.ts +65 -0
  477. package/dist/skills/pi-subagents/SKILL.md +20 -15
  478. package/dist/skills/pi-subagents/references/constraints-and-recipes.md +77 -83
  479. package/dist/skills/pi-subagents/references/execution-controls.md +215 -106
  480. package/dist/skills/pi-subagents/references/management-authoring-rpc.md +29 -9
  481. package/dist/skills/pi-subagents/references/prompting-and-roles.md +58 -43
  482. package/docs/plans/workflow-autoloop-reference.md +192 -0
  483. package/docs/plans/workflow-subagent-consolidation-planb.md +374 -0
  484. package/docs/plans/workflow-subagent-scripted-merge.md +406 -0
  485. package/package.json +1 -1
  486. package/dist/extensions/workflow/adapter.ts +0 -949
  487. package/dist/extensions/workflow/modes/loop.ts +0 -74
  488. package/dist/extensions/workflow/modes/prototype.ts +0 -170
  489. package/dist/extensions/workflow/modes/quicktype.ts +0 -150
  490. package/dist/extensions/workflow/modes/task.ts +0 -105
  491. package/dist/extensions/workflow/run-state.ts +0 -124
  492. package/dist/extensions/workflow/state-machine.ts +0 -484
  493. package/dist/extensions/workflow/validators.ts +0 -42
@@ -0,0 +1,187 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import type { AgentToolResult } from "@earendil-works/pi-agent-core";
5
+ import type { Details, ForegroundRunControl, SubagentState } from "../../shared/types.ts";
6
+ import { readStatus } from "../../shared/utils.ts";
7
+ import {
8
+ consumeSteerAckFromDir,
9
+ readSteerCapability,
10
+ steerAcksDir,
11
+ steerCapabilityPath,
12
+ stepSteerInboxDir,
13
+ writeSteerRequestToExistingDir,
14
+ type SteerDeliveryMode,
15
+ type SteerRequest,
16
+ } from "../background/control-channel.ts";
17
+
18
+ export interface WorkflowForegroundSteeringTarget {
19
+ control: ForegroundRunControl;
20
+ workflowRunId: string;
21
+ sourceRunId: string;
22
+ }
23
+
24
+ export type WorkflowForegroundSteeringResolution =
25
+ | { ok: true; target: WorkflowForegroundSteeringTarget }
26
+ | { ok: false; message: string };
27
+
28
+ function activeWorkflowError(state: SubagentState, workflowRunId: string, asyncDirRoot: string): string | undefined {
29
+ if (!state.currentSessionId) return "Workflow steering requires an active parent session.";
30
+ if (!state.workflowControllers?.has(workflowRunId)) return `Workflow '${workflowRunId}' has no live foreground child.`;
31
+ const status = readStatus(path.join(asyncDirRoot, workflowRunId));
32
+ if (!status || status.mode !== "workflow" || (status.state !== "running" && status.state !== "queued")) {
33
+ return `Workflow '${workflowRunId}' has no live foreground child.`;
34
+ }
35
+ if (status.sessionId !== state.currentSessionId) return `Workflow '${workflowRunId}' was not found in the active session.`;
36
+ return undefined;
37
+ }
38
+
39
+ function controlIsLiveInWorkflow(control: ForegroundRunControl, workflowRunId: string, sessionId: string): boolean {
40
+ return control.parentWorkflowRunId === workflowRunId
41
+ && control.sessionId === sessionId
42
+ && Boolean(control.workflowSteeringDir)
43
+ && (control.activeChildren?.size ?? 0) > 0;
44
+ }
45
+
46
+ export function resolveWorkflowForegroundSteeringTarget(input: {
47
+ state: SubagentState;
48
+ childRunId?: string;
49
+ workflowRunId?: string;
50
+ asyncDirRoot: string;
51
+ }): WorkflowForegroundSteeringResolution {
52
+ const { state, childRunId, asyncDirRoot } = input;
53
+ if (childRunId) {
54
+ const control = state.foregroundControls.get(childRunId);
55
+ if (!control?.parentWorkflowRunId) return { ok: false, message: `Foreground run '${childRunId}' is not a live workflow-owned child.` };
56
+ const workflowRunId = control.parentWorkflowRunId;
57
+ const workflowError = activeWorkflowError(state, workflowRunId, asyncDirRoot);
58
+ if (workflowError) return { ok: false, message: workflowError };
59
+ if (!controlIsLiveInWorkflow(control, workflowRunId, state.currentSessionId!)) {
60
+ return { ok: false, message: `Foreground run '${childRunId}' is not a live workflow-owned child in the active session.` };
61
+ }
62
+ return { ok: true, target: { control, workflowRunId, sourceRunId: childRunId } };
63
+ }
64
+
65
+ const workflowRunId = input.workflowRunId;
66
+ if (!workflowRunId) return { ok: false, message: "Workflow steering requires a workflow or child run id." };
67
+ const workflowError = activeWorkflowError(state, workflowRunId, asyncDirRoot);
68
+ if (workflowError) return { ok: false, message: workflowError };
69
+ const controls = [...state.foregroundControls.values()].filter((control) => controlIsLiveInWorkflow(control, workflowRunId, state.currentSessionId!));
70
+ if (controls.length === 0) return { ok: false, message: `Workflow '${workflowRunId}' has no live foreground child.` };
71
+ if (controls.length > 1) return { ok: false, message: `Workflow '${workflowRunId}' has ${controls.length} live foreground children; steer a child run id instead.` };
72
+ return { ok: true, target: { control: controls[0]!, workflowRunId, sourceRunId: workflowRunId } };
73
+ }
74
+
75
+ function managementError(message: string): AgentToolResult<Details> {
76
+ return { content: [{ type: "text", text: message }], isError: true, details: { mode: "management", results: [] } };
77
+ }
78
+
79
+ export async function steerWorkflowForegroundTarget(input: {
80
+ target: WorkflowForegroundSteeringTarget;
81
+ message: string;
82
+ mode?: SteerDeliveryMode;
83
+ index?: number;
84
+ signal?: AbortSignal;
85
+ ackTimeoutMs?: number;
86
+ }): Promise<AgentToolResult<Details>> {
87
+ const { control, sourceRunId } = input.target;
88
+ const routeDir = control.workflowSteeringDir;
89
+ if (!routeDir || !fs.existsSync(routeDir)) return managementError(`Foreground run '${control.runId}' has no live workflow steering route.`);
90
+ const activeIndexes = [...(control.activeChildren?.keys() ?? [])].sort((left, right) => left - right);
91
+ const index = input.index ?? (activeIndexes.length === 1 ? activeIndexes[0] : undefined);
92
+ if (index === undefined) {
93
+ return managementError(activeIndexes.length === 0
94
+ ? `Foreground run '${control.runId}' has no live child session.`
95
+ : `Foreground run '${control.runId}' has ${activeIndexes.length} live child sessions; provide index.`);
96
+ }
97
+ if (!activeIndexes.includes(index)) return managementError(`Foreground run '${control.runId}' child ${index} is not live.`);
98
+ const capability = readSteerCapability(routeDir, index);
99
+ if (capability?.supported === false) return managementError(`Foreground run '${control.runId}' child ${index} does not support steering.`);
100
+
101
+ const request: SteerRequest = {
102
+ type: "steer",
103
+ id: randomUUID(),
104
+ ts: Date.now(),
105
+ message: input.message.trim(),
106
+ ...(input.mode && input.mode !== "steer" ? { mode: input.mode } : {}),
107
+ targetIndex: index,
108
+ source: "steer-action",
109
+ };
110
+ try {
111
+ writeSteerRequestToExistingDir(stepSteerInboxDir(routeDir, index), request);
112
+ } catch (error) {
113
+ if (typeof error === "object" && error !== null && "code" in error && (error as NodeJS.ErrnoException).code === "ENOENT") {
114
+ return managementError(`Foreground run '${control.runId}' has no live workflow steering route.`);
115
+ }
116
+ return managementError(`Failed to queue steering for foreground run ${control.runId}: ${error instanceof Error ? error.message : String(error)}`);
117
+ }
118
+
119
+ const deadline = Date.now() + (input.ackTimeoutMs ?? 3_000);
120
+ let ack;
121
+ let routeRemoved = false;
122
+ while (Date.now() <= deadline) {
123
+ ack = consumeSteerAckFromDir(steerAcksDir(routeDir, index), request.id);
124
+ if (ack || input.signal?.aborted) break;
125
+ if (!fs.existsSync(routeDir)) {
126
+ routeRemoved = true;
127
+ break;
128
+ }
129
+ await new Promise<void>((resolve) => setTimeout(resolve, Math.min(50, Math.max(1, deadline - Date.now()))));
130
+ }
131
+ if (routeRemoved || (!ack && !input.signal?.aborted && !fs.existsSync(routeDir))) {
132
+ return managementError(`Foreground run '${control.runId}' has no live child session.`);
133
+ }
134
+ const target = ack?.state === "delivered"
135
+ ? { index, state: "delivered" as const, deliveredAt: ack.ts }
136
+ : ack?.state === "queued"
137
+ ? { index, state: "queued" as const }
138
+ : ack?.state === "failed"
139
+ ? { index, state: "failed" as const, reason: ack.message }
140
+ : { index, state: "pending" as const };
141
+ const steering = {
142
+ requestId: request.id,
143
+ state: ack?.state === "delivered" ? "delivered" as const : ack?.state === "failed" ? "failed" as const : "pending" as const,
144
+ deliveryStatus: ack?.state === "delivered" ? "delivered" as const : "queued" as const,
145
+ sourceRunId,
146
+ targets: [target],
147
+ };
148
+ if (input.signal?.aborted) {
149
+ return { content: [{ type: "text", text: `Steering pending for foreground run ${control.runId} (request ${request.id}); caller aborted before acknowledgment.` }], details: { mode: "management", results: [], steering } };
150
+ }
151
+ if (ack?.state === "delivered") {
152
+ return { content: [{ type: "text", text: `Steering delivered for foreground run ${control.runId} (request ${request.id}).` }], details: { mode: "management", results: [], steering } };
153
+ }
154
+ if (ack?.state === "queued") {
155
+ return { content: [{ type: "text", text: `Steering queued for foreground run ${control.runId} (request ${request.id}).` }], details: { mode: "management", results: [], steering } };
156
+ }
157
+ if (ack?.state === "failed") {
158
+ return { content: [{ type: "text", text: `Steering failed for foreground run ${control.runId} (request ${request.id}): ${ack.message}` }], isError: true, details: { mode: "management", results: [], steering } };
159
+ }
160
+ return { content: [{ type: "text", text: `Steering pending for foreground run ${control.runId} (request ${request.id}); no acknowledgment was received.` }], details: { mode: "management", results: [], steering } };
161
+ }
162
+
163
+ export function workflowForegroundSteeringDir(asyncDirRoot: string, workflowRunId: string, childRunId: string): string {
164
+ return path.join(asyncDirRoot, workflowRunId, "control", "workflow-foreground", childRunId);
165
+ }
166
+
167
+ export function removeWorkflowForegroundSteeringRoute(control: ForegroundRunControl): void {
168
+ if (!control.workflowSteeringDir) return;
169
+ try {
170
+ fs.rmSync(control.workflowSteeringDir, { recursive: true, force: true });
171
+ } catch (error) {
172
+ console.warn(`[pi-subagents] Failed to remove workflow foreground steering route '${control.workflowSteeringDir}': ${error instanceof Error ? error.message : String(error)}`);
173
+ }
174
+ }
175
+
176
+ export function workflowForegroundSteeringLaunchOptions(control: ForegroundRunControl | undefined, index: number): Pick<import("../../shared/types.ts").RunSyncOptions, "steerInboxDir" | "steerCapabilityPath" | "steerAckDir"> {
177
+ if (!control?.workflowSteeringDir) return {};
178
+ const steerInboxDir = stepSteerInboxDir(control.workflowSteeringDir, index);
179
+ const steerAckDir = steerAcksDir(control.workflowSteeringDir, index);
180
+ fs.mkdirSync(steerInboxDir, { recursive: true });
181
+ fs.mkdirSync(steerAckDir, { recursive: true });
182
+ return {
183
+ steerInboxDir,
184
+ steerCapabilityPath: steerCapabilityPath(control.workflowSteeringDir, index),
185
+ steerAckDir,
186
+ };
187
+ }
@@ -1,5 +1,6 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { spawnSync } from "node:child_process";
3
+ import { createHash } from "node:crypto";
3
4
  import * as fs from "node:fs";
4
5
  import * as path from "node:path";
5
6
  import type {
@@ -50,7 +51,7 @@ const ACCEPTANCE_CONFIG_KEYS = new Set(["level", "criteria", "evidence", "verify
50
51
  const ACCEPTANCE_GATE_KEYS = new Set(["id", "must", "evidence", "severity"]);
51
52
  const ACCEPTANCE_VERIFY_KEYS = new Set(["id", "command", "timeoutMs", "cwd", "env", "allowFailure"]);
52
53
  const ACCEPTANCE_REVIEW_KEYS = new Set(["agent", "focus", "required"]);
53
- const EXPLICIT_REVIEWED_UNAVAILABLE = "is an achieved status, not a requestable acceptance level. For a read-only commentator call, omit acceptance. To require independent review of a writer result, use acceptance.review.required and orchestrate the commentator separately.";
54
+ const EXPLICIT_REVIEWED_UNAVAILABLE = "is an achieved status, not a requestable acceptance level. For a read-only reviewer call, omit acceptance. To require independent review of a writer result, use acceptance.review.required and orchestrate the reviewer separately.";
54
55
 
55
56
  function normalizeLevel(level: AcceptanceLevel | undefined): Exclude<AcceptanceLevel, "auto"> | "auto" {
56
57
  return level ?? "auto";
@@ -87,20 +88,18 @@ function inferLevel(input: {
87
88
  const reasons: string[] = [];
88
89
  // Declared roles replace name heuristics, so use the full writer grammar to detect explicit mutation independently of the actual agent name.
89
90
  const intent = classifyTaskMutationIntent(input.acceptanceRole ? "worker" : input.agentName, input.task ?? "");
90
- const taskMutation = taskMayMutate(input.task ?? "");
91
- const reviewerStyleAgent = /\b(?:commentator|reviewer|oracle|advisor)\b/.test(agent);
92
- const readOnlyTask = (intent.kind === "read-only" && (!taskMutation || reviewerStyleAgent))
93
- || (intent.kind === "unknown" && !taskMutation && /\b(?:read[- ]only|review[- ]only|no edits|without edits|inspect|summari[sz]e)\b/.test(task));
91
+ const readOnlyTask = intent.kind === "read-only"
92
+ || (intent.kind === "unknown" && /\b(?:read[- ]only|review[- ]only|no edits|without edits|inspect|summari[sz]e)\b/.test(task));
94
93
  const rolePatchTask = input.acceptanceRole !== undefined
95
94
  && intent.kind !== "read-only"
96
95
  && !/\b(?:do not|don't|must not)\s+patch\b/.test(task)
97
96
  && /\bpatch\s+(?:(?:\.{0,2}[\\/])?(?:[\w.-]+[\\/])+[\w.-]+|[\w.-]+\.[a-z0-9]+\b|(?:the\s+)?parser\b)/.test(task);
98
- const taskMayWrite = readOnlyTask ? false : taskMutation || intent.kind === "implementation" || rolePatchTask;
97
+ const taskMayWrite = readOnlyTask ? false : taskMayMutate(input.task ?? "") || intent.kind === "implementation" || rolePatchTask;
99
98
  const readOnlyAgent = input.acceptanceRole === "read-only"
100
- || (input.acceptanceRole === undefined && /\b(?:commentator|architect|explorer|recapper|researcher|reviewer|oracle|scout|context-builder|analyst)\b/.test(agent));
99
+ || (input.acceptanceRole === undefined && /\b(?:reviewer|oracle|scout|researcher|analyst)\b/.test(agent));
101
100
  const writeTask = taskMayWrite
102
101
  || (input.acceptanceRole === "writer" && !readOnlyTask)
103
- || (input.acceptanceRole === undefined && /\b(?:builder|worker)\b/.test(agent) && !readOnlyTask);
102
+ || (input.acceptanceRole === undefined && /\bworker\b/.test(agent) && !readOnlyTask);
104
103
  const inferredReadOnly = readOnlyTask || (input.acceptanceRole === "read-only" && !taskMayWrite);
105
104
  const roleResolvesReadOnly = input.acceptanceRole !== undefined && inferredReadOnly;
106
105
  const keywordRiskReadOnly = input.acceptanceRole === undefined ? intent.kind === "read-only" : inferredReadOnly;
@@ -117,11 +116,11 @@ function inferLevel(input: {
117
116
  reasons,
118
117
  criteria: ["Implement the requested change without widening scope", "Return evidence sufficient for an independent acceptance review"],
119
118
  evidence: requiredEvidenceForLevel("checked"),
120
- review: { agent: "commentator", required: true },
119
+ review: { agent: "reviewer", required: true },
121
120
  };
122
121
  }
123
122
  if (writeTask && !readOnlyTask) {
124
- reasons.push(input.acceptanceRole === "writer" && !taskMayWrite ? "declared writer acceptance role" : "write-capable builder/task");
123
+ reasons.push(input.acceptanceRole === "writer" && !taskMayWrite ? "declared writer acceptance role" : "write-capable worker/task");
125
124
  return {
126
125
  level: "checked",
127
126
  reasons,
@@ -130,7 +129,7 @@ function inferLevel(input: {
130
129
  };
131
130
  }
132
131
  if (readOnlyAgent || readOnlyTask) {
133
- reasons.push(input.acceptanceRole === "read-only" && !readOnlyTask ? "declared read-only acceptance role" : readOnlyAgent ? "read-only/commentator-style agent" : "read-only task wording");
132
+ reasons.push(input.acceptanceRole === "read-only" && !readOnlyTask ? "declared read-only acceptance role" : readOnlyAgent ? "read-only/reviewer-style agent" : "read-only task wording");
134
133
  return {
135
134
  level: "attested",
136
135
  reasons,
@@ -154,6 +153,17 @@ export function normalizeAcceptanceInput(input: AcceptanceInput | undefined): Ac
154
153
  return { ...input };
155
154
  }
156
155
 
156
+ type GateAcceptanceNormalizationResult =
157
+ | { ok: true; acceptance?: AcceptanceInput }
158
+ | { ok: false; error: string };
159
+
160
+ export function normalizeGateAcceptance(gate: unknown, acceptance: AcceptanceInput | undefined): GateAcceptanceNormalizationResult {
161
+ if (gate === undefined) return acceptance === undefined ? { ok: true } : { ok: true, acceptance };
162
+ if (typeof gate !== "string" || !gate.trim()) return { ok: false, error: "gate must be a non-empty command string." };
163
+ if (acceptance !== undefined) return { ok: false, error: "gate cannot be combined with acceptance; use one gate command or acceptance.verify." };
164
+ return { ok: true, acceptance: { level: "verified", verify: [{ id: "gate", command: gate.trim() }] } };
165
+ }
166
+
157
167
  function explicitAcceptanceCanDisable(explicit: AcceptanceConfig): boolean {
158
168
  return explicit.level === "none" && typeof explicit.reason === "string" && explicit.reason.trim().length > 0;
159
169
  }
@@ -171,7 +181,7 @@ export function validateAcceptanceInput(input: unknown, pathLabel = "acceptance"
171
181
  if (input === "reviewed") errors.push(`${pathLabel} ${EXPLICIT_REVIEWED_UNAVAILABLE}`);
172
182
  else if (!VALID_LEVELS.has(input as AcceptanceLevel)) errors.push(`${pathLabel} has invalid level '${input}'.`);
173
183
  else if (input === "none") errors.push(`${pathLabel} level "none" requires a reason; use { level: "none", reason: "..." }.`);
174
- else if (input === "verified") errors.push(`${pathLabel} level "verified" requires object form with at least one verify command.`);
184
+ else if (input === "verified") errors.push(`${pathLabel} level "verified" requires object form with at least one runtime verify command. Use level "checked" or provide a non-empty acceptance.verify array.`);
175
185
  return errors;
176
186
  }
177
187
  if (!input || typeof input !== "object" || Array.isArray(input)) {
@@ -236,7 +246,7 @@ export function validateAcceptanceInput(input: unknown, pathLabel = "acceptance"
236
246
  errors.push(`${pathLabel}.evidence must be an array. ${ACCEPTANCE_EVIDENCE_HELP}`);
237
247
  }
238
248
  if (value.level === "verified" && (!Array.isArray(value.verify) || value.verify.length === 0)) {
239
- errors.push(`${pathLabel}.verify must contain at least one command when level is verified.`);
249
+ errors.push(`${pathLabel}.verify must contain at least one runtime command when level is verified. Use level "checked" or provide a non-empty acceptance.verify array.`);
240
250
  } else if (value.verify !== undefined && !Array.isArray(value.verify)) {
241
251
  errors.push(`${pathLabel}.verify must be an array.`);
242
252
  }
@@ -927,7 +937,7 @@ function reportEvidenceStatus(report: AcceptanceReport, kind: AcceptanceEvidence
927
937
  }
928
938
 
929
939
  function checkNoStagedFiles(cwd: string): AcceptanceRuntimeCheck {
930
- const result = spawnSync("git", ["status", "--short"], { cwd, encoding: "utf-8", windowsHide: true });
940
+ const result = spawnSync("git", ["status", "--short"], { cwd, encoding: "utf-8" });
931
941
  if (result.status !== 0) {
932
942
  return { id: "no-staged-files", status: "not-applicable", message: "git status unavailable; no staged-files check skipped" };
933
943
  }
@@ -961,6 +971,28 @@ function trimOutput(value: string): string | undefined {
961
971
  return trimmed.length > 12_000 ? `${trimmed.slice(0, 12_000)}\n...[truncated]` : trimmed;
962
972
  }
963
973
 
974
+ const SENSITIVE_ENV_KEY_PATTERN = /(?:^|_)(?:TOKEN|SECRET|PASSWORD|PASS|AUTH|CREDENTIAL|COOKIE|SESSION|PRIVATE|API_KEY|ACCESS_KEY)(?:_|$)/i;
975
+
976
+ function effectiveVerifyEnv(env: Record<string, string> | undefined): Record<string, string> {
977
+ const inherited = Object.fromEntries(Object.entries(process.env).flatMap(([key, value]) => {
978
+ return typeof value === "string" ? [[key, value]] : [];
979
+ }));
980
+ return { ...inherited, ...(env ?? {}) };
981
+ }
982
+
983
+ function verifyRedactionEnv(env: Record<string, string> | undefined): Record<string, string> {
984
+ return Object.fromEntries(Object.entries(effectiveVerifyEnv(env)).filter(([key, value]) => {
985
+ return value.length >= 4 && SENSITIVE_ENV_KEY_PATTERN.test(key);
986
+ }));
987
+ }
988
+
989
+ function redactVerifyEnv(value: string, env: Record<string, string> | undefined): string {
990
+ let redacted = value;
991
+ const secrets = [...new Set(Object.values(verifyRedactionEnv(env)).filter(Boolean))].sort((left, right) => right.length - left.length);
992
+ for (const secret of secrets) redacted = redacted.replaceAll(secret, "[REDACTED]");
993
+ return redacted;
994
+ }
995
+
964
996
  function uniqueStrings(items: Array<string | undefined>): string[] {
965
997
  return unique(items.map((item) => item?.trim()).filter((item): item is string => Boolean(item)));
966
998
  }
@@ -997,6 +1029,108 @@ export function aggregateAcceptanceReport(input: {
997
1029
  };
998
1030
  }
999
1031
 
1032
+ const DEFAULT_VERIFY_TIMEOUT_MS = 120_000;
1033
+
1034
+ function hash(value: string): string {
1035
+ return createHash("sha256").update(value).digest("hex");
1036
+ }
1037
+
1038
+ interface VerifyWorkspaceState {
1039
+ kind: "git-tracked";
1040
+ repoRoot: string;
1041
+ cwdRelative: string;
1042
+ head: string;
1043
+ diffHash: string;
1044
+ }
1045
+
1046
+ function readVerifyWorkspaceState(cwd: string): VerifyWorkspaceState | undefined {
1047
+ const repo = spawnSync("git", ["rev-parse", "--show-toplevel"], { cwd, encoding: "utf-8" });
1048
+ if (repo.status !== 0 || !repo.stdout.trim()) return undefined;
1049
+ const repoRoot = fs.realpathSync(repo.stdout.trim());
1050
+ const head = spawnSync("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf-8" });
1051
+ const diff = spawnSync("git", ["diff", "--binary", "--full-index", "HEAD", "--"], { cwd: repoRoot, encoding: "utf-8", maxBuffer: 50 * 1024 * 1024 });
1052
+ if (head.status !== 0 || diff.status !== 0 || !head.stdout.trim()) return undefined;
1053
+ return {
1054
+ kind: "git-tracked",
1055
+ repoRoot,
1056
+ cwdRelative: path.relative(repoRoot, fs.realpathSync(cwd)) || ".",
1057
+ head: head.stdout.trim(),
1058
+ diffHash: hash(diff.stdout),
1059
+ };
1060
+ }
1061
+
1062
+ function isCachedVerifyResult(value: unknown): value is AcceptanceVerifyResult {
1063
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
1064
+ const result = value as Partial<AcceptanceVerifyResult>;
1065
+ return typeof result.id === "string"
1066
+ && typeof result.command === "string"
1067
+ && (typeof result.exitCode === "number" || result.exitCode === null)
1068
+ && (result.status === "passed" || result.status === "failed" || result.status === "timed-out" || result.status === "allowed-failure")
1069
+ && typeof result.durationMs === "number";
1070
+ }
1071
+
1072
+ async function runMemoizedVerifyCommand(command: AcceptanceVerifyCommand, defaultCwd: string, options: {
1073
+ signal?: AbortSignal;
1074
+ abortMessage?: string;
1075
+ artifactsDir?: string;
1076
+ runId?: string;
1077
+ } = {}): Promise<AcceptanceVerifyResult> {
1078
+ const cwd = command.cwd ? path.resolve(defaultCwd, command.cwd) : defaultCwd;
1079
+ let workspaceState: VerifyWorkspaceState | undefined;
1080
+ try {
1081
+ workspaceState = readVerifyWorkspaceState(cwd);
1082
+ } catch {
1083
+ workspaceState = undefined;
1084
+ }
1085
+ if (!workspaceState || !options.artifactsDir || !options.runId) {
1086
+ return runVerifyCommand(command, defaultCwd, options);
1087
+ }
1088
+ const envKeys = Object.keys(command.env ?? {}).sort();
1089
+ const envHash = hash(JSON.stringify(Object.fromEntries(Object.entries(effectiveVerifyEnv(command.env)).sort(([left], [right]) => left.localeCompare(right)))));
1090
+ const timeoutMs = command.timeoutMs ?? DEFAULT_VERIFY_TIMEOUT_MS;
1091
+ const cacheKey = hash(JSON.stringify({
1092
+ version: 1,
1093
+ command: command.command,
1094
+ cwdRelative: workspaceState.cwdRelative,
1095
+ envKeys,
1096
+ envHash,
1097
+ timeoutMs,
1098
+ allowFailure: command.allowFailure === true,
1099
+ head: workspaceState.head,
1100
+ diffHash: workspaceState.diffHash,
1101
+ }));
1102
+ const artifactPath = path.join(options.artifactsDir, "acceptance", "verify", options.runId, `${cacheKey}.json`);
1103
+ try {
1104
+ const cached = JSON.parse(fs.readFileSync(artifactPath, "utf-8")) as { cacheKey?: unknown; result?: unknown };
1105
+ if (cached.cacheKey === cacheKey && isCachedVerifyResult(cached.result)) {
1106
+ return { ...cached.result, id: command.id, command: command.command, cwd, artifactPath, cacheKey, memoized: true, envKeys, envHash, workspaceState };
1107
+ }
1108
+ } catch {
1109
+ // A cache miss or unreadable artifact must not prevent host verification.
1110
+ }
1111
+ const result = await runVerifyCommand(command, defaultCwd, options);
1112
+ const evidenced: AcceptanceVerifyResult = { ...result, artifactPath, cacheKey, memoized: false, envKeys, envHash, workspaceState };
1113
+ try {
1114
+ fs.mkdirSync(path.dirname(artifactPath), { recursive: true });
1115
+ fs.writeFileSync(artifactPath, JSON.stringify({
1116
+ version: 1,
1117
+ cacheKey,
1118
+ command: command.command,
1119
+ cwdRelative: workspaceState.cwdRelative,
1120
+ envKeys,
1121
+ envHash,
1122
+ timeoutMs,
1123
+ allowFailure: command.allowFailure === true,
1124
+ workspaceState,
1125
+ result: evidenced,
1126
+ }, null, 2), "utf-8");
1127
+ } catch (error) {
1128
+ evidenced.artifactError = error instanceof Error ? error.message : String(error);
1129
+ delete evidenced.artifactPath;
1130
+ }
1131
+ return evidenced;
1132
+ }
1133
+
1000
1134
  function runVerifyCommand(command: AcceptanceVerifyCommand, defaultCwd: string, options: { signal?: AbortSignal; abortMessage?: string } = {}): Promise<AcceptanceVerifyResult> {
1001
1135
  return new Promise((resolve) => {
1002
1136
  const startedAt = Date.now();
@@ -1008,7 +1142,7 @@ function runVerifyCommand(command: AcceptanceVerifyCommand, defaultCwd: string,
1008
1142
  let hardKill: NodeJS.Timeout | undefined;
1009
1143
  const child = spawn(command.command, {
1010
1144
  cwd,
1011
- env: { ...process.env, ...(command.env ?? {}) },
1145
+ env: effectiveVerifyEnv(command.env),
1012
1146
  shell: true,
1013
1147
  stdio: ["ignore", "pipe", "pipe"],
1014
1148
  windowsHide: true,
@@ -1036,13 +1170,13 @@ function runVerifyCommand(command: AcceptanceVerifyCommand, defaultCwd: string,
1036
1170
  finish({
1037
1171
  exitCode: null,
1038
1172
  status: "timed-out",
1039
- stdout: trimOutput(stdout),
1040
- stderr: trimOutput(stderr || options.abortMessage || "Acceptance verification timed out."),
1173
+ stdout: trimOutput(redactVerifyEnv(stdout, command.env)),
1174
+ stderr: trimOutput(redactVerifyEnv(stderr || options.abortMessage || "Acceptance verification timed out.", command.env)),
1041
1175
  });
1042
1176
  }, 1000);
1043
1177
  hardKill.unref?.();
1044
1178
  };
1045
- const timeout = setTimeout(abortVerification, command.timeoutMs ?? 120_000);
1179
+ const timeout = setTimeout(abortVerification, command.timeoutMs ?? DEFAULT_VERIFY_TIMEOUT_MS);
1046
1180
  timeout.unref?.();
1047
1181
  if (options.signal?.aborted) abortVerification();
1048
1182
  else options.signal?.addEventListener("abort", abortVerification, { once: true });
@@ -1057,15 +1191,17 @@ function runVerifyCommand(command: AcceptanceVerifyCommand, defaultCwd: string,
1057
1191
  finish({
1058
1192
  exitCode,
1059
1193
  status: timedOut ? "timed-out" : passed ? "passed" : command.allowFailure ? "allowed-failure" : "failed",
1060
- stdout: trimOutput(stdout),
1061
- stderr: trimOutput(stderr || (timedOut ? options.abortMessage ?? "" : "")),
1194
+ stdout: trimOutput(redactVerifyEnv(stdout, command.env)),
1195
+ stderr: trimOutput(redactVerifyEnv(stderr || (timedOut ? options.abortMessage ?? "" : ""), command.env)),
1062
1196
  });
1063
1197
  });
1064
1198
  child.on("error", (error) => {
1065
1199
  finish({
1066
1200
  exitCode: timedOut ? null : 1,
1067
1201
  status: timedOut ? "timed-out" : command.allowFailure ? "allowed-failure" : "failed",
1068
- stderr: timedOut ? trimOutput(stderr || options.abortMessage || "Acceptance verification timed out.") : error instanceof Error ? error.message : String(error),
1202
+ stderr: timedOut
1203
+ ? trimOutput(redactVerifyEnv(stderr || options.abortMessage || "Acceptance verification timed out.", command.env))
1204
+ : redactVerifyEnv(error instanceof Error ? error.message : String(error), command.env),
1069
1205
  });
1070
1206
  });
1071
1207
  });
@@ -1087,6 +1223,8 @@ export async function evaluateAcceptance(input: {
1087
1223
  signal?: AbortSignal;
1088
1224
  abortMessage?: string;
1089
1225
  reportOptional?: boolean;
1226
+ artifactsDir?: string;
1227
+ runId?: string;
1090
1228
  }): Promise<AcceptanceLedger> {
1091
1229
  const acceptance = input.acceptance;
1092
1230
  const initialStatus = acceptance.level === "none" ? "not-required" : "claimed";
@@ -1148,7 +1286,12 @@ export async function evaluateAcceptance(input: {
1148
1286
  }
1149
1287
  ledger.verifyRuns = [];
1150
1288
  for (const command of acceptance.verify) {
1151
- ledger.verifyRuns.push(await runVerifyCommand(command, input.cwd, { signal: input.signal, abortMessage: input.abortMessage }));
1289
+ ledger.verifyRuns.push(await runMemoizedVerifyCommand(command, input.cwd, {
1290
+ signal: input.signal,
1291
+ abortMessage: input.abortMessage,
1292
+ artifactsDir: input.artifactsDir,
1293
+ runId: input.runId,
1294
+ }));
1152
1295
  if (input.signal?.aborted) break;
1153
1296
  }
1154
1297
  if (ledger.verifyRuns.some((run) => run.status === "failed" || run.status === "timed-out")) {
@@ -49,7 +49,7 @@ const DYNAMIC_EXPAND_FROM_KEYS = new Set(["output", "path"]);
49
49
  const DYNAMIC_PARALLEL_KEYS = new Set(["agent", "task", "phase", "label", "outputSchema", "cwd", "output", "outputMode", "reads", "progress", "skill", "model", "toolBudget", "acceptance", "agentContract", "gateOn"]);
50
50
  const RUNNER_DYNAMIC_PARALLEL_KEYS = new Set([
51
51
  ...DYNAMIC_PARALLEL_KEYS,
52
- "outputName", "structured", "inheritProjectContext", "inheritSkills", "skills", "outputPath", "namespaceOutputPath", "maxSubagentDepth", "waitToolEnabled",
52
+ "outputName", "structured", "inheritProjectContext", "inheritSkills", "skills", "outputPath", "namespaceOutputPath", "maxSubagentDepth", "timeoutMs", "waitToolEnabled",
53
53
  "structuredOutput", "structuredOutputSchema", "tools", "extensions", "subagentOnlyExtensions", "mcpDirectTools", "capabilityCeiling", "completionGuard", "systemPrompt",
54
54
  "systemPromptMode", "thinking", "modelCandidates", "sessionFile", "effectiveAcceptance", "acceptanceInput", "acceptanceRole", "parentSessionId", "launchResolvedExtensions",
55
55
  ]);
@@ -38,6 +38,7 @@ interface ServerEntry {
38
38
  exposeResources?: boolean;
39
39
  includeTools?: string[];
40
40
  excludeTools?: string[];
41
+ protocolVersion?: string;
41
42
  directTools?: boolean | string[];
42
43
  }
43
44
 
@@ -284,6 +285,7 @@ export function computeMcpServerHash(definition: ServerEntry): string {
284
285
  exposeResources: definition.exposeResources,
285
286
  includeTools: definition.includeTools,
286
287
  excludeTools: definition.excludeTools,
288
+ protocolVersion: definition.protocolVersion,
287
289
  };
288
290
  return createHash("sha256").update(stableStringify(identity)).digest("hex");
289
291
  }
@@ -183,7 +183,7 @@ function defaultScopeWarn(violation: ModelScopeViolation): void {
183
183
  * sentinel), the child must inherit the parent session's *in-memory* model
184
184
  * (`provider/id`) instead of being left to resolve its own model. Without an
185
185
  * explicit `provider/id`, the child falls back to the global
186
- * `~/.selesai/agent/settings.json` default, which is shared across every open Selesai
186
+ * `~/.selesai/agent/settings.json` default, which is shared across every open PI
187
187
  * session — so a different session that last changed its model in the TUI would
188
188
  * silently contaminate this session's subagents (see issue #266). Passing an
189
189
  * explicit `provider/id` keeps each session's children isolated to that
@@ -191,7 +191,8 @@ function defaultScopeWarn(violation: ModelScopeViolation): void {
191
191
  *
192
192
  * An explicitly requested model string is resolved via {@link resolveModelCandidate}.
193
193
  * When `options.scope.enforce` is on, an out-of-scope resolved model throws for
194
- * an explicit (`source: "explicit"`) request and warns for an inherited one.
194
+ * an explicit (`source: "explicit"`) request and warns for an inherited one,
195
+ * unless strict scope enforcement makes inherited violations hard errors.
195
196
  */
196
197
  export function resolveSubagentModelOverride(
197
198
  requestedModel: string | boolean | undefined,
@@ -245,7 +246,7 @@ export function resolveEffectiveSubagentModel(
245
246
  }
246
247
 
247
248
  export interface BuildModelCandidatesOptions {
248
- /** Fallback models are inherited agent config and warn, rather than error, when out of scope. */
249
+ /** Fallback models warn by default and throw when strict scope enforcement is enabled. */
249
250
  scope?: ModelScopeConfig;
250
251
  onWarn?: (violation: ModelScopeViolation) => void;
251
252
  }
@@ -265,9 +266,12 @@ export function buildModelCandidates(
265
266
  if (!raw) continue;
266
267
  const normalized = resolveModelCandidate(raw.trim(), availableModels, preferredProvider);
267
268
  if (!normalized || seen.has(normalized)) continue;
268
- if (index > 0 && options?.scope?.enforce) {
269
+ if ((index > 0 || options?.scope?.strict === true) && options?.scope?.enforce) {
269
270
  const violation = checkModelScope(normalized, options.scope, "inherited");
270
- if (violation) (options.onWarn ?? defaultScopeWarn)(violation);
271
+ if (violation) {
272
+ if (violation.severity === "error") throw new Error(violation.message);
273
+ (options.onWarn ?? defaultScopeWarn)(violation);
274
+ }
271
275
  }
272
276
  seen.add(normalized);
273
277
  candidates.push(normalized);
@@ -6,7 +6,8 @@
6
6
  * where the model came from: an explicit caller-supplied model (`--model`,
7
7
  * tool-call `model`, or a TUI clarify pick) is a hard error, while a model
8
8
  * inherited from agent frontmatter / `defaultModel` / the parent session only
9
- * emits a warning so existing configurations keep working.
9
+ * emits a warning so existing configurations keep working. Optional strict
10
+ * enforcement makes inherited models hard errors too.
10
11
  *
11
12
  * The decision logic ({@link checkModelScope}) is a pure function of its
12
13
  * inputs so it can be unit-tested without touching the filesystem or config.
@@ -16,6 +17,8 @@ import { splitKnownThinkingSuffix } from "../../shared/model-info.ts";
16
17
 
17
18
  export interface ModelScopeConfig {
18
19
  enforce?: boolean;
20
+ /** Reject inherited and fallback models outside the allowlist instead of warning. */
21
+ strict?: boolean;
19
22
  /** Glob-style allow patterns (only `*` is special), matched against `provider/id`. */
20
23
  allow?: string[];
21
24
  }
@@ -67,7 +70,7 @@ export function checkModelScope(
67
70
  if (allow.some((pattern) => matchesScopePattern(model, pattern))) return undefined;
68
71
 
69
72
  const baseModel = stripThinkingSuffix(model);
70
- const severity: ModelScopeViolation["severity"] = source === "explicit" ? "error" : "warn";
73
+ const severity: ModelScopeViolation["severity"] = source === "explicit" || scope.strict === true ? "error" : "warn";
71
74
  return {
72
75
  model: baseModel,
73
76
  severity,
@@ -102,6 +105,13 @@ export function parseModelScopeConfig(
102
105
  config.enforce = input.enforce;
103
106
  }
104
107
 
108
+ if ("strict" in input) {
109
+ if (typeof input.strict !== "boolean") {
110
+ throw new Error(`Subagent settings in '${meta.filePath}' have invalid 'modelScope.strict'; expected a boolean.`);
111
+ }
112
+ config.strict = input.strict;
113
+ }
114
+
105
115
  if ("allow" in input) {
106
116
  if (!Array.isArray(input.allow)) {
107
117
  throw new Error(`Subagent settings in '${meta.filePath}' have invalid 'modelScope.allow'; expected an array of strings.`);
@@ -40,6 +40,7 @@ export interface RunnerSubagentStep {
40
40
  outputMode?: "inline" | "file-only";
41
41
  sessionFile?: string;
42
42
  maxSubagentDepth?: number;
43
+ timeoutMs?: number;
43
44
  waitToolEnabled?: boolean;
44
45
  structuredOutput?: {
45
46
  schema: import("../../shared/types.ts").JsonSchemaObject;