gsd-pi 2.82.0-dev.c22380fc3 → 2.82.0-dev.e7a7f1ed5

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 (390) hide show
  1. package/README.md +5 -4
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/GSD-WORKFLOW.md +10 -1
  4. package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
  5. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +1 -1
  6. package/dist/resources/extensions/cmux/index.js +5 -0
  7. package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
  8. package/dist/resources/extensions/gsd/auto/loop.js +5 -5
  9. package/dist/resources/extensions/gsd/auto/orchestrator.js +11 -0
  10. package/dist/resources/extensions/gsd/auto/phases.js +81 -31
  11. package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
  12. package/dist/resources/extensions/gsd/auto-dashboard.js +66 -1
  13. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +1 -0
  14. package/dist/resources/extensions/gsd/auto-dispatch.js +18 -17
  15. package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
  16. package/dist/resources/extensions/gsd/auto-post-unit.js +233 -127
  17. package/dist/resources/extensions/gsd/auto-prompts.js +2 -2
  18. package/dist/resources/extensions/gsd/auto-recovery.js +71 -14
  19. package/dist/resources/extensions/gsd/auto-start.js +87 -14
  20. package/dist/resources/extensions/gsd/auto-verification.js +45 -26
  21. package/dist/resources/extensions/gsd/auto-worktree.js +176 -10
  22. package/dist/resources/extensions/gsd/auto.js +37 -5
  23. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +31 -7
  24. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +9 -8
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +4 -2
  26. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
  27. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -2
  28. package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
  29. package/dist/resources/extensions/gsd/commands/catalog.js +4 -1
  30. package/dist/resources/extensions/gsd/commands/handlers/core.js +37 -0
  31. package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
  32. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +7 -2
  33. package/dist/resources/extensions/gsd/crash-recovery.js +43 -5
  34. package/dist/resources/extensions/gsd/db/milestone-leases.js +24 -0
  35. package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
  36. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
  37. package/dist/resources/extensions/gsd/doctor-git-checks.js +46 -1
  38. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
  39. package/dist/resources/extensions/gsd/doctor.js +2 -28
  40. package/dist/resources/extensions/gsd/export-html.js +27 -425
  41. package/dist/resources/extensions/gsd/git-service.js +45 -3
  42. package/dist/resources/extensions/gsd/gsd-db.js +21 -6
  43. package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -3
  44. package/dist/resources/extensions/gsd/guided-flow.js +101 -116
  45. package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
  46. package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
  47. package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
  48. package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
  49. package/dist/resources/extensions/gsd/native-git-bridge.js +48 -12
  50. package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
  51. package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
  52. package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
  53. package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
  54. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  55. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  56. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  57. package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
  58. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  59. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  60. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  61. package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
  62. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  63. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  64. package/dist/resources/extensions/gsd/queue-reorder-ui.js +30 -13
  65. package/dist/resources/extensions/gsd/smart-entry-routing.js +36 -0
  66. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
  67. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
  68. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
  69. package/dist/resources/extensions/gsd/status-guards.js +11 -0
  70. package/dist/resources/extensions/gsd/templates/plan.md +8 -5
  71. package/dist/resources/extensions/gsd/templates/task-plan.md +4 -2
  72. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -8
  73. package/dist/resources/extensions/gsd/tools/complete-slice.js +6 -8
  74. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
  75. package/dist/resources/extensions/gsd/tools/plan-slice.js +89 -14
  76. package/dist/resources/extensions/gsd/unit-context-manifest.js +32 -10
  77. package/dist/resources/extensions/gsd/validation.js +23 -1
  78. package/dist/resources/extensions/gsd/verification-gate.js +68 -7
  79. package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
  80. package/dist/resources/extensions/gsd/workflow-mcp.js +17 -1
  81. package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
  82. package/dist/resources/extensions/gsd/worktree-lifecycle.js +33 -8
  83. package/dist/resources/extensions/shared/html-shell.js +388 -0
  84. package/dist/resources/extensions/subagent/index.js +448 -78
  85. package/dist/resources/extensions/subagent/launch.js +77 -0
  86. package/dist/resources/extensions/subagent/run-store.js +148 -0
  87. package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
  88. package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
  89. package/dist/resources/extensions/visual-brief/index.js +5 -0
  90. package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
  91. package/dist/resources/extensions/visual-brief/prompts.js +140 -0
  92. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  93. package/dist/web/standalone/.next/BUILD_ID +1 -1
  94. package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
  95. package/dist/web/standalone/.next/build-manifest.json +3 -3
  96. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  97. package/dist/web/standalone/.next/react-loadable-manifest.json +3 -3
  98. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  100. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  108. package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  109. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  111. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -7
  112. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
  113. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -5
  115. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
  118. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/index.html +1 -1
  121. package/dist/web/standalone/.next/server/app/index.rsc +4 -7
  122. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -7
  124. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -5
  126. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
  127. package/dist/web/standalone/.next/server/app/page.js +2 -2
  128. package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
  129. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
  131. package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
  132. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  136. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  137. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  138. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  139. package/dist/web/standalone/.next/static/chunks/2973.33f26573894b6153.js +2 -0
  140. package/dist/web/standalone/.next/static/chunks/{8359.e059d86b255fce1c.js → 8359.7eb3bb8f8ecf4c01.js} +2 -2
  141. package/dist/web/standalone/.next/static/chunks/app/layout-8c10ec293ae0f1d5.js +1 -0
  142. package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-9a4db269f9ed63ad.js} +1 -1
  143. package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
  144. package/package.json +4 -4
  145. package/packages/mcp-server/src/workflow-tools.test.ts +1 -1
  146. package/packages/native/tsconfig.json +2 -1
  147. package/packages/native/tsconfig.tsbuildinfo +1 -1
  148. package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
  149. package/packages/pi-ai/dist/providers/google-gemini-cli.js +5 -0
  150. package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
  151. package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts +2 -0
  152. package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts.map +1 -0
  153. package/packages/pi-ai/dist/providers/google-gemini-cli.test.js +41 -0
  154. package/packages/pi-ai/dist/providers/google-gemini-cli.test.js.map +1 -0
  155. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  156. package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
  157. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  158. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
  159. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
  160. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
  161. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
  162. package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
  163. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  164. package/packages/pi-ai/dist/providers/simple-options.js +5 -6
  165. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  166. package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
  167. package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
  168. package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
  169. package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
  170. package/packages/pi-ai/src/providers/google-gemini-cli.test.ts +49 -0
  171. package/packages/pi-ai/src/providers/google-gemini-cli.ts +7 -0
  172. package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
  173. package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
  174. package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
  175. package/packages/pi-ai/src/providers/simple-options.ts +5 -6
  176. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  177. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
  178. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
  179. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
  180. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
  181. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
  182. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  183. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  184. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
  185. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  186. package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
  187. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
  188. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
  189. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  190. package/packages/pi-tui/dist/__tests__/terminal.test.d.ts +2 -0
  191. package/packages/pi-tui/dist/__tests__/terminal.test.d.ts.map +1 -0
  192. package/packages/pi-tui/dist/__tests__/terminal.test.js +103 -0
  193. package/packages/pi-tui/dist/__tests__/terminal.test.js.map +1 -0
  194. package/packages/pi-tui/dist/terminal.d.ts +2 -0
  195. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  196. package/packages/pi-tui/dist/terminal.js +12 -0
  197. package/packages/pi-tui/dist/terminal.js.map +1 -1
  198. package/packages/pi-tui/src/__tests__/terminal.test.ts +121 -0
  199. package/packages/pi-tui/src/terminal.ts +11 -0
  200. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  201. package/src/resources/GSD-WORKFLOW.md +10 -1
  202. package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
  203. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +1 -1
  204. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
  205. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +9 -0
  206. package/src/resources/extensions/cmux/index.ts +6 -0
  207. package/src/resources/extensions/gsd/auto/contracts.ts +14 -6
  208. package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
  209. package/src/resources/extensions/gsd/auto/loop.ts +8 -5
  210. package/src/resources/extensions/gsd/auto/orchestrator.ts +11 -0
  211. package/src/resources/extensions/gsd/auto/phases.ts +90 -38
  212. package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
  213. package/src/resources/extensions/gsd/auto-dashboard.ts +72 -1
  214. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +1 -0
  215. package/src/resources/extensions/gsd/auto-dispatch.ts +19 -17
  216. package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
  217. package/src/resources/extensions/gsd/auto-post-unit.ts +266 -139
  218. package/src/resources/extensions/gsd/auto-prompts.ts +2 -2
  219. package/src/resources/extensions/gsd/auto-recovery.ts +74 -11
  220. package/src/resources/extensions/gsd/auto-start.ts +94 -12
  221. package/src/resources/extensions/gsd/auto-verification.ts +58 -36
  222. package/src/resources/extensions/gsd/auto-worktree.ts +193 -10
  223. package/src/resources/extensions/gsd/auto.ts +40 -5
  224. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +42 -7
  225. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +9 -8
  226. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +4 -2
  227. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
  228. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +19 -3
  229. package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
  230. package/src/resources/extensions/gsd/commands/catalog.ts +4 -1
  231. package/src/resources/extensions/gsd/commands/handlers/core.ts +40 -0
  232. package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
  233. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +8 -3
  234. package/src/resources/extensions/gsd/crash-recovery.ts +44 -4
  235. package/src/resources/extensions/gsd/db/milestone-leases.ts +26 -0
  236. package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
  237. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
  238. package/src/resources/extensions/gsd/doctor-git-checks.ts +45 -1
  239. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
  240. package/src/resources/extensions/gsd/doctor-types.ts +1 -0
  241. package/src/resources/extensions/gsd/doctor.ts +2 -27
  242. package/src/resources/extensions/gsd/export-html.ts +27 -427
  243. package/src/resources/extensions/gsd/git-service.ts +51 -4
  244. package/src/resources/extensions/gsd/gsd-db.ts +21 -6
  245. package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -3
  246. package/src/resources/extensions/gsd/guided-flow.ts +134 -133
  247. package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
  248. package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
  249. package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
  250. package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
  251. package/src/resources/extensions/gsd/native-git-bridge.ts +54 -12
  252. package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
  253. package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
  254. package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
  255. package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
  256. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  257. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  258. package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  259. package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
  260. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  261. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  262. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  263. package/src/resources/extensions/gsd/prompts/queue.md +4 -4
  264. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  265. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  266. package/src/resources/extensions/gsd/queue-reorder-ui.ts +31 -13
  267. package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
  268. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
  269. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
  270. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
  271. package/src/resources/extensions/gsd/status-guards.ts +13 -0
  272. package/src/resources/extensions/gsd/templates/plan.md +8 -5
  273. package/src/resources/extensions/gsd/templates/task-plan.md +4 -2
  274. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +71 -0
  275. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
  276. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +56 -0
  277. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +80 -1
  278. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +35 -7
  279. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +53 -2
  280. package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +12 -1
  281. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +91 -6
  282. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
  283. package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +20 -0
  284. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
  285. package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
  286. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +87 -0
  287. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
  288. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +11 -2
  289. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
  290. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
  291. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
  292. package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
  293. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +86 -2
  294. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
  295. package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
  296. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +59 -2
  297. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +66 -0
  298. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
  299. package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
  300. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +38 -0
  301. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
  302. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +11 -0
  303. package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
  304. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
  305. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
  306. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
  307. package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
  308. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
  309. package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
  310. package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
  311. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
  312. package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
  313. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +112 -1
  314. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
  315. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +46 -0
  316. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +179 -0
  317. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
  318. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
  319. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +63 -2
  320. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
  321. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
  322. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
  323. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
  324. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  325. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +225 -1
  326. package/src/resources/extensions/gsd/tests/plan-task.test.ts +17 -0
  327. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  328. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +86 -0
  329. package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
  330. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +53 -0
  331. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +59 -0
  332. package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
  333. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +37 -1
  334. package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +54 -0
  335. package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +89 -2
  336. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +2 -3
  337. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
  338. package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
  339. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +53 -2
  340. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
  341. package/src/resources/extensions/gsd/tests/status-guards.test.ts +13 -1
  342. package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
  343. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
  344. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +86 -7
  345. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +29 -2
  346. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
  347. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
  348. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +19 -1
  349. package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
  350. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1 -1
  351. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
  352. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
  353. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +54 -0
  354. package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
  355. package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
  356. package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
  357. package/src/resources/extensions/gsd/tools/plan-slice.ts +98 -12
  358. package/src/resources/extensions/gsd/types.ts +1 -1
  359. package/src/resources/extensions/gsd/unit-context-manifest.ts +47 -11
  360. package/src/resources/extensions/gsd/validation.ts +23 -1
  361. package/src/resources/extensions/gsd/verification-gate.ts +78 -6
  362. package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
  363. package/src/resources/extensions/gsd/workflow-mcp.ts +18 -1
  364. package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
  365. package/src/resources/extensions/gsd/worktree-lifecycle.ts +41 -8
  366. package/src/resources/extensions/shared/html-shell.ts +412 -0
  367. package/src/resources/extensions/subagent/index.ts +567 -103
  368. package/src/resources/extensions/subagent/launch.ts +131 -0
  369. package/src/resources/extensions/subagent/run-store.ts +218 -0
  370. package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
  371. package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
  372. package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
  373. package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
  374. package/src/resources/extensions/visual-brief/index.ts +8 -0
  375. package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
  376. package/src/resources/extensions/visual-brief/prompts.ts +183 -0
  377. package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
  378. package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
  379. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
  380. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
  381. package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
  382. package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
  383. package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  384. package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  385. package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
  386. package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  387. package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
  388. package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  389. /package/dist/web/standalone/.next/static/{Wop3A7KRGyR06H3rla_1- → 4dSwdrs__8NwCZggxP9KF}/_buildManifest.js +0 -0
  390. /package/dist/web/standalone/.next/static/{Wop3A7KRGyR06H3rla_1- → 4dSwdrs__8NwCZggxP9KF}/_ssgManifest.js +0 -0
