gsd-pi 2.45.0 → 2.46.0-dev.cc9d310

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 (347) hide show
  1. package/dist/help-text.js +1 -1
  2. package/dist/loader.js +34 -0
  3. package/dist/resources/extensions/gsd/auto/phases.js +27 -42
  4. package/dist/resources/extensions/gsd/auto/run-unit.js +6 -3
  5. package/dist/resources/extensions/gsd/auto/session.js +0 -11
  6. package/dist/resources/extensions/gsd/auto-artifact-paths.js +112 -0
  7. package/dist/resources/extensions/gsd/auto-post-unit.js +25 -96
  8. package/dist/resources/extensions/gsd/auto-start.js +2 -3
  9. package/dist/resources/extensions/gsd/auto-worktree.js +5 -4
  10. package/dist/resources/extensions/gsd/auto.js +12 -57
  11. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +15 -12
  12. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +18 -0
  13. package/dist/resources/extensions/gsd/commands/context.js +0 -4
  14. package/dist/resources/extensions/gsd/commands/handlers/parallel.js +1 -1
  15. package/dist/resources/extensions/gsd/crash-recovery.js +2 -4
  16. package/dist/resources/extensions/gsd/dashboard-overlay.js +0 -44
  17. package/dist/resources/extensions/gsd/db-writer.js +9 -9
  18. package/dist/resources/extensions/gsd/doctor-checks.js +167 -2
  19. package/dist/resources/extensions/gsd/doctor.js +5 -3
  20. package/dist/resources/extensions/gsd/gsd-db.js +16 -3
  21. package/dist/resources/extensions/gsd/guided-flow.js +1 -2
  22. package/dist/resources/extensions/gsd/parallel-merge.js +1 -1
  23. package/dist/resources/extensions/gsd/parallel-orchestrator.js +5 -18
  24. package/dist/resources/extensions/gsd/preferences-types.js +2 -2
  25. package/dist/resources/extensions/gsd/preferences.js +8 -4
  26. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +21 -8
  27. package/dist/resources/extensions/gsd/prompts/complete-slice.md +10 -23
  28. package/dist/resources/extensions/gsd/prompts/discuss.md +2 -2
  29. package/dist/resources/extensions/gsd/prompts/execute-task.md +5 -15
  30. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  31. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  32. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  33. package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  34. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  35. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -2
  36. package/dist/resources/extensions/gsd/prompts/queue.md +2 -2
  37. package/dist/resources/extensions/gsd/prompts/quick-task.md +2 -0
  38. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
  39. package/dist/resources/extensions/gsd/prompts/research-slice.md +3 -3
  40. package/dist/resources/extensions/gsd/prompts/rethink.md +7 -2
  41. package/dist/resources/extensions/gsd/prompts/system.md +1 -1
  42. package/dist/resources/extensions/gsd/session-lock.js +1 -3
  43. package/dist/resources/extensions/gsd/state.js +7 -0
  44. package/dist/resources/extensions/gsd/sync-lock.js +89 -0
  45. package/dist/resources/extensions/gsd/tools/complete-milestone.js +61 -11
  46. package/dist/resources/extensions/gsd/tools/complete-slice.js +56 -11
  47. package/dist/resources/extensions/gsd/tools/complete-task.js +50 -2
  48. package/dist/resources/extensions/gsd/tools/plan-milestone.js +37 -1
  49. package/dist/resources/extensions/gsd/tools/plan-slice.js +30 -1
  50. package/dist/resources/extensions/gsd/tools/plan-task.js +27 -1
  51. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +32 -2
  52. package/dist/resources/extensions/gsd/tools/reopen-slice.js +86 -0
  53. package/dist/resources/extensions/gsd/tools/reopen-task.js +90 -0
  54. package/dist/resources/extensions/gsd/tools/replan-slice.js +32 -2
  55. package/dist/resources/extensions/gsd/unit-ownership.js +85 -0
  56. package/dist/resources/extensions/gsd/workflow-events.js +102 -0
  57. package/dist/resources/extensions/gsd/workflow-logger.js +193 -0
  58. package/dist/resources/extensions/gsd/workflow-manifest.js +244 -0
  59. package/dist/resources/extensions/gsd/workflow-migration.js +280 -0
  60. package/dist/resources/extensions/gsd/workflow-projections.js +373 -0
  61. package/dist/resources/extensions/gsd/workflow-reconcile.js +411 -0
  62. package/dist/resources/extensions/gsd/worktree-manager.js +4 -3
  63. package/dist/resources/extensions/gsd/worktree-resolver.js +37 -0
  64. package/dist/resources/extensions/gsd/write-intercept.js +84 -0
  65. package/dist/resources/extensions/voice/index.js +11 -16
  66. package/dist/resources/extensions/voice/linux-ready.js +67 -0
  67. package/dist/web/standalone/.next/BUILD_ID +1 -1
  68. package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
  69. package/dist/web/standalone/.next/build-manifest.json +3 -3
  70. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  71. package/dist/web/standalone/.next/required-server-files.json +3 -3
  72. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  73. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  74. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  75. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  83. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  84. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  85. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  86. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  87. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  89. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  99. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  137. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  143. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  157. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  159. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  161. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  163. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/index.html +1 -1
  173. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  174. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  175. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  176. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  177. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  178. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  179. package/dist/web/standalone/.next/server/app/page.js +2 -2
  180. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app-paths-manifest.json +17 -17
  182. package/dist/web/standalone/.next/server/chunks/229.js +1 -1
  183. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  184. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/middleware.js +2 -2
  186. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  188. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  189. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  190. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  191. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  192. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  193. package/dist/web/standalone/.next/static/chunks/app/page-6654a8cca61a3d1c.js +1 -0
  194. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  195. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  196. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  197. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  198. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  199. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  200. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  201. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  202. package/dist/web/standalone/server.js +1 -1
  203. package/package.json +2 -1
  204. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
  205. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +2 -0
  206. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  207. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -1
  208. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  209. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +4 -0
  211. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -1
  212. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +10 -5
  213. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -1
  214. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts +2 -0
  215. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts.map +1 -0
  216. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js +185 -0
  217. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js.map +1 -0
  218. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +239 -10
  219. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  220. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +2 -1
  221. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  222. package/packages/pi-coding-agent/dist/core/model-registry.js +20 -2
  223. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  224. package/packages/pi-coding-agent/dist/core/package-commands.test.js +206 -195
  225. package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -1
  226. package/packages/pi-coding-agent/package.json +1 -1
  227. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +2 -0
  228. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -1
  229. package/packages/pi-coding-agent/src/core/lifecycle-hooks.test.ts +227 -0
  230. package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +11 -5
  231. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +297 -11
  232. package/packages/pi-coding-agent/src/core/model-registry.ts +30 -3
  233. package/packages/pi-coding-agent/src/core/package-commands.test.ts +227 -205
  234. package/pkg/package.json +1 -1
  235. package/src/resources/extensions/gsd/auto/loop-deps.ts +0 -19
  236. package/src/resources/extensions/gsd/auto/phases.ts +24 -44
  237. package/src/resources/extensions/gsd/auto/run-unit.ts +6 -3
  238. package/src/resources/extensions/gsd/auto/session.ts +0 -18
  239. package/src/resources/extensions/gsd/auto-artifact-paths.ts +131 -0
  240. package/src/resources/extensions/gsd/auto-dashboard.ts +0 -1
  241. package/src/resources/extensions/gsd/auto-post-unit.ts +25 -106
  242. package/src/resources/extensions/gsd/auto-start.ts +1 -3
  243. package/src/resources/extensions/gsd/auto-worktree.ts +8 -5
  244. package/src/resources/extensions/gsd/auto.ts +7 -83
  245. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +15 -12
  246. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +22 -0
  247. package/src/resources/extensions/gsd/commands/context.ts +0 -5
  248. package/src/resources/extensions/gsd/commands/handlers/parallel.ts +1 -1
  249. package/src/resources/extensions/gsd/crash-recovery.ts +1 -5
  250. package/src/resources/extensions/gsd/dashboard-overlay.ts +0 -50
  251. package/src/resources/extensions/gsd/db-writer.ts +9 -17
  252. package/src/resources/extensions/gsd/doctor-checks.ts +180 -2
  253. package/src/resources/extensions/gsd/doctor-types.ts +7 -1
  254. package/src/resources/extensions/gsd/doctor.ts +6 -3
  255. package/src/resources/extensions/gsd/gsd-db.ts +16 -3
  256. package/src/resources/extensions/gsd/guided-flow.ts +1 -2
  257. package/src/resources/extensions/gsd/journal.ts +6 -1
  258. package/src/resources/extensions/gsd/parallel-merge.ts +1 -1
  259. package/src/resources/extensions/gsd/parallel-orchestrator.ts +5 -21
  260. package/src/resources/extensions/gsd/preferences-types.ts +2 -2
  261. package/src/resources/extensions/gsd/preferences.ts +7 -3
  262. package/src/resources/extensions/gsd/prompts/complete-milestone.md +21 -8
  263. package/src/resources/extensions/gsd/prompts/complete-slice.md +10 -23
  264. package/src/resources/extensions/gsd/prompts/discuss.md +2 -2
  265. package/src/resources/extensions/gsd/prompts/execute-task.md +5 -15
  266. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  267. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  268. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  269. package/src/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  270. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  271. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -2
  272. package/src/resources/extensions/gsd/prompts/queue.md +2 -2
  273. package/src/resources/extensions/gsd/prompts/quick-task.md +2 -0
  274. package/src/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
  275. package/src/resources/extensions/gsd/prompts/research-slice.md +3 -3
  276. package/src/resources/extensions/gsd/prompts/rethink.md +7 -2
  277. package/src/resources/extensions/gsd/prompts/system.md +1 -1
  278. package/src/resources/extensions/gsd/session-lock.ts +0 -4
  279. package/src/resources/extensions/gsd/state.ts +8 -0
  280. package/src/resources/extensions/gsd/sync-lock.ts +94 -0
  281. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +5 -13
  282. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +6 -10
  283. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +96 -0
  284. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +264 -228
  285. package/src/resources/extensions/gsd/tests/complete-task.test.ts +317 -250
  286. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +2 -8
  287. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +0 -3
  288. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
  289. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +1 -1
  290. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +15 -24
  291. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -3
  292. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  293. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  294. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +1 -1
  295. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +8 -9
  296. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +42 -3
  297. package/src/resources/extensions/gsd/tests/parallel-budget-atomicity.test.ts +0 -1
  298. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +0 -7
  299. package/src/resources/extensions/gsd/tests/parallel-merge.test.ts +7 -8
  300. package/src/resources/extensions/gsd/tests/parallel-orchestration.test.ts +20 -24
  301. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +0 -2
  302. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +9 -6
  303. package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +171 -0
  304. package/src/resources/extensions/gsd/tests/preferences.test.ts +7 -9
  305. package/src/resources/extensions/gsd/tests/projection-regression.test.ts +174 -0
  306. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +15 -14
  307. package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +155 -0
  308. package/src/resources/extensions/gsd/tests/reopen-task.test.ts +165 -0
  309. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +1 -4
  310. package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +2 -3
  311. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +122 -0
  312. package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +175 -0
  313. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +205 -0
  314. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +275 -0
  315. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +186 -0
  316. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +171 -0
  317. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +220 -0
  318. package/src/resources/extensions/gsd/tests/write-intercept.test.ts +76 -0
  319. package/src/resources/extensions/gsd/tools/complete-milestone.ts +74 -11
  320. package/src/resources/extensions/gsd/tools/complete-slice.ts +68 -11
  321. package/src/resources/extensions/gsd/tools/complete-task.ts +63 -1
  322. package/src/resources/extensions/gsd/tools/plan-milestone.ts +45 -0
  323. package/src/resources/extensions/gsd/tools/plan-slice.ts +38 -0
  324. package/src/resources/extensions/gsd/tools/plan-task.ts +35 -1
  325. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +39 -1
  326. package/src/resources/extensions/gsd/tools/reopen-slice.ts +125 -0
  327. package/src/resources/extensions/gsd/tools/reopen-task.ts +129 -0
  328. package/src/resources/extensions/gsd/tools/replan-slice.ts +38 -1
  329. package/src/resources/extensions/gsd/types.ts +8 -0
  330. package/src/resources/extensions/gsd/unit-ownership.ts +104 -0
  331. package/src/resources/extensions/gsd/workflow-events.ts +154 -0
  332. package/src/resources/extensions/gsd/workflow-logger.ts +243 -0
  333. package/src/resources/extensions/gsd/workflow-manifest.ts +334 -0
  334. package/src/resources/extensions/gsd/workflow-migration.ts +345 -0
  335. package/src/resources/extensions/gsd/workflow-projections.ts +425 -0
  336. package/src/resources/extensions/gsd/workflow-reconcile.ts +503 -0
  337. package/src/resources/extensions/gsd/worktree-manager.ts +4 -9
  338. package/src/resources/extensions/gsd/worktree-resolver.ts +37 -0
  339. package/src/resources/extensions/gsd/write-intercept.ts +90 -0
  340. package/src/resources/extensions/voice/index.ts +11 -21
  341. package/src/resources/extensions/voice/linux-ready.ts +87 -0
  342. package/src/resources/extensions/voice/tests/linux-ready.test.ts +124 -0
  343. package/dist/web/standalone/.next/static/chunks/app/page-12dd5ece0df4badc.js +0 -1
  344. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  345. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  346. /package/dist/web/standalone/.next/static/{wUzEX1U3CmFcMry2SUDJn → ZIDqryyYDroh_8AnaAOSG}/_buildManifest.js +0 -0
  347. /package/dist/web/standalone/.next/static/{wUzEX1U3CmFcMry2SUDJn → ZIDqryyYDroh_8AnaAOSG}/_ssgManifest.js +0 -0
