gsd-pi 2.77.0-dev.eaa4973bc → 2.78.0-dev.aeeb2ca00

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 (545) hide show
  1. package/README.md +53 -17
  2. package/dist/claude-cli-check.js +46 -10
  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 +72 -16
  13. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +481 -17
  14. package/dist/resources/extensions/github-sync/templates.js +103 -0
  15. package/dist/resources/extensions/google-search/index.js +3 -2
  16. package/dist/resources/extensions/gsd/auto/loop.js +124 -2
  17. package/dist/resources/extensions/gsd/auto/phases.js +57 -39
  18. package/dist/resources/extensions/gsd/auto/session.js +6 -2
  19. package/dist/resources/extensions/gsd/auto-dispatch.js +142 -29
  20. package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
  21. package/dist/resources/extensions/gsd/auto-post-unit.js +150 -64
  22. package/dist/resources/extensions/gsd/auto-prompts.js +372 -104
  23. package/dist/resources/extensions/gsd/auto-recovery.js +197 -48
  24. package/dist/resources/extensions/gsd/auto-start.js +107 -29
  25. package/dist/resources/extensions/gsd/auto-tool-tracking.js +47 -7
  26. package/dist/resources/extensions/gsd/auto-worktree.js +122 -26
  27. package/dist/resources/extensions/gsd/auto.js +76 -21
  28. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +19 -1
  29. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +209 -0
  30. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +3 -6
  31. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -3
  32. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +127 -9
  33. package/dist/resources/extensions/gsd/component-loader.js +447 -0
  34. package/dist/resources/extensions/gsd/component-types.js +69 -0
  35. package/dist/resources/extensions/gsd/context-store.js +23 -7
  36. package/dist/resources/extensions/gsd/detection.js +49 -1
  37. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -17
  38. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  39. package/dist/resources/extensions/gsd/forensics.js +106 -0
  40. package/dist/resources/extensions/gsd/gate-registry.js +2 -2
  41. package/dist/resources/extensions/gsd/git-constants.js +28 -1
  42. package/dist/resources/extensions/gsd/git-self-heal.js +27 -0
  43. package/dist/resources/extensions/gsd/git-service.js +126 -2
  44. package/dist/resources/extensions/gsd/gsd-db.js +6 -3
  45. package/dist/resources/extensions/gsd/guided-flow.js +39 -13
  46. package/dist/resources/extensions/gsd/memory-extractor.js +7 -1
  47. package/dist/resources/extensions/gsd/milestone-scope-classifier.js +299 -0
  48. package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
  49. package/dist/resources/extensions/gsd/model-cost-table.js +3 -0
  50. package/dist/resources/extensions/gsd/model-router.js +6 -0
  51. package/dist/resources/extensions/gsd/native-git-bridge.js +34 -4
  52. package/dist/resources/extensions/gsd/preferences-validation.js +23 -0
  53. package/dist/resources/extensions/gsd/prompt-cache-optimizer.js +4 -0
  54. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  55. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  56. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  57. package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  58. package/dist/resources/extensions/gsd/safety/git-checkpoint.js +11 -0
  59. package/dist/resources/extensions/gsd/service-tier.js +5 -2
  60. package/dist/resources/extensions/gsd/session-lock.js +19 -10
  61. package/dist/resources/extensions/gsd/skill-manifest.js +168 -0
  62. package/dist/resources/extensions/gsd/slice-cadence.js +238 -0
  63. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +278 -8
  64. package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
  65. package/dist/resources/extensions/gsd/state.js +69 -58
  66. package/dist/resources/extensions/gsd/sync-lock.js +98 -42
  67. package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -2
  68. package/dist/resources/extensions/gsd/unit-context-composer.js +147 -0
  69. package/dist/resources/extensions/gsd/unit-context-manifest.js +370 -0
  70. package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
  71. package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
  72. package/dist/resources/extensions/gsd/uok/gate-runner.js +53 -5
  73. package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
  74. package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
  75. package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
  76. package/dist/resources/extensions/gsd/uok/plan-v2.js +10 -4
  77. package/dist/resources/extensions/gsd/uok/writer.js +82 -0
  78. package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
  79. package/dist/resources/extensions/gsd/worktree-manager.js +85 -8
  80. package/dist/resources/extensions/gsd/worktree-resolver.js +86 -7
  81. package/dist/resources/extensions/gsd/worktree-telemetry.js +198 -0
  82. package/dist/resources/extensions/mcp-client/index.js +3 -1
  83. package/dist/resources/extensions/ollama/index.js +5 -1
  84. package/dist/resources/extensions/remote-questions/manager.js +11 -5
  85. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  86. package/dist/web/standalone/.next/BUILD_ID +1 -1
  87. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  88. package/dist/web/standalone/.next/build-manifest.json +2 -2
  89. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  90. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  107. package/dist/web/standalone/.next/server/app/index.html +1 -1
  108. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  115. package/dist/web/standalone/.next/server/chunks/1926.js +1 -1
  116. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  117. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  119. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  120. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  121. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  122. package/package.json +2 -3
  123. package/packages/daemon/package.json +2 -2
  124. package/packages/daemon/src/logger.ts +4 -3
  125. package/packages/mcp-server/dist/server.d.ts +24 -0
  126. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  127. package/packages/mcp-server/dist/server.js +88 -87
  128. package/packages/mcp-server/dist/server.js.map +1 -1
  129. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  130. package/packages/mcp-server/dist/workflow-tools.js +15 -6
  131. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  132. package/packages/mcp-server/package.json +2 -2
  133. package/packages/mcp-server/src/mcp-server.test.ts +25 -3
  134. package/packages/mcp-server/src/readers/graph.test.ts +87 -15
  135. package/packages/mcp-server/src/secure-env-collect.test.ts +232 -237
  136. package/packages/mcp-server/src/server.ts +131 -105
  137. package/packages/mcp-server/src/workflow-tools.test.ts +85 -0
  138. package/packages/mcp-server/src/workflow-tools.ts +19 -6
  139. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  140. package/packages/native/package.json +2 -2
  141. package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
  142. package/packages/native/src/__tests__/module-compat.test.mjs +59 -27
  143. package/packages/native/src/__tests__/ps.test.mjs +14 -8
  144. package/packages/native/src/__tests__/stream-process.test.mjs +23 -2
  145. package/packages/native/src/__tests__/truncate.test.mjs +17 -2
  146. package/packages/pi-agent-core/package.json +1 -1
  147. package/packages/pi-agent-core/src/agent-loop.test.ts +5 -15
  148. package/packages/pi-agent-core/src/agent.test.ts +96 -102
  149. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  150. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -1
  151. package/packages/pi-ai/dist/models/capability-patches.js +9 -2
  152. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -1
  153. package/packages/pi-ai/dist/models/generated/index.d.ts +34 -0
  154. package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
  155. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
  156. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
  157. package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
  158. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
  159. package/packages/pi-ai/dist/models/generated/openai.d.ts +17 -0
  160. package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -1
  161. package/packages/pi-ai/dist/models/generated/openai.js +17 -0
  162. package/packages/pi-ai/dist/models/generated/openai.js.map +1 -1
  163. package/packages/pi-ai/dist/models.generated.test.js +43 -70
  164. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  165. package/packages/pi-ai/dist/models.test.js +36 -11
  166. package/packages/pi-ai/dist/models.test.js.map +1 -1
  167. package/packages/pi-ai/package.json +1 -1
  168. package/packages/pi-ai/scripts/generate-models.ts +44 -0
  169. package/packages/pi-ai/src/models/capability-patches.ts +10 -2
  170. package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
  171. package/packages/pi-ai/src/models/generated/openai.ts +17 -0
  172. package/packages/pi-ai/src/models.generated.test.ts +46 -73
  173. package/packages/pi-ai/src/models.test.ts +48 -11
  174. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  175. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +96 -32
  176. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  177. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js +75 -12
  178. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js.map +1 -1
  179. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +99 -31
  180. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  181. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
  182. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/extensions/loader.js +61 -0
  184. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +30 -4
  186. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
  187. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +17 -0
  188. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +76 -18
  190. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  192. package/packages/pi-coding-agent/dist/core/retry-handler.js +2 -6
  193. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  194. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +5 -1
  195. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts +18 -0
  197. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts.map +1 -0
  198. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js +18 -0
  199. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js.map +1 -0
  200. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +20 -0
  201. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  202. package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -2
  203. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  204. package/packages/pi-coding-agent/dist/index.d.ts +1 -0
  205. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  206. package/packages/pi-coding-agent/dist/index.js +1 -0
  207. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -5
  209. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +20 -13
  211. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
  212. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  213. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +30 -12
  214. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  215. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  216. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +18 -3
  217. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  218. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +125 -0
  219. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  220. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +2 -0
  221. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  222. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  223. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
  224. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  225. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +105 -13
  226. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  227. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts +2 -0
  228. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts.map +1 -0
  229. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js +130 -0
  230. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js.map +1 -0
  231. package/packages/pi-coding-agent/package.json +1 -1
  232. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +113 -37
  233. package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +89 -17
  234. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +112 -43
  235. package/packages/pi-coding-agent/src/core/extensions/loader.ts +58 -0
  236. package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +35 -4
  237. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +20 -0
  238. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +93 -28
  239. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +5 -1
  240. package/packages/pi-coding-agent/src/core/retry-handler.ts +2 -8
  241. package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
  242. package/packages/pi-coding-agent/src/core/system-prompt.ts +35 -1
  243. package/packages/pi-coding-agent/src/index.ts +1 -0
  244. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +49 -3
  245. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
  246. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +48 -9
  247. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +146 -1
  248. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +20 -3
  249. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +2 -0
  250. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +119 -13
  251. package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
  252. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  253. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +18 -8
  254. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  255. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +128 -17
  256. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
  257. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +37 -11
  258. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
  259. package/packages/pi-tui/dist/__tests__/tui.test.js +18 -30
  260. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  261. package/packages/pi-tui/dist/components/__tests__/input.test.js +10 -3
  262. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
  263. package/packages/pi-tui/dist/components/__tests__/loader.test.js +53 -9
  264. package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -1
  265. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +6 -2
  266. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -1
  267. package/packages/pi-tui/dist/components/editor.d.ts +14 -0
  268. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  269. package/packages/pi-tui/dist/components/editor.js +19 -0
  270. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  271. package/packages/pi-tui/dist/components/image.test.js +6 -5
  272. package/packages/pi-tui/dist/components/image.test.js.map +1 -1
  273. package/packages/pi-tui/dist/editor-component.d.ts +2 -0
  274. package/packages/pi-tui/dist/editor-component.d.ts.map +1 -1
  275. package/packages/pi-tui/dist/editor-component.js.map +1 -1
  276. package/packages/pi-tui/package.json +1 -1
  277. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +24 -8
  278. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +140 -17
  279. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +42 -11
  280. package/packages/pi-tui/src/__tests__/tui.test.ts +18 -37
  281. package/packages/pi-tui/src/components/__tests__/input.test.ts +19 -3
  282. package/packages/pi-tui/src/components/__tests__/loader.test.ts +112 -35
  283. package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +9 -2
  284. package/packages/pi-tui/src/components/editor.ts +22 -0
  285. package/packages/pi-tui/src/components/image.test.ts +10 -5
  286. package/packages/pi-tui/src/editor-component.ts +3 -0
  287. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  288. package/packages/rpc-client/dist/rpc-client.test.js +101 -51
  289. package/packages/rpc-client/dist/rpc-client.test.js.map +1 -1
  290. package/packages/rpc-client/package.json +1 -1
  291. package/packages/rpc-client/src/rpc-client.test.ts +109 -52
  292. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  293. package/pkg/package.json +1 -1
  294. package/scripts/install.js +15 -1
  295. package/src/resources/extensions/browser-tools/capture.ts +12 -0
  296. package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  297. package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  298. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  299. package/src/resources/extensions/browser-tools/tools/forms.ts +5 -1
  300. package/src/resources/extensions/browser-tools/tools/intent.ts +5 -1
  301. package/src/resources/extensions/claude-code-cli/readiness.ts +75 -16
  302. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +518 -19
  303. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +919 -75
  304. package/src/resources/extensions/github-sync/templates.ts +151 -0
  305. package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
  306. package/src/resources/extensions/github-sync/tests/templates.test.ts +92 -1
  307. package/src/resources/extensions/google-search/index.ts +3 -2
  308. package/src/resources/extensions/gsd/auto/loop.ts +142 -2
  309. package/src/resources/extensions/gsd/auto/phases.ts +62 -38
  310. package/src/resources/extensions/gsd/auto/session.ts +7 -2
  311. package/src/resources/extensions/gsd/auto-dispatch.ts +156 -29
  312. package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
  313. package/src/resources/extensions/gsd/auto-post-unit.ts +163 -73
  314. package/src/resources/extensions/gsd/auto-prompts.ts +385 -93
  315. package/src/resources/extensions/gsd/auto-recovery.ts +230 -51
  316. package/src/resources/extensions/gsd/auto-start.ts +127 -9
  317. package/src/resources/extensions/gsd/auto-tool-tracking.ts +51 -7
  318. package/src/resources/extensions/gsd/auto-worktree.ts +130 -26
  319. package/src/resources/extensions/gsd/auto.ts +90 -23
  320. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +20 -1
  321. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +221 -0
  322. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +3 -7
  323. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -3
  324. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +158 -9
  325. package/src/resources/extensions/gsd/component-loader.ts +598 -0
  326. package/src/resources/extensions/gsd/component-types.ts +362 -0
  327. package/src/resources/extensions/gsd/context-store.ts +25 -8
  328. package/src/resources/extensions/gsd/detection.ts +58 -1
  329. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -20
  330. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  331. package/src/resources/extensions/gsd/forensics.ts +118 -1
  332. package/src/resources/extensions/gsd/gate-registry.ts +2 -2
  333. package/src/resources/extensions/gsd/git-constants.ts +30 -1
  334. package/src/resources/extensions/gsd/git-self-heal.ts +31 -0
  335. package/src/resources/extensions/gsd/git-service.ts +149 -2
  336. package/src/resources/extensions/gsd/gsd-db.ts +6 -3
  337. package/src/resources/extensions/gsd/guided-flow.ts +57 -14
  338. package/src/resources/extensions/gsd/journal.ts +11 -1
  339. package/src/resources/extensions/gsd/memory-extractor.ts +11 -3
  340. package/src/resources/extensions/gsd/milestone-scope-classifier.ts +366 -0
  341. package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
  342. package/src/resources/extensions/gsd/model-cost-table.ts +3 -0
  343. package/src/resources/extensions/gsd/model-router.ts +6 -0
  344. package/src/resources/extensions/gsd/native-git-bridge.ts +34 -4
  345. package/src/resources/extensions/gsd/preferences-validation.ts +21 -0
  346. package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +4 -0
  347. package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  348. package/src/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  349. package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  350. package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  351. package/src/resources/extensions/gsd/safety/git-checkpoint.ts +15 -0
  352. package/src/resources/extensions/gsd/service-tier.ts +5 -2
  353. package/src/resources/extensions/gsd/session-lock.ts +20 -10
  354. package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
  355. package/src/resources/extensions/gsd/slice-cadence.ts +299 -0
  356. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +309 -8
  357. package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
  358. package/src/resources/extensions/gsd/state.ts +76 -66
  359. package/src/resources/extensions/gsd/sync-lock.ts +97 -39
  360. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +270 -0
  361. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +2 -1
  362. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +341 -0
  363. package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +264 -0
  364. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +133 -292
  365. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
  366. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +78 -0
  367. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +61 -0
  368. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +93 -0
  369. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +4 -1
  370. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -194
  371. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +3 -2
  372. package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +2 -2
  373. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
  374. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +2 -2
  375. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +3 -2
  376. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +3 -2
  377. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -1
  378. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
  379. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
  380. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +263 -0
  381. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +25 -0
  382. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +192 -0
  383. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +2 -1
  384. package/src/resources/extensions/gsd/tests/complete-task.test.ts +16 -8
  385. package/src/resources/extensions/gsd/tests/component-loader.test.ts +589 -0
  386. package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
  387. package/src/resources/extensions/gsd/tests/context-store.test.ts +79 -0
  388. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +2 -1
  389. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +50 -1
  390. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +159 -0
  391. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
  392. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -3
  393. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +40 -0
  394. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +91 -3
  395. package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -4
  396. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +2 -1
  397. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +2 -1
  398. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +5 -0
  399. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
  400. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
  401. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
  402. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +4 -3
  403. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +4 -3
  404. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
  405. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
  406. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +8 -104
  407. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
  408. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +1 -1
  409. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +14 -4
  410. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
  411. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +4 -55
  412. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -56
  413. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +20 -0
  414. package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +18 -2
  415. package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +10 -4
  416. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +144 -7
  417. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +4 -0
  418. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +2 -16
  419. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +9 -3
  420. package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
  421. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +64 -0
  422. package/src/resources/extensions/gsd/tests/knowledge.test.ts +93 -1
  423. package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +8 -37
  424. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +5 -15
  425. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +227 -55
  426. package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
  427. package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
  428. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
  429. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  430. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +6 -48
  431. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
  432. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +59 -2
  433. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -130
  434. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +301 -0
  435. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +32 -1
  436. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +2 -1
  437. package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +12 -0
  438. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +15 -4
  439. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +23 -24
  440. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +32 -0
  441. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +3 -2
  442. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +4 -5
  443. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +75 -2
  444. package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +132 -0
  445. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +8 -40
  446. package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +136 -256
  447. package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +114 -0
  448. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +6 -3
  449. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +148 -0
  450. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  451. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +29 -0
  452. package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +3 -2
  453. package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +55 -95
  454. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
  455. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +120 -1
  456. package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
  457. package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +242 -0
  458. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +3 -2
  459. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +164 -1
  460. package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +2 -1
  461. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
  462. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +29 -5
  463. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
  464. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +3 -3
  465. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
  466. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +7 -6
  467. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +102 -101
  468. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +31 -0
  469. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +4 -3
  470. package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
  471. package/src/resources/extensions/gsd/tests/test-helpers.ts +153 -0
  472. package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
  473. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +61 -1
  474. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -1
  475. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +355 -0
  476. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +258 -0
  477. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
  478. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
  479. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +75 -0
  480. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +49 -26
  481. package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
  482. package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
  483. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +19 -2
  484. package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
  485. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +12 -0
  486. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -80
  487. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -54
  488. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +342 -277
  489. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +37 -29
  490. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +226 -266
  491. package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +103 -67
  492. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +92 -90
  493. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +238 -59
  494. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +113 -161
  495. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +210 -0
  496. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +262 -0
  497. package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +186 -0
  498. package/src/resources/extensions/gsd/tests/write-gate.test.ts +7 -5
  499. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +80 -96
  500. package/src/resources/extensions/gsd/tools/validate-milestone.ts +8 -2
  501. package/src/resources/extensions/gsd/types.ts +3 -3
  502. package/src/resources/extensions/gsd/unit-context-composer.ts +218 -0
  503. package/src/resources/extensions/gsd/unit-context-manifest.ts +574 -0
  504. package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
  505. package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
  506. package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
  507. package/src/resources/extensions/gsd/uok/gate-runner.ts +65 -5
  508. package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
  509. package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
  510. package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
  511. package/src/resources/extensions/gsd/uok/plan-v2.ts +13 -5
  512. package/src/resources/extensions/gsd/uok/writer.ts +113 -0
  513. package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
  514. package/src/resources/extensions/gsd/worktree-manager.ts +108 -7
  515. package/src/resources/extensions/gsd/worktree-resolver.ts +96 -9
  516. package/src/resources/extensions/gsd/worktree-telemetry.ts +322 -0
  517. package/src/resources/extensions/mcp-client/index.ts +3 -1
  518. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +70 -36
  519. package/src/resources/extensions/ollama/index.ts +5 -1
  520. package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +123 -15
  521. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +206 -19
  522. package/src/resources/extensions/remote-questions/manager.ts +36 -4
  523. package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +200 -190
  524. package/src/resources/extensions/shared/tests/interview-preview.test.ts +11 -3
  525. package/src/resources/extensions/voice/tests/linux-ready.test.ts +129 -113
  526. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +0 -2
  527. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +0 -1
  528. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +0 -289
  529. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +0 -1
  530. package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +0 -363
  531. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +0 -143
  532. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +0 -157
  533. package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +0 -107
  534. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +0 -48
  535. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -159
  536. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
  537. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -79
  538. package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +0 -74
  539. package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
  540. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +0 -38
  541. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +0 -73
  542. package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +0 -125
  543. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -42
  544. /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → cAJH99yNS1UPbeSEiNRrV}/_buildManifest.js +0 -0
  545. /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → cAJH99yNS1UPbeSEiNRrV}/_ssgManifest.js +0 -0
