gsd-pi 2.80.0-dev.3065f7bfa → 2.80.0-dev.488219eb6

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 (376) hide show
  1. package/dist/claude-cli-check.d.ts +30 -0
  2. package/dist/claude-cli-check.js +18 -7
  3. package/dist/cli.js +0 -19
  4. package/dist/headless-query.d.ts +10 -0
  5. package/dist/headless-query.js +6 -4
  6. package/dist/loader-entrypoint.d.ts +8 -0
  7. package/dist/loader-entrypoint.js +27 -0
  8. package/dist/loader.js +2 -11
  9. package/dist/mcp-server.d.ts +1 -0
  10. package/dist/mcp-server.js +6 -3
  11. package/dist/resources/.managed-resources-content-hash +1 -1
  12. package/dist/resources/extensions/claude-code-cli/readiness.js +18 -7
  13. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +29 -0
  14. package/dist/resources/extensions/github-sync/sync.js +4 -1
  15. package/dist/resources/extensions/gsd/auto/loop.js +71 -8
  16. package/dist/resources/extensions/gsd/auto/phases.js +32 -8
  17. package/dist/resources/extensions/gsd/auto/resolve.js +12 -0
  18. package/dist/resources/extensions/gsd/auto/run-unit.js +3 -1
  19. package/dist/resources/extensions/gsd/auto/workflow-dispatch-claim.js +33 -1
  20. package/dist/resources/extensions/gsd/auto/workflow-worker-heartbeat.js +9 -1
  21. package/dist/resources/extensions/gsd/auto-post-unit.js +81 -76
  22. package/dist/resources/extensions/gsd/auto-start.js +41 -6
  23. package/dist/resources/extensions/gsd/auto-worktree.js +98 -80
  24. package/dist/resources/extensions/gsd/auto.js +84 -29
  25. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +62 -13
  26. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +20 -26
  27. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +29 -12
  28. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +6 -9
  29. package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +4 -7
  30. package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +6 -10
  31. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +5 -9
  32. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +1 -1
  33. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +60 -26
  34. package/dist/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.js +4 -0
  35. package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -2
  36. package/dist/resources/extensions/gsd/commands-config.js +1 -1
  37. package/dist/resources/extensions/gsd/commands-eval-review.js +2 -2
  38. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
  39. package/dist/resources/extensions/gsd/db/unit-dispatches.js +53 -0
  40. package/dist/resources/extensions/gsd/git-service.js +37 -1
  41. package/dist/resources/extensions/gsd/guided-flow.js +14 -4
  42. package/dist/resources/extensions/gsd/init-wizard.js +4 -1
  43. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -4
  44. package/dist/resources/extensions/gsd/slice-cadence.js +45 -2
  45. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +15 -9
  46. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -7
  47. package/dist/resources/extensions/gsd/tools/complete-task.js +1 -1
  48. package/dist/resources/extensions/gsd/worktree-resolver.js +22 -1
  49. package/dist/resources/skills/web-quality-audit/scripts/analyze.sh +0 -0
  50. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  51. package/dist/web/standalone/.next/BUILD_ID +1 -1
  52. package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
  53. package/dist/web/standalone/.next/build-manifest.json +3 -3
  54. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  55. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  56. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  57. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  58. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  66. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  67. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/index.html +1 -1
  75. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  76. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  77. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  78. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  82. package/dist/web/standalone/.next/server/app-paths-manifest.json +17 -17
  83. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  84. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/middleware.js +3 -3
  86. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  87. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  88. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  89. package/dist/web/standalone/.next/static/chunks/8359.e059d86b255fce1c.js +10 -0
  90. package/dist/web/standalone/.next/static/chunks/app/{page-fab3ebb85b006001.js → page-752f1e2ebdaa3e45.js} +1 -1
  91. package/dist/web/standalone/.next/static/chunks/{webpack-0481f1221120a7c6.js → webpack-de742b64187e13fe.js} +1 -1
  92. package/dist/welcome-screen.d.ts +2 -0
  93. package/dist/welcome-screen.js +9 -7
  94. package/package.json +1 -1
  95. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +35 -13
  96. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
  97. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js +21 -11
  98. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js.map +1 -1
  99. package/packages/pi-ai/dist/providers/anthropic.d.ts +7 -0
  100. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  101. package/packages/pi-ai/dist/providers/anthropic.js +9 -7
  102. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  103. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +23 -14
  104. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -1
  105. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +48 -21
  106. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -1
  107. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js +22 -21
  108. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js.map +1 -1
  109. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js +22 -21
  110. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js.map +1 -1
  111. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +39 -25
  112. package/packages/pi-ai/src/providers/anthropic-bearer-auth.test.ts +26 -22
  113. package/packages/pi-ai/src/providers/anthropic.ts +22 -9
  114. package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +34 -21
  115. package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +56 -22
  116. package/packages/pi-ai/src/utils/oauth/google-antigravity.test.ts +24 -28
  117. package/packages/pi-ai/src/utils/oauth/google-gemini-cli.test.ts +24 -28
  118. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  119. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +3 -1
  120. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  121. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -2
  122. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  123. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  124. package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js +22 -56
  125. package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js.map +1 -1
  126. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +1 -0
  127. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  128. package/packages/pi-coding-agent/dist/core/tools/bash.js +3 -1
  129. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  130. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts +2 -0
  131. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  132. package/packages/pi-coding-agent/dist/core/tools/edit.js +12 -1
  133. package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  134. package/packages/pi-coding-agent/dist/core/tools/find.d.ts +2 -0
  135. package/packages/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
  136. package/packages/pi-coding-agent/dist/core/tools/find.js +14 -6
  137. package/packages/pi-coding-agent/dist/core/tools/find.js.map +1 -1
  138. package/packages/pi-coding-agent/dist/core/tools/grep.d.ts +2 -0
  139. package/packages/pi-coding-agent/dist/core/tools/grep.d.ts.map +1 -1
  140. package/packages/pi-coding-agent/dist/core/tools/grep.js +12 -3
  141. package/packages/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
  142. package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts +2 -0
  143. package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
  144. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +3 -1
  145. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
  146. package/packages/pi-coding-agent/dist/core/tools/index.d.ts +2 -1
  147. package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
  148. package/packages/pi-coding-agent/dist/core/tools/index.js +1 -0
  149. package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
  150. package/packages/pi-coding-agent/dist/core/tools/ls.d.ts +2 -0
  151. package/packages/pi-coding-agent/dist/core/tools/ls.d.ts.map +1 -1
  152. package/packages/pi-coding-agent/dist/core/tools/ls.js +10 -3
  153. package/packages/pi-coding-agent/dist/core/tools/ls.js.map +1 -1
  154. package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -0
  155. package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  156. package/packages/pi-coding-agent/dist/core/tools/read.js +3 -1
  157. package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  158. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +7 -62
  159. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -1
  160. package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.d.ts +2 -0
  161. package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.d.ts.map +1 -0
  162. package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.js +115 -0
  163. package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.js.map +1 -0
  164. package/packages/pi-coding-agent/dist/core/tools/tool-target.d.ts +19 -0
  165. package/packages/pi-coding-agent/dist/core/tools/tool-target.d.ts.map +1 -0
  166. package/packages/pi-coding-agent/dist/core/tools/tool-target.js +20 -0
  167. package/packages/pi-coding-agent/dist/core/tools/tool-target.js.map +1 -0
  168. package/packages/pi-coding-agent/dist/core/tools/write.d.ts +4 -0
  169. package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  170. package/packages/pi-coding-agent/dist/core/tools/write.js +9 -1
  171. package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  172. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +89 -2
  173. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  174. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +25 -1
  175. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
  176. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +5 -0
  177. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  178. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +153 -8
  179. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  180. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  181. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +18 -1
  182. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  183. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +23 -5
  184. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +2 -0
  186. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  187. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +19 -0
  188. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +23 -5
  190. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -1
  191. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +3 -1
  192. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -1
  193. package/packages/pi-coding-agent/src/core/tools/bash-spawn-windows.test.ts +22 -66
  194. package/packages/pi-coding-agent/src/core/tools/bash.ts +4 -1
  195. package/packages/pi-coding-agent/src/core/tools/edit.ts +13 -1
  196. package/packages/pi-coding-agent/src/core/tools/find.ts +15 -6
  197. package/packages/pi-coding-agent/src/core/tools/grep.ts +13 -3
  198. package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +4 -1
  199. package/packages/pi-coding-agent/src/core/tools/index.ts +8 -0
  200. package/packages/pi-coding-agent/src/core/tools/ls.ts +11 -3
  201. package/packages/pi-coding-agent/src/core/tools/read.ts +4 -1
  202. package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +11 -72
  203. package/packages/pi-coding-agent/src/core/tools/tool-target-metadata.test.ts +127 -0
  204. package/packages/pi-coding-agent/src/core/tools/tool-target.ts +48 -0
  205. package/packages/pi-coding-agent/src/core/tools/write.ts +14 -2
  206. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +119 -2
  207. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +31 -1
  208. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +177 -8
  209. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +24 -5
  210. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +17 -1
  211. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +21 -0
  212. package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +25 -8
  213. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  214. package/src/resources/extensions/claude-code-cli/readiness.ts +25 -7
  215. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +30 -0
  216. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +26 -0
  217. package/src/resources/extensions/github-sync/sync.ts +8 -1
  218. package/src/resources/extensions/github-sync/tests/sync-source.test.ts +6 -18
  219. package/src/resources/extensions/gsd/auto/loop.ts +84 -8
  220. package/src/resources/extensions/gsd/auto/phases.ts +43 -8
  221. package/src/resources/extensions/gsd/auto/resolve.ts +19 -0
  222. package/src/resources/extensions/gsd/auto/run-unit.ts +3 -0
  223. package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +63 -1
  224. package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +14 -1
  225. package/src/resources/extensions/gsd/auto-post-unit.ts +93 -78
  226. package/src/resources/extensions/gsd/auto-start.ts +56 -6
  227. package/src/resources/extensions/gsd/auto-worktree.ts +118 -72
  228. package/src/resources/extensions/gsd/auto.ts +121 -29
  229. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +76 -12
  230. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +20 -26
  231. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +27 -12
  232. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +7 -9
  233. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +4 -7
  234. package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +6 -10
  235. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +5 -9
  236. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +1 -1
  237. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +64 -26
  238. package/src/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.ts +4 -0
  239. package/src/resources/extensions/gsd/commands/handlers/ops.ts +4 -2
  240. package/src/resources/extensions/gsd/commands-config.ts +1 -1
  241. package/src/resources/extensions/gsd/commands-eval-review.ts +2 -2
  242. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
  243. package/src/resources/extensions/gsd/db/unit-dispatches.ts +66 -0
  244. package/src/resources/extensions/gsd/git-service.ts +41 -2
  245. package/src/resources/extensions/gsd/guided-flow.ts +19 -4
  246. package/src/resources/extensions/gsd/init-wizard.ts +5 -1
  247. package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -4
  248. package/src/resources/extensions/gsd/slice-cadence.ts +49 -2
  249. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +23 -9
  250. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +59 -89
  251. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +47 -172
  252. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +0 -35
  253. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +35 -9
  254. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +15 -0
  255. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +80 -59
  256. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +3 -47
  257. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +76 -18
  258. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +106 -0
  259. package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +54 -95
  260. package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +67 -26
  261. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +32 -30
  262. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +32 -128
  263. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +20 -54
  264. package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +20 -30
  265. package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +17 -29
  266. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +138 -0
  267. package/src/resources/extensions/gsd/tests/auto-start-time-persistence.test.ts +21 -39
  268. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +15 -24
  269. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +44 -29
  270. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +39 -51
  271. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +1 -217
  272. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +15 -32
  273. package/src/resources/extensions/gsd/tests/browser-teardown.test.ts +0 -41
  274. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +34 -27
  275. package/src/resources/extensions/gsd/tests/cmux.test.ts +51 -53
  276. package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +39 -61
  277. package/src/resources/extensions/gsd/tests/commands-config.test.ts +26 -19
  278. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +140 -0
  279. package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +29 -33
  280. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +45 -108
  281. package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +35 -31
  282. package/src/resources/extensions/gsd/tests/cwd-fallback-hardening.test.ts +138 -0
  283. package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +4 -68
  284. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +4 -9
  285. package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +14 -65
  286. package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +44 -37
  287. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +58 -40
  288. package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +25 -15
  289. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +35 -17
  290. package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +16 -21
  291. package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +15 -82
  292. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +2 -20
  293. package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +18 -26
  294. package/src/resources/extensions/gsd/tests/init-skip-git.test.ts +9 -12
  295. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +40 -0
  296. package/src/resources/extensions/gsd/tests/integration/commands-eval-review.integration.test.ts +4 -2
  297. package/src/resources/extensions/gsd/tests/integration/git-locale.test.ts +31 -20
  298. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +12 -0
  299. package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +0 -47
  300. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +60 -202
  301. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +13 -59
  302. package/src/resources/extensions/gsd/tests/lazy-pi-tui-import.test.ts +44 -6
  303. package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +21 -35
  304. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +79 -98
  305. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +70 -278
  306. package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +37 -30
  307. package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +32 -28
  308. package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +24 -37
  309. package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +9 -24
  310. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +113 -0
  311. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +36 -22
  312. package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +36 -30
  313. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +74 -4
  314. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +20 -22
  315. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +130 -32
  316. package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +18 -36
  317. package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +35 -73
  318. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +76 -138
  319. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +70 -125
  320. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +59 -161
  321. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +33 -29
  322. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +22 -196
  323. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +23 -93
  324. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +50 -79
  325. package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +27 -13
  326. package/src/resources/extensions/gsd/tests/remote-questions.test.ts +151 -251
  327. package/src/resources/extensions/gsd/tests/resource-loader-import-path.test.ts +41 -29
  328. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +58 -90
  329. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +32 -164
  330. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +57 -41
  331. package/src/resources/extensions/gsd/tests/session-model-override.test.ts +14 -9
  332. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +77 -0
  333. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +61 -1
  334. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +44 -42
  335. package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +56 -24
  336. package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +51 -11
  337. package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +23 -0
  338. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +66 -50
  339. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +68 -107
  340. package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +115 -42
  341. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +21 -97
  342. package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +25 -116
  343. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +21 -57
  344. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +29 -76
  345. package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +33 -24
  346. package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +39 -30
  347. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +33 -47
  348. package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +48 -46
  349. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +14 -102
  350. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +78 -232
  351. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +32 -35
  352. package/src/resources/extensions/gsd/tests/token-profile.test.ts +84 -309
  353. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +134 -341
  354. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +8 -25
  355. package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +50 -1
  356. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +6 -101
  357. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +43 -36
  358. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -444
  359. package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +142 -0
  360. package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +44 -189
  361. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -57
  362. package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +32 -1
  363. package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +21 -44
  364. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +27 -26
  365. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +14 -13
  366. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -18
  367. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +36 -0
  368. package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -13
  369. package/src/resources/extensions/gsd/tools/complete-milestone.ts +14 -15
  370. package/src/resources/extensions/gsd/tools/complete-task.ts +1 -1
  371. package/src/resources/extensions/gsd/worktree-resolver.ts +34 -1
  372. package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +86 -40
  373. package/src/resources/skills/web-quality-audit/scripts/analyze.sh +0 -0
  374. package/dist/web/standalone/.next/static/chunks/8336.631939fb583761fa.js +0 -10
  375. /package/dist/web/standalone/.next/static/{O2WvnXROue6l7nAp_4dhC → G68KoLv5claox_Dyd4pZn}/_buildManifest.js +0 -0
  376. /package/dist/web/standalone/.next/static/{O2WvnXROue6l7nAp_4dhC → G68KoLv5claox_Dyd4pZn}/_ssgManifest.js +0 -0