@@ -105,6 +105,6 @@ Once the user confirms depth:
105
105
 
106
106
  1. Use the **Context** output template below
107
107
  2. `mkdir -p` the milestone directory if needed
108
- 3. Write `{{milestoneId}}-CONTEXT.md` — preserve the user's exact terminology, emphasis, and framing. Do not paraphrase nuance into generic summaries. The context file is downstream agents' only window into this conversation.
108
+ 3. Call `gsd_summary_save` with `milestone_id: {{milestoneId}}`, `artifact_type: "CONTEXT"`, and the full context markdown as `content`the tool writes the file to disk and persists to DB. Preserve the user's exact terminology, emphasis, and framing in the content. Do not paraphrase nuance into generic summaries. The context file is downstream agents' only window into this conversation.
109
109
  4. {{commitInstruction}}
110
110
  5. Say exactly: `"{{milestoneId}} context written."` — nothing else.
@@ -48,7 +48,7 @@ Once the user is ready to wrap up:
48
48
 
49
49
  1. Use the **Slice Context** output template below
50
50
  2. `mkdir -p {{sliceDirPath}}`
51
- 3. Write `{{contextPath}}` — use the template structure, filling in:
51
+ 3. Call `gsd_summary_save` with `milestone_id: {{milestoneId}}`, `slice_id: {{sliceId}}`, `artifact_type: "CONTEXT"`, and the context as `content` the tool writes the file to disk and persists to DB. Use the template structure, filling in:
52
52
  - **Goal** — one sentence: what this slice delivers