@@ -26,12 +26,12 @@ import {
26
26
  import { detectStuck } from "./detect-stuck.js";
27
27
  import { runUnit } from "./run-unit.js";
28
28
  import { debugLog } from "../debug-logger.js";
29
- import { PROJECT_FILES } from "../detection.js";
29
+ import { PROJECT_FILES, hasProjectFileInAncestor } from "../detection.js";
30
30
  import { MergeConflictError } from "../git-service.js";
31
31
  import { setCurrentPhase, clearCurrentPhase } from "../../shared/gsd-phase-state.js";
32
32
  import { pauseAutoForProviderError } from "../provider-error-pause.js";
33
33
  import { resumeAutoAfterProviderDelay } from "../bootstrap/provider-error-resume.js";
34
- import { join, basename, dirname, parse as parsePath } from "node:path";
34
+ import { join, basename } from "node:path";
35
35
  import { existsSync, cpSync, readdirSync } from "node:fs";
36
36
  import {
37
37
  logWarning,
@@ -51,7 +51,7 @@ import { getEligibleSlices } from "../slice-parallel-eligibility.js";
51
51
  import { startSliceParallel } from "../slice-parallel-orchestrator.js";
52
52
  import { isDbAvailable, getMilestoneSlices } from "../gsd-db.js";
53
53
  import type { MinimalModelRegistry } from "../context-budget.js";
54
- import { ensurePlanV2Graph } from "../uok/plan-v2.js";
54
+ import { ensurePlanV2Graph, isMissingFinalizedContextResult } from "../uok/plan-v2.js";
55
55
  import { resolveUokFlags } from "../uok/flags.js";
56
56
  import { UokGateRunner } from "../uok/gate-runner.js";
57
57
  import { resetEvidence, loadEvidenceFromDisk } from "../safety/evidence-collector.js";
@@ -201,6 +201,7 @@ async function closeoutAndStop(
201
201
  s.currentUnit.startedAt,
202
202
  deps.buildSnapshotOpts(s.currentUnit.type, s.currentUnit.id),
203
203
  );
204
+ s.currentUnit = null;
204
205
  }
205
206
  await deps.stopAuto(ctx, pi, reason);
206
207
  }
