@opengsd/gsd-pi 1.8.1 → 1.9.0-dev.97ef11e3

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 (613) 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 +27 -3
  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/loop.js +24 -4
  18. package/dist/resources/extensions/gsd/auto/run-unit.js +19 -1
  19. package/dist/resources/extensions/gsd/auto/unit-phase.js +37 -5
  20. package/dist/resources/extensions/gsd/auto-artifact-paths.js +16 -10
  21. package/dist/resources/extensions/gsd/auto-dispatch.js +76 -19
  22. package/dist/resources/extensions/gsd/auto-post-unit.js +4 -0
  23. package/dist/resources/extensions/gsd/auto-prompts.js +137 -22
  24. package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
  25. package/dist/resources/extensions/gsd/auto-runtime-state.js +5 -5
  26. package/dist/resources/extensions/gsd/auto-start.js +29 -9
  27. package/dist/resources/extensions/gsd/auto-tool-tracking.js +40 -0
  28. package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +4 -0
  29. package/dist/resources/extensions/gsd/auto-worktree-sync.js +7 -3
  30. package/dist/resources/extensions/gsd/auto-worktree-teardown.js +1 -1
  31. package/dist/resources/extensions/gsd/auto.js +20 -6
  32. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -4
  33. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -7
  34. package/dist/resources/extensions/gsd/bootstrap/system-context.js +10 -3
  35. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +88 -50
  36. package/dist/resources/extensions/gsd/command-feedback.js +16 -12
  37. package/dist/resources/extensions/gsd/commands-verdict.js +10 -9
  38. package/dist/resources/extensions/gsd/compat/compat-marker.js +98 -6
  39. package/dist/resources/extensions/gsd/constants.js +12 -13
  40. package/dist/resources/extensions/gsd/context-masker.js +97 -21
  41. package/dist/resources/extensions/gsd/db/command-queue.js +7 -2
  42. package/dist/resources/extensions/gsd/db/engine.js +56 -18
  43. package/dist/resources/extensions/gsd/db/writers/cascades.js +5 -1
  44. package/dist/resources/extensions/gsd/db/writers/status.js +13 -3
  45. package/dist/resources/extensions/gsd/db-base-schema.js +28 -0
  46. package/dist/resources/extensions/gsd/db-migration-steps.js +30 -0
  47. package/dist/resources/extensions/gsd/db-schema-metadata.js +4 -1
  48. package/dist/resources/extensions/gsd/docs/preferences-reference.md +26 -4
  49. package/dist/resources/extensions/gsd/doctor-engine-checks.js +24 -8
  50. package/dist/resources/extensions/gsd/error-classifier.js +12 -2
  51. package/dist/resources/extensions/gsd/exec-sandbox.js +1 -0
  52. package/dist/resources/extensions/gsd/flat-phase-migration.js +168 -21
  53. package/dist/resources/extensions/gsd/git-service.js +19 -7
  54. package/dist/resources/extensions/gsd/gsd-db.js +262 -76
  55. package/dist/resources/extensions/gsd/guided-flow.js +40 -15
  56. package/dist/resources/extensions/gsd/markdown-renderer.js +20 -22
  57. package/dist/resources/extensions/gsd/md-importer.js +107 -20
  58. package/dist/resources/extensions/gsd/migrate/command.js +19 -162
  59. package/dist/resources/extensions/gsd/migrate/execution.js +98 -0
  60. package/dist/resources/extensions/gsd/migrate/plan.js +49 -0
  61. package/dist/resources/extensions/gsd/migrate/planning-writer.js +12 -17
  62. package/dist/resources/extensions/gsd/migrate/presentation.js +64 -0
  63. package/dist/resources/extensions/gsd/model-cost-table.js +2 -0
  64. package/dist/resources/extensions/gsd/model-router.js +11 -0
  65. package/dist/resources/extensions/gsd/parallel-eligibility.js +5 -4
  66. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +28 -43
  67. package/dist/resources/extensions/gsd/paths.js +70 -16
  68. package/dist/resources/extensions/gsd/phase-anchor.js +7 -2
  69. package/dist/resources/extensions/gsd/planning-subagent-policy.js +37 -0
  70. package/dist/resources/extensions/gsd/planning-subagent-registry.js +25 -0
  71. package/dist/resources/extensions/gsd/post-execution-checks.js +4 -4
  72. package/dist/resources/extensions/gsd/preferences-types.js +5 -0
  73. package/dist/resources/extensions/gsd/preferences-validation.js +48 -1
  74. package/dist/resources/extensions/gsd/preferences.js +17 -0
  75. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  76. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +5 -5
  77. package/dist/resources/extensions/gsd/provider-payload-policy.js +16 -5
  78. package/dist/resources/extensions/gsd/safety/destructive-guard.js +1 -1
  79. package/dist/resources/extensions/gsd/safety/evidence-collector.js +26 -1
  80. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +30 -5
  81. package/dist/resources/extensions/gsd/skill-activation.js +17 -3
  82. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.js +125 -15
  83. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.js +17 -4
  84. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +5 -2
  85. package/dist/resources/extensions/gsd/stop-notice.js +24 -1
  86. package/dist/resources/extensions/gsd/sync-lock.js +13 -7
  87. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
  88. package/dist/resources/extensions/gsd/tools/complete-task.js +94 -6
  89. package/dist/resources/extensions/gsd/tools/plan-task.js +13 -15
  90. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +18 -15
  91. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +14 -5
  92. package/dist/resources/extensions/gsd/tools/reopen-slice.js +15 -5
  93. package/dist/resources/extensions/gsd/tools/reopen-task.js +16 -10
  94. package/dist/resources/extensions/gsd/tools/replan-task.js +128 -0
  95. package/dist/resources/extensions/gsd/tools/rework-brief.js +74 -0
  96. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +81 -0
  97. package/dist/resources/extensions/gsd/unit-context-composer.js +28 -5
  98. package/dist/resources/extensions/gsd/unit-registry.js +4 -0
  99. package/dist/resources/extensions/gsd/uok/plan-v2.js +19 -3
  100. package/dist/resources/extensions/gsd/workflow-projections.js +2 -3
  101. package/dist/resources/extensions/gsd/workspace.js +2 -1
  102. package/dist/resources/extensions/gsd/worktree-state-projection.js +26 -18
  103. package/dist/resources/extensions/mac-tools/index.js +31 -9
  104. package/dist/resources/extensions/shared/interview-ui.js +43 -6
  105. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  106. package/dist/web/standalone/.next/BUILD_ID +1 -1
  107. package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
  108. package/dist/web/standalone/.next/build-manifest.json +3 -3
  109. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  110. package/dist/web/standalone/.next/required-server-files.json +3 -3
  111. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  112. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  122. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
  125. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  126. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  128. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  131. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  138. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  150. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  172. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  182. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  188. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  204. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  208. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  214. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  215. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  216. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  217. package/dist/web/standalone/.next/server/app/index.html +1 -1
  218. package/dist/web/standalone/.next/server/app/index.rsc +5 -5
  219. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  220. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
  221. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  222. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  223. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  224. package/dist/web/standalone/.next/server/app/page.js +2 -2
  225. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  226. package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
  227. package/dist/web/standalone/.next/server/chunks/1991.js +2 -2
  228. package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
  229. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  230. package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
  231. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  232. package/dist/web/standalone/.next/server/middleware.js +3 -3
  233. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  234. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  235. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  236. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
  237. package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
  238. package/dist/web/standalone/.next/static/chunks/app/page-72a856634ad14c10.js +1 -0
  239. package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
  240. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
  241. package/dist/web/standalone/.next/static/css/3b1ceb7abfb9a230.css +1 -0
  242. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  243. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  244. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  245. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  246. package/dist/web/standalone/package.json +0 -1
  247. package/dist/web/standalone/server.js +1 -1
  248. package/dist/web-mode.js +31 -3
  249. package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
  250. package/integrations/hermes/pyproject.toml +1 -1
  251. package/package.json +13 -10
  252. package/packages/cloud-mcp-gateway/package.json +2 -2
  253. package/packages/contracts/dist/workflow.d.ts +14 -0
  254. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  255. package/packages/contracts/dist/workflow.js +16 -0
  256. package/packages/contracts/dist/workflow.js.map +1 -1
  257. package/packages/contracts/package.json +1 -1
  258. package/packages/daemon/dist/cloud-config.d.ts +1 -1
  259. package/packages/daemon/dist/cloud-config.d.ts.map +1 -1
  260. package/packages/daemon/dist/cloud-config.js +5 -1
  261. package/packages/daemon/dist/cloud-config.js.map +1 -1
  262. package/packages/daemon/dist/cloud-config.test.js +51 -1
  263. package/packages/daemon/dist/cloud-config.test.js.map +1 -1
  264. package/packages/daemon/dist/local-tool-executor.d.ts.map +1 -1
  265. package/packages/daemon/dist/local-tool-executor.js +2 -0
  266. package/packages/daemon/dist/local-tool-executor.js.map +1 -1
  267. package/packages/daemon/package.json +6 -6
  268. package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
  269. package/packages/gsd-agent-core/dist/compaction/compaction.js +36 -4
  270. package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
  271. package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
  272. package/packages/gsd-agent-core/dist/sdk.js +1 -0
  273. package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
  274. package/packages/gsd-agent-core/package.json +5 -5
  275. package/packages/gsd-agent-modes/package.json +7 -7
  276. package/packages/gsd-cloud/README.md +9 -3
  277. package/packages/gsd-cloud/dist/background-cli.test.d.ts +2 -0
  278. package/packages/gsd-cloud/dist/background-cli.test.d.ts.map +1 -0
  279. package/packages/gsd-cloud/dist/background-cli.test.js +248 -0
  280. package/packages/gsd-cloud/dist/background-cli.test.js.map +1 -0
  281. package/packages/gsd-cloud/dist/cli.d.ts +5 -0
  282. package/packages/gsd-cloud/dist/cli.d.ts.map +1 -0
  283. package/packages/gsd-cloud/dist/cli.js +266 -0
  284. package/packages/gsd-cloud/dist/cli.js.map +1 -0
  285. package/packages/gsd-cloud/dist/cloud-config.d.ts +19 -0
  286. package/packages/gsd-cloud/dist/cloud-config.d.ts.map +1 -0
  287. package/packages/gsd-cloud/dist/cloud-config.js +237 -0
  288. package/packages/gsd-cloud/dist/cloud-config.js.map +1 -0
  289. package/packages/gsd-cloud/dist/cloud-config.test.d.ts +2 -0
  290. package/packages/gsd-cloud/dist/cloud-config.test.d.ts.map +1 -0
  291. package/packages/gsd-cloud/dist/cloud-config.test.js +118 -0
  292. package/packages/gsd-cloud/dist/cloud-config.test.js.map +1 -0
  293. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts +2 -0
  294. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts.map +1 -0
  295. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js +37 -0
  296. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js.map +1 -0
  297. package/packages/gsd-cloud/dist/cloud-runtime.d.ts +33 -0
  298. package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -0
  299. package/packages/gsd-cloud/dist/cloud-runtime.js +260 -0
  300. package/packages/gsd-cloud/dist/cloud-runtime.js.map +1 -0
  301. package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts +2 -0
  302. package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts.map +1 -0
  303. package/packages/gsd-cloud/dist/cloud-runtime.test.js +88 -0
  304. package/packages/gsd-cloud/dist/cloud-runtime.test.js.map +1 -0
  305. package/packages/gsd-cloud/dist/cloud-token.d.ts +3 -0
  306. package/packages/gsd-cloud/dist/cloud-token.d.ts.map +1 -0
  307. package/packages/gsd-cloud/dist/cloud-token.js +37 -0
  308. package/packages/gsd-cloud/dist/cloud-token.js.map +1 -0
  309. package/packages/gsd-cloud/dist/config.d.ts +17 -0
  310. package/packages/gsd-cloud/dist/config.d.ts.map +1 -0
  311. package/packages/gsd-cloud/dist/config.js +146 -0
  312. package/packages/gsd-cloud/dist/config.js.map +1 -0
  313. package/packages/gsd-cloud/dist/device-flow.d.ts +24 -0
  314. package/packages/gsd-cloud/dist/device-flow.d.ts.map +1 -0
  315. package/packages/gsd-cloud/dist/device-flow.js +128 -0
  316. package/packages/gsd-cloud/dist/device-flow.js.map +1 -0
  317. package/packages/gsd-cloud/dist/device-flow.test.d.ts +2 -0
  318. package/packages/gsd-cloud/dist/device-flow.test.d.ts.map +1 -0
  319. package/packages/gsd-cloud/dist/device-flow.test.js +155 -0
  320. package/packages/gsd-cloud/dist/device-flow.test.js.map +1 -0
  321. package/packages/gsd-cloud/dist/executors/claude-executor.d.ts +6 -0
  322. package/packages/gsd-cloud/dist/executors/claude-executor.d.ts.map +1 -0
  323. package/packages/gsd-cloud/dist/executors/claude-executor.js +15 -0
  324. package/packages/gsd-cloud/dist/executors/claude-executor.js.map +1 -0
  325. package/packages/gsd-cloud/dist/executors/codex-executor.d.ts +6 -0
  326. package/packages/gsd-cloud/dist/executors/codex-executor.d.ts.map +1 -0
  327. package/packages/gsd-cloud/dist/executors/codex-executor.js +15 -0
  328. package/packages/gsd-cloud/dist/executors/codex-executor.js.map +1 -0
  329. package/packages/gsd-cloud/dist/executors/executor.d.ts +28 -0
  330. package/packages/gsd-cloud/dist/executors/executor.d.ts.map +1 -0
  331. package/packages/gsd-cloud/dist/executors/executor.js +11 -0
  332. package/packages/gsd-cloud/dist/executors/executor.js.map +1 -0
  333. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts +34 -0
  334. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts.map +1 -0
  335. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js +179 -0
  336. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js.map +1 -0
  337. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts +2 -0
  338. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts.map +1 -0
  339. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js +44 -0
  340. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js.map +1 -0
  341. package/packages/gsd-cloud/dist/executors/index.d.ts +17 -0
  342. package/packages/gsd-cloud/dist/executors/index.d.ts.map +1 -0
  343. package/packages/gsd-cloud/dist/executors/index.js +29 -0
  344. package/packages/gsd-cloud/dist/executors/index.js.map +1 -0
  345. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts +36 -0
  346. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts.map +1 -0
  347. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js +176 -0
  348. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js.map +1 -0
  349. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts +2 -0
  350. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts.map +1 -0
  351. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js +34 -0
  352. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js.map +1 -0
  353. package/packages/gsd-cloud/dist/index.d.ts +7 -0
  354. package/packages/gsd-cloud/dist/index.d.ts.map +1 -0
  355. package/packages/gsd-cloud/dist/index.js +8 -0
  356. package/packages/gsd-cloud/dist/index.js.map +1 -0
  357. package/packages/gsd-cloud/dist/inject-gateway.d.ts +16 -0
  358. package/packages/gsd-cloud/dist/inject-gateway.d.ts.map +1 -0
  359. package/packages/gsd-cloud/dist/inject-gateway.js +29 -0
  360. package/packages/gsd-cloud/dist/inject-gateway.js.map +1 -0
  361. package/packages/gsd-cloud/dist/inject-gateway.test.d.ts +2 -0
  362. package/packages/gsd-cloud/dist/inject-gateway.test.d.ts.map +1 -0
  363. package/packages/gsd-cloud/dist/inject-gateway.test.js +41 -0
  364. package/packages/gsd-cloud/dist/inject-gateway.test.js.map +1 -0
  365. package/packages/gsd-cloud/dist/logger.d.ts +25 -0
  366. package/packages/gsd-cloud/dist/logger.d.ts.map +1 -0
  367. package/packages/gsd-cloud/dist/logger.js +72 -0
  368. package/packages/gsd-cloud/dist/logger.js.map +1 -0
  369. package/packages/gsd-cloud/dist/runtime-process.d.ts +27 -0
  370. package/packages/gsd-cloud/dist/runtime-process.d.ts.map +1 -0
  371. package/packages/gsd-cloud/dist/runtime-process.js +272 -0
  372. package/packages/gsd-cloud/dist/runtime-process.js.map +1 -0
  373. package/packages/gsd-cloud/dist/runtime-process.test.d.ts +2 -0
  374. package/packages/gsd-cloud/dist/runtime-process.test.d.ts.map +1 -0
  375. package/packages/gsd-cloud/dist/runtime-process.test.js +97 -0
  376. package/packages/gsd-cloud/dist/runtime-process.test.js.map +1 -0
  377. package/packages/gsd-cloud/dist/types.d.ts +51 -0
  378. package/packages/gsd-cloud/dist/types.d.ts.map +1 -0
  379. package/packages/gsd-cloud/dist/types.js +9 -0
  380. package/packages/gsd-cloud/dist/types.js.map +1 -0
  381. package/packages/gsd-cloud/package.json +3 -3
  382. package/packages/mcp-server/README.md +15 -2
  383. package/packages/mcp-server/dist/cli-runner.d.ts +3 -0
  384. package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -1
  385. package/packages/mcp-server/dist/cli-runner.js +119 -33
  386. package/packages/mcp-server/dist/cli-runner.js.map +1 -1
  387. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  388. package/packages/mcp-server/dist/server.js +5 -5
  389. package/packages/mcp-server/dist/server.js.map +1 -1
  390. package/packages/mcp-server/dist/workflow-tools.d.ts +4 -3
  391. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  392. package/packages/mcp-server/dist/workflow-tools.js +64 -2
  393. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  394. package/packages/mcp-server/package.json +4 -4
  395. package/packages/native/package.json +1 -1
  396. package/packages/pi-agent-core/dist/agent.d.ts +5 -1
  397. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  398. package/packages/pi-agent-core/dist/agent.js +2 -0
  399. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  400. package/packages/pi-agent-core/package.json +1 -1
  401. package/packages/pi-ai/dist/models.generated.d.ts +136 -0
  402. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  403. package/packages/pi-ai/dist/models.generated.js +124 -0
  404. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  405. package/packages/pi-ai/dist/providers/amazon-bedrock.js +1 -0
  406. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  407. package/packages/pi-ai/dist/providers/anthropic.js +25 -1
  408. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  409. package/packages/pi-ai/dist/providers/openai-codex-responses.js +1 -1
  410. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  411. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  412. package/packages/pi-ai/dist/providers/openai-completions.js +103 -0
  413. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  414. package/packages/pi-ai/dist/providers/openai-responses.js +1 -1
  415. package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
  416. package/packages/pi-ai/package.json +1 -1
  417. package/packages/pi-coding-agent/dist/core/capability-patches.js +1 -1
  418. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  419. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -1
  420. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  421. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +11 -1
  422. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  423. package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
  424. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  425. package/packages/pi-coding-agent/package.json +7 -7
  426. package/packages/pi-tui/package.json +2 -2
  427. package/packages/rpc-client/package.json +2 -2
  428. package/pkg/package.json +1 -1
  429. package/src/resources/GSD-WORKFLOW.md +18 -49
  430. package/src/resources/extensions/browser-tools/capture.ts +2 -86
  431. package/src/resources/extensions/browser-tools/screenshot-constraints.ts +94 -0
  432. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +18 -1
  433. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -0
  434. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +30 -2
  435. package/src/resources/extensions/gsd/artifact-verification.ts +3 -8
  436. package/src/resources/extensions/gsd/auto/loop.ts +48 -4
  437. package/src/resources/extensions/gsd/auto/run-unit.ts +20 -1
  438. package/src/resources/extensions/gsd/auto/unit-phase.ts +41 -5
  439. package/src/resources/extensions/gsd/auto-artifact-paths.ts +16 -9
  440. package/src/resources/extensions/gsd/auto-dispatch.ts +87 -19
  441. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -0
  442. package/src/resources/extensions/gsd/auto-prompts.ts +156 -20
  443. package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
  444. package/src/resources/extensions/gsd/auto-runtime-state.ts +12 -7
  445. package/src/resources/extensions/gsd/auto-start.ts +31 -8
  446. package/src/resources/extensions/gsd/auto-tool-tracking.ts +56 -0
  447. package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +4 -0
  448. package/src/resources/extensions/gsd/auto-worktree-sync.ts +10 -3
  449. package/src/resources/extensions/gsd/auto-worktree-teardown.ts +1 -1
  450. package/src/resources/extensions/gsd/auto.ts +25 -8
  451. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +92 -4
  452. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +41 -12
  453. package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -3
  454. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +87 -53
  455. package/src/resources/extensions/gsd/command-feedback.ts +19 -12
  456. package/src/resources/extensions/gsd/commands-verdict.ts +16 -9
  457. package/src/resources/extensions/gsd/compat/compat-marker.ts +119 -8
  458. package/src/resources/extensions/gsd/constants.ts +14 -13
  459. package/src/resources/extensions/gsd/context-masker.ts +98 -2
  460. package/src/resources/extensions/gsd/db/command-queue.ts +7 -1
  461. package/src/resources/extensions/gsd/db/engine.ts +58 -19
  462. package/src/resources/extensions/gsd/db/writers/cascades.ts +5 -1
  463. package/src/resources/extensions/gsd/db/writers/status.ts +25 -8
  464. package/src/resources/extensions/gsd/db-base-schema.ts +30 -0
  465. package/src/resources/extensions/gsd/db-migration-steps.ts +32 -0
  466. package/src/resources/extensions/gsd/db-schema-metadata.ts +4 -1
  467. package/src/resources/extensions/gsd/docs/preferences-reference.md +26 -4
  468. package/src/resources/extensions/gsd/doctor-engine-checks.ts +30 -7
  469. package/src/resources/extensions/gsd/error-classifier.ts +13 -2
  470. package/src/resources/extensions/gsd/exec-sandbox.ts +1 -0
  471. package/src/resources/extensions/gsd/flat-phase-migration.ts +174 -19
  472. package/src/resources/extensions/gsd/git-service.ts +19 -6
  473. package/src/resources/extensions/gsd/gsd-db.ts +340 -85
  474. package/src/resources/extensions/gsd/guided-flow.ts +50 -14
  475. package/src/resources/extensions/gsd/markdown-renderer.ts +28 -30
  476. package/src/resources/extensions/gsd/md-importer.ts +114 -16
  477. package/src/resources/extensions/gsd/migrate/command.ts +21 -227
  478. package/src/resources/extensions/gsd/migrate/execution.ts +136 -0
  479. package/src/resources/extensions/gsd/migrate/plan.ts +101 -0
  480. package/src/resources/extensions/gsd/migrate/planning-writer.ts +12 -20
  481. package/src/resources/extensions/gsd/migrate/presentation.ts +83 -0
  482. package/src/resources/extensions/gsd/model-cost-table.ts +2 -0
  483. package/src/resources/extensions/gsd/model-router.ts +12 -0
  484. package/src/resources/extensions/gsd/parallel-eligibility.ts +5 -4
  485. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +37 -40
  486. package/src/resources/extensions/gsd/paths.ts +77 -16
  487. package/src/resources/extensions/gsd/phase-anchor.ts +8 -2
  488. package/src/resources/extensions/gsd/planning-subagent-policy.ts +58 -0
  489. package/src/resources/extensions/gsd/planning-subagent-registry.ts +31 -0
  490. package/src/resources/extensions/gsd/post-execution-checks.ts +4 -4
  491. package/src/resources/extensions/gsd/preferences-types.ts +16 -0
  492. package/src/resources/extensions/gsd/preferences-validation.ts +62 -0
  493. package/src/resources/extensions/gsd/preferences.ts +25 -0
  494. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  495. package/src/resources/extensions/gsd/prompts/validate-milestone.md +5 -5
  496. package/src/resources/extensions/gsd/provider-payload-policy.ts +18 -4
  497. package/src/resources/extensions/gsd/safety/destructive-guard.ts +1 -1
  498. package/src/resources/extensions/gsd/safety/evidence-collector.ts +28 -1
  499. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +31 -5
  500. package/src/resources/extensions/gsd/skill-activation.ts +17 -3
  501. package/src/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.ts +162 -15
  502. package/src/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.ts +20 -4
  503. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +4 -2
  504. package/src/resources/extensions/gsd/state-reconciliation/types.ts +2 -2
  505. package/src/resources/extensions/gsd/stop-notice.ts +29 -1
  506. package/src/resources/extensions/gsd/sync-lock.ts +14 -6
  507. package/src/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
  508. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +7 -7
  509. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +264 -0
  510. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +39 -0
  511. package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +21 -1
  512. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +74 -1
  513. package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +55 -0
  514. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +96 -1
  515. package/src/resources/extensions/gsd/tests/command-feedback.test.ts +12 -0
  516. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +10 -0
  517. package/src/resources/extensions/gsd/tests/compat-marker.test.ts +129 -0
  518. package/src/resources/extensions/gsd/tests/complete-task.test.ts +362 -1
  519. package/src/resources/extensions/gsd/tests/context-masker.test.ts +204 -8
  520. package/src/resources/extensions/gsd/tests/db-engine-cjs-compat.test.ts +12 -0
  521. package/src/resources/extensions/gsd/tests/db-engine-migrate-guards.test.ts +186 -0
  522. package/src/resources/extensions/gsd/tests/db-tools-alias-suppression.test.ts +62 -0
  523. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +29 -0
  524. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +33 -0
  525. package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +14 -0
  526. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +123 -0
  527. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +50 -0
  528. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +49 -0
  529. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +83 -0
  530. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +81 -0
  531. package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +22 -0
  532. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +33 -1
  533. package/src/resources/extensions/gsd/tests/external-edit-scoped-import.test.ts +262 -0
  534. package/src/resources/extensions/gsd/tests/external-markdown-edit.test.ts +38 -1
  535. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +201 -0
  536. package/src/resources/extensions/gsd/tests/flat-phase-validation-path.test.ts +20 -1
  537. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +29 -0
  538. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +57 -0
  539. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +22 -0
  540. package/src/resources/extensions/gsd/tests/import-slice-milestone-completion-preserve.test.ts +116 -0
  541. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +13 -0
  542. package/src/resources/extensions/gsd/tests/integration/paths.test.ts +22 -4
  543. package/src/resources/extensions/gsd/tests/integration-branch-meta-location.test.ts +62 -0
  544. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +5 -5
  545. package/src/resources/extensions/gsd/tests/migrate-plan.test.ts +68 -0
  546. package/src/resources/extensions/gsd/tests/migrate-presentation.test.ts +98 -0
  547. package/src/resources/extensions/gsd/tests/migrate-safety-audit.test.ts +1 -1
  548. package/src/resources/extensions/gsd/tests/milestone-leases.test.ts +55 -0
  549. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
  550. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  551. package/src/resources/extensions/gsd/tests/parallel-eligibility-file-overlap.test.ts +146 -0
  552. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +59 -0
  553. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +7 -5
  554. package/src/resources/extensions/gsd/tests/phase-anchor.test.ts +32 -4
  555. package/src/resources/extensions/gsd/tests/plan-task.test.ts +26 -23
  556. package/src/resources/extensions/gsd/tests/planning-writer.test.ts +29 -0
  557. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +22 -0
  558. package/src/resources/extensions/gsd/tests/preferences.test.ts +84 -0
  559. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +4 -0
  560. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +87 -0
  561. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +121 -1
  562. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +39 -0
  563. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +50 -0
  564. package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +105 -0
  565. package/src/resources/extensions/gsd/tests/replan-task-handler.test.ts +103 -0
  566. package/src/resources/extensions/gsd/tests/rework-brief.test.ts +197 -0
  567. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  568. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +33 -7
  569. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -16
  570. package/src/resources/extensions/gsd/tests/skip-slice-cascades-tasks.test.ts +21 -0
  571. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +52 -0
  572. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +38 -1
  573. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +19 -0
  574. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +13 -7
  575. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +14 -0
  576. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
  577. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -0
  578. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +73 -0
  579. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +93 -1
  580. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +7 -0
  581. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -0
  582. package/src/resources/extensions/gsd/tests/workflow-migration-gates.test.ts +139 -0
  583. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -4
  584. package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +36 -0
  585. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +60 -0
  586. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +34 -0
  587. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +52 -0
  588. package/src/resources/extensions/gsd/tools/complete-task.ts +140 -5
  589. package/src/resources/extensions/gsd/tools/plan-task.ts +14 -16
  590. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +18 -17
  591. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +24 -5
  592. package/src/resources/extensions/gsd/tools/reopen-slice.ts +25 -5
  593. package/src/resources/extensions/gsd/tools/reopen-task.ts +23 -9
  594. package/src/resources/extensions/gsd/tools/replan-task.ts +160 -0
  595. package/src/resources/extensions/gsd/tools/rework-brief.ts +91 -0
  596. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +92 -0
  597. package/src/resources/extensions/gsd/types.ts +11 -0
  598. package/src/resources/extensions/gsd/unit-context-composer.ts +34 -8
  599. package/src/resources/extensions/gsd/unit-registry.ts +4 -0
  600. package/src/resources/extensions/gsd/uok/plan-v2.ts +20 -3
  601. package/src/resources/extensions/gsd/workflow-projections.ts +2 -3
  602. package/src/resources/extensions/gsd/workspace.ts +2 -1
  603. package/src/resources/extensions/gsd/worktree-state-projection.ts +33 -24
  604. package/src/resources/extensions/mac-tools/index.ts +52 -9
  605. package/src/resources/extensions/mac-tools/tests/mac-screenshot-payload.test.cjs +70 -0
  606. package/src/resources/extensions/shared/interview-ui.ts +47 -8
  607. package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +29 -0
  608. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
  609. package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +0 -1
  610. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
  611. package/dist/web/standalone/.next/static/css/18c2fdf261bfc1b7.css +0 -1
  612. /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → DXD9fZPnqtjZSlT5xdC3v}/_buildManifest.js +0 -0
  613. /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → DXD9fZPnqtjZSlT5xdC3v}/_ssgManifest.js +0 -0
