gsd-pi 2.77.0-dev.58d3d4d6c → 2.77.0-dev.cfd69e714

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 (429) hide show
  1. package/README.md +1 -1
  2. package/dist/claude-cli-check.js +5 -1
  3. package/dist/headless.js +49 -4
  4. package/dist/resource-loader.d.ts +40 -0
  5. package/dist/resource-loader.js +32 -13
  6. package/dist/resources/extensions/browser-tools/capture.js +9 -0
  7. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  8. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  9. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  10. package/dist/resources/extensions/browser-tools/tools/forms.js +5 -1
  11. package/dist/resources/extensions/browser-tools/tools/intent.js +5 -1
  12. package/dist/resources/extensions/claude-code-cli/readiness.js +5 -1
  13. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +481 -17
  14. package/dist/resources/extensions/gsd/auto/loop.js +43 -0
  15. package/dist/resources/extensions/gsd/auto/phases.js +15 -21
  16. package/dist/resources/extensions/gsd/auto/session.js +0 -2
  17. package/dist/resources/extensions/gsd/auto-dispatch.js +102 -24
  18. package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
  19. package/dist/resources/extensions/gsd/auto-post-unit.js +71 -64
  20. package/dist/resources/extensions/gsd/auto-prompts.js +329 -102
  21. package/dist/resources/extensions/gsd/auto-recovery.js +195 -23
  22. package/dist/resources/extensions/gsd/auto-start.js +34 -24
  23. package/dist/resources/extensions/gsd/auto-tool-tracking.js +47 -7
  24. package/dist/resources/extensions/gsd/auto-worktree.js +122 -26
  25. package/dist/resources/extensions/gsd/auto.js +31 -20
  26. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +9 -1
  27. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +209 -0
  28. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +3 -6
  29. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -3
  30. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +127 -9
  31. package/dist/resources/extensions/gsd/component-loader.js +447 -0
  32. package/dist/resources/extensions/gsd/component-types.js +69 -0
  33. package/dist/resources/extensions/gsd/detection.js +49 -1
  34. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  35. package/dist/resources/extensions/gsd/gate-registry.js +2 -2
  36. package/dist/resources/extensions/gsd/git-constants.js +28 -1
  37. package/dist/resources/extensions/gsd/git-self-heal.js +27 -0
  38. package/dist/resources/extensions/gsd/git-service.js +126 -2
  39. package/dist/resources/extensions/gsd/gsd-db.js +6 -3
  40. package/dist/resources/extensions/gsd/guided-flow.js +17 -5
  41. package/dist/resources/extensions/gsd/memory-extractor.js +7 -1
  42. package/dist/resources/extensions/gsd/milestone-scope-classifier.js +299 -0
  43. package/dist/resources/extensions/gsd/model-cost-table.js +3 -0
  44. package/dist/resources/extensions/gsd/model-router.js +6 -0
  45. package/dist/resources/extensions/gsd/native-git-bridge.js +34 -4
  46. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  47. package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  48. package/dist/resources/extensions/gsd/safety/git-checkpoint.js +11 -0
  49. package/dist/resources/extensions/gsd/service-tier.js +5 -2
  50. package/dist/resources/extensions/gsd/session-lock.js +19 -10
  51. package/dist/resources/extensions/gsd/skill-manifest.js +168 -0
  52. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +278 -8
  53. package/dist/resources/extensions/gsd/state.js +44 -33
  54. package/dist/resources/extensions/gsd/sync-lock.js +98 -42
  55. package/dist/resources/extensions/gsd/unit-context-composer.js +147 -0
  56. package/dist/resources/extensions/gsd/unit-context-manifest.js +370 -0
  57. package/dist/resources/extensions/gsd/uok/gate-runner.js +53 -5
  58. package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
  59. package/dist/resources/extensions/gsd/worktree-manager.js +34 -8
  60. package/dist/resources/extensions/mcp-client/index.js +3 -1
  61. package/dist/resources/extensions/ollama/index.js +5 -1
  62. package/dist/resources/extensions/remote-questions/manager.js +11 -5
  63. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  64. package/dist/web/standalone/.next/BUILD_ID +1 -1
  65. package/dist/web/standalone/.next/app-path-routes-manifest.json +5 -5
  66. package/dist/web/standalone/.next/build-manifest.json +2 -2
  67. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  68. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  69. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  75. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  77. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  85. package/dist/web/standalone/.next/server/app/index.html +1 -1
  86. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app-paths-manifest.json +5 -5
  93. package/dist/web/standalone/.next/server/chunks/1926.js +1 -1
  94. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  95. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  96. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  97. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  98. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  99. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  100. package/package.json +2 -3
  101. package/packages/daemon/src/logger.ts +4 -3
  102. package/packages/mcp-server/dist/server.d.ts +24 -0
  103. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  104. package/packages/mcp-server/dist/server.js +88 -87
  105. package/packages/mcp-server/dist/server.js.map +1 -1
  106. package/packages/mcp-server/src/mcp-server.test.ts +25 -3
  107. package/packages/mcp-server/src/readers/graph.test.ts +87 -15
  108. package/packages/mcp-server/src/secure-env-collect.test.ts +232 -237
  109. package/packages/mcp-server/src/server.ts +131 -105
  110. package/packages/mcp-server/src/workflow-tools.test.ts +80 -39
  111. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  112. package/packages/native/package.json +1 -1
  113. package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
  114. package/packages/native/src/__tests__/module-compat.test.mjs +59 -27
  115. package/packages/native/src/__tests__/ps.test.mjs +14 -8
  116. package/packages/native/src/__tests__/stream-process.test.mjs +23 -2
  117. package/packages/native/src/__tests__/truncate.test.mjs +17 -2
  118. package/packages/pi-agent-core/src/agent-loop.test.ts +5 -15
  119. package/packages/pi-agent-core/src/agent.test.ts +96 -102
  120. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  121. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -1
  122. package/packages/pi-ai/dist/models/capability-patches.js +9 -2
  123. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -1
  124. package/packages/pi-ai/dist/models/generated/index.d.ts +34 -0
  125. package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
  126. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
  127. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
  128. package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
  129. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
  130. package/packages/pi-ai/dist/models/generated/openai.d.ts +17 -0
  131. package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -1
  132. package/packages/pi-ai/dist/models/generated/openai.js +17 -0
  133. package/packages/pi-ai/dist/models/generated/openai.js.map +1 -1
  134. package/packages/pi-ai/dist/models.generated.test.js +43 -70
  135. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  136. package/packages/pi-ai/dist/models.test.js +36 -11
  137. package/packages/pi-ai/dist/models.test.js.map +1 -1
  138. package/packages/pi-ai/scripts/generate-models.ts +44 -0
  139. package/packages/pi-ai/src/models/capability-patches.ts +10 -2
  140. package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
  141. package/packages/pi-ai/src/models/generated/openai.ts +17 -0
  142. package/packages/pi-ai/src/models.generated.test.ts +46 -73
  143. package/packages/pi-ai/src/models.test.ts +48 -11
  144. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  145. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +96 -32
  146. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  147. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js +75 -12
  148. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js.map +1 -1
  149. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +99 -31
  150. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  151. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
  152. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  153. package/packages/pi-coding-agent/dist/core/extensions/loader.js +61 -0
  154. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  155. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +30 -4
  156. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
  157. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +17 -0
  158. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  159. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +76 -18
  160. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -1
  161. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  162. package/packages/pi-coding-agent/dist/core/retry-handler.js +2 -6
  163. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  164. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +5 -1
  165. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  166. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts +18 -0
  167. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts.map +1 -0
  168. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js +18 -0
  169. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js.map +1 -0
  170. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +20 -0
  171. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  172. package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -2
  173. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  174. package/packages/pi-coding-agent/dist/index.d.ts +1 -0
  175. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  176. package/packages/pi-coding-agent/dist/index.js +1 -0
  177. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  178. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +20 -13
  179. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
  180. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  181. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +18 -3
  182. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  183. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +125 -0
  184. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +2 -0
  186. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  187. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  188. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
  189. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  190. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +105 -13
  191. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  192. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts +2 -0
  193. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts.map +1 -0
  194. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js +130 -0
  195. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js.map +1 -0
  196. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +113 -37
  197. package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +89 -17
  198. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +112 -43
  199. package/packages/pi-coding-agent/src/core/extensions/loader.ts +58 -0
  200. package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +35 -4
  201. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +20 -0
  202. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +93 -28
  203. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +5 -1
  204. package/packages/pi-coding-agent/src/core/retry-handler.ts +2 -8
  205. package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
  206. package/packages/pi-coding-agent/src/core/system-prompt.ts +35 -1
  207. package/packages/pi-coding-agent/src/index.ts +1 -0
  208. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
  209. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +146 -1
  210. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +20 -3
  211. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +2 -0
  212. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +119 -13
  213. package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
  214. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  215. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +18 -8
  216. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  217. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +128 -17
  218. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
  219. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +36 -12
  220. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
  221. package/packages/pi-tui/dist/__tests__/tui.test.js +18 -30
  222. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  223. package/packages/pi-tui/dist/components/__tests__/input.test.js +10 -3
  224. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
  225. package/packages/pi-tui/dist/components/__tests__/loader.test.js +53 -9
  226. package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -1
  227. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +6 -2
  228. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -1
  229. package/packages/pi-tui/dist/components/editor.d.ts +14 -0
  230. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  231. package/packages/pi-tui/dist/components/editor.js +19 -0
  232. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  233. package/packages/pi-tui/dist/components/image.test.js +6 -5
  234. package/packages/pi-tui/dist/components/image.test.js.map +1 -1
  235. package/packages/pi-tui/dist/editor-component.d.ts +2 -0
  236. package/packages/pi-tui/dist/editor-component.d.ts.map +1 -1
  237. package/packages/pi-tui/dist/editor-component.js.map +1 -1
  238. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +24 -8
  239. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +140 -17
  240. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +41 -12
  241. package/packages/pi-tui/src/__tests__/tui.test.ts +18 -37
  242. package/packages/pi-tui/src/components/__tests__/input.test.ts +19 -3
  243. package/packages/pi-tui/src/components/__tests__/loader.test.ts +112 -35
  244. package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +9 -2
  245. package/packages/pi-tui/src/components/editor.ts +22 -0
  246. package/packages/pi-tui/src/components/image.test.ts +10 -5
  247. package/packages/pi-tui/src/editor-component.ts +3 -0
  248. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  249. package/packages/rpc-client/dist/rpc-client.test.js +101 -51
  250. package/packages/rpc-client/dist/rpc-client.test.js.map +1 -1
  251. package/packages/rpc-client/src/rpc-client.test.ts +109 -52
  252. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  253. package/scripts/install.js +15 -1
  254. package/src/resources/extensions/browser-tools/capture.ts +12 -0
  255. package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  256. package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  257. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  258. package/src/resources/extensions/browser-tools/tools/forms.ts +5 -1
  259. package/src/resources/extensions/browser-tools/tools/intent.ts +5 -1
  260. package/src/resources/extensions/claude-code-cli/readiness.ts +5 -1
  261. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +518 -19
  262. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +919 -75
  263. package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
  264. package/src/resources/extensions/github-sync/tests/templates.test.ts +33 -1
  265. package/src/resources/extensions/gsd/auto/loop.ts +47 -0
  266. package/src/resources/extensions/gsd/auto/phases.ts +16 -20
  267. package/src/resources/extensions/gsd/auto/session.ts +0 -2
  268. package/src/resources/extensions/gsd/auto-dispatch.ts +113 -24
  269. package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
  270. package/src/resources/extensions/gsd/auto-post-unit.ts +82 -73
  271. package/src/resources/extensions/gsd/auto-prompts.ts +330 -90
  272. package/src/resources/extensions/gsd/auto-recovery.ts +225 -24
  273. package/src/resources/extensions/gsd/auto-start.ts +54 -6
  274. package/src/resources/extensions/gsd/auto-tool-tracking.ts +51 -7
  275. package/src/resources/extensions/gsd/auto-worktree.ts +130 -26
  276. package/src/resources/extensions/gsd/auto.ts +43 -22
  277. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +9 -1
  278. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +221 -0
  279. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +3 -7
  280. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -3
  281. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +158 -9
  282. package/src/resources/extensions/gsd/component-loader.ts +598 -0
  283. package/src/resources/extensions/gsd/component-types.ts +362 -0
  284. package/src/resources/extensions/gsd/detection.ts +58 -1
  285. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  286. package/src/resources/extensions/gsd/gate-registry.ts +2 -2
  287. package/src/resources/extensions/gsd/git-constants.ts +30 -1
  288. package/src/resources/extensions/gsd/git-self-heal.ts +31 -0
  289. package/src/resources/extensions/gsd/git-service.ts +133 -2
  290. package/src/resources/extensions/gsd/gsd-db.ts +6 -3
  291. package/src/resources/extensions/gsd/guided-flow.ts +20 -5
  292. package/src/resources/extensions/gsd/memory-extractor.ts +11 -3
  293. package/src/resources/extensions/gsd/milestone-scope-classifier.ts +366 -0
  294. package/src/resources/extensions/gsd/model-cost-table.ts +3 -0
  295. package/src/resources/extensions/gsd/model-router.ts +6 -0
  296. package/src/resources/extensions/gsd/native-git-bridge.ts +34 -4
  297. package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  298. package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  299. package/src/resources/extensions/gsd/safety/git-checkpoint.ts +15 -0
  300. package/src/resources/extensions/gsd/service-tier.ts +5 -2
  301. package/src/resources/extensions/gsd/session-lock.ts +20 -10
  302. package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
  303. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +309 -8
  304. package/src/resources/extensions/gsd/state.ts +49 -44
  305. package/src/resources/extensions/gsd/sync-lock.ts +97 -39
  306. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +270 -0
  307. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +341 -0
  308. package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +264 -0
  309. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +94 -289
  310. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
  311. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +78 -0
  312. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +61 -0
  313. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +93 -0
  314. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -197
  315. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
  316. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
  317. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +263 -0
  318. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +25 -0
  319. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +192 -0
  320. package/src/resources/extensions/gsd/tests/complete-task.test.ts +16 -8
  321. package/src/resources/extensions/gsd/tests/component-loader.test.ts +589 -0
  322. package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
  323. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +50 -1
  324. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -3
  325. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +40 -0
  326. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +91 -3
  327. package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -3
  328. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
  329. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
  330. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +9 -105
  331. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
  332. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +1 -1
  333. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +4 -55
  334. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -57
  335. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +20 -0
  336. package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +18 -2
  337. package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +10 -4
  338. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +144 -7
  339. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +4 -0
  340. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +2 -16
  341. package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
  342. package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +8 -37
  343. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +5 -15
  344. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +227 -62
  345. package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
  346. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
  347. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  348. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +6 -49
  349. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
  350. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -133
  351. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +301 -0
  352. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +32 -1
  353. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +23 -24
  354. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +32 -0
  355. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +75 -2
  356. package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +132 -0
  357. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +8 -40
  358. package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +136 -256
  359. package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +114 -0
  360. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +148 -0
  361. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  362. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +29 -0
  363. package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +55 -95
  364. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
  365. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +120 -1
  366. package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
  367. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +164 -1
  368. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +5 -5
  369. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
  370. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +102 -101
  371. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +31 -0
  372. package/src/resources/extensions/gsd/tests/test-helpers.test.ts +12 -61
  373. package/src/resources/extensions/gsd/tests/test-helpers.ts +21 -8
  374. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +61 -1
  375. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -1
  376. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +355 -0
  377. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +258 -0
  378. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +75 -0
  379. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +49 -26
  380. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +1 -0
  381. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -81
  382. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -54
  383. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +342 -277
  384. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +37 -29
  385. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +226 -266
  386. package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +103 -67
  387. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +92 -90
  388. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +238 -59
  389. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +113 -161
  390. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +262 -0
  391. package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +186 -0
  392. package/src/resources/extensions/gsd/tests/write-gate.test.ts +7 -5
  393. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +80 -96
  394. package/src/resources/extensions/gsd/types.ts +3 -3
  395. package/src/resources/extensions/gsd/unit-context-composer.ts +218 -0
  396. package/src/resources/extensions/gsd/unit-context-manifest.ts +574 -0
  397. package/src/resources/extensions/gsd/uok/gate-runner.ts +65 -5
  398. package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
  399. package/src/resources/extensions/gsd/worktree-manager.ts +55 -7
  400. package/src/resources/extensions/mcp-client/index.ts +3 -1
  401. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +70 -36
  402. package/src/resources/extensions/ollama/index.ts +5 -1
  403. package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +123 -15
  404. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +206 -19
  405. package/src/resources/extensions/remote-questions/manager.ts +36 -4
  406. package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +200 -190
  407. package/src/resources/extensions/shared/tests/interview-preview.test.ts +11 -3
  408. package/src/resources/extensions/voice/tests/linux-ready.test.ts +129 -113
  409. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +0 -2
  410. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +0 -1
  411. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +0 -289
  412. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +0 -1
  413. package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +0 -363
  414. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +0 -144
  415. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +0 -157
  416. package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +0 -107
  417. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +0 -48
  418. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -159
  419. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
  420. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -79
  421. package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +0 -75
  422. package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
  423. package/src/resources/extensions/gsd/tests/forensics-worktree-telemetry.test.ts +0 -145
  424. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +0 -38
  425. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +0 -73
  426. package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +0 -130
  427. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -43
  428. /package/dist/web/standalone/.next/static/{Cev5xrAYA3ZGTRLyjR2fX → SvCJDZPQW104bR1KnBQg1}/_buildManifest.js +0 -0
  429. /package/dist/web/standalone/.next/static/{Cev5xrAYA3ZGTRLyjR2fX → SvCJDZPQW104bR1KnBQg1}/_ssgManifest.js +0 -0
