gsd-pi 2.82.0-dev.725028083 → 2.82.0-dev.98ea09b1e

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 (355) hide show
  1. package/README.md +4 -3
  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/cmux/index.js +5 -0
  6. package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
  7. package/dist/resources/extensions/gsd/auto/loop.js +5 -5
  8. package/dist/resources/extensions/gsd/auto/orchestrator.js +124 -6
  9. package/dist/resources/extensions/gsd/auto/phases.js +8 -1
  10. package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
  11. package/dist/resources/extensions/gsd/auto-dispatch.js +13 -6
  12. package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
  13. package/dist/resources/extensions/gsd/auto-post-unit.js +233 -127
  14. package/dist/resources/extensions/gsd/auto-prompts.js +2 -2
  15. package/dist/resources/extensions/gsd/auto-recovery.js +31 -1
  16. package/dist/resources/extensions/gsd/auto-start.js +85 -12
  17. package/dist/resources/extensions/gsd/auto-verification.js +28 -22
  18. package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
  19. package/dist/resources/extensions/gsd/auto.js +158 -55
  20. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +4 -1
  21. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +9 -8
  22. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
  23. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -2
  24. package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
  25. package/dist/resources/extensions/gsd/commands/catalog.js +4 -1
  26. package/dist/resources/extensions/gsd/commands/handlers/core.js +37 -0
  27. package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
  28. package/dist/resources/extensions/gsd/crash-recovery.js +31 -5
  29. package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
  30. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
  31. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
  32. package/dist/resources/extensions/gsd/doctor.js +2 -28
  33. package/dist/resources/extensions/gsd/export-html.js +27 -425
  34. package/dist/resources/extensions/gsd/git-service.js +39 -1
  35. package/dist/resources/extensions/gsd/gsd-db.js +1 -0
  36. package/dist/resources/extensions/gsd/guided-flow.js +13 -6
  37. package/dist/resources/extensions/gsd/md-importer.js +1 -1
  38. package/dist/resources/extensions/gsd/migrate/command.js +5 -0
  39. package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
  40. package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
  41. package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
  42. package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
  43. package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
  44. package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
  45. package/dist/resources/extensions/gsd/native-git-bridge.js +48 -12
  46. package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
  47. package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
  48. package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
  49. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  50. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  51. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  52. package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
  53. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  54. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  55. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  56. package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
  57. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  58. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  59. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
  60. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
  61. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
  62. package/dist/resources/extensions/gsd/status-guards.js +4 -0
  63. package/dist/resources/extensions/gsd/templates/plan.md +8 -5
  64. package/dist/resources/extensions/gsd/templates/task-plan.md +4 -2
  65. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -8
  66. package/dist/resources/extensions/gsd/tools/complete-slice.js +6 -8
  67. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
  68. package/dist/resources/extensions/gsd/tools/plan-slice.js +89 -14
  69. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
  70. package/dist/resources/extensions/gsd/unit-context-manifest.js +32 -10
  71. package/dist/resources/extensions/gsd/validation.js +23 -1
  72. package/dist/resources/extensions/gsd/verification-gate.js +68 -7
  73. package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
  74. package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
  75. package/dist/resources/extensions/gsd/worktree-lifecycle.js +54 -10
  76. package/dist/resources/extensions/shared/html-shell.js +388 -0
  77. package/dist/resources/extensions/subagent/index.js +448 -78
  78. package/dist/resources/extensions/subagent/launch.js +77 -0
  79. package/dist/resources/extensions/subagent/run-store.js +148 -0
  80. package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
  81. package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
  82. package/dist/resources/extensions/visual-brief/index.js +5 -0
  83. package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
  84. package/dist/resources/extensions/visual-brief/prompts.js +140 -0
  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 +14 -14
  88. package/dist/web/standalone/.next/build-manifest.json +3 -3
  89. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  90. package/dist/web/standalone/.next/react-loadable-manifest.json +3 -3
  91. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  101. package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -7
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -5
  108. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
  111. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/index.html +1 -1
  113. package/dist/web/standalone/.next/server/app/index.rsc +4 -7
  114. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -7
  116. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -5
  118. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
  119. package/dist/web/standalone/.next/server/app/page.js +2 -2
  120. package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
  121. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  123. package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
  124. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  128. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  129. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  130. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  131. package/dist/web/standalone/.next/static/chunks/2973.33f26573894b6153.js +2 -0
  132. package/dist/web/standalone/.next/static/chunks/{8359.e059d86b255fce1c.js → 8359.7eb3bb8f8ecf4c01.js} +2 -2
  133. package/dist/web/standalone/.next/static/chunks/app/layout-8c10ec293ae0f1d5.js +1 -0
  134. package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-9a4db269f9ed63ad.js} +1 -1
  135. package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
  136. package/package.json +4 -4
  137. package/packages/contracts/dist/rpc.test.js +7 -0
  138. package/packages/contracts/dist/rpc.test.js.map +1 -1
  139. package/packages/contracts/dist/workflow.d.ts +21 -0
  140. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  141. package/packages/contracts/dist/workflow.js +24 -0
  142. package/packages/contracts/dist/workflow.js.map +1 -1
  143. package/packages/contracts/src/rpc.test.ts +8 -0
  144. package/packages/contracts/src/workflow.ts +24 -0
  145. package/packages/mcp-server/README.md +13 -4
  146. package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
  147. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  148. package/packages/mcp-server/dist/workflow-tools.js +80 -0
  149. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  150. package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
  151. package/packages/mcp-server/src/workflow-tools.ts +168 -0
  152. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  153. package/packages/native/tsconfig.json +2 -1
  154. package/packages/native/tsconfig.tsbuildinfo +1 -1
  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/openai-codex-responses.test.ts +63 -0
  171. package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
  172. package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
  173. package/packages/pi-ai/src/providers/simple-options.ts +5 -6
  174. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  175. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
  176. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
  177. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
  178. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
  179. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
  180. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  181. package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
  182. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
  183. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  184. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  185. package/packages/pi-tui/dist/tui.js +5 -0
  186. package/packages/pi-tui/dist/tui.js.map +1 -1
  187. package/packages/pi-tui/src/tui.ts +6 -0
  188. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  189. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  190. package/src/resources/GSD-WORKFLOW.md +10 -1
  191. package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
  192. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
  193. package/src/resources/extensions/cmux/index.ts +6 -0
  194. package/src/resources/extensions/gsd/auto/contracts.ts +59 -16
  195. package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
  196. package/src/resources/extensions/gsd/auto/loop.ts +8 -5
  197. package/src/resources/extensions/gsd/auto/orchestrator.ts +129 -6
  198. package/src/resources/extensions/gsd/auto/phases.ts +7 -1
  199. package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
  200. package/src/resources/extensions/gsd/auto-dispatch.ts +14 -6
  201. package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
  202. package/src/resources/extensions/gsd/auto-post-unit.ts +266 -139
  203. package/src/resources/extensions/gsd/auto-prompts.ts +2 -2
  204. package/src/resources/extensions/gsd/auto-recovery.ts +29 -0
  205. package/src/resources/extensions/gsd/auto-start.ts +92 -9
  206. package/src/resources/extensions/gsd/auto-verification.ts +36 -34
  207. package/src/resources/extensions/gsd/auto-worktree.ts +119 -1
  208. package/src/resources/extensions/gsd/auto.ts +167 -53
  209. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +6 -1
  210. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +9 -8
  211. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
  212. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +19 -3
  213. package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
  214. package/src/resources/extensions/gsd/commands/catalog.ts +4 -1
  215. package/src/resources/extensions/gsd/commands/handlers/core.ts +40 -0
  216. package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
  217. package/src/resources/extensions/gsd/crash-recovery.ts +30 -4
  218. package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
  219. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
  220. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
  221. package/src/resources/extensions/gsd/doctor.ts +2 -27
  222. package/src/resources/extensions/gsd/export-html.ts +27 -427
  223. package/src/resources/extensions/gsd/git-service.ts +45 -1
  224. package/src/resources/extensions/gsd/gsd-db.ts +3 -0
  225. package/src/resources/extensions/gsd/guided-flow.ts +14 -7
  226. package/src/resources/extensions/gsd/md-importer.ts +1 -1
  227. package/src/resources/extensions/gsd/migrate/command.ts +5 -0
  228. package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
  229. package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
  230. package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
  231. package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
  232. package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
  233. package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
  234. package/src/resources/extensions/gsd/native-git-bridge.ts +54 -12
  235. package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
  236. package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
  237. package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
  238. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  239. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  240. package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  241. package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
  242. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  243. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  244. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  245. package/src/resources/extensions/gsd/prompts/queue.md +4 -4
  246. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  247. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  248. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
  249. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
  250. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
  251. package/src/resources/extensions/gsd/status-guards.ts +5 -0
  252. package/src/resources/extensions/gsd/templates/plan.md +8 -5
  253. package/src/resources/extensions/gsd/templates/task-plan.md +4 -2
  254. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
  255. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +54 -0
  256. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +487 -4
  257. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +12 -11
  258. package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +12 -1
  259. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +15 -1
  260. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +4 -4
  261. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
  262. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
  263. package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
  264. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
  265. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
  266. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
  267. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
  268. package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
  269. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +43 -2
  270. package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
  271. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +59 -2
  272. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +39 -0
  273. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
  274. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +38 -0
  275. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
  276. package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
  277. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
  278. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +6 -6
  279. package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
  280. package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
  281. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
  282. package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
  283. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +103 -1
  284. package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
  285. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
  286. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
  287. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
  288. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
  289. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
  290. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +63 -2
  291. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
  292. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
  293. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
  294. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  295. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +225 -1
  296. package/src/resources/extensions/gsd/tests/plan-task.test.ts +17 -0
  297. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  298. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +86 -0
  299. package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
  300. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +53 -0
  301. package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
  302. package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +46 -2
  303. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
  304. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +31 -1
  305. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
  306. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
  307. package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
  308. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
  309. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +86 -7
  310. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
  311. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
  312. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +1 -1
  313. package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
  314. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1 -1
  315. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
  316. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
  317. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +25 -0
  318. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +54 -0
  319. package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
  320. package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
  321. package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
  322. package/src/resources/extensions/gsd/tools/plan-slice.ts +98 -12
  323. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
  324. package/src/resources/extensions/gsd/types.ts +1 -1
  325. package/src/resources/extensions/gsd/unit-context-manifest.ts +47 -11
  326. package/src/resources/extensions/gsd/validation.ts +23 -1
  327. package/src/resources/extensions/gsd/verification-gate.ts +78 -6
  328. package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
  329. package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
  330. package/src/resources/extensions/gsd/worktree-lifecycle.ts +61 -10
  331. package/src/resources/extensions/shared/html-shell.ts +412 -0
  332. package/src/resources/extensions/subagent/index.ts +567 -103
  333. package/src/resources/extensions/subagent/launch.ts +131 -0
  334. package/src/resources/extensions/subagent/run-store.ts +218 -0
  335. package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
  336. package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
  337. package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
  338. package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
  339. package/src/resources/extensions/visual-brief/index.ts +8 -0
  340. package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
  341. package/src/resources/extensions/visual-brief/prompts.ts +183 -0
  342. package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
  343. package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
  344. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
  345. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
  346. package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
  347. package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
  348. package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  349. package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  350. package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
  351. package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  352. package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
  353. package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  354. /package/dist/web/standalone/.next/static/{KDRTXR-22LPCsa80X9dey → euQ0CLP_v8V4e76Tu3odJ}/_buildManifest.js +0 -0
  355. /package/dist/web/standalone/.next/static/{KDRTXR-22LPCsa80X9dey → euQ0CLP_v8V4e76Tu3odJ}/_ssgManifest.js +0 -0
