gsd-pi 2.44.0 → 2.45.0-dev.1afbdaa

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 (608) hide show
  1. package/README.md +30 -12
  2. package/dist/help-text.js +1 -1
  3. package/dist/loader.js +34 -0
  4. package/dist/resources/extensions/gsd/activity-log.js +7 -0
  5. package/dist/resources/extensions/gsd/auto/infra-errors.js +3 -0
  6. package/dist/resources/extensions/gsd/auto/phases.js +63 -77
  7. package/dist/resources/extensions/gsd/auto/run-unit.js +6 -3
  8. package/dist/resources/extensions/gsd/auto/session.js +0 -11
  9. package/dist/resources/extensions/gsd/auto-artifact-paths.js +112 -0
  10. package/dist/resources/extensions/gsd/auto-post-unit.js +25 -96
  11. package/dist/resources/extensions/gsd/auto-prompts.js +24 -1
  12. package/dist/resources/extensions/gsd/auto-start.js +33 -5
  13. package/dist/resources/extensions/gsd/auto-timers.js +57 -3
  14. package/dist/resources/extensions/gsd/auto-worktree-sync.js +4 -0
  15. package/dist/resources/extensions/gsd/auto-worktree.js +14 -10
  16. package/dist/resources/extensions/gsd/auto.js +42 -60
  17. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +170 -11
  18. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +18 -0
  19. package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -12
  20. package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
  21. package/dist/resources/extensions/gsd/commands/context.js +0 -4
  22. package/dist/resources/extensions/gsd/commands/handlers/core.js +2 -0
  23. package/dist/resources/extensions/gsd/commands/handlers/ops.js +10 -0
  24. package/dist/resources/extensions/gsd/commands/handlers/parallel.js +1 -1
  25. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
  26. package/dist/resources/extensions/gsd/commands-mcp-status.js +187 -0
  27. package/dist/resources/extensions/gsd/crash-recovery.js +2 -4
  28. package/dist/resources/extensions/gsd/dashboard-overlay.js +0 -44
  29. package/dist/resources/extensions/gsd/db-writer.js +40 -22
  30. package/dist/resources/extensions/gsd/doctor-checks.js +167 -2
  31. package/dist/resources/extensions/gsd/doctor.js +13 -3
  32. package/dist/resources/extensions/gsd/git-service.js +8 -3
  33. package/dist/resources/extensions/gsd/gsd-db.js +28 -4
  34. package/dist/resources/extensions/gsd/guided-flow.js +1 -2
  35. package/dist/resources/extensions/gsd/markdown-renderer.js +1 -1
  36. package/dist/resources/extensions/gsd/parallel-merge.js +1 -1
  37. package/dist/resources/extensions/gsd/parallel-orchestrator.js +5 -18
  38. package/dist/resources/extensions/gsd/preferences-types.js +2 -2
  39. package/dist/resources/extensions/gsd/preferences.js +17 -5
  40. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +21 -10
  41. package/dist/resources/extensions/gsd/prompts/complete-slice.md +10 -23
  42. package/dist/resources/extensions/gsd/prompts/discuss.md +2 -2
  43. package/dist/resources/extensions/gsd/prompts/execute-task.md +5 -15
  44. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  45. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  46. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  47. package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  48. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  49. package/dist/resources/extensions/gsd/prompts/plan-slice.md +5 -3
  50. package/dist/resources/extensions/gsd/prompts/queue.md +2 -2
  51. package/dist/resources/extensions/gsd/prompts/quick-task.md +2 -0
  52. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
  53. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  54. package/dist/resources/extensions/gsd/prompts/replan-slice.md +3 -14
  55. package/dist/resources/extensions/gsd/prompts/research-slice.md +3 -3
  56. package/dist/resources/extensions/gsd/prompts/rethink.md +83 -0
  57. package/dist/resources/extensions/gsd/prompts/system.md +1 -1
  58. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
  59. package/dist/resources/extensions/gsd/provider-error-pause.js +7 -0
  60. package/dist/resources/extensions/gsd/repo-identity.js +45 -7
  61. package/dist/resources/extensions/gsd/rethink.js +115 -0
  62. package/dist/resources/extensions/gsd/session-lock.js +1 -3
  63. package/dist/resources/extensions/gsd/state.js +48 -3
  64. package/dist/resources/extensions/gsd/sync-lock.js +89 -0
  65. package/dist/resources/extensions/gsd/tools/complete-milestone.js +61 -11
  66. package/dist/resources/extensions/gsd/tools/complete-slice.js +56 -11
  67. package/dist/resources/extensions/gsd/tools/complete-task.js +50 -2
  68. package/dist/resources/extensions/gsd/tools/plan-milestone.js +37 -1
  69. package/dist/resources/extensions/gsd/tools/plan-slice.js +31 -1
  70. package/dist/resources/extensions/gsd/tools/plan-task.js +28 -1
  71. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +32 -2
  72. package/dist/resources/extensions/gsd/tools/reopen-slice.js +86 -0
  73. package/dist/resources/extensions/gsd/tools/reopen-task.js +90 -0
  74. package/dist/resources/extensions/gsd/tools/replan-slice.js +34 -2
  75. package/dist/resources/extensions/gsd/tools/validate-milestone.js +88 -0
  76. package/dist/resources/extensions/gsd/unit-ownership.js +85 -0
  77. package/dist/resources/extensions/gsd/workflow-events.js +102 -0
  78. package/dist/resources/extensions/gsd/workflow-logger.js +193 -0
  79. package/dist/resources/extensions/gsd/workflow-manifest.js +244 -0
  80. package/dist/resources/extensions/gsd/workflow-migration.js +280 -0
  81. package/dist/resources/extensions/gsd/workflow-projections.js +373 -0
  82. package/dist/resources/extensions/gsd/workflow-reconcile.js +411 -0
  83. package/dist/resources/extensions/gsd/worktree-manager.js +34 -3
  84. package/dist/resources/extensions/gsd/worktree-resolver.js +43 -0
  85. package/dist/resources/extensions/gsd/write-intercept.js +84 -0
  86. package/dist/resources/extensions/mcp-client/index.js +14 -0
  87. package/dist/resources/extensions/voice/index.js +11 -16
  88. package/dist/resources/extensions/voice/linux-ready.js +67 -0
  89. package/dist/web/standalone/.next/BUILD_ID +1 -1
  90. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  91. package/dist/web/standalone/.next/build-manifest.json +4 -4
  92. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  93. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  94. package/dist/web/standalone/.next/required-server-files.json +3 -3
  95. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  96. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  98. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  106. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.rsc +5 -5
  109. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +5 -5
  110. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  112. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  115. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  122. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  160. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  166. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  180. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  182. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  184. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  186. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/index.html +1 -1
  196. package/dist/web/standalone/.next/server/app/index.rsc +6 -6
  197. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  198. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +6 -6
  199. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  200. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  201. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  202. package/dist/web/standalone/.next/server/app/page.js +2 -2
  203. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  205. package/dist/web/standalone/.next/server/chunks/229.js +1 -1
  206. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  207. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/middleware.js +2 -2
  210. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  211. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  212. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  213. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  214. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  215. package/dist/web/standalone/.next/static/chunks/4024.11ca5c01938e5948.js +9 -0
  216. package/dist/web/standalone/.next/static/chunks/{3721.bf31263de6d5fa46.js → 485.243af25f0cdf50d6.js} +2 -2
  217. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  218. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  219. package/dist/web/standalone/.next/static/chunks/app/page-6654a8cca61a3d1c.js +1 -0
  220. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  221. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  222. package/dist/web/standalone/.next/static/chunks/webpack-0a4cd455ec4197d2.js +1 -0
  223. package/dist/web/standalone/.next/static/css/dd4ae3f58ac9b600.css +1 -0
  224. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  225. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  226. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  227. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  228. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  229. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  230. package/dist/web/standalone/server.js +1 -1
  231. package/package.json +2 -1
  232. package/packages/native/dist/stream-process/index.js +2 -2
  233. package/packages/native/src/__tests__/stream-process.test.mjs +34 -0
  234. package/packages/native/src/stream-process/index.ts +2 -2
  235. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +3 -1
  236. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  237. package/packages/pi-coding-agent/dist/core/auth-storage.js +15 -1
  238. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  239. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
  240. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  241. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
  242. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +2 -0
  243. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  244. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
  245. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  246. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -1
  247. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  248. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  249. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
  250. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  251. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +4 -0
  252. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -1
  253. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +10 -5
  254. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -1
  255. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts +2 -0
  256. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts.map +1 -0
  257. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js +185 -0
  258. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js.map +1 -0
  259. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts +15 -0
  260. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts.map +1 -0
  261. package/packages/pi-coding-agent/dist/core/local-model-check.js +41 -0
  262. package/packages/pi-coding-agent/dist/core/local-model-check.js.map +1 -0
  263. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +239 -10
  264. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  265. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +13 -1
  266. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  267. package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
  268. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  269. package/packages/pi-coding-agent/dist/core/package-commands.test.js +206 -195
  270. package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -1
  271. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
  272. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  273. package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
  274. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  275. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  276. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  277. package/packages/pi-coding-agent/dist/core/settings-manager.js +6 -0
  278. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
  280. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  281. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  282. package/packages/pi-coding-agent/dist/main.js +17 -0
  283. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  284. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts +2 -0
  285. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts.map +1 -0
  286. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js +32 -0
  287. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js.map +1 -0
  288. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +3 -1
  289. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  290. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +8 -1
  291. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  292. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  293. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  294. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +12 -0
  295. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  296. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts +15 -0
  297. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts.map +1 -0
  298. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js +40 -0
  299. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js.map +1 -0
  300. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  301. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +4 -1
  302. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  303. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +5 -2
  304. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  305. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +13 -2
  306. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  307. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  308. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +17 -8
  309. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  310. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  311. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +7 -3
  312. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  313. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
  314. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  315. package/packages/pi-coding-agent/package.json +1 -1
  316. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  317. package/packages/pi-coding-agent/src/core/auth-storage.ts +15 -1
  318. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +2 -0
  319. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  320. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -1
  321. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
  322. package/packages/pi-coding-agent/src/core/lifecycle-hooks.test.ts +227 -0
  323. package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +11 -5
  324. package/packages/pi-coding-agent/src/core/local-model-check.ts +45 -0
  325. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +297 -11
  326. package/packages/pi-coding-agent/src/core/model-registry.ts +51 -4
  327. package/packages/pi-coding-agent/src/core/package-commands.test.ts +227 -205
  328. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
  329. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  330. package/packages/pi-coding-agent/src/core/settings-manager.ts +9 -0
  331. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  332. package/packages/pi-coding-agent/src/main.ts +19 -0
  333. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/timestamp.test.ts +38 -0
  334. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +10 -0
  335. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  336. package/packages/pi-coding-agent/src/modes/interactive/components/timestamp.ts +48 -0
  337. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +3 -1
  338. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +18 -3
  339. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +16 -7
  340. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +8 -1
  341. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  342. package/pkg/package.json +1 -1
  343. package/src/resources/extensions/gsd/activity-log.ts +1 -0
  344. package/src/resources/extensions/gsd/auto/infra-errors.ts +3 -0
  345. package/src/resources/extensions/gsd/auto/loop-deps.ts +0 -19
  346. package/src/resources/extensions/gsd/auto/phases.ts +69 -91
  347. package/src/resources/extensions/gsd/auto/run-unit.ts +6 -3
  348. package/src/resources/extensions/gsd/auto/session.ts +0 -18
  349. package/src/resources/extensions/gsd/auto-artifact-paths.ts +131 -0
  350. package/src/resources/extensions/gsd/auto-dashboard.ts +0 -1
  351. package/src/resources/extensions/gsd/auto-post-unit.ts +25 -106
  352. package/src/resources/extensions/gsd/auto-prompts.ts +24 -1
  353. package/src/resources/extensions/gsd/auto-start.ts +40 -5
  354. package/src/resources/extensions/gsd/auto-timers.ts +64 -3
  355. package/src/resources/extensions/gsd/auto-worktree-sync.ts +5 -0
  356. package/src/resources/extensions/gsd/auto-worktree.ts +17 -11
  357. package/src/resources/extensions/gsd/auto.ts +44 -86
  358. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +162 -11
  359. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +22 -0
  360. package/src/resources/extensions/gsd/bootstrap/system-context.ts +48 -11
  361. package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
  362. package/src/resources/extensions/gsd/commands/context.ts +0 -5
  363. package/src/resources/extensions/gsd/commands/handlers/core.ts +2 -0
  364. package/src/resources/extensions/gsd/commands/handlers/ops.ts +10 -0
  365. package/src/resources/extensions/gsd/commands/handlers/parallel.ts +1 -1
  366. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
  367. package/src/resources/extensions/gsd/commands-mcp-status.ts +247 -0
  368. package/src/resources/extensions/gsd/crash-recovery.ts +1 -5
  369. package/src/resources/extensions/gsd/dashboard-overlay.ts +0 -50
  370. package/src/resources/extensions/gsd/db-writer.ts +41 -27
  371. package/src/resources/extensions/gsd/doctor-checks.ts +180 -2
  372. package/src/resources/extensions/gsd/doctor-types.ts +7 -1
  373. package/src/resources/extensions/gsd/doctor.ts +13 -4
  374. package/src/resources/extensions/gsd/git-service.ts +6 -2
  375. package/src/resources/extensions/gsd/gsd-db.ts +32 -4
  376. package/src/resources/extensions/gsd/guided-flow.ts +1 -2
  377. package/src/resources/extensions/gsd/journal.ts +6 -1
  378. package/src/resources/extensions/gsd/markdown-renderer.ts +1 -1
  379. package/src/resources/extensions/gsd/parallel-merge.ts +1 -1
  380. package/src/resources/extensions/gsd/parallel-orchestrator.ts +5 -21
  381. package/src/resources/extensions/gsd/preferences-types.ts +2 -2
  382. package/src/resources/extensions/gsd/preferences.ts +18 -4
  383. package/src/resources/extensions/gsd/prompts/complete-milestone.md +21 -10
  384. package/src/resources/extensions/gsd/prompts/complete-slice.md +10 -23
  385. package/src/resources/extensions/gsd/prompts/discuss.md +2 -2
  386. package/src/resources/extensions/gsd/prompts/execute-task.md +5 -15
  387. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  388. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  389. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  390. package/src/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  391. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  392. package/src/resources/extensions/gsd/prompts/plan-slice.md +5 -3
  393. package/src/resources/extensions/gsd/prompts/queue.md +2 -2
  394. package/src/resources/extensions/gsd/prompts/quick-task.md +2 -0
  395. package/src/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
  396. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  397. package/src/resources/extensions/gsd/prompts/replan-slice.md +3 -14
  398. package/src/resources/extensions/gsd/prompts/research-slice.md +3 -3
  399. package/src/resources/extensions/gsd/prompts/rethink.md +83 -0
  400. package/src/resources/extensions/gsd/prompts/system.md +1 -1
  401. package/src/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
  402. package/src/resources/extensions/gsd/provider-error-pause.ts +9 -0
  403. package/src/resources/extensions/gsd/repo-identity.ts +46 -7
  404. package/src/resources/extensions/gsd/rethink.ts +154 -0
  405. package/src/resources/extensions/gsd/session-lock.ts +0 -4
  406. package/src/resources/extensions/gsd/state.ts +49 -1
  407. package/src/resources/extensions/gsd/sync-lock.ts +94 -0
  408. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  409. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +19 -29
  410. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +6 -10
  411. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
  412. package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +88 -0
  413. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
  414. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
  415. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
  416. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
  417. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
  418. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
  419. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
  420. package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
  421. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
  422. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
  423. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  424. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  425. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +134 -59
  426. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +15 -14
  427. package/src/resources/extensions/gsd/tests/complete-task.test.ts +27 -12
  428. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +114 -0
  429. package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
  430. package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
  431. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
  432. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +26 -40
  433. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +0 -3
  434. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
  435. package/src/resources/extensions/gsd/tests/db-writer.test.ts +465 -416
  436. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
  437. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
  438. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +121 -0
  439. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +210 -181
  440. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
  441. package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
  442. package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
  443. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
  444. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
  445. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
  446. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
  447. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
  448. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
  449. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
  450. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
  451. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
  452. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
  453. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
  454. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
  455. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
  456. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
  457. package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
  458. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
  459. package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +120 -0
  460. package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
  461. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
  462. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
  463. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
  464. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
  465. package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
  466. package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
  467. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
  468. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
  469. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
  470. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
  471. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
  472. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
  473. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  474. package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
  475. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +82 -103
  476. package/src/resources/extensions/gsd/tests/infra-error.test.ts +20 -2
  477. package/src/resources/extensions/gsd/tests/inherited-repo-home-dir.test.ts +121 -0
  478. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
  479. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
  480. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
  481. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
  482. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +33 -42
  483. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -3
  484. package/src/resources/extensions/gsd/tests/knowledge.test.ts +89 -0
  485. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
  486. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +103 -0
  487. package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
  488. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
  489. package/src/resources/extensions/gsd/tests/memory-store.test.ts +81 -94
  490. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +66 -0
  491. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
  492. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
  493. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
  494. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
  495. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
  496. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
  497. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
  498. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +8 -9
  499. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
  500. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +75 -37
  501. package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
  502. package/src/resources/extensions/gsd/tests/parallel-budget-atomicity.test.ts +0 -1
  503. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +39 -53
  504. package/src/resources/extensions/gsd/tests/parallel-merge.test.ts +7 -8
  505. package/src/resources/extensions/gsd/tests/parallel-orchestration.test.ts +20 -24
  506. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +24 -29
  507. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
  508. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
  509. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
  510. package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
  511. package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
  512. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +9 -6
  513. package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +171 -0
  514. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
  515. package/src/resources/extensions/gsd/tests/preferences.test.ts +34 -9
  516. package/src/resources/extensions/gsd/tests/projection-regression.test.ts +174 -0
  517. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +26 -21
  518. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  519. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
  520. package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
  521. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
  522. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
  523. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
  524. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
  525. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +176 -0
  526. package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +155 -0
  527. package/src/resources/extensions/gsd/tests/reopen-task.test.ts +165 -0
  528. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
  529. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
  530. package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
  531. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
  532. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
  533. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
  534. package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
  535. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
  536. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -47
  537. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
  538. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
  539. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
  540. package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +67 -0
  541. package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +2 -3
  542. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +108 -0
  543. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
  544. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +122 -0
  545. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +49 -0
  546. package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
  547. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
  548. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +10 -11
  549. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
  550. package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +175 -0
  551. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
  552. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
  553. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
  554. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
  555. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
  556. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
  557. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
  558. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +205 -0
  559. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +275 -0
  560. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +186 -0
  561. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +171 -0
  562. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
  563. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
  564. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
  565. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
  566. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
  567. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
  568. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
  569. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +220 -0
  570. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +65 -0
  571. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
  572. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
  573. package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
  574. package/src/resources/extensions/gsd/tests/write-intercept.test.ts +76 -0
  575. package/src/resources/extensions/gsd/tools/complete-milestone.ts +74 -11
  576. package/src/resources/extensions/gsd/tools/complete-slice.ts +68 -11
  577. package/src/resources/extensions/gsd/tools/complete-task.ts +63 -1
  578. package/src/resources/extensions/gsd/tools/plan-milestone.ts +45 -0
  579. package/src/resources/extensions/gsd/tools/plan-slice.ts +40 -0
  580. package/src/resources/extensions/gsd/tools/plan-task.ts +37 -1
  581. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +39 -1
  582. package/src/resources/extensions/gsd/tools/reopen-slice.ts +125 -0
  583. package/src/resources/extensions/gsd/tools/reopen-task.ts +129 -0
  584. package/src/resources/extensions/gsd/tools/replan-slice.ts +41 -1
  585. package/src/resources/extensions/gsd/tools/validate-milestone.ts +127 -0
  586. package/src/resources/extensions/gsd/types.ts +8 -0
  587. package/src/resources/extensions/gsd/unit-ownership.ts +104 -0
  588. package/src/resources/extensions/gsd/workflow-events.ts +154 -0
  589. package/src/resources/extensions/gsd/workflow-logger.ts +243 -0
  590. package/src/resources/extensions/gsd/workflow-manifest.ts +334 -0
  591. package/src/resources/extensions/gsd/workflow-migration.ts +345 -0
  592. package/src/resources/extensions/gsd/workflow-projections.ts +425 -0
  593. package/src/resources/extensions/gsd/workflow-reconcile.ts +503 -0
  594. package/src/resources/extensions/gsd/worktree-manager.ts +41 -5
  595. package/src/resources/extensions/gsd/worktree-resolver.ts +44 -0
  596. package/src/resources/extensions/gsd/write-intercept.ts +90 -0
  597. package/src/resources/extensions/mcp-client/index.ts +20 -0
  598. package/src/resources/extensions/voice/index.ts +11 -21
  599. package/src/resources/extensions/voice/linux-ready.ts +87 -0
  600. package/src/resources/extensions/voice/tests/linux-ready.test.ts +124 -0
  601. package/dist/web/standalone/.next/static/chunks/4024.0de81b543b28b9fe.js +0 -9
  602. package/dist/web/standalone/.next/static/chunks/app/page-7e9530a7122506c5.js +0 -1
  603. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  604. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  605. package/dist/web/standalone/.next/static/chunks/webpack-9014b5adb127a98a.js +0 -1
  606. package/dist/web/standalone/.next/static/css/8a727f372cf53002.css +0 -1
  607. /package/dist/web/standalone/.next/static/{mgkxN0mGP6gSUmGPEzbk_ → j-BskPs0nxxPeYY-bSrab}/_buildManifest.js +0 -0
  608. /package/dist/web/standalone/.next/static/{mgkxN0mGP6gSUmGPEzbk_ → j-BskPs0nxxPeYY-bSrab}/_ssgManifest.js +0 -0