@@ -1,9 +1,6 @@
1
1
  import test, { mock } from "node:test";
2
2
  import assert from "node:assert/strict";
3
- import { readFileSync } from "node:fs";
4
- import { resolve } from "node:path";
5
3
 
6
- import { extractSourceRegion } from "./test-helpers.ts";
7
4
  import {
8
5
  resolveAgentEnd,
9
6
  resolveAgentEndCancelled,
@@ -18,6 +15,7 @@ import {
18
15
  type AgentEndEvent,
19
16
  type LoopDeps,
20
17
  } from "../auto-loop.js";
18
+ import { ModelPolicyDispatchBlockedError } from "../auto-model-selection.js";
21
19
  import type { SessionLockStatus } from "../session-lock.js";
22
20
 
23
21
  // ─── Helpers ─────────────────────────────────────────────────────────────────
@@ -557,65 +555,15 @@ test("auto-loop.ts exports autoLoop, runUnit, resolveAgentEnd", async () => {
557
555
  );
558
556
  });
559
557
 
560
- test("auto/loop.ts contains a while keyword", () => {
561
- const src = readFileSync(
562
- resolve(import.meta.dirname, "..", "auto", "loop.ts"),
563
- "utf-8",
564
- );
565
- assert.ok(
566
- src.includes("while"),
567
- "auto/loop.ts should contain a while keyword (loop or placeholder)",
568
- );
569
- });
570
-
571
- test("auto/resolve.ts one-shot pattern: _currentResolve is nulled before calling resolver", () => {
572
- const src = readFileSync(
573
- resolve(import.meta.dirname, "..", "auto", "resolve.ts"),
574
- "utf-8",
575
- );
576
- // The one-shot pattern requires: save ref, null the variable, then call
577
- const resolveBlock = src.slice(
578
- src.indexOf("export function resolveAgentEnd"),
579
- src.indexOf("export function resolveAgentEnd") + 600,
580
- );
581
- const nullIdx = resolveBlock.indexOf("_currentResolve = null");
582
- const callIdx = resolveBlock.indexOf("r({");
583
- assert.ok(nullIdx > 0, "should null _currentResolve in resolveAgentEnd");
584
- assert.ok(callIdx > 0, "should call resolver in resolveAgentEnd");
585
- assert.ok(
586
- nullIdx < callIdx,
587
- "_currentResolve should be nulled before calling the resolver (one-shot)",
588
- );
589
- });
590
-
591
- test("auto/phases.ts: selectAndApplyModel called exactly once and before updateProgressWidget (#2907)", () => {
592
- const src = readFileSync(
593
- resolve(import.meta.dirname, "..", "auto", "phases.ts"),
594
- "utf-8",
595
- );
596
- // Extract the runUnitPhase function body
597
- const fnStart = src.indexOf("export async function runUnitPhase");
598
- assert.ok(fnStart > 0, "runUnitPhase should exist in phases.ts");
599
- const fnBody = extractSourceRegion(src, "export async function runUnitPhase");
600
-
601
- // selectAndApplyModel must appear exactly once
602
- const allOccurrences = [...fnBody.matchAll(/selectAndApplyModel\(/g)];
603
- assert.equal(
604
- allOccurrences.length,
605
- 1,
606
- `selectAndApplyModel should be called exactly once in runUnitPhase, found ${allOccurrences.length} calls`,
607
- );
608
-
609
- // selectAndApplyModel must appear BEFORE updateProgressWidget
610
- const modelIdx = fnBody.indexOf("selectAndApplyModel(");
611
- const widgetIdx = fnBody.indexOf("updateProgressWidget(");
612
- assert.ok(modelIdx > 0, "selectAndApplyModel should exist in runUnitPhase");
613
- assert.ok(widgetIdx > 0, "updateProgressWidget should exist in runUnitPhase");
614
- assert.ok(
615
- modelIdx < widgetIdx,
616
- "selectAndApplyModel must be called BEFORE updateProgressWidget (#2899/#2907)",
617
- );
618
- });
558
+ // NOTE: the "while keyword", "one-shot null-before-resolve", and
559
+ // "selectAndApplyModel before updateProgressWidget" source-grep tests
560
+ // previously here were deleted as tautological (readFileSync + substring
561
+ // match). The one-shot pattern is already covered behaviourally by the
562
+ // "double resolveAgentEnd only resolves once" test above, which drives the
563
+ // real resolveAgentEnd/runUnit flow and asserts on the observable promise
564
+ // outcome. The phases.ts ordering contract is tracked via a follow-up
565
+ // issue proposing extraction of a pure `dispatchOrder` helper (per the
566
+ // #4832/PR #4859 precedent) so it can be tested behaviourally.
619
567
 
620
568
  // ─── autoLoop tests (T02) ─────────────────────────────────────────────────
621
569
 
@@ -1452,213 +1400,18 @@ test("autoLoop exits when no active milestone found", async (t) => {
1452
1400
  );
1453
1401
  });