@@ -420,27 +421,41 @@ export async function runPreDispatch(
420
421
  const compiled = ensurePlanV2Graph(s.basePath, state);
421
422
  if (!compiled.ok) {
422
423
  const reason = compiled.reason ?? "Plan v2 compilation failed";
424
+ if (isMissingFinalizedContextResult(compiled)) {
425
+ await runPreDispatchGate({
426
+ gateId: "plan-v2-gate",
427
+ gateType: "policy",
428
+ outcome: "pass",
429
+ failureClass: "none",
430
+ rationale: "plan v2 missing context recovery deferred to dispatch",
431
+ findings: reason,
432
+ milestoneId: state.activeMilestone?.id ?? undefined,
433
+ });
434
+ } else {
435
+ await runPreDispatchGate({
436
+ gateId: "plan-v2-gate",
437
+ gateType: "policy",
438
+ outcome: "manual-attention",
439
+ failureClass: "manual-attention",
440
+ rationale: "plan v2 compile gate failed",
441
+ findings: reason,
442
+ milestoneId: state.activeMilestone?.id ?? undefined,
443
+ });
444
+ ctx.ui.notify(`Plan gate failed-closed: ${reason}\n\nIf this keeps happening, try: /gsd doctor heal`, "error");
445
+ await deps.pauseAuto(ctx, pi);
446
+ return { action: "break", reason: "plan-v2-gate-failed" };
447
+ }
448
+ }
449
+ if (compiled.ok) {
423
450
  await runPreDispatchGate({
424
451
  gateId: "plan-v2-gate",
425
452
  gateType: "policy",
426
- outcome: "manual-attention",
427
- failureClass: "manual-attention",
428
- rationale: "plan v2 compile gate failed",
429
- findings: reason,
453
+ outcome: "pass",
454
+ failureClass: "none",
455
+ rationale: "plan v2 compile gate passed",
430
456
  milestoneId: state.activeMilestone?.id ?? undefined,
431
457
  });
432
- ctx.ui.notify(`Plan gate failed-closed: ${reason}\n\nIf this keeps happening, try: /gsd doctor heal`, "error");
433
- await deps.pauseAuto(ctx, pi);
434
- return { action: "break", reason: "plan-v2-gate-failed" };
435
458
  }
436
- await runPreDispatchGate({
437
- gateId: "plan-v2-gate",
438
- gateType: "policy",
439
- outcome: "pass",
440
- failureClass: "none",
441
- rationale: "plan v2 compile gate passed",
442
- milestoneId: state.activeMilestone?.id ?? undefined,
443
- });
444
459
  }
