gsd-pi 2.43.0-next.8 → 2.44.0-dev.0b97ffd

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 (399) hide show
  1. package/README.md +30 -12
  2. package/dist/cli.js +13 -1
  3. package/dist/help-text.js +24 -0
  4. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +21 -8
  5. package/dist/resources/extensions/gsd/auto-prompts.js +130 -51
  6. package/dist/resources/extensions/gsd/auto-start.js +10 -0
  7. package/dist/resources/extensions/gsd/auto-worktree.js +16 -2
  8. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
  9. package/dist/resources/extensions/gsd/dispatch-guard.js +34 -10
  10. package/dist/resources/extensions/gsd/markdown-renderer.js +7 -5
  11. package/dist/resources/extensions/gsd/reactive-graph.js +13 -2
  12. package/dist/resources/extensions/gsd/skill-health.js +3 -1
  13. package/dist/resources/extensions/gsd/tools/plan-milestone.js +2 -11
  14. package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -10
  15. package/dist/resources/extensions/gsd/visualizer-data.js +45 -13
  16. package/dist/resources/extensions/gsd/workspace-index.js +46 -15
  17. package/dist/web/standalone/.next/BUILD_ID +1 -1
  18. package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -18
  19. package/dist/web/standalone/.next/build-manifest.json +3 -3
  20. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  21. package/dist/web/standalone/.next/required-server-files.json +4 -4
  22. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  23. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  24. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  25. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  30. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  31. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  32. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  33. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  34. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  35. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  36. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  37. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  38. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  39. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  41. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  43. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  44. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  45. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  46. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  47. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  48. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  49. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  50. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  51. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  52. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  53. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  54. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  55. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  56. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  57. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  58. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  59. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  60. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  61. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  62. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  63. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  64. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  65. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  66. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  67. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  74. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  87. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  93. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  109. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  111. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  113. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/index.html +1 -1
  123. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  124. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  125. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  126. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  128. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/page.js +2 -2
  130. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -18
  132. package/dist/web/standalone/.next/server/chunks/229.js +1 -1
  133. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  134. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/middleware.js +2 -2
  136. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  138. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  139. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  140. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  141. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
  142. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
  143. package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
  144. package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
  145. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  146. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  147. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  148. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  149. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  150. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  151. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  152. package/dist/web/standalone/server.js +1 -1
  153. package/package.json +4 -4
  154. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +3 -3
  155. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  156. package/packages/pi-coding-agent/dist/core/agent-session.js +11 -34
  157. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  158. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
  159. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  160. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts +2 -2
  161. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  162. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js.map +1 -1
  163. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +2 -2
  164. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  165. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  166. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +4 -4
  167. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  168. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  169. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  170. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  171. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  172. package/packages/pi-coding-agent/dist/core/extensions/loader.js +18 -0
  173. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  174. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
  175. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  176. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +37 -0
  177. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  178. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  179. package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts.map +1 -1
  180. package/packages/pi-coding-agent/dist/core/fallback-resolver.js +2 -3
  181. package/packages/pi-coding-agent/dist/core/fallback-resolver.js.map +1 -1
  182. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js +12 -2
  183. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
  185. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  186. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +38 -0
  187. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -0
  188. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +192 -0
  189. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -0
  190. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts +2 -0
  191. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts.map +1 -0
  192. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +255 -0
  193. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -0
  194. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +15 -0
  195. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
  197. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  198. package/packages/pi-coding-agent/dist/core/package-commands.d.ts +25 -0
  199. package/packages/pi-coding-agent/dist/core/package-commands.d.ts.map +1 -0
  200. package/packages/pi-coding-agent/dist/core/package-commands.js +253 -0
  201. package/packages/pi-coding-agent/dist/core/package-commands.js.map +1 -0
  202. package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts +2 -0
  203. package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts.map +1 -0
  204. package/packages/pi-coding-agent/dist/core/package-commands.test.js +225 -0
  205. package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -0
  206. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
  207. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  209. package/packages/pi-coding-agent/dist/core/sdk.js +4 -0
  210. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  211. package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
  212. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  213. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
  214. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  215. package/packages/pi-coding-agent/dist/index.d.ts +3 -1
  216. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  217. package/packages/pi-coding-agent/dist/index.js +1 -0
  218. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  219. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  220. package/packages/pi-coding-agent/dist/main.js +11 -199
  221. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  222. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
  223. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  224. package/packages/pi-coding-agent/package.json +1 -1
  225. package/packages/pi-coding-agent/src/core/agent-session.ts +13 -37
  226. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  227. package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +2 -2
  228. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +3 -3
  229. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +4 -4
  230. package/packages/pi-coding-agent/src/core/extensions/index.ts +5 -0
  231. package/packages/pi-coding-agent/src/core/extensions/loader.ts +23 -0
  232. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  233. package/packages/pi-coding-agent/src/core/extensions/types.ts +44 -0
  234. package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +15 -2
  235. package/packages/pi-coding-agent/src/core/fallback-resolver.ts +2 -3
  236. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
  237. package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +274 -0
  238. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +288 -0
  239. package/packages/pi-coding-agent/src/core/model-registry.ts +39 -3
  240. package/packages/pi-coding-agent/src/core/package-commands.test.ts +240 -0
  241. package/packages/pi-coding-agent/src/core/package-commands.ts +310 -0
  242. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
  243. package/packages/pi-coding-agent/src/core/sdk.ts +4 -0
  244. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  245. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  246. package/packages/pi-coding-agent/src/index.ts +7 -0
  247. package/packages/pi-coding-agent/src/main.ts +11 -232
  248. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  249. package/pkg/package.json +1 -1
  250. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +22 -7
  251. package/src/resources/extensions/gsd/auto-prompts.ts +109 -42
  252. package/src/resources/extensions/gsd/auto-start.ts +14 -0
  253. package/src/resources/extensions/gsd/auto-worktree.ts +16 -3
  254. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
  255. package/src/resources/extensions/gsd/dispatch-guard.ts +28 -10
  256. package/src/resources/extensions/gsd/markdown-renderer.ts +7 -5
  257. package/src/resources/extensions/gsd/reactive-graph.ts +12 -2
  258. package/src/resources/extensions/gsd/skill-health.ts +2 -1
  259. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  260. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
  261. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
  262. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
  263. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
  264. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
  265. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
  266. package/src/resources/extensions/gsd/tests/auto-stash-merge.test.ts +3 -3
  267. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
  268. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
  269. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
  270. package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
  271. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
  272. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
  273. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  274. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  275. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +38 -59
  276. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +228 -263
  277. package/src/resources/extensions/gsd/tests/complete-task.test.ts +250 -302
  278. package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
  279. package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
  280. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
  281. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
  282. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
  283. package/src/resources/extensions/gsd/tests/db-writer.test.ts +390 -420
  284. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
  285. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
  286. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +152 -183
  287. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
  288. package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
  289. package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
  290. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
  291. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
  292. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
  293. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
  294. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
  295. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
  296. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
  297. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
  298. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
  299. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
  300. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
  301. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
  302. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
  303. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
  304. package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
  305. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
  306. package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
  307. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
  308. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
  309. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
  310. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
  311. package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
  312. package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
  313. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
  314. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
  315. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
  316. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
  317. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
  318. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
  319. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  320. package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
  321. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -102
  322. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
  323. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
  324. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
  325. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
  326. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
  327. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
  328. package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
  329. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
  330. package/src/resources/extensions/gsd/tests/memory-store.test.ts +80 -93
  331. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
  332. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
  333. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
  334. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
  335. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
  336. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
  337. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
  338. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
  339. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
  340. package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
  341. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
  342. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
  343. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
  344. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
  345. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
  346. package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
  347. package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
  348. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
  349. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  350. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
  351. package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
  352. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
  353. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
  354. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
  355. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
  356. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
  357. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
  358. package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
  359. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
  360. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
  361. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
  362. package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
  363. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
  364. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
  365. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
  366. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
  367. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
  368. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
  369. package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
  370. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
  371. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +9 -11
  372. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
  373. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
  374. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
  375. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
  376. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
  377. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
  378. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
  379. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
  380. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
  381. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
  382. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
  383. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
  384. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
  385. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
  386. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
  387. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
  388. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
  389. package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
  390. package/src/resources/extensions/gsd/tools/plan-milestone.ts +1 -18
  391. package/src/resources/extensions/gsd/tools/plan-slice.ts +1 -15
  392. package/src/resources/extensions/gsd/visualizer-data.ts +46 -14
  393. package/src/resources/extensions/gsd/workspace-index.ts +49 -18
  394. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
  395. package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
  396. package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
  397. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
  398. /package/dist/web/standalone/.next/static/{drUWS0zys9uepCfCwecJv → alS4hoANx0TK4UVZY27da}/_buildManifest.js +0 -0
  399. /package/dist/web/standalone/.next/static/{drUWS0zys9uepCfCwecJv → alS4hoANx0TK4UVZY27da}/_ssgManifest.js +0 -0