@@ -21,10 +21,10 @@ import { invalidateAllCaches } from "./cache.js";
21
21
  import { writeLock, clearLock } from "./crash-recovery.js";
22
22
  import { acquireSessionLock, releaseSessionLock, updateSessionLock, } from "./session-lock.js";
23
23
  import { ensureGitignore, untrackRuntimeFiles } from "./gitignore.js";
24
- import { nativeIsRepo, nativeInit, nativeAddAll, nativeCommit, nativeGetCurrentBranch, nativeDetectMainBranch, nativeCheckoutBranch, nativeBranchList, nativeBranchListMerged, nativeBranchDelete, nativeWorktreeRemove, nativeCommitCountBetween, } from "./native-git-bridge.js";
24
+ import { nativeIsRepo, nativeInit, nativeAddAll, nativeCommit, nativeGetCurrentBranch, nativeDetectMainBranch, nativeBranchList, nativeBranchExists, nativeBranchListMerged, nativeBranchDelete, nativeWorktreeRemove, nativeCommitCountBetween, } from "./native-git-bridge.js";
25
25
  import { GitServiceImpl } from "./git-service.js";
26
26
  import { captureIntegrationBranch, detectWorktreeName, setActiveMilestoneId, } from "./worktree.js";
27
- import { getAutoWorktreePath } from "./auto-worktree.js";
27
+ import { getAutoWorktreePath, checkoutBranchWithStashGuard } from "./auto-worktree.js";
28
28
  import { readResourceVersion, cleanStaleRuntimeUnits } from "./auto-worktree.js";