@@ -44,6 +44,7 @@ import {
44
44
  nativeDetectMainBranch,
45
45
  nativeCheckoutBranch,
46
46
  nativeBranchList,
47
+ nativeBranchExists,
47
48
  nativeBranchListMerged,
48
49
  nativeBranchDelete,
49
50
  nativeWorktreeRemove,
@@ -64,7 +65,7 @@ import { initRoutingHistory } from "./routing-history.js";
64
65
  import { restoreHookState, resetHookState } from "./post-unit-hooks.js";
65
66
  import { resetProactiveHealing, setLevelChangeCallback } from "./doctor-proactive.js";
66
67
  import { snapshotSkills } from "./skill-discovery.js";
67
- import { isDbAvailable, getMilestone, openDatabase, getDbStatus } from "./gsd-db.js";
68
+ import { isDbAvailable, getMilestone, getAllMilestones, openDatabase, getDbStatus } from "./gsd-db.js";
68
69
  import { isClosedStatus } from "./status-guards.js";
69
70
  import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
70
71
  import { auditOrphanedPreflightStashes } from "./orphan-stash-audit.js";
@@ -101,6 +102,7 @@ import { getSessionModelOverride } from "./session-model-override.js";
101
102
  export interface BootstrapDeps {
102
103
  shouldUseWorktreeIsolation: (basePath?: string) => boolean;
103
104
  registerSigtermHandler: (basePath: string) => void;
105
+ registerAutoWorkerForSession: (basePath: string) => void;
104
106
  lockBase: () => string;
105
107
  buildLifecycle: () => WorktreeLifecycle;
106
108
  }
@@ -202,9 +204,15 @@ export function decideSurvivorAction(
202
204
  export function auditOrphanedMilestoneBranches(
203
205
  basePath: string,
204
206
  isolationMode: "worktree" | "branch" | "none",
207
+ gitDeps: {
208
+ branchList?: typeof nativeBranchList;
209
+ branchExists?: typeof nativeBranchExists;
210
+ } = {},
205
211
  ): { recovered: string[]; warnings: string[] } {
206
212
  const recovered: string[] = [];
207
213
  const warnings: string[] = [];
214
+ const branchList = gitDeps.branchList ?? nativeBranchList;
215
+ const branchExists = gitDeps.branchExists ?? nativeBranchExists;
208
216
 
209
217
  // Skip in none mode — no milestone branches are created
210
218
  if (isolationMode === "none") return { recovered, warnings };
@@ -213,15 +221,16 @@ export function auditOrphanedMilestoneBranches(
213
221
  if (!isDbAvailable()) return { recovered, warnings };
214
222
 
215
223
  let milestoneBranches: string[];
224
+ let milestoneBranchListAvailable = true;
216
225
  try {
217
- milestoneBranches = nativeBranchList(basePath, "milestone/*");
226
+ milestoneBranches = branchList(basePath, "milestone/*");
218
227
  } catch {
219
- // git branch list failed — skip audit
220
- return { recovered, warnings };
228
+ milestoneBranchListAvailable = false;
229
+ // git branch list failed — fall through with an empty branch set so the
230
+ // branch-less orphan pass can still run after per-milestone verification.
231
+ milestoneBranches = [];
221
232
  }
222
233
 
223
- if (milestoneBranches.length === 0) return { recovered, warnings };
224
-
225
234
  // Detect main branch for merge-check
226
235
  let mainBranch: string;
227
236
  try {
@@ -354,6 +363,74 @@ export function auditOrphanedMilestoneBranches(
354
363
  }
355
364
  }
356
365
 
366
+ // Second pass (#5879): catch worktree directories stranded by a previous
367
+ // audit that deleted the milestone/* branch but failed to remove the
368
+ // directory (or the dir was orphaned by a separate path entirely, e.g.
369
+ // postflight-stash-restore-failed during closeout). The branch-keyed loop
370
+ // above is invisible to these cases — `nativeBranchList` returns nothing
371
+ // for the milestone, so the dir-cleanup block at line ~310 is never
372
+ // reached.
373
+ //
374
+ // Keyed on milestones whose DB status is `complete`. We do not iterate
375
+ // over arbitrary directories under .gsd/worktrees/ to avoid touching
376
+ // dirs that belong to an in-progress milestone whose branch was deleted
377
+ // separately — those are handled by the in-progress orphan path above
378
+ // when the branch is present, and by `/gsd doctor` when it is not.
379
+ const seenMilestoneIds = new Set(
380
+ milestoneBranches.map((branch) => branch.replace(/^milestone\//, "")),
381
+ );
382
+ let completedMilestones: readonly { id: string; status: string }[] = [];
383
+ try {
384
+ completedMilestones = getAllMilestones();
385
+ } catch {
386
+ // DB read failure — skip the second pass; the first pass is still useful.
387
+ completedMilestones = [];
388
+ }
389
+ for (const m of completedMilestones) {
390
+ if (m.status !== "complete") continue;
391
+ if (seenMilestoneIds.has(m.id)) continue; // already processed in the branch loop
392
+ if (!milestoneBranchListAvailable) {
393
+ try {
394
+ if (branchExists(basePath, `milestone/${m.id}`)) continue;
395
+ } catch (err) {
396
+ warnings.push(
397
+ `Could not verify whether milestone/${m.id} still exists; skipping branch-less worktree cleanup for safety: ${err instanceof Error ? err.message : String(err)}`,
398
+ );
399
+ continue;
400
+ }
401
+ }
402
+ const wtDir = getWorktreeDir(basePath, m.id);
403
+ if (!existsSync(wtDir)) continue;
404
+ if (!isInsideWorktreesDir(basePath, wtDir)) {
405
+ warnings.push(
406
+ `Orphaned worktree directory for ${m.id} is outside .gsd/worktrees/ — skipping removal for safety.`,
407
+ );
408
+ continue;
409
+ }
410
+ // Try `git worktree remove` first in case the dir is still registered
411
+ // (defensive — usually it is not when we reach this branch-less pass).
412
+ try {
413
+ nativeWorktreeRemove(basePath, wtDir, true);
414
+ } catch (e) {
415
+ logWarning(
416
+ "engine",
417
+ `worktree remove failed (expected for branch-less orphans): ${e instanceof Error ? e.message : String(e)}`,
418
+ );
419
+ }
420
+ if (existsSync(wtDir)) {
421
+ try {
422
+ rmSync(wtDir, { recursive: true, force: true });
423
+ recovered.push(`Removed orphaned worktree directory for ${m.id} (branch already deleted).`);
424
+ } catch (err) {
425
+ warnings.push(
426
+ `Failed to remove orphaned worktree directory for ${m.id}: ${err instanceof Error ? err.message : String(err)}`,
427
+ );
428
+ }
429
+ } else {
430
+ recovered.push(`Removed orphaned worktree directory for ${m.id} (branch already deleted).`);
431
+ }
432
+ }
433
+
357
434
  return { recovered, warnings };
358
435
  }
359
436
 
@@ -533,6 +610,7 @@ export async function bootstrapAutoSession(
533
610
  const {
534
611
  shouldUseWorktreeIsolation,
535
612
  registerSigtermHandler,
613
+ registerAutoWorkerForSession,
536
614
  lockBase,
537
615
  buildLifecycle,
538
616
  } = deps;
@@ -722,6 +800,7 @@ export async function bootstrapAutoSession(
722
800
  // consult DB status and avoid clearing runtime units for milestones that
723
801
  // only have a failure-path SUMMARY on disk (#4663).
724
802
  await openProjectDbIfPresent(base);
803
+ registerAutoWorkerForSession(base);
725
804
 
726
805
  // Clean stale runtime unit files for completed milestones (#887).
727
806
  // DB-authoritative: when DB is available, require DB status to be closed
@@ -818,14 +897,18 @@ export async function bootstrapAutoSession(
818
897
  // worktree cleanup) was never run — the survivor branch must be merged.
819
898
  // Applies to both worktree and branch isolation modes.
820
899
  let hasSurvivorBranch = false;
900
+ let survivorMilestoneId = state.activeMilestone?.id ?? null;
901
+ if (!survivorMilestoneId && state.phase === "complete") {
902
+ survivorMilestoneId = findUnmergedCompletedMilestone(base, getIsolationMode(base));
903
+ }
821
904
  if (
822
- state.activeMilestone &&
905
+ survivorMilestoneId &&
823
906
  (state.phase === "pre-planning" || state.phase === "complete") &&
824
907
  getIsolationMode(base) !== "none" &&
825
908
  !detectWorktreeName(base) &&
826
909
  !base.includes(`${pathSep}.gsd${pathSep}worktrees${pathSep}`)
827
910
  ) {
828
- const milestoneBranch = `milestone/${state.activeMilestone.id}`;
911
+ const milestoneBranch = `milestone/${survivorMilestoneId}`;
829
912
  const { nativeBranchExists } = await import("./native-git-bridge.js");
830
913
  hasSurvivorBranch = nativeBranchExists(base, milestoneBranch);
831
914
  if (hasSurvivorBranch) {
@@ -869,7 +952,7 @@ export async function bootstrapAutoSession(
869
952
  // Re-evaluate via the helper — the discuss branch above may have cleared
870
953
  // hasSurvivorBranch after a successful promotion.
871
954
  if (decideSurvivorAction(hasSurvivorBranch, state.phase) === "finalize") {
872
- const mid = state.activeMilestone!.id;
955
+ const mid = survivorMilestoneId!;
873
956
  // Commit 68ef58a3c made `_mergeBranchMode` throw on wrong-branch
874
957
  // instead of returning false silently. Wrap the call so the throw is
875
958
  // converted into an error notify + clean bootstrap abort, not an
@@ -40,6 +40,7 @@ import { join } from "node:path";
40
40
  import { resolveUokFlags } from "./uok/flags.js";
41
41
  import { UokGateRunner } from "./uok/gate-runner.js";
42
42
  import { verificationRetryKey } from "./auto/verification-retry-policy.js";
43
+ import { decideVerificationVerdict } from "./verification-verdict.js";
43
44
 
44
45
  export interface VerificationContext {
45
46
  s: AutoSession;
@@ -49,12 +50,6 @@ export interface VerificationContext {
49
50
 
50
51
  export type VerificationResult = "continue" | "retry" | "pause";
51
52
 
52
- function isInfraVerificationFailure(stderr: string): boolean {
53
- return /\b(ENOENT|ENOTFOUND|ETIMEDOUT|ECONNRESET|EAI_AGAIN|spawn\s+\S+\s+ENOENT|command not found)\b/i.test(
54
- stderr,
55
- );
56
- }
57
-
58
53
  /**
59
54
  * Post-unit guard for `validate-milestone` units (#4094).
60
55
  *
@@ -196,7 +191,7 @@ async function countIncompleteSlices(basePath: string, milestoneId: string): Pro
196
191
  /**
197
192
  * Run the verification gate for the current execute-task unit.
198
193
  * Returns:
199
- * - "continue" — gate passed (or no checks configured), proceed normally
194
+ * - "continue" — host-owned verification passed, proceed normally
200
195
  * - "retry" — gate failed with retries remaining, s.pendingVerificationRetry set for loop re-iteration
201
196
  * - "pause" — gate failed with retries exhausted, pauseAuto already called
202
197
  */
@@ -260,6 +255,11 @@ export async function runPostUnitVerification(
260
255
  }
261
256
  }
262
257
 
258
+ const verdict = decideVerificationVerdict(s.currentUnit.type, result);
259
+ if (!verdict.passed) {
260
+ result.passed = false;
261
+ }
262
+
263
263
  if (uokFlags.gates) {
264
264
  const gateRunner = new UokGateRunner();
265
265
  gateRunner.register({
@@ -272,10 +272,12 @@ export async function runPostUnitVerification(
272
272
  : "verification",
273
273
  rationale: result.passed
274
274
  ? "verification checks passed"
275
- : "verification checks failed",
275
+ : verdict.reason === "no-host-checks"
276
+ ? "no runnable host-owned verification checks discovered"
277
+ : "verification checks failed",
276
278
  findings: result.passed
277
279
  ? ""
278
- : formatFailureContext(result),
280
+ : verdict.failureContext || formatFailureContext(result),
279
281
  }),
280
282
  });
281
283
 
@@ -343,13 +345,18 @@ export async function runPostUnitVerification(
343
345
  writeVerificationJSON(result, tasksDir, tid, s.currentUnit.id);
344
346
  } else {
345
347
  const nextAttempt = attempt + 1;
348
+ const includeRetryMetadata =
349
+ !result.passed &&
350
+ verdict.retryable &&
351
+ autoFixEnabled &&
352
+ nextAttempt <= maxRetries;
346
353
  writeVerificationJSON(
347
354
  result,
348
355
  tasksDir,
349
356
  tid,
350
357
  s.currentUnit.id,
351
- nextAttempt,
352
- maxRetries,
358
+ includeRetryMetadata ? nextAttempt : undefined,
359
+ includeRetryMetadata ? maxRetries : undefined,
353
360
  );
354
361
  }
355
362
  }
@@ -358,26 +365,6 @@ export async function runPostUnitVerification(
358
365
  }
359
366
  }
360
367
 
361
- const advisoryFailure =
362
- !result.passed &&
363
- (result.discoverySource === "package-json" ||
364
- result.checks.some((check) =>
365
- isInfraVerificationFailure(check.stderr),
366
- ));
367
-
368
- if (advisoryFailure) {
369
- s.verificationRetryCount.delete(retryKey);
370
- s.verificationRetryFailureHashes.delete(retryKey);
371
- s.pendingVerificationRetry = null;
372
- ctx.ui.notify(
373
- result.discoverySource === "package-json"
374
- ? "Verification failed in auto-discovered package.json checks — treating as advisory."
375
- : "Verification failed due to infrastructure/runtime environment issues — treating as advisory.",
376
- "warning",
377
- );
378
- return "continue";
379
- }
380
-
381
368
  // ── Post-execution checks (run after main verification passes for execute-task units) ──
382
369
  let postExecChecks: PostExecutionCheckJSON[] | undefined;
383
370
  let postExecBlockingFailure = false;
@@ -572,6 +559,17 @@ export async function runPostUnitVerification(
572
559
  s.verificationRetryFailureHashes.delete(retryKey);
573
560
  s.pendingVerificationRetry = null;
574
561
  return "continue";
562
+ } else if (verdict.reason === "no-host-checks") {
563
+ s.verificationRetryCount.delete(retryKey);
564
+ s.verificationRetryFailureHashes.delete(retryKey);
565
+ s.pendingVerificationRetry = null;
566
+ ctx.ui.notify(
567
+ "Verification gate FAILED — no runnable host-owned verification checks were discovered. Pausing for human review.",
568
+ "error",
569
+ );
570
+ process.stderr.write(`verification-gate: ${verdict.failureContext}\n`);
571
+ await pauseAuto(ctx, pi);
572
+ return "pause";
575
573
  } else if (postExecBlockingFailure) {
576
574
  // Post-execution failures are cross-task consistency issues — retrying the same task won't fix them.
577
575
  // Skip retry and pause immediately for human review.
@@ -589,7 +587,7 @@ export async function runPostUnitVerification(
589
587
  s.verificationRetryCount.set(retryKey, nextAttempt);
590
588
  s.pendingVerificationRetry = {
591
589
  unitId: s.currentUnit.id,
592
- failureContext: formatFailureContext(result),
590
+ failureContext: verdict.failureContext || formatFailureContext(result),
593
591
  attempt: nextAttempt,
594
592
  };
595
593
  const failedCmds = result.checks
@@ -623,9 +621,13 @@ export async function runPostUnitVerification(
623
621
  return "pause";
624
622
  }
625
623
  } catch (err) {
626
- // Gate errors are non-fatal
627
624
  logWarning("engine", `verification-gate error: ${(err as Error).message}`);
628
- return "continue";
625
+ ctx.ui.notify(
626
+ `Verification gate errored before producing an authoritative verdict: ${(err as Error).message}`,
627
+ "error",
628
+ );
629
+ await pauseAuto(ctx, pi);
630
+ return "pause";
629
631
  }
630
632
  }
631
633
 
@@ -252,7 +252,17 @@ function gitPathspecForWorktreePath(basePath: string, targetPath: string): strin
252
252
  let base = basePath;
253
253
  let target = targetPath;
254
254
  try {
255
- base = realpathSync.native(basePath);
255
+ base = execFileSync("git", ["rev-parse", "--show-toplevel"], {
256
+ cwd: basePath,
257
+ stdio: ["ignore", "pipe", "ignore"],
258
+ encoding: "utf-8",
259
+ }).trim() || basePath;
260
+ } catch {
261
+ /* keep original */
262
+ void base;
263
+ }
264
+ try {
265
+ base = realpathSync.native(base);
256
266
  } catch {
257
267
  /* keep original */
258
268
  void base;
@@ -269,6 +279,10 @@ function gitPathspecForWorktreePath(basePath: string, targetPath: string): strin
269
279
  return rel.replaceAll("\\", "/");
270
280
  }
271
281
 
282
+ export function _gitPathspecForWorktreePath(basePath: string, targetPath: string): string | null {
283
+ return gitPathspecForWorktreePath(basePath, targetPath);
284
+ }
285
+
272
286
  function gitRemoteExists(basePath: string, remote: string): boolean {
273
287
  try {
274
288
  execFileSync("git", ["remote", "get-url", remote], {
@@ -282,6 +296,50 @@ function gitRemoteExists(basePath: string, remote: string): boolean {
282
296
  }
283
297
  }
284
298
 
299
+ function findRegularMergeChangedPaths(basePath: string, milestoneBranch: string, mainBranch: string): Set<string> {
300
+ const changedPaths = new Set<string>();
301
+ let mergeLog = "";
302
+ try {
303
+ mergeLog = execFileSync("git", ["rev-list", "--merges", "--parents", mainBranch], {
304
+ cwd: basePath,
305
+ stdio: ["ignore", "pipe", "pipe"],
306
+ encoding: "utf-8",
307
+ }).trim();
308
+ } catch (err) {
309
+ logWarning("worktree", `regular merge lookup failed: ${err instanceof Error ? err.message : String(err)}`);
310
+ return changedPaths;
311
+ }
312
+
313
+ for (const line of mergeLog.split("\n").filter(Boolean)) {
314
+ const [mergeCommit, firstParent, ...otherParents] = line.split(" ");
315
+ if (!mergeCommit || !firstParent || otherParents.length === 0) continue;
316
+ const mergedMilestone = otherParents.some((parent) => {
317
+ try {
318
+ return nativeIsAncestor(basePath, milestoneBranch, parent);
319
+ } catch {
320
+ return false;
321
+ }
322
+ });
323
+ if (!mergedMilestone) continue;
324
+
325
+ try {
326
+ const output = execFileSync("git", ["diff", "--name-only", firstParent, mergeCommit], {
327
+ cwd: basePath,
328
+ stdio: ["ignore", "pipe", "pipe"],
329
+ encoding: "utf-8",
330
+ }).trim();
331
+ for (const path of output.split("\n").filter(Boolean)) {
332
+ if (!path.startsWith(".gsd/")) changedPaths.add(path);
333
+ }
334
+ } catch (err) {
335
+ logWarning("worktree", `regular merge diff lookup failed: ${err instanceof Error ? err.message : String(err)}`);
336
+ }
337
+ return changedPaths;
338
+ }
339
+
340
+ return changedPaths;
341
+ }
342
+
285
343
  function clearProjectRootStateFiles(basePath: string, milestoneId: string): void {
286
344
  const gsdDir = gsdRoot(basePath);
287
345
  // Phase C pt 2: auto.lock removed from this list — the file is gone
@@ -1739,6 +1797,66 @@ export function mergeMilestoneToMain(
1739
1797
  }
1740
1798
  }
1741
1799
 
1800
+ // Already regular-merged milestones can skip the squash path and proceed to cleanup (#5831).
1801
+ if (nativeIsAncestor(originalBasePath_, milestoneBranch, mainBranch)) {
1802
+ const codeChanges = nativeDiffNumstat(
1803
+ originalBasePath_,
1804
+ mainBranch,
1805
+ milestoneBranch,
1806
+ ).filter((entry) => !entry.path.startsWith(".gsd/"));
1807
+ if (codeChanges.length > 0) {
1808
+ const regularMergeChangedPaths = findRegularMergeChangedPaths(
1809
+ originalBasePath_,
1810
+ milestoneBranch,
1811
+ mainBranch,
1812
+ );
1813
+ const unanchoredCodeChanges = codeChanges.filter((entry) =>
1814
+ regularMergeChangedPaths.has(entry.path)
1815
+ );
1816
+ if (unanchoredCodeChanges.length > 0) {
1817
+ process.chdir(previousCwd);
1818
+ throw new GSDError(
1819
+ GSD_GIT_ERROR,
1820
+ `Milestone branch "${milestoneBranch}" is reachable from "${mainBranch}" ` +
1821
+ `but has ${unanchoredCodeChanges.length} milestone-touched code file(s) not on current "${mainBranch}". ` +
1822
+ `Aborting worktree teardown to prevent data loss.`,
1823
+ );
1824
+ }
1825
+ }
1826
+ debugLog("mergeMilestoneToMain", {
1827
+ action: "skip-squash-already-merged",
1828
+ milestoneId,
1829
+ milestoneBranch,
1830
+ mainBranch,
1831
+ });
1832
+ try {
1833
+ clearProjectRootStateFiles(originalBasePath_, milestoneId);
1834
+ } catch (err) {
1835
+ logWarning("worktree", `clearProjectRootStateFiles failed during already-merged cleanup: ${err instanceof Error ? err.message : String(err)}`);
1836
+ }
1837
+ try {
1838
+ removeWorktree(originalBasePath_, milestoneId, {
1839
+ branch: milestoneBranch,
1840
+ deleteBranch: false,
1841
+ });
1842
+ } catch (err) {
1843
+ logWarning("worktree", `worktree removal failed: ${err instanceof Error ? err.message : String(err)}`);
1844
+ }
1845
+ try {
1846
+ nativeBranchDelete(originalBasePath_, milestoneBranch);
1847
+ } catch (err) {
1848
+ logWarning("worktree", `git branch-delete failed: ${err instanceof Error ? err.message : String(err)}`);
1849
+ }
1850
+ setActiveWorkspace(null);
1851
+ nudgeGitBranchCache(previousCwd);
1852
+ try {
1853
+ process.chdir(originalBasePath_);
1854
+ } catch (err) {
1855
+ logWarning("worktree", `chdir to project root after already-merged cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
1856
+ }
1857
+ return { commitMessage, pushed: false, prCreated: false, codeFilesChanged: true };
1858
+ }
1859
+
1742
1860
  // 7. Shelter queued milestone directories before the squash merge (#2505).
1743
1861
  // The milestone branch may contain copies of queued milestone dirs (via
1744
1862
  // copyPlanningArtifacts), so `git merge --squash` rejects when those same