@@ -57,6 +57,19 @@ test("needsFlatPhaseMigration returns false when no .gsd/milestones/", () => {
57
57
  assert.equal(needsFlatPhaseMigration(base), false);
58
58
  });
59
59
 
60
+ test("needsFlatPhaseMigration ignores legacy anchor runtime scaffolding", () => {
61
+ const base = mkdtempSync(join(tmpdir(), `gsd-anchor-nomig-${randomUUID()}`));
62
+ mkdirSync(join(base, ".gsd", "phases"), { recursive: true });
63
+ mkdirSync(join(base, ".gsd", "milestones", "M001", "anchors"), { recursive: true });
64
+ writeFileSync(
65
+ join(base, ".gsd", "milestones", "M001", "anchors", "research-slice.json"),
66
+ "{}",
67
+ "utf-8",
68
+ );
69
+ tmpDirs.push(base);
70
+ assert.equal(needsFlatPhaseMigration(base), false);
71
+ });
72
+
60
73
  test("migrateToFlatPhase moves content from milestones/ to phases/", async () => {
61
74
  const base = makeTmp();
62
75
  await migrateToFlatPhase(base);
@@ -109,6 +122,58 @@ test("migrateToFlatPhase creates a backup", async () => {
109
122
  assert.ok(backups.length >= 1, "at least one migrate-* backup dir should exist");
110
123
  });
111
124
 
125
+ test("migrateToFlatPhase removes disposable phases snapshot after successful migration", async () => {
126
+ const base = makeTmp();
127
+ const reviewPath = join(base, ".gsd", "phases", "01-foundation", "PLAN-REVIEW.md");
128
+ mkdirSync(join(base, ".gsd", "phases", "01-foundation"), { recursive: true });
129
+ writeFileSync(reviewPath, "# Plan Review\n\nHand-authored review.", "utf-8");
130
+
131
+ await migrateToFlatPhase(base);
132
+
133
+ const backupRoot = join(base, ".gsd-backups");
134
+ const backups = readdirSync(backupRoot).filter(d => d.startsWith("migrate-"));
135
+ assert.equal(backups.length, 1, "one migrate backup should exist");
136
+ assert.equal(
137
+ existsSync(join(backupRoot, backups[0]!, "__phases")),
138
+ false,
139
+ "temporary phases/ recovery snapshot should be removed after success",
140
+ );
141
+ });
142
+
143
+ test("failed migration restores pre-existing phases projection from backup", async (t) => {
144
+ const base = makeTmp();
145
+ const phasesPath = join(base, ".gsd", "phases");
146
+ const reviewPath = join(phasesPath, "01-foundation", "PLAN-REVIEW.md");
147
+ mkdirSync(join(phasesPath, "01-foundation"), { recursive: true });
148
+ writeFileSync(reviewPath, "# Plan Review\n\nHand-authored review.", "utf-8");
149
+
150
+ let sabotagedClear = false;
151
+ const restoreFsOps = _setFlatPhaseMigrationFsOpsForTest({
152
+ rmSync(target, opts) {
153
+ rmSync(target, opts as never);
154
+ if (target === phasesPath && !sabotagedClear) {
155
+ sabotagedClear = true;
156
+ writeFileSync(phasesPath, "not a directory", "utf-8");
157
+ }
158
+ },
159
+ });
160
+ t.after(restoreFsOps);
161
+
162
+ await assert.rejects(migrateToFlatPhase(base), /flat-phase migration render failed/);
163
+
164
+ assert.equal(sabotagedClear, true, "test should force a post-clear render failure");
165
+ assert.equal(
166
+ readFileSync(reviewPath, "utf-8"),
167
+ "# Plan Review\n\nHand-authored review.",
168
+ "rollback should restore the pre-existing phases/ files",
169
+ );
170
+ const backupRoot = join(base, ".gsd-backups");
171
+ const leaked = existsSync(backupRoot)
172
+ ? readdirSync(backupRoot).filter((d) => d.startsWith("migrate-"))
173
+ : [];
174
+ assert.equal(leaked.length, 0, "rollback should still clean the backup it created");
175
+ });
176
+
112
177
  test("failed migration rolls back without leaking a .gsd-backups/migrate-* dir", async (t) => {
113
178
  const base = makeTmp();
114
179
  const milestonesPath = join(base, ".gsd", "milestones");
@@ -136,6 +201,33 @@ test("failed migration rolls back without leaking a .gsd-backups/migrate-* dir",
136
201
  assert.equal(leaked.length, 0, "rollback must delete the migrate-* backup it created");
137
202
  });
138
203
 
204
+ test("resumed migration removes disposable phases snapshot after success", async () => {
205
+ const base = makeTmp();
206
+ const milestonesPath = join(base, ".gsd", "milestones");
207
+ const migratingPath = join(base, ".gsd", "milestones.migrating");
208
+ const reviewPath = join(base, ".gsd", "phases", "01-foundation", "PLAN-REVIEW.md");
209
+ mkdirSync(join(base, ".gsd", "phases", "01-foundation"), { recursive: true });
210
+ writeFileSync(reviewPath, "# Plan Review\n\nResume recovery copy.", "utf-8");
211
+ renameSync(milestonesPath, migratingPath);
212
+
213
+ await migrateToFlatPhase(base);
214
+
215
+ assert.equal(existsSync(migratingPath), false, "resume staging dir should be removed after success");
216
+ const backupRoot = join(base, ".gsd-backups");
217
+ const backups = readdirSync(backupRoot).filter((d) => d.startsWith("migrate-"));
218
+ assert.equal(backups.length, 1, "resumed migration should create one retained migrate backup");
219
+ assert.equal(
220
+ existsSync(join(backupRoot, backups[0]!, "__phases")),
221
+ false,
222
+ "temporary phases/ recovery snapshot should be removed after resumed success",
223
+ );
224
+ assert.equal(
225
+ existsSync(join(migratingPath, "__phases")),
226
+ false,
227
+ "resume should not store the phases snapshot inside the disposable migrating tree",
228
+ );
229
+ });
230
+
139
231
  test("migrateToFlatPhase preserves milestone/slice/task counts in DB", async () => {
140
232
  const base = makeTmp();
141
233
  const msBefore = getAllMilestones().length;
@@ -190,6 +282,42 @@ test("migrateToFlatPhase prunes legacy milestones artifact rows after flat rende
190
282
  );
191
283
  });
192
284
 
285
+ test("migrateToFlatPhase prunes stale flat-phase artifact rows that renderAll intentionally skips", async () => {
286
+ const base = makeTmp();
287
+ insertArtifact({
288
+ path: "phases/01-foundation/T01-PLAN.md",
289
+ artifact_type: "PLAN",
290
+ milestone_id: "M001",
291
+ slice_id: "S01",
292
+ task_id: "T01",
293
+ full_content: "# Legacy standalone task plan\n",
294
+ });
295
+ insertArtifact({
296
+ path: "phases/01-foundation/01-01-RESEARCH.md",
297
+ artifact_type: "RESEARCH",
298
+ milestone_id: "M001",
299
+ slice_id: "S01",
300
+ task_id: null,
301
+ full_content: "",
302
+ });
303
+
304
+ await migrateToFlatPhase(base);
305
+
306
+ const rows = _getAdapter()!
307
+ .prepare("SELECT path FROM artifacts ORDER BY path")
308
+ .all() as Array<{ path: string }>;
309
+ assert.equal(
310
+ rows.some((row) => row.path === "phases/01-foundation/T01-PLAN.md"),
311
+ false,
312
+ "standalone task PLAN rows should be pruned when the flat renderer does not recreate the file",
313
+ );
314
+ assert.equal(
315
+ rows.some((row) => row.path === "phases/01-foundation/01-01-RESEARCH.md"),
316
+ false,
317
+ "empty-content artifact rows should be pruned when the flat renderer skips the file",
318
+ );
319
+ });
320
+
193
321
  test("migrateToFlatPhase is idempotent (second run is a no-op)", async () => {
194
322
  const base = makeTmp();
195
323
  await migrateToFlatPhase(base);
@@ -199,6 +327,79 @@ test("migrateToFlatPhase is idempotent (second run is a no-op)", async () => {
199
327
  assert.equal(backups.length, 1, "should only have one backup");
200
328
  });
201
329
 
330
+ test("re-fired migration reuses the existing backup instead of leaking a new migrate-* dir (#1292)", async () => {
331
+ const base = makeTmp();
332
+ await migrateToFlatPhase(base);
333
+ const backupRoot = join(base, ".gsd-backups");
334
+ const firstBackups = readdirSync(backupRoot).filter((d) => d.startsWith("migrate-"));
335
+ assert.equal(firstBackups.length, 1, "first migration snapshots exactly one backup");
336
+
337
+ // Simulate the re-fire: the legacy .gsd/milestones/ layout reappears (e.g. a
338
+ // marker-key mismatch re-imports the whole tree). The DB rows still exist, so
339
+ // the migration gate proceeds again — it must not snapshot a second backup.
340
+ mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks", "T01"), { recursive: true });
341
+ assert.equal(needsFlatPhaseMigration(base), true, "reappeared legacy layout re-triggers migration");
342
+
343
+ await migrateToFlatPhase(base);
344
+
345
+ const afterBackups = readdirSync(backupRoot).filter((d) => d.startsWith("migrate-"));
346
+ assert.deepEqual(afterBackups, firstBackups, "re-fire must not leak a second migrate-* backup");
347
+ assert.equal(existsSync(join(base, ".gsd", "milestones")), false, "legacy milestones/ removed again");
348
+ });
349
+
350
+ test("rollback after a re-fired migration preserves the reused migrate-* backup", async (t) => {
351
+ const base = makeTmp();
352
+ await migrateToFlatPhase(base);
353
+ const backupRoot = join(base, ".gsd-backups");
354
+ const firstBackups = readdirSync(backupRoot).filter((d) => d.startsWith("migrate-"));
355
+ assert.equal(firstBackups.length, 1, "first migration snapshots exactly one backup");
356
+
357
+ mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks", "T01"), { recursive: true });
358
+ const milestonesPath = join(base, ".gsd", "milestones");
359
+ const phasesPath = join(base, ".gsd", "phases");
360
+
361
+ const restoreFsOps = _setFlatPhaseMigrationFsOpsForTest({
362
+ rmSync(target, opts) {
363
+ if (target === phasesPath) {
364
+ throw Object.assign(new Error("simulated locked phases/"), { code: "EPERM" });
365
+ }
366
+ return rmSync(target, opts as never);
367
+ },
368
+ });
369
+ t.after(restoreFsOps);
370
+
371
+ await assert.rejects(migrateToFlatPhase(base), /simulated locked/);
372
+
373
+ const afterBackups = readdirSync(backupRoot).filter((d) => d.startsWith("migrate-"));
374
+ assert.deepEqual(afterBackups, firstBackups, "rollback must preserve the reused backup");
375
+ assert.ok(existsSync(milestonesPath), "legacy milestones/ should be restored on rollback");
376
+ });
377
+
378
+ test("migration ignores an empty/partial leftover backup and writes a complete one (#1292)", async () => {
379
+ const base = makeTmp();
380
+
381
+ // Simulate a prior first-time backup that crashed mid-cpSync: an empty
382
+ // migrate-<ts>/ leftover with no milestones/ content. It is the newest entry,
383
+ // so mtime-based selection would reuse it as the rollback copy if content were
384
+ // not validated — silently retaining a recovery copy missing the legacy tree.
385
+ const backupRoot = join(base, ".gsd-backups");
386
+ const emptyLeftover = join(backupRoot, "migrate-crashed");
387
+ mkdirSync(emptyLeftover, { recursive: true });
388
+
389
+ await migrateToFlatPhase(base);
390
+
391
+ assert.ok(existsSync(join(base, ".gsd", "phases", "01-foundation")), "flat phase should render");
392
+ // The empty leftover must not have been reused; a fresh, content-bearing
393
+ // backup that actually captured the legacy milestones/ tree must be created.
394
+ const contentBackups = readdirSync(backupRoot)
395
+ .filter((d) => d.startsWith("migrate-"))
396
+ .filter((d) => existsSync(join(backupRoot, d, "M001")));
397
+ assert.ok(
398
+ contentBackups.length >= 1,
399
+ "a complete backup containing the legacy milestones/ tree must be created, not the empty leftover",
400
+ );
401
+ });
402
+
202
403
  test("migrateToFlatPhase preserves slice sidecar artifacts and skips recovery placeholder PLAN", async () => {
203
404
  const base = makeTmp({ withTask: false });
204
405
  const legacySliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
@@ -9,7 +9,7 @@ import { join } from "node:path";
9
9
  import assert from "node:assert/strict";
10
10
  import test from "node:test";
11
11
 
12
- import { normalizeRealPath, relMilestoneFile, relSliceFile, resolveMilestoneFile, targetMilestoneFile } from "../paths.ts";
12
+ import { normalizeRealPath, relMilestoneFile, relSliceFile, resolveMilestoneFile, resolveSliceFile, targetMilestoneFile } from "../paths.ts";
13
13
 
14
14
  function makeFlatPhaseFixture(): { basePath: string; cleanup: () => void } {
15
15
  const basePath = mkdtempSync(join(tmpdir(), "flat-phase-validation-"));
@@ -99,6 +99,25 @@ test("flat-phase: resolveMilestoneFile finds the on-disk file", (t) => {
99
99
  assert.equal(existsSync(abs!), true);
100
100
  });
101
101
 
102
+ test("flat-phase: file resolvers ignore directories with artifact-like names", (t) => {
103
+ const basePath = mkdtempSync(join(tmpdir(), "flat-phase-dir-artifacts-"));
104
+ t.after(() => rmSync(basePath, { recursive: true, force: true }));
105
+ const phaseDir = join(basePath, ".gsd", "phases", "03-match-capture-manual-entry");
106
+ mkdirSync(join(phaseDir, "03-VALIDATION.md"), { recursive: true });
107
+ mkdirSync(join(phaseDir, "03-01-SUMMARY.md"), { recursive: true });
108
+
109
+ assert.equal(
110
+ resolveMilestoneFile(basePath, "M003", "VALIDATION"),
111
+ null,
112
+ "milestone resolver must not return a directory as a validation file",
113
+ );
114
+ assert.equal(
115
+ resolveSliceFile(basePath, "M003", "S01", "SUMMARY"),
116
+ null,
117
+ "slice resolver must not return a directory as a summary file",
118
+ );
119
+ });
120
+
102
121
  test("flat-phase: the legacy hardcoded path does NOT resolve (regression for #876)", (t) => {
103
122
  const { basePath, cleanup } = makeFlatPhaseFixture();
104
123
  t.after(cleanup);
@@ -19,6 +19,11 @@ import {
19
19
  insertMilestone,
20
20
  insertSlice,
21
21
  } from "../gsd-db.ts";
22
+ import { getDb } from "../db/engine.ts";
23
+
24
+ function gateRunCount(gateId: string): number {
25
+ return (getDb().prepare("SELECT count(*) AS cnt FROM gate_runs WHERE gate_id = :gid").get({ ":gid": gateId }) as { cnt: number }).cnt;
26
+ }
22
27
 
23
28
  describe("quality_gates CRUD", () => {
24
29
  let tmpDir: string;
@@ -83,6 +88,30 @@ describe("quality_gates CRUD", () => {
83
88
  assert.ok(results[0].evaluated_at);
84
89
  });
85
90
 
91
+ test("saveGateResult commits the verdict and the gate_runs ledger row together", () => {
92
+ insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
93
+ saveGateResult({
94
+ milestoneId: "M001", sliceId: "S01", gateId: "Q3",
95
+ verdict: "pass", rationale: "OK", findings: "",
96
+ });
97
+ assert.equal(getGateResults("M001", "S01")[0].status, "complete");
98
+ assert.equal(gateRunCount("Q3"), 1, "exactly one ledger row must accompany the verdict");
99
+ });
100
+
101
+ test("saveGateResult rolls back the verdict UPDATE if the ledger INSERT fails", () => {
102
+ insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
103
+ // Force the insertGateRun step to throw after the UPDATE by removing the
104
+ // ledger table. Atomicity means the gate row must stay pending.
105
+ getDb().exec("DROP TABLE gate_runs");
106
+ assert.throws(() => saveGateResult({
107
+ milestoneId: "M001", sliceId: "S01", gateId: "Q3",
108
+ verdict: "pass", rationale: "OK", findings: "",
109
+ }));
110
+ const gate = getGateResults("M001", "S01")[0];
111
+ assert.equal(gate.status, "pending", "gate verdict UPDATE must roll back when the ledger INSERT fails");
112
+ assert.equal(gate.verdict ?? "", "", "verdict must not persist after rollback");
113
+ });
114
+
86
115
  test("saveGateResult throws when the gate row does not exist", () => {
87
116
  assert.throws(
88
117
  () => saveGateResult({
@@ -46,6 +46,9 @@ import {
46
46
  tryCreateMemoriesFts,
47
47
  _isLikelyWslDrvFsPathForTest,
48
48
  _shouldAttemptVacuumRecoveryForTest,
49
+ insertArtifact,
50
+ getArtifact,
51
+ upsertMilestonePlanning,
49
52
  } from '../gsd-db.ts';
50
53
  import { MigrationBackupError } from '../db-migration-backup.ts';
51
54
  import { _resetLogs, peekLogs, setStderrLoggingEnabled } from '../workflow-logger.ts';
@@ -280,6 +283,31 @@ describe('gsd-db', () => {
280
283
  }
281
284
  });
282
285
 
286
+ test("gsd-db: insertTask stamps completed_at for every complete-alias but not for skipped", () => {
287
+ openDatabase(":memory:");
288
+
289
+ try {
290
+ insertMilestone({ id: "M001", title: "Completion stamp", status: "active" });
291
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Slice", status: "active", sequence: 1 });
292
+ insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "Closed", status: "closed", sequence: 1 });
293
+ insertTask({ id: "T02", sliceId: "S01", milestoneId: "M001", title: "Done", status: "done", sequence: 2 });
294
+ insertTask({ id: "T03", sliceId: "S01", milestoneId: "M001", title: "Skipped", status: "skipped", sequence: 3 });
295
+
296
+ assert.ok(
297
+ getTask("M001", "S01", "T01")?.completed_at,
298
+ "a task imported as 'closed' is terminal and must carry a completed_at",
299
+ );
300
+ assert.ok(getTask("M001", "S01", "T02")?.completed_at, "'done' alias must stamp completed_at");
301
+ assert.equal(
302
+ getTask("M001", "S01", "T03")?.completed_at,
303
+ null,
304
+ "a skipped task was never completed and must have null completed_at",
305
+ );
306
+ } finally {
307
+ closeDatabase();
308
+ }
309
+ });
310
+
283
311
  test('gsd-db: active_decisions view excludes superseded', () => {
284
312
  openDatabase(':memory:');
285
313
 
@@ -332,6 +360,35 @@ describe('gsd-db', () => {
332
360
  closeDatabase();
333
361
  });
334
362
 
363
+ test("gsd-db: upsertMilestonePlanning rewrites placeholder phase artifact paths to final title slug", () => {
364
+ openDatabase(":memory:");
365
+
366
+ const stalePath = "phases/01-new-milestone-m001/01-ROADMAP.md";
367
+ const finalPath = "phases/01-lokably-brand-foundation-and-welcome-pag/01-ROADMAP.md";
368
+ insertMilestone({ id: "M001", title: "New milestone M001", status: "active" });
369
+ insertArtifact({
370
+ path: stalePath,
371
+ artifact_type: "ROADMAP",
372
+ milestone_id: "M001",
373
+ slice_id: null,
374
+ task_id: null,
375
+ full_content: "# Placeholder roadmap\n",
376
+ });
377
+
378
+ upsertMilestonePlanning("M001", {
379
+ title: "Lokably brand foundation and welcome page rebuild",
380
+ });
381
+
382
+ assert.equal(getArtifact(stalePath), null, "placeholder-derived artifact row should be removed");
383
+ assert.equal(
384
+ getArtifact(finalPath)?.full_content,
385
+ "# Placeholder roadmap\n",
386
+ "artifact row should move to the final title-derived phase path",
387
+ );
388
+
389
+ closeDatabase();
390
+ });
391
+
335
392
  test('gsd-db: active_requirements view excludes superseded', () => {
336
393
  openDatabase(':memory:');
337
394
 
@@ -87,6 +87,28 @@ test("guided milestone prompt builder preloads milestone planning context", asyn
87
87
  }
88
88
  });
89
89
 
90
+ test("guided milestone prompt builder prepends configured response language", async () => {
91
+ const base = mkdtempSync(join(tmpdir(), "gsd-guided-milestone-language-"));
92
+ const gsdHome = mkdtempSync(join(tmpdir(), "gsd-guided-milestone-language-home-"));
93
+ const previousGsdHome = process.env.GSD_HOME;
94
+ process.env.GSD_HOME = gsdHome;
95
+
96
+ try {
97
+ writeFileSync(join(gsdHome, "PREFERENCES.md"), "---\nversion: 1\nlanguage: 中文\n---\n", "utf-8");
98
+
99
+ const prompt = await buildDiscussMilestonePrompt("M001", "Language Preference", base, "true", {
100
+ includeContextMode: false,
101
+ });
102
+
103
+ assert.match(prompt, /^## Response Language\n\nAlways respond in 中文/);
104
+ } finally {
105
+ if (previousGsdHome === undefined) delete process.env.GSD_HOME;
106
+ else process.env.GSD_HOME = previousGsdHome;
107
+ rmSync(base, { recursive: true, force: true });
108
+ rmSync(gsdHome, { recursive: true, force: true });
109
+ }
110
+ });
111
+
90
112
  test("guided milestone prompt builder caps prior draft seed before interpolation", async () => {
91
113
  const base = mkdtempSync(join(tmpdir(), "gsd-guided-milestone-draft-cap-"));
92
114
  const previousGsdHome = process.env.GSD_HOME;
@@ -0,0 +1,116 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Regression for #1291 — a full markdown re-import must NOT rewrite
3
+ // the completed_at of an already-complete slice or milestone with the current
4
+ // import time. The task path was fixed for this (#1222/#1228) via
5
+ // preserveCompletionMetadata; the slice and milestone backfills in
6
+ // migrateHierarchyToDb had no such guard, so every re-import re-stamped every
7
+ // complete slice/milestone. The fix threads preserveCompletion through
8
+ // updateSliceStatus/updateMilestoneStatus so an existing completed_at survives.
9
+
10
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
11
+ import { join } from 'node:path';
12
+ import { tmpdir } from 'node:os';
13
+
14
+ import {
15
+ openDatabase,
16
+ closeDatabase,
17
+ getAllMilestones,
18
+ getMilestoneSlices,
19
+ updateSliceStatus,
20
+ updateMilestoneStatus,
21
+ } from '../gsd-db.ts';
22
+ import { migrateHierarchyToDb } from '../md-importer.ts';
23
+ import { describe, test, afterEach } from 'node:test';
24
+ import assert from 'node:assert/strict';
25
+
26
+ const tmpDirs: string[] = [];
27
+ afterEach(() => {
28
+ closeDatabase();
29
+ for (const d of tmpDirs) { try { rmSync(d, { recursive: true, force: true }); } catch { /* */ } }
30
+ tmpDirs.length = 0;
31
+ });
32
+
33
+ function createFixtureBase(): string {
34
+ const base = mkdtempSync(join(tmpdir(), 'gsd-preserve-completion-'));
35
+ tmpDirs.push(base);
36
+ return base;
37
+ }
38
+
39
+ function writeFile(base: string, relativePath: string, content: string): void {
40
+ const full = join(base, '.gsd', relativePath);
41
+ mkdirSync(join(full, '..'), { recursive: true });
42
+ writeFileSync(full, content);
43
+ }
44
+
45
+ // All slices [x] → milestone imports complete, slices import complete.
46
+ const ROADMAP_ALL_DONE = `# M001: Finished Milestone
47
+
48
+ **Vision:** Done work.
49
+
50
+ ## Slices
51
+
52
+ - [x] **S01: First Slice** \`risk:low\` \`depends:[]\`
53
+ > After this: Done.
54
+
55
+ - [x] **S02: Second Slice** \`risk:medium\` \`depends:[S01]\`
56
+ > After this: Also done.
57
+ `;
58
+
59
+ const REAL_S01 = '2026-07-05T19:52:04.672Z';
60
+ const REAL_S02 = '2026-07-05T20:36:51.313Z';
61
+ const REAL_M001 = '2026-07-05T21:00:00.000Z';
62
+
63
+ describe('migrateHierarchyToDb: re-import preserves existing completion timestamps (#1291)', () => {
64
+ test('a re-import does not rewrite already-complete slice completed_at', () => {
65
+ const base = createFixtureBase();
66
+ writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_ALL_DONE);
67
+
68
+ openDatabase(join(base, '.gsd', 'gsd.db'));
69
+ migrateHierarchyToDb(base);
70
+
71
+ // Simulate the durable completion timestamps the real run wrote hours apart.
72
+ updateSliceStatus('M001', 'S01', 'complete', REAL_S01);
73
+ updateSliceStatus('M001', 'S02', 'complete', REAL_S02);
74
+
75
+ // A second full re-import (the class of event that bit the reporter).
76
+ migrateHierarchyToDb(base);
77
+
78
+ const slices = getMilestoneSlices('M001');
79
+ const s01 = slices.find((s) => s.id === 'S01')!;
80
+ const s02 = slices.find((s) => s.id === 'S02')!;
81
+ assert.equal(s01.completed_at, REAL_S01, 'S01 completed_at must survive re-import unchanged');
82
+ assert.equal(s02.completed_at, REAL_S02, 'S02 completed_at must survive re-import unchanged');
83
+ });
84
+
85
+ test('a re-import does not rewrite an already-complete milestone completed_at', () => {
86
+ const base = createFixtureBase();
87
+ writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_ALL_DONE);
88
+
89
+ openDatabase(join(base, '.gsd', 'gsd.db'));
90
+ migrateHierarchyToDb(base);
91
+
92
+ updateMilestoneStatus('M001', 'complete', REAL_M001);
93
+
94
+ migrateHierarchyToDb(base);
95
+
96
+ const m001 = getAllMilestones().find((m) => m.id === 'M001')!;
97
+ assert.equal(m001.completed_at, REAL_M001, 'M001 completed_at must survive re-import unchanged');
98
+ });
99
+
100
+ test('an initial import of a complete slice still backfills a completed_at when the row has none', () => {
101
+ // The guard preserves an existing timestamp but must not suppress the
102
+ // legitimate first-time backfill for a slice imported as complete.
103
+ const base = createFixtureBase();
104
+ writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_ALL_DONE);
105
+
106
+ openDatabase(join(base, '.gsd', 'gsd.db'));
107
+ migrateHierarchyToDb(base);
108
+
109
+ const slices = getMilestoneSlices('M001');
110
+ for (const s of slices) {
111
+ assert.ok(s.completed_at, `complete slice ${s.id} should receive a backfilled completed_at on first import`);
112
+ }
113
+ const m001 = getAllMilestones().find((m) => m.id === 'M001')!;
114
+ assert.ok(m001.completed_at, 'complete milestone should receive a backfilled completed_at on first import');
115
+ });
116
+ });
@@ -1428,6 +1428,19 @@ process.exit(result.status ?? 0);
1428
1428
  rmSync(repo, { recursive: true, force: true });
1429
1429
  });
1430
1430
 
1431
+ test('Integration branch: write does not create legacy milestones scaffold', () => {
1432
+ const repo = initBranchTestRepo();
1433
+ mkdirSync(join(repo, ".gsd", "phases"), { recursive: true });
1434
+
1435
+ writeIntegrationBranch(repo, "M001", "f-123-new-thing");
1436
+
1437
+ assert.deepStrictEqual(readIntegrationBranch(repo, "M001"), "f-123-new-thing");
1438
+ assert.ok(existsSync(join(repo, ".gsd", "M001-META.json")), "metadata is written at the flat .gsd root");
1439
+ assert.ok(!existsSync(join(repo, ".gsd", "milestones")), "legacy milestones/ root is not created");
1440
+
1441
+ rmSync(repo, { recursive: true, force: true });
1442
+ });
1443
+
1431
1444
  // ─── writeIntegrationBranch: updates when branch changes (#300) ──────
1432
1445
 
1433
1446
  test('Integration branch: updates on branch change', () => {
@@ -1,6 +1,6 @@
1
1
  import { describe, test } from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
- import { mkdtempSync, mkdirSync, rmSync, realpathSync, symlinkSync, writeFileSync } from "node:fs";
3
+ import { mkdtempSync, mkdirSync, rmSync, realpathSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { tmpdir } from "node:os";
6
6
  import { spawnSync } from "node:child_process";
@@ -12,6 +12,8 @@ import {
12
12
  resolveGsdPathContract,
13
13
  resolveSliceFile,
14
14
  resolveTaskFile,
15
+ resolveTaskFiles,
16
+ taskIdFromTaskFileName,
15
17
  _clearGsdRootCache,
16
18
  } from "../../paths.ts";
17
19
  /** Create a tmp dir and resolve symlinks + 8.3 short names (macOS /var→/private/var, Windows RUNNER~1→runneradmin). */
@@ -171,21 +173,37 @@ describe('paths', () => {
171
173
  test('Case 9: flat-phase task SUMMARY resolves at phase root despite a stray slices/SID/ dir', () => {
172
174
  const root = tmp();
173
175
  try {
174
- // Hybrid flat-phase milestone: phase dir holds flat TID-SUMMARY.md, but a
176
+ // Hybrid flat-phase milestone: phase dir holds flat task summaries, but a
175
177
  // stray slices/S01/ folder also exists on disk. resolveSlicePath then points
176
178
  // under slices/, so layout (phases/ vs milestones/) — not slicePath===phaseDir
177
179
  // — must decide the flat-phase task summary location.
178
180
  const phaseDir = join(root, ".gsd", "phases", "01-foo");
179
181
  mkdirSync(join(phaseDir, "slices", "S01"), { recursive: true });
180
- const flatSummary = join(phaseDir, "T01-SUMMARY.md");
182
+ const flatSummary = join(phaseDir, "S01-T01-SUMMARY.md");
183
+ const legacyFlatSummary = join(phaseDir, "T01-SUMMARY.md");
181
184
  writeFileSync(flatSummary, "# task summary\n");
185
+ writeFileSync(legacyFlatSummary, "# legacy task summary\n");
182
186
 
183
187
  _clearGsdRootCache();
184
188
 
189
+ assert.deepStrictEqual(resolveTaskFiles(phaseDir, "SUMMARY").sort(), [
190
+ "S01-T01-SUMMARY.md",
191
+ "T01-SUMMARY.md",
192
+ ]);
193
+ assert.equal(taskIdFromTaskFileName("S01-T01-SUMMARY.md", "SUMMARY"), "T01");
194
+ assert.equal(taskIdFromTaskFileName("T01-SUMMARY.md", "SUMMARY"), "T01");
195
+
185
196
  assert.deepStrictEqual(
186
197
  resolveTaskFile(root, "M001", "S01", "T01", "SUMMARY"),
187
198
  flatSummary,
188
- "flat-phase TID-SUMMARY.md at phase root is found even when slices/S01/ exists",
199
+ "flat-phase S01-T01-SUMMARY.md at phase root is preferred even when slices/S01/ exists",
200
+ );
201
+
202
+ unlinkSync(flatSummary);
203
+ assert.deepStrictEqual(
204
+ resolveTaskFile(root, "M001", "S01", "T01", "SUMMARY"),
205
+ legacyFlatSummary,
206
+ "legacy flat T01-SUMMARY.md is still found as a fallback",
189
207
  );
190
208
  } finally { cleanup(root); }
191
209
  });