29
29
  import { worktreePath as getWorktreeDir, isInsideWorktreesDir } from "./worktree-manager.js";
30
30
  import { emitWorktreeOrphaned } from "./worktree-telemetry.js";
@@ -33,7 +33,7 @@ import { initRoutingHistory } from "./routing-history.js";
33
33
  import { restoreHookState, resetHookState } from "./post-unit-hooks.js";
34
34
  import { resetProactiveHealing, setLevelChangeCallback } from "./doctor-proactive.js";
35
35
  import { snapshotSkills } from "./skill-discovery.js";
36
- import { isDbAvailable, getMilestone, openDatabase, getDbStatus } from "./gsd-db.js";
36
+ import { isDbAvailable, getMilestone, getAllMilestones, openDatabase, getDbStatus } from "./gsd-db.js";
37
37
  import { isClosedStatus } from "./status-guards.js";
38
38
  import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
39
39
  import { auditOrphanedPreflightStashes } from "./orphan-stash-audit.js";
@@ -88,9 +88,11 @@ export function decideSurvivorAction(hasSurvivorBranch, phase) {
88
88
  return "finalize";
89
89
  return "none";
90
90
  }
91
- export function auditOrphanedMilestoneBranches(basePath, isolationMode) {
91
+ export function auditOrphanedMilestoneBranches(basePath, isolationMode, gitDeps = {}) {
92
92
  const recovered = [];
93
93
  const warnings = [];
94
+ const branchList = gitDeps.branchList ?? nativeBranchList;
95
+ const branchExists = gitDeps.branchExists ?? nativeBranchExists;
94
96
  // Skip in none mode — no milestone branches are created
95
97
  if (isolationMode === "none")
96
98
  return { recovered, warnings };
@@ -98,15 +100,16 @@ export function auditOrphanedMilestoneBranches(basePath, isolationMode) {
98
100
  if (!isDbAvailable())
99
101
  return { recovered, warnings };
100
102
  let milestoneBranches;
103
+ let milestoneBranchListAvailable = true;
101
104
  try {
102
- milestoneBranches = nativeBranchList(basePath, "milestone/*");
105
+ milestoneBranches = branchList(basePath, "milestone/*");
103
106
  }
104
107
  catch {
105
- // git branch list failed — skip audit
106
- return { recovered, warnings };
108
+ milestoneBranchListAvailable = false;
109
+ // git branch list failed — fall through with an empty branch set so the
110
+ // branch-less orphan pass can still run after per-milestone verification.
111
+ milestoneBranches = [];
107
112
  }
108
- if (milestoneBranches.length === 0)
109
- return { recovered, warnings };
110
113
  // Detect main branch for merge-check
111
114
  let mainBranch;
112
115
  try {
@@ -236,6 +239,71 @@ export function auditOrphanedMilestoneBranches(basePath, isolationMode) {
236
239
  }
237
240
  }
238
241
  }
242
+ // Second pass (#5879): catch worktree directories stranded by a previous
243
+ // audit that deleted the milestone/* branch but failed to remove the
244
+ // directory (or the dir was orphaned by a separate path entirely, e.g.
245
+ // postflight-stash-restore-failed during closeout). The branch-keyed loop
246
+ // above is invisible to these cases — `nativeBranchList` returns nothing
247
+ // for the milestone, so the dir-cleanup block at line ~310 is never
248
+ // reached.
249
+ //
250
+ // Keyed on milestones whose DB status is `complete`. We do not iterate
251
+ // over arbitrary directories under .gsd/worktrees/ to avoid touching
252
+ // dirs that belong to an in-progress milestone whose branch was deleted
253
+ // separately — those are handled by the in-progress orphan path above
254
+ // when the branch is present, and by `/gsd doctor` when it is not.
255
+ const seenMilestoneIds = new Set(milestoneBranches.map((branch) => branch.replace(/^milestone\//, "")));
256
+ let completedMilestones = [];
257
+ try {
258
+ completedMilestones = getAllMilestones();
259
+ }
260
+ catch {
261
+ // DB read failure — skip the second pass; the first pass is still useful.
262
+ completedMilestones = [];
263
+ }
264
+ for (const m of completedMilestones) {
265
+ if (m.status !== "complete")
266
+ continue;
267
+ if (seenMilestoneIds.has(m.id))
268
+ continue; // already processed in the branch loop
269
+ if (!milestoneBranchListAvailable) {
270
+ try {
271
+ if (branchExists(basePath, `milestone/${m.id}`))
272
+ continue;
273
+ }
274
+ catch (err) {
275
+ warnings.push(`Could not verify whether milestone/${m.id} still exists; skipping branch-less worktree cleanup for safety: ${err instanceof Error ? err.message : String(err)}`);
276
+ continue;
277
+ }
278
+ }
279
+ const wtDir = getWorktreeDir(basePath, m.id);
280
+ if (!existsSync(wtDir))
281
+ continue;
282
+ if (!isInsideWorktreesDir(basePath, wtDir)) {
283
+ warnings.push(`Orphaned worktree directory for ${m.id} is outside .gsd/worktrees/ — skipping removal for safety.`);
284
+ continue;
285
+ }
286
+ // Try `git worktree remove` first in case the dir is still registered
287
+ // (defensive — usually it is not when we reach this branch-less pass).
288
+ try {
289
+ nativeWorktreeRemove(basePath, wtDir, true);
290
+ }
291
+ catch (e) {
292
+ logWarning("engine", `worktree remove failed (expected for branch-less orphans): ${e instanceof Error ? e.message : String(e)}`);
293
+ }
294
+ if (existsSync(wtDir)) {
295
+ try {
296
+ rmSync(wtDir, { recursive: true, force: true });
297
+ recovered.push(`Removed orphaned worktree directory for ${m.id} (branch already deleted).`);
298
+ }
299
+ catch (err) {
300
+ warnings.push(`Failed to remove orphaned worktree directory for ${m.id}: ${err instanceof Error ? err.message : String(err)}`);
301
+ }
302
+ }
303
+ else {
304
+ recovered.push(`Removed orphaned worktree directory for ${m.id} (branch already deleted).`);
305
+ }
306
+ }
239
307
  return { recovered, warnings };
240
308
  }
241
309
  /**
@@ -368,7 +436,7 @@ export function _mergeOrphanCompletedMilestone(lifecycle, orphanId, ui) {
368
436
  return { merged: false, error: err };
369
437
  }
370
438
  export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, requestedStepMode, deps, interrupted) {
371
- const { shouldUseWorktreeIsolation, registerSigtermHandler, lockBase, buildLifecycle, } = deps;
439
+ const { shouldUseWorktreeIsolation, registerSigtermHandler, registerAutoWorkerForSession, lockBase, buildLifecycle, } = deps;
372
440
  const dirCheck = validateDirectory(base);
373
441
  if (dirCheck.severity === "blocked") {
374
442
  ctx.ui.notify(dirCheck.reason, "error");
@@ -523,6 +591,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
523
591
  // consult DB status and avoid clearing runtime units for milestones that
524
592
  // only have a failure-path SUMMARY on disk (#4663).
525
593
  await openProjectDbIfPresent(base);
594
+ registerAutoWorkerForSession(base);
526
595
  // Clean stale runtime unit files for completed milestones (#887).
527
596
  // DB-authoritative: when DB is available, require DB status to be closed
528
597
  // before clearing runtime units. A SUMMARY file alone is no longer
@@ -606,12 +675,16 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
606
675
  // worktree cleanup) was never run — the survivor branch must be merged.
607
676
  // Applies to both worktree and branch isolation modes.
608
677
  let hasSurvivorBranch = false;
609
- if (state.activeMilestone &&
678
+ let survivorMilestoneId = state.activeMilestone?.id ?? null;
679
+ if (!survivorMilestoneId && state.phase === "complete") {
680
+ survivorMilestoneId = findUnmergedCompletedMilestone(base, getIsolationMode(base));
681
+ }
682
+ if (survivorMilestoneId &&
610
683
  (state.phase === "pre-planning" || state.phase === "complete") &&
611
684
  getIsolationMode(base) !== "none" &&
612
685
  !detectWorktreeName(base) &&
613
686
  !base.includes(`${pathSep}.gsd${pathSep}worktrees${pathSep}`)) {
614
- const milestoneBranch = `milestone/${state.activeMilestone.id}`;
687
+ const milestoneBranch = `milestone/${survivorMilestoneId}`;
615
688
  const { nativeBranchExists } = await import("./native-git-bridge.js");
616
689
  hasSurvivorBranch = nativeBranchExists(base, milestoneBranch);
617
690
  if (hasSurvivorBranch) {
@@ -645,7 +718,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
645
718
  // Re-evaluate via the helper — the discuss branch above may have cleared
646
719
  // hasSurvivorBranch after a successful promotion.
647
720
  if (decideSurvivorAction(hasSurvivorBranch, state.phase) === "finalize") {
648
- const mid = state.activeMilestone.id;
721
+ const mid = survivorMilestoneId;
649
722
  // Commit 68ef58a3c made `_mergeBranchMode` throw on wrong-branch
650
723
  // instead of returning false silently. Wrap the call so the throw is
651
724
  // converted into an error notify + clean bootstrap abort, not an
@@ -828,7 +901,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
828
901
  const integrationBranch = nativeDetectMainBranch(base);
829
902
  const branchToCheckout = resolveIsolationNoneBranchCheckout(currentBranch, integrationBranch, isolationMode, isRepo);
830
903
  if (branchToCheckout) {
831
- nativeCheckoutBranch(base, branchToCheckout);
904
+ checkoutBranchWithStashGuard(base, branchToCheckout, "isolation-none-recovery");
832
905
  logWarning("bootstrap", `Returned to "${branchToCheckout}" — HEAD was on stale milestone branch "${currentBranch}" (isolation: none does not use milestone branches).`);
833
906
  }
834
907
  }
@@ -18,9 +18,7 @@ import { join } from "node:path";
18
18
  import { resolveUokFlags } from "./uok/flags.js";
19
19
  import { UokGateRunner } from "./uok/gate-runner.js";
20
20
  import { verificationRetryKey } from "./auto/verification-retry-policy.js";
21
- function isInfraVerificationFailure(stderr) {
22
- return /\b(ENOENT|ENOTFOUND|ETIMEDOUT|ECONNRESET|EAI_AGAIN|spawn\s+\S+\s+ENOENT|command not found)\b/i.test(stderr);
23
- }
21
+ import { decideVerificationVerdict } from "./verification-verdict.js";
24
22
  /**
25
23
  * Post-unit guard for `validate-milestone` units (#4094).
26
24
  *
@@ -67,12 +65,25 @@ async function runValidateMilestonePostCheck(vctx, pauseAuto) {
67
65
  const { milestone: mid } = parseUnitId(s.currentUnit.id);
68
66
  if (!mid)
69
67
  return "continue";
68
+ const setToolFailureRetry = (message) => {
69
+ const retryKey = verificationRetryKey(s.currentUnit.type, s.currentUnit.id);
70
+ const attempt = (s.verificationRetryCount.get(retryKey) ?? 0) + 1;
71
+ s.verificationRetryCount.set(retryKey, attempt);
72
+ s.pendingVerificationRetry = {
73
+ unitId: s.currentUnit.id,
74
+ failureContext: message,
75
+ attempt,
76
+ };
77
+ return "retry";
78
+ };
70
79
  const validationFile = resolveMilestoneFile(s.basePath, mid, "VALIDATION");
71
- if (!validationFile)
72
- return "continue";
80
+ if (!validationFile) {
81
+ return setToolFailureRetry("You must call gsd_validate_milestone to persist the validation results. No VALIDATION.md was created.");
82
+ }
73
83
  const validationContent = await loadFile(validationFile);
74
- if (!validationContent)
75
- return "continue";
84
+ if (!validationContent) {
85
+ return setToolFailureRetry("You must call gsd_validate_milestone to persist the validation results. VALIDATION.md exists but is empty.");
86
+ }
76
87
  const verdict = extractVerdict(validationContent);
77
88
  if (verdict !== "needs-remediation") {
78
89
  await persistMilestoneValidationGate("pass", "none", `milestone validation verdict is ${verdict}; no remediation loop risk`, "", mid);
@@ -128,7 +139,7 @@ async function countIncompleteSlices(basePath, milestoneId) {
128
139
  /**
129
140
  * Run the verification gate for the current execute-task unit.
130
141
  * Returns:
131
- * - "continue" — gate passed (or no checks configured), proceed normally
142
+ * - "continue" — host-owned verification passed, proceed normally
132
143
  * - "retry" — gate failed with retries remaining, s.pendingVerificationRetry set for loop re-iteration
133
144
  * - "pause" — gate failed with retries exhausted, pauseAuto already called
134
145
  */
@@ -178,6 +189,10 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
178
189
  process.stderr.write(` [${w.severity}] ${w.name}: ${w.title}\n`);
179
190
  }
180
191
  }
192
+ const verdict = decideVerificationVerdict(s.currentUnit.type, result);
193
+ if (!verdict.passed) {
194
+ result.passed = false;
195
+ }
181
196
  if (uokFlags.gates) {
182
197
  const gateRunner = new UokGateRunner();
183
198
  gateRunner.register({
@@ -190,10 +205,12 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
190
205
  : "verification",
191
206
  rationale: result.passed
192
207
  ? "verification checks passed"
193
- : "verification checks failed",
208
+ : verdict.reason === "no-host-checks"
209
+ ? "no runnable host-owned verification checks discovered"
210
+ : "verification checks failed",
194
211
  findings: result.passed
195
212
  ? ""
196
- : formatFailureContext(result),
213
+ : verdict.failureContext || formatFailureContext(result),
197
214
  }),
198
215
  });
199
216
  await gateRunner.run("verification-gate", {
@@ -251,7 +268,11 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
251
268
  }
252
269
  else {
253
270
  const nextAttempt = attempt + 1;
254
- writeVerificationJSON(result, tasksDir, tid, s.currentUnit.id, nextAttempt, maxRetries);
271
+ const includeRetryMetadata = !result.passed &&
272
+ verdict.retryable &&
273
+ autoFixEnabled &&
274
+ nextAttempt <= maxRetries;
275
+ writeVerificationJSON(result, tasksDir, tid, s.currentUnit.id, includeRetryMetadata ? nextAttempt : undefined, includeRetryMetadata ? maxRetries : undefined);
255
276
  }
256
277
  }
257
278
  }
