@opengsd/gsd-pi 1.8.1 → 1.9.0-dev.5c1a3ff2

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 (546) hide show
  1. package/README.md +10 -8
  2. package/dist/cli.js +5 -1
  3. package/dist/headless-events.d.ts +2 -1
  4. package/dist/headless-events.js +11 -3
  5. package/dist/headless-milestone-readiness.d.ts +29 -0
  6. package/dist/headless-milestone-readiness.js +161 -0
  7. package/dist/headless.js +25 -2
  8. package/dist/print-mode-exit.d.ts +12 -0
  9. package/dist/print-mode-exit.js +14 -0
  10. package/dist/resources/.managed-resources-content-hash +1 -1
  11. package/dist/resources/GSD-WORKFLOW.md +18 -49
  12. package/dist/resources/extensions/browser-tools/capture.js +2 -77
  13. package/dist/resources/extensions/browser-tools/screenshot-constraints.js +83 -0
  14. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +17 -2
  15. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +30 -2
  16. package/dist/resources/extensions/gsd/artifact-verification.js +3 -4
  17. package/dist/resources/extensions/gsd/auto-artifact-paths.js +16 -10
  18. package/dist/resources/extensions/gsd/auto-dispatch.js +74 -19
  19. package/dist/resources/extensions/gsd/auto-post-unit.js +4 -0
  20. package/dist/resources/extensions/gsd/auto-prompts.js +125 -18
  21. package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
  22. package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +4 -0
  23. package/dist/resources/extensions/gsd/auto-worktree-teardown.js +1 -1
  24. package/dist/resources/extensions/gsd/auto.js +5 -1
  25. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -4
  26. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +31 -5
  27. package/dist/resources/extensions/gsd/bootstrap/system-context.js +10 -3
  28. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +88 -50
  29. package/dist/resources/extensions/gsd/command-feedback.js +16 -12
  30. package/dist/resources/extensions/gsd/compat/compat-marker.js +19 -2
  31. package/dist/resources/extensions/gsd/constants.js +12 -13
  32. package/dist/resources/extensions/gsd/context-masker.js +97 -21
  33. package/dist/resources/extensions/gsd/db/command-queue.js +7 -2
  34. package/dist/resources/extensions/gsd/db/engine.js +51 -16
  35. package/dist/resources/extensions/gsd/db/writers/cascades.js +5 -1
  36. package/dist/resources/extensions/gsd/db/writers/status.js +13 -3
  37. package/dist/resources/extensions/gsd/db-base-schema.js +28 -0
  38. package/dist/resources/extensions/gsd/db-migration-steps.js +30 -0
  39. package/dist/resources/extensions/gsd/db-schema-metadata.js +4 -1
  40. package/dist/resources/extensions/gsd/docs/preferences-reference.md +26 -4
  41. package/dist/resources/extensions/gsd/doctor-engine-checks.js +3 -6
  42. package/dist/resources/extensions/gsd/flat-phase-migration.js +156 -21
  43. package/dist/resources/extensions/gsd/git-service.js +19 -7
  44. package/dist/resources/extensions/gsd/gsd-db.js +187 -45
  45. package/dist/resources/extensions/gsd/guided-flow.js +38 -13
  46. package/dist/resources/extensions/gsd/markdown-renderer.js +17 -13
  47. package/dist/resources/extensions/gsd/md-importer.js +107 -20
  48. package/dist/resources/extensions/gsd/migrate/command.js +19 -162
  49. package/dist/resources/extensions/gsd/migrate/execution.js +98 -0
  50. package/dist/resources/extensions/gsd/migrate/plan.js +49 -0
  51. package/dist/resources/extensions/gsd/migrate/planning-writer.js +12 -17
  52. package/dist/resources/extensions/gsd/migrate/presentation.js +64 -0
  53. package/dist/resources/extensions/gsd/model-cost-table.js +2 -0
  54. package/dist/resources/extensions/gsd/model-router.js +11 -0
  55. package/dist/resources/extensions/gsd/parallel-eligibility.js +5 -4
  56. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +28 -43
  57. package/dist/resources/extensions/gsd/paths.js +55 -11
  58. package/dist/resources/extensions/gsd/phase-anchor.js +7 -2
  59. package/dist/resources/extensions/gsd/planning-subagent-policy.js +37 -0
  60. package/dist/resources/extensions/gsd/planning-subagent-registry.js +25 -0
  61. package/dist/resources/extensions/gsd/post-execution-checks.js +4 -4
  62. package/dist/resources/extensions/gsd/preferences-types.js +5 -0
  63. package/dist/resources/extensions/gsd/preferences-validation.js +48 -1
  64. package/dist/resources/extensions/gsd/preferences.js +17 -0
  65. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  66. package/dist/resources/extensions/gsd/provider-payload-policy.js +16 -5
  67. package/dist/resources/extensions/gsd/safety/destructive-guard.js +1 -1
  68. package/dist/resources/extensions/gsd/safety/evidence-collector.js +26 -1
  69. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +30 -5
  70. package/dist/resources/extensions/gsd/skill-activation.js +17 -3
  71. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.js +27 -13
  72. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.js +13 -3
  73. package/dist/resources/extensions/gsd/stop-notice.js +15 -1
  74. package/dist/resources/extensions/gsd/sync-lock.js +13 -7
  75. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
  76. package/dist/resources/extensions/gsd/tools/complete-task.js +94 -6
  77. package/dist/resources/extensions/gsd/tools/plan-task.js +13 -15
  78. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +18 -15
  79. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +14 -5
  80. package/dist/resources/extensions/gsd/tools/reopen-slice.js +15 -5
  81. package/dist/resources/extensions/gsd/tools/reopen-task.js +16 -10
  82. package/dist/resources/extensions/gsd/tools/replan-task.js +128 -0
  83. package/dist/resources/extensions/gsd/tools/rework-brief.js +74 -0
  84. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +81 -0
  85. package/dist/resources/extensions/gsd/unit-context-composer.js +28 -5
  86. package/dist/resources/extensions/gsd/unit-registry.js +4 -0
  87. package/dist/resources/extensions/gsd/uok/plan-v2.js +19 -3
  88. package/dist/resources/extensions/gsd/workflow-projections.js +2 -3
  89. package/dist/resources/extensions/gsd/workspace.js +2 -1
  90. package/dist/resources/extensions/gsd/worktree-state-projection.js +6 -0
  91. package/dist/resources/extensions/mac-tools/index.js +31 -9
  92. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  93. package/dist/web/standalone/.next/BUILD_ID +1 -1
  94. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  95. package/dist/web/standalone/.next/build-manifest.json +3 -3
  96. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  97. package/dist/web/standalone/.next/required-server-files.json +3 -3
  98. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  99. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  101. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  109. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  111. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
  112. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  113. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  115. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  118. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  125. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  137. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  159. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  169. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  175. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  191. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  195. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app/index.html +1 -1
  205. package/dist/web/standalone/.next/server/app/index.rsc +5 -5
  206. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  207. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
  208. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  209. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  210. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  211. package/dist/web/standalone/.next/server/app/page.js +2 -2
  212. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  214. package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
  215. package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
  216. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  217. package/dist/web/standalone/.next/server/middleware.js +3 -3
  218. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  219. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  220. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  221. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
  222. package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
  223. package/dist/web/standalone/.next/static/chunks/app/page-72a856634ad14c10.js +1 -0
  224. package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
  225. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
  226. package/dist/web/standalone/.next/static/css/3b1ceb7abfb9a230.css +1 -0
  227. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  228. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  229. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  230. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  231. package/dist/web/standalone/package.json +0 -1
  232. package/dist/web/standalone/server.js +1 -1
  233. package/dist/web-mode.js +31 -3
  234. package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
  235. package/integrations/hermes/pyproject.toml +1 -1
  236. package/package.json +12 -10
  237. package/packages/cloud-mcp-gateway/package.json +2 -2
  238. package/packages/contracts/dist/workflow.d.ts +14 -0
  239. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  240. package/packages/contracts/dist/workflow.js +16 -0
  241. package/packages/contracts/dist/workflow.js.map +1 -1
  242. package/packages/contracts/package.json +1 -1
  243. package/packages/daemon/dist/cloud-config.d.ts +1 -1
  244. package/packages/daemon/dist/cloud-config.d.ts.map +1 -1
  245. package/packages/daemon/dist/cloud-config.js +5 -1
  246. package/packages/daemon/dist/cloud-config.js.map +1 -1
  247. package/packages/daemon/dist/cloud-config.test.js +51 -1
  248. package/packages/daemon/dist/cloud-config.test.js.map +1 -1
  249. package/packages/daemon/dist/local-tool-executor.d.ts.map +1 -1
  250. package/packages/daemon/dist/local-tool-executor.js +2 -0
  251. package/packages/daemon/dist/local-tool-executor.js.map +1 -1
  252. package/packages/daemon/package.json +6 -6
  253. package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
  254. package/packages/gsd-agent-core/dist/compaction/compaction.js +36 -4
  255. package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
  256. package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
  257. package/packages/gsd-agent-core/dist/sdk.js +1 -0
  258. package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
  259. package/packages/gsd-agent-core/package.json +5 -5
  260. package/packages/gsd-agent-modes/package.json +7 -7
  261. package/packages/gsd-cloud/dist/cli.d.ts +5 -0
  262. package/packages/gsd-cloud/dist/cli.d.ts.map +1 -0
  263. package/packages/gsd-cloud/dist/cli.js +160 -0
  264. package/packages/gsd-cloud/dist/cli.js.map +1 -0
  265. package/packages/gsd-cloud/dist/cloud-config.d.ts +19 -0
  266. package/packages/gsd-cloud/dist/cloud-config.d.ts.map +1 -0
  267. package/packages/gsd-cloud/dist/cloud-config.js +231 -0
  268. package/packages/gsd-cloud/dist/cloud-config.js.map +1 -0
  269. package/packages/gsd-cloud/dist/cloud-config.test.d.ts +2 -0
  270. package/packages/gsd-cloud/dist/cloud-config.test.d.ts.map +1 -0
  271. package/packages/gsd-cloud/dist/cloud-config.test.js +118 -0
  272. package/packages/gsd-cloud/dist/cloud-config.test.js.map +1 -0
  273. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts +2 -0
  274. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts.map +1 -0
  275. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js +37 -0
  276. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js.map +1 -0
  277. package/packages/gsd-cloud/dist/cloud-runtime.d.ts +35 -0
  278. package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -0
  279. package/packages/gsd-cloud/dist/cloud-runtime.js +258 -0
  280. package/packages/gsd-cloud/dist/cloud-runtime.js.map +1 -0
  281. package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts +2 -0
  282. package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts.map +1 -0
  283. package/packages/gsd-cloud/dist/cloud-runtime.test.js +88 -0
  284. package/packages/gsd-cloud/dist/cloud-runtime.test.js.map +1 -0
  285. package/packages/gsd-cloud/dist/cloud-token.d.ts +3 -0
  286. package/packages/gsd-cloud/dist/cloud-token.d.ts.map +1 -0
  287. package/packages/gsd-cloud/dist/cloud-token.js +37 -0
  288. package/packages/gsd-cloud/dist/cloud-token.js.map +1 -0
  289. package/packages/gsd-cloud/dist/config.d.ts +17 -0
  290. package/packages/gsd-cloud/dist/config.d.ts.map +1 -0
  291. package/packages/gsd-cloud/dist/config.js +146 -0
  292. package/packages/gsd-cloud/dist/config.js.map +1 -0
  293. package/packages/gsd-cloud/dist/device-flow.d.ts +24 -0
  294. package/packages/gsd-cloud/dist/device-flow.d.ts.map +1 -0
  295. package/packages/gsd-cloud/dist/device-flow.js +128 -0
  296. package/packages/gsd-cloud/dist/device-flow.js.map +1 -0
  297. package/packages/gsd-cloud/dist/device-flow.test.d.ts +2 -0
  298. package/packages/gsd-cloud/dist/device-flow.test.d.ts.map +1 -0
  299. package/packages/gsd-cloud/dist/device-flow.test.js +155 -0
  300. package/packages/gsd-cloud/dist/device-flow.test.js.map +1 -0
  301. package/packages/gsd-cloud/dist/executors/claude-executor.d.ts +6 -0
  302. package/packages/gsd-cloud/dist/executors/claude-executor.d.ts.map +1 -0
  303. package/packages/gsd-cloud/dist/executors/claude-executor.js +15 -0
  304. package/packages/gsd-cloud/dist/executors/claude-executor.js.map +1 -0
  305. package/packages/gsd-cloud/dist/executors/codex-executor.d.ts +6 -0
  306. package/packages/gsd-cloud/dist/executors/codex-executor.d.ts.map +1 -0
  307. package/packages/gsd-cloud/dist/executors/codex-executor.js +15 -0
  308. package/packages/gsd-cloud/dist/executors/codex-executor.js.map +1 -0
  309. package/packages/gsd-cloud/dist/executors/executor.d.ts +28 -0
  310. package/packages/gsd-cloud/dist/executors/executor.d.ts.map +1 -0
  311. package/packages/gsd-cloud/dist/executors/executor.js +11 -0
  312. package/packages/gsd-cloud/dist/executors/executor.js.map +1 -0
  313. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts +34 -0
  314. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts.map +1 -0
  315. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js +179 -0
  316. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js.map +1 -0
  317. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts +2 -0
  318. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts.map +1 -0
  319. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js +44 -0
  320. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js.map +1 -0
  321. package/packages/gsd-cloud/dist/executors/index.d.ts +17 -0
  322. package/packages/gsd-cloud/dist/executors/index.d.ts.map +1 -0
  323. package/packages/gsd-cloud/dist/executors/index.js +29 -0
  324. package/packages/gsd-cloud/dist/executors/index.js.map +1 -0
  325. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts +36 -0
  326. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts.map +1 -0
  327. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js +176 -0
  328. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js.map +1 -0
  329. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts +2 -0
  330. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts.map +1 -0
  331. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js +34 -0
  332. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js.map +1 -0
  333. package/packages/gsd-cloud/dist/index.d.ts +7 -0
  334. package/packages/gsd-cloud/dist/index.d.ts.map +1 -0
  335. package/packages/gsd-cloud/dist/index.js +8 -0
  336. package/packages/gsd-cloud/dist/index.js.map +1 -0
  337. package/packages/gsd-cloud/dist/inject-gateway.d.ts +16 -0
  338. package/packages/gsd-cloud/dist/inject-gateway.d.ts.map +1 -0
  339. package/packages/gsd-cloud/dist/inject-gateway.js +29 -0
  340. package/packages/gsd-cloud/dist/inject-gateway.js.map +1 -0
  341. package/packages/gsd-cloud/dist/inject-gateway.test.d.ts +2 -0
  342. package/packages/gsd-cloud/dist/inject-gateway.test.d.ts.map +1 -0
  343. package/packages/gsd-cloud/dist/inject-gateway.test.js +41 -0
  344. package/packages/gsd-cloud/dist/inject-gateway.test.js.map +1 -0
  345. package/packages/gsd-cloud/dist/logger.d.ts +25 -0
  346. package/packages/gsd-cloud/dist/logger.d.ts.map +1 -0
  347. package/packages/gsd-cloud/dist/logger.js +72 -0
  348. package/packages/gsd-cloud/dist/logger.js.map +1 -0
  349. package/packages/gsd-cloud/dist/types.d.ts +51 -0
  350. package/packages/gsd-cloud/dist/types.d.ts.map +1 -0
  351. package/packages/gsd-cloud/dist/types.js +9 -0
  352. package/packages/gsd-cloud/dist/types.js.map +1 -0
  353. package/packages/gsd-cloud/package.json +3 -3
  354. package/packages/mcp-server/README.md +15 -2
  355. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  356. package/packages/mcp-server/dist/server.js +5 -5
  357. package/packages/mcp-server/dist/server.js.map +1 -1
  358. package/packages/mcp-server/dist/workflow-tools.d.ts +4 -3
  359. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  360. package/packages/mcp-server/dist/workflow-tools.js +64 -2
  361. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  362. package/packages/mcp-server/package.json +4 -4
  363. package/packages/native/package.json +1 -1
  364. package/packages/pi-agent-core/dist/agent.d.ts +5 -1
  365. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  366. package/packages/pi-agent-core/dist/agent.js +2 -0
  367. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  368. package/packages/pi-agent-core/package.json +1 -1
  369. package/packages/pi-ai/dist/models.generated.d.ts +119 -0
  370. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  371. package/packages/pi-ai/dist/models.generated.js +107 -0
  372. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  373. package/packages/pi-ai/dist/providers/amazon-bedrock.js +1 -0
  374. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  375. package/packages/pi-ai/dist/providers/anthropic.js +25 -1
  376. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  377. package/packages/pi-ai/dist/providers/openai-codex-responses.js +1 -1
  378. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  379. package/packages/pi-ai/dist/providers/openai-responses.js +1 -1
  380. package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
  381. package/packages/pi-ai/package.json +1 -1
  382. package/packages/pi-coding-agent/dist/core/capability-patches.js +1 -1
  383. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  384. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -1
  385. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  386. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +11 -1
  387. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  388. package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
  389. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  390. package/packages/pi-coding-agent/package.json +7 -7
  391. package/packages/pi-tui/package.json +2 -2
  392. package/packages/rpc-client/package.json +2 -2
  393. package/pkg/package.json +1 -1
  394. package/src/resources/GSD-WORKFLOW.md +18 -49
  395. package/src/resources/extensions/browser-tools/capture.ts +2 -86
  396. package/src/resources/extensions/browser-tools/screenshot-constraints.ts +94 -0
  397. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +18 -1
  398. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -0
  399. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +30 -2
  400. package/src/resources/extensions/gsd/artifact-verification.ts +3 -8
  401. package/src/resources/extensions/gsd/auto-artifact-paths.ts +16 -9
  402. package/src/resources/extensions/gsd/auto-dispatch.ts +86 -19
  403. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -0
  404. package/src/resources/extensions/gsd/auto-prompts.ts +142 -16
  405. package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
  406. package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +4 -0
  407. package/src/resources/extensions/gsd/auto-worktree-teardown.ts +1 -1
  408. package/src/resources/extensions/gsd/auto.ts +5 -1
  409. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +92 -4
  410. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +39 -10
  411. package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -3
  412. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +87 -53
  413. package/src/resources/extensions/gsd/command-feedback.ts +19 -12
  414. package/src/resources/extensions/gsd/compat/compat-marker.ts +21 -4
  415. package/src/resources/extensions/gsd/constants.ts +14 -13
  416. package/src/resources/extensions/gsd/context-masker.ts +98 -2
  417. package/src/resources/extensions/gsd/db/command-queue.ts +7 -1
  418. package/src/resources/extensions/gsd/db/engine.ts +53 -17
  419. package/src/resources/extensions/gsd/db/writers/cascades.ts +5 -1
  420. package/src/resources/extensions/gsd/db/writers/status.ts +25 -8
  421. package/src/resources/extensions/gsd/db-base-schema.ts +30 -0
  422. package/src/resources/extensions/gsd/db-migration-steps.ts +32 -0
  423. package/src/resources/extensions/gsd/db-schema-metadata.ts +4 -1
  424. package/src/resources/extensions/gsd/docs/preferences-reference.md +26 -4
  425. package/src/resources/extensions/gsd/doctor-engine-checks.ts +3 -5
  426. package/src/resources/extensions/gsd/flat-phase-migration.ts +160 -19
  427. package/src/resources/extensions/gsd/git-service.ts +19 -6
  428. package/src/resources/extensions/gsd/gsd-db.ts +255 -52
  429. package/src/resources/extensions/gsd/guided-flow.ts +48 -12
  430. package/src/resources/extensions/gsd/markdown-renderer.ts +25 -21
  431. package/src/resources/extensions/gsd/md-importer.ts +114 -16
  432. package/src/resources/extensions/gsd/migrate/command.ts +21 -227
  433. package/src/resources/extensions/gsd/migrate/execution.ts +136 -0
  434. package/src/resources/extensions/gsd/migrate/plan.ts +101 -0
  435. package/src/resources/extensions/gsd/migrate/planning-writer.ts +12 -20
  436. package/src/resources/extensions/gsd/migrate/presentation.ts +83 -0
  437. package/src/resources/extensions/gsd/model-cost-table.ts +2 -0
  438. package/src/resources/extensions/gsd/model-router.ts +12 -0
  439. package/src/resources/extensions/gsd/parallel-eligibility.ts +5 -4
  440. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +37 -40
  441. package/src/resources/extensions/gsd/paths.ts +62 -11
  442. package/src/resources/extensions/gsd/phase-anchor.ts +8 -2
  443. package/src/resources/extensions/gsd/planning-subagent-policy.ts +58 -0
  444. package/src/resources/extensions/gsd/planning-subagent-registry.ts +31 -0
  445. package/src/resources/extensions/gsd/post-execution-checks.ts +4 -4
  446. package/src/resources/extensions/gsd/preferences-types.ts +16 -0
  447. package/src/resources/extensions/gsd/preferences-validation.ts +62 -0
  448. package/src/resources/extensions/gsd/preferences.ts +25 -0
  449. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  450. package/src/resources/extensions/gsd/provider-payload-policy.ts +18 -4
  451. package/src/resources/extensions/gsd/safety/destructive-guard.ts +1 -1
  452. package/src/resources/extensions/gsd/safety/evidence-collector.ts +28 -1
  453. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +31 -5
  454. package/src/resources/extensions/gsd/skill-activation.ts +17 -3
  455. package/src/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.ts +30 -13
  456. package/src/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.ts +16 -3
  457. package/src/resources/extensions/gsd/state-reconciliation/types.ts +2 -2
  458. package/src/resources/extensions/gsd/stop-notice.ts +18 -1
  459. package/src/resources/extensions/gsd/sync-lock.ts +14 -6
  460. package/src/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
  461. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +7 -7
  462. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +39 -0
  463. package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +55 -0
  464. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +96 -1
  465. package/src/resources/extensions/gsd/tests/command-feedback.test.ts +12 -0
  466. package/src/resources/extensions/gsd/tests/compat-marker.test.ts +104 -0
  467. package/src/resources/extensions/gsd/tests/complete-task.test.ts +362 -1
  468. package/src/resources/extensions/gsd/tests/context-masker.test.ts +204 -8
  469. package/src/resources/extensions/gsd/tests/db-engine-migrate-guards.test.ts +186 -0
  470. package/src/resources/extensions/gsd/tests/db-tools-alias-suppression.test.ts +62 -0
  471. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +29 -0
  472. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +33 -0
  473. package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +14 -0
  474. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +123 -0
  475. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +50 -0
  476. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +49 -0
  477. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +81 -0
  478. package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +22 -0
  479. package/src/resources/extensions/gsd/tests/external-edit-scoped-import.test.ts +262 -0
  480. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +202 -0
  481. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +29 -0
  482. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +25 -0
  483. package/src/resources/extensions/gsd/tests/import-slice-milestone-completion-preserve.test.ts +116 -0
  484. package/src/resources/extensions/gsd/tests/integration/paths.test.ts +22 -4
  485. package/src/resources/extensions/gsd/tests/integration-branch-meta-location.test.ts +62 -0
  486. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +5 -5
  487. package/src/resources/extensions/gsd/tests/migrate-plan.test.ts +68 -0
  488. package/src/resources/extensions/gsd/tests/migrate-presentation.test.ts +98 -0
  489. package/src/resources/extensions/gsd/tests/migrate-safety-audit.test.ts +1 -1
  490. package/src/resources/extensions/gsd/tests/milestone-leases.test.ts +55 -0
  491. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
  492. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  493. package/src/resources/extensions/gsd/tests/parallel-eligibility-file-overlap.test.ts +146 -0
  494. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +59 -0
  495. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +7 -5
  496. package/src/resources/extensions/gsd/tests/phase-anchor.test.ts +32 -4
  497. package/src/resources/extensions/gsd/tests/plan-task.test.ts +26 -23
  498. package/src/resources/extensions/gsd/tests/planning-writer.test.ts +29 -0
  499. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +22 -0
  500. package/src/resources/extensions/gsd/tests/preferences.test.ts +84 -0
  501. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +4 -0
  502. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +66 -0
  503. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +39 -0
  504. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +50 -0
  505. package/src/resources/extensions/gsd/tests/replan-task-handler.test.ts +103 -0
  506. package/src/resources/extensions/gsd/tests/rework-brief.test.ts +197 -0
  507. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  508. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +33 -7
  509. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -16
  510. package/src/resources/extensions/gsd/tests/skip-slice-cascades-tasks.test.ts +21 -0
  511. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +17 -0
  512. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +19 -0
  513. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +13 -7
  514. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -0
  515. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +73 -0
  516. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +93 -1
  517. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -0
  518. package/src/resources/extensions/gsd/tests/workflow-migration-gates.test.ts +139 -0
  519. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -4
  520. package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +36 -0
  521. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +34 -0
  522. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +52 -0
  523. package/src/resources/extensions/gsd/tools/complete-task.ts +140 -5
  524. package/src/resources/extensions/gsd/tools/plan-task.ts +14 -16
  525. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +18 -17
  526. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +24 -5
  527. package/src/resources/extensions/gsd/tools/reopen-slice.ts +25 -5
  528. package/src/resources/extensions/gsd/tools/reopen-task.ts +23 -9
  529. package/src/resources/extensions/gsd/tools/replan-task.ts +160 -0
  530. package/src/resources/extensions/gsd/tools/rework-brief.ts +91 -0
  531. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +92 -0
  532. package/src/resources/extensions/gsd/types.ts +11 -0
  533. package/src/resources/extensions/gsd/unit-context-composer.ts +34 -8
  534. package/src/resources/extensions/gsd/unit-registry.ts +4 -0
  535. package/src/resources/extensions/gsd/uok/plan-v2.ts +20 -3
  536. package/src/resources/extensions/gsd/workflow-projections.ts +2 -3
  537. package/src/resources/extensions/gsd/workspace.ts +2 -1
  538. package/src/resources/extensions/gsd/worktree-state-projection.ts +12 -0
  539. package/src/resources/extensions/mac-tools/index.ts +52 -9
  540. package/src/resources/extensions/mac-tools/tests/mac-screenshot-payload.test.cjs +70 -0
  541. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
  542. package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +0 -1
  543. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
  544. package/dist/web/standalone/.next/static/css/18c2fdf261bfc1b7.css +0 -1
  545. /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → 6YWV7VAPg-jqjfPswrKZb}/_buildManifest.js +0 -0
  546. /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → 6YWV7VAPg-jqjfPswrKZb}/_ssgManifest.js +0 -0