1454
1402
 
1455
- test("autoLoop exports LoopDeps type", async () => {
1456
- const src = readFileSync(
1457
- resolve(import.meta.dirname, "..", "auto", "loop-deps.ts"),
1458
- "utf-8",
1459
- );
1460
- assert.ok(
1461
- src.includes("export interface LoopDeps"),
1462
- "auto/loop-deps.ts should export LoopDeps interface",
1463
- );
1464
- });
1465
-
1466
- test("autoLoop signature accepts deps parameter", async () => {
1467
- const src = readFileSync(
1468
- resolve(import.meta.dirname, "..", "auto", "loop.ts"),
1469
- "utf-8",
1470
- );
1471
- assert.ok(
1472
- src.includes("deps: LoopDeps"),
1473
- "autoLoop should accept a deps: LoopDeps parameter",
1474
- );
1475
- });
1476
-
1477
- test("autoLoop contains while (s.active) loop", () => {
1478
- const src = readFileSync(
1479
- resolve(import.meta.dirname, "..", "auto", "loop.ts"),
1480
- "utf-8",
1481
- );
1482
- assert.ok(
1483
- src.includes("while (s.active)"),
1484
- "autoLoop should contain a while (s.active) loop",
1485
- );
1486
- });
1487
-
1488
- // ── T03: End-to-end wiring structural assertions ─────────────────────────────
1489
-
1490
- test("auto-loop.ts barrel re-exports autoLoop, runUnit, and resolveAgentEnd", () => {
1491
- const barrel = readFileSync(
1492
- resolve(import.meta.dirname, "..", "auto-loop.ts"),
1493
- "utf-8",
1494
- );
1495
- assert.ok(
1496
- barrel.includes("autoLoop"),
1497
- "barrel must re-export autoLoop",
1498
- );
1499
- assert.ok(
1500
- barrel.includes("runUnit"),
1501
- "barrel must re-export runUnit",
1502
- );
1503
- assert.ok(
1504
- barrel.includes("resolveAgentEnd"),
1505
- "barrel must re-export resolveAgentEnd",
1506
- );
1507
- // Verify the actual function declarations exist in the submodules
1508
- const loopSrc = readFileSync(
1509
- resolve(import.meta.dirname, "..", "auto", "loop.ts"),
1510
- "utf-8",
1511
- );
1512
- assert.ok(
1513
- loopSrc.includes("export async function autoLoop"),
1514
- "auto/loop.ts must define autoLoop",
1515
- );
1516
- const runUnitSrc = readFileSync(
1517
- resolve(import.meta.dirname, "..", "auto", "run-unit.ts"),
1518
- "utf-8",
1519
- );
1520
- assert.ok(
1521
- runUnitSrc.includes("export async function runUnit"),
1522
- "auto/run-unit.ts must define runUnit",
1523
- );
1524
- const resolveSrc = readFileSync(
1525
- resolve(import.meta.dirname, "..", "auto", "resolve.ts"),
1526
- "utf-8",
1527
- );
1528
- assert.ok(
1529
- resolveSrc.includes("export function resolveAgentEnd"),
1530
- "auto/resolve.ts must define resolveAgentEnd",
1531
- );
1532
- });
1533
-
1534
- test("auto.ts startAuto dispatches through the UOK kernel wrapper with explicit kernel and legacy paths", () => {
1535
- const src = readFileSync(
1536
- resolve(import.meta.dirname, "..", "auto.ts"),
1537
- "utf-8",
1538
- );
1539
- // Find the startAuto function body
1540
- const fnIdx = src.indexOf("export async function startAuto");
1541
- assert.ok(fnIdx > -1, "startAuto must exist in auto.ts");
1542
- const fnBlock = extractSourceRegion(src, "export async function startAuto", "\n// ─── ");
1543
- assert.ok(
1544
- fnBlock.includes("runAutoLoopWithUok("),
1545
- "startAuto must dispatch through runAutoLoopWithUok()",
1546
- );
1547
- assert.ok(
1548
- fnBlock.includes("runKernelLoop: runUokKernelLoop"),
1549
- "startAuto must wire the explicit UOK kernel loop path",
1550
- );
1551
- assert.ok(
1552
- fnBlock.includes("runLegacyLoop: runLegacyAutoLoop"),
1553
- "startAuto must preserve explicit legacy fallback dispatch",
1554
- );
1555
- });
1556
-
1557
- test("startAuto calls selfHealRuntimeRecords before autoLoop (#1727)", { skip: "selfHealRuntimeRecords moved to crash-recovery pipeline in v3" }, () => {
1558
- const src = readFileSync(
1559
- resolve(import.meta.dirname, "..", "auto.ts"),
1560
- "utf-8",
1561
- );
1562
- const fnIdx = src.indexOf("export async function startAuto");
1563
- assert.ok(fnIdx > -1, "startAuto must exist in auto.ts");
1564
- const fnBlock = extractSourceRegion(src, "export async function startAuto", "\n// ─── ");
1565
-
1566
- // Both autoLoop call sites must be preceded by selfHealRuntimeRecords
1567
- const healIdx = fnBlock.indexOf("selfHealRuntimeRecords");
1568
- const loopIdx = fnBlock.indexOf("autoLoop(");
1569
- assert.ok(healIdx > -1, "startAuto must call selfHealRuntimeRecords");
1570
- assert.ok(healIdx < loopIdx, "selfHealRuntimeRecords must be called before autoLoop");
1571
-
1572
- // Verify the second autoLoop call site also has selfHeal before it (if present)
1573
- const secondLoopIdx = fnBlock.indexOf("autoLoop(", loopIdx + 1);
1574
- const secondHealIdx = fnBlock.indexOf("selfHealRuntimeRecords", healIdx + 1);
1575
- assert.ok(
1576
- secondLoopIdx === -1 || (secondHealIdx > -1 && secondHealIdx < secondLoopIdx),
1577
- "if a second autoLoop call exists, it must also be preceded by selfHealRuntimeRecords",
1578
- );
1579
- });
1580
-
1581
- test("startAuto guards against concurrent invocation (#2923)", () => {
1582
- const src = readFileSync(
1583
- resolve(import.meta.dirname, "..", "auto.ts"),
1584
- "utf-8",
1585
- );
1586
- const fnIdx = src.indexOf("export async function startAuto");
1587
- assert.ok(fnIdx > -1, "startAuto must exist in auto.ts");
1588
- // The guard must appear before any other logic in the function body
1589
- const fnBody = extractSourceRegion(src, "export async function startAuto");
1590
- const activeGuard = fnBody.indexOf("if (s.active)");
1591
- assert.ok(activeGuard > -1, "startAuto must check s.active to prevent concurrent auto-loops");
1592
- const returnIdx = fnBody.indexOf("return;", activeGuard);
1593
- assert.ok(
1594
- returnIdx > -1 && returnIdx < activeGuard + 120,
1595
- "s.active guard must early-return to prevent a second concurrent loop",
1596
- );
1597
- });
1598
-
1599
- test("agent_end handler calls resolveAgentEnd (not the legacy auto.ts path)", () => {
1600
- const hooksSrc = readFileSync(
1601
- resolve(import.meta.dirname, "..", "bootstrap", "register-hooks.ts"),
1602
- "utf-8",
1603
- );
1604
- // Verify the agent_end hook is registered
1605
- const handlerIdx = hooksSrc.indexOf('pi.on("agent_end"');
1606
- assert.ok(handlerIdx > -1, "register-hooks.ts must have an agent_end handler");
1607
-
1608
- const recoverySrc = readFileSync(
1609
- resolve(import.meta.dirname, "..", "bootstrap", "agent-end-recovery.ts"),
1610
- "utf-8",
1611
- );
1612
- assert.ok(
1613
- recoverySrc.includes("resolveAgentEnd(event)"),
1614
- "agent_end success path must call resolveAgentEnd(event) instead of legacy wrappers",
1615
- );
1616
- assert.ok(
1617
- recoverySrc.includes("isSessionSwitchInFlight()"),
1618
- "agent_end handler must ignore session-switch agent_end events from cmdCtx.newSession()",
1619
- );
1620
- });
1621
-
1622
- test("auto-verification.ts runPostUnitVerification does not take dispatchNextUnit callback", () => {
1623
- const src = readFileSync(
1624
- resolve(import.meta.dirname, "..", "auto-verification.ts"),
1625
- "utf-8",
1626
- );
1627
- const fnIdx = src.indexOf("export async function runPostUnitVerification");
1628
- assert.ok(fnIdx > -1, "runPostUnitVerification must exist");
1629
- const sigEnd = src.indexOf("): Promise<VerificationResult>", fnIdx);
1630
- const signature = src.slice(fnIdx, sigEnd);
1631
- assert.ok(
1632
- !signature.includes("dispatchNextUnit"),
1633
- "runPostUnitVerification must not take a dispatchNextUnit callback parameter",
1634
- );
1635
- assert.ok(
1636
- !signature.includes("startDispatchGapWatchdog"),
1637
- "runPostUnitVerification must not take a startDispatchGapWatchdog callback parameter",
1638
- );
1639
- });
1640
-
1641
- test("auto-timeout-recovery.ts calls resolveAgentEnd instead of dispatchNextUnit", () => {
1642
- const src = readFileSync(
1643
- resolve(import.meta.dirname, "..", "auto-timeout-recovery.ts"),
1644
- "utf-8",
1645
- );
1646
- assert.ok(
1647
- !src.includes("await dispatchNextUnit"),
1648
- "auto-timeout-recovery.ts must not call dispatchNextUnit",
1649
- );
1650
- // After PR #4716, advance branches go through bumpAndResolveSynthetic()
1651
- // (which bumps the turn epoch and calls resolveAgentEnd atomically).
1652
- // Either direct resolveAgentEnd() or the helper satisfies the invariant:
1653
- // the loop must be re-iterated on timeout recovery.
1654
- const reIteratesLoop =
1655
- src.includes("resolveAgentEnd(") ||
1656
- src.includes("bumpAndResolveSynthetic(");
1657
- assert.ok(
1658
- reIteratesLoop,
1659
- "auto-timeout-recovery.ts must call resolveAgentEnd (directly or via bumpAndResolveSynthetic) to re-iterate the loop on timeout recovery",
1660
- );
1661
- });
1403
+ // NOTE: The T03 "wiring structural assertions" block (barrel re-exports,
1404
+ // LoopDeps-interface-declared, while-loop keyword, UOK kernel wrapper,
1405
+ // selfHeal ordering, s.active concurrent guard, agent_end handler call
1406
+ // shape, runPostUnitVerification signature, auto-timeout-recovery call
1407
+ // shape) was a pure source-grep chain — readFileSync + includes/indexOf —
1408
+ // so it asserted on code shape rather than runtime behaviour. The symbols
1409
+ // named in those assertions are ALREADY imported at the top of this file;
1410
+ // if the production barrel drops any of them, this file fails to import
1411
+ // and every test here fails cold. That import-time check is the real
1412
+ // behavioural contract. The ordering/signature contracts (UOK dispatch,
1413
+ // concurrent guard, agent_end wiring) are tracked as follow-up issues for
1414
+ // pure-helper extraction per the #4832/PR #4859 precedent.
1662
1415
 