@@ -259,18 +280,6 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
259
280
  logWarning("engine", `verification-evidence write error: ${evidenceErr.message}`);
260
281
  }
261
282
  }
262
- const advisoryFailure = !result.passed &&
263
- (result.discoverySource === "package-json" ||
264
- result.checks.some((check) => isInfraVerificationFailure(check.stderr)));
265
- if (advisoryFailure) {
266
- s.verificationRetryCount.delete(retryKey);
267
- s.verificationRetryFailureHashes.delete(retryKey);
268
- s.pendingVerificationRetry = null;
269
- ctx.ui.notify(result.discoverySource === "package-json"
270
- ? "Verification failed in auto-discovered package.json checks — treating as advisory."
271
- : "Verification failed due to infrastructure/runtime environment issues — treating as advisory.", "warning");
272
- return "continue";
273
- }
274
283
  // ── Post-execution checks (run after main verification passes for execute-task units) ──
275
284
  let postExecChecks;
276
285
  let postExecBlockingFailure = false;
@@ -430,6 +439,15 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
430
439
  s.pendingVerificationRetry = null;
431
440
  return "continue";
432
441
  }
442
+ else if (verdict.reason === "no-host-checks") {
443
+ s.verificationRetryCount.delete(retryKey);
444
+ s.verificationRetryFailureHashes.delete(retryKey);
445
+ s.pendingVerificationRetry = null;
446
+ ctx.ui.notify("Verification gate FAILED — no runnable host-owned verification checks were discovered. Pausing for human review.", "error");
447
+ process.stderr.write(`verification-gate: ${verdict.failureContext}\n`);
448
+ await pauseAuto(ctx, pi);
449
+ return "pause";
450
+ }
433
451
  else if (postExecBlockingFailure) {
434
452
  // Post-execution failures are cross-task consistency issues — retrying the same task won't fix them.
435
453
  // Skip retry and pause immediately for human review.
@@ -445,7 +463,7 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
445
463
  s.verificationRetryCount.set(retryKey, nextAttempt);
446
464
  s.pendingVerificationRetry = {
447
465
  unitId: s.currentUnit.id,
448
- failureContext: formatFailureContext(result),
466
+ failureContext: verdict.failureContext || formatFailureContext(result),
449
467
  attempt: nextAttempt,
450
468
  };
451
469
  const failedCmds = result.checks
@@ -475,9 +493,10 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
475
493
  }