@@ -37,22 +37,29 @@ function requireDb() {
37
37
  export function applyStatusTransition(t) {
38
38
  const db = requireDb();
39
39
  const completedAt = t.completedAt ?? null;
40
+ const preserve = t.preserveCompletion ? 1 : 0;
40
41
  switch (t.entity) {
41
42
  case "task":
42
- db.prepare(`UPDATE tasks SET status = :status, completed_at = :completed_at
43
+ db.prepare(`UPDATE tasks SET status = :status,
44
+ completed_at = CASE WHEN :preserve_completion = 1 AND tasks.completed_at IS NOT NULL
45
+ THEN tasks.completed_at ELSE :completed_at END
43
46
  WHERE milestone_id = :milestone_id AND slice_id = :slice_id AND id = :id`).run({
44
47
  ":status": t.status,
45
48
  ":completed_at": completedAt,
49
+ ":preserve_completion": preserve,
46
50
  ":milestone_id": t.milestoneId,
47
51
  ":slice_id": t.sliceId,
48
52
  ":id": t.taskId,
49
53
  });
50
54
  return;
51
55
  case "slice":
52
- db.prepare(`UPDATE slices SET status = :status, completed_at = :completed_at
56
+ db.prepare(`UPDATE slices SET status = :status,
57
+ completed_at = CASE WHEN :preserve_completion = 1 AND slices.completed_at IS NOT NULL
58
+ THEN slices.completed_at ELSE :completed_at END
53
59
  WHERE milestone_id = :milestone_id AND id = :id`).run({
54
60
  ":status": t.status,
55
61
  ":completed_at": completedAt,
62
+ ":preserve_completion": preserve,
56
63
  ":milestone_id": t.milestoneId,
57
64
  ":id": t.sliceId,
58
65
  });
@@ -63,7 +70,10 @@ export function applyStatusTransition(t) {
63
70
  if (currentStatus && isClosedStatus(currentStatus) && !isClosedStatus(t.status)) {
64
71
  throw new Error(`Cannot update closed milestone ${t.milestoneId} from ${currentStatus} to ${t.status}; use gsd_milestone_reopen for an explicit reopen.`);
65
72
  }
66
- db.prepare(`UPDATE milestones SET status = :status, completed_at = :completed_at WHERE id = :id`).run({ ":status": t.status, ":completed_at": completedAt, ":id": t.milestoneId });
73
+ db.prepare(`UPDATE milestones SET status = :status,
74
+ completed_at = CASE WHEN :preserve_completion = 1 AND milestones.completed_at IS NOT NULL
75
+ THEN milestones.completed_at ELSE :completed_at END
76
+ WHERE id = :id`).run({ ":status": t.status, ":completed_at": completedAt, ":preserve_completion": preserve, ":id": t.milestoneId });
67
77
  return;
68
78
  }
69
79
  }
@@ -221,6 +221,32 @@ export function createBaseSchemaObjects(db, hooks) {
221
221
  created_at TEXT NOT NULL DEFAULT '',
222
222
  FOREIGN KEY (milestone_id) REFERENCES milestones(id)
223
223
  )
224
+ `);
225
+ db.exec(`
226
+ CREATE TABLE IF NOT EXISTS rework_briefs (
227
+ id TEXT PRIMARY KEY,
228
+ milestone_id TEXT NOT NULL DEFAULT '',
229
+ slice_id TEXT NOT NULL DEFAULT '',
230
+ task_id TEXT NOT NULL DEFAULT '',
231
+ created_at TEXT NOT NULL DEFAULT '',
232
+ updated_at TEXT NOT NULL DEFAULT ''
233
+ )
234
+ `);
235
+ db.exec(`
236
+ CREATE TABLE IF NOT EXISTS rework_brief_findings (
237
+ brief_id TEXT NOT NULL,
238
+ finding_id TEXT NOT NULL,
239
+ severity TEXT NOT NULL DEFAULT 'blocking',
240
+ description TEXT NOT NULL DEFAULT '',
241
+ required_fix TEXT NOT NULL DEFAULT '',
242
+ verification_commands TEXT NOT NULL DEFAULT '[]',
243
+ status TEXT NOT NULL DEFAULT 'pending',
244
+ evidence TEXT NOT NULL DEFAULT '',
245
+ decision_ref TEXT NOT NULL DEFAULT '',
246
+ updated_at TEXT NOT NULL DEFAULT '',
247
+ PRIMARY KEY (brief_id, finding_id),
248
+ FOREIGN KEY (brief_id) REFERENCES rework_briefs(id)
249
+ )
224
250
  `);
225
251
  db.exec(`
226
252
  CREATE TABLE IF NOT EXISTS assessments (
@@ -336,6 +362,8 @@ export function createBaseSchemaObjects(db, hooks) {
336
362
  `);
337
363
  db.exec("CREATE INDEX IF NOT EXISTS idx_memories_active ON memories(superseded_by)");
338
364
  db.exec("CREATE INDEX IF NOT EXISTS idx_replan_history_milestone ON replan_history(milestone_id, created_at)");
365
+ db.exec("CREATE INDEX IF NOT EXISTS idx_rework_briefs_task ON rework_briefs(milestone_id, slice_id, task_id)");
366
+ db.exec("CREATE INDEX IF NOT EXISTS idx_rework_findings_status ON rework_brief_findings(brief_id, severity, status)");
339
367
  db.exec("CREATE INDEX IF NOT EXISTS idx_tasks_active ON tasks(milestone_id, slice_id, status)");
340
368
  db.exec("CREATE INDEX IF NOT EXISTS idx_slices_active ON slices(milestone_id, status)");
341
369
  db.exec("CREATE INDEX IF NOT EXISTS idx_milestones_status ON milestones(status)");
@@ -418,3 +418,33 @@ export function applyMigrationV22QualityGateRepair(db, hooks) {
418
418
  ensureColumn(db, "quality_gates", "scope", "ALTER TABLE quality_gates ADD COLUMN scope TEXT NOT NULL DEFAULT 'slice'");
419
419
  ensureColumn(db, "assessments", "scope", "ALTER TABLE assessments ADD COLUMN scope TEXT NOT NULL DEFAULT ''");
420
420
  }
421
+ export function applyMigrationV30ReworkBriefs(db) {
422
+ db.exec(`
423
+ CREATE TABLE IF NOT EXISTS rework_briefs (
424
+ id TEXT PRIMARY KEY,
425
+ milestone_id TEXT NOT NULL DEFAULT '',
426
+ slice_id TEXT NOT NULL DEFAULT '',
427
+ task_id TEXT NOT NULL DEFAULT '',
428
+ created_at TEXT NOT NULL DEFAULT '',
429
+ updated_at TEXT NOT NULL DEFAULT ''
430
+ )
431
+ `);
432
+ db.exec(`
433
+ CREATE TABLE IF NOT EXISTS rework_brief_findings (
434
+ brief_id TEXT NOT NULL,
435
+ finding_id TEXT NOT NULL,
436
+ severity TEXT NOT NULL DEFAULT 'blocking',
437
+ description TEXT NOT NULL DEFAULT '',
438
+ required_fix TEXT NOT NULL DEFAULT '',
439
+ verification_commands TEXT NOT NULL DEFAULT '[]',
440
+ status TEXT NOT NULL DEFAULT 'pending',
441
+ evidence TEXT NOT NULL DEFAULT '',
442
+ decision_ref TEXT NOT NULL DEFAULT '',
443
+ updated_at TEXT NOT NULL DEFAULT '',
444
+ PRIMARY KEY (brief_id, finding_id),
445
+ FOREIGN KEY (brief_id) REFERENCES rework_briefs(id)
446
+ )
447
+ `);
448
+ db.exec("CREATE INDEX IF NOT EXISTS idx_rework_briefs_task ON rework_briefs(milestone_id, slice_id, task_id)");
449
+ db.exec("CREATE INDEX IF NOT EXISTS idx_rework_findings_status ON rework_brief_findings(brief_id, severity, status)");
450
+ }
@@ -12,8 +12,11 @@ export function ensureColumn(db, table, column, ddl) {
12
12
  db.exec(ddl);
13
13
  }
14
14
  export function getCurrentSchemaVersion(db) {
15
+ // MAX(version) on an empty table returns a row whose value is NULL —
16
+ // treat that (and any non-numeric value) as version 0, not NULL-as-number.
15
17
  const row = db.prepare("SELECT MAX(version) as v FROM schema_version").get();
16
- return row ? row["v"] : 0;
18
+ const v = row?.["v"];
19
+ return typeof v === "number" ? v : 0;
17
20
  }
18
21
  export function recordSchemaVersion(db, version) {
19
22
  db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
@@ -128,7 +128,7 @@ Diagnostics record the file path, scope (global/project), severity (error/warnin
128
128
  - Two equivalent ways to set it: inline as `models.<phase>.thinking`, or as a separate `thinking:` block keyed by phase. For the same phase, the inline value wins over the block; project preferences win over global; a phase that's unset inherits via the same sibling chain as `models` (e.g. `discuss → planning`).
129
129
  - If no thinking is configured for a phase, the session level (set via `/model`) is used, exactly as before — this is fully backward-compatible.
130
130
  - `execute-task` (code-writing) has a measured reasoning floor of `medium`: at lower levels models stop planning edits and thrash on file re-reads. The floor applies to the session/default path. An **explicit** `execution` thinking level bypasses the floor and is honored verbatim (with a one-time advisory) — set `execution: low` deliberately if you want it.
131
- - Levels a model can't support are clamped to the nearest supported level at dispatch and never sent to the provider, so a model/level mismatch never fails a unit mid-run. `xhigh` is only honored by select model families.
131
+ - Levels a model can't support are clamped to the nearest supported level at dispatch and never sent to the provider, so a model/level mismatch never fails a unit mid-run. `xhigh` support is model-dependent; current examples include OpenAI Codex Max models and Claude Sonnet 5 on Amazon Bedrock.
132
132
 
133
133
  - `skill_staleness_days`: number — skills unused for this many days get deprioritized during discovery. Set to `0` to disable staleness tracking. Default: `60`.
134
134
 
@@ -357,6 +357,28 @@ In `"parent"` mode, slice/task `targetRepositories` default to the declared chil
357
357
  - `"replace"` requires `prompt`.
358
358
  - `"skip"` is valid with no additional fields.
359
359
 
360
+ - `planning_subagents`: object — project-local widening for read-only planning subagent dispatch. Supported unit keys are `plan-milestone` and `plan-slice`; each has:
361
+ - `allowed`: string[] — additional planning-safe agents for that unit.
362
+
363
+ Agents must already be classified by GSD as read-only planning specialists: `mnemo`, `scout`, `planner`, `reviewer`, `security`, or `tester`. The write gate still blocks source writes outside `.gsd/**`, unrestricted bash, stale subagent calls without agent identities, agents outside the global read-only registry, and agents not listed for the active unit.
364
+
365
+ Example:
366
+
367
+ ```yaml
368
+ planning_subagents:
369
+ plan-milestone:
370
+ allowed:
371
+ - scout
372
+ - planner
373
+ - security
374
+ plan-slice:
375
+ allowed:
376
+ - scout
377
+ - planner
378
+ - reviewer
379
+ - security
380
+ ```
381
+
360
382
  **Known unit types for `before`/`after`:** `research-milestone`, `plan-milestone`, `research-slice`, `plan-slice`, `execute-task`, `complete-slice`, `replan-slice`, `reassess-roadmap`, `run-uat`.
361
383
 
362
384
  - `experimental`: opt-in experimental features. All features here are **off by default** — you must explicitly set each one to `true` to enable it. Features in this block may change or be removed without a deprecation cycle while in experimental status. Keys:
@@ -482,13 +504,13 @@ Inline form — thinking pinned alongside the model:
482
504
  version: 1
483
505
  models:
484
506
  planning:
485
- model: openai-codex/gpt-5.4
507
+ model: bedrock/global.anthropic.claude-sonnet-5
486
508
  thinking: xhigh
487
509
  execution:
488
- model: openai-codex/gpt-5.4
510
+ model: bedrock/global.anthropic.claude-sonnet-5
489
511
  thinking: low # explicit → bypasses the execute-task medium floor
490
512
  validation:
491
- model: openai-codex/gpt-5.4
513
+ model: bedrock/global.anthropic.claude-sonnet-5
492
514
  thinking: high
493
515
  ---
494
516
  ```
@@ -3,7 +3,7 @@ import { isAbsolute, join, relative, sep } from "node:path";
3
3
  import { deleteArtifactByPath, getAllMilestones, getMilestoneSlices, getSliceTasks, isDbAvailable, isMemoriesFtsAvailable, repairTaskCompletionFromSummary, _getAdapter, } from "./gsd-db.js";
4
4
  import { MEMORIES_FTS_REBUILT_KEY } from "./db-memory-fts-schema.js";
5
5
  import { isAfter, latestExplicitReopenAt } from "./milestone-reopen-events.js";
6
- import { buildTaskFileName, gsdProjectionRoot, gsdRoot, resolveGsdPathContract, resolveMilestoneFile, resolveMilestonePath, resolveSliceFile, } from "./paths.js";
6
+ import { gsdProjectionRoot, gsdRoot, resolveGsdPathContract, resolveMilestoneFile, resolveSliceFile, resolveTaskFile, } from "./paths.js";
7
7
  import { deriveState } from "./state.js";
8
8
  import { isClosedStatus } from "./status-guards.js";
9
9
  import { workflowEventLogPath } from "./workflow-event-ledger.js";
@@ -152,11 +152,8 @@ function resolveFlatPhaseArtifactDiskPath(basePath, row) {
152
152
  if (!artifactType)
153
153
  return null;
154
154
  if (row.slice_id && row.task_id) {
155
- const phaseDir = resolveMilestonePath(basePath, row.milestone_id);
156
- if (!phaseDir || !isFlatPhaseDiskPath(basePath, phaseDir))
157
- return null;
158
- const candidate = join(phaseDir, buildTaskFileName(row.task_id, artifactType));
159
- return existsSync(candidate) ? candidate : null;
155
+ const candidate = resolveTaskFile(basePath, row.milestone_id, row.slice_id, row.task_id, artifactType);
156
+ return candidate && isFlatPhaseDiskPath(basePath, candidate) ? candidate : null;
160
157
  }
161
158
  const candidate = row.slice_id
162
159
  ? resolveSliceFile(basePath, row.milestone_id, row.slice_id, artifactType)
@@ -4,12 +4,12 @@
4
4
  import { cpSync, existsSync, mkdirSync, readdirSync, renameSync, rmSync, statSync } from "node:fs";
5
5
  import { join } from "node:path";
6
6
  import { renderAllFromDb, renderRoadmapFromDb } from "./markdown-renderer.js";
7
- import { deleteArtifactsByPathPrefix, getAllMilestones, getMilestoneSlices } from "./gsd-db.js";
7
+ import { deleteArtifactByPath, deleteArtifactsByPathPrefix, getAllMilestones, getArtifactsByPathPrefix, getMilestoneSlices, } from "./gsd-db.js";
8
8
  import { migrateFromMarkdown } from "./md-importer.js";
9
9
  import { countDbHierarchy } from "./migration-auto-check.js";
10
10
  import { logWarning } from "./workflow-logger.js";
11
11
  import { LAYOUT_SEGMENTS } from "./layout-policy.js";
12
- import { canonicalPhaseDirName, dirIsContentBearingLegacyMilestone, milestonesDir, resolveMilestonePath, } from "./paths.js";
12
+ import { canonicalPhaseDirName, dirIsContentBearingLegacyMilestone, gsdProjectionRoot, milestonesDir, resolveMilestonePath, } from "./paths.js";
13
13
  const LEGACY_MIGRATING_SEGMENT = "milestones.migrating";
14
14
  const RETRYABLE_FS_ERROR_CODES = new Set(["EPERM", "EBUSY", "ENOTEMPTY"]);
15
15
  const RM_RETRY_OPTIONS = { recursive: true, force: true, maxRetries: 5, retryDelay: 100 };
@@ -60,6 +60,46 @@ function expectedPhaseDirs(basePath) {
60
60
  return getAllMilestones().map((milestone) => resolveMilestonePath(basePath, milestone.id) ??
61
61
  join(milestonesDir(basePath), canonicalPhaseDirName(milestone.id, milestone.title)));
62
62
  }
63
+ /**
64
+ * Return the most-recent existing `.gsd-backups/migrate-<ts>/` snapshot, or null.
65
+ *
66
+ * The flat-phase migration can re-fire on later dispatches when the legacy
67
+ * `.gsd/milestones/` layout reappears (e.g. a marker-key mismatch re-triggers a
68
+ * whole-tree re-import — issue #1292). The DB was already reconciled from that
69
+ * tree before the backup step runs, so re-snapshotting an identical legacy tree
70
+ * on every dispatch only leaks a fresh `migrate-<ts>/` directory each time. When
71
+ * a prior snapshot already exists we reuse it as the rollback fallback instead
72
+ * of creating a duplicate, bounding the accumulation to one recovery copy.
73
+ */
74
+ function existingMigrateBackup(basePath) {
75
+ const backupRoot = join(basePath, ".gsd-backups");
76
+ if (!existsSync(backupRoot))
77
+ return null;
78
+ try {
79
+ let latest = null;
80
+ for (const entry of readdirSync(backupRoot)) {
81
+ if (!entry.startsWith("migrate-"))
82
+ continue;
83
+ const dirPath = join(backupRoot, entry);
84
+ try {
85
+ const st = statSync(dirPath);
86
+ if (!st.isDirectory())
87
+ continue;
88
+ if (!hasLegacyMilestoneSubdirs(dirPath))
89
+ continue;
90
+ if (!latest || st.mtimeMs > latest.mtimeMs)
91
+ latest = { path: dirPath, mtimeMs: st.mtimeMs };
92
+ }
93
+ catch {
94
+ // Non-fatal: skip unreadable entries.
95
+ }
96
+ }
97
+ return latest?.path ?? null;
98
+ }
99
+ catch {
100
+ return null;
101
+ }
102
+ }
63
103
  function hasLegacyMilestoneSubdirs(dirPath) {
64
104
  if (!existsSync(dirPath))
65
105
  return false;
@@ -70,7 +110,58 @@ function hasLegacyMilestoneSubdirs(dirPath) {
70
110
  return false;
71
111
  }
72
112
  }
73
- function rollbackPartialMigration(basePath, backupDir, migratingPath) {
113
+ function backupFlatProjectionIfPresent(basePath, phasesPath, backupDir) {
114
+ if (!existsSync(phasesPath))
115
+ return;
116
+ const phaseBackupDir = join(backupDir, "__phases");
117
+ try {
118
+ mkdirSync(backupDir, { recursive: true });
119
+ if (existsSync(phaseBackupDir)) {
120
+ removePathWithRetries(phaseBackupDir);
121
+ }
122
+ fsOps.cpSync(phasesPath, phaseBackupDir, { recursive: true, force: true });
123
+ }
124
+ catch (err) {
125
+ logWarning("migration", `flat-phase projection backup failed: ${err.message}`);
126
+ throw err;
127
+ }
128
+ }
129
+ function isInsideFlatProjectionBackup(backupDir, src) {
130
+ const phaseBackupDir = join(backupDir, "__phases");
131
+ return src === phaseBackupDir || src.startsWith(`${phaseBackupDir}/`) || src.startsWith(`${phaseBackupDir}\\`);
132
+ }
133
+ function restoreFlatProjectionFromBackup(basePath, backupDir) {
134
+ const phaseBackupDir = join(backupDir, "__phases");
135
+ if (!existsSync(phaseBackupDir))
136
+ return;
137
+ const phasesPath = join(basePath, ".gsd", LAYOUT_SEGMENTS.level1);
138
+ try {
139
+ if (existsSync(phasesPath)) {
140
+ removePathWithRetries(phasesPath);
141
+ }
142
+ mkdirSync(join(basePath, ".gsd"), { recursive: true });
143
+ cpSync(phaseBackupDir, phasesPath, { recursive: true });
144
+ }
145
+ catch (restoreErr) {
146
+ logWarning("migration", `rollback: could not restore ${LAYOUT_SEGMENTS.level1}/ from backup: ${restoreErr.message}`);
147
+ }
148
+ }
149
+ function pruneStaleFlatPhaseArtifactRows(basePath) {
150
+ const projectionRoot = gsdProjectionRoot(basePath);
151
+ let pruned = 0;
152
+ for (const row of getArtifactsByPathPrefix(`${LAYOUT_SEGMENTS.level1}/`)) {
153
+ if (existsSync(join(projectionRoot, row.path)))
154
+ continue;
155
+ const staleTaskPlan = row.artifact_type.toUpperCase() === "PLAN" && Boolean(row.task_id);
156
+ const skippedEmptyArtifact = row.full_content.trim() === "";
157
+ if (!staleTaskPlan && !skippedEmptyArtifact)
158
+ continue;
159
+ deleteArtifactByPath(row.path);
160
+ pruned++;
161
+ }
162
+ return pruned;
163
+ }
164
+ function rollbackPartialMigration(basePath, backupDir, migratingPath, backupCreatedThisRun = true) {
74
165
  // Remove the partially-written phases/ dir.
75
166
  try {
76
167
  removePathWithRetries(join(basePath, ".gsd", LAYOUT_SEGMENTS.level1));
@@ -83,7 +174,7 @@ function rollbackPartialMigration(basePath, backupDir, migratingPath) {
83
174
  // preserved migrating tree (the sole surviving data source) and must never be
84
175
  // removed here. Deleting the backup after a successful rollback keeps the gate
85
176
  // from leaking one .gsd-backups/migrate-<ts>/ per session_start.
86
- const isDisposableBackup = Boolean(backupDir) && backupDir !== migratingPath;
177
+ const isDisposableBackup = Boolean(backupDir) && backupDir !== migratingPath && backupCreatedThisRun;
87
178
  const cleanupBackup = () => {
88
179
  if (!isDisposableBackup || !existsSync(backupDir))
89
180
  return;
@@ -99,11 +190,16 @@ function rollbackPartialMigration(basePath, backupDir, migratingPath) {
99
190
  try {
100
191
  if (migratingPath && existsSync(migratingPath) && !existsSync(milestonesPath)) {
101
192
  movePathWithCopyDeleteFallback(migratingPath, milestonesPath);
193
+ restoreFlatProjectionFromBackup(basePath, backupDir);
102
194
  cleanupBackup();
103
195
  return;
104
196
  }
105
197
  if (existsSync(backupDir)) {
106
- cpSync(backupDir, milestonesPath, { recursive: true });
198
+ cpSync(backupDir, milestonesPath, {
199
+ recursive: true,
200
+ filter: (src) => !isInsideFlatProjectionBackup(backupDir, src),
201
+ });
202
+ restoreFlatProjectionFromBackup(basePath, backupDir);
107
203
  cleanupBackup();
108
204
  }
109
205
  if (migratingPath && existsSync(migratingPath)) {
@@ -204,17 +300,33 @@ export async function migrateToFlatPhase(basePath) {
204
300
  return;
205
301
  }
206
302
  let backupDir = migratingPath;
303
+ let backupCreatedThisRun = false;
207
304
  if (!resumingInterrupted) {
208
- // 2. Backup (only reached when the DB has rows and migration will proceed)
209
- const ts = Date.now();
210
- backupDir = join(basePath, ".gsd-backups", `migrate-${ts}`);
211
- try {
212
- mkdirSync(join(basePath, ".gsd-backups"), { recursive: true });
213
- cpSync(milestonesPath, backupDir, { recursive: true });
305
+ // 2. Backup (only reached when the DB has rows and migration will proceed).
306
+ // migrateFromMarkdown above already reconciled the legacy tree into the DB,
307
+ // so its content is safely persisted. If a prior successful migration
308
+ // already snapshotted the legacy tree, a re-fire of this gate (issue #1292:
309
+ // marker-key mismatch re-importing the whole tree at dispatch boundaries)
310
+ // must not leak a fresh .gsd-backups/migrate-<ts>/ every dispatch. Treat it
311
+ // as a marker-refresh re-projection: reuse the existing snapshot as the
312
+ // rollback fallback instead of creating a duplicate.
313
+ const priorBackup = existingMigrateBackup(basePath);
314
+ if (priorBackup) {
315
+ backupDir = priorBackup;
316
+ logWarning("migration", `flat-phase migration re-fired; reusing existing backup ${priorBackup} instead of re-snapshotting (issue #1292)`);
214
317
  }
215
- catch (err) {
216
- logWarning("migration", `flat-phase migration backup failed: ${err.message}`);
217
- throw err;
318
+ else {
319
+ const ts = Date.now();
320
+ backupDir = join(basePath, ".gsd-backups", `migrate-${ts}`);
321
+ try {
322
+ mkdirSync(join(basePath, ".gsd-backups"), { recursive: true });
323
+ cpSync(milestonesPath, backupDir, { recursive: true });
324
+ backupCreatedThisRun = true;
325
+ }
326
+ catch (err) {
327
+ logWarning("migration", `flat-phase migration backup failed: ${err.message}`);
328
+ throw err;
329
+ }
218
330
  }
219
331
  if (existsSync(migratingPath)) {
220
332
  removePathWithRetries(migratingPath);
@@ -230,14 +342,34 @@ export async function migrateToFlatPhase(basePath) {
230
342
  throw err;
231
343
  }
232
344
  }
345
+ else {
346
+ const priorBackup = existingMigrateBackup(basePath);
347
+ if (priorBackup) {
348
+ backupDir = priorBackup;
349
+ }
350
+ else {
351
+ const ts = Date.now();
352
+ backupDir = join(basePath, ".gsd-backups", `migrate-${ts}`);
353
+ try {
354
+ mkdirSync(join(basePath, ".gsd-backups"), { recursive: true });
355
+ cpSync(migratingPath, backupDir, { recursive: true });
356
+ backupCreatedThisRun = true;
357
+ }
358
+ catch (err) {
359
+ logWarning("migration", `flat-phase migration backup failed during resume: ${err.message}`);
360
+ throw err;
361
+ }
362
+ }
363
+ }
233
364
  // Clear any stale or partially-rendered flat projection before this run
234
365
  // writes. Verification below checks the current DB render, not leftovers.
235
366
  try {
367
+ backupFlatProjectionIfPresent(basePath, phasesPath, backupDir);
236
368
  removePathWithRetries(phasesPath);
237
369
  }
238
370
  catch (err) {
239
371
  logWarning("migration", `failed to clear stale phases/ before render: ${err.message}`);
240
- rollbackPartialMigration(basePath, backupDir, migratingPath);
372
+ rollbackPartialMigration(basePath, backupDir, migratingPath, backupCreatedThisRun);
241
373
  throw err;
242
374
  }
243
375
  // 4. Render flat-phase from DB
@@ -260,35 +392,38 @@ export async function migrateToFlatPhase(basePath) {
260
392
  }
261
393
  catch (err) {
262
394
  logWarning("migration", `flat-phase render failed: ${err.message}`);
263
- rollbackPartialMigration(basePath, backupDir, migratingPath);
395
+ rollbackPartialMigration(basePath, backupDir, migratingPath, backupCreatedThisRun);
264
396
  throw err;
265
397
  }
266
398
  // 5. Verify render succeeded and flat-phase projection was written
267
399
  if (renderResult.errors.length > 0) {
268
400
  logWarning("migration", `flat-phase render had ${renderResult.errors.length} error(s): ${renderResult.errors.join("; ")}`);
269
- rollbackPartialMigration(basePath, backupDir, migratingPath);
401
+ rollbackPartialMigration(basePath, backupDir, migratingPath, backupCreatedThisRun);
270
402
  throw new Error(`flat-phase migration render failed: ${renderResult.errors.slice(0, 3).join("; ")}`);
271
403
  }
272
404
  const db = countDbHierarchy();
273
405
  const missingPhaseDirs = expectedPhaseDirs(basePath).filter((phaseDir) => !existsSync(phaseDir));
274
406
  if (db.milestones > 0 && missingPhaseDirs.length > 0) {
275
407
  logWarning("migration", `flat-phase migration missing ${missingPhaseDirs.length} expected phase dir(s): ${missingPhaseDirs.join(", ")}`);
276
- rollbackPartialMigration(basePath, backupDir, migratingPath);
408
+ rollbackPartialMigration(basePath, backupDir, migratingPath, backupCreatedThisRun);
277
409
  throw new Error("flat-phase migration verification failed: missing rendered phase directories");
278
410
  }
279
411
  if (db.slices > 0 && renderResult.rendered === 0) {
280
412
  logWarning("migration", "flat-phase migration verification failed: render produced no artifacts for populated DB");
281
- rollbackPartialMigration(basePath, backupDir, migratingPath);
413
+ rollbackPartialMigration(basePath, backupDir, migratingPath, backupCreatedThisRun);
282
414
  throw new Error("flat-phase migration verification failed: no artifacts rendered");
283
415
  }
284
416
  // 6. Verified — prune legacy artifact rows now that renderAllFromDb has
285
- // re-inserted flat-phase rows for artifacts that still have files.
417
+ // re-inserted flat-phase rows for artifacts that still have files. Also
418
+ // prune flat-phase rows whose files the renderer intentionally no longer
419
+ // materializes, such as task PLAN files and empty-content artifacts.
286
420
  try {
287
421
  deleteArtifactsByPathPrefix("milestones/");
422
+ pruneStaleFlatPhaseArtifactRows(basePath);
288
423
  }
289
424
  catch (err) {
290
425
  logWarning("migration", `flat-phase migration could not prune legacy artifact rows: ${err.message}`);
291
- rollbackPartialMigration(basePath, backupDir, migratingPath);
426
+ rollbackPartialMigration(basePath, backupDir, migratingPath, backupCreatedThisRun);
292
427
  throw err;
293
428
  }
294
429
  // 7. Remove the renamed legacy tree (backup already on disk).
@@ -229,10 +229,15 @@ export const RUNTIME_EXCLUSION_PATHS = [
229
229
  const runtimeFilesCleanedUpRepos = new Set();
230
230
  // ─── Integration Branch Metadata ───────────────────────────────────────────
231
231
  /**
232
- * Path to the milestone metadata file that stores the integration branch.
233
- * Format: .gsd/milestones/<MID>/<MID>-META.json
232
+ * Path to the milestone integration-branch metadata file.
233
+ * Format: .gsd/<MID>-META.json (deliberately OUTSIDE milestones/<MID>/ so it
234
+ * cannot poison isLegacyMilestonesLayout — see ADR-045).
234
235
  */
235
- function milestoneMetaPath(basePath, milestoneId) {
236
+ export function milestoneMetaPath(basePath, milestoneId) {
237
+ return join(gsdRoot(basePath), `${milestoneId}-META.json`);
238
+ }
239
+ /** Legacy location (pre-ADR-045). Read-only fallback for existing on-disk trees. */
240
+ function legacyMilestoneMetaPath(basePath, milestoneId) {
236
241
  return join(gsdRoot(basePath), "milestones", milestoneId, `${milestoneId}-META.json`);
237
242
  }
238
243
  /**
@@ -241,9 +246,13 @@ function milestoneMetaPath(basePath, milestoneId) {
241
246
  */
242
247
  export function readIntegrationBranch(basePath, milestoneId) {
243
248
  try {
244
- const metaFile = milestoneMetaPath(basePath, milestoneId);
245
- if (!existsSync(metaFile))
246
- return null;
249
+ let metaFile = milestoneMetaPath(basePath, milestoneId);
250
+ if (!existsSync(metaFile)) {
251
+ const legacy = legacyMilestoneMetaPath(basePath, milestoneId);
252
+ if (!existsSync(legacy))
253
+ return null;
254
+ metaFile = legacy;
255
+ }
247
256
  const data = JSON.parse(readFileSync(metaFile, "utf-8"));
248
257
  const branch = data?.integrationBranch;
249
258
  if (typeof branch === "string" && branch.trim() !== "" && VALID_BRANCH_NAME.test(branch)) {
@@ -295,7 +304,10 @@ export function writeIntegrationBranch(basePath, milestoneId, branch) {
295
304
  if (existingBranch === branch)
296
305
  return;
297
306
  const metaFile = milestoneMetaPath(basePath, milestoneId);
298
- mkdirSync(join(gsdRoot(basePath), "milestones", milestoneId), { recursive: true });
307
+ // Ensure the flat .gsd/ root exists (never milestones/<MID>/ that would
308
+ // poison layout detection, ADR-045). In production .gsd/ already exists; this
309
+ // guards fresh trees so the write below can't ENOENT.
310
+ mkdirSync(gsdRoot(basePath), { recursive: true });
299
311
  // Merge with existing metadata if present
300
312
  let existing = {};
301
313
  try {