@@ -1,3 +1,5 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Auto-mode post-unit git, verification, projection, and hook processing.
1
3
  /**
2
4
  * Post-unit processing for auto-loop — auto-commit, doctor run,
3
5
  * state rebuild, projection checks, DB tool closeout, hooks, triage, and
@@ -103,6 +105,67 @@ function formatPreExecutionCheckDetail(check: PreExecutionCheckJSON): string {
103
105
  const COMPLETE_MILESTONE_DB_SETTLE_MS = 1500;
104
106
  const COMPLETE_MILESTONE_DB_SETTLE_POLL_MS = 100;
105
107
 
108
+ function stripKnownIdPrefix(value: string | undefined | null, id: string): string | undefined {
109
+ const raw = String(value ?? "").trim();
110
+ if (!raw) return undefined;
111
+ const lower = raw.toLowerCase();
112
+ const idLower = id.toLowerCase();
113
+ if (lower.startsWith(`${idLower}:`)) return raw.slice(id.length + 1).trim() || undefined;
114
+ return raw;
115
+ }
116
+
117
+ async function buildTaskCommitContextForUnit(
118
+ basePath: string,
119
+ unitId: string,
120
+ ): Promise<TaskCommitContext | undefined> {
121
+ const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
122
+ if (!mid || !sid || !tid) return undefined;
123
+
124
+ const milestone = isDbAvailable() ? getMilestone(mid) : null;
125
+ const slice = isDbAvailable() ? getSlice(mid, sid) : null;
126
+ const task = isDbAvailable() ? getTask(mid, sid, tid) : null;
127
+ let summary: ReturnType<typeof parseSummary> | null = null;
128
+
129
+ const summaryPath = resolveTaskFile(basePath, mid, sid, tid, "SUMMARY");
130
+ if (summaryPath) {
131
+ try {
132
+ const summaryContent = await loadFile(summaryPath);
133
+ if (summaryContent) summary = parseSummary(summaryContent);
134
+ } catch (e) {
135
+ debugLog("postUnit", { phase: "task-summary-parse", error: String(e) });
136
+ }
137
+ }
138
+
139
+ if (!summary && !task) return undefined;
140
+
141
+ let ghIssueNumber: number | undefined;
142
+ try {
143
+ const { getTaskIssueNumberForCommit } = await import("../github-sync/sync.js");
144
+ ghIssueNumber = getTaskIssueNumberForCommit(basePath, mid, sid, tid) ?? undefined;
145
+ } catch (err) {
146
+ logWarning("engine", `GitHub issue lookup failed: ${err instanceof Error ? err.message : String(err)}`);
147
+ }
148
+
149
+ return {
150
+ taskId: `${sid}/${tid}`,
151
+ taskDisplayId: tid,
152
+ taskTitle:
153
+ stripKnownIdPrefix(summary?.title, tid) ??
154
+ stripKnownIdPrefix(task?.title, tid) ??
155
+ tid,
156
+ milestoneId: mid,
157
+ milestoneTitle: stripKnownIdPrefix(milestone?.title, mid),
158
+ sliceId: sid,
159
+ sliceTitle: stripKnownIdPrefix(slice?.title, sid),
160
+ oneLiner: summary?.oneLiner || task?.one_liner || undefined,
161
+ keyFiles:
162
+ summary?.frontmatter.key_files?.filter(f => !f.includes("{{")) ??
163
+ task?.key_files ??
164
+ undefined,
165
+ issueNumber: ghIssueNumber,
166
+ };
167
+ }
168
+
106
169
  async function waitForMilestoneDbClose(mid: string): Promise<boolean> {
107
170
  const deadline = Date.now() + COMPLETE_MILESTONE_DB_SETTLE_MS;
108
171
  while (Date.now() < deadline) {
@@ -134,6 +197,26 @@ function enqueueSidecar(
134
197
  if (notification) ctx.ui.notify(notification, "info");
135
198
  return "continue";
136
199
  }
200
+
201
+ export function _shouldDispatchTriageForTest(
202
+ state: Pick<AutoSession, "stepMode" | "currentUnit">,
203
+ ): boolean {
204
+ return !state.stepMode &&
205
+ !!state.currentUnit &&
206
+ !state.currentUnit.type.startsWith("hook/") &&
207
+ state.currentUnit.type !== "triage-captures" &&
208
+ state.currentUnit.type !== "quick-task";
209
+ }
210
+
211
+ export function _shouldDispatchQuickTaskForTest(
212
+ state: Pick<AutoSession, "stepMode" | "currentUnit" | "pendingQuickTasks">,
213
+ ): boolean {
214
+ return !state.stepMode &&
215
+ state.pendingQuickTasks.length > 0 &&
216
+ !!state.currentUnit &&
217
+ state.currentUnit.type !== "quick-task";
218
+ }
219
+
137
220
  /** Unit types that only touch `.gsd/` internal state files (no code changes).
138
221
  * Auto-commit is skipped for these — their state files are picked up by the
139
222
  * next actual task commit via `smartStage()`. */