53
53
  - **Why this Slice** — why now, what it unblocks
54
54
  - **Scope / In Scope** — what was confirmed in scope during the interview
@@ -1,3 +1,3 @@
1
- Plan slice {{sliceId}} ("{{sliceTitle}}") of milestone {{milestoneId}}. Read `.gsd/DECISIONS.md` if it exists — respect existing decisions. Read `.gsd/REQUIREMENTS.md` if it exists — identify which Active requirements the roadmap says this slice owns or supports, and ensure the plan delivers them. Read the roadmap boundary map, any existing context/research files, and dependency summaries. Use the **Slice Plan** and **Task Plan** output templates below. Decompose into tasks with must-haves. Fill the `Proof Level` and `Integration Closure` sections truthfully so the plan says what class of proof this slice really delivers and what end-to-end wiring still remains. Write `{{sliceId}}-PLAN.md` and individual `T##-PLAN.md` files in the `tasks/` subdirectory. If planning produces structural decisions, append them to `.gsd/DECISIONS.md`. {{skillActivation}} Before committing, self-audit the plan: every must-have maps to at least one task, every task has complete sections (steps, must-haves, verification, observability impact, inputs, and expected output), task ordering is consistent with no circular references, every pair of artifacts that must connect has an explicit wiring step, task scope targets 2–5 steps and 3–8 files (6–8 steps or 8–10 files — consider splitting; 10+ steps or 12+ files — must split), the plan honors locked decisions from context/research/decisions artifacts, the proof-level wording does not overclaim live integration if only fixture/contract proof is planned, every Active requirement this slice owns has at least one task with verification that proves it is met, and every task produces real user-facing progress — if the slice has a UI surface at least one task builds the real UI, if it has an API at least one task connects it to a real data source, and showing the completed result to a non-technical stakeholder would demonstrate real product progress rather than developer artifacts.
1
+ Plan slice {{sliceId}} ("{{sliceTitle}}") of milestone {{milestoneId}}. Read `.gsd/DECISIONS.md` if it exists — respect existing decisions. Read `.gsd/REQUIREMENTS.md` if it exists — identify which Active requirements the roadmap says this slice owns or supports, and ensure the plan delivers them. Read the roadmap boundary map, any existing context/research files, and dependency summaries. Use the **Slice Plan** and **Task Plan** output templates below. Decompose into tasks with must-haves. Fill the `Proof Level` and `Integration Closure` sections truthfully so the plan says what class of proof this slice really delivers and what end-to-end wiring still remains. Call `gsd_plan_slice` to persist the slice plan — the tool writes `{{sliceId}}-PLAN.md` and individual `T##-PLAN.md` files to disk and persists to DB. Do **not** write plan files manually — use the DB-backed tool so state stays consistent. If planning produces structural decisions, call `gsd_decision_save` for each — the tool auto-assigns IDs and regenerates `.gsd/DECISIONS.md` automatically. {{skillActivation}} Before finishing, self-audit the plan: every must-have maps to at least one task, every task has complete sections (steps, must-haves, verification, observability impact, inputs, and expected output), task ordering is consistent with no circular references, every pair of artifacts that must connect has an explicit wiring step, task scope targets 2–5 steps and 3–8 files (6–8 steps or 8–10 files — consider splitting; 10+ steps or 12+ files — must split), the plan honors locked decisions from context/research/decisions artifacts, the proof-level wording does not overclaim live integration if only fixture/contract proof is planned, every Active requirement this slice owns has at least one task with verification that proves it is met, and every task produces real user-facing progress — if the slice has a UI surface at least one task builds the real UI, if it has an API at least one task connects it to a real data source, and showing the completed result to a non-technical stakeholder would demonstrate real product progress rather than developer artifacts.
2
2
 
3
3
  {{inlinedTemplates}}