445
460
  deps.syncCmuxSidebar(prefs, state);
446
461
  let mid = state.activeMilestone?.id;
@@ -947,10 +962,14 @@ export async function runDispatch(
947
962
  // ── Sliding-window stuck detection with graduated recovery ──
948
963
  const derivedKey = `${unitType}/${unitId}`;
949
964
 
950
- if (!s.pendingVerificationRetry) {
951
- loopState.recentUnits.push({ key: derivedKey });
952
- if (loopState.recentUnits.length > STUCK_WINDOW_SIZE) loopState.recentUnits.shift();
965
+ // Always record this dispatch in the sliding window so detectStuck() has
966
+ // accurate history. Skipping the push when pendingVerificationRetry is set
967
+ // caused infinite artifact-retry loops to be invisible to stuck detection
968
+ // (#2007). Only the *response* to a stuck signal is suppressed during retries.
969
+ loopState.recentUnits.push({ key: derivedKey });
970
+ if (loopState.recentUnits.length > STUCK_WINDOW_SIZE) loopState.recentUnits.shift();
953
971
 
972
+ if (!s.pendingVerificationRetry) {
954
973
  const stuckSignal = detectStuck(loopState.recentUnits);
955
974
  if (stuckSignal) {
956
975
  debugLog("autoLoop", {
@@ -1364,21 +1383,10 @@ export async function runUnitPhase(
1364
1383
  // Monorepo support (#2347): if no project files in the worktree directory,
1365
1384
  // walk parent directories up to the filesystem root. In monorepos,
1366
1385
  // package.json / Cargo.toml etc. live in a parent directory.
1367
- let hasProjectFileInParent = false;
1368
- if (!hasProjectFile && !hasSrcDir && !hasXcodeBundle) {
1369
- let checkDir = dirname(s.basePath);
1370
- const { root } = parsePath(checkDir);
1371
- while (checkDir !== root) {
1372
- // Stop at git repository boundary — ancestors above the repo root
1373
- // (e.g. ~ or /usr/local) may contain unrelated project files.
1374
- if (deps.existsSync(join(checkDir, ".git"))) break;
1375
- if (PROJECT_FILES.some((f) => deps.existsSync(join(checkDir, f)))) {
1376
- hasProjectFileInParent = true;
1377
- break;
1378
- }
1379
- checkDir = dirname(checkDir);
1380
- }
1381
- }
1386
+ const hasProjectFileInParent =
1387
+ !hasProjectFile && !hasSrcDir && !hasXcodeBundle
1388
+ ? hasProjectFileInAncestor(s.basePath, deps.existsSync)
1389
+ : false;
1382
1390
  if (!hasProjectFile && !hasSrcDir && !hasXcodeBundle && !hasProjectFileInParent) {
1383
1391
  // Greenfield projects won't have project files yet — the first task creates them.
1384
1392
  // Log a warning but allow execution to proceed. The .git check above is sufficient
@@ -1680,9 +1688,23 @@ export async function runUnitPhase(
1680
1688
 
1681
1689
  if (unitResult.status === "cancelled") {
1682
1690
  const errorCategory = unitResult.errorContext?.category;
1683
- // Provider-error pause: pauseAuto already handled cleanup and scheduled
1684
- // recovery. Don't hard-stop just break out of the loop (#2762).
1691
+ // Provider-error pause: agent_end recovery normally pauses before this
1692
+ // branch. Provider readiness failures happen before dispatch, so pause here
1693
+ // if nothing upstream already did.
1685
1694
  if (errorCategory === "provider") {
1695
+ if (!s.paused) {
1696
+ const detail = unitResult.errorContext?.message ?? `Provider unavailable for ${unitType} ${unitId}`;
1697
+ await pauseAutoForProviderError(
1698
+ ctx.ui,
1699
+ detail,
1700
+ () => deps.pauseAuto(ctx, pi),
1701
+ {
1702
+ isRateLimit: false,
1703
+ isTransient: Boolean(unitResult.errorContext?.isTransient),
1704
+ retryAfterMs: unitResult.errorContext?.retryAfterMs,
1705
+ },
1706
+ );
1707
+ }
1686
1708
  await emitCancelledUnitEnd(ic, unitType, unitId, unitStartSeq, unitResult.errorContext);
1687
1709
  debugLog("autoLoop", { phase: "exit", reason: "provider-pause", isTransient: unitResult.errorContext?.isTransient });
1688
1710
  return { action: "break", reason: "provider-pause" };
@@ -2084,6 +2106,8 @@ export async function runFinalize(
2084
2106
 
2085
2107
  // Both pre and post verification completed without timeout — reset counter
2086
2108
  loopState.consecutiveFinalizeTimeouts = 0;
2109
+ s.currentUnit = null;
2110
+ clearCurrentPhase();
2087
2111
 
2088
2112
  // Surface accumulated workflow-logger issues for this unit to the user.
2089
2113
  // Warnings/errors logged during the unit are buffered in the logger and
@@ -75,9 +75,7 @@ export interface PreExecFailure {
75
75
 
76
76
  // ─── Constants ───────────────────────────────────────────────────────────────
77
77
 
78
- export const MAX_UNIT_DISPATCHES = 3;
79
78
  export const STUB_RECOVERY_THRESHOLD = 2;
80
- export const MAX_LIFETIME_DISPATCHES = 6;
81
79
  export const NEW_SESSION_TIMEOUT_MS = 120_000;
82
80
 
83
81
  // ─── AutoSession ─────────────────────────────────────────────────────────────
@@ -178,6 +176,12 @@ export class AutoSession {
178
176
  * stopAuto does not attempt the same merge a second time (#2645). */
179
177
  milestoneMergedInPhases = false;
180
178
 
179
+ // #4765 — slice-cadence collapse: main-branch SHAs at the moment each
180
+ // milestone's first slice merge began. Used by resquashMilestoneOnMain at
181
+ // milestone completion to collapse N slice commits into one. Cleared when
182
+ // the milestone finishes (or resquash runs).
183
+ milestoneStartShas: Map<string, string> = new Map();
184
+
181
185
  // ── Dispatch circuit breakers ──────────────────────────────────────
182
186
  rewriteAttemptCount = 0;
183
187
  /** Tracks consecutive bootstrap attempts that found phase === "complete".
@@ -299,6 +303,7 @@ export class AutoSession {
299
303
  this.lastGitActionStatus = null;
300
304
  this.isolationDegraded = false;
301
305
  this.milestoneMergedInPhases = false;
306
+ this.milestoneStartShas = new Map();
302
307
  this.checkpointSha = null;
303
308
 
304
309
  // Signal handler
@@ -33,7 +33,8 @@ import { parseRoadmap } from "./parsers-legacy.js";
33
33
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
34
34
  import { logWarning, logError } from "./workflow-logger.js";
35
35
  import { join } from "node:path";
36
- import { hasImplementationArtifacts, classifyMilestoneSummaryContent } from "./auto-recovery.js";
36
+ import { hasImplementationArtifacts } from "./auto-recovery.js";
37
+ import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
37
38
  import {
38
39
  buildDiscussMilestonePrompt,
39
40
  buildResearchMilestonePrompt,
@@ -58,6 +59,10 @@ import {
58
59
  import { resolveModelWithFallbacksForUnit } from "./preferences-models.js";
59
60
  import { resolveUokFlags } from "./uok/flags.js";
60
61
  import { selectReactiveDispatchBatch } from "./uok/execution-graph.js";
62
+ import { getMilestonePipelineVariant } from "./milestone-scope-classifier.js";
63
+ import { EXECUTION_ENTRY_PHASES, hasFinalizedMilestoneContext } from "./uok/plan-v2.js";
64
+ import { isAutoActive } from "./auto.js";
65
+ import { markDepthVerified } from "./bootstrap/write-gate.js";
61
66
 
62
67
  // ─── Types ────────────────────────────────────────────────────────────────
63
68
 
@@ -88,6 +93,18 @@ export interface DispatchContext {
88
93
  modelRegistry?: MinimalModelRegistry;
89
94
  }
90
95
 
96
+ type ReassessmentChecker = typeof checkNeedsReassessment;
97
+
98
+ let reassessmentChecker: ReassessmentChecker = checkNeedsReassessment;
99
+
100
+ export function setReassessmentCheckerForTest(checker: ReassessmentChecker): () => void {
101
+ const previous = reassessmentChecker;
102
+ reassessmentChecker = checker;
103
+ return () => {
104
+ reassessmentChecker = previous;
105
+ };
106
+ }
107
+
91
108
  export interface DispatchRule {
92
109
  /** Human-readable name for debugging and test identification */
93
110
  name: string;
@@ -95,6 +112,38 @@ export interface DispatchRule {
95
112
  match: (ctx: DispatchContext) => Promise<DispatchAction | null>;
96
113
  }
97
114
 
115
+ async function readUatGateVerdict(
116
+ basePath: string,
117
+ mid: string,
118
+ sliceId: string,
119
+ ): Promise<{ verdict: string; uatType: UatType | undefined } | null> {
120
+ const uatFile = resolveSliceFile(basePath, mid, sliceId, "UAT");
121
+ const assessmentFile = resolveSliceFile(basePath, mid, sliceId, "ASSESSMENT");
122
+
123
+ const uatContent = uatFile ? await loadFile(uatFile) : null;
124
+ const uatType = uatContent ? extractUatType(uatContent) : undefined;
125
+
126
+ const assessmentContent = assessmentFile ? await loadFile(assessmentFile) : null;
127
+ if (assessmentContent) {
128
+ const assessmentVerdict = extractVerdict(assessmentContent);
129
+ if (assessmentVerdict) {
130
+ return {
131
+ verdict: assessmentVerdict,
132
+ uatType: uatType ?? extractUatType(assessmentContent),
133
+ };
134
+ }
135
+ }
136
+
137
+ if (uatContent) {
138
+ const legacyUatVerdict = extractVerdict(uatContent);
139
+ if (legacyUatVerdict) {
140
+ return { verdict: legacyUatVerdict, uatType };
141
+ }
142
+ }
143
+
144
+ return null;
145
+ }
146
+
98
147
  function missingSliceStop(mid: string, phase: string): DispatchAction {
99
148
  return {
100
149
  action: "stop",
@@ -242,6 +291,48 @@ export const DISPATCH_RULES: DispatchRule[] = [
242
291
  };
243
292
  },
244
293
  },
294
+ {
295
+ // #4671 — Recovery path for execution-entry phases with missing CONTEXT.md.
296
+ //
297
+ // Once `deriveStateFromDb` returns an execution-entry phase (executing /
298
+ // summarizing / validating-milestone / completing-milestone), the
299
+ // pre-planning guard at `pre-planning (no context) → discuss-milestone`
300
+ // no longer fires. The plan-v2 gate correctly detects the missing context
301
+ // but can only block — it cannot redispatch. Without this rule the
302
+ // milestone is stuck until `/gsd doctor heal` repairs it (and heal
303
+ // historically missed this check too).
304
+ //
305
+ // Fire BEFORE the execution-entry phase rules so we redispatch to
306
+ // `discuss-milestone` instead of hitting the plan-v2 gate.
307
+ name: "execution-entry phase (no context) → discuss-milestone",
308
+ match: async ({ state, mid, midTitle, basePath, structuredQuestionsAvailable }) => {
309
+ if (!EXECUTION_ENTRY_PHASES.has(state.phase)) return null;
310
+ // Align with the plan-v2 gate's lookup semantics: whitespace-only counts
311
+ // as missing, and an auto worktree may fall back to GSD_PROJECT_ROOT.
312
+ if (hasFinalizedMilestoneContext(basePath, mid)) return null;
313
+ // H6 fix (#4973): In auto-mode there is no human to answer the
314
+ // depth-verification ask_user_questions, so the write-gate deadlocks.
315
+ // Pre-mark the milestone as depth-verified so gsd_summary_save({artifact_type:"CONTEXT"})
316
+ // is not blocked. Safe ordering: session_switch fires clearDiscussionFlowState()
317
+ // (register-hooks.ts:106) before before_agent_start, which fires before resolveDispatch
318
+ // reaches this match fn — so this call always happens after any session-switch reset.
319
+ // Interactive sessions (isAutoActive()===false) are unaffected.
320
+ if (isAutoActive()) {
321
+ markDepthVerified(mid, basePath);
322
+ }
323
+ return {
324
+ action: "dispatch",
325
+ unitType: "discuss-milestone",
326
+ unitId: mid,
327
+ prompt: await buildDiscussMilestonePrompt(
328
+ mid,
329
+ midTitle,
330
+ basePath,
331
+ structuredQuestionsAvailable,
332
+ ),
333
+ };
334
+ },
335
+ },
245
336
  {
246
337
  name: "summarizing → complete-slice",
247
338
  match: async ({ state, mid, midTitle, basePath }) => {
@@ -302,27 +393,28 @@ export const DISPATCH_RULES: DispatchRule[] = [
302
393
  // Only applies when UAT dispatch is enabled
303
394
  if (!prefs?.uat_dispatch) return null;
304
395
 
305
- const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
306
-
307
- // DB-first: get completed slices from DB
308
- let completedSliceIds: string[];
396
+ // DB-first: prefer closed slices from DB; fall back to ROADMAP on disk.
397
+ let closedSliceIds: string[];
309
398
  if (isDbAvailable()) {
310
- completedSliceIds = getMilestoneSlices(mid)
311
- .filter(s => s.status === "complete")
399
+ closedSliceIds = getMilestoneSlices(mid)
400
+ .filter(s => isClosedStatus(s.status))
312
401
  .map(s => s.id);
313
402
  } else {
314
- return null;
403
+ // Filesystem fallback for degraded / unmigrated projects.
404
+ // `slice.done` in the parsed ROADMAP is the disk-level closed signal.
405
+ const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
406
+ const roadmapContent = roadmapFile ? await loadFile(roadmapFile) : null;
407
+ if (!roadmapContent) return null;
408
+ const roadmap = parseRoadmap(roadmapContent);
409
+ closedSliceIds = roadmap.slices.filter(s => s.done).map(s => s.id);
315
410
  }
316
411
 
317
- for (const sliceId of completedSliceIds) {
318
- const resultFile = resolveSliceFile(basePath, mid, sliceId, "UAT");
319
- if (!resultFile) continue;
320
- const content = await loadFile(resultFile);
321
- if (!content) continue;
322
- const verdict = extractVerdict(content);
323
- const uatType = extractUatType(content);
412
+ for (const sliceId of closedSliceIds) {
413
+ const result = await readUatGateVerdict(basePath, mid, sliceId);
414
+ if (!result) continue;
415
+ const { verdict, uatType } = result;
324
416
 
325
- if (verdict && !isAcceptableUatVerdict(verdict, uatType)) {
417
+ if (!isAcceptableUatVerdict(verdict, uatType)) {
326
418
  return {
327
419
  action: "stop" as const,
328
420
  reason: `UAT verdict for ${sliceId} is "${verdict}" — blocking progression until resolved.\nReview the UAT result and update the verdict to PASS, or re-run /gsd auto after fixing.`,
@@ -337,11 +429,15 @@ export const DISPATCH_RULES: DispatchRule[] = [
337
429
  name: "reassess-roadmap (post-completion)",
338
430
  match: async ({ state, mid, midTitle, basePath, prefs }) => {
339
431
  if (prefs?.phases?.skip_reassess) return null;
340
- // Default reassess_after_slice to true reassessment after slice completion
341
- // is essential for roadmap integrity. Opt-out via explicit `false`.
342
- const reassessEnabled = prefs?.phases?.reassess_after_slice ?? true;
432
+ // Default reassess_after_slice to false per ADR-003 §4 most reassess
433
+ // units conclude "roadmap is fine" and burn a session for no change.
434
+ // The plan-slice prompt now carries a reassessment preamble so the
435
+ // next slice's planner does JIT roadmap verification at zero extra
436
+ // cost. Opt-in via explicit `reassess_after_slice: true` (e.g.
437
+ // burn-max profile) when you want the dedicated reassess session.
438
+ const reassessEnabled = prefs?.phases?.reassess_after_slice ?? false;
343
439
  if (!reassessEnabled) return null;
344
- const needsReassess = await checkNeedsReassessment(basePath, mid, state);
440
+ const needsReassess = await reassessmentChecker(basePath, mid, state);
345
441
  if (!needsReassess) return null;
346
442
  return {
347
443
  action: "dispatch",
@@ -360,6 +456,12 @@ export const DISPATCH_RULES: DispatchRule[] = [
360
456
  name: "needs-discussion → discuss-milestone",
361
457
  match: async ({ state, mid, midTitle, basePath, structuredQuestionsAvailable }) => {
362
458
  if (state.phase !== "needs-discussion") return null;
459
+ // H6 fix (#4973): auto-mark depth-verified so the write-gate does not
460
+ // deadlock in non-interactive (auto-mode) runs. See ordering note at
461
+ // "execution-entry phase (no context) → discuss-milestone" above.
462
+ if (isAutoActive()) {
463
+ markDepthVerified(mid, basePath);
464
+ }
363
465
  return {
364
466
  action: "dispatch",
365
467
  unitType: "discuss-milestone",
@@ -380,6 +482,12 @@ export const DISPATCH_RULES: DispatchRule[] = [
380
482
  const contextFile = resolveMilestoneFile(basePath, mid, "CONTEXT");
381
483
  const hasContext = !!(contextFile && (await loadFile(contextFile)));
382
484
  if (hasContext) return null; // fall through to next rule
485
+ // H6 fix (#4973): auto-mark depth-verified so the write-gate does not
486
+ // deadlock in non-interactive (auto-mode) runs. See ordering note at
487
+ // "execution-entry phase (no context) → discuss-milestone" above.
488
+ if (isAutoActive()) {
489
+ markDepthVerified(mid, basePath);
490
+ }
383
491
  return {
384
492
  action: "dispatch",
385
493
  unitType: "discuss-milestone",
@@ -448,6 +556,11 @@ export const DISPATCH_RULES: DispatchRule[] = [
448
556
  match: async ({ state, mid, midTitle, basePath, prefs }) => {
449
557
  if (state.phase !== "planning") return null;
450
558
  if (prefs?.phases?.skip_research || prefs?.phases?.skip_slice_research) return null;
559
+ // #4781 phase 2: trivial-scope milestones skip dedicated slice research.
560
+ // plan-slice absorbs the lightweight discovery a trivial deliverable
561
+ // needs. Null result (DB unavailable / unknown) falls through to today's
562
+ // behavior.
563
+ if (await getMilestonePipelineVariant(mid) === "trivial") return null;
451
564
 
452
565
  // Load roadmap to find all slices
453
566
  const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
@@ -504,6 +617,8 @@ export const DISPATCH_RULES: DispatchRule[] = [
504
617
  // Phase skip: skip research when preference or profile says so
505
618
  if (prefs?.phases?.skip_research || prefs?.phases?.skip_slice_research)
506
619
  return null;
620
+ // #4781 phase 2: trivial-scope milestones skip dedicated slice research.
621
+ if (await getMilestonePipelineVariant(mid) === "trivial") return null;
507
622
  if (!state.activeSlice) return missingSliceStop(mid, state.phase);
508
623
  const sid = state.activeSlice!.id;
509
624
  const sTitle = state.activeSlice!.title;
@@ -856,8 +971,13 @@ export const DISPATCH_RULES: DispatchRule[] = [
856
971
  };
857
972
  }
858
973
 
859
- // Skip preference: write a minimal pass-through VALIDATION file
860
- if (prefs?.phases?.skip_milestone_validation) {
974
+ // #4781 phase 2: trivial-scope milestones skip the dedicated validate
975
+ // unit — complete-milestone's own verification steps (3/4/5 in the
976
+ // closer prompt) are sufficient proof for contained deliverables.
977
+ const trivialVariant = await getMilestonePipelineVariant(mid) === "trivial";
978
+
979
+ // Skip preference OR trivial scope: write a minimal pass-through VALIDATION file.
980
+ if (prefs?.phases?.skip_milestone_validation || trivialVariant) {
861
981
  const mDir = resolveMilestonePath(basePath, mid);
862
982
  if (mDir) {
863
983
  if (!existsSync(mDir)) mkdirSync(mDir, { recursive: true });
@@ -865,15 +985,18 @@ export const DISPATCH_RULES: DispatchRule[] = [
865
985
  mDir,
866
986
  buildMilestoneFileName(mid, "VALIDATION"),
867
987
  );
988
+ const skipSource = trivialVariant
989
+ ? "trivial-scope pipeline variant (#4781)"
990
+ : "`skip_milestone_validation` preference";
868
991
  const content = [
869
992
  "---",
870
993
  "verdict: pass",
871
994
  "remediation_round: 0",
872
995
  "---",
873
996
  "",
874
- "# Milestone Validation (skipped by preference)",
997
+ "# Milestone Validation (skipped)",
875
998
  "",
876
- "Milestone validation was skipped via `skip_milestone_validation` preference.",
999
+ `Milestone validation was skipped via ${skipSource}.`,
877
1000
  ].join("\n");
878
1001
  writeFileSync(validationPath, content, "utf-8");
879
1002
  }
@@ -905,7 +1028,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
905
1028
 
906
1029
  const existingSummary = resolveMilestoneFile(basePath, mid, "SUMMARY");
907
1030
  let summaryOutcome: "success" | "failure" | "unknown" = "unknown";
908
- if (existingSummary && isDbAvailable()) {
1031
+ if (existingSummary) {
909
1032
  const summaryContent = await loadFile(existingSummary);
910
1033
  if (summaryContent) {
911
1034
  summaryOutcome = classifyMilestoneSummaryContent(summaryContent);
@@ -944,7 +1067,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
944
1067
  // Safety guard (#1703): verify the milestone produced implementation
945
1068
  // artifacts (non-.gsd/ files). A milestone with only plan files and
946
1069
  // zero implementation code should not be marked complete.
947
- const artifactCheck = hasImplementationArtifacts(basePath);
1070
+ const artifactCheck = hasImplementationArtifacts(basePath, mid);
948
1071
  if (artifactCheck === "absent") {
949
1072
  return {
950
1073
  action: "stop",
@@ -999,11 +1122,15 @@ export const DISPATCH_RULES: DispatchRule[] = [
999
1122
  // - success summary: reconcile DB and skip re-dispatch
1000
1123
  // - failure summary: pause/fail-closed
1001
1124
  // - unknown summary: pause/fail-closed
1002
- if (existingSummary && isDbAvailable()) {
1003
- const milestone = getMilestone(mid);
1004
- const status = milestone?.status ?? "missing";
1125
+ if (existingSummary) {
1126
+ const milestone = isDbAvailable() ? getMilestone(mid) : null;
1127
+ const status = milestone?.status ?? (isDbAvailable() ? "missing" : "unavailable");
1005
1128
 
1006
1129
  if (summaryOutcome === "success") {
1130
+ if (!isDbAvailable()) {
1131
+ logWarning("dispatch", `Milestone ${mid} SUMMARY indicates completion while DB is unavailable — skipping duplicate complete-milestone dispatch`);
1132
+ return { action: "skip" };
1133
+ }
1007
1134
  try {
1008
1135
  updateMilestoneStatus(mid, "complete", new Date().toISOString());
1009
1136
  logWarning("dispatch", `Milestone ${mid} SUMMARY indicates completion while DB status was "${status}" — reconciled DB to complete (#4658)`);