1663
1416
  // ── Stuck counter tests ──────────────────────────────────────────────────────
1664
1417
 
@@ -1957,26 +1710,10 @@ test("detectStuck: truncates long error strings", () => {
1957
1710
  assert.ok(result!.reason.length < 300, "reason should be truncated");
1958
1711
  });
1959
1712
 
1960
- test("stuck detection: logs debug output with stuck-detected phase", () => {
1961
- // Structural test: verify auto/phases.ts contains
1962
- // stuck-detected and stuck-counter-reset debug log phases, plus detectStuck
1963
- const src = readFileSync(
1964
- resolve(import.meta.dirname, "..", "auto", "phases.ts"),
1965
- "utf-8",
1966
- );
1967
- assert.ok(
1968
- src.includes('"stuck-detected"'),
1969
- "auto/phases.ts must log phase: 'stuck-detected' when stuck detection fires",
1970
- );
1971
- assert.ok(
1972
- src.includes('"stuck-counter-reset"'),
1973
- "auto/phases.ts must log phase: 'stuck-counter-reset' when recovery resets on new unit",
1974
- );
1975
- assert.ok(
1976
- src.includes("detectStuck"),
1977
- "auto/phases.ts must use detectStuck for sliding window analysis",
1978
- );
1979
- });
1713
+ // NOTE: the "stuck-detected" / "stuck-counter-reset" debug-log grep was
1714
+ // removed — that string test never exercised the detector. detectStuck
1715
+ // itself is tested behaviourally above against the real implementation
1716
+ // imported from auto-loop.js.
1980
1717
 