@@ -276,7 +359,7 @@ export function detectRogueFileWrites(
276
359
  * in auto-verification.ts. Exceeding this limit pauses auto-mode instead of
277
360
  * looping indefinitely (#2007).
278
361
  */
279
- const MAX_ARTIFACT_VERIFICATION_RETRIES = 3;
362
+ export const MAX_ARTIFACT_VERIFICATION_RETRIES = 3;
280
363
 
281
364
  export const STEP_COMPLETE_FALLBACK_MESSAGE =
282
365
  "Step complete. Run /clear, then /gsd to continue (or /gsd auto to run continuously).";
@@ -357,35 +440,7 @@ export async function autoCommitUnit(
357
440
  let taskContext: TaskCommitContext | undefined;
358
441
 
359
442
  if (unitType === "execute-task") {
360
- const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
361
- if (mid && sid && tid) {
362
- const summaryPath = resolveTaskFile(basePath, mid, sid, tid, "SUMMARY");
363
- if (summaryPath) {
364
- try {
365
- const summaryContent = await loadFile(summaryPath);
366
- if (summaryContent) {
367
- const summary = parseSummary(summaryContent);
368
- let ghIssueNumber: number | undefined;
369
- try {
370
- const { getTaskIssueNumberForCommit } = await import("../github-sync/sync.js");
371
- ghIssueNumber = getTaskIssueNumberForCommit(basePath, mid, sid, tid) ?? undefined;
372
- } catch (err) {
373
- logWarning("engine", `GitHub issue lookup failed: ${err instanceof Error ? err.message : String(err)}`);
374
- }
375
-
376
- taskContext = {
377
- taskId: `${sid}/${tid}`,
378
- taskTitle: summary.title?.replace(/^T\d+:\s*/, "") || tid,
379
- oneLiner: summary.oneLiner || undefined,
380
- keyFiles: summary.frontmatter.key_files?.filter(f => !f.includes("{{")) || undefined,
381
- issueNumber: ghIssueNumber,
382
- };
383
- }
384
- } catch (e) {
385
- debugLog("postUnit", { phase: "task-summary-parse", error: String(e) });
386
- }
387
- }
388
- }
443
+ taskContext = await buildTaskCommitContextForUnit(basePath, unitId);
389
444
  }
390
445
 
391
446
  _resetHasChangesCache();
@@ -457,37 +512,7 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
457
512
  let taskContext: TaskCommitContext | undefined;
458
513
 
459
514
  if (turnAction === "commit" && s.currentUnit.type === "execute-task") {
460
- const { milestone: mid, slice: sid, task: tid } = parseUnitId(s.currentUnit.id);
461
- if (mid && sid && tid) {
462
- const summaryPath = resolveTaskFile(s.basePath, mid, sid, tid, "SUMMARY");
463
- if (summaryPath) {
464
- try {
465
- const summaryContent = await loadFile(summaryPath);
466
- if (summaryContent) {
467
- const summary = parseSummary(summaryContent);
468
- // Look up GitHub issue number for commit linking
469
- let ghIssueNumber: number | undefined;
470
- try {
471
- const { getTaskIssueNumberForCommit } = await import("../github-sync/sync.js");
472
- ghIssueNumber = getTaskIssueNumberForCommit(s.basePath, mid, sid, tid) ?? undefined;
473
- } catch (err) {
474
- // GitHub sync not available — skip
475
- logWarning("engine", `GitHub issue lookup failed: ${err instanceof Error ? err.message : String(err)}`);
476
- }
477
-
478
- taskContext = {
479
- taskId: `${sid}/${tid}`,
480
- taskTitle: summary.title?.replace(/^T\d+:\s*/, "") || tid,
481
- oneLiner: summary.oneLiner || undefined,
482
- keyFiles: summary.frontmatter.key_files?.filter(f => !f.includes("{{")) || undefined,
483
- issueNumber: ghIssueNumber,
484
- };
485
- }
486
- } catch (e) {
487
- debugLog("postUnit", { phase: "task-summary-parse", error: String(e) });
488
- }
489
- }
490
- }
515
+ taskContext = await buildTaskCommitContextForUnit(s.basePath, s.currentUnit.id);
491
516
  }
492
517
 
493
518
  // Invalidate the nativeHasChanges cache before auto-commit (#1853).
@@ -1320,10 +1345,11 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
1320
1345
 
1321
1346
  const strictMode = prefs?.enhanced_verification_strict === true;
1322
1347
 
1323
- // Run pre-execution checks against the canonical project root. In
1324
- // worktree isolation, s.basePath can point at a metadata-only worktree,
1325
- // while source files remain under the project root.
1326
- const preExecutionBasePath = s.canonicalProjectRoot;
1348
+ // Run pre-execution checks against s.basePath the actual checkout
1349
+ // where prior-slice files were created. In worktree isolation,
1350
+ // s.canonicalProjectRoot is the project root and lacks files that a
1351
+ // prior slice wrote to the worktree but hasn't merged to main yet.
1352
+ const preExecutionBasePath = s.basePath;
1327
1353
  const result: PreExecutionResult = await runPreExecutionChecks(tasks, preExecutionBasePath);
1328
1354
 
1329
1355
  // Log summary to stderr in existing verification output format
@@ -1487,13 +1513,7 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
1487
1513
  }
1488
1514
 
1489
1515
  // ── Triage check ──
1490
- if (
1491
- !s.stepMode &&
1492
- s.currentUnit &&
1493
- !s.currentUnit.type.startsWith("hook/") &&
1494
- s.currentUnit.type !== "triage-captures" &&
1495
- s.currentUnit.type !== "quick-task"
1496
- ) {
1516
+ if (_shouldDispatchTriageForTest(s)) {
1497
1517
  try {
1498
1518
  if (hasPendingCaptures(s.basePath)) {
1499
1519
  const pending = loadPendingCaptures(s.basePath);
@@ -1541,12 +1561,7 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
1541
1561
  }
1542
1562
 
1543
1563
  // ── Quick-task dispatch ──
1544
- if (
1545
- !s.stepMode &&
1546
- s.pendingQuickTasks.length > 0 &&
1547
- s.currentUnit &&
1548
- s.currentUnit.type !== "quick-task"
1549
- ) {
1564
+ if (_shouldDispatchQuickTaskForTest(s)) {
1550
1565
  try {
1551
1566
  const capture = s.pendingQuickTasks.shift()!;
1552
1567
  const { buildQuickTaskPrompt } = await import("./triage-resolution.js");
@@ -1,3 +1,5 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Auto-mode bootstrap, worktree recovery, and fresh-start initialization.
1
3
  /**
2
4
  * Auto-mode bootstrap — fresh-start initialization path.
3
5
  *
@@ -103,6 +105,16 @@ export interface BootstrapDeps {
103
105
  buildResolver: () => WorktreeResolver;
104
106
  }
105
107
 
108
+ export function resolveIsolationNoneBranchCheckout(
109
+ currentBranch: string,
110
+ integrationBranch: string,
111
+ isolationMode: string,
112
+ isRepo: boolean,
113
+ ): string | null {
114
+ if (!isRepo || isolationMode !== "none") return null;
115
+ return currentBranch.startsWith("milestone/") ? integrationBranch : null;
116
+ }
117
+
106
118
  /**
107
119
  * Bootstrap a fresh auto-mode session. Handles everything from git init
108
120
  * through secrets collection, returning when ready for the first
@@ -116,6 +128,18 @@ export interface BootstrapDeps {
116
128
  // Counter moved to AutoSession.consecutiveCompleteBootstraps so s.reset() clears it.
117
129
  const MAX_CONSECUTIVE_COMPLETE_BOOTSTRAPS = 2;
118
130
 
131
+ export function hasGitIndexLockForTest(basePath: string): boolean {
132
+ return existsSync(join(basePath, ".git", "index.lock"));
133
+ }
134
+
135
+ export function _shouldAbortBootstrapForUnavailableDbForTest(
136
+ gsdDbPath: string,
137
+ dbAvailable: boolean,
138
+ pathExists: (path: string) => boolean = existsSync,
139
+ ): boolean {
140
+ return pathExists(gsdDbPath) && !dbAvailable;
141
+ }
142
+
119
143
  export async function openProjectDbIfPresent(basePath: string): Promise<void> {
120
144
  const gsdDbPath = resolveProjectRootDbPath(basePath);
121
145
  if (!existsSync(gsdDbPath) || isDbAvailable()) return;
@@ -876,7 +900,25 @@ export async function bootstrapAutoSession(
876
900
  {
877
901
  const orphan = findUnmergedCompletedMilestone(base, getIsolationMode(base));
878
902
  if (orphan && orphan !== state.activeMilestone?.id) {
903
+ const priorBasePath = s.basePath;
904
+ const priorOriginalBasePath = s.originalBasePath;
905
+ s.originalBasePath = base;
906
+ s.basePath = getAutoWorktreePath(base, orphan) ?? base;
879
907
  const result = _mergeOrphanCompletedMilestone(buildResolver(), orphan, ctx.ui);
908
+ if (!result.merged) {
909
+ s.basePath = base;
910
+ s.originalBasePath = base;
911
+ try {
912
+ process.chdir(base);
913
+ } catch (err) {
914
+ logWarning("bootstrap", `could not restore cwd after orphan merge failure: ${err instanceof Error ? err.message : String(err)}`);
915
+ }
916
+ return releaseLockAndReturn();
917
+ }
918
+ if (!s.active) {
919
+ s.basePath = priorBasePath || base;
920
+ s.originalBasePath = priorOriginalBasePath || base;
921
+ }
880
922
  if (result.merged) {
881
923
  invalidateAllCaches();
882
924
  state = await deriveState(base);
@@ -1030,13 +1072,21 @@ export async function bootstrapAutoSession(
1030
1072
  // Guard against stale milestone branch when isolation:none (#3613).
1031
1073
  // A prior session with isolation:branch/worktree may have left HEAD on
1032
1074
  // milestone/<MID>. Auto-checkout back to the integration branch.
1033
- if (getIsolationMode(base) === "none" && nativeIsRepo(base)) {
1075
+ const isolationMode = getIsolationMode(base);
1076
+ const isRepo = nativeIsRepo(base);
1077
+ if (isolationMode === "none" && isRepo) {
1034
1078
  try {
1035
1079
  const currentBranch = nativeGetCurrentBranch(base);
1036
- if (currentBranch.startsWith("milestone/")) {
1037
- const integrationBranch = nativeDetectMainBranch(base);
1038
- nativeCheckoutBranch(base, integrationBranch);
1039
- logWarning("bootstrap", `Returned to "${integrationBranch}" — HEAD was on stale milestone branch "${currentBranch}" (isolation: none does not use milestone branches).`);
1080
+ const integrationBranch = nativeDetectMainBranch(base);
1081
+ const branchToCheckout = resolveIsolationNoneBranchCheckout(
1082
+ currentBranch,
1083
+ integrationBranch,
1084
+ isolationMode,
1085
+ isRepo,
1086
+ );
1087
+ if (branchToCheckout) {
1088
+ nativeCheckoutBranch(base, branchToCheckout);
1089
+ logWarning("bootstrap", `Returned to "${branchToCheckout}" — HEAD was on stale milestone branch "${currentBranch}" (isolation: none does not use milestone branches).`);
1040
1090
  }
1041
1091
  } catch (err) {
1042
1092
  logWarning("bootstrap", `Could not auto-checkout from stale milestone branch: ${err instanceof Error ? err.message : String(err)}`);
@@ -1085,7 +1135,7 @@ export async function bootstrapAutoSession(
1085
1135
  logError("engine", `failed to initialize project database: ${(err as Error).message}`);
1086
1136
  }
1087
1137
  }
1088
- if (existsSync(gsdDbPath) && !isDbAvailable()) {
1138
+ if (_shouldAbortBootstrapForUnavailableDbForTest(gsdDbPath, isDbAvailable())) {
1089
1139
  try {
1090
1140
  const { openDatabase: openDb } = await import("./gsd-db.js");
1091
1141
  openDb(gsdDbPath);
@@ -28,6 +28,7 @@ import {
28
28
  isDbAvailable,
29
29
  getMilestone,
30
30
  getMilestoneSlices,
31
+ getSliceTasks,
31
32
  closeDatabase,
32
33
  openDatabase,
33
34
  getDbPath,
@@ -194,6 +195,48 @@ function isSamePath(a: string, b: string): boolean {
194
195
  }
195
196
  }
196
197
 
198
+ export function _isSamePathForTest(a: string, b: string): boolean {
199
+ return isSamePath(a, b);
200
+ }
201
+
202
+ export function _resolveAutoWorktreeStartPointForTest(
203
+ integrationBranch: string | null | undefined,
204
+ gitMainBranch: string | null | undefined,
205
+ branchExists: (branch: string) => boolean,
206
+ ): string | undefined {
207
+ if (integrationBranch) return integrationBranch;
208
+ return gitMainBranch &&
209
+ typeof gitMainBranch === "string" &&
210
+ gitMainBranch.length > 0 &&
211
+ branchExists(gitMainBranch)
212
+ ? gitMainBranch
213
+ : undefined;
214
+ }
215
+
216
+ export function _shouldReconcileWorktreeDbForTest(
217
+ worktreeDbPath: string,
218
+ mainDbPath: string,
219
+ pathExists: (path: string) => boolean = existsSync,
220
+ samePath: (a: string, b: string) => boolean = isSamePath,
221
+ ): boolean {
222
+ return pathExists(worktreeDbPath) && !samePath(worktreeDbPath, mainDbPath);
223
+ }
224
+
225
+ export function _isExpectedWorktreeUnlinkErrorForTest(
226
+ code: string | undefined,
227
+ ): boolean {
228
+ return code === "ENOENT" || code === "EISDIR";
229
+ }
230
+
231
+ function stripGsdDisplayPrefix(value: string | undefined | null, id: string): string | undefined {
232
+ const raw = String(value ?? "").trim();
233
+ if (!raw) return undefined;
234
+ const lower = raw.toLowerCase();
235
+ const idLower = id.toLowerCase();
236
+ if (lower.startsWith(`${idLower}:`)) return raw.slice(id.length + 1).trim() || undefined;
237
+ return raw;
238
+ }
239
+
197
240
  // ─── ASSESSMENT Force-Sync Helper (#2821) ─────────────────────────────────
198
241
 
199
242
  /** Regex matching YAML frontmatter `verdict:` field. */
@@ -357,7 +400,7 @@ function clearProjectRootStateFiles(basePath: string, milestoneId: string): void
357
400
  } catch (err) {
358
401
  // ENOENT/EISDIR are expected for already-removed or directory entries (#3597)
359
402
  const code = (err as NodeJS.ErrnoException).code;
360
- if (code !== "ENOENT" && code !== "EISDIR") {
403
+ if (!_isExpectedWorktreeUnlinkErrorForTest(code)) {
361
404
  logWarning("worktree", `untracked file unlink failed: ${err instanceof Error ? err.message : String(err)}`);
362
405
  }
363
406
  }
@@ -390,6 +433,42 @@ export const isSafeToAutoResolve = (filePath: string): boolean =>
390
433
  filePath.startsWith(".gsd/") ||
391
434
  SAFE_AUTO_RESOLVE_PATTERNS.some((re) => re.test(filePath));
392
435
 
436
+ function removeMergeStateFiles(basePath: string, contextLabel: string): void {
437
+ try {
438
+ const gitDir_ = resolveGitDir(basePath);
439
+ for (const f of ["SQUASH_MSG", "MERGE_MSG", "MERGE_HEAD"]) {
440
+ const p = join(gitDir_, f);
441
+ if (existsSync(p)) unlinkSync(p);
442
+ }
443
+ } catch (err) {
444
+ logError("worktree", `${contextLabel} merge state cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
445
+ }
446
+ }
447
+
448
+ function cleanupSquashConflictState(basePath: string): void {
449
+ // `git merge --squash` conflicts can leave unmerged index entries without
450
+ // MERGE_HEAD, so merge-abort alone is not enough. Reset the merge index, then
451
+ // remove merge message files that native/libgit2 paths may have created.
452
+ try {
453
+ nativeMergeAbort(basePath);
454
+ } catch (err) {
455
+ // Expected for squash conflicts when MERGE_HEAD was never written.
456
+ debugLog("squash-conflict-cleanup:merge-abort-skipped", {
457
+ error: err instanceof Error ? err.message : String(err),
458
+ });
459
+ }
460
+ try {
461
+ execFileSync("git", ["reset", "--merge"], {
462
+ cwd: basePath,
463
+ stdio: ["ignore", "pipe", "pipe"],
464
+ encoding: "utf-8",
465
+ });
466
+ } catch (err) {
467
+ logError("worktree", `git reset --merge failed after squash conflict: ${err instanceof Error ? err.message : String(err)}`);
468
+ }
469
+ removeMergeStateFiles(basePath, "squash conflict");
470
+ }
471
+
393
472
  // ─── Dispatch-Level Sync (project root ↔ worktree) ──────────────────────────
394
473
 
395
474
  /**
@@ -1096,19 +1175,12 @@ export function enterBranchModeForMilestone(
1096
1175
  const integrationBranch =
1097
1176
  readIntegrationBranch(basePath, milestoneId) ?? undefined;
1098
1177
  const gitPrefs = loadEffectiveGSDPreferences()?.preferences?.git;
1099
- // Validate main_branch preference exists in the repo before using it —
1100
- // a stale preference (e.g. "master" when repo uses "main") would cause
1101
- // nativeBranchForceReset to fail with a bad start-point reference.
1102
- const validatedPrefBranch =
1103
- gitPrefs?.main_branch &&
1104
- typeof gitPrefs.main_branch === "string" &&
1105
- gitPrefs.main_branch.length > 0 &&
1106
- nativeBranchExists(basePath, gitPrefs.main_branch)
1107
- ? gitPrefs.main_branch
1108
- : undefined;
1109
1178
  const startPoint =
1110
- integrationBranch ??
1111
- validatedPrefBranch ??
1179
+ _resolveAutoWorktreeStartPointForTest(
1180
+ integrationBranch,
1181
+ gitPrefs?.main_branch,
1182
+ (branchName) => nativeBranchExists(basePath, branchName),
1183
+ ) ??
1112
1184
  nativeDetectMainBranch(basePath);
1113
1185
 
1114
1186
  // TOCTOU ancestry guard (Issue #4980 HIGH-3).
@@ -1345,14 +1417,11 @@ export function createAutoWorktree(
1345
1417
  const integrationBranch =
1346
1418
  readIntegrationBranch(basePath, milestoneId) ?? undefined;
1347
1419
  const gitPrefs = loadEffectiveGSDPreferences()?.preferences?.git;
1348
- const validatedPrefBranch =
1349
- gitPrefs?.main_branch &&
1350
- typeof gitPrefs.main_branch === "string" &&
1351
- gitPrefs.main_branch.length > 0 &&
1352
- nativeBranchExists(basePath, gitPrefs.main_branch)
1353
- ? gitPrefs.main_branch
1354
- : undefined;
1355
- const startPoint = integrationBranch ?? validatedPrefBranch ?? undefined;
1420
+ const startPoint = _resolveAutoWorktreeStartPointForTest(
1421
+ integrationBranch,
1422
+ gitPrefs?.main_branch,
1423
+ (branchName) => nativeBranchExists(basePath, branchName),
1424
+ );
1356
1425
  info = createWorktree(basePath, milestoneId, {
1357
1426
  branch,
1358
1427
  startPoint,
@@ -1448,7 +1517,7 @@ export function teardownAutoWorktree(
1448
1517
  const contract = resolveGsdPathContract(previousCwd, originalBasePath);
1449
1518
  const worktreeDbPath = join(contract.worktreeGsd ?? join(previousCwd, ".gsd"), "gsd.db");
1450
1519
  const mainDbPath = contract.projectDb;
1451
- if (existsSync(worktreeDbPath) && !isSamePath(worktreeDbPath, mainDbPath)) {
1520
+ if (_shouldReconcileWorktreeDbForTest(worktreeDbPath, mainDbPath)) {
1452
1521
  reconcileWorktreeDb(mainDbPath, worktreeDbPath);
1453
1522
  }
1454
1523
  } catch (err) {
@@ -1747,7 +1816,7 @@ export function mergeMilestoneToMain(
1747
1816
  const contract = resolveGsdPathContract(worktreeCwd, originalBasePath_);
1748
1817
  const worktreeDbPath = join(contract.worktreeGsd ?? join(worktreeCwd, ".gsd"), "gsd.db");
1749
1818
  const mainDbPath = contract.projectDb;
1750
- if (existsSync(worktreeDbPath) && !isSamePath(worktreeDbPath, mainDbPath)) {
1819
+ if (_shouldReconcileWorktreeDbForTest(worktreeDbPath, mainDbPath)) {
1751
1820
  reconcileWorktreeDb(mainDbPath, worktreeDbPath);
1752
1821
  }
1753
1822
  } catch (err) {
@@ -1757,18 +1826,27 @@ export function mergeMilestoneToMain(
1757
1826
  }
1758
1827
 
1759
1828
  // 2. Get completed slices for commit message
1760
- let completedSlices: { id: string; title: string }[] = [];
1829
+ let completedSlices: { id: string; title: string; tasks: Array<{ id: string; title: string }> }[] = [];
1761
1830
  if (isDbAvailable()) {
1762
1831
  completedSlices = getMilestoneSlices(milestoneId)
1763
1832
  .filter(s => s.status === "complete")
1764
- .map(s => ({ id: s.id, title: s.title }));
1833
+ .map(s => ({
1834
+ id: s.id,
1835
+ title: stripGsdDisplayPrefix(s.title, s.id) ?? s.id,
1836
+ tasks: getSliceTasks(milestoneId, s.id)
1837
+ .filter((task) => task.status === "complete")
1838
+ .map((task) => ({
1839
+ id: task.id,
1840
+ title: stripGsdDisplayPrefix(task.title, task.id) ?? task.id,
1841
+ })),
1842
+ }));
1765
1843
  }
1766
1844
  // Fallback: parse roadmap content when DB is unavailable
1767
1845
  if (completedSlices.length === 0 && roadmapContent) {
1768
1846
  const sliceRe = /- \[x\] \*\*(\w+):\s*(.+?)\*\*/gi;
1769
1847
  let m: RegExpExecArray | null;
1770
1848
  while ((m = sliceRe.exec(roadmapContent)) !== null) {
1771
- completedSlices.push({ id: m[1], title: m[2] });
1849
+ completedSlices.push({ id: m[1], title: m[2], tasks: [] });
1772
1850
  }
1773
1851
  }
1774
1852
 
@@ -1841,8 +1919,7 @@ export function mergeMilestoneToMain(
1841
1919
 
1842
1920
  // 6. Build rich commit message
1843
1921
  const dbMilestone = getMilestone(milestoneId);
1844
- let milestoneTitle =
1845
- (dbMilestone?.title ?? "").replace(/^M\d+:\s*/, "").trim();
1922
+ let milestoneTitle = stripGsdDisplayPrefix(dbMilestone?.title, milestoneId) ?? "";
1846
1923
  // Fallback: parse title from roadmap content header (e.g. "# M020: Backend foundation")
1847
1924
  if (!milestoneTitle && roadmapContent) {
1848
1925
  const titleMatch = roadmapContent.match(new RegExp(`^#\\s+${milestoneId}:\\s*(.+)`, "m"));
@@ -1850,14 +1927,21 @@ export function mergeMilestoneToMain(
1850
1927
  }
1851
1928
  milestoneTitle = milestoneTitle || milestoneId;
1852
1929
  const subject = `feat: ${milestoneTitle}`;
1930
+ const milestoneContext = milestoneTitle === milestoneId
1931
+ ? `Milestone: ${milestoneId}`
1932
+ : `Milestone: ${milestoneId} - ${milestoneTitle}`;
1853
1933
  let body = "";
1854
1934
  if (completedSlices.length > 0) {
1855
1935
  const sliceLines = completedSlices
1856
1936
  .map((s) => `- ${s.id}: ${s.title}`)
1857
1937
  .join("\n");
1858
- body = `\n\nCompleted slices:\n${sliceLines}\n\nGSD-Milestone: ${milestoneId}\nBranch: ${milestoneBranch}`;
1938
+ const taskLines = completedSlices
1939
+ .flatMap((s) => s.tasks.map((task) => `- ${s.id}/${task.id}: ${task.title}`))
1940
+ .join("\n");
1941
+ const taskBlock = taskLines ? `\n\nCompleted tasks:\n${taskLines}` : "";
1942
+ body = `\n\nCompleted slices:\n${sliceLines}${taskBlock}\n\n${milestoneContext}\nGSD-Milestone: ${milestoneId}\nBranch: ${milestoneBranch}`;
1859
1943
  } else {
1860
- body = `\n\nGSD-Milestone: ${milestoneId}\nBranch: ${milestoneBranch}`;
1944
+ body = `\n\n${milestoneContext}\nGSD-Milestone: ${milestoneId}\nBranch: ${milestoneBranch}`;
1861
1945
  }
1862
1946
  const commitMessage = subject + body;
1863
1947
 
@@ -2065,15 +2149,7 @@ export function mergeMilestoneToMain(
2065
2149
  // or interrupted operation) causes `git merge --squash` to refuse with
2066
2150
  // "fatal: You have not concluded your merge (MERGE_HEAD exists)".
2067
2151
  // Defensively remove merge artifacts before starting.
2068
- try {
2069
- const gitDir_ = resolveGitDir(originalBasePath_);
2070
- for (const f of ["SQUASH_MSG", "MERGE_MSG", "MERGE_HEAD"]) {
2071
- const p = join(gitDir_, f);
2072
- if (existsSync(p)) unlinkSync(p);
2073
- }
2074
- } catch (err) { /* best-effort */
2075
- logError("worktree", `merge state cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
2076
- }
2152
+ removeMergeStateFiles(originalBasePath_, "pre-merge");
2077
2153
 
2078
2154
  // 8. Squash merge — auto-resolve .gsd/ state file conflicts (#530)
2079
2155
  const mergeResult = nativeMergeSquash(originalBasePath_, milestoneBranch);
@@ -2085,15 +2161,7 @@ export function mergeMilestoneToMain(
2085
2161
  if (mergeResult.conflicts.includes("__dirty_working_tree__")) {
2086
2162
  // Defensively clean merge state — the native path may leave MERGE_HEAD
2087
2163
  // even when the merge is rejected (#2912).
2088
- try {
2089
- const gitDir_ = resolveGitDir(originalBasePath_);
2090
- for (const f of ["SQUASH_MSG", "MERGE_MSG", "MERGE_HEAD"]) {
2091
- const p = join(gitDir_, f);
2092
- if (existsSync(p)) unlinkSync(p);
2093
- }
2094
- } catch (err) { /* best-effort */
2095
- logError("worktree", `merge state cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
2096
- }
2164
+ removeMergeStateFiles(originalBasePath_, "dirty-tree rejection");
2097
2165
 
2098
2166
  // Pop stash before throwing so local work is not lost.
2099
2167
  if (stashed) {
@@ -2151,21 +2219,7 @@ export function mergeMilestoneToMain(
2151
2219
 
2152
2220
  // If there are still real code conflicts, escalate
2153
2221
  if (codeConflicts.length > 0) {
2154
- // Abort merge state so MERGE_HEAD is not left on disk (#2912).
2155
- // libgit2's merge creates MERGE_HEAD even for squash merges; if left
2156
- // dangling, subsequent merges fail and doctor reports corrupt state.
2157
- try { nativeMergeAbort(originalBasePath_); } catch (err) { /* best-effort */
2158
- logError("worktree", `git merge-abort failed: ${err instanceof Error ? err.message : String(err)}`);
2159
- }
2160
- try {
2161
- const gitDir_ = resolveGitDir(originalBasePath_);
2162
- for (const f of ["SQUASH_MSG", "MERGE_MSG", "MERGE_HEAD"]) {
2163
- const p = join(gitDir_, f);
2164
- if (existsSync(p)) unlinkSync(p);
2165
- }
2166
- } catch (err) { /* best-effort */
2167
- logError("worktree", `merge state file cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
2168
- }
2222
+ cleanupSquashConflictState(originalBasePath_);
2169
2223
 
2170
2224
  // Pop stash before throwing so local work is not lost (#2151).
2171
2225
  if (stashed) {
@@ -2203,15 +2257,7 @@ export function mergeMilestoneToMain(
2203
2257
  // of which trigger git's SQUASH_MSG cleanup. MERGE_HEAD is created by
2204
2258
  // libgit2's merge even in squash mode and is not removed by nativeCommit.
2205
2259
  // If left on disk, doctor reports `corrupt_merge_state` on every subsequent run.
2206
- try {
2207
- const gitDir_ = resolveGitDir(originalBasePath_);
2208
- for (const f of ["SQUASH_MSG", "MERGE_MSG", "MERGE_HEAD"]) {
2209
- const p = join(gitDir_, f);
2210
- if (existsSync(p)) unlinkSync(p);
2211
- }
2212
- } catch (err) { /* best-effort */
2213
- logError("worktree", `post-commit merge state cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
2214
- }
2260
+ removeMergeStateFiles(originalBasePath_, "post-commit");
2215
2261
 
2216
2262
  // 9a-ii. Restore stashed files now that the merge+commit is complete (#2151).
2217
2263
  // Pop after commit so stashed changes do not interfere with the squash merge