@@ -1,4 +1,4 @@
1
- Research slice {{sliceId}} ("{{sliceTitle}}") of milestone {{milestoneId}}. Read `.gsd/DECISIONS.md` if it exists — respect existing decisions, don't contradict them. Read `.gsd/REQUIREMENTS.md` if it exists — identify which Active requirements this slice owns or supports and target research toward risks, unknowns, and constraints that could affect delivery of those requirements. {{skillActivation}} Explore the relevant code — use `rg`/`find` for targeted reads, or `scout` if the area is broad or unfamiliar. Check libraries with `resolve_library`/`get_library_docs` — skip this for libraries already used in the codebase. Use the **Research** output template below. Write `{{sliceId}}-RESEARCH.md` in the slice directory.
1
+ Research slice {{sliceId}} ("{{sliceTitle}}") of milestone {{milestoneId}}. Read `.gsd/DECISIONS.md` if it exists — respect existing decisions, don't contradict them. Read `.gsd/REQUIREMENTS.md` if it exists — identify which Active requirements this slice owns or supports and target research toward risks, unknowns, and constraints that could affect delivery of those requirements. {{skillActivation}} Explore the relevant code — use `rg`/`find` for targeted reads, or `scout` if the area is broad or unfamiliar. Check libraries with `resolve_library`/`get_library_docs` — skip this for libraries already used in the codebase. Use the **Research** output template below. Call `gsd_summary_save` with `milestone_id: {{milestoneId}}`, `slice_id: {{sliceId}}`, `artifact_type: "RESEARCH"`, and the research content — the tool writes the file to disk and persists to DB.
2
2
 
3
3
  **You are the scout.** A planner agent reads your output in a fresh context to decompose this slice into tasks. Write for the planner — surface key files, where the work divides naturally, what to build first, and how to verify. If the research doc is vague, the planner re-explores code you already read. If it's precise, the planner decomposes immediately.
4
4
 
@@ -48,7 +48,7 @@ Then:
48
48
  3. Create the roadmap: decompose into demoable vertical slices — as many as the work genuinely needs, no more. A simple feature might be 1 slice. Don't decompose for decomposition's sake.
49
49
  4. Order by risk (high-risk first)
50
50
  5. Call `gsd_plan_milestone` to persist the milestone planning fields and slice rows in the DB-backed planning path. Do **not** write `{{outputPath}}`, `ROADMAP.md`, or other planning artifacts manually — the planning tool owns roadmap rendering and persistence.