476
494
  }
477
495
  catch (err) {
478
- // Gate errors are non-fatal
479
496
  logWarning("engine", `verification-gate error: ${err.message}`);
480
- return "continue";
497
+ ctx.ui.notify(`Verification gate errored before producing an authoritative verdict: ${err.message}`, "error");
498
+ await pauseAuto(ctx, pi);
499
+ return "pause";
481
500
  }
482
501
  }
483
502
  /**
@@ -173,7 +173,18 @@ function gitPathspecForWorktreePath(basePath, targetPath) {
173
173
  let base = basePath;
174
174
  let target = targetPath;
175
175
  try {
176
- base = realpathSync.native(basePath);
176
+ base = execFileSync("git", ["rev-parse", "--show-toplevel"], {
177
+ cwd: basePath,
178
+ stdio: ["ignore", "pipe", "ignore"],
179
+ encoding: "utf-8",
180
+ }).trim() || basePath;
181
+ }
182
+ catch {
183
+ /* keep original */
184
+ void base;
185
+ }
186
+ try {
187
+ base = realpathSync.native(base);
177
188
  }
178
189
  catch {
179
190
  /* keep original */
@@ -191,6 +202,9 @@ function gitPathspecForWorktreePath(basePath, targetPath) {
191
202
  return null;
192
203
  return rel.replaceAll("\\", "/");
193
204
  }
205
+ export function _gitPathspecForWorktreePath(basePath, targetPath) {
206
+ return gitPathspecForWorktreePath(basePath, targetPath);
207
+ }
194
208
  function gitRemoteExists(basePath, remote) {
195
209
  try {
196
210
  execFileSync("git", ["remote", "get-url", remote], {
@@ -204,6 +218,52 @@ function gitRemoteExists(basePath, remote) {
204
218
  return false;
205
219
  }
206
220
  }
221
+ function findRegularMergeChangedPaths(basePath, milestoneBranch, mainBranch) {
222
+ const changedPaths = new Set();
223
+ let mergeLog = "";
224
+ try {
225
+ mergeLog = execFileSync("git", ["rev-list", "--merges", "--parents", mainBranch], {
226
+ cwd: basePath,
227
+ stdio: ["ignore", "pipe", "pipe"],
228
+ encoding: "utf-8",
229
+ }).trim();
230
+ }
231
+ catch (err) {
232
+ logWarning("worktree", `regular merge lookup failed: ${err instanceof Error ? err.message : String(err)}`);
233
+ return changedPaths;
234
+ }
235
+ for (const line of mergeLog.split("\n").filter(Boolean)) {
236
+ const [mergeCommit, firstParent, ...otherParents] = line.split(" ");
237
+ if (!mergeCommit || !firstParent || otherParents.length === 0)
238
+ continue;
239
+ const mergedMilestone = otherParents.some((parent) => {
240
+ try {
241
+ return nativeIsAncestor(basePath, milestoneBranch, parent);
242
+ }
243
+ catch {
244
+ return false;
245
+ }
246
+ });
247
+ if (!mergedMilestone)
248
+ continue;
249
+ try {
250
+ const output = execFileSync("git", ["diff", "--name-only", firstParent, mergeCommit], {
251
+ cwd: basePath,
252
+ stdio: ["ignore", "pipe", "pipe"],
253
+ encoding: "utf-8",
254
+ }).trim();
255
+ for (const path of output.split("\n").filter(Boolean)) {
256
+ if (!path.startsWith(".gsd/"))
257
+ changedPaths.add(path);
258
+ }
259
+ }
260
+ catch (err) {
261
+ logWarning("worktree", `regular merge diff lookup failed: ${err instanceof Error ? err.message : String(err)}`);
262
+ }
263
+ return changedPaths;
264
+ }
265
+ return changedPaths;
266
+ }
207
267
  function clearProjectRootStateFiles(basePath, milestoneId) {
208
268
  const gsdDir = gsdRoot(basePath);
209
269
  // Phase C pt 2: auto.lock removed from this list — the file is gone
@@ -810,7 +870,63 @@ export function enterBranchModeForMilestone(basePath, milestoneId) {
810
870
  reused: true,
811
871
  });
812
872
  }
813
- nativeCheckoutBranch(basePath, branch);
873
+ checkoutBranchWithStashGuard(basePath, branch, `enter-branch-mode:${milestoneId}`);
874
+ }
875
+ export function checkoutBranchWithStashGuard(basePath, branch, reason) {
876
+ let stashMarker = null;
877
+ let stashed = false;
878
+ const status = nativeWorkingTreeStatus(basePath).trim();
879
+ if (status.length > 0) {
880
+ stashMarker = `gsd-checkout-stash:${reason}:${process.pid}:${Date.now()}:${process.hrtime.bigint().toString(36)}`;
881
+ const stashListBefore = execFileSync("git", ["stash", "list"], {
882
+ cwd: basePath,
883
+ stdio: ["ignore", "pipe", "pipe"],
884
+ encoding: "utf-8",
885
+ });
886
+ execFileSync("git", ["stash", "push", "--include-untracked", "-m", `gsd: checkout stash [${stashMarker}]`], {
887
+ cwd: basePath,
888
+ stdio: ["ignore", "pipe", "pipe"],
889
+ encoding: "utf-8",
890
+ });
891
+ const stashListAfter = execFileSync("git", ["stash", "list"], {
892
+ cwd: basePath,
893
+ stdio: ["ignore", "pipe", "pipe"],
894
+ encoding: "utf-8",
895
+ });
896
+ stashed = stashListAfter !== stashListBefore;
897
+ }
898
+ // Checkout and stash-restore are split so we can distinguish two failure
899
+ // modes: (a) checkout failed → HEAD did not move, restore stash and rethrow;
900
+ // (b) checkout succeeded but stash pop failed → HEAD moved to `branch` but
901
+ // the working-tree changes remain in the stash list. We surface a distinct
902
+ // error in case (b) so callers don't assume the branch switch was rolled back.
903
+ try {
904
+ nativeCheckoutBranch(basePath, branch);
905
+ }
906
+ catch (checkoutErr) {
907
+ if (stashed) {
908
+ try {
909
+ popStashByRef(basePath, stashMarker);
910
+ }
911
+ catch (restoreErr) {
912
+ logWarning("worktree", `git stash pop failed during checkout restore: ${restoreErr instanceof Error ? restoreErr.message : String(restoreErr)}`);
913
+ }
914
+ }
915
+ throw checkoutErr;
916
+ }
917
+ if (stashed) {
918
+ try {
919
+ popStashByRef(basePath, stashMarker);
920
+ }
921
+ catch (popErr) {
922
+ const msg = popErr instanceof Error ? popErr.message : String(popErr);
923
+ const wrapped = new Error(`checkout to '${branch}' succeeded but stash restore failed; working tree changes remain in the stash list. Original error: ${msg}`);
924
+ const ref = popErr?.stashRef;
925
+ if (ref)
926
+ wrapped.stashRef = ref;
927
+ throw wrapped;
928
+ }
929
+ }
814
930
  }
815
931
  // ─── Public API ────────────────────────────────────────────────────────────
816
932
  /**
@@ -1482,6 +1598,56 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1482
1598
  });
1483
1599
  }
1484
1600
  }
1601
+ // Already regular-merged milestones can skip the squash path and proceed to cleanup (#5831).
1602
+ if (nativeIsAncestor(originalBasePath_, milestoneBranch, mainBranch)) {
1603
+ const codeChanges = nativeDiffNumstat(originalBasePath_, mainBranch, milestoneBranch).filter((entry) => !entry.path.startsWith(".gsd/"));
1604
+ if (codeChanges.length > 0) {
1605
+ const regularMergeChangedPaths = findRegularMergeChangedPaths(originalBasePath_, milestoneBranch, mainBranch);
1606
+ const unanchoredCodeChanges = codeChanges.filter((entry) => regularMergeChangedPaths.has(entry.path));
1607
+ if (unanchoredCodeChanges.length > 0) {
1608
+ process.chdir(previousCwd);
1609
+ throw new GSDError(GSD_GIT_ERROR, `Milestone branch "${milestoneBranch}" is reachable from "${mainBranch}" ` +
1610
+ `but has ${unanchoredCodeChanges.length} milestone-touched code file(s) not on current "${mainBranch}". ` +
1611
+ `Aborting worktree teardown to prevent data loss.`);
1612
+ }
1613
+ }
1614
+ debugLog("mergeMilestoneToMain", {
1615
+ action: "skip-squash-already-merged",
1616
+ milestoneId,
1617
+ milestoneBranch,
1618
+ mainBranch,
1619
+ });
1620
+ try {
1621
+ clearProjectRootStateFiles(originalBasePath_, milestoneId);
1622
+ }
1623
+ catch (err) {
1624
+ logWarning("worktree", `clearProjectRootStateFiles failed during already-merged cleanup: ${err instanceof Error ? err.message : String(err)}`);
1625
+ }
1626
+ try {
1627
+ removeWorktree(originalBasePath_, milestoneId, {
1628
+ branch: milestoneBranch,
1629
+ deleteBranch: false,
1630
+ });
1631
+ }
1632
+ catch (err) {
1633
+ logWarning("worktree", `worktree removal failed: ${err instanceof Error ? err.message : String(err)}`);
1634
+ }
1635
+ try {
1636
+ nativeBranchDelete(originalBasePath_, milestoneBranch);
1637
+ }
1638
+ catch (err) {
1639
+ logWarning("worktree", `git branch-delete failed: ${err instanceof Error ? err.message : String(err)}`);
1640
+ }
1641
+ setActiveWorkspace(null);
1642
+ nudgeGitBranchCache(previousCwd);
1643
+ try {
1644
+ process.chdir(originalBasePath_);
1645
+ }
1646
+ catch (err) {
1647
+ logWarning("worktree", `chdir to project root after already-merged cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
1648
+ }
1649
+ return { commitMessage, pushed: false, prCreated: false, codeFilesChanged: true };
1650
+ }
1485
1651
  // 7. Shelter queued milestone directories before the squash merge (#2505).
1486
1652
  // The milestone branch may contain copies of queued milestone dirs (via
1487
1653
  // copyPlanningArtifacts), so `git merge --squash` rejects when those same
@@ -1617,14 +1783,6 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1617
1783
  // report the dirty tree if it fails.
1618
1784
  logWarning("worktree", `git stash failed: ${err instanceof Error ? err.message : String(err)}`);
1619
1785
  }
1620
- if (needsDbCycle && dbPathToReopen) {
1621
- try {
1622
- openDatabase(dbPathToReopen);
1623
- }
1624
- catch (err) {
1625
- logWarning("worktree", `post-stash db reopen failed: ${err instanceof Error ? err.message : String(err)}`);
1626
- }
1627
- }
1628
1786
  // 7b. Clean up stale merge state before attempting squash merge (#2912).
1629
1787
  // A leftover MERGE_HEAD (from a previous failed merge, libgit2 native path,
1630
1788
  // or interrupted operation) causes `git merge --squash` to refuse with
@@ -1633,6 +1791,14 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1633
1791
  removeMergeStateFiles(originalBasePath_, "pre-merge");
1634
1792
  // 8. Squash merge — auto-resolve .gsd/ state file conflicts (#530)
1635
1793
  const mergeResult = nativeMergeSquash(originalBasePath_, milestoneBranch);
1794
+ if (needsDbCycle && dbPathToReopen) {
1795
+ try {
1796
+ openDatabase(dbPathToReopen);
1797
+ }
1798
+ catch (err) {
1799
+ logWarning("worktree", `post-merge db reopen failed: ${err instanceof Error ? err.message : String(err)}`);
1800
+ }
1801
+ }
1636
1802
  if (!mergeResult.success) {
1637
1803
  // Dirty working tree — the merge was rejected before it started (e.g.
1638
1804
  // untracked .gsd/ files left by syncStateToProjectRoot). Preserve the