@selesai/code 0.9.10 → 0.9.12

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 (862) hide show
  1. package/CHANGELOG.md +271 -255
  2. package/dist/cli/args.js +13 -2
  3. package/dist/cli/args.test.js +8 -0
  4. package/dist/cli/credential-print.js +4 -4
  5. package/dist/cli.js +0 -0
  6. package/dist/config.d.ts +4 -6
  7. package/dist/config.js +10 -14
  8. package/dist/core/agent-session-auto-handoff.test.js +24 -1
  9. package/dist/core/agent-session.d.ts +10 -4
  10. package/dist/core/agent-session.js +61 -46
  11. package/dist/core/compaction/branch-summarization.js +30 -30
  12. package/dist/core/compaction/compaction.js +81 -81
  13. package/dist/core/compaction/utils.js +2 -2
  14. package/dist/core/defaults.d.ts +1 -0
  15. package/dist/core/defaults.js +9 -0
  16. package/dist/core/export-html/template.css +1066 -1066
  17. package/dist/core/export-html/template.html +55 -55
  18. package/dist/core/export-html/template.js +1864 -1864
  19. package/dist/core/export-html/vendor/highlight.min.js +1212 -1212
  20. package/dist/core/export-html/vendor/marked.min.js +78 -78
  21. package/dist/core/extensions/loader.js +108 -35
  22. package/dist/core/extensions/loader.test.js +21 -0
  23. package/dist/core/extensions/types.d.ts +12 -4
  24. package/dist/core/keybindings.d.ts +2 -2
  25. package/dist/core/messages.js +7 -7
  26. package/dist/core/model-resolver.d.ts +1 -0
  27. package/dist/core/model-resolver.js +10 -4
  28. package/dist/core/package-manager.js +4 -4
  29. package/dist/core/sdk.d.ts +5 -5
  30. package/dist/core/sdk.js +16 -4
  31. package/dist/core/settings-manager.d.ts +6 -2
  32. package/dist/core/settings-manager.js +22 -3
  33. package/dist/core/tools/bash.d.ts +18 -1
  34. package/dist/core/tools/bash.js +41 -23
  35. package/dist/core/tools/index.d.ts +4 -2
  36. package/dist/core/tools/index.js +9 -2
  37. package/dist/core/tools/powershell.d.ts +15 -0
  38. package/dist/core/tools/powershell.js +38 -0
  39. package/dist/core/tools/powershell.test.d.ts +1 -0
  40. package/dist/core/tools/powershell.test.js +20 -0
  41. package/dist/defaults/settings.json +0 -1
  42. package/dist/extensions/context-compaction-reminder.test.ts +82 -82
  43. package/dist/extensions/context-compaction-reminder.ts +28 -28
  44. package/dist/extensions/model-prompt-injector/index.test.ts +0 -10
  45. package/dist/extensions/model-prompt-injector/index.ts +0 -3
  46. package/dist/extensions/pi-intercom/CHANGELOG.md +53 -16
  47. package/dist/extensions/pi-intercom/LICENSE +21 -21
  48. package/dist/extensions/pi-intercom/README.md +41 -8
  49. package/dist/extensions/pi-intercom/banner.png +0 -0
  50. package/dist/extensions/pi-intercom/broker/broker.ts +498 -215
  51. package/dist/extensions/pi-intercom/broker/client.test.ts +83 -83
  52. package/dist/extensions/pi-intercom/broker/client.ts +39 -12
  53. package/dist/extensions/pi-intercom/broker/extension.test.ts +486 -387
  54. package/dist/extensions/pi-intercom/broker/framing.test.ts +114 -114
  55. package/dist/extensions/pi-intercom/broker/paths.test.ts +153 -153
  56. package/dist/extensions/pi-intercom/broker/paths.ts +134 -134
  57. package/dist/extensions/pi-intercom/broker/protocol.ts +26 -0
  58. package/dist/extensions/pi-intercom/broker/runtime-claim.test.ts +34 -34
  59. package/dist/extensions/pi-intercom/broker/runtime-claim.ts +21 -21
  60. package/dist/extensions/pi-intercom/broker/spawn.test.ts +5 -20
  61. package/dist/extensions/pi-intercom/config.test.ts +41 -0
  62. package/dist/extensions/pi-intercom/config.ts +21 -0
  63. package/dist/extensions/pi-intercom/cwd.test.ts +40 -40
  64. package/dist/extensions/pi-intercom/cwd.ts +31 -31
  65. package/dist/extensions/pi-intercom/extension-api.ts +84 -44
  66. package/dist/extensions/pi-intercom/format-context.test.ts +31 -31
  67. package/dist/extensions/pi-intercom/format-context.ts +32 -32
  68. package/dist/extensions/pi-intercom/index.ts +362 -26
  69. package/dist/extensions/pi-intercom/intercom.integration.test.ts +819 -13
  70. package/dist/extensions/pi-intercom/package.json +1 -1
  71. package/dist/extensions/pi-intercom/project-agent.ts +2 -2
  72. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +8 -110
  73. package/dist/extensions/pi-intercom/test/overlay-width.test.ts +66 -66
  74. package/dist/extensions/pi-intercom/types.ts +32 -5
  75. package/dist/extensions/pi-intercom/ui/compose.ts +143 -143
  76. package/dist/extensions/pi-intercom/ui/inline-message.ts +6 -0
  77. package/dist/extensions/pi-intercom/ui/session-list.ts +166 -166
  78. package/dist/extensions/pi-powerline-footer/bash-mode/shell-session.ts +286 -286
  79. package/dist/extensions/pi-powerline-footer/bash-mode/transcript.ts +108 -108
  80. package/dist/extensions/pi-powerline-footer/separators.ts +57 -57
  81. package/dist/extensions/pi-powerline-footer/tests/session-usage.test.ts +47 -47
  82. package/dist/extensions/pi-powerline-footer/tests/tps.test.ts +39 -39
  83. package/dist/extensions/pi-powerline-footer/theme.example.json +24 -24
  84. package/dist/extensions/pi-powerline-footer/theme.json +12 -12
  85. package/dist/extensions/pi-powerline-footer/tps.ts +345 -345
  86. package/dist/extensions/pi-rewind-hook/README.md +245 -245
  87. package/dist/extensions/pi-rewind-hook/index.ts +1445 -1445
  88. package/dist/extensions/pi-rewind-hook/package.json +29 -29
  89. package/dist/extensions/pi-subagents/.github/assets/subagent-fleet-inspector.png +0 -0
  90. package/dist/extensions/pi-subagents/.github/workflows/release.yml +28 -0
  91. package/dist/extensions/pi-subagents/.github/workflows/test.yml +51 -0
  92. package/dist/extensions/pi-subagents/.greptile/config.json +33 -0
  93. package/dist/extensions/pi-subagents/.greptile/files.json +8 -0
  94. package/dist/extensions/pi-subagents/.greptile/rules.md +16 -0
  95. package/dist/extensions/pi-subagents/CHANGELOG.md +309 -87
  96. package/dist/extensions/pi-subagents/README.md +15 -17
  97. package/dist/extensions/pi-subagents/agents/oracle.md +3 -1
  98. package/dist/extensions/pi-subagents/agents/researcher.md +32 -13
  99. package/dist/extensions/pi-subagents/agents/reviewer.md +13 -2
  100. package/dist/extensions/pi-subagents/agents/scout.md +2 -2
  101. package/dist/extensions/pi-subagents/agents/worker.md +2 -1
  102. package/dist/extensions/pi-subagents/async-retention-discovery-worker.mjs +180 -0
  103. package/dist/extensions/pi-subagents/docs/configuration.md +106 -27
  104. package/dist/extensions/pi-subagents/docs/extension-api.md +85 -21
  105. package/dist/extensions/pi-subagents/docs/missions.md +41 -4
  106. package/dist/extensions/pi-subagents/docs/models.md +52 -9
  107. package/dist/extensions/pi-subagents/docs/observability.md +103 -16
  108. package/dist/extensions/pi-subagents/docs/tool-reference.md +60 -45
  109. package/dist/extensions/pi-subagents/docs/watchdog.md +60 -3
  110. package/dist/extensions/pi-subagents/docs/workflows.md +181 -7
  111. package/dist/extensions/pi-subagents/index.ts +10 -1
  112. package/dist/extensions/pi-subagents/install.mjs +4 -4
  113. package/dist/extensions/pi-subagents/package-lock.json +1483 -1470
  114. package/dist/extensions/pi-subagents/package.json +6 -3
  115. package/dist/extensions/pi-subagents/prompts/council.md +60 -0
  116. package/dist/extensions/pi-subagents/prompts/parallel-review.md +5 -1
  117. package/dist/extensions/pi-subagents/prompts/review-loop.md +9 -5
  118. package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +254 -0
  119. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +18 -17
  120. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +31 -9
  121. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +107 -140
  122. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +9 -12
  123. package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +39 -0
  124. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +44 -92
  125. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +261 -368
  126. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +6 -2
  127. package/dist/extensions/pi-subagents/src/agents/agents.ts +388 -85
  128. package/dist/extensions/pi-subagents/src/agents/builtin-names.ts +14 -0
  129. package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +418 -0
  130. package/dist/extensions/pi-subagents/src/agents/skills.ts +1 -1
  131. package/dist/extensions/pi-subagents/src/api/agents.ts +7 -0
  132. package/dist/extensions/pi-subagents/src/api/external-job-provider.ts +195 -0
  133. package/dist/extensions/pi-subagents/src/api/preflight.ts +88 -27
  134. package/dist/extensions/pi-subagents/src/api/project-panes.ts +2 -0
  135. package/dist/extensions/pi-subagents/src/api/shared-types.ts +2 -0
  136. package/dist/extensions/pi-subagents/src/extension/config.ts +20 -11
  137. package/dist/extensions/pi-subagents/src/extension/doctor.ts +14 -6
  138. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +5 -4
  139. package/dist/extensions/pi-subagents/src/extension/index.ts +270 -187
  140. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +65 -28
  141. package/dist/extensions/pi-subagents/src/extension/rpc.ts +120 -11
  142. package/dist/extensions/pi-subagents/src/extension/schemas.ts +46 -64
  143. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +51 -37
  144. package/dist/extensions/pi-subagents/src/extension/tool-result.ts +19 -0
  145. package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +2 -2
  146. package/dist/extensions/pi-subagents/src/inspectors/herdr/client.ts +3 -3
  147. package/dist/extensions/pi-subagents/src/inspectors/herdr/focus.ts +55 -0
  148. package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +2 -1
  149. package/dist/extensions/pi-subagents/src/inspectors/herdr/project-panes.ts +230 -46
  150. package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +26 -4
  151. package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +32 -10
  152. package/dist/extensions/pi-subagents/src/missions/lifecycle.ts +6 -1
  153. package/dist/extensions/pi-subagents/src/missions/store.ts +4 -9
  154. package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +2 -2
  155. package/dist/extensions/pi-subagents/src/policy/authority.ts +2 -0
  156. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +3 -1
  157. package/dist/extensions/pi-subagents/src/runs/background/active-run-index.ts +31 -8
  158. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +210 -52
  159. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +63 -33
  160. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +71 -17
  161. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +886 -0
  162. package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +14 -5
  163. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +49 -56
  164. package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +1 -0
  165. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +3 -33
  166. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +5 -0
  167. package/dist/extensions/pi-subagents/src/runs/background/completion-dedupe.ts +5 -1
  168. package/dist/extensions/pi-subagents/src/runs/background/completion-replay.ts +22 -12
  169. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +105 -71
  170. package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +68 -19
  171. package/dist/extensions/pi-subagents/src/runs/background/index-segment.ts +59 -0
  172. package/dist/extensions/pi-subagents/src/runs/background/inspect-rpc.ts +443 -0
  173. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +94 -10
  174. package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +158 -90
  175. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +141 -53
  176. package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +8 -5
  177. package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +14 -4
  178. package/dist/extensions/pi-subagents/src/runs/background/run-id-query.ts +7 -0
  179. package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +13 -14
  180. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +46 -25
  181. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +823 -0
  182. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +9 -3
  183. package/dist/extensions/pi-subagents/src/runs/background/steering.ts +11 -1
  184. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +594 -216
  185. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +17 -13
  186. package/dist/extensions/pi-subagents/src/runs/background/terminal-run-index.ts +138 -0
  187. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +23 -4
  188. package/dist/extensions/pi-subagents/src/runs/background/wait-subscriptions.ts +82 -4
  189. package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +5 -3
  190. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +21 -14
  191. package/dist/extensions/pi-subagents/src/runs/foreground/async-stop-action.ts +23 -2
  192. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +153 -58
  193. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +7 -9
  194. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +1283 -1657
  195. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +274 -0
  196. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +6 -5
  197. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +59 -10
  198. package/dist/extensions/pi-subagents/src/runs/shared/agent-contract.ts +1 -1
  199. package/dist/extensions/pi-subagents/src/runs/shared/chain-outputs.ts +1 -3
  200. package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +36 -0
  201. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +52 -2
  202. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +1 -1
  203. package/dist/extensions/pi-subagents/src/runs/shared/extension-bindings.ts +78 -0
  204. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +2 -0
  205. package/dist/extensions/pi-subagents/src/runs/shared/external-job-bridge.ts +460 -0
  206. package/dist/extensions/pi-subagents/src/runs/shared/external-job-runner.ts +389 -0
  207. package/dist/extensions/pi-subagents/src/runs/shared/fast-mode-extension.ts +10 -0
  208. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +14 -0
  209. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +243 -0
  210. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +201 -85
  211. package/dist/extensions/pi-subagents/src/runs/shared/model-scope.ts +106 -39
  212. package/dist/extensions/pi-subagents/src/runs/shared/mutation-evidence.ts +145 -0
  213. package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +150 -27
  214. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +46 -4
  215. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +19 -15
  216. package/dist/extensions/pi-subagents/src/runs/shared/permissions.ts +5 -1
  217. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +86 -2
  218. package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +9 -9
  219. package/dist/extensions/pi-subagents/src/runs/shared/session-lease.ts +0 -6
  220. package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +18 -4
  221. package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +51 -7
  222. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +62 -21
  223. package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +1 -3
  224. package/dist/extensions/pi-subagents/src/runs/shared/tool-timeout.ts +1 -3
  225. package/dist/extensions/pi-subagents/src/runs/shared/workflow-graph.ts +1 -23
  226. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +14 -2
  227. package/dist/extensions/pi-subagents/src/shared/artifacts.ts +2 -2
  228. package/dist/extensions/pi-subagents/src/shared/atomic-json.ts +22 -2
  229. package/dist/extensions/pi-subagents/src/shared/capacity-resilient-json.ts +102 -0
  230. package/dist/extensions/pi-subagents/src/shared/completion-owner.ts +14 -0
  231. package/dist/extensions/pi-subagents/src/shared/file-system-retry.ts +49 -1
  232. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +59 -1
  233. package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +12 -5
  234. package/dist/extensions/pi-subagents/src/shared/model-info.ts +20 -0
  235. package/dist/extensions/pi-subagents/src/shared/prompt-resources.ts +0 -40
  236. package/dist/extensions/pi-subagents/src/shared/settings.ts +11 -30
  237. package/dist/extensions/pi-subagents/src/shared/thinking-ceiling.ts +52 -0
  238. package/dist/extensions/pi-subagents/src/shared/types.ts +228 -49
  239. package/dist/extensions/pi-subagents/src/shared/utils.ts +11 -3
  240. package/dist/extensions/pi-subagents/src/shared/watch-strategy.ts +10 -0
  241. package/dist/extensions/pi-subagents/src/slash/prompt-workflows.ts +0 -162
  242. package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +2 -5
  243. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +105 -13
  244. package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +6 -36
  245. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +829 -0
  246. package/dist/extensions/pi-subagents/src/tui/fleet.ts +1415 -0
  247. package/dist/extensions/pi-subagents/src/tui/render.ts +78 -7
  248. package/dist/extensions/pi-subagents/src/watchdog/change-signature.ts +1 -1
  249. package/dist/extensions/pi-subagents/src/watchdog/lsp-diagnostics.ts +1 -0
  250. package/dist/extensions/pi-subagents/src/watchdog/permission-arbiter.ts +59 -51
  251. package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +8 -2
  252. package/dist/extensions/pi-subagents/src/watchdog/tool-actions.ts +2 -1
  253. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +4 -4
  254. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +471 -86
  255. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +140 -0
  256. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
  257. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/cli.d.ts +3 -0
  258. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/register-bedrock.d.ts +2 -0
  259. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/restore-sandbox-env.d.ts +17 -0
  260. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/args.d.ts +57 -0
  261. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/config-selector.d.ts +16 -0
  262. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/file-processor.d.ts +15 -0
  263. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/initial-message.d.ts +18 -0
  264. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/list-models.d.ts +9 -0
  265. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/project-trust.d.ts +10 -0
  266. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/session-picker.d.ts +10 -0
  267. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/startup-ui.d.ts +20 -0
  268. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli.d.ts +3 -0
  269. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/config.d.ts +96 -0
  270. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-runtime.d.ts +119 -0
  271. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-services.d.ts +85 -0
  272. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session.d.ts +620 -0
  273. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-guidance.d.ts +5 -0
  274. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-storage.d.ts +56 -0
  275. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/bash-executor.d.ts +32 -0
  276. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/cache-stats.d.ts +49 -0
  277. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/branch-summarization.d.ts +93 -0
  278. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/compaction.d.ts +128 -0
  279. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/index.d.ts +7 -0
  280. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/utils.d.ts +38 -0
  281. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/defaults.d.ts +3 -0
  282. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/diagnostics.d.ts +15 -0
  283. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/event-bus.d.ts +9 -0
  284. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/exec.d.ts +29 -0
  285. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/experimental.d.ts +2 -0
  286. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/ansi-to-html.d.ts +22 -0
  287. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/index.d.ts +37 -0
  288. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/tool-renderer.d.ts +34 -0
  289. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/index.d.ts +12 -0
  290. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/loader.d.ts +23 -0
  291. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/runner.d.ts +171 -0
  292. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/types.d.ts +1261 -0
  293. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/wrapper.d.ts +20 -0
  294. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/footer-data-provider.d.ts +54 -0
  295. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/http-dispatcher.d.ts +22 -0
  296. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/index.d.ts +13 -0
  297. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/keybindings.d.ts +358 -0
  298. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/messages.d.ts +77 -0
  299. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-config.d.ts +512 -0
  300. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-registry.d.ts +43 -0
  301. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-resolver.d.ts +121 -0
  302. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-runtime.d.ts +82 -0
  303. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/models-store.d.ts +17 -0
  304. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/output-guard.d.ts +7 -0
  305. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/package-manager.d.ts +210 -0
  306. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/project-trust.d.ts +15 -0
  307. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/prompt-templates.d.ts +54 -0
  308. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-attribution.d.ts +4 -0
  309. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-composer.d.ts +55 -0
  310. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/radius.d.ts +2 -0
  311. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/remote-catalog-provider.d.ts +5 -0
  312. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resolve-config-value.d.ts +30 -0
  313. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resource-loader.d.ts +206 -0
  314. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/runtime-credentials.d.ts +15 -0
  315. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/sdk.d.ts +106 -0
  316. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-cwd.d.ts +19 -0
  317. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-manager.d.ts +356 -0
  318. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/settings-manager.d.ts +297 -0
  319. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/skills.d.ts +60 -0
  320. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/slash-commands.d.ts +15 -0
  321. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/source-info.d.ts +18 -0
  322. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/system-prompt.d.ts +28 -0
  323. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/telemetry.d.ts +3 -0
  324. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/timings.d.ts +10 -0
  325. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/bash.d.ts +68 -0
  326. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit-diff.d.ts +106 -0
  327. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit.d.ts +51 -0
  328. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/file-mutation-queue.d.ts +6 -0
  329. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/find.d.ts +35 -0
  330. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/grep.d.ts +37 -0
  331. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/index.d.ts +40 -0
  332. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/ls.d.ts +37 -0
  333. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/output-accumulator.d.ts +52 -0
  334. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/path-utils.d.ts +10 -0
  335. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/read.d.ts +35 -0
  336. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/render-utils.d.ts +24 -0
  337. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
  338. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/truncate.d.ts +70 -0
  339. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/write.d.ts +26 -0
  340. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/trust-manager.d.ts +36 -0
  341. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/usage-totals.d.ts +19 -0
  342. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/index.d.ts +3 -0
  343. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/client.d.ts +61 -0
  344. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/huggingface.d.ts +23 -0
  345. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/index.d.ts +3 -0
  346. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/provider.d.ts +10 -0
  347. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/ui.d.ts +42 -0
  348. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/index.d.ts +35 -0
  349. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/main.d.ts +12 -0
  350. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/migrations.d.ts +33 -0
  351. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/index.d.ts +9 -0
  352. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/armin.d.ts +34 -0
  353. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/assistant-message.d.ts +22 -0
  354. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bash-execution.d.ts +34 -0
  355. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
  356. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
  357. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
  358. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/config-selector.d.ts +102 -0
  359. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
  360. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-editor.d.ts +21 -0
  361. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-entry.d.ts +19 -0
  362. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-message.d.ts +20 -0
  363. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/daxnuts.d.ts +23 -0
  364. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/diff.d.ts +12 -0
  365. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
  366. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
  367. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-editor.d.ts +22 -0
  368. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-input.d.ts +23 -0
  369. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-selector.d.ts +26 -0
  370. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/first-time-setup.d.ts +25 -0
  371. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/footer.d.ts +32 -0
  372. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/index.d.ts +34 -0
  373. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/keybinding-hints.d.ts +13 -0
  374. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/login-dialog.d.ts +52 -0
  375. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/model-selector.d.ts +54 -0
  376. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/oauth-selector.d.ts +33 -0
  377. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/scoped-models-selector.d.ts +42 -0
  378. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
  379. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector.d.ts +95 -0
  380. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/settings-selector.d.ts +77 -0
  381. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
  382. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
  383. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/status-indicator.d.ts +28 -0
  384. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/theme-selector.d.ts +11 -0
  385. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
  386. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tool-execution.d.ts +63 -0
  387. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tree-selector.d.ts +94 -0
  388. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/trust-selector.d.ts +23 -0
  389. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
  390. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message.d.ts +14 -0
  391. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
  392. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/interactive-mode.d.ts +394 -0
  393. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/model-search.d.ts +12 -0
  394. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme-controller.d.ts +29 -0
  395. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme.d.ts +120 -0
  396. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/print-mode.d.ts +28 -0
  397. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/jsonl.d.ts +17 -0
  398. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-client.d.ts +246 -0
  399. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-mode.d.ts +20 -0
  400. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-types.d.ts +457 -0
  401. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/package-manager-cli.d.ts +8 -0
  402. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/rpc-entry.d.ts +3 -0
  403. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/ansi.d.ts +2 -0
  404. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/changelog.d.ts +22 -0
  405. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/child-process.d.ts +18 -0
  406. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-image.d.ts +11 -0
  407. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-native.d.ts +11 -0
  408. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard.d.ts +4 -0
  409. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/deprecation.d.ts +4 -0
  410. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/exif-orientation.d.ts +5 -0
  411. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/frontmatter.d.ts +8 -0
  412. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/fs-watch.d.ts +5 -0
  413. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/git.d.ts +26 -0
  414. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/html.d.ts +7 -0
  415. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-convert.d.ts +10 -0
  416. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-process.d.ts +18 -0
  417. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-core.d.ts +30 -0
  418. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-worker.d.ts +2 -0
  419. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize.d.ts +16 -0
  420. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/json.d.ts +3 -0
  421. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/mime.d.ts +3 -0
  422. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/open-browser.d.ts +9 -0
  423. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/paths.d.ts +31 -0
  424. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/photon.d.ts +21 -0
  425. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/pi-user-agent.d.ts +2 -0
  426. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/shell.d.ts +31 -0
  427. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/sleep.d.ts +5 -0
  428. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/syntax-highlight.d.ts +12 -0
  429. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/tools-manager.d.ts +3 -0
  430. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/version-check.d.ts +15 -0
  431. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/windows-self-update.d.ts +3 -0
  432. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/index.mjs +1 -1
  433. package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +0 -54
  434. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +1053 -414
  435. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +194 -4
  436. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +59 -4
  437. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +0 -77
  438. package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +107 -6
  439. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +211 -897
  440. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +265 -375
  441. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +77 -7
  442. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +1 -1
  443. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +10 -10
  444. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +547 -30
  445. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +2112 -310
  446. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +274 -34
  447. package/dist/extensions/pi-subagents/test/integration/slash-live-state.test.ts +1 -1
  448. package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +20 -3
  449. package/dist/extensions/pi-subagents/test/support/isolated-temp-root.mjs +9 -0
  450. package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +30 -5
  451. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +2 -0
  452. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +4 -2
  453. package/dist/extensions/pi-subagents/test/support/register-loader.mjs +1 -0
  454. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +197 -0
  455. package/dist/extensions/pi-subagents/test/unit/agent-contract.test.ts +14 -0
  456. package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +1 -1
  457. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +204 -27
  458. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +444 -145
  459. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +256 -4
  460. package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +9 -7
  461. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +152 -22
  462. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +29 -0
  463. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +205 -23
  464. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +579 -0
  465. package/dist/extensions/pi-subagents/test/unit/atomic-json.test.ts +24 -0
  466. package/dist/extensions/pi-subagents/test/unit/authority-policy.test.ts +1 -0
  467. package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +3 -3
  468. package/dist/extensions/pi-subagents/test/unit/capacity-resilient-json.test.ts +155 -0
  469. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +2 -2
  470. package/dist/extensions/pi-subagents/test/unit/completion-dedupe.test.ts +7 -0
  471. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +123 -0
  472. package/dist/extensions/pi-subagents/test/unit/completion-replay.test.ts +81 -3
  473. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +109 -7
  474. package/dist/extensions/pi-subagents/test/unit/default-extensions.test.ts +2 -2
  475. package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +5 -2
  476. package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +3 -2
  477. package/dist/extensions/pi-subagents/test/unit/extension-bindings.test.ts +79 -0
  478. package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +22 -0
  479. package/dist/extensions/pi-subagents/test/unit/external-job-runner.test.ts +961 -0
  480. package/dist/extensions/pi-subagents/test/unit/file-system-retry.test.ts +64 -0
  481. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +1110 -0
  482. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +1664 -0
  483. package/dist/extensions/pi-subagents/test/unit/fork-context.test.ts +81 -1
  484. package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +138 -11
  485. package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +41 -2
  486. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +210 -79
  487. package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +95 -0
  488. package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +596 -0
  489. package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +10 -1
  490. package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +3 -5
  491. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +167 -0
  492. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +319 -18
  493. package/dist/extensions/pi-subagents/test/unit/model-info.test.ts +78 -0
  494. package/dist/extensions/pi-subagents/test/unit/model-scope-settings.test.ts +19 -5
  495. package/dist/extensions/pi-subagents/test/unit/model-scope.test.ts +44 -0
  496. package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +129 -0
  497. package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +231 -2
  498. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +28 -1
  499. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +106 -2
  500. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +204 -7
  501. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +59 -4
  502. package/dist/extensions/pi-subagents/test/unit/path-handling.test.ts +2 -6
  503. package/dist/extensions/pi-subagents/test/unit/pi-args-permission-system.test.ts +34 -2
  504. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +116 -6
  505. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +12 -3
  506. package/dist/extensions/pi-subagents/test/unit/pi-spawn.test.ts +56 -61
  507. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +416 -1
  508. package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +9 -2
  509. package/dist/extensions/pi-subagents/test/unit/project-panes-public-api.test.ts +42 -0
  510. package/dist/extensions/pi-subagents/test/unit/prompt-workflows.test.ts +21 -30
  511. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +86 -11
  512. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +49 -1
  513. package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +233 -5
  514. package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +28 -5
  515. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +323 -20
  516. package/dist/extensions/pi-subagents/test/unit/run-id-resolver.test.ts +66 -10
  517. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +68 -5
  518. package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +174 -0
  519. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +679 -0
  520. package/dist/extensions/pi-subagents/test/unit/scheduled-store-root.test.ts +67 -0
  521. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +55 -44
  522. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +399 -84
  523. package/dist/extensions/pi-subagents/test/unit/session-lease.test.ts +13 -0
  524. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
  525. package/dist/extensions/pi-subagents/test/unit/slash-bridge.test.ts +15 -10
  526. package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +11 -7
  527. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +2 -0
  528. package/dist/extensions/pi-subagents/test/unit/steering.test.ts +40 -1
  529. package/dist/extensions/pi-subagents/test/unit/subagent-action-recovery.test.ts +10 -2
  530. package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +38 -3
  531. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +110 -12
  532. package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +204 -19
  533. package/dist/extensions/pi-subagents/test/unit/temp-paths.test.ts +25 -0
  534. package/dist/extensions/pi-subagents/test/unit/thinking-ceiling.test.ts +73 -0
  535. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +90 -50
  536. package/dist/extensions/pi-subagents/test/unit/tool-timeout.test.ts +1 -2
  537. package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +234 -7
  538. package/dist/extensions/pi-subagents/test/unit/watch-strategy.test.ts +24 -0
  539. package/dist/extensions/pi-subagents/test/unit/watchdog-permission-arbiter.test.ts +36 -0
  540. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +37 -9
  541. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +302 -0
  542. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +167 -7
  543. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +113 -0
  544. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +6 -6
  545. package/dist/extensions/pi-web-agent/package.json +31 -31
  546. package/dist/extensions/pi-web-agent/src/backends/config.ts +205 -205
  547. package/dist/extensions/pi-web-agent/src/backends/doctor.ts +136 -136
  548. package/dist/extensions/pi-web-agent/src/backends/factory.ts +152 -152
  549. package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +25 -25
  550. package/dist/extensions/pi-web-agent/src/cache/ttl-cache.ts +28 -28
  551. package/dist/extensions/pi-web-agent/src/changelog-notice.ts +136 -136
  552. package/dist/extensions/pi-web-agent/src/commands/web-agent-config.ts +946 -946
  553. package/dist/extensions/pi-web-agent/src/extension.ts +126 -126
  554. package/dist/extensions/pi-web-agent/src/extract/readability.ts +118 -118
  555. package/dist/extensions/pi-web-agent/src/fetch/browser-resolution.ts +199 -199
  556. package/dist/extensions/pi-web-agent/src/fetch/firecrawl-fetch.ts +100 -100
  557. package/dist/extensions/pi-web-agent/src/fetch/headless-fetch.ts +117 -117
  558. package/dist/extensions/pi-web-agent/src/fetch/http-fetch.ts +67 -67
  559. package/dist/extensions/pi-web-agent/src/orchestration/answer-synthesizer.ts +60 -60
  560. package/dist/extensions/pi-web-agent/src/orchestration/candidate-selector.ts +50 -50
  561. package/dist/extensions/pi-web-agent/src/orchestration/direct-url.ts +52 -52
  562. package/dist/extensions/pi-web-agent/src/orchestration/evidence-quality.ts +105 -105
  563. package/dist/extensions/pi-web-agent/src/orchestration/evidence-ranker.ts +45 -45
  564. package/dist/extensions/pi-web-agent/src/orchestration/index.ts +28 -28
  565. package/dist/extensions/pi-web-agent/src/orchestration/query-planner.ts +47 -47
  566. package/dist/extensions/pi-web-agent/src/orchestration/research-orchestrator.ts +376 -376
  567. package/dist/extensions/pi-web-agent/src/orchestration/research-types.ts +64 -64
  568. package/dist/extensions/pi-web-agent/src/orchestration/research-worker.ts +181 -181
  569. package/dist/extensions/pi-web-agent/src/orchestration/source-profile.ts +101 -101
  570. package/dist/extensions/pi-web-agent/src/orchestration/stop-decider.ts +81 -81
  571. package/dist/extensions/pi-web-agent/src/presentation/config-store.ts +210 -210
  572. package/dist/extensions/pi-web-agent/src/presentation/config.ts +75 -75
  573. package/dist/extensions/pi-web-agent/src/presentation/explore-presentation.ts +61 -61
  574. package/dist/extensions/pi-web-agent/src/presentation/fetch-presentation.ts +54 -54
  575. package/dist/extensions/pi-web-agent/src/presentation/search-presentation.ts +41 -41
  576. package/dist/extensions/pi-web-agent/src/presentation/select-view.ts +20 -20
  577. package/dist/extensions/pi-web-agent/src/presentation/types.ts +63 -63
  578. package/dist/extensions/pi-web-agent/src/search/brave.ts +114 -114
  579. package/dist/extensions/pi-web-agent/src/search/duckduckgo.ts +72 -72
  580. package/dist/extensions/pi-web-agent/src/search/searxng.ts +96 -96
  581. package/dist/extensions/pi-web-agent/src/tools/web-explore.ts +71 -71
  582. package/dist/extensions/pi-web-agent/src/tools/web-fetch-headless.ts +31 -31
  583. package/dist/extensions/pi-web-agent/src/tools/web-fetch.ts +31 -31
  584. package/dist/extensions/pi-web-agent/src/tools/web-search.ts +157 -157
  585. package/dist/extensions/pi-web-agent/src/types.ts +88 -88
  586. package/dist/extensions/ponytail/index.js +31 -25
  587. package/dist/extensions/ponytail/package.json +8 -8
  588. package/dist/extensions/ponytail/ponytail-config.cjs +34 -7
  589. package/dist/extensions/ponytail/ponytail-instructions.cjs +7 -9
  590. package/dist/extensions/ponytail/test/extension.test.js +7 -8
  591. package/dist/extensions/ponytail/test/helpers.test.js +1 -1
  592. package/dist/extensions/question/batch.ts +103 -103
  593. package/dist/extensions/question/constants.ts +30 -30
  594. package/dist/extensions/question/helpers.ts +58 -58
  595. package/dist/extensions/question/navigation.ts +14 -14
  596. package/dist/extensions/question/package.json +19 -19
  597. package/dist/extensions/question/schemas.ts +43 -43
  598. package/dist/extensions/question/selection-mode.ts +46 -46
  599. package/dist/extensions/question/shortcuts.ts +44 -44
  600. package/dist/extensions/question/types.ts +132 -132
  601. package/dist/extensions/test-resolve-hook-impl.mjs +6 -6
  602. package/dist/extensions/test-resolve-hook.mjs +6 -6
  603. package/dist/extensions/web-agent-onboarding.ts +222 -222
  604. package/dist/extensions/workflow/package.json +17 -17
  605. package/dist/package-manager-cli.js +71 -71
  606. package/dist/rpc-entry.js +0 -0
  607. package/dist/skills/agent-browser/SKILL.md +52 -52
  608. package/dist/skills/batch-grill-me/SKILL.md +19 -19
  609. package/dist/skills/brandkit/SKILL.md +799 -0
  610. package/dist/skills/design-taste-frontend/SKILL.md +1207 -0
  611. package/dist/skills/design-taste-frontend-v1/SKILL.md +227 -0
  612. package/dist/skills/full-output-enforcement/SKILL.md +50 -0
  613. package/dist/skills/gpt-taste/SKILL.md +75 -0
  614. package/dist/skills/grill-me/SKILL.md +10 -10
  615. package/dist/skills/handoff/SKILL.md +16 -16
  616. package/dist/skills/handoff-text/SKILL.md +14 -14
  617. package/dist/skills/high-end-visual-design/SKILL.md +99 -0
  618. package/dist/skills/image-to-code/SKILL.md +1229 -0
  619. package/dist/skills/imagegen-frontend-mobile/SKILL.md +1466 -0
  620. package/dist/skills/imagegen-frontend-web/SKILL.md +988 -0
  621. package/dist/skills/implanger/SKILL.md +69 -69
  622. package/dist/skills/improve-codebase/REFERENCE.md +78 -78
  623. package/dist/skills/improve-codebase/SKILL.md +178 -178
  624. package/dist/skills/industrial-brutalist-ui/SKILL.md +93 -0
  625. package/dist/skills/minimalist-ui/SKILL.md +86 -0
  626. package/dist/skills/pi-subagents/SKILL.md +18 -17
  627. package/dist/skills/pi-subagents/references/constraints-and-recipes.md +31 -9
  628. package/dist/skills/pi-subagents/references/execution-controls.md +95 -143
  629. package/dist/skills/pi-subagents/references/management-authoring-rpc.md +9 -12
  630. package/dist/skills/pi-subagents/references/multi-lane-orchestration.md +39 -0
  631. package/dist/skills/pi-subagents/references/prompting-and-roles.md +45 -94
  632. package/dist/skills/planger/SKILL.md +166 -166
  633. package/dist/skills/ponytail/SKILL.md +120 -116
  634. package/dist/skills/ponytail-audit/SKILL.md +41 -42
  635. package/dist/skills/ponytail-debt/SKILL.md +44 -45
  636. package/dist/skills/ponytail-gain/SKILL.md +50 -51
  637. package/dist/skills/ponytail-help/SKILL.md +71 -70
  638. package/dist/skills/ponytail-review/SKILL.md +57 -58
  639. package/dist/skills/redesign-existing-projects/SKILL.md +179 -0
  640. package/dist/skills/selesai-handoff/SKILL.md +20 -20
  641. package/dist/skills/stitch-design-taste/SKILL.md +185 -0
  642. package/dist/skills/unlazy/CHANGELOG.md +100 -0
  643. package/dist/skills/unlazy/CONTRIBUTING.md +66 -0
  644. package/dist/skills/unlazy/LICENSE +21 -0
  645. package/dist/skills/unlazy/README.md +242 -0
  646. package/dist/skills/unlazy/SECURITY.md +70 -0
  647. package/dist/skills/unlazy/SKILL.md +100 -0
  648. package/dist/skills/unlazy/package.json +13 -0
  649. package/dist/skills/unlazy/references/dispatch.md +82 -0
  650. package/dist/skills/unlazy/references/gates.md +132 -0
  651. package/dist/skills/unlazy/references/method.md +49 -0
  652. package/dist/skills/unlazy/references/orchestration.md +99 -0
  653. package/dist/skills/unlazy/references/parallel.md +123 -0
  654. package/dist/skills/unlazy/references/token-economy.md +39 -0
  655. package/dist/skills/unlazy/research/validation-protocol.md +81 -0
  656. package/dist/skills/unlazy/scripts/dispatch-check.mjs +108 -0
  657. package/dist/skills/unlazy/scripts/gate-check.mjs +894 -0
  658. package/dist/skills/unlazy/scripts/gate-lint.mjs +178 -0
  659. package/dist/skills/unlazy/scripts/install-hooks.mjs +206 -0
  660. package/dist/skills/unlazy/scripts/lib/check-supervisor.mjs +46 -0
  661. package/dist/skills/unlazy/scripts/lib/dispatch.mjs +283 -0
  662. package/dist/skills/unlazy/scripts/lib/gates.mjs +629 -0
  663. package/dist/skills/unlazy/scripts/lib/process-tree.mjs +161 -0
  664. package/dist/skills/unlazy/scripts/lib/regex-worker.mjs +9 -0
  665. package/dist/skills/unlazy/scripts/stop-hook.mjs +174 -0
  666. package/dist/skills/unlazy/templates/PLAN.md +65 -0
  667. package/dist/skills/unlazy/templates/gates-leaf.md +51 -0
  668. package/dist/skills/unlazy/templates/gates-node.md +50 -0
  669. package/dist/skills/unlazy/tests/contract-tests.mjs +127 -0
  670. package/dist/skills/unlazy/tests/dispatch-tests.mjs +481 -0
  671. package/dist/skills/unlazy/tests/hardening-tests.mjs +903 -0
  672. package/dist/skills/unlazy/tests/lint-tests.mjs +242 -0
  673. package/dist/skills/unlazy/tests/run-tests.mjs +554 -0
  674. package/dist/skills/unlazy/tests/self-check.mjs +165 -0
  675. package/dist/skills/unlazy/tests/stress-tests.mjs +356 -0
  676. package/dist/skills/web-design-guidelines/SKILL.md +40 -0
  677. package/dist/skills/workflow-creation/SKILL.md +73 -73
  678. package/dist/themes/powerline-footer/theme.json +33 -33
  679. package/dist/utils/shell.d.ts +3 -0
  680. package/dist/utils/shell.js +17 -5
  681. package/docs/compaction.md +396 -396
  682. package/docs/containerization.md +111 -111
  683. package/docs/development.md +71 -71
  684. package/docs/docs.json +164 -164
  685. package/docs/environment-variables.md +86 -86
  686. package/docs/index.md +83 -83
  687. package/docs/json.md +82 -82
  688. package/docs/models.md +502 -502
  689. package/docs/packages.md +227 -227
  690. package/docs/plans/subagent-delegation/phase-0-correctness.md +264 -264
  691. package/docs/plans/subagent-delegation/phase-1-behavioral-contract.md +485 -485
  692. package/docs/plans/subagent-delegation/phase-2-context-controls.md +281 -281
  693. package/docs/plans/subagent-delegation/phase-3-advisory-routing.md +361 -361
  694. package/docs/plans/subagent-delegation/phase-4-optional-enforcement.md +380 -380
  695. package/docs/prompt-templates.md +95 -95
  696. package/docs/providers.md +293 -293
  697. package/docs/sdk.md +1144 -1143
  698. package/docs/security.md +59 -59
  699. package/docs/session-format.md +414 -414
  700. package/docs/sessions.md +145 -145
  701. package/docs/settings.md +0 -5
  702. package/docs/shared-host-extensions.md +109 -109
  703. package/docs/shell-aliases.md +13 -13
  704. package/docs/skills.md +231 -231
  705. package/docs/terminal-setup.md +142 -142
  706. package/docs/termux.md +127 -127
  707. package/docs/themes.md +295 -295
  708. package/docs/tmux.md +63 -63
  709. package/docs/tui.md +927 -927
  710. package/docs/windows.md +17 -17
  711. package/examples/README.md +25 -25
  712. package/examples/extensions/README.md +211 -211
  713. package/examples/extensions/auto-commit-on-exit.ts +49 -49
  714. package/examples/extensions/bash-spawn-hook.ts +30 -30
  715. package/examples/extensions/bookmark.ts +50 -50
  716. package/examples/extensions/border-status-editor.ts +150 -150
  717. package/examples/extensions/built-in-tool-renderer.ts +249 -249
  718. package/examples/extensions/claude-rules.ts +86 -86
  719. package/examples/extensions/commands.ts +72 -72
  720. package/examples/extensions/confirm-destructive.ts +59 -59
  721. package/examples/extensions/custom-compaction.ts +130 -130
  722. package/examples/extensions/custom-footer.ts +64 -64
  723. package/examples/extensions/custom-header.ts +73 -73
  724. package/examples/extensions/custom-provider-anthropic/index.ts +610 -610
  725. package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -24
  726. package/examples/extensions/custom-provider-anthropic/package.json +19 -19
  727. package/examples/extensions/custom-provider-gitlab-duo/index.ts +404 -404
  728. package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -16
  729. package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -82
  730. package/examples/extensions/dirty-repo-guard.ts +56 -56
  731. package/examples/extensions/doom-overlay/README.md +46 -46
  732. package/examples/extensions/doom-overlay/doom/build/doom.js +21 -21
  733. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  734. package/examples/extensions/doom-overlay/doom/build.sh +152 -152
  735. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -72
  736. package/examples/extensions/doom-overlay/doom-component.ts +132 -132
  737. package/examples/extensions/doom-overlay/doom-engine.ts +173 -173
  738. package/examples/extensions/doom-overlay/doom-keys.ts +104 -104
  739. package/examples/extensions/doom-overlay/index.ts +74 -74
  740. package/examples/extensions/doom-overlay/wad-finder.ts +51 -51
  741. package/examples/extensions/dynamic-resources/SKILL.md +8 -8
  742. package/examples/extensions/dynamic-resources/dynamic.json +79 -79
  743. package/examples/extensions/dynamic-resources/dynamic.md +5 -5
  744. package/examples/extensions/dynamic-resources/index.ts +15 -15
  745. package/examples/extensions/dynamic-tools.ts +74 -74
  746. package/examples/extensions/event-bus.ts +43 -43
  747. package/examples/extensions/file-trigger.ts +41 -41
  748. package/examples/extensions/git-checkpoint.ts +53 -53
  749. package/examples/extensions/git-merge-and-resolve.ts +115 -115
  750. package/examples/extensions/github-issue-autocomplete.ts +185 -185
  751. package/examples/extensions/gondolin/index.ts +531 -531
  752. package/examples/extensions/gondolin/package-lock.json +185 -185
  753. package/examples/extensions/gondolin/package.json +19 -19
  754. package/examples/extensions/handoff.ts +199 -199
  755. package/examples/extensions/hello.ts +26 -26
  756. package/examples/extensions/hidden-thinking-label.ts +53 -53
  757. package/examples/extensions/inline-bash.ts +94 -94
  758. package/examples/extensions/input-transform-streaming.ts +39 -39
  759. package/examples/extensions/input-transform.ts +43 -43
  760. package/examples/extensions/interactive-shell.ts +196 -196
  761. package/examples/extensions/mac-system-theme.ts +47 -47
  762. package/examples/extensions/message-renderer.ts +59 -59
  763. package/examples/extensions/minimal-mode.ts +426 -426
  764. package/examples/extensions/modal-editor.ts +85 -85
  765. package/examples/extensions/model-status.ts +31 -31
  766. package/examples/extensions/notify.ts +55 -55
  767. package/examples/extensions/overlay-qa-tests.ts +1450 -1450
  768. package/examples/extensions/overlay-test.ts +153 -153
  769. package/examples/extensions/permission-gate.ts +34 -34
  770. package/examples/extensions/pirate.ts +47 -47
  771. package/examples/extensions/plan-mode/README.md +66 -66
  772. package/examples/extensions/plan-mode/index.ts +390 -390
  773. package/examples/extensions/plan-mode/utils.ts +168 -168
  774. package/examples/extensions/preset.ts +436 -436
  775. package/examples/extensions/project-trust.ts +64 -64
  776. package/examples/extensions/prompt-customizer.ts +97 -97
  777. package/examples/extensions/protected-paths.ts +30 -30
  778. package/examples/extensions/provider-payload.ts +18 -18
  779. package/examples/extensions/qna.ts +122 -122
  780. package/examples/extensions/question.ts +285 -285
  781. package/examples/extensions/questionnaire.ts +448 -448
  782. package/examples/extensions/rainbow-editor.ts +88 -88
  783. package/examples/extensions/reload-runtime.ts +37 -37
  784. package/examples/extensions/rpc-demo.ts +118 -118
  785. package/examples/extensions/sandbox/index.ts +321 -321
  786. package/examples/extensions/sandbox/package-lock.json +92 -92
  787. package/examples/extensions/sandbox/package.json +19 -19
  788. package/examples/extensions/send-user-message.ts +97 -97
  789. package/examples/extensions/session-name.ts +27 -27
  790. package/examples/extensions/shutdown-command.ts +63 -63
  791. package/examples/extensions/snake.ts +343 -343
  792. package/examples/extensions/space-invaders.ts +560 -560
  793. package/examples/extensions/ssh.ts +220 -220
  794. package/examples/extensions/status-line.ts +32 -32
  795. package/examples/extensions/structured-output.ts +65 -65
  796. package/examples/extensions/subagent/README.md +175 -175
  797. package/examples/extensions/subagent/agents/planner.md +37 -37
  798. package/examples/extensions/subagent/agents/reviewer.md +35 -35
  799. package/examples/extensions/subagent/agents/scout.md +50 -50
  800. package/examples/extensions/subagent/agents/worker.md +24 -24
  801. package/examples/extensions/subagent/agents.ts +126 -126
  802. package/examples/extensions/subagent/index.ts +1015 -1015
  803. package/examples/extensions/subagent/prompts/implement-and-review.md +10 -10
  804. package/examples/extensions/subagent/prompts/implement.md +10 -10
  805. package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -9
  806. package/examples/extensions/summarize.ts +209 -209
  807. package/examples/extensions/system-prompt-header.ts +17 -17
  808. package/examples/extensions/tic-tac-toe.ts +1008 -1008
  809. package/examples/extensions/timed-confirm.ts +70 -70
  810. package/examples/extensions/titlebar-spinner.ts +58 -58
  811. package/examples/extensions/todo.ts +297 -297
  812. package/examples/extensions/tool-override.ts +144 -144
  813. package/examples/extensions/tools.ts +146 -146
  814. package/examples/extensions/trigger-compact.ts +50 -50
  815. package/examples/extensions/truncated-tool.ts +195 -195
  816. package/examples/extensions/widget-placement.ts +9 -9
  817. package/examples/extensions/with-deps/index.ts +32 -32
  818. package/examples/extensions/with-deps/package-lock.json +31 -31
  819. package/examples/extensions/with-deps/package.json +22 -22
  820. package/examples/extensions/working-indicator.ts +123 -123
  821. package/examples/extensions/working-message-test.ts +25 -25
  822. package/examples/rpc-extension-ui.ts +632 -632
  823. package/examples/sdk/01-minimal.ts +26 -26
  824. package/examples/sdk/02-custom-model.ts +53 -53
  825. package/examples/sdk/03-custom-prompt.ts +75 -75
  826. package/examples/sdk/04-skills.ts +55 -55
  827. package/examples/sdk/05-tools.ts +48 -48
  828. package/examples/sdk/06-extensions.ts +99 -99
  829. package/examples/sdk/07-context-files.ts +47 -47
  830. package/examples/sdk/08-prompt-templates.ts +51 -51
  831. package/examples/sdk/09-api-keys-and-oauth.ts +52 -52
  832. package/examples/sdk/10-settings.ts +53 -53
  833. package/examples/sdk/11-sessions.ts +52 -52
  834. package/examples/sdk/12-full-control.ts +79 -79
  835. package/examples/sdk/13-session-runtime.ts +67 -67
  836. package/examples/sdk/README.md +144 -144
  837. package/package.json +4 -4
  838. package/dist/core/tools/schema-prune.d.ts +0 -16
  839. package/dist/core/tools/schema-prune.js +0 -39
  840. package/dist/core/tools/schema-prune.test.js +0 -111
  841. package/dist/extensions/pi-subagents/UPSTREAM-V0.50-MAPPING.md +0 -172
  842. package/dist/extensions/pi-subagents/prompts/parallel-context-build.md +0 -55
  843. package/dist/extensions/pi-subagents/prompts/parallel-handoff-plan.md +0 -61
  844. package/dist/extensions/pi-subagents/src/agents/task-aware-routing.ts +0 -132
  845. package/dist/extensions/pi-subagents/src/extension/chain-validation.ts +0 -181
  846. package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +0 -1354
  847. package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +0 -1581
  848. package/dist/extensions/pi-subagents/src/shared/env.ts +0 -16
  849. package/dist/extensions/pi-subagents/src/shared/session-lineage.ts +0 -71
  850. package/dist/extensions/pi-subagents/src/slash/inline-subagents.ts +0 -136
  851. package/dist/extensions/pi-subagents/src/workflows/workflow-auto-relaunch.ts +0 -41
  852. package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +0 -466
  853. package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +0 -1859
  854. package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +0 -733
  855. package/dist/extensions/pi-subagents/test/unit/builtin-agent-documentation.test.ts +0 -63
  856. package/dist/extensions/pi-subagents/test/unit/chain-validation.test.ts +0 -326
  857. package/dist/extensions/pi-subagents/test/unit/handoff-adoption.test.ts +0 -103
  858. package/dist/extensions/pi-subagents/test/unit/inline-subagents.test.ts +0 -127
  859. package/dist/extensions/pi-subagents/test/unit/session-lineage.test.ts +0 -73
  860. package/dist/extensions/pi-subagents/test/unit/task-aware-routing.test.ts +0 -213
  861. package/dist/extensions/pi-subagents/test/unit/workflow-auto-relaunch.test.ts +0 -65
  862. /package/dist/core/{tools/schema-prune.test.d.ts → extensions/loader.test.d.ts} +0 -0