51
- 6. If planning produced structural decisions (e.g. slice ordering rationale, technology choices, scope exclusions), append them to `.gsd/DECISIONS.md` (use the **Decisions** output template from the inlined context above if the file doesn't exist yet)
51
+ 6. If planning produced structural decisions (e.g. slice ordering rationale, technology choices, scope exclusions), call `gsd_decision_save` for each decision the tool auto-assigns IDs and regenerates `.gsd/DECISIONS.md` automatically.
52
52
 
53
53
  ## Requirement Mapping Rules
54
54
 
@@ -72,9 +72,11 @@ Then:
72
72
  - **Key links planned:** For every pair of artifacts that must connect, there is an explicit step that wires them.
73
73
  - **Scope sanity:** Target 2–5 steps and 3–8 files per task. 10+ steps or 12+ files — must split. Each task must be completable in a single fresh context window.
74
74
  - **Feature completeness:** Every task produces real, user-facing progress — not just internal scaffolding.
75
- 8. If planning produced structural decisions, append them to `.gsd/DECISIONS.md`
76
- 9. {{commitInstruction}}
75
+ 10. If planning produced structural decisions, append them to `.gsd/DECISIONS.md`
76
+ 11. {{commitInstruction}}
77
77
 
78
78
  The slice directory and tasks/ subdirectory already exist. Do NOT mkdir. All work stays in your working directory: `{{workingDirectory}}`.
79
79
 
80
+ **You MUST write the file `{{outputPath}}` before finishing.**
81
+
80
82
  When done, say: "Slice {{sliceId}} planned."
@@ -8,7 +8,7 @@ Before asking "What do you want to add?", check the existing milestones context
8
8
 
9
9
  1. Tell the user which milestones have draft contexts and briefly summarize what each draft contains (read the draft file).
10
10
  2. Use `ask_user_questions` to ask per-draft milestone:
11
- - **"Discuss now"** — Treat this draft as the primary topic. Read the draft content, use it as seed material, and conduct a focused discussion following the standard discussion flow (reflection → investigation → questioning → depth verification → requirements → roadmap). After the discussion, write the full CONTEXT.md and delete the `CONTEXT-DRAFT.md` file. The milestone is then ready for auto-planning.
11
+ - **"Discuss now"** — Treat this draft as the primary topic. Read the draft content, use it as seed material, and conduct a focused discussion following the standard discussion flow (reflection → investigation → questioning → depth verification → requirements → roadmap). After the discussion, call `gsd_summary_save` with the milestone ID and `artifact_type: "CONTEXT"` to write the full context then delete the `CONTEXT-DRAFT.md` file. The milestone is then ready for auto-planning.
12
12
  - **"Leave for later"** — Keep the draft as-is. The user will discuss it in a future session. Auto-mode will continue to pause when it reaches this milestone.
13
13
  3. Handle all draft discussions before proceeding to new queue work.
14
14
  4. If no drafts exist in the context, skip this section entirely and proceed to "What do you want to add?"
@@ -108,7 +108,7 @@ The user confirms or corrects before you write. One depth verification per miles
108
108
  Once the user is satisfied, in a single pass for **each** new milestone:
109
109
 
110
110
  1. Call `gsd_milestone_generate_id` to get the milestone ID — never invent milestone IDs manually. Then `mkdir -p .gsd/milestones/<ID>/slices`.
111
- 2. Write `.gsd/milestones/<ID>/<ID>-CONTEXT.md` — use the **Context** output template below. Capture intent, scope, risks, constraints, integration points, and relevant requirements. Mark the status as "Queued — pending auto-mode execution." **If this milestone depends on other milestones, add YAML frontmatter with `depends_on`:**
111
+ 2. Call `gsd_summary_save` with `milestone_id: <ID>`, `artifact_type: "CONTEXT"`, and the full context markdown as `content`the tool computes the file path and persists to both DB and disk. Capture intent, scope, risks, constraints, integration points, and relevant requirements in the content. Mark the status as "Queued — pending auto-mode execution." **If this milestone depends on other milestones, include YAML frontmatter with `depends_on` in the content:**
112
112
  ```yaml
113
113
  ---
114
114
  depends_on: [M001, M002]
@@ -21,7 +21,9 @@ You are executing a GSD quick task — a lightweight, focused unit of work outsi
21
21
  - Use conventional commit messages (feat:, fix:, refactor:, etc.)
22
22
  - Stage only relevant files — never commit secrets or runtime files.
23
23
  - Commit logical units separately if the task involves distinct changes.
24
+ - Quick tasks run outside the auto-mode lifecycle — there is no system auto-commit, so commit directly here.
24
25
  7. Write a brief summary to `{{summaryPath}}`:
26
+ - Quick tasks operate outside the milestone/slice/task DB structure, so `gsd_summary_save` (which requires a `milestone_id`) cannot be used here. Write the file directly.
25
27
 
26
28
  ```markdown
27
29
  # Quick Task: {{description}}
@@ -26,7 +26,7 @@ You are executing **multiple tasks in parallel** for this slice. The task graph
26
26
  2. **Wait for all subagents** to complete.
27
27
  3. **Verify each dispatched task's outputs** — check that expected files were created/modified, that verification commands pass where applicable, and that each task wrote its own `T##-SUMMARY.md`.
28
28
  4. **Do not rewrite successful task summaries or duplicate completion tool calls.** Treat a subagent-written summary as authoritative for that task.
29
- 5. **If a failed task produced no summary, write a recovery summary for that task** with `blocker_discovered: true`, clear failure details, and leave the task unchecked so replan/retry has an authoritative record.
29
+ 5. **If a failed task produced no summary, call `gsd_summary_save`** with `milestone_id: {{milestoneId}}`, `slice_id: {{sliceId}}`, the failed task's `task_id`, and `artifact_type: "SUMMARY"` — include `blocker_discovered: true` and clear failure details in the `content`. Do NOT call `gsd_task_complete` for the failed task leave it uncompleted so replan/retry has an authoritative record.
30
30
  6. **Preserve successful sibling tasks exactly as they landed.** Do not roll back good work because another parallel task failed.
31
31
  7. **Do NOT create a batch commit.** The surrounding unit lifecycle owns commits; this parent batch agent should not invent a second commit layer.
32
32
  8. **Report the batch outcome** — which tasks succeeded, which failed, and any output collisions or dependency surprises.
@@ -48,10 +48,10 @@ Research what this slice needs. Narrate key findings and surprises as you go —
48
48
  4. Use `resolve_library` / `get_library_docs` for unfamiliar libraries — skip this for libraries already used in the codebase
49
49
  5. **Web search budget:** You have a limited budget of web searches (max ~15 per session). Use them strategically — prefer `resolve_library` / `get_library_docs` for library documentation. Do NOT repeat the same or similar queries. If a search didn't find what you need, rephrase once or move on. Target 3-5 total web searches for a typical research unit.
50
50
  6. Use the **Research** output template from the inlined context above — include only sections that have real content. The template is already inlined above; do NOT attempt to read any template file from disk (there is no `templates/SLICE-RESEARCH.md` — the correct template is already present in this prompt).
51
- 7. Write `{{outputPath}}`
51
+ 7. Call `gsd_summary_save` with `milestone_id: {{milestoneId}}`, `slice_id: {{sliceId}}`, `artifact_type: "RESEARCH"`, and the full research markdown as `content` — the tool computes the file path and persists to both DB and disk.
52
52
 
53
- The slice directory already exists at `{{slicePath}}/`. Do NOT mkdir — just write the file.
53
+ The slice directory already exists at `{{slicePath}}/`. Do NOT mkdir.
54
54
 
55
- **You MUST write the file `{{outputPath}}` before finishing.**
55
+ **You MUST call `gsd_summary_save` with the research content before finishing.**
56
56
 
57
57
  When done, say: "Slice {{sliceId}} researched."
@@ -16,6 +16,11 @@ You are a project reorganization assistant for a GSD (Get Shit Done) project. Th
16
16
 
17
17
  ## Supported Operations
18
18
 
19
+ <!-- NOTE: Park, unpark, reorder, discard, and dependency-update operations are intentionally
20
+ file-based. No gsd_* tool API exists for these milestone-lifecycle mutations yet.
21
+ The single-writer DB tools (gsd_plan_milestone, gsd_complete_milestone, etc.) own
22
+ create and complete; queue management is file-driven until tool support is added. -->
23
+
19
24
  ### Reorder milestones
20
25
  Change execution order of pending/active milestones. Write `.gsd/QUEUE-ORDER.json`:
21
26
  ```json
@@ -44,7 +49,7 @@ Remove the `{ID}-PARKED.md` file from the milestone directory to reactivate it.
44
49
  **Permanently** delete a milestone directory and prune it from QUEUE-ORDER.json. **Always confirm with the user before discarding.** Warn explicitly if the milestone has completed work.
45
50
 
46
51
  ### Add a new milestone
47
- Use the `gsd_milestone_generate_id` tool to get the next ID, then write a `{ID}-CONTEXT.md` file in `.gsd/milestones/{ID}/` with scope, goals, and success criteria. Update QUEUE-ORDER.json to place it at the desired position.
52
+ Use the `gsd_milestone_generate_id` tool to get the next ID, then call `gsd_summary_save` with `milestone_id: {ID}`, `artifact_type: "CONTEXT"`, and the scope/goals/success criteria as `content` — the tool writes the context file to disk and persists to DB. Update QUEUE-ORDER.json to place it at the desired position.
48
53
 
49
54
  ### Update dependencies
50
55
  Edit `depends_on` in the YAML frontmatter of a milestone's `{ID}-CONTEXT.md` file. For example:
@@ -75,4 +80,4 @@ If a proposed order would violate constraints, explain the issue and suggest alt
75
80
  - Do NOT park completed milestones — it would corrupt dependency satisfaction
76
81
  - Park is preferred over discard when a milestone has any completed work
77
82
  - Always persist queue order changes to `.gsd/QUEUE-ORDER.json`
78
- - After changes, run `git add .gsd/ && git commit -m "docs: rethink milestone order"` to persist
83
+ - After changes, run `git add .gsd/ && git commit -m "docs(gsd): rethink milestone plan"` to persist (rethink runs interactively outside auto-mode, so no system auto-commit)
@@ -112,7 +112,7 @@ In all modes, slices commit sequentially on the active branch; there are no per-
112
112
  - **Milestones** are major project phases (M001, M002, ...)
113
113
  - **Slices** are demoable vertical increments (S01, S02, ...) ordered by risk. After each slice completes, the roadmap is reassessed before the next slice begins.
114
114
  - **Tasks** are single-context-window units of work (T01, T02, ...)
115
- - Checkboxes in roadmap and plan files track completion (`[ ]` → `[x]`)
115
+ - Checkboxes in roadmap and plan files track completion (`[ ]` → `[x]`) — toggled automatically by gsd_* tools, never edited manually
116
116
  - Summaries compress prior work - read them instead of re-reading all task details
117
117
  - `STATE.md` is a system-managed status file — rebuilt automatically after each unit completes
118
118
 
@@ -32,7 +32,6 @@ export interface SessionLockData {
32
32
  unitType: string;
33
33
  unitId: string;
34
34
  unitStartedAt: string;
35
- completedUnits: number;
36
35
  sessionFile?: string;
37
36
  }
38
37
 
@@ -205,7 +204,6 @@ export function acquireSessionLock(basePath: string): SessionLockResult {
205
204
  unitType: "starting",
206
205
  unitId: "bootstrap",
207
206
  unitStartedAt: new Date().toISOString(),
208
- completedUnits: 0,
209
207
  };
210
208
 
211
209
  let lockfile: typeof import("proper-lockfile");
@@ -379,7 +377,6 @@ export function updateSessionLock(
379
377
  basePath: string,
380
378
  unitType: string,
381
379
  unitId: string,
382
- completedUnits: number,
383
380
  sessionFile?: string,
384
381
  ): void {
385
382
  if (_lockedPath !== basePath && _lockedPath !== null) return;
@@ -392,7 +389,6 @@ export function updateSessionLock(
392
389
  unitType,
393
390
  unitId,
394
391
  unitStartedAt: new Date().toISOString(),
395
- completedUnits,
396
392
  sessionFile,
397
393
  };
398
394
  atomicWriteSync(lp, JSON.stringify(data, null, 2));
@@ -118,6 +118,11 @@ interface StateCache {
118
118
  const CACHE_TTL_MS = 100;
119
119
  let _stateCache: StateCache | null = null;
120
120
 
121
+ // ── Telemetry counters for derive-path observability ────────────────────────
122
+ let _telemetry = { dbDeriveCount: 0, markdownDeriveCount: 0 };
123
+ export function getDeriveTelemetry() { return { ..._telemetry }; }
124
+ export function resetDeriveTelemetry() { _telemetry = { dbDeriveCount: 0, markdownDeriveCount: 0 }; }
125
+
121
126
  /**
122
127
  * Invalidate the deriveState() cache. Call this whenever planning files on disk
123
128
  * may have changed (unit completion, merges, file writes).
@@ -204,12 +209,15 @@ export async function deriveState(basePath: string): Promise<GSDState> {
204
209
  const stopDbTimer = debugTime("derive-state-db");
205
210
  result = await deriveStateFromDb(basePath);
206
211
  stopDbTimer({ phase: result.phase, milestone: result.activeMilestone?.id });
212
+ _telemetry.dbDeriveCount++;
207
213
  } else {
208
214
  // DB open but empty hierarchy tables — pre-migration project, use filesystem
209
215
  result = await _deriveStateImpl(basePath);
216
+ _telemetry.markdownDeriveCount++;
210
217
  }
211
218
  } else {
212
219
  result = await _deriveStateImpl(basePath);
220
+ _telemetry.markdownDeriveCount++;
213
221
  }
214
222
 
215
223
  stopTimer({ phase: result.phase, milestone: result.activeMilestone?.id });
@@ -0,0 +1,94 @@
1
+ // GSD Extension — Advisory Sync Lock
2
+ // Prevents concurrent worktree syncs from colliding via a simple file lock.
3
+ // Stale locks (mtime > 60s) are auto-overridden. Lock acquisition waits up
4
+ // to 5 seconds then skips non-fatally.
5
+
6
+ import { existsSync, statSync, unlinkSync } from "node:fs";
7
+ import { join } from "node:path";
8
+ import { atomicWriteSync } from "./atomic-write.js";
9
+
10
+ const STALE_THRESHOLD_MS = 60_000; // 60 seconds
11
+ const DEFAULT_TIMEOUT_MS = 5_000; // 5 seconds
12
+ const SPIN_INTERVAL_MS = 100; // 100ms polling interval
13
+
14
+ // SharedArrayBuffer for synchronous sleep via Atomics.wait
15
+ const SLEEP_BUFFER = new SharedArrayBuffer(4);
16
+ const SLEEP_VIEW = new Int32Array(SLEEP_BUFFER);
17
+
18
+ function lockFilePath(basePath: string): string {
19
+ return join(basePath, ".gsd", "sync.lock");
20
+ }
21
+
22
+ function sleepSync(ms: number): void {
23
+ Atomics.wait(SLEEP_VIEW, 0, 0, ms);
24
+ }
25
+
26
+ /**
27
+ * Acquire an advisory sync lock for the given basePath.
28
+ * Returns { acquired: true } on success, { acquired: false } after timeout.
29
+ *
30
+ * - Creates lock file at {basePath}/.gsd/sync.lock with JSON { pid, acquired_at }
31
+ * - If lock exists and mtime > 60s (stale), overrides it
32
+ * - If lock exists and not stale, spins up to timeoutMs before giving up
33
+ */
34
+ export function acquireSyncLock(
35
+ basePath: string,
36
+ timeoutMs: number = DEFAULT_TIMEOUT_MS,
37
+ ): { acquired: boolean } {
38
+ const lp = lockFilePath(basePath);
39
+ const deadline = Date.now() + timeoutMs;
40
+
41
+ while (true) {
42
+ // Check if lock file exists
43
+ if (existsSync(lp)) {
44
+ // Check staleness
45
+ try {
46
+ const stat = statSync(lp);
47
+ const age = Date.now() - stat.mtimeMs;
48
+ if (age > STALE_THRESHOLD_MS) {
49
+ // Stale lock — override it
50
+ try { unlinkSync(lp); } catch { /* race: already removed */ }
51
+ } else {
52
+ // Lock is held and not stale — wait or give up
53
+ if (Date.now() >= deadline) {
54
+ return { acquired: false };
55
+ }
56
+ sleepSync(SPIN_INTERVAL_MS);
57
+ continue;
58
+ }
59
+ } catch {
60
+ // stat failed (file removed between exists check and stat) — try to acquire
61
+ }
62
+ }
63
+
64
+ // Lock file does not exist (or was just removed) — try to write it
65
+ try {
66
+ const lockData = {
67
+ pid: process.pid,
68
+ acquired_at: new Date().toISOString(),
69
+ };
70
+ atomicWriteSync(lp, JSON.stringify(lockData, null, 2));
71
+ return { acquired: true };
72
+ } catch {
73
+ // Write failed (race condition with another process) — retry or give up
74
+ if (Date.now() >= deadline) {
75
+ return { acquired: false };
76
+ }
77
+ sleepSync(SPIN_INTERVAL_MS);
78
+ }
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Release the advisory sync lock. No-op if lock file does not exist.
84
+ */
85
+ export function releaseSyncLock(basePath: string): void {
86
+ const lp = lockFilePath(basePath);
87
+ try {
88
+ if (existsSync(lp)) {
89
+ unlinkSync(lp);
90
+ }
91
+ } catch {
92
+ // Non-fatal — lock may have been released by another process
93
+ }
94
+ }
@@ -27,7 +27,7 @@ test("writeLock creates auto.lock with correct structure", () => {
27
27
  const dir = mkdtempSync(join(tmpdir(), "gsd-lock-test-"));
28
28
  mkdirSync(join(dir, ".gsd"), { recursive: true });
29
29
 
30
- writeLock(dir, "starting", "M001", 0);
30
+ writeLock(dir, "starting", "M001");
31
31
 
32
32
  const lockPath = join(dir, ".gsd", "auto.lock");
33
33
  assert.ok(existsSync(lockPath), "auto.lock should exist after writeLock");
@@ -36,7 +36,6 @@ test("writeLock creates auto.lock with correct structure", () => {
36
36
  assert.equal(data.pid, process.pid, "lock should contain current PID");
37
37
  assert.equal(data.unitType, "starting", "lock should contain unit type");
38
38
  assert.equal(data.unitId, "M001", "lock should contain unit ID");
39
- assert.equal(data.completedUnits, 0, "lock should show 0 completed units");
40
39
  assert.ok(data.startedAt, "lock should have startedAt timestamp");
41
40
 
42
41
  rmSync(dir, { recursive: true, force: true });
@@ -46,13 +45,12 @@ test("writeLock updates existing lock with new unit info", () => {
46
45
  const dir = mkdtempSync(join(tmpdir(), "gsd-lock-test-"));
47
46
  mkdirSync(join(dir, ".gsd"), { recursive: true });
48
47
 
49
- writeLock(dir, "starting", "M001", 0);
50
- writeLock(dir, "execute-task", "M001/S01/T01", 2, "/tmp/session.jsonl");
48
+ writeLock(dir, "starting", "M001");
49
+ writeLock(dir, "execute-task", "M001/S01/T01", "/tmp/session.jsonl");
51
50
 
52
51
  const data = JSON.parse(readFileSync(join(dir, ".gsd", "auto.lock"), "utf-8"));
53
52
  assert.equal(data.unitType, "execute-task", "lock should be updated to new unit type");
54
53
  assert.equal(data.unitId, "M001/S01/T01", "lock should be updated to new unit ID");
55
- assert.equal(data.completedUnits, 2, "completed count should be updated");
56
54
  assert.equal(data.sessionFile, "/tmp/session.jsonl", "session file should be recorded");
57
55
 
58
56
  rmSync(dir, { recursive: true, force: true });
@@ -74,13 +72,12 @@ test("readCrashLock returns lock data when file exists", () => {
74
72
  const dir = mkdtempSync(join(tmpdir(), "gsd-lock-test-"));
75
73
  mkdirSync(join(dir, ".gsd"), { recursive: true });
76
74
 
77
- writeLock(dir, "plan-milestone", "M002", 5);
75
+ writeLock(dir, "plan-milestone", "M002");
78
76
  const lock = readCrashLock(dir);
79
77
 
80
78
  assert.ok(lock, "should return lock data");
81
79
  assert.equal(lock!.unitType, "plan-milestone");
82
80
  assert.equal(lock!.unitId, "M002");
83
- assert.equal(lock!.completedUnits, 5);
84
81
 
85
82
  rmSync(dir, { recursive: true, force: true });
86
83
  });
@@ -91,7 +88,7 @@ test("clearLock removes the lock file", () => {
91
88
  const dir = mkdtempSync(join(tmpdir(), "gsd-lock-test-"));
92
89
  mkdirSync(join(dir, ".gsd"), { recursive: true });
93
90
 
94
- writeLock(dir, "starting", "M001", 0);
91
+ writeLock(dir, "starting", "M001");
95
92
  assert.ok(existsSync(join(dir, ".gsd", "auto.lock")), "lock should exist before clear");
96
93
 
97
94
  clearLock(dir);
@@ -139,7 +136,6 @@ test("isLockProcessAlive returns false for dead PID", () => {
139
136
  unitType: "execute-task",
140
137
  unitId: "M001/S01/T01",
141
138
  unitStartedAt: new Date().toISOString(),
142
- completedUnits: 0,
143
139
  };
144
140
  assert.equal(isLockProcessAlive(lock), false, "dead PID should return false");
145
141
  });
@@ -151,7 +147,6 @@ test("isLockProcessAlive returns false for own PID (recycled)", () => {
151
147
  unitType: "execute-task",
152
148
  unitId: "M001/S01/T01",
153
149
  unitStartedAt: new Date().toISOString(),
154
- completedUnits: 0,
155
150
  };
156
151
  assert.equal(isLockProcessAlive(lock), false, "own PID should return false (recycled)");
157
152
  });
@@ -163,7 +158,6 @@ test("isLockProcessAlive returns false for invalid PID", () => {
163
158
  unitType: "execute-task",
164
159
  unitId: "M001/S01/T01",
165
160
  unitStartedAt: new Date().toISOString(),
166
- completedUnits: 0,
167
161
  };
168
162
  assert.equal(isLockProcessAlive(lock), false, "negative PID should return false");
169
163
  });
@@ -183,7 +177,6 @@ test("lock file enables cross-process auto-mode detection", () => {
183
177
  unitType: "execute-task",
184
178
  unitId: "M001/S01/T02",
185
179
  unitStartedAt: new Date().toISOString(),
186
- completedUnits: 3,
187
180
  };
188
181
  writeFileSync(join(dir, ".gsd", "auto.lock"), JSON.stringify(lockData, null, 2));
189
182
 
@@ -209,7 +202,6 @@ test("stale lock from dead process is detected as not alive", () => {
209
202
  unitType: "plan-slice",
210
203
  unitId: "M001/S02",
211
204
  unitStartedAt: "2026-03-01T00:05:00Z",
212
- completedUnits: 1,
213
205
  };
214
206
  writeFileSync(join(dir, ".gsd", "auto.lock"), JSON.stringify(lockData, null, 2));
215
207
 
@@ -367,9 +367,6 @@ function makeMockDeps(
367
367
  getPriorSliceCompletionBlocker: () => null,
368
368
  getMainBranch: () => "main",
369
369
  closeoutUnit: async () => {},
370
- verifyExpectedArtifact: () => true,
371
- clearUnitRuntimeRecord: () => {},
372
- writeUnitRuntimeRecord: () => {},
373
370
  recordOutcome: () => {},
374
371
  writeLock: () => {},
375
372
  captureAvailableSkills: () => {},
@@ -713,10 +710,10 @@ test("crash lock records session file from AFTER newSession, not before (#1710)"
713
710
  prompt: "do the thing",
714
711
  };
715
712
  },
716
- writeLock: (_base: string, _ut: string, _uid: string, _count: number, sessionFile?: string) => {
713
+ writeLock: (_base: string, _ut: string, _uid: string, sessionFile?: string) => {
717
714
  writeLockCalls.push({ sessionFile });
718
715
  },
719
- updateSessionLock: (_base: string, _ut: string, _uid: string, _count: number, sessionFile?: string) => {
716
+ updateSessionLock: (_base: string, _ut: string, _uid: string, sessionFile?: string) => {
720
717
  updateSessionLockCalls.push({ sessionFile });
721
718
  },
722
719
  getSessionFile: (ctxArg: any) => {
@@ -1104,7 +1101,7 @@ test("auto.ts startAuto calls autoLoop (not dispatchNextUnit as first dispatch)"
1104
1101
  );
1105
1102
  });
1106
1103
 
1107
- test("startAuto calls selfHealRuntimeRecords before autoLoop (#1727)", () => {
1104
+ test("startAuto calls selfHealRuntimeRecords before autoLoop (#1727)", { skip: "selfHealRuntimeRecords moved to crash-recovery pipeline in v3" }, () => {
1108
1105
  const src = readFileSync(
1109
1106
  resolve(import.meta.dirname, "..", "auto.ts"),
1110
1107
  "utf-8",
@@ -1990,7 +1987,6 @@ test("autoLoop does NOT reject non-execute-task units with 0 tool calls (#1833)"
1990
1987
  });
1991
1988
  },
1992
1989
  getLedger: () => mockLedger,
1993
- verifyExpectedArtifact: () => true,
1994
1990
  postUnitPostVerification: async () => {
1995
1991
  deps.callLog.push("postUnitPostVerification");
1996
1992
  s.active = false;
@@ -2014,10 +2010,10 @@ test("autoLoop does NOT reject non-execute-task units with 0 tool calls (#1833)"
2014
2010
  "should NOT flag non-execute-task units with 0 tool calls",
2015
2011
  );
2016
2012
 
2017
- // The unit should have been added to completedUnits normally
2013
+ // Verify the loop ran to completion (postUnitPostVerification was called)
2018
2014
  assert.ok(
2019
- s.completedUnits.length >= 1,
2020
- "complete-slice with 0 tool calls should still be marked as completed",
2015
+ deps.callLog.includes("postUnitPostVerification"),
2016
+ "complete-slice with 0 tool calls should still complete the post-unit pipeline",
2021
2017
  );
2022
2018
  });
2023
2019
 
@@ -115,6 +115,102 @@ describe("complete-milestone", () => {
115
115
  assert.ok(prompt.includes("Milestone M002 complete"), "prompt contains completion sentinel for M002");
116
116
  });
117
117
 
118
+ test("prompt contains verification gate that blocks completion on failure", () => {
119
+ const prompt = loadPromptFromWorktree("complete-milestone", {
120
+ workingDirectory: "/tmp/test-project",
121
+ milestoneId: "M001",
122
+ milestoneTitle: "Gate Test",
123
+ roadmapPath: ".gsd/milestones/M001/M001-ROADMAP.md",
124
+ inlinedContext: "context",
125
+ });
126
+
127
+ // Verification gate section must exist
128
+ assert.ok(
129
+ prompt.includes("Verification Gate"),
130
+ "prompt contains 'Verification Gate' section",
131
+ );
132
+
133
+ // Failure path must block gsd_complete_milestone
134
+ assert.ok(
135
+ prompt.includes("Do NOT call `gsd_complete_milestone`"),
136
+ "failure path explicitly blocks calling the completion tool",
137
+ );
138
+
139
+ // Failure path must have its own sentinel distinct from success
140
+ assert.ok(
141
+ prompt.includes("verification FAILED"),
142
+ "failure path outputs a FAILED sentinel",
143
+ );
144
+
145
+ // verificationPassed parameter must be referenced
146
+ assert.ok(
147
+ prompt.includes("verificationPassed"),
148
+ "prompt references verificationPassed parameter",
149
+ );
150
+ });
151
+
152
+ test("handleCompleteMilestone rejects when verificationPassed is false", async () => {
153
+ const { handleCompleteMilestone } = await import("../tools/complete-milestone.ts");
154
+ const base = createFixtureBase();
155
+ try {
156
+ const result = await handleCompleteMilestone({
157
+ milestoneId: "M001",
158
+ title: "Test Milestone",
159
+ oneLiner: "Test",
160
+ narrative: "Test narrative",
161
+ successCriteriaResults: "None met",
162
+ definitionOfDoneResults: "Incomplete",
163
+ requirementOutcomes: "None validated",
164
+ keyDecisions: [],
165
+ keyFiles: [],
166
+ lessonsLearned: [],
167
+ followUps: "",
168
+ deviations: "",
169
+ verificationPassed: false,
170
+ }, base);
171
+
172
+ assert.ok("error" in result, "returns error when verificationPassed is false");
173
+ assert.ok(
174
+ (result as { error: string }).error.includes("verification did not pass"),
175
+ "error message mentions verification did not pass",
176
+ );
177
+ } finally {
178
+ cleanup(base);
179
+ }
180
+ });
181
+
182
+ test("handleCompleteMilestone rejects when verificationPassed is omitted", async () => {
183
+ const { handleCompleteMilestone } = await import("../tools/complete-milestone.ts");
184
+ const base = createFixtureBase();
185
+ try {
186
+ // Simulate omitted verificationPassed (undefined coerced via any)
187
+ const params: any = {
188
+ milestoneId: "M001",
189
+ title: "Test Milestone",
190
+ oneLiner: "Test",
191
+ narrative: "Test narrative",
192
+ successCriteriaResults: "Results",
193
+ definitionOfDoneResults: "Done results",
194
+ requirementOutcomes: "Outcomes",
195
+ keyDecisions: [],
196
+ keyFiles: [],
197
+ lessonsLearned: [],
198
+ followUps: "",
199
+ deviations: "",
200
+ // verificationPassed intentionally omitted
201
+ };
202
+ const result = await handleCompleteMilestone(params, base);
203
+
204
+ assert.ok("error" in result, "returns error when verificationPassed is omitted");
205
+ assert.ok(
206
+ (result as { error: string }).error.includes("verification did not pass"),
207
+ "error message mentions verification did not pass",
208
+ );
209
+ } finally {
210
+ cleanup(base);
211
+ }
212
+ });
213
+
118
214
  test("diagnoseExpectedArtifact logic for complete-milestone", async () => {
119
215
  // Import the path helpers used by diagnoseExpectedArtifact
120
216
  const { relMilestoneFile } = await import("../paths.ts");