@@ -169,7 +169,6 @@ export function acquireSessionLock(basePath) {
169
169
  unitType: "starting",
170
170
  unitId: "bootstrap",
171
171
  unitStartedAt: new Date().toISOString(),
172
- completedUnits: 0,
173
172
  };
174
173
  let lockfile;
175
174
  try {
@@ -314,7 +313,7 @@ function acquireFallbackLock(basePath, lp, lockData) {
314
313
  * Update the lock file metadata (called on each unit dispatch).
315
314
  * Does NOT re-acquire the OS lock — just updates the JSON content.
316
315
  */
317
- export function updateSessionLock(basePath, unitType, unitId, completedUnits, sessionFile) {
316
+ export function updateSessionLock(basePath, unitType, unitId, sessionFile) {
318
317
  if (_lockedPath !== basePath && _lockedPath !== null)
319
318
  return;
320
319
  const lp = lockPath(basePath);
@@ -325,7 +324,6 @@ export function updateSessionLock(basePath, unitType, unitId, completedUnits, se
325
324
  unitType,
326
325
  unitId,
327
326
  unitStartedAt: new Date().toISOString(),
328
- completedUnits,
329
327
  sessionFile,
330
328
  };
331
329
  atomicWriteSync(lp, JSON.stringify(data, null, 2));
@@ -4,12 +4,12 @@
4
4
  import { parseRoadmap, parsePlan, } from './parsers-legacy.js';
5
5
  import { parseSummary, loadFile, parseRequirementCounts, parseContextDependsOn, } from './files.js';
6
6
  import { resolveMilestoneFile, resolveSlicePath, resolveSliceFile, resolveTaskFile, resolveTasksDir, resolveGsdRootFile, gsdRoot, } from './paths.js';
7
- import { findMilestoneIds } from './milestone-ids.js';
7
+ import { milestoneIdSort, findMilestoneIds } from './milestone-ids.js';
8
8
  import { nativeBatchParseGsdFiles } from './native-parser-bridge.js';
9
9
  import { join, resolve } from 'path';
10
10
  import { existsSync, readdirSync } from 'node:fs';
11
11
  import { debugCount, debugTime } from './debug-logger.js';
12
- import { isDbAvailable, getAllMilestones, getMilestoneSlices, getSliceTasks, getReplanHistory, getSlice, } from './gsd-db.js';
12
+ import { isDbAvailable, getAllMilestones, getMilestoneSlices, getSliceTasks, getReplanHistory, getSlice, insertMilestone, } from './gsd-db.js';
13
13
  /**
14
14
  * A "ghost" milestone directory contains only META.json (and no substantive
15
15
  * files like CONTEXT, CONTEXT-DRAFT, ROADMAP, or SUMMARY). These appear when
@@ -57,6 +57,10 @@ export function isValidationTerminal(validationContent) {
57
57
  }
58
58
  const CACHE_TTL_MS = 100;
59
59
  let _stateCache = null;
60
+ // ── Telemetry counters for derive-path observability ────────────────────────
61
+ let _telemetry = { dbDeriveCount: 0, markdownDeriveCount: 0 };
62
+ export function getDeriveTelemetry() { return { ..._telemetry }; }
63
+ export function resetDeriveTelemetry() { _telemetry = { dbDeriveCount: 0, markdownDeriveCount: 0 }; }
60
64
  /**
61
65
  * Invalidate the deriveState() cache. Call this whenever planning files on disk
62
66
  * may have changed (unit completion, merges, file writes).
@@ -141,14 +145,17 @@ export async function deriveState(basePath) {
141
145
  const stopDbTimer = debugTime("derive-state-db");
142
146
  result = await deriveStateFromDb(basePath);
143
147
  stopDbTimer({ phase: result.phase, milestone: result.activeMilestone?.id });
148
+ _telemetry.dbDeriveCount++;
144
149
  }
145
150
  else {
146
151
  // DB open but empty hierarchy tables — pre-migration project, use filesystem
147
152
  result = await _deriveStateImpl(basePath);
153
+ _telemetry.markdownDeriveCount++;
148
154
  }
149
155
  }
150
156
  else {
151
157
  result = await _deriveStateImpl(basePath);
158
+ _telemetry.markdownDeriveCount++;
152
159
  }
153
160
  stopTimer({ phase: result.phase, milestone: result.activeMilestone?.id });
154
161
  debugCount("deriveStateCalls");
@@ -192,7 +199,45 @@ function isStatusDone(status) {
192
199
  */
193
200
  export async function deriveStateFromDb(basePath) {
194
201
  const requirements = parseRequirementCounts(await loadFile(resolveGsdRootFile(basePath, "REQUIREMENTS")));
195
- const allMilestones = getAllMilestones();
202
+ let allMilestones = getAllMilestones();
203
+ // Incremental disk→DB sync: milestone directories created outside the DB
204
+ // write path (via /gsd queue, manual mkdir, or complete-milestone writing the
205
+ // next CONTEXT.md) are never inserted by the initial migration guard in
206
+ // auto-start.ts because that guard only runs when gsd.db doesn't exist yet.
207
+ // Reconcile here so deriveStateFromDb never silently misses queued milestones.
208
+ // insertMilestone uses INSERT OR IGNORE, so this is safe to call every time.
209
+ const dbIdSet = new Set(allMilestones.map(m => m.id));
210
+ const diskIds = findMilestoneIds(basePath);
211
+ let synced = false;
212
+ for (const diskId of diskIds) {
213
+ if (!dbIdSet.has(diskId) && !isGhostMilestone(basePath, diskId)) {
214
+ insertMilestone({ id: diskId, status: 'active' });
215
+ synced = true;
216
+ }
217
+ }
218
+ if (synced)
219
+ allMilestones = getAllMilestones();
220
+ // Reconcile: discover milestones that exist on disk but are missing from
221
+ // the DB. This happens when milestones were created before the DB migration
222
+ // or were manually added to the filesystem. Without this, disk-only
223
+ // milestones are invisible after migration (#2416).
224
+ const dbMilestoneIds = new Set(allMilestones.map(m => m.id));
225
+ const diskMilestoneIds = findMilestoneIds(basePath);
226
+ for (const diskId of diskMilestoneIds) {
227
+ if (!dbMilestoneIds.has(diskId)) {
228
+ // Synthesize a minimal MilestoneRow for the disk-only milestone.
229
+ // Title and status will be resolved from disk files in the loop below.
230
+ allMilestones.push({
231
+ id: diskId,
232
+ title: diskId,
233
+ status: 'active',
234
+ depends_on: [],
235
+ created_at: new Date().toISOString(),
236
+ });
237
+ }
238
+ }
239
+ // Re-sort so milestones are in canonical order after injection
240
+ allMilestones.sort((a, b) => milestoneIdSort(a.id, b.id));
196
241
  // Parallel worker isolation: when locked, filter to just the locked milestone
197
242
  const milestoneLock = process.env.GSD_MILESTONE_LOCK;
198
243
  const milestones = milestoneLock
@@ -0,0 +1,89 @@
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
+ import { existsSync, statSync, unlinkSync } from "node:fs";
6
+ import { join } from "node:path";
7
+ import { atomicWriteSync } from "./atomic-write.js";
8
+ const STALE_THRESHOLD_MS = 60_000; // 60 seconds
9
+ const DEFAULT_TIMEOUT_MS = 5_000; // 5 seconds
10
+ const SPIN_INTERVAL_MS = 100; // 100ms polling interval
11
+ // SharedArrayBuffer for synchronous sleep via Atomics.wait
12
+ const SLEEP_BUFFER = new SharedArrayBuffer(4);
13
+ const SLEEP_VIEW = new Int32Array(SLEEP_BUFFER);
14
+ function lockFilePath(basePath) {
15
+ return join(basePath, ".gsd", "sync.lock");
16
+ }
17
+ function sleepSync(ms) {
18
+ Atomics.wait(SLEEP_VIEW, 0, 0, ms);
19
+ }
20
+ /**
21
+ * Acquire an advisory sync lock for the given basePath.
22
+ * Returns { acquired: true } on success, { acquired: false } after timeout.
23
+ *
24
+ * - Creates lock file at {basePath}/.gsd/sync.lock with JSON { pid, acquired_at }
25
+ * - If lock exists and mtime > 60s (stale), overrides it
26
+ * - If lock exists and not stale, spins up to timeoutMs before giving up
27
+ */
28
+ export function acquireSyncLock(basePath, timeoutMs = DEFAULT_TIMEOUT_MS) {
29
+ const lp = lockFilePath(basePath);
30
+ const deadline = Date.now() + timeoutMs;
31
+ while (true) {
32
+ // Check if lock file exists
33
+ if (existsSync(lp)) {
34
+ // Check staleness
35
+ try {
36
+ const stat = statSync(lp);
37
+ const age = Date.now() - stat.mtimeMs;
38
+ if (age > STALE_THRESHOLD_MS) {
39
+ // Stale lock — override it
40
+ try {
41
+ unlinkSync(lp);
42
+ }
43
+ catch { /* race: already removed */ }
44
+ }
45
+ else {
46
+ // Lock is held and not stale — wait or give up
47
+ if (Date.now() >= deadline) {
48
+ return { acquired: false };
49
+ }
50
+ sleepSync(SPIN_INTERVAL_MS);
51
+ continue;
52
+ }
53
+ }
54
+ catch {
55
+ // stat failed (file removed between exists check and stat) — try to acquire
56
+ }
57
+ }
58
+ // Lock file does not exist (or was just removed) — try to write it
59
+ try {
60
+ const lockData = {
61
+ pid: process.pid,
62
+ acquired_at: new Date().toISOString(),
63
+ };
64
+ atomicWriteSync(lp, JSON.stringify(lockData, null, 2));
65
+ return { acquired: true };
66
+ }
67
+ catch {
68
+ // Write failed (race condition with another process) — retry or give up
69
+ if (Date.now() >= deadline) {
70
+ return { acquired: false };
71
+ }
72
+ sleepSync(SPIN_INTERVAL_MS);
73
+ }
74
+ }
75
+ }
76
+ /**
77
+ * Release the advisory sync lock. No-op if lock file does not exist.
78
+ */
79
+ export function releaseSyncLock(basePath) {
80
+ const lp = lockFilePath(basePath);
81
+ try {
82
+ if (existsSync(lp)) {
83
+ unlinkSync(lp);
84
+ }
85
+ }
86
+ catch {
87
+ // Non-fatal — lock may have been released by another process
88
+ }
89
+ }
@@ -7,10 +7,13 @@
7
7
  */
8
8
  import { join } from "node:path";
9
9
  import { mkdirSync } from "node:fs";
10
- import { transaction, getMilestoneSlices, _getAdapter, } from "../gsd-db.js";
10
+ import { transaction, getMilestone, getMilestoneSlices, getSliceTasks, _getAdapter, } from "../gsd-db.js";
11
11
  import { resolveMilestonePath, clearPathCache } from "../paths.js";
12
12
  import { saveFile, clearParseCache } from "../files.js";
13
13
  import { invalidateStateCache } from "../state.js";
14
+ import { renderAllProjections } from "../workflow-projections.js";
15
+ import { writeManifest } from "../workflow-manifest.js";
16
+ import { appendEvent } from "../workflow-events.js";
14
17
  function renderMilestoneSummaryMarkdown(params) {
15
18
  const now = new Date().toISOString();
16
19
  const keyDecisionsYaml = params.keyDecisions.length > 0
@@ -72,25 +75,56 @@ export async function handleCompleteMilestone(params, basePath) {
72
75
  if (!params.title || typeof params.title !== "string" || params.title.trim() === "") {
73
76
  return { error: "title is required and must be a non-empty string" };
74
77
  }
75
- // ── Verify all slices are complete ───────────────────────────────────────
76
- const slices = getMilestoneSlices(params.milestoneId);
77
- if (slices.length === 0) {
78
- return { error: `no slices found for milestone ${params.milestoneId}` };
78
+ // ── Verify that verification passed ─────────────────────────────────────
79
+ if (params.verificationPassed !== true) {
80
+ return { error: "verification did not pass — milestone completion blocked. verificationPassed must be explicitly set to true after all verification steps succeed" };
79
81
  }
80
- const incompleteSlices = slices.filter(s => s.status !== "complete" && s.status !== "done");
81
- if (incompleteSlices.length > 0) {
82
- const incompleteIds = incompleteSlices.map(s => `${s.id} (status: ${s.status})`).join(", ");
83
- return { error: `incomplete slices: ${incompleteIds}` };
84
- }
85
- // ── DB writes inside a transaction ──────────────────────────────────────
82
+ // ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
86
83
  const completedAt = new Date().toISOString();
84
+ let guardError = null;
87
85
  transaction(() => {
86
+ // State machine preconditions (inside txn for atomicity)
87
+ const milestone = getMilestone(params.milestoneId);
88
+ if (!milestone) {
89
+ guardError = `milestone not found: ${params.milestoneId}`;
90
+ return;
91
+ }
92
+ if (milestone.status === "complete" || milestone.status === "done") {
93
+ guardError = `milestone ${params.milestoneId} is already complete`;
94
+ return;
95
+ }
96
+ // Verify all slices are complete
97
+ const slices = getMilestoneSlices(params.milestoneId);
98
+ if (slices.length === 0) {
99
+ guardError = `no slices found for milestone ${params.milestoneId}`;
100
+ return;
101
+ }
102
+ const incompleteSlices = slices.filter(s => s.status !== "complete" && s.status !== "done");
103
+ if (incompleteSlices.length > 0) {
104
+ const incompleteIds = incompleteSlices.map(s => `${s.id} (status: ${s.status})`).join(", ");
105
+ guardError = `incomplete slices: ${incompleteIds}`;
106
+ return;
107
+ }
108
+ // Deep check: verify all tasks in all slices are complete
109
+ for (const slice of slices) {
110
+ const tasks = getSliceTasks(params.milestoneId, slice.id);
111
+ const incompleteTasks = tasks.filter(t => t.status !== "complete" && t.status !== "done");
112
+ if (incompleteTasks.length > 0) {
113
+ const ids = incompleteTasks.map(t => `${t.id} (status: ${t.status})`).join(", ");
114
+ guardError = `slice ${slice.id} has incomplete tasks: ${ids}`;
115
+ return;
116
+ }
117
+ }
118
+ // All guards passed — perform write
88
119
  const adapter = _getAdapter();
89
120
  adapter.prepare(`UPDATE milestones SET status = 'complete', completed_at = :completed_at WHERE id = :mid`).run({
90
121
  ":completed_at": completedAt,
91
122
  ":mid": params.milestoneId,
92
123
  });
93
124
  });
125
+ if (guardError) {
126
+ return { error: guardError };
127
+ }
94
128
  // ── Filesystem operations (outside transaction) ─────────────────────────
95
129
  const summaryMd = renderMilestoneSummaryMarkdown(params);
96
130
  let summaryPath;
@@ -121,6 +155,22 @@ export async function handleCompleteMilestone(params, basePath) {
121
155
  invalidateStateCache();
122
156
  clearPathCache();
123
157
  clearParseCache();
158
+ // ── Post-mutation hook: projections, manifest, event log ───────────────
159
+ try {
160
+ await renderAllProjections(basePath, params.milestoneId);
161
+ writeManifest(basePath);
162
+ appendEvent(basePath, {
163
+ cmd: "complete-milestone",
164
+ params: { milestoneId: params.milestoneId },
165
+ ts: new Date().toISOString(),
166
+ actor: "agent",
167
+ actor_name: params.actorName,
168
+ trigger_reason: params.triggerReason,
169
+ });
170
+ }
171
+ catch (hookErr) {
172
+ process.stderr.write(`gsd: complete-milestone post-mutation hook warning: ${hookErr.message}\n`);
173
+ }
124
174
  return {
125
175
  milestoneId: params.milestoneId,
126
176
  summaryPath,
@@ -8,11 +8,15 @@
8
8
  */
9
9
  import { join } from "node:path";
10
10
  import { mkdirSync } from "node:fs";
11
- import { transaction, insertMilestone, insertSlice, getSliceTasks, updateSliceStatus, _getAdapter, } from "../gsd-db.js";
11
+ import { transaction, insertMilestone, insertSlice, getSlice, getSliceTasks, getMilestone, updateSliceStatus, _getAdapter, } from "../gsd-db.js";
12
12
  import { resolveSlicePath, clearPathCache } from "../paths.js";
13
+ import { checkOwnership, sliceUnitKey } from "../unit-ownership.js";
13
14
  import { saveFile, clearParseCache } from "../files.js";
14
15
  import { invalidateStateCache } from "../state.js";
15
16
  import { renderRoadmapCheckboxes } from "../markdown-renderer.js";
17
+ import { renderAllProjections } from "../workflow-projections.js";
18
+ import { writeManifest } from "../workflow-manifest.js";
19
+ import { appendEvent } from "../workflow-events.js";
16
20
  /**
17
21
  * Render slice summary markdown matching the template format.
18
22
  * YAML frontmatter uses snake_case keys for parseSummary() compatibility.
@@ -162,23 +166,48 @@ export async function handleCompleteSlice(params, basePath) {
162
166
  if (!params.milestoneId || typeof params.milestoneId !== "string" || params.milestoneId.trim() === "") {
163
167
  return { error: "milestoneId is required and must be a non-empty string" };
164
168
  }
165
- // ── Verify all tasks are complete ───────────────────────────────────────
166
- const tasks = getSliceTasks(params.milestoneId, params.sliceId);
167
- if (tasks.length === 0) {
168
- return { error: `no tasks found for slice ${params.sliceId} in milestone ${params.milestoneId}` };
169
+ // ── Ownership check (opt-in: only enforced when claim file exists) ──────
170
+ const ownershipErr = checkOwnership(basePath, sliceUnitKey(params.milestoneId, params.sliceId), params.actorName);
171
+ if (ownershipErr) {
172
+ return { error: ownershipErr };
169
173
  }
170
- const incompleteTasks = tasks.filter(t => t.status !== "complete");
171
- if (incompleteTasks.length > 0) {
172
- const incompleteIds = incompleteTasks.map(t => `${t.id} (status: ${t.status})`).join(", ");
173
- return { error: `incomplete tasks: ${incompleteIds}` };
174
- }
175
- // ── DB writes inside a transaction ──────────────────────────────────────
174
+ // ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
176
175
  const completedAt = new Date().toISOString();
176
+ let guardError = null;
177
177
  transaction(() => {
178
+ // State machine preconditions (inside txn for atomicity).
179
+ // Milestone/slice not existing is OK — insertMilestone/insertSlice below will auto-create.
180
+ // Only block if they exist and are closed.
181
+ const milestone = getMilestone(params.milestoneId);
182
+ if (milestone && (milestone.status === "complete" || milestone.status === "done")) {
183
+ guardError = `cannot complete slice in a closed milestone: ${params.milestoneId} (status: ${milestone.status})`;
184
+ return;
185
+ }
186
+ const slice = getSlice(params.milestoneId, params.sliceId);
187
+ if (slice && (slice.status === "complete" || slice.status === "done")) {
188
+ guardError = `slice ${params.sliceId} is already complete — use gsd_slice_reopen first if you need to redo it`;
189
+ return;
190
+ }
191
+ // Verify all tasks are complete
192
+ const tasks = getSliceTasks(params.milestoneId, params.sliceId);
193
+ if (tasks.length === 0) {
194
+ guardError = `no tasks found for slice ${params.sliceId} in milestone ${params.milestoneId}`;
195
+ return;
196
+ }
197
+ const incompleteTasks = tasks.filter(t => t.status !== "complete" && t.status !== "done");
198
+ if (incompleteTasks.length > 0) {
199
+ const incompleteIds = incompleteTasks.map(t => `${t.id} (status: ${t.status})`).join(", ");
200
+ guardError = `incomplete tasks: ${incompleteIds}`;
201
+ return;
202
+ }
203
+ // All guards passed — perform writes
178
204
  insertMilestone({ id: params.milestoneId });
179
205
  insertSlice({ id: params.sliceId, milestoneId: params.milestoneId });
180
206
  updateSliceStatus(params.milestoneId, params.sliceId, "complete", completedAt);
181
207
  });
208
+ if (guardError) {
209
+ return { error: guardError };
210
+ }
182
211
  // ── Filesystem operations (outside transaction) ─────────────────────────
183
212
  // If disk render fails, roll back the DB status so deriveState() and
184
213
  // verifyExpectedArtifact() stay consistent (both say "not done").
@@ -235,6 +264,22 @@ export async function handleCompleteSlice(params, basePath) {
235
264
  invalidateStateCache();
236
265
  clearPathCache();
237
266
  clearParseCache();
267
+ // ── Post-mutation hook: projections, manifest, event log ───────────────
268
+ try {
269
+ await renderAllProjections(basePath, params.milestoneId);
270
+ writeManifest(basePath);
271
+ appendEvent(basePath, {
272
+ cmd: "complete-slice",
273
+ params: { milestoneId: params.milestoneId, sliceId: params.sliceId },
274
+ ts: new Date().toISOString(),
275
+ actor: "agent",
276
+ actor_name: params.actorName,
277
+ trigger_reason: params.triggerReason,
278
+ });
279
+ }
280
+ catch (hookErr) {
281
+ process.stderr.write(`gsd: complete-slice post-mutation hook warning: ${hookErr.message}\n`);
282
+ }
238
283
  return {
239
284
  sliceId: params.sliceId,
240
285
  milestoneId: params.milestoneId,
@@ -8,11 +8,15 @@
8
8
  */
9
9
  import { join } from "node:path";
10
10
  import { mkdirSync } from "node:fs";
11
- import { transaction, insertMilestone, insertSlice, insertTask, insertVerificationEvidence, _getAdapter, } from "../gsd-db.js";
11
+ import { transaction, insertMilestone, insertSlice, insertTask, insertVerificationEvidence, getMilestone, getSlice, getTask, _getAdapter, } from "../gsd-db.js";
12
12
  import { resolveSliceFile, resolveTasksDir, clearPathCache } from "../paths.js";
13
+ import { checkOwnership, taskUnitKey } from "../unit-ownership.js";
13
14
  import { saveFile, clearParseCache } from "../files.js";
14
15
  import { invalidateStateCache } from "../state.js";
15
16
  import { renderPlanCheckboxes } from "../markdown-renderer.js";
17
+ import { renderAllProjections } from "../workflow-projections.js";
18
+ import { writeManifest } from "../workflow-manifest.js";
19
+ import { appendEvent } from "../workflow-events.js";
16
20
  /**
17
21
  * Render task summary markdown matching the template format.
18
22
  * YAML frontmatter uses snake_case keys for parseSummary() compatibility.
@@ -105,9 +109,34 @@ export async function handleCompleteTask(params, basePath) {
105
109
  if (!params.milestoneId || typeof params.milestoneId !== "string" || params.milestoneId.trim() === "") {
106
110
  return { error: "milestoneId is required and must be a non-empty string" };
107
111
  }
108
- // ── DB writes inside a transaction ──────────────────────────────────────
112
+ // ── Ownership check (opt-in: only enforced when claim file exists) ──────
113
+ const ownershipErr = checkOwnership(basePath, taskUnitKey(params.milestoneId, params.sliceId, params.taskId), params.actorName);
114
+ if (ownershipErr) {
115
+ return { error: ownershipErr };
116
+ }
117
+ // ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
109
118
  const completedAt = new Date().toISOString();
119
+ let guardError = null;
110
120
  transaction(() => {
121
+ // State machine preconditions (inside txn for atomicity).
122
+ // Milestone/slice not existing is OK — insertMilestone/insertSlice below will auto-create.
123
+ // Only block if they exist and are closed.
124
+ const milestone = getMilestone(params.milestoneId);
125
+ if (milestone && (milestone.status === "complete" || milestone.status === "done")) {
126
+ guardError = `cannot complete task in a closed milestone: ${params.milestoneId} (status: ${milestone.status})`;
127
+ return;
128
+ }
129
+ const slice = getSlice(params.milestoneId, params.sliceId);
130
+ if (slice && (slice.status === "complete" || slice.status === "done")) {
131
+ guardError = `cannot complete task in a closed slice: ${params.sliceId} (status: ${slice.status})`;
132
+ return;
133
+ }
134
+ const existingTask = getTask(params.milestoneId, params.sliceId, params.taskId);
135
+ if (existingTask && (existingTask.status === "complete" || existingTask.status === "done")) {
136
+ guardError = `task ${params.taskId} is already complete — use gsd_task_reopen first if you need to redo it`;
137
+ return;
138
+ }
139
+ // All guards passed — perform writes
111
140
  insertMilestone({ id: params.milestoneId });
112
141
  insertSlice({ id: params.sliceId, milestoneId: params.milestoneId });
113
142
  insertTask({
@@ -138,6 +167,9 @@ export async function handleCompleteTask(params, basePath) {
138
167
  });
139
168
  }
140
169
  });
170
+ if (guardError) {
171
+ return { error: guardError };
172
+ }
141
173
  // ── Filesystem operations (outside transaction) ─────────────────────────
142
174
  // If disk render fails, roll back the DB status so deriveState() and
143
175
  // verifyExpectedArtifact() stay consistent (both say "not done").
@@ -195,6 +227,22 @@ export async function handleCompleteTask(params, basePath) {
195
227
  invalidateStateCache();
196
228
  clearPathCache();
197
229
  clearParseCache();
230
+ // ── Post-mutation hook: projections, manifest, event log ───────────────
231
+ try {
232
+ await renderAllProjections(basePath, params.milestoneId);
233
+ writeManifest(basePath);
234
+ appendEvent(basePath, {
235
+ cmd: "complete-task",
236
+ params: { milestoneId: params.milestoneId, sliceId: params.sliceId, taskId: params.taskId },
237
+ ts: new Date().toISOString(),
238
+ actor: "agent",
239
+ actor_name: params.actorName,
240
+ trigger_reason: params.triggerReason,
241
+ });
242
+ }
243
+ catch (hookErr) {
244
+ process.stderr.write(`gsd: complete-task post-mutation hook warning: ${hookErr.message}\n`);
245
+ }
198
246
  return {
199
247
  taskId: params.taskId,
200
248
  sliceId: params.sliceId,
@@ -1,7 +1,10 @@
1
1
  import { clearParseCache } from "../files.js";
2
- import { transaction, insertMilestone, insertSlice, upsertMilestonePlanning, upsertSlicePlanning, } from "../gsd-db.js";
2
+ import { transaction, getMilestone, insertMilestone, insertSlice, upsertMilestonePlanning, upsertSlicePlanning, } from "../gsd-db.js";
3
3
  import { invalidateStateCache } from "../state.js";
4
4
  import { renderRoadmapFromDb } from "../markdown-renderer.js";
5
+ import { renderAllProjections } from "../workflow-projections.js";
6
+ import { writeManifest } from "../workflow-manifest.js";
7
+ import { appendEvent } from "../workflow-events.js";
5
8
  function isNonEmptyString(value) {
6
9
  return typeof value === "string" && value.trim().length > 0;
7
10
  }
@@ -142,6 +145,23 @@ export async function handlePlanMilestone(rawParams, basePath) {
142
145
  catch (err) {
143
146
  return { error: `validation failed: ${err.message}` };
144
147
  }
148
+ // ── State machine preconditions ─────────────────────────────────────────
149
+ const existingMilestone = getMilestone(params.milestoneId);
150
+ if (existingMilestone && (existingMilestone.status === "complete" || existingMilestone.status === "done")) {
151
+ return { error: `cannot re-plan milestone ${params.milestoneId}: it is already complete` };
152
+ }
153
+ // Validate depends_on: all dependencies must exist and be complete
154
+ if (params.dependsOn && params.dependsOn.length > 0) {
155
+ for (const depId of params.dependsOn) {
156
+ const dep = getMilestone(depId);
157
+ if (!dep) {
158
+ return { error: `depends_on references unknown milestone: ${depId}` };
159
+ }
160
+ if (dep.status !== "complete" && dep.status !== "done") {
161
+ return { error: `depends_on milestone ${depId} is not yet complete (status: ${dep.status})` };
162
+ }
163
+ }
164
+ }
145
165
  try {
146
166
  transaction(() => {
147
167
  insertMilestone({
@@ -198,6 +218,22 @@ export async function handlePlanMilestone(rawParams, basePath) {
198
218
  }
199
219
  invalidateStateCache();
200
220
  clearParseCache();
221
+ // ── Post-mutation hook: projections, manifest, event log ───────────────
222
+ try {
223
+ await renderAllProjections(basePath, params.milestoneId);
224
+ writeManifest(basePath);
225
+ appendEvent(basePath, {
226
+ cmd: "plan-milestone",
227
+ params: { milestoneId: params.milestoneId },
228
+ ts: new Date().toISOString(),
229
+ actor: "agent",
230
+ actor_name: params.actorName,
231
+ trigger_reason: params.triggerReason,
232
+ });
233
+ }
234
+ catch (hookErr) {
235
+ process.stderr.write(`gsd: plan-milestone post-mutation hook warning: ${hookErr.message}\n`);
236
+ }
201
237
  return {
202
238
  milestoneId: params.milestoneId,
203
239
  roadmapPath,
@@ -1,7 +1,10 @@
1
1
  import { clearParseCache } from "../files.js";
2
- import { transaction, getSlice, insertTask, upsertSlicePlanning, upsertTaskPlanning, } from "../gsd-db.js";
2
+ import { transaction, getMilestone, getSlice, insertTask, upsertSlicePlanning, upsertTaskPlanning, } from "../gsd-db.js";
3
3
  import { invalidateStateCache } from "../state.js";
4
4
  import { renderPlanFromDb } from "../markdown-renderer.js";
5
+ import { renderAllProjections } from "../workflow-projections.js";
6
+ import { writeManifest } from "../workflow-manifest.js";
7
+ import { appendEvent } from "../workflow-events.js";
5
8
  function isNonEmptyString(value) {
6
9
  return typeof value === "string" && value.trim().length > 0;
7
10
  }
@@ -99,10 +102,20 @@ export async function handlePlanSlice(rawParams, basePath) {
99
102
  catch (err) {
100
103
  return { error: `validation failed: ${err.message}` };
101
104
  }
105
+ const parentMilestone = getMilestone(params.milestoneId);
106
+ if (!parentMilestone) {
107
+ return { error: `milestone not found: ${params.milestoneId}` };
108
+ }
109
+ if (parentMilestone.status === "complete" || parentMilestone.status === "done") {
110
+ return { error: `cannot plan slice in a closed milestone: ${params.milestoneId} (status: ${parentMilestone.status})` };
111
+ }
102
112
  const parentSlice = getSlice(params.milestoneId, params.sliceId);
103
113
  if (!parentSlice) {
104
114
  return { error: `missing parent slice: ${params.milestoneId}/${params.sliceId}` };
105
115
  }
116
+ if (parentSlice.status === "complete" || parentSlice.status === "done") {
117
+ return { error: `cannot re-plan slice ${params.sliceId}: it is already complete — use gsd_slice_reopen first` };
118
+ }
106
119
  try {
107
120
  transaction(() => {
108
121
  upsertSlicePlanning(params.milestoneId, params.sliceId, {
@@ -129,6 +142,7 @@ export async function handlePlanSlice(rawParams, basePath) {
129
142
  inputs: task.inputs,
130
143
  expectedOutput: task.expectedOutput,
131
144
  observabilityImpact: task.observabilityImpact ?? "",
145
+ fullPlanMd: task.fullPlanMd,
132
146
  });
133
147
  }
134
148
  });
@@ -140,6 +154,22 @@ export async function handlePlanSlice(rawParams, basePath) {
140
154
  const renderResult = await renderPlanFromDb(basePath, params.milestoneId, params.sliceId);
141
155
  invalidateStateCache();
142
156
  clearParseCache();
157
+ // ── Post-mutation hook: projections, manifest, event log ─────────────
158
+ try {
159
+ await renderAllProjections(basePath, params.milestoneId);
160
+ writeManifest(basePath);
161
+ appendEvent(basePath, {
162
+ cmd: "plan-slice",
163
+ params: { milestoneId: params.milestoneId, sliceId: params.sliceId },
164
+ ts: new Date().toISOString(),
165
+ actor: "agent",
166
+ actor_name: params.actorName,
167
+ trigger_reason: params.triggerReason,
168
+ });
169
+ }
170
+ catch (hookErr) {
171
+ process.stderr.write(`gsd: plan-slice post-mutation hook warning: ${hookErr.message}\n`);
172
+ }
143
173
  return {
144
174
  milestoneId: params.milestoneId,
145
175
  sliceId: params.sliceId,