1981
1718
  // ── Lifecycle test (S05/T02) ─────────────────────────────────────────────────
1982
1719
 
@@ -2623,3 +2360,71 @@ test("autoLoop warns but proceeds for greenfield project (no project files) (#18
2623
2360
  "should warn about greenfield project (no project files)",
2624
2361
  );
2625
2362
  });
2363
+
2364
+ // ─── #4850: pre-send model-policy block is non-retryable ────────────────────
2365
+ test("autoLoop classifies ModelPolicyDispatchBlockedError as blocked, not a retryable error", async () => {
2366
+ _resetPendingResolve();
2367
+
2368
+ const ctx = makeMockCtx();
2369
+ ctx.ui.setStatus = () => {};
2370
+ const notifications: Array<{ message: string; level?: string }> = [];
2371
+ ctx.ui.notify = (m: string, l?: string) => { notifications.push({ message: m, level: l }); };
2372
+
2373
+ const pi = makeMockPi();
2374
+ const s = makeLoopSession();
2375
+
2376
+ const journalEvents: Array<{ eventType: string; data?: any }> = [];
2377
+ let pauseAutoCalls = 0;
2378
+ let stopAutoCalls = 0;
2379
+ // Capture onTurnResult to assert blocked-unit identity is propagated to
2380
+ // the uokObserver. Without the fix, observedUnitType/Id are unset because
2381
+ // the throw happens inside dispatch before the success-path assignments
2382
+ // at loop.ts:453/631/647 (#4959 / CodeRabbit Minor).
2383
+ const turnResults: Array<{ unitType?: string; unitId?: string; status: string }> = [];
2384
+
2385
+ const deps = makeMockDeps({
2386
+ selectAndApplyModel: async () => {
2387
+ throw new ModelPolicyDispatchBlockedError(
2388
+ "research-slice",
2389
+ "M001/S01",
2390
+ [{ provider: "openai", modelId: "gpt-4o", reason: "tool policy denied (web_search) for openai-completions" }],
2391
+ );
2392
+ },
2393
+ pauseAuto: async () => { pauseAutoCalls++; },
2394
+ stopAuto: async () => { stopAutoCalls++; },
2395
+ emitJournalEvent: (entry: any) => { journalEvents.push(entry); },
2396
+ uokObserver: {
2397
+ onTurnStart: () => {},
2398
+ onPhaseResult: () => {},
2399
+ onTurnResult: (res: any) => { turnResults.push({ unitType: res.unitType, unitId: res.unitId, status: res.status }); },
2400
+ } as any,
2401
+ });
2402
+
2403
+ await autoLoop(ctx, pi, s, deps);
2404
+
2405
+ // The unit-end event with status: "blocked" must be emitted.
2406
+ const unitEnd = journalEvents.find(
2407
+ e => e.eventType === "unit-end" && e.data?.status === "blocked",
2408
+ );
2409
+ assert.ok(unitEnd, "should emit unit-end with status=blocked");
2410
+ assert.equal(unitEnd!.data.reason, "model-policy-dispatch-blocked");
2411
+
2412
+ // Loop must pause for manual attention, NOT retry until 3-strike hard stop.
2413
+ assert.equal(pauseAutoCalls, 1, "should pause once on policy block");
2414
+ assert.equal(stopAutoCalls, 0, "should NOT call stopAuto — pre-send block is not a retryable iteration error");
2415
+
2416
+ // The notification should surface the per-model deny reason from the typed error.
2417
+ const blockedNotice = notifications.find(
2418
+ n => n.message.includes("model-policy denied dispatch")
2419
+ && n.message.includes("tool policy denied (web_search)"),
2420
+ );
2421
+ assert.ok(blockedNotice, "user-facing notification should name the policy block + deny reason");
2422
+
2423
+ // Blocked-unit identity must reach uokObserver.onTurnResult — the typed
2424
+ // error already carries it, the loop must thread it into observedUnitType/Id
2425
+ // before finishTurn is called (#4959 / CodeRabbit Minor).
2426
+ const pausedTurn = turnResults.find(r => r.status === "paused");
2427
+ assert.ok(pausedTurn, "uokObserver should observe a paused turn for the blocked unit");
2428
+ assert.equal(pausedTurn!.unitType, "research-slice", "onTurnResult must receive the blocked unitType from the typed error");
2429
+ assert.equal(pausedTurn!.unitId, "M001/S01", "onTurnResult must receive the blocked unitId from the typed error");
2430
+ });