@@ -0,0 +1,903 @@
1
+ #!/usr/bin/env node
2
+ // Security, parser, execution, and writeback regressions. Zero dependencies.
3
+
4
+ import {
5
+ appendFileSync, chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync,
6
+ readdirSync, realpathSync, renameSync, rmSync, symlinkSync, writeFileSync,
7
+ } from "node:fs";
8
+ import { execFile, spawnSync } from "node:child_process";
9
+ import { delimiter, dirname, join, win32 } from "node:path";
10
+ import { tmpdir } from "node:os";
11
+ import { fileURLToPath } from "node:url";
12
+ import {
13
+ terminateProcessTree, windowsTaskkillPath, WINDOWS_TASKKILL_TIMEOUT_MS,
14
+ } from "../scripts/lib/process-tree.mjs";
15
+
16
+ const HERE = dirname(fileURLToPath(import.meta.url));
17
+ const GATE_CHECK = join(HERE, "..", "scripts", "gate-check.mjs");
18
+ const STOP_HOOK = join(HERE, "..", "scripts", "stop-hook.mjs");
19
+ const WINDOWS_ENV = { SystemRoot: "C:\\Windows", WINDIR: "C:\\Windows", SystemDrive: "C:" };
20
+ const tests = [];
21
+ const test = (name, fn) => tests.push({ name, fn });
22
+
23
+ function sandbox() {
24
+ // macOS and custom TMPDIR values can expose lexical aliases (for example
25
+ // /var versus /private/var). Match the checker's canonical CWD semantics at
26
+ // the fixture boundary so every path assertion is portable.
27
+ const dir = realpathSync(mkdtempSync(join(tmpdir(), "unlazy-hardening-")));
28
+ const approvals = realpathSync(mkdtempSync(join(tmpdir(), "unlazy-approval-")));
29
+ return {
30
+ dir, approvals,
31
+ path(rel) { return join(dir, rel); },
32
+ write(rel, text) {
33
+ const path = join(dir, rel);
34
+ mkdirSync(dirname(path), { recursive: true });
35
+ writeFileSync(path, text);
36
+ return path;
37
+ },
38
+ read(rel) { return readFileSync(join(dir, rel), "utf8"); },
39
+ cleanup() {
40
+ rmSync(dir, { recursive: true, force: true });
41
+ rmSync(approvals, { recursive: true, force: true });
42
+ },
43
+ };
44
+ }
45
+
46
+ function run(script, args, options = {}) {
47
+ return new Promise((done) => {
48
+ const child = execFile(process.execPath, [script, ...args], {
49
+ cwd: options.cwd,
50
+ encoding: "utf8",
51
+ maxBuffer: 16 * 1024 * 1024,
52
+ env: { ...process.env, ...(options.env || {}) },
53
+ }, (error, stdout, stderr) => {
54
+ done({ code: error ? (typeof error.code === "number" ? error.code : 1) : 0, out: (stdout || "") + (stderr || "") });
55
+ });
56
+ if (options.stdin !== undefined) child.stdin.end(options.stdin);
57
+ });
58
+ }
59
+
60
+ function gateRun(s, args, options = {}) {
61
+ const action = args.some((arg) => ["--status", "--claim", "--release", "--list-scopes", "--log", "--bind", "--help"].includes(arg));
62
+ const actual = options.approve !== false && !action && !args.includes("--approve") ? ["--approve", ...args] : args;
63
+ return run(GATE_CHECK, actual, {
64
+ cwd: s.dir,
65
+ env: { UNLAZY_APPROVAL_DIR: s.approvals, ...(options.env || {}) },
66
+ });
67
+ }
68
+
69
+ const gate = (id, title, check, expect, extra = "") =>
70
+ "- [ ] " + id + ": " + title + "\n" +
71
+ (check !== null ? " CHECK: " + check + "\n" : "") +
72
+ (expect !== null ? " EXPECT: " + expect + "\n" : "") + extra +
73
+ " EVIDENCE: pending\n";
74
+
75
+ const assert = (condition, message) => { if (!condition) throw new Error(message); };
76
+ const has = (text, value, label = "output") => assert(text.includes(value), label + " missing " + JSON.stringify(value) + "\n" + text);
77
+ const lacks = (text, value, label = "output") => assert(!text.includes(value), label + " unexpectedly includes " + JSON.stringify(value) + "\n" + text);
78
+
79
+ async function waitForPath(path, timeoutMs = 5000) {
80
+ const deadline = Date.now() + timeoutMs;
81
+ while (!existsSync(path)) {
82
+ if (Date.now() >= deadline) throw new Error("timed out waiting for " + path);
83
+ await new Promise((done) => setTimeout(done, 20));
84
+ }
85
+ }
86
+
87
+ function processExists(pid) {
88
+ try { process.kill(pid, 0); return true; }
89
+ catch (error) { return error.code === "EPERM"; }
90
+ }
91
+
92
+ async function waitForProcessExit(pid, timeoutMs = 5000) {
93
+ const deadline = Date.now() + timeoutMs;
94
+ while (processExists(pid)) {
95
+ if (Date.now() >= deadline) throw new Error("process " + pid + " remained alive after cleanup");
96
+ await new Promise((done) => setTimeout(done, 25));
97
+ }
98
+ }
99
+
100
+ test("approval: status is read-only and an unapproved CHECK is printed but not run", async () => {
101
+ const s = sandbox();
102
+ try {
103
+ s.write("check.mjs", "import { writeFileSync } from 'node:fs'; writeFileSync('ran.txt','yes'); console.log('OK');\n");
104
+ s.write("GATES.md", gate("G1", "approval", "node check.mjs", "OK"));
105
+ const before = s.read("GATES.md");
106
+ const status = await gateRun(s, ["--status"], { approve: false, env: { UNLAZY_SHELL: "definitely-missing-shell" } });
107
+ assert(status.code === 1, "status should report unmet");
108
+ assert(s.read("GATES.md") === before, "status changed ledger");
109
+ assert(!readdirSync(s.approvals).length, "status wrote approval state");
110
+ const denied = await gateRun(s, [], { approve: false });
111
+ assert(denied.code === 1, "unapproved run should remain unmet");
112
+ has(denied.out, "APPROVAL REQUIRED GATES:G1");
113
+ has(denied.out, "NOT RUN");
114
+ assert(!s.path("ran.txt") || !await fileExists(s.path("ran.txt")), "unapproved CHECK executed");
115
+ s.write("GATES.md", "- [x] G1: claimed\n CHECK: node check.mjs\n EXPECT: OK\n EVIDENCE: claimed\n");
116
+ const unverified = await gateRun(s, ["--reverify"], { approve: false });
117
+ assert(unverified.code === 1, "unapproved reverify must not certify existing evidence\n" + unverified.out);
118
+ has(unverified.out, "GATES:G1 (reverify not run)");
119
+ } finally { s.cleanup(); }
120
+ });
121
+
122
+ async function fileExists(path) {
123
+ try { await import("node:fs/promises").then((fs) => fs.access(path)); return true; }
124
+ catch { return false; }
125
+ }
126
+
127
+ test("approval: token binds the full oracle and changing CWD invalidates it", async () => {
128
+ const s = sandbox();
129
+ try {
130
+ for (const dir of ["a", "b"]) s.write(dir + "/check.mjs", "console.log('OK');\n");
131
+ s.write("GATES.md", gate("G1", "oracle", "node check.mjs", "OK", " CWD: a\n"));
132
+ const first = await gateRun(s, []);
133
+ assert(first.code === 0, first.out);
134
+ const tokens = readdirSync(s.approvals).filter((name) => name.endsWith(".json"));
135
+ assert(tokens.length === 1, "expected one approval token");
136
+ const token = JSON.parse(readFileSync(join(s.approvals, tokens[0]), "utf8"));
137
+ for (const key of ["check", "expect", "cwd", "shell", "timeoutMs", "maxOutputBytes", "regexTimeoutMs", "platform", "path"]) {
138
+ assert(Object.prototype.hasOwnProperty.call(token.oracle, key), "approval oracle missing " + key);
139
+ }
140
+ s.write("GATES.md", gate("G1", "oracle", "node check.mjs", "OK", " CWD: b\n"));
141
+ const changed = await gateRun(s, [], { approve: false });
142
+ assert(changed.code === 1, changed.out);
143
+ has(changed.out, "APPROVAL REQUIRED");
144
+ has(changed.out, join(s.dir, "b"));
145
+ } finally { s.cleanup(); }
146
+ });
147
+
148
+ test("approval: storage failures use the infrastructure exit code", async () => {
149
+ const s = sandbox();
150
+ try {
151
+ s.write("ok.mjs", "console.log('OK');\n");
152
+ s.write("GATES.md", gate("G1", "approval storage", "node ok.mjs", "OK"));
153
+ rmSync(s.approvals, { recursive: true, force: true });
154
+ writeFileSync(s.approvals, "not a directory\n");
155
+ const result = await gateRun(s, ["--approve"], {
156
+ approve: false,
157
+ env: { UNLAZY_APPROVAL_DIR: join(s.approvals, "records") },
158
+ });
159
+ assert(result.code === 2, "approval storage failure returned " + result.code + "\n" + result.out);
160
+ has(result.out, "infrastructure failure prevented 1 approval");
161
+ } finally { s.cleanup(); }
162
+ });
163
+
164
+ test("approval: a lexical outside alias cannot resolve back into the repository", async () => {
165
+ const s = sandbox();
166
+ try {
167
+ s.write("marker.mjs", "import { writeFileSync } from 'node:fs'; writeFileSync('ran.txt','yes'); console.log('OK');\n");
168
+ s.write("GATES.md", gate("G1", "canonical approval boundary", "node marker.mjs", "OK"));
169
+ const approved = await gateRun(s, []);
170
+ assert(approved.code === 0, approved.out);
171
+
172
+ const inside = s.path("repo-controlled-approvals");
173
+ renameSync(s.approvals, inside);
174
+ symlinkSync(inside, s.approvals, process.platform === "win32" ? "junction" : "dir");
175
+ rmSync(s.path("ran.txt"), { force: true });
176
+ s.write("GATES.md", gate("G1", "canonical approval boundary", "node marker.mjs", "OK"));
177
+
178
+ const replay = await gateRun(s, [], { approve: false });
179
+ assert(replay.code === 2, "aliased approval store returned " + replay.code + "\n" + replay.out);
180
+ has(replay.out, "could not validate approval");
181
+ assert(!existsSync(s.path("ran.txt")), "a repo-controlled approval alias authorized CHECK execution");
182
+ } finally { s.cleanup(); }
183
+ });
184
+
185
+ test("approval: an existing store must remain private to its owner", async () => {
186
+ if (process.platform === "win32") return;
187
+ const s = sandbox();
188
+ try {
189
+ s.write("ok.mjs", "console.log('OK');\n");
190
+ s.write("GATES.md", gate("G1", "private approval store", "node ok.mjs", "OK"));
191
+ chmodSync(s.approvals, 0o755);
192
+ const result = await gateRun(s, [], { approve: false });
193
+ assert(result.code === 2, result.out);
194
+ has(result.out, "must not grant group or other permissions");
195
+ } finally { s.cleanup(); }
196
+ });
197
+
198
+ test("approval: a FIFO record is rejected without blocking or executing", async () => {
199
+ if (process.platform === "win32") return;
200
+ const s = sandbox();
201
+ try {
202
+ s.write("marker.mjs", "import { writeFileSync } from 'node:fs'; writeFileSync('ran.txt','yes'); console.log('OK');\n");
203
+ s.write("GATES.md", gate("G1", "regular approval record", "node marker.mjs", "OK"));
204
+ const first = await gateRun(s, []);
205
+ assert(first.code === 0, first.out);
206
+ const token = readdirSync(s.approvals).find((name) => name.endsWith(".json"));
207
+ assert(token, "approval token was not created");
208
+ rmSync(join(s.approvals, token));
209
+ const made = spawnSync("mkfifo", [join(s.approvals, token)], { encoding: "utf8" });
210
+ assert(made.status === 0, "could not create FIFO fixture: " + made.stderr);
211
+ rmSync(s.path("ran.txt"), { force: true });
212
+ s.write("GATES.md", gate("G1", "regular approval record", "node marker.mjs", "OK"));
213
+
214
+ const started = Date.now();
215
+ const replay = await gateRun(s, [], { approve: false });
216
+ assert(replay.code === 2, replay.out);
217
+ assert(Date.now() - started < 1800, "FIFO approval record blocked");
218
+ has(replay.out, "could not validate approval");
219
+ assert(!existsSync(s.path("ran.txt")), "FIFO record authorized CHECK execution");
220
+ } finally { s.cleanup(); }
221
+ });
222
+
223
+ test("shell: resolution and PATH context are visible, invalid overrides are usage errors", async () => {
224
+ const s = sandbox();
225
+ try {
226
+ s.write("ok.mjs", "console.log('SHELL-OK');\n");
227
+ s.write("GATES.md", gate("G1", "shell", "node ok.mjs", "SHELL-OK"));
228
+ const good = await gateRun(s, []);
229
+ assert(good.code === 0, good.out);
230
+ has(good.out, "shell=");
231
+ has(good.out, "PATH=");
232
+ const ledger = s.read("GATES.md");
233
+ has(ledger, "exit=0; shell=");
234
+ has(ledger, "; path=");
235
+ s.write("GATES.md", gate("G1", "shell", "node ok.mjs", "SHELL-OK"));
236
+ const bad = await gateRun(s, ["--shell", "definitely-missing-shell"], { approve: false });
237
+ assert(bad.code === 2, bad.out);
238
+ has(bad.out, "cannot resolve command shell");
239
+ } finally { s.cleanup(); }
240
+ });
241
+
242
+ test("execution: exit zero and EXPECT must both pass", async () => {
243
+ const s = sandbox();
244
+ try {
245
+ s.write("bad.mjs", "console.log('MATCH'); process.exitCode = 7;\n");
246
+ s.write("GATES.md", gate("G1", "nonzero", "node bad.mjs", "MATCH"));
247
+ const result = await gateRun(s, []);
248
+ assert(result.code === 1, result.out);
249
+ has(result.out, "exit=7; EXPECT=matched");
250
+ has(s.read("GATES.md"), "- [ ] G1");
251
+ } finally { s.cleanup(); }
252
+ });
253
+
254
+ test("execution: failure summaries retain early assertion diagnostics", async () => {
255
+ const s = sandbox();
256
+ try {
257
+ s.write("bad.mjs", [
258
+ "console.error('AssertionError: expected 3 but received 4');",
259
+ "for (let index = 0; index < 20; index++) console.error('trailer-' + index);",
260
+ "process.exitCode = 1;",
261
+ "",
262
+ ].join("\n"));
263
+ s.write("GATES.md", gate("G1", "diagnostic", "node bad.mjs", "WILL-NOT-MATCH"));
264
+ const result = await gateRun(s, []);
265
+ assert(result.code === 1, result.out);
266
+ has(result.out, "AssertionError: expected 3 but received 4");
267
+ has(result.out, "trailer-19");
268
+ } finally { s.cleanup(); }
269
+ });
270
+
271
+ test("evidence: successful output is fingerprinted instead of persisted or echoed", async () => {
272
+ const s = sandbox();
273
+ const sentinel = "token-shaped-private-value-7f13b9";
274
+ try {
275
+ s.write("private.mjs", "console.log('" + sentinel + "'); console.log('CHECK_OK');\n");
276
+ s.write("GATES.md", gate("G1", "private output", "node private.mjs", "CHECK_OK"));
277
+ const result = await gateRun(s, []);
278
+ assert(result.code === 0, result.out);
279
+ lacks(result.out, sentinel, "success transcript");
280
+ has(result.out, "output=sha256=");
281
+ const ledger = s.read("GATES.md");
282
+ lacks(ledger, sentinel, "persisted evidence");
283
+ has(ledger, "EXPECT=matched; output-sha256=");
284
+ has(ledger, "; output-bytes=");
285
+ } finally { s.cleanup(); }
286
+ });
287
+
288
+ test("terminal: repository titles and diagnostics cannot emit controls or bidi overrides", async () => {
289
+ const s = sandbox();
290
+ try {
291
+ s.write("GATES.md", "- [ ] G1: title\u001b]0;owned\u0007\u202eevil\n EVIDENCE: pending\n");
292
+ const status = await gateRun(s, ["--status"], { approve: false });
293
+ assert(status.code === 1, status.out);
294
+ assert(!/[\u001b\u0007\u202e]/.test(status.out), "terminal controls survived status output");
295
+
296
+ s.write("bad.mjs", "console.error('failure\\u001b[31m red\\u001b[0m'); process.exitCode=1;\n");
297
+ s.write("GATES.md", gate("G2", "controlled failure", "node bad.mjs", "NEVER"));
298
+ const failed = await gateRun(s, []);
299
+ assert(failed.code === 1, failed.out);
300
+ assert(!failed.out.includes("\u001b"), "terminal escape survived failure output");
301
+ has(failed.out, "failure [31m red [0m");
302
+ } finally { s.cleanup(); }
303
+ });
304
+
305
+ test("reverify: a stale success is demoted and a reproducible success stays met", async () => {
306
+ const s = sandbox();
307
+ try {
308
+ s.write("bad.mjs", "console.log('WRONG');\n");
309
+ s.write("GATES.md", "- [x] G1: forged\n CHECK: node bad.mjs\n EXPECT: RIGHT\n EVIDENCE: forged\n");
310
+ const plain = await gateRun(s, []);
311
+ assert(plain.code === 0, plain.out);
312
+ const failed = await gateRun(s, ["--reverify"]);
313
+ assert(failed.code === 1, failed.out);
314
+ has(failed.out, "FAIL GATES:G1");
315
+ has(s.read("GATES.md"), "- [ ] G1");
316
+ has(s.read("GATES.md"), "EVIDENCE: pending");
317
+ s.write("good.mjs", "console.log('RIGHT');\n");
318
+ s.write("GATES.md", "- [x] G1: real\n CHECK: node good.mjs\n EXPECT: RIGHT\n EVIDENCE: RIGHT\n");
319
+ const passed = await gateRun(s, ["--reverify"]);
320
+ assert(passed.code === 0, passed.out);
321
+ has(passed.out, "reverified: 1");
322
+ } finally { s.cleanup(); }
323
+ });
324
+
325
+ test("parser: fenced examples are ignored and CRLF plus missing EVIDENCE are preserved", async () => {
326
+ const s = sandbox();
327
+ try {
328
+ s.write("ok.mjs", "console.log('OK');\n");
329
+ s.write("GATES.md", [
330
+ "- [ ] G1: real", " CHECK: node ok.mjs", " EXPECT: OK",
331
+ "```markdown", "- [ ] BAD: example", " CHECK: node absent.mjs", " EXPECT: BAD", "```", "",
332
+ ].join("\r\n"));
333
+ const result = await gateRun(s, []);
334
+ assert(result.code === 0, result.out);
335
+ lacks(result.out, "BAD:");
336
+ const after = s.read("GATES.md");
337
+ has(after, "- [x] G1: real\r\n");
338
+ has(after, "EVIDENCE: exit=0;");
339
+ assert(!/(^|[^\r])\n/.test(after), "write introduced bare LF");
340
+ } finally { s.cleanup(); }
341
+ });
342
+
343
+ test("parser: Markdown fence length and closing syntax are respected", async () => {
344
+ const s = sandbox();
345
+ try {
346
+ s.write("ok.mjs", "console.log('REAL-OK');\n");
347
+ s.write("GATES.md", [
348
+ "# Gates",
349
+ "",
350
+ "````markdown",
351
+ "```",
352
+ "- [ ] FAKE: remains fenced",
353
+ " CHECK: node absent.mjs",
354
+ " EXPECT: FAKE",
355
+ "```not-a-closing-fence",
356
+ "````",
357
+ "",
358
+ "- [ ] G1: real gate after the fence",
359
+ " CHECK: node ok.mjs",
360
+ " EXPECT: REAL-OK",
361
+ " EVIDENCE: pending",
362
+ "",
363
+ ].join("\n"));
364
+ const result = await gateRun(s, []);
365
+ assert(result.code === 0, result.out);
366
+ lacks(result.out, "FAKE:");
367
+ has(result.out, "PASS GATES:G1");
368
+ } finally { s.cleanup(); }
369
+ });
370
+
371
+ test("parser: malformed ledgers are usage errors in checker and blocking in hook", async () => {
372
+ const cases = [
373
+ ["zero", "# Gates only\n", "zero live gates"],
374
+ ["duplicate", "- [ ] G1: a\n EVIDENCE: pending\n- [ ] G1: b\n EVIDENCE: pending\n", "duplicate gate id"],
375
+ ["blank abandon", "- [ ] G1: a\n EVIDENCE: pending\nABANDON: G1\n", "non-blank reason"],
376
+ ["invalid regex", "- [ ] G1: a\n CHECK: node x.mjs\n EXPECT: /[/\n EVIDENCE: pending\n", "invalid EXPECT regex"],
377
+ ["incomplete", "- [ ] G1: a\n CHECK: node x.mjs\n EVIDENCE: pending\n", "require both"],
378
+ ["unindented", "- [ ] G1: a\nCHECK: node x.mjs\nEXPECT: OK\nEVIDENCE: pending\n", "unindented"],
379
+ ["orphan attribute", " CHECK: node x.mjs\n- [ ] G1: manual\n EVIDENCE: pending\n", "orphan CHECK"],
380
+ ["missing id", "- [ ] outcome without id\n EVIDENCE: pending\n", "explicit ID"],
381
+ ["blank outcome", "- [ ] G1:\n EVIDENCE: pending\n", "outcome is blank"],
382
+ ["unknown abandon", "- [x] G1: done\n EVIDENCE: measured\nABANDON: TYPO wrong id\n", "ABANDON references unknown gate"],
383
+ ];
384
+ for (const [name, text, expected] of cases) {
385
+ const s = sandbox();
386
+ try {
387
+ s.write("GATES.md", text);
388
+ const status = await gateRun(s, ["--status"], { approve: false });
389
+ assert(status.code === 2, name + " should exit 2\n" + status.out);
390
+ has(status.out, expected, name);
391
+ const hook = await run(STOP_HOOK, [], { cwd: s.dir, stdin: JSON.stringify({ cwd: s.dir, session_id: name }) });
392
+ has(hook.out, '"decision":"block"', name + " hook");
393
+ has(hook.out, "PARSE", name + " hook");
394
+ } finally { s.cleanup(); }
395
+ }
396
+ });
397
+
398
+ test("regex: a decisive regex succeeds and catastrophic matching is bounded", async () => {
399
+ const s = sandbox();
400
+ try {
401
+ s.write("good.mjs", "console.log('total: 42 items');\n");
402
+ s.write("GATES.md", gate("G1", "regex", "node good.mjs", "/total: \\d+ items/"));
403
+ const good = await gateRun(s, []);
404
+ assert(good.code === 0, good.out);
405
+ s.write("evil.mjs", "console.log('a'.repeat(30000) + '!');\n");
406
+ s.write("GATES.md", gate("G1", "bounded", "node evil.mjs", "/(a+)+$/"));
407
+ const start = Date.now();
408
+ const bad = await gateRun(s, []);
409
+ const elapsed = Date.now() - start;
410
+ assert(bad.code === 1, bad.out);
411
+ has(bad.out, "EXPECT regex exceeded 250ms");
412
+ assert(elapsed < 5000, "regex run was not bounded: " + elapsed + "ms");
413
+ } finally { s.cleanup(); }
414
+ });
415
+
416
+ test("regex: worker startup is outside the match budget and concurrency is capped", async () => {
417
+ const s = sandbox();
418
+ try {
419
+ s.write("simple.mjs", "console.log('total: 42 items');\n");
420
+ let ledger = "";
421
+ for (let index = 1; index <= 32; index++) {
422
+ ledger += gate("G" + index, "simple regex " + index, "node simple.mjs", "/total: \\d+ items/");
423
+ }
424
+ s.write("GATES.md", ledger);
425
+ const result = await gateRun(s, ["--jobs", "32", "--timeout", "10"]);
426
+ assert(result.code === 0, result.out);
427
+ lacks(result.out, "worker startup exceeded");
428
+ lacks(result.out, "EXPECT regex exceeded");
429
+ has(result.out, "PASS GATES:G32");
430
+ } finally { s.cleanup(); }
431
+ });
432
+
433
+ test("execution: output is capped and overflow cannot certify a gate", async () => {
434
+ const s = sandbox();
435
+ try {
436
+ s.write("large.mjs", "process.stdout.write('x'.repeat(1100000)); console.log('FINAL');\n");
437
+ s.write("GATES.md", gate("G1", "bounded output", "node large.mjs", "FINAL"));
438
+ const result = await gateRun(s, []);
439
+ assert(result.code === 1, result.out.slice(-2000));
440
+ has(result.out, "output exceeded 1048576 bytes");
441
+ assert(result.out.length < 1100000, "transcript leaked the full output");
442
+ } finally { s.cleanup(); }
443
+ });
444
+
445
+ test("jobs: rolling concurrency is opt-in and output stays in gate order", async () => {
446
+ const s = sandbox();
447
+ try {
448
+ for (let index = 1; index <= 3; index++) {
449
+ s.write("g" + index + ".mjs",
450
+ "import { appendFileSync } from 'node:fs';\n" +
451
+ "appendFileSync('order.log','start" + index + "\\n');\n" +
452
+ "setTimeout(()=>{appendFileSync('order.log','end" + index + "\\n'); console.log('OK" + index + "');},250);\n");
453
+ }
454
+ s.write("GATES.md", gate("G1", "one", "node g1.mjs", "OK1") +
455
+ gate("G2", "two", "node g2.mjs", "OK2") + gate("G3", "three", "node g3.mjs", "OK3"));
456
+ const result = await gateRun(s, ["--jobs", "2"]);
457
+ assert(result.code === 0, result.out);
458
+ const order = s.read("order.log").trim().split(/\r?\n/);
459
+ const firstEnd = order.findIndex((line) => line.startsWith("end"));
460
+ assert(firstEnd >= 2, "two checks did not overlap: " + order.join(","));
461
+ assert(result.out.indexOf("PASS GATES:G1") < result.out.indexOf("PASS GATES:G2") &&
462
+ result.out.indexOf("PASS GATES:G2") < result.out.indexOf("PASS GATES:G3"), "transcript order was nondeterministic\n" + result.out);
463
+ } finally { s.cleanup(); }
464
+ });
465
+
466
+ test("jobs: runner waits for stdio close so delayed descendant output is visible", async () => {
467
+ const s = sandbox();
468
+ try {
469
+ s.write("delayed.mjs",
470
+ "import { spawn } from 'node:child_process';\n" +
471
+ "spawn(process.execPath,['-e',\"setTimeout(()=>console.log('LATE_OK'),250)\"],{stdio:['ignore','inherit','inherit']});\n");
472
+ s.write("GATES.md", gate("G1", "late output", "node delayed.mjs", "LATE_OK"));
473
+ const result = await gateRun(s, []);
474
+ assert(result.code === 0, result.out);
475
+ has(result.out, "PASS GATES:G1");
476
+ has(result.out, "output=sha256=");
477
+ // EXPECT is printed during approval; the successful process output itself
478
+ // is represented only by the fingerprint above.
479
+ } finally { s.cleanup(); }
480
+ });
481
+
482
+ test("writeback: a result cannot certify a gate whose oracle changed in flight", async () => {
483
+ const s = sandbox();
484
+ try {
485
+ s.write("slow.mjs", "import { writeFileSync } from 'node:fs'; writeFileSync('started.txt','yes'); setTimeout(()=>console.log('OLD'),800);\n");
486
+ s.write("GATES.md", gate("G1", "stale", "node slow.mjs", "OLD"));
487
+ const running = gateRun(s, []);
488
+ await waitForPath(s.path("started.txt"));
489
+ s.write("GATES.md", gate("G1", "stale", "node slow.mjs", "NEW"));
490
+ const result = await running;
491
+ has(result.out, "STALE GATES:G1");
492
+ const after = s.read("GATES.md");
493
+ has(after, "EXPECT: NEW");
494
+ has(after, "- [ ] G1");
495
+ } finally { s.cleanup(); }
496
+ });
497
+
498
+ test("reverify: a stale in-flight result cannot leave old evidence falsely green", async () => {
499
+ const s = sandbox();
500
+ try {
501
+ s.write("slow.mjs", "import { writeFileSync } from 'node:fs'; writeFileSync('started.txt','yes'); setTimeout(()=>console.log('OLD'),800);\n");
502
+ s.write("GATES.md", "- [x] G1: stale met\n CHECK: node slow.mjs\n EXPECT: OLD\n EVIDENCE: old evidence\n");
503
+ const running = gateRun(s, ["--reverify"]);
504
+ await waitForPath(s.path("started.txt"));
505
+ s.write("GATES.md", "- [x] G1: stale met\n CHECK: node slow.mjs\n EXPECT: NEW\n EVIDENCE: old evidence\n");
506
+ const result = await running;
507
+ assert(result.code === 1, "stale reverify returned " + result.code + "\n" + result.out);
508
+ has(result.out, "STALE GATES:G1");
509
+ has(result.out, "GATES:G1 (stale result discarded)");
510
+ lacks(result.out, "ALL MET");
511
+ lacks(result.out, "reverified: 1");
512
+ assert(s.read("GATES.md").includes("EXPECT: NEW\n EVIDENCE: old evidence"), "newer ledger was clobbered");
513
+ } finally { s.cleanup(); }
514
+ });
515
+
516
+ test("CLI: numeric bounds, incompatible modes, and file types fail with exit 2", async () => {
517
+ const s = sandbox();
518
+ try {
519
+ s.write("GATES.md", "- [ ] G1: manual\n EVIDENCE: pending\n");
520
+ mkdirSync(s.path("directory.md"));
521
+ const cases = [
522
+ ["--jobs", "0"], ["--jobs", "1.5"], ["--jobs", "Infinity"], ["--jobs", "65"],
523
+ ["--timeout", "0"], ["--timeout", "1.5"], ["--timeout", "86401"], ["--timeout", "Infinity"], ["--timeout"],
524
+ ["--status", "--reverify"], ["--status", "--approve"], ["directory.md"],
525
+ ];
526
+ for (const args of cases) {
527
+ const result = await gateRun(s, args, { approve: false });
528
+ assert(result.code === 2, args.join(" ") + " expected 2, got " + result.code + "\n" + result.out);
529
+ }
530
+ } finally { s.cleanup(); }
531
+ });
532
+
533
+ test("CLI: trusted help layout remains multiline", async () => {
534
+ const s = sandbox();
535
+ try {
536
+ const result = await gateRun(s, ["--help"], { approve: false });
537
+ assert(result.code === 0, result.out);
538
+ has(result.out, "usage: gate-check.mjs [options] [file ...]\n\nrun modes:\n");
539
+ has(result.out, "\npipeline actions:\n");
540
+ assert(result.out.trimEnd().split("\n").length > 20, "help output was flattened\n" + result.out);
541
+ } finally { s.cleanup(); }
542
+ });
543
+
544
+ test("targeting: explicit files anchor relative commands and every positional file is honored", async () => {
545
+ const s = sandbox();
546
+ try {
547
+ for (const name of ["a", "b"]) {
548
+ s.write(name + "/check.mjs", "console.log('" + name.toUpperCase() + "');\n");
549
+ s.write(name + "/leaf.md", gate("G1", name, "node check.mjs", name.toUpperCase()));
550
+ }
551
+ const result = await gateRun(s, ["--timeout", "5", "a/leaf.md", "b/leaf.md"]);
552
+ assert(result.code === 0, result.out);
553
+ has(result.out, "PASS leaf:G1");
554
+ has(s.read("a/leaf.md"), "cwd=" + realpathSync(join(s.dir, "a")));
555
+ has(s.read("b/leaf.md"), "cwd=" + realpathSync(join(s.dir, "b")));
556
+ } finally { s.cleanup(); }
557
+ });
558
+
559
+ test("leases: unsafe declarations, unknown leaves, and wildcard witnesses fail closed", async () => {
560
+ const s = sandbox();
561
+ try {
562
+ s.write(".unlazy/a/gates/leaf-a.md", "OWNS: src/a*.js\n\n" + gate("G1", "a", null, null));
563
+ s.write(".unlazy/b/gates/leaf-b.md", "OWNS: src/ab*.js\n\n" + gate("G1", "b", null, null));
564
+ const first = await gateRun(s, ["--scope", "a", "--leaf", "leaf-a", "--claim"], { approve: false });
565
+ assert(first.code === 0, first.out);
566
+ const overlap = await gateRun(s, ["--scope", "b", "--leaf", "leaf-b", "--claim"], { approve: false });
567
+ assert(overlap.code === 3, overlap.out);
568
+ has(overlap.out, "CONFLICT src/ab*.js overlaps src/a*.js");
569
+ const unknown = await gateRun(s, ["--scope", "a", "--leaf", "missing", "--claim"], { approve: false });
570
+ assert(unknown.code === 2, unknown.out);
571
+ has(unknown.out, "unknown --leaf missing");
572
+ const released = await gateRun(s, ["--scope", "a", "--release"], { approve: false });
573
+ assert(released.code === 0, released.out);
574
+ s.write(".unlazy/dot-a/gates/leaf.md", "OWNS: src/./same.js\n\n" + gate("G1", "dot a", null, null));
575
+ s.write(".unlazy/dot-b/gates/leaf.md", "OWNS: src/same.js\n\n" + gate("G1", "dot b", null, null));
576
+ const dotFirst = await gateRun(s, ["--scope", "dot-a", "--leaf", "leaf", "--claim"], { approve: false });
577
+ assert(dotFirst.code === 0, dotFirst.out);
578
+ has(dotFirst.out, "src/same.js");
579
+ const dotOverlap = await gateRun(s, ["--scope", "dot-b", "--leaf", "leaf", "--claim"], { approve: false });
580
+ assert(dotOverlap.code === 3, dotOverlap.out);
581
+ has(dotOverlap.out, "CONFLICT src/same.js overlaps src/same.js");
582
+ await gateRun(s, ["--scope", "dot-a", "--release"], { approve: false });
583
+ s.write(".unlazy/prefix-a/gates/leaf.md", "OWNS: src/api\n\n" + gate("G1", "prefix a", null, null));
584
+ s.write(".unlazy/prefix-b/gates/leaf.md", "OWNS: src/api/**\n\n" + gate("G1", "prefix b", null, null));
585
+ const prefixFirst = await gateRun(s, ["--scope", "prefix-a", "--leaf", "leaf", "--claim"], { approve: false });
586
+ assert(prefixFirst.code === 0, prefixFirst.out);
587
+ const prefixOverlap = await gateRun(s, ["--scope", "prefix-b", "--leaf", "leaf", "--claim"], { approve: false });
588
+ assert(prefixOverlap.code === 3, prefixOverlap.out);
589
+ has(prefixOverlap.out, "CONFLICT src/api/** overlaps src/api");
590
+ s.write(".unlazy/c/gates/leaf-c.md", "OWNS: ../outside/**\n\n" + gate("G1", "c", null, null));
591
+ const unsafe = await gateRun(s, ["--scope", "c", "--leaf", "leaf-c", "--claim"], { approve: false });
592
+ assert(unsafe.code === 2, unsafe.out);
593
+ has(unsafe.out, "cannot contain traversal");
594
+ } finally { s.cleanup(); }
595
+ });
596
+
597
+ test("parser: an indented ABANDON is diagnosed instead of silently ignored", async () => {
598
+ const s = sandbox();
599
+ try {
600
+ // Every other attribute must be indented, so indenting the abandonment is
601
+ // the natural mistake. Ignoring the line silently leaves the gate unmet
602
+ // with no diagnostic, so the honest exit fails for a formatting reason the
603
+ // author is never told about.
604
+ s.write("GATES.md", [
605
+ "# Gates: indented abandonment",
606
+ "",
607
+ "Scope: an abandonment indented like every other attribute",
608
+ "",
609
+ "- [ ] G1: upstream export reconciles",
610
+ " EVIDENCE: pending",
611
+ " ABANDON: G1 upstream export was withdrawn",
612
+ "",
613
+ ].join("\n"));
614
+ const result = await gateRun(s, ["--status"], { approve: false });
615
+ assert(result.code === 2, "expected a parse error, got " + result.code + "\n" + result.out);
616
+ has(result.out, "indented ABANDON");
617
+ has(result.out, "column 1");
618
+ } finally { s.cleanup(); }
619
+ });
620
+
621
+ test("parser: a slash wrapped literal path warns that it became a regex", async () => {
622
+ const s = sandbox();
623
+ try {
624
+ // "/etc/app/conf/" is a plausible literal expectation, and the slash sniff
625
+ // silently turns it into the pattern etc/app/conf, whose dots would be
626
+ // wildcards. There is no way to express that literal, so the author needs
627
+ // to be told which reading applies.
628
+ s.write("show.mjs", "console.log('resolved /etc/app/conf/');\n");
629
+ s.write("GATES.md", gate("G1", "config path is reported", "node show.mjs", "/etc/app/conf/"));
630
+ const warned = await gateRun(s, ["--status"], { approve: false });
631
+ has(warned.out, "G1");
632
+ has(warned.out, "read as a regular expression");
633
+ assert(warned.code === 1, "a warning must not become a parse error, got " + warned.code);
634
+
635
+ // A deliberate pattern carries no unescaped inner slash and stays quiet.
636
+ s.write("GATES.md", gate("G2", "typecheck is clean", "node show.mjs", "/Found 0 errors/"));
637
+ const quiet = await gateRun(s, ["--status"], { approve: false });
638
+ lacks(quiet.out, "read as a regular expression");
639
+
640
+ // Escaping keeps the pattern reading without the warning.
641
+ s.write("GATES.md", gate("G3", "path pattern", "node show.mjs", "/etc\\/app/"));
642
+ const escaped = await gateRun(s, ["--status"], { approve: false });
643
+ lacks(escaped.out, "read as a regular expression");
644
+ } finally { s.cleanup(); }
645
+ });
646
+
647
+ test("win32 cleanup: taskkill ENOENT invokes child.kill fallback", async () => {
648
+ const calls = [];
649
+ const child = { pid: 4242, kill(signal) { calls.push(signal); return true; } };
650
+ const result = terminateProcessTree(child, {
651
+ platform: "win32",
652
+ env: { ...WINDOWS_ENV, PATH: "C:\\shadow" },
653
+ spawnSyncImpl: () => ({ status: null, signal: null, error: Object.assign(new Error("missing"), { code: "ENOENT" }) }),
654
+ });
655
+ assert(result.fallback && result.ok, JSON.stringify(result));
656
+ assert(calls.join(",") === "SIGKILL", "expected SIGKILL fallback, got " + calls.join(","));
657
+ has(result.diagnostic, "ENOENT");
658
+ });
659
+
660
+ test("win32 cleanup: taskkill itself has a bounded timeout", async () => {
661
+ const calls = [];
662
+ let invocation = null;
663
+ const child = { pid: 4243, kill(signal) { calls.push(signal); return true; } };
664
+ const result = terminateProcessTree(child, {
665
+ platform: "win32",
666
+ env: WINDOWS_ENV,
667
+ spawnSyncImpl: (command, args, options) => {
668
+ invocation = { command, args, options };
669
+ return { status: null, signal: "SIGKILL", error: Object.assign(new Error("timed out"), { code: "ETIMEDOUT" }) };
670
+ },
671
+ });
672
+ assert(invocation.options.timeout === WINDOWS_TASKKILL_TIMEOUT_MS, JSON.stringify(invocation));
673
+ assert(invocation.options.killSignal === "SIGKILL", JSON.stringify(invocation));
674
+ assert(result.ok && result.fallback, JSON.stringify(result));
675
+ assert(calls.join(",") === "SIGKILL", "helper timeout did not request direct fallback");
676
+ has(result.diagnostic, "ETIMEDOUT");
677
+ });
678
+
679
+ test("win32 cleanup: nonzero taskkill status invokes fallback and checker settles", async () => {
680
+ const calls = [];
681
+ const child = { pid: 4343, kill(signal) { calls.push(signal); return true; } };
682
+ const result = terminateProcessTree(child, {
683
+ platform: "win32",
684
+ env: WINDOWS_ENV,
685
+ spawnSyncImpl: () => ({ status: 5, signal: null, error: null }),
686
+ });
687
+ assert(result.fallback && result.ok, JSON.stringify(result));
688
+ assert(calls.length === 1, "fallback was not requested exactly once");
689
+ has(result.diagnostic, "exit 5");
690
+ });
691
+
692
+ test("win32 cleanup: a false child.kill result is reported as fallback failure", async () => {
693
+ const child = { pid: 4444, kill() { return false; } };
694
+ const result = terminateProcessTree(child, {
695
+ platform: "win32",
696
+ env: WINDOWS_ENV,
697
+ spawnSyncImpl: () => ({ status: 5, signal: null, error: null }),
698
+ });
699
+ assert(!result.ok && result.fallback, JSON.stringify(result));
700
+ has(result.diagnostic, "returned false");
701
+ });
702
+
703
+ test("win32 cleanup: internal taskkill resolution cannot be shadowed by test PATH", async () => {
704
+ const expected = win32.join("C:\\Windows", "System32", "taskkill.exe");
705
+ const resolved = windowsTaskkillPath({ ...WINDOWS_ENV, PATH: "C:\\attacker" });
706
+ assert(resolved === expected, "expected system taskkill, got " + resolved);
707
+ lacks(resolved.toLowerCase(), "attacker");
708
+ });
709
+
710
+ test("win32 cleanup: a non-C system drive keeps protected tree cleanup", async () => {
711
+ const expected = win32.join("D:\\Windows", "System32", "taskkill.exe");
712
+ const resolved = windowsTaskkillPath({
713
+ SystemRoot: "D:\\Windows",
714
+ WINDIR: "D:\\Windows",
715
+ SystemDrive: "D:",
716
+ PATH: "D:\\repo",
717
+ });
718
+ assert(resolved === expected, "expected non-C system taskkill, got " + resolved);
719
+ });
720
+
721
+ test("win32 cleanup: inconsistent system directory variables fail closed", async () => {
722
+ const mismatches = [
723
+ { SystemRoot: "D:\\Windows", WINDIR: "C:\\Windows", SystemDrive: "C:" },
724
+ { SystemRoot: "D:\\Windows", WINDIR: "D:\\Windows", SystemDrive: "C:" },
725
+ { SystemRoot: "D:\\Windows", WINDIR: "D:\\Windows" },
726
+ ];
727
+ for (const env of mismatches) {
728
+ assert(windowsTaskkillPath(env) === null, "trusted inconsistent Windows environment: " + JSON.stringify(env));
729
+ }
730
+ });
731
+
732
+ test("win32 cleanup: missing trusted system root skips PATH lookup", async () => {
733
+ let spawned = false;
734
+ let killed = false;
735
+ const child = { pid: 4545, kill() { killed = true; return true; } };
736
+ const result = terminateProcessTree(child, {
737
+ platform: "win32",
738
+ env: { PATH: "C:\\attacker" },
739
+ spawnSyncImpl: () => { spawned = true; return { status: 0 }; },
740
+ });
741
+ assert(windowsTaskkillPath({ PATH: "C:\\attacker" }) === null, "bare taskkill fallback remained enabled");
742
+ assert(!spawned, "untrusted PATH was used to resolve taskkill");
743
+ assert(killed && result.ok && result.fallback, JSON.stringify(result));
744
+ has(result.diagnostic, "trusted system taskkill path unavailable");
745
+ });
746
+
747
+ test("win32 cleanup: an arbitrary absolute SystemRoot is not executable trust", async () => {
748
+ let spawned = false;
749
+ let killed = false;
750
+ const child = { pid: 4546, kill() { killed = true; return true; } };
751
+ const hostile = { SystemRoot: "C:\\repo\\fake-windows", PATH: "C:\\repo" };
752
+ const result = terminateProcessTree(child, {
753
+ platform: "win32",
754
+ env: hostile,
755
+ spawnSyncImpl: () => { spawned = true; return { status: 0 }; },
756
+ });
757
+ assert(windowsTaskkillPath(hostile) === null, "repository SystemRoot was trusted");
758
+ assert(!spawned && killed && result.ok && result.fallback, JSON.stringify(result));
759
+ });
760
+
761
+ test("cleanup: an already-exited child is never signalled through a reusable PID", async () => {
762
+ let spawned = false;
763
+ let killed = false;
764
+ const child = { pid: 4646, exitCode: 0, signalCode: null, kill() { killed = true; return true; } };
765
+ const result = terminateProcessTree(child, {
766
+ platform: "win32",
767
+ env: WINDOWS_ENV,
768
+ spawnSyncImpl: () => { spawned = true; return { status: 0 }; },
769
+ });
770
+ assert(result.ok && result.diagnostic === "child already exited", JSON.stringify(result));
771
+ assert(!spawned && !killed, "an exited child PID was reused for cleanup");
772
+ });
773
+
774
+ test("posix cleanup: an exited supervisor never targets a reusable process group", async () => {
775
+ let group = null;
776
+ let direct = false;
777
+ const child = { pid: 4747, exitCode: 0, signalCode: null, kill() { direct = true; return true; } };
778
+ const result = terminateProcessTree(child, {
779
+ platform: "linux",
780
+ killGroup(pid, signal) { group = { pid, signal }; },
781
+ });
782
+ assert(result.ok && !result.fallback, JSON.stringify(result));
783
+ assert(result.diagnostic === "process supervisor already exited", JSON.stringify(result));
784
+ assert(group === null && !direct, "an exited supervisor's reusable PID/PGID was signalled");
785
+ });
786
+
787
+ test("win32 integration: a timed-out shell and nested descendant are both reaped", async () => {
788
+ if (process.platform !== "win32") return;
789
+ const s = sandbox();
790
+ const pids = [];
791
+ try {
792
+ s.write("descendant.mjs", "setInterval(() => {}, 1000);\n");
793
+ s.write("parent.mjs", [
794
+ "import { spawn } from 'node:child_process';",
795
+ "import { writeFileSync } from 'node:fs';",
796
+ "writeFileSync('shell.pid', String(process.ppid));",
797
+ "const child = spawn(process.execPath, ['descendant.mjs'], { stdio: 'inherit' });",
798
+ "writeFileSync('descendant.pid', String(child.pid));",
799
+ "setInterval(() => {}, 1000);",
800
+ "",
801
+ ].join("\n"));
802
+ s.write("GATES.md", gate("G1", "nested process times out", "node parent.mjs", "never printed"));
803
+ const started = Date.now();
804
+ const result = await gateRun(s, ["--timeout", "1"]);
805
+ const elapsed = Date.now() - started;
806
+ assert(result.code === 1, result.out);
807
+ has(result.out, "timed out after 1s");
808
+ assert(elapsed < 12000, "bounded timeout took " + elapsed + "ms\n" + result.out);
809
+ await waitForPath(s.path("shell.pid"));
810
+ await waitForPath(s.path("descendant.pid"));
811
+ pids.push(Number(s.read("shell.pid")), Number(s.read("descendant.pid")));
812
+ assert(pids.every((pid) => Number.isInteger(pid) && pid > 0), "invalid captured PIDs: " + pids.join(","));
813
+ await Promise.all(pids.map((pid) => waitForProcessExit(pid)));
814
+ } finally {
815
+ for (const pid of pids) try { process.kill(pid, "SIGKILL"); } catch { /* already gone */ }
816
+ s.cleanup();
817
+ }
818
+ });
819
+
820
+ test("execution: timeout settlement is bounded even when a detached descendant keeps pipes", async () => {
821
+ const s = sandbox();
822
+ let descendantPid = null;
823
+ try {
824
+ s.write("pipe-holder.mjs", "setInterval(() => {}, 1000);\n");
825
+ s.write("escape.mjs", [
826
+ "import { spawn } from 'node:child_process';",
827
+ "import { writeFileSync } from 'node:fs';",
828
+ "const child = spawn(process.execPath, ['pipe-holder.mjs'], { detached: true, stdio: ['ignore', 'inherit', 'inherit'] });",
829
+ "writeFileSync('pipe-holder.pid', String(child.pid));",
830
+ "child.unref();",
831
+ "setInterval(() => {}, 1000);",
832
+ "",
833
+ ].join("\n"));
834
+ s.write("GATES.md", gate("G1", "escaped pipe holder times out", "node escape.mjs", "never printed"));
835
+ const started = Date.now();
836
+ const result = await gateRun(s, ["--timeout", "1"]);
837
+ const elapsed = Date.now() - started;
838
+ assert(result.code === 1, result.out);
839
+ has(result.out, "timed out after 1s");
840
+ assert(elapsed < 7000, "checker did not settle independently after cleanup request: " + elapsed + "ms");
841
+ await waitForPath(s.path("pipe-holder.pid"));
842
+ descendantPid = Number(s.read("pipe-holder.pid"));
843
+ } finally {
844
+ if (Number.isInteger(descendantPid) && descendantPid > 0) {
845
+ try { process.kill(descendantPid, "SIGKILL"); } catch { /* already gone */ }
846
+ }
847
+ s.cleanup();
848
+ }
849
+ });
850
+
851
+ test("posix integration: an exited shell leader still has its ordinary descendants reaped", async () => {
852
+ if (process.platform === "win32") return;
853
+ const s = sandbox();
854
+ let descendantPid = null;
855
+ try {
856
+ s.write("ordinary-child.mjs", [
857
+ "import { writeFileSync } from 'node:fs';",
858
+ "setTimeout(() => writeFileSync('ordinary-marker.txt', 'survived'), 3000);",
859
+ "setInterval(() => {}, 1000);",
860
+ "",
861
+ ].join("\n"));
862
+ s.write("exiting-parent.mjs", [
863
+ "import { spawn } from 'node:child_process';",
864
+ "import { writeFileSync } from 'node:fs';",
865
+ "const child = spawn(process.execPath, ['ordinary-child.mjs'], { stdio: 'inherit' });",
866
+ "writeFileSync('ordinary-child.pid', String(child.pid));",
867
+ "child.unref();",
868
+ "",
869
+ ].join("\n"));
870
+ s.write("GATES.md", gate("G1", "orphaned group member times out", "node exiting-parent.mjs", "never printed"));
871
+ const result = await gateRun(s, ["--timeout", "1"]);
872
+ assert(result.code === 1, result.out);
873
+ has(result.out, "timed out after 1s");
874
+ has(result.out, "signal=SIGKILL");
875
+ await waitForPath(s.path("ordinary-child.pid"));
876
+ descendantPid = Number(s.read("ordinary-child.pid"));
877
+ await waitForProcessExit(descendantPid);
878
+ assert(!existsSync(s.path("ordinary-marker.txt")), "ordinary process-group descendant survived cleanup");
879
+ } finally {
880
+ if (Number.isInteger(descendantPid) && descendantPid > 0) {
881
+ try { process.kill(descendantPid, "SIGKILL"); } catch { /* already gone */ }
882
+ }
883
+ s.cleanup();
884
+ }
885
+ });
886
+
887
+ let passed = 0;
888
+ const failures = [];
889
+ for (const item of tests) {
890
+ try {
891
+ await item.fn();
892
+ passed++;
893
+ console.log("ok " + item.name);
894
+ } catch (error) {
895
+ failures.push(item.name);
896
+ console.log("FAIL " + item.name + "\n " + String(error.message).replace(/\n/g, "\n "));
897
+ }
898
+ }
899
+ console.log("\n" + passed + "/" + tests.length + " passed");
900
+ if (failures.length) {
901
+ console.log("failed: " + failures.join(", "));
902
+ process.exit(1);
903
+ }