@@ -16,6 +16,7 @@ import {
16
16
  resolveGsdRootFile, relGsdRootFile, resolveRuntimeFile,
17
17
  } from "./paths.js";
18
18
  import { resolveSkillDiscoveryMode, resolveInlineLevel, loadEffectiveGSDPreferences, resolveAllSkillReferences } from "./preferences.js";
19
+ import { parseRoadmap } from "./parsers-legacy.js";
19
20
  import type { GSDState, InlineLevel } from "./types.js";
20
21
  import type { GSDPreferences } from "./preferences.js";
21
22
  import { getLoadedSkills, type Skill } from "@gsd/pi-coding-agent";
@@ -183,14 +184,30 @@ export async function inlineDependencySummaries(
183
184
  const { isDbAvailable, getSlice } = await import("./gsd-db.js");
184
185
  if (isDbAvailable()) {
185
186
  const slice = getSlice(mid, sid);
186
- if (!slice || slice.depends.length === 0) return "- (no dependencies)";
187
- depends = slice.depends as string[];
187
+ if (slice) {
188
+ if (slice.depends.length === 0) return "- (no dependencies)";
189
+ depends = slice.depends as string[];
190
+ }
191
+ // If slice not found in DB, fall through to file-based parsing
188
192
  }
189
193
  } catch { /* fall through */ }
190
194
 
191
- // If DB didn't provide depends, we can't determine them without parsers
195
+ // If DB didn't provide depends, fall back to roadmap parsing
192
196
  if (!depends) {
193
- return "- (no dependencies)";
197
+ const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
198
+ if (roadmapPath) {
199
+ const roadmapContent = await loadFile(roadmapPath);
200
+ if (roadmapContent) {
201
+ const parsed = parseRoadmap(roadmapContent);
202
+ const slice = parsed.slices.find(s => s.id === sid);
203
+ if (slice && slice.depends.length > 0) {
204
+ depends = slice.depends;
205
+ }
206
+ }
207
+ }
208
+ if (!depends) {
209
+ return "- (no dependencies)";
210
+ }
194
211
  }
195
212
 
196
213
  const sections: string[] = [];
@@ -684,29 +701,44 @@ export async function getDependencyTaskSummaryPaths(
684
701
  export async function checkNeedsReassessment(
685
702
  base: string, mid: string, state: GSDState,
686
703
  ): Promise<{ sliceId: string } | null> {
687
- // DB primary path
688
- let completedSliceIds: string[] = [];
689
- let hasIncomplete = false;
704
+ // DB primary path — fall through to file-based when DB has no data for this milestone
690
705
  try {
691
706
  const { isDbAvailable, getMilestoneSlices } = await import("./gsd-db.js");
692
707
  if (isDbAvailable()) {
693
708
  const slices = getMilestoneSlices(mid);
694
- completedSliceIds = slices.filter(s => s.status === "complete").map(s => s.id);
695
- hasIncomplete = slices.some(s => s.status !== "complete");
696
- if (completedSliceIds.length === 0 || !hasIncomplete) return null;
697
- const lastCompleted = completedSliceIds[completedSliceIds.length - 1];
698
- const assessmentFile = resolveSliceFile(base, mid, lastCompleted, "ASSESSMENT");
699
- const hasAssessment = !!(assessmentFile && await loadFile(assessmentFile));
700
- if (hasAssessment) return null;
701
- const summaryFile = resolveSliceFile(base, mid, lastCompleted, "SUMMARY");
702
- const hasSummary = !!(summaryFile && await loadFile(summaryFile));
703
- if (!hasSummary) return null;
704
- return { sliceId: lastCompleted };
709
+ if (slices.length > 0) {
710
+ const completedSliceIds = slices.filter(s => s.status === "complete").map(s => s.id);
711
+ const hasIncomplete = slices.some(s => s.status !== "complete");
712
+ if (completedSliceIds.length === 0 || !hasIncomplete) return null;
713
+ const lastCompleted = completedSliceIds[completedSliceIds.length - 1];
714
+ const assessmentFile = resolveSliceFile(base, mid, lastCompleted, "ASSESSMENT");
715
+ const hasAssessment = !!(assessmentFile && await loadFile(assessmentFile));
716
+ if (hasAssessment) return null;
717
+ const summaryFile = resolveSliceFile(base, mid, lastCompleted, "SUMMARY");
718
+ const hasSummary = !!(summaryFile && await loadFile(summaryFile));
719
+ if (!hasSummary) return null;
720
+ return { sliceId: lastCompleted };
721
+ }
705
722
  }
706
723
  } catch { /* fall through */ }
707
724
 
708
- // DB unavailable cannot determine assessment needs
709
- return null;
725
+ // File-based fallback using roadmap checkboxes
726
+ const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
727
+ if (!roadmapPath) return null;
728
+ const roadmapContent = await loadFile(roadmapPath);
729
+ if (!roadmapContent) return null;
730
+ const parsed = parseRoadmap(roadmapContent);
731
+ const fileCompletedIds = parsed.slices.filter(s => s.done).map(s => s.id);
732
+ const fileHasIncomplete = parsed.slices.some(s => !s.done);
733
+ if (fileCompletedIds.length === 0 || !fileHasIncomplete) return null;
734
+ const lastDone = fileCompletedIds[fileCompletedIds.length - 1];
735
+ const assessFile = resolveSliceFile(base, mid, lastDone, "ASSESSMENT");
736
+ const hasAssess = !!(assessFile && await loadFile(assessFile));
737
+ if (hasAssess) return null;
738
+ const summFile = resolveSliceFile(base, mid, lastDone, "SUMMARY");
739
+ const hasSumm = !!(summFile && await loadFile(summFile));
740
+ if (!hasSumm) return null;
741
+ return { sliceId: lastDone };
710
742
  }
711
743
 
712
744
  /**
@@ -723,34 +755,57 @@ export async function checkNeedsReassessment(
723
755
  export async function checkNeedsRunUat(
724
756
  base: string, mid: string, state: GSDState, prefs: GSDPreferences | undefined,
725
757
  ): Promise<{ sliceId: string; uatType: UatType } | null> {
726
- // DB primary path
758
+ // DB primary path — fall through to file-based when DB has no data for this milestone
727
759
  try {
728
760
  const { isDbAvailable, getMilestoneSlices } = await import("./gsd-db.js");
729
761
  if (isDbAvailable()) {
730
762
  const slices = getMilestoneSlices(mid);
731
- const completedSlices = slices.filter(s => s.status === "complete");
732
- const incompleteSlices = slices.filter(s => s.status !== "complete");
733
- if (completedSlices.length === 0) return null;
734
- if (incompleteSlices.length === 0) return null;
735
- if (!prefs?.uat_dispatch) return null;
736
- const lastCompleted = completedSlices[completedSlices.length - 1];
737
- const sid = lastCompleted.id;
738
- const uatFile = resolveSliceFile(base, mid, sid, "UAT");
739
- if (!uatFile) return null;
740
- const uatContent = await loadFile(uatFile);
741
- if (!uatContent) return null;
742
- const uatResultFile = resolveSliceFile(base, mid, sid, "UAT-RESULT");
743
- if (uatResultFile) {
744
- const hasResult = !!(await loadFile(uatResultFile));
745
- if (hasResult) return null;
763
+ if (slices.length > 0) {
764
+ const completedSlices = slices.filter(s => s.status === "complete");
765
+ const incompleteSlices = slices.filter(s => s.status !== "complete");
766
+ if (completedSlices.length === 0) return null;
767
+ if (incompleteSlices.length === 0) return null;
768
+ if (!prefs?.uat_dispatch) return null;
769
+ const lastCompleted = completedSlices[completedSlices.length - 1];
770
+ const sid = lastCompleted.id;
771
+ const uatFile = resolveSliceFile(base, mid, sid, "UAT");
772
+ if (!uatFile) return null;
773
+ const uatContent = await loadFile(uatFile);
774
+ if (!uatContent) return null;
775
+ const uatResultFile = resolveSliceFile(base, mid, sid, "UAT-RESULT");
776
+ if (uatResultFile) {
777
+ const hasResult = !!(await loadFile(uatResultFile));
778
+ if (hasResult) return null;
779
+ }
780
+ const uatType = extractUatType(uatContent) ?? "artifact-driven";
781
+ return { sliceId: sid, uatType };
746
782
  }
747
- const uatType = extractUatType(uatContent) ?? "artifact-driven";
748
- return { sliceId: sid, uatType };
749
783
  }
750
784
  } catch { /* fall through */ }
751
785
 
752
- // DB unavailable cannot determine UAT needs
753
- return null;
786
+ // File-based fallback using roadmap checkboxes
787
+ if (!prefs?.uat_dispatch) return null;
788
+ const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
789
+ if (!roadmapPath) return null;
790
+ const roadmapContent = await loadFile(roadmapPath);
791
+ if (!roadmapContent) return null;
792
+ const parsed = parseRoadmap(roadmapContent);
793
+ const completedFileSlices = parsed.slices.filter(s => s.done);
794
+ const incompleteFileSlices = parsed.slices.filter(s => !s.done);
795
+ if (completedFileSlices.length === 0 || incompleteFileSlices.length === 0) return null;
796
+ const lastCompletedFile = completedFileSlices[completedFileSlices.length - 1];
797
+ const uatSid = lastCompletedFile.id;
798
+ const uatFileFb = resolveSliceFile(base, mid, uatSid, "UAT");
799
+ if (!uatFileFb) return null;
800
+ const uatContentFb = await loadFile(uatFileFb);
801
+ if (!uatContentFb) return null;
802
+ const uatResultFb = resolveSliceFile(base, mid, uatSid, "UAT-RESULT");
803
+ if (uatResultFb) {
804
+ const hasResultFb = !!(await loadFile(uatResultFb));
805
+ if (hasResultFb) return null;
806
+ }
807
+ const uatTypeFb = extractUatType(uatContentFb) ?? "artifact-driven";
808
+ return { sliceId: uatSid, uatType: uatTypeFb };
754
809
  }
755
810
 
756
811
  // ─── Prompt Builders ──────────────────────────────────────────────────────
@@ -1207,7 +1262,13 @@ export async function buildCompleteMilestonePrompt(
1207
1262
  sliceIds = getMilestoneSlices(mid).map(s => s.id);
1208
1263
  }
1209
1264
  } catch { /* fall through */ }
1210
- // If DB didn't provide slice IDs, sliceIds stays empty no summaries to inline
1265
+ // File-based fallback: parse roadmap for slice IDs when DB has no data
1266
+ if (sliceIds.length === 0 && roadmapPath) {
1267
+ const roadmapContent = await loadFile(roadmapPath);
1268
+ if (roadmapContent) {
1269
+ sliceIds = parseRoadmap(roadmapContent).slices.map(s => s.id);
1270
+ }
1271
+ }
1211
1272
  const seenSlices = new Set<string>();
1212
1273
  for (const sid of sliceIds) {
1213
1274
  if (seenSlices.has(sid)) continue;
@@ -1267,7 +1328,13 @@ export async function buildValidateMilestonePrompt(
1267
1328
  valSliceIds = getMilestoneSlices(mid).map(s => s.id);
1268
1329
  }
1269
1330
  } catch { /* fall through */ }
1270
- // If DB didn't provide slice IDs, valSliceIds stays empty
1331
+ // File-based fallback: parse roadmap for slice IDs when DB has no data
1332
+ if (valSliceIds.length === 0 && roadmapPath) {
1333
+ const roadmapContent = await loadFile(roadmapPath);
1334
+ if (roadmapContent) {
1335
+ valSliceIds = parseRoadmap(roadmapContent).slices.map(s => s.id);
1336
+ }
1337
+ }
1271
1338
  const seenValSlices = new Set<string>();
1272
1339
  for (const sid of valSliceIds) {
1273
1340
  if (seenValSlices.has(sid)) continue;
@@ -551,6 +551,20 @@ export async function bootstrapAutoSession(
551
551
  }
552
552
  }
553
553
 
554
+ // Gate: abort bootstrap if the DB file exists but the provider is
555
+ // still unavailable after both open attempts above. Without this,
556
+ // auto-mode starts but every gsd_task_complete / gsd_slice_complete
557
+ // call returns "db_unavailable", triggering artifact-retry which
558
+ // re-dispatches the same task — producing an infinite loop (#2419).
559
+ if (existsSync(gsdDbPath) && !isDbAvailable()) {
560
+ ctx.ui.notify(
561
+ "SQLite database exists but failed to open. Auto-mode cannot proceed without a working database provider. " +
562
+ "Check for corrupt gsd.db or missing native SQLite bindings.",
563
+ "error",
564
+ );
565
+ return releaseLockAndReturn();
566
+ }
567
+
554
568
  // Initialize metrics
555
569
  initMetrics(s.basePath);
556
570
 
@@ -1006,7 +1006,14 @@ export function mergeMilestoneToMain(
1006
1006
  .filter(s => s.status === "complete")
1007
1007
  .map(s => ({ id: s.id, title: s.title }));
1008
1008
  }
1009
- // When DB unavailable, completedSlices stays empty commit message will omit slice details
1009
+ // Fallback: parse roadmap content when DB is unavailable
1010
+ if (completedSlices.length === 0 && roadmapContent) {
1011
+ const sliceRe = /- \[x\] \*\*(\w+):\s*(.+?)\*\*/gi;
1012
+ let m: RegExpExecArray | null;
1013
+ while ((m = sliceRe.exec(roadmapContent)) !== null) {
1014
+ completedSlices.push({ id: m[1], title: m[2] });
1015
+ }
1016
+ }
1010
1017
 
1011
1018
  // 3. chdir to original base
1012
1019
  const previousCwd = process.cwd();
@@ -1037,8 +1044,14 @@ export function mergeMilestoneToMain(
1037
1044
 
1038
1045
  // 6. Build rich commit message
1039
1046
  const dbMilestone = getMilestone(milestoneId);
1040
- const milestoneTitle =
1041
- (dbMilestone?.title ?? "").replace(/^M\d+:\s*/, "").trim() || milestoneId;
1047
+ let milestoneTitle =
1048
+ (dbMilestone?.title ?? "").replace(/^M\d+:\s*/, "").trim();
1049
+ // Fallback: parse title from roadmap content header (e.g. "# M020: Backend foundation")
1050
+ if (!milestoneTitle && roadmapContent) {
1051
+ const titleMatch = roadmapContent.match(new RegExp(`^#\\s+${milestoneId}:\\s*(.+)`, "m"));
1052
+ if (titleMatch) milestoneTitle = titleMatch[1].trim();
1053
+ }
1054
+ milestoneTitle = milestoneTitle || milestoneId;
1042
1055
  const subject = `feat(${milestoneId}): ${milestoneTitle}`;
1043
1056
  let body = "";
1044
1057
  if (completedSlices.length > 0) {
@@ -188,6 +188,14 @@ export async function handleWorkflowCommand(trimmed: string, ctx: ExtensionComma
188
188
  return true;
189
189
  }
190
190
  if (trimmed === "quick" || trimmed.startsWith("quick ")) {
191
+ if (isAutoActive()) {
192
+ ctx.ui.notify(
193
+ "/gsd quick cannot run while auto-mode is active.\n" +
194
+ "Stop auto-mode first with /gsd stop, then run /gsd quick.",
195
+ "error",
196
+ );
197
+ return true;
198
+ }
191
199
  await handleQuick(trimmed.replace(/^quick\s*/, "").trim(), ctx, pi);
192
200
  return true;
193
201
  }
@@ -3,6 +3,8 @@
3
3
  import { resolveMilestoneFile } from "./paths.js";
4
4
  import { findMilestoneIds } from "./guided-flow.js";
5
5
  import { isDbAvailable, getMilestoneSlices } from "./gsd-db.js";
6
+ import { parseRoadmap } from "./parsers-legacy.js";
7
+ import { readFileSync } from "node:fs";
6
8
 
7
9
  const SLICE_DISPATCH_TYPES = new Set([
8
10
  "research-slice",
@@ -34,18 +36,34 @@ export function getPriorSliceCompletionBlocker(
34
36
  if (resolveMilestoneFile(base, mid, "PARKED")) continue;
35
37
  if (resolveMilestoneFile(base, mid, "SUMMARY")) continue;
36
38
 
37
- // Normalised slice list from DB
39
+ // Normalised slice list from DB or file fallback
38
40
  type NormSlice = { id: string; done: boolean; depends: string[] };
41
+ let slices: NormSlice[] | null = null;
39
42
 
40
- if (!isDbAvailable()) continue;
41
-
42
- const rows = getMilestoneSlices(mid);
43
- if (rows.length === 0) continue;
44
- const slices: NormSlice[] = rows.map((r) => ({
45
- id: r.id,
46
- done: r.status === "complete",
47
- depends: r.depends ?? [],
48
- }));
43
+ if (isDbAvailable()) {
44
+ const rows = getMilestoneSlices(mid);
45
+ if (rows.length > 0) {
46
+ slices = rows.map((r) => ({
47
+ id: r.id,
48
+ done: r.status === "complete",
49
+ depends: r.depends ?? [],
50
+ }));
51
+ }
52
+ }
53
+ if (!slices) {
54
+ // File-based fallback: parse roadmap checkboxes
55
+ const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
56
+ if (!roadmapPath) continue;
57
+ let roadmapContent: string;
58
+ try { roadmapContent = readFileSync(roadmapPath, "utf-8"); } catch { continue; }
59
+ const parsed = parseRoadmap(roadmapContent);
60
+ if (parsed.slices.length === 0) continue;
61
+ slices = parsed.slices.map((s) => ({
62
+ id: s.id,
63
+ done: s.done,
64
+ depends: s.depends ?? [],
65
+ }));
66
+ }
49
67
 
50
68
  if (mid !== targetMid) {
51
69
  const incomplete = slices.find((slice) => !slice.done);
@@ -933,12 +933,14 @@ export async function repairStaleRenders(basePath: string): Promise<number> {
933
933
 
934
934
  for (const entry of staleEntries) {
935
935
  if (repairedPaths.has(entry.path)) continue;
936
+ // Normalize path separators for cross-platform regex matching
937
+ const normPath = entry.path.replace(/\\/g, "/");
936
938
 
937
939
  try {
938
940
  // Determine repair action from the reason
939
941
  if (entry.reason.includes("in roadmap")) {
940
942
  // Roadmap checkbox mismatch — extract milestone ID from path
941
- const milestoneMatch = entry.path.match(/milestones\/([^/]+)\//);
943
+ const milestoneMatch = normPath.match(/milestones\/([^/]+)\//);
942
944
  if (milestoneMatch) {
943
945
  const ok = await renderRoadmapCheckboxes(basePath, milestoneMatch[1]);
944
946
  if (ok) {
@@ -948,7 +950,7 @@ export async function repairStaleRenders(basePath: string): Promise<number> {
948
950
  }
949
951
  } else if (entry.reason.includes("in plan")) {
950
952
  // Plan checkbox mismatch — extract milestone + slice IDs from path
951
- const pathMatch = entry.path.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
953
+ const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
952
954
  if (pathMatch) {
953
955
  const ok = await renderPlanCheckboxes(basePath, pathMatch[1], pathMatch[2]);
954
956
  if (ok) {
@@ -958,7 +960,7 @@ export async function repairStaleRenders(basePath: string): Promise<number> {
958
960
  }
959
961
  } else if (entry.reason.includes("SUMMARY.md missing") && entry.reason.match(/^T\d+/)) {
960
962
  // Missing task summary — extract IDs from path
961
- const pathMatch = entry.path.match(/milestones\/([^/]+)\/slices\/([^/]+)\/tasks\//);
963
+ const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\/tasks\//);
962
964
  const taskMatch = entry.reason.match(/^(T\d+)/);
963
965
  if (pathMatch && taskMatch) {
964
966
  const ok = await renderTaskSummary(basePath, pathMatch[1], pathMatch[2], taskMatch[1]);
@@ -969,7 +971,7 @@ export async function repairStaleRenders(basePath: string): Promise<number> {
969
971
  }
970
972
  } else if (entry.reason.includes("SUMMARY.md missing") && entry.reason.match(/^S\d+/)) {
971
973
  // Missing slice summary — extract IDs from path
972
- const pathMatch = entry.path.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
974
+ const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
973
975
  if (pathMatch) {
974
976
  const ok = await renderSliceSummary(basePath, pathMatch[1], pathMatch[2]);
975
977
  if (ok) {
@@ -979,7 +981,7 @@ export async function repairStaleRenders(basePath: string): Promise<number> {
979
981
  }
980
982
  } else if (entry.reason.includes("UAT.md missing")) {
981
983
  // Missing slice UAT — renderSliceSummary handles both SUMMARY + UAT
982
- const pathMatch = entry.path.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
984
+ const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
983
985
  if (pathMatch) {
984
986
  const ok = await renderSliceSummary(basePath, pathMatch[1], pathMatch[2]);
985
987
  if (ok) {
@@ -12,6 +12,7 @@
12
12
  import type { TaskIO, DerivedTaskNode, ReactiveExecutionState } from "./types.js";
13
13
  import { loadFile, parseTaskPlanIO } from "./files.js";
14
14
  import { isDbAvailable, getSliceTasks } from "./gsd-db.js";
15
+ import { parsePlan } from "./parsers-legacy.js";
15
16
  import { resolveTasksDir, resolveTaskFiles } from "./paths.js";
16
17
  import { join } from "node:path";
17
18
  import { loadJsonFileOrNull, saveJsonFile } from "./json-persistence.js";
@@ -205,8 +206,17 @@ export async function loadSliceTaskIO(
205
206
  } catch { /* fall through */ }
206
207
 
207
208
  if (!taskEntries) {
208
- // DB unavailable cannot determine task graph
209
- return [];
209
+ // File-based fallback: parse slice plan for task entries
210
+ const parsed = parsePlan(planContent);
211
+ if (parsed.tasks.length > 0) {
212
+ taskEntries = parsed.tasks.map(t => ({
213
+ id: t.id,
214
+ title: t.title,
215
+ done: t.done,
216
+ }));
217
+ } else {
218
+ return [];
219
+ }
210
220
  }
211
221
 
212
222
  const tDir = resolveTasksDir(basePath, mid, sid);
@@ -283,7 +283,8 @@ export function computeStaleAvoidList(
283
283
  staleDays?: number,
284
284
  ): string[] {
285
285
  const ledger = loadLedgerFromDisk(basePath);
286
- const units = (ledger?.units ?? []).filter(u => u.skills && u.skills.length > 0);
286
+ if (!ledger) return [];
287
+ const units = ledger.units.filter(u => u.skills && u.skills.length > 0);
287
288
  const stale = detectStaleSkills(units, staleDays ?? DEFAULT_STALE_DAYS);
288
289
  const avoidSet = new Set(currentAvoidList);
289
290
 
@@ -130,119 +130,119 @@ test("auto-loop 'all milestones complete' path merges before stopping (#962)", (
130
130
 
131
131
  // ─── Integration: single milestone completes → merged to main ────────────────
132
132
 
133
- test("single milestone worktree is merged to main when all complete (#962)", () => {
133
+ test("single milestone worktree is merged to main when all complete (#962)", (t) => {
134
134
  const savedCwd = process.cwd();
135
135
  let tempDir = "";
136
136
 
137
- try {
138
- tempDir = createTempRepo();
139
-
140
- // Set up a single milestone
141
- createMilestoneArtifacts(tempDir, "M001");
142
- run("git add .", tempDir);
143
- run('git commit -m "add milestone"', tempDir);
144
-
145
- // Create worktree and simulate work
146
- const wt = createAutoWorktree(tempDir, "M001");
147
- assert.ok(isInAutoWorktree(tempDir), "should be in auto-worktree");
148
-
149
- writeFileSync(join(wt, "feature.ts"), "export const feature = true;\n");
150
- run("git add .", wt);
151
- run('git commit -m "feat(M001): add feature"', wt);
152
-
153
- // Simulate the fix: merge before stopping (what the "all complete" path now does)
154
- const roadmapPath = join(
155
- tempDir,
156
- ".gsd",
157
- "milestones",
158
- "M001",
159
- "M001-ROADMAP.md",
160
- );
161
- const roadmapContent = readFileSync(roadmapPath, "utf-8");
162
- const mergeResult = mergeMilestoneToMain(tempDir, "M001", roadmapContent);
163
-
164
- // Verify work is on main
165
- assert.ok(
166
- existsSync(join(tempDir, "feature.ts")),
167
- "feature.ts should be on main after merge",
168
- );
169
- assert.equal(process.cwd(), tempDir, "cwd restored to project root");
170
- assert.ok(!isInAutoWorktree(tempDir), "no longer in auto-worktree");
171
- assert.equal(getAutoWorktreeOriginalBase(), null, "originalBase cleared");
172
-
173
- // Verify milestone branch was cleaned up
174
- const branches = run("git branch", tempDir);
175
- assert.ok(
176
- !branches.includes("milestone/M001"),
177
- "milestone branch should be deleted",
178
- );
179
-
180
- // Verify squash commit on main
181
- const log = run("git log --oneline -3", tempDir);
182
- assert.ok(
183
- log.includes("M001"),
184
- "squash commit on main should reference M001",
185
- );
186
-
187
- assert.ok(mergeResult.commitMessage.length > 0, "commit message returned");
188
- } finally {
137
+ t.after(() => {
189
138
  process.chdir(savedCwd);
190
139
  if (tempDir && existsSync(tempDir)) {
191
- rmSync(tempDir, { recursive: true, force: true });
140
+ rmSync(tempDir, { recursive: true, force: true });
192
141
  }
193
- }
142
+ });
143
+
144
+ tempDir = createTempRepo();
145
+
146
+ // Set up a single milestone
147
+ createMilestoneArtifacts(tempDir, "M001");
148
+ run("git add .", tempDir);
149
+ run('git commit -m "add milestone"', tempDir);
150
+
151
+ // Create worktree and simulate work
152
+ const wt = createAutoWorktree(tempDir, "M001");
153
+ assert.ok(isInAutoWorktree(tempDir), "should be in auto-worktree");
154
+
155
+ writeFileSync(join(wt, "feature.ts"), "export const feature = true;\n");
156
+ run("git add .", wt);
157
+ run('git commit -m "feat(M001): add feature"', wt);
158
+
159
+ // Simulate the fix: merge before stopping (what the "all complete" path now does)
160
+ const roadmapPath = join(
161
+ tempDir,
162
+ ".gsd",
163
+ "milestones",
164
+ "M001",
165
+ "M001-ROADMAP.md",
166
+ );
167
+ const roadmapContent = readFileSync(roadmapPath, "utf-8");
168
+ const mergeResult = mergeMilestoneToMain(tempDir, "M001", roadmapContent);
169
+
170
+ // Verify work is on main
171
+ assert.ok(
172
+ existsSync(join(tempDir, "feature.ts")),
173
+ "feature.ts should be on main after merge",
174
+ );
175
+ assert.equal(process.cwd(), tempDir, "cwd restored to project root");
176
+ assert.ok(!isInAutoWorktree(tempDir), "no longer in auto-worktree");
177
+ assert.equal(getAutoWorktreeOriginalBase(), null, "originalBase cleared");
178
+
179
+ // Verify milestone branch was cleaned up
180
+ const branches = run("git branch", tempDir);
181
+ assert.ok(
182
+ !branches.includes("milestone/M001"),
183
+ "milestone branch should be deleted",
184
+ );
185
+
186
+ // Verify squash commit on main
187
+ const log = run("git log --oneline -3", tempDir);
188
+ assert.ok(
189
+ log.includes("M001"),
190
+ "squash commit on main should reference M001",
191
+ );
192
+
193
+ assert.ok(mergeResult.commitMessage.length > 0, "commit message returned");
194
194
  });
195
195
 
196
196
  // ─── Integration: last of multiple milestones completes → merged ─────────────
197
197
 
198
- test("last milestone worktree is merged when it's the final one (#962)", () => {
198
+ test("last milestone worktree is merged when it's the final one (#962)", (t) => {
199
199
  const savedCwd = process.cwd();
200
200
  let tempDir = "";
201
201
 
202
- try {
203
- tempDir = createTempRepo();
204
-
205
- // Set up two milestones
206
- createMilestoneArtifacts(tempDir, "M001");
207
- createMilestoneArtifacts(tempDir, "M002");
208
- run("git add .", tempDir);
209
- run('git commit -m "add milestones"', tempDir);
210
-
211
- // Complete M001 first (merge it)
212
- const wt1 = createAutoWorktree(tempDir, "M001");
213
- writeFileSync(join(wt1, "m001-work.ts"), "export const m001 = true;\n");
214
- run("git add .", wt1);
215
- run('git commit -m "feat(M001): m001 work"', wt1);
216
- const roadmap1 = readFileSync(
217
- join(tempDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md"),
218
- "utf-8",
219
- );
220
- mergeMilestoneToMain(tempDir, "M001", roadmap1);
221
-
222
- // Now complete M002 (the LAST milestone — this is the #962 scenario)
223
- const wt2 = createAutoWorktree(tempDir, "M002");
224
- writeFileSync(join(wt2, "m002-work.ts"), "export const m002 = true;\n");
225
- run("git add .", wt2);
226
- run('git commit -m "feat(M002): m002 work"', wt2);
227
- const roadmap2 = readFileSync(
228
- join(tempDir, ".gsd", "milestones", "M002", "M002-ROADMAP.md"),
229
- "utf-8",
230
- );
231
- mergeMilestoneToMain(tempDir, "M002", roadmap2);
232
-
233
- // Both features should now be on main
234
- assert.ok(existsSync(join(tempDir, "m001-work.ts")), "M001 work on main");
235
- assert.ok(existsSync(join(tempDir, "m002-work.ts")), "M002 work on main");
236
- assert.ok(!isInAutoWorktree(tempDir), "not in worktree after final merge");
237
-
238
- // Both milestone branches should be cleaned up
239
- const branches = run("git branch", tempDir);
240
- assert.ok(!branches.includes("milestone/M001"), "M001 branch deleted");
241
- assert.ok(!branches.includes("milestone/M002"), "M002 branch deleted");
242
- } finally {
202
+ t.after(() => {
243
203
  process.chdir(savedCwd);
244
204
  if (tempDir && existsSync(tempDir)) {
245
- rmSync(tempDir, { recursive: true, force: true });
205
+ rmSync(tempDir, { recursive: true, force: true });
246
206
  }
247
- }
207
+ });
208
+
209
+ tempDir = createTempRepo();
210
+
211
+ // Set up two milestones
212
+ createMilestoneArtifacts(tempDir, "M001");
213
+ createMilestoneArtifacts(tempDir, "M002");
214
+ run("git add .", tempDir);
215
+ run('git commit -m "add milestones"', tempDir);
216
+
217
+ // Complete M001 first (merge it)
218
+ const wt1 = createAutoWorktree(tempDir, "M001");
219
+ writeFileSync(join(wt1, "m001-work.ts"), "export const m001 = true;\n");
220
+ run("git add .", wt1);
221
+ run('git commit -m "feat(M001): m001 work"', wt1);
222
+ const roadmap1 = readFileSync(
223
+ join(tempDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md"),
224
+ "utf-8",
225
+ );
226
+ mergeMilestoneToMain(tempDir, "M001", roadmap1);
227
+
228
+ // Now complete M002 (the LAST milestone — this is the #962 scenario)
229
+ const wt2 = createAutoWorktree(tempDir, "M002");
230
+ writeFileSync(join(wt2, "m002-work.ts"), "export const m002 = true;\n");
231
+ run("git add .", wt2);
232
+ run('git commit -m "feat(M002): m002 work"', wt2);
233
+ const roadmap2 = readFileSync(
234
+ join(tempDir, ".gsd", "milestones", "M002", "M002-ROADMAP.md"),
235
+ "utf-8",
236
+ );
237
+ mergeMilestoneToMain(tempDir, "M002", roadmap2);
238
+
239
+ // Both features should now be on main
240
+ assert.ok(existsSync(join(tempDir, "m001-work.ts")), "M001 work on main");
241
+ assert.ok(existsSync(join(tempDir, "m002-work.ts")), "M002 work on main");
242
+ assert.ok(!isInAutoWorktree(tempDir), "not in worktree after final merge");
243
+
244
+ // Both milestone branches should be cleaned up
245
+ const branches = run("git branch", tempDir);
246
+ assert.ok(!branches.includes("milestone/M001"), "M001 branch deleted");
247
+ assert.ok(!branches.includes("milestone/M002"), "M002 branch deleted");
248
248
  });