@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
@@ -56,6 +56,10 @@ function buildBlock(
56
56
  });
57
57
  }
58
58
 
59
+ function expectedSkillRead(base: string, name: string): string {
60
+ return `Read the skill file at \`${join(base, "skills", name, "SKILL.md")}\``;
61
+ }
62
+
59
63
  test("buildSkillActivationBlock does not auto-activate skills via broad context heuristic", () => {
60
64
  const base = makeTempBase();
61
65
  try {
@@ -92,7 +96,7 @@ test("buildSkillActivationBlock activates skills via prefer_skills when context
92
96
  prefer_skills: ["react"],
93
97
  });
94
98
 
95
- assert.match(result, /Read the installed 'react' skill file from <available_skills>/);
99
+ assert.ok(result.includes(expectedSkillRead(base, "react")));
96
100
  assert.doesNotMatch(result, /swiftui/);
97
101
  } finally {
98
102
  cleanup(base);
@@ -111,7 +115,7 @@ test("buildSkillActivationBlock includes always_use_skills using read-based skil
111
115
 
112
116
  assert.equal(
113
117
  result,
114
- "<skill_activation>Read the installed 'swift-testing' skill file from <available_skills>.</skill_activation>",
118
+ `<skill_activation>Read the skill file at \`${join(base, "skills", "swift-testing", "SKILL.md")}\`.</skill_activation>`,
115
119
  );
116
120
  } finally {
117
121
  cleanup(base);
@@ -140,8 +144,8 @@ test("buildSkillActivationBlock includes skill_rules matches and task-plan skill
140
144
  skill_rules: [{ when: "prisma database schema", use: ["prisma"] }],
141
145
  });
142
146
 
143
- assert.match(result, /Read the installed 'accessibility' skill file from <available_skills>/);
144
- assert.match(result, /Read the installed 'prisma' skill file from <available_skills>/);
147
+ assert.ok(result.includes(expectedSkillRead(base, "accessibility")));
148
+ assert.ok(result.includes(expectedSkillRead(base, "prisma")));
145
149
  } finally {
146
150
  cleanup(base);
147
151
  }
@@ -163,7 +167,7 @@ test("buildSkillActivationBlock matches skill_rules against exact unit type cont
163
167
  ],
164
168
  });
165
169
 
166
- assert.match(result, /Read the installed 'complete-slice-policies' skill file from <available_skills>/);
170
+ assert.ok(result.includes(expectedSkillRead(base, "complete-slice-policies")));
167
171
  assert.doesNotMatch(result, /slice-broad/);
168
172
  } finally {
169
173
  cleanup(base);
@@ -267,8 +271,8 @@ test("buildSkillActivationBlock allows valid skill names and rejects invalid one
267
271
  });
268
272
 
269
273
  assert.match(result, /skill_activation/);
270
- assert.match(result, /Read the installed 'react' skill file from <available_skills>/);
271
- assert.match(result, /Read the installed 'good-skill-2' skill file from <available_skills>/);
274
+ assert.ok(result.includes(expectedSkillRead(base, "react")));
275
+ assert.ok(result.includes(expectedSkillRead(base, "good-skill-2")));
272
276
  assert.doesNotMatch(result, /bad'name/);
273
277
  } finally {
274
278
  cleanup(base);
@@ -292,8 +296,8 @@ test("buildSkillActivationBlock: explicit always_use_skills bypass the unit-type
292
296
  always_use_skills: ["write-docs", "swiftui"],
293
297
  });
294
298
 
295
- assert.match(result, /Read the installed 'write-docs' skill file from <available_skills>/);
296
- assert.match(result, /Read the installed 'swiftui' skill file from <available_skills>/);
299
+ assert.ok(result.includes(expectedSkillRead(base, "write-docs")));
300
+ assert.ok(result.includes(expectedSkillRead(base, "swiftui")));
297
301
  } finally {
298
302
  cleanup(base);
299
303
  }
@@ -310,7 +314,7 @@ test("buildSkillActivationBlock falls through to all skills for unknown unit typ
310
314
  });
311
315
 
312
316
  // Unknown unit type = wildcard fallback (pre-manifest behavior).
313
- assert.match(result, /Read the installed 'swiftui' skill file from <available_skills>/);
317
+ assert.ok(result.includes(expectedSkillRead(base, "swiftui")));
314
318
  } finally {
315
319
  cleanup(base);
316
320
  }
@@ -327,7 +331,7 @@ test("buildSkillActivationBlock without unitType preserves pre-manifest behavior
327
331
  always_use_skills: ["swiftui"],
328
332
  });
329
333
 
330
- assert.match(result, /Read the installed 'swiftui' skill file from <available_skills>/);
334
+ assert.ok(result.includes(expectedSkillRead(base, "swiftui")));
331
335
  } finally {
332
336
  cleanup(base);
333
337
  }
@@ -344,12 +348,12 @@ test("milestone prompt builders propagate always_use_skills through buildSkillAc
344
348
  loadOnlyTestSkills(base);
345
349
 
346
350
  const researchPrompt = await buildResearchMilestonePrompt("M001", "Test", base);
347
- assert.match(researchPrompt, /Read the installed 'write-docs' skill file from <available_skills>/);
348
- assert.match(researchPrompt, /Read the installed 'swiftui' skill file from <available_skills>/);
351
+ assert.ok(researchPrompt.includes(expectedSkillRead(base, "write-docs")));
352
+ assert.ok(researchPrompt.includes(expectedSkillRead(base, "swiftui")));
349
353
 
350
354
  const planPrompt = await buildPlanMilestonePrompt("M001", "Test", base);
351
- assert.match(planPrompt, /Read the installed 'write-docs' skill file from <available_skills>/);
352
- assert.match(planPrompt, /Read the installed 'swiftui' skill file from <available_skills>/);
355
+ assert.ok(planPrompt.includes(expectedSkillRead(base, "write-docs")));
356
+ assert.ok(planPrompt.includes(expectedSkillRead(base, "swiftui")));
353
357
  } finally {
354
358
  cleanup(base);
355
359
  }
@@ -380,7 +384,7 @@ test("complete-slice prompt propagates always_use_skills through buildSkillActiv
380
384
 
381
385
  const prompt = await buildCompleteSlicePrompt("M001", "Test", "S01", "Slice", base);
382
386
 
383
- assert.match(prompt, /Read the installed 'write-docs' skill file from <available_skills>/);
387
+ assert.ok(prompt.includes(expectedSkillRead(base, "write-docs")));
384
388
  } finally {
385
389
  cleanup(base);
386
390
  }
@@ -25,6 +25,7 @@ import {
25
25
  updateTaskStatus,
26
26
  } from "../gsd-db.ts";
27
27
  import { handleSkipSlice } from "../tools/skip-slice.ts";
28
+ import { skipSliceCascade } from "../db/writers/cascades.ts";
28
29
 
29
30
  describe("handleSkipSlice cascades skip to tasks (#4375)", () => {
30
31
  let dir: string;
@@ -122,4 +123,24 @@ describe("handleSkipSlice cascades skip to tasks (#4375)", () => {
122
123
  assert.match(result.error!, /not found/i);
123
124
  assert.equal(result.errorCode, "slice_not_found");
124
125
  });
126
+
127
+ test("skipSliceCascade rejects a slice in the legacy 'closed' status without nulling completed_at", () => {
128
+ const completedAt = "2026-01-01T00:00:00.000Z";
129
+ updateSliceStatus("M001", "S03", "closed", completedAt);
130
+
131
+ const outcome = skipSliceCascade("M001", "S03");
132
+ assert.deepEqual(outcome, { ok: false, reason: "slice-already-complete" });
133
+
134
+ const slice = getSlice("M001", "S03");
135
+ assert.equal(slice?.status, "closed", "closed slice must not be downgraded to skipped");
136
+ assert.equal(slice?.completed_at, completedAt, "completed_at must be preserved");
137
+ });
138
+
139
+ test("skipSliceCascade still re-skips an already-skipped slice (ok, wasAlreadySkipped)", () => {
140
+ updateSliceStatus("M001", "S03", "skipped");
141
+
142
+ const outcome = skipSliceCascade("M001", "S03");
143
+ assert.equal(outcome.ok, true);
144
+ if (outcome.ok) assert.equal(outcome.wasAlreadySkipped, true);
145
+ });
125
146
  });
@@ -14,6 +14,7 @@ import {
14
14
  isPauseNotice,
15
15
  isBlockedNoticeMessage,
16
16
  isManualResolutionNotice,
17
+ isInteractiveMenuUnavailableNotice,
17
18
  PAUSED_NOTICE_PREFIXES,
18
19
  TERMINAL_NOTICE_PREFIXES,
19
20
  } from "../stop-notice.js";
@@ -62,6 +63,22 @@ describe("emitter↔detector round-trip", () => {
62
63
  assert.ok(isBlockedNoticeMessage(message));
63
64
  });
64
65
 
66
+ test("un-showable menu notices classify as blocked (#1294)", () => {
67
+ // Emitted verbatim by notifyCommandMenuUnavailable (next-action-ui.ts / command-feedback.ts).
68
+ const menuUnavailable =
69
+ "gsd — m002: editorial hn menu could not be shown in this session.\nrun /gsd when ready.";
70
+ assert.ok(isInteractiveMenuUnavailableNotice(menuUnavailable));
71
+ assert.ok(isBlockedNoticeMessage(menuUnavailable));
72
+
73
+ // Emitted by notifyPickerCommandNeedsInteractiveMenu (command-feedback.ts).
74
+ const pickerGuidance = "/gsd did not start: milestone menu needs an interactive session";
75
+ assert.ok(isInteractiveMenuUnavailableNotice(pickerGuidance));
76
+ assert.ok(isBlockedNoticeMessage(pickerGuidance));
77
+
78
+ // Unrelated notices are not swept up.
79
+ assert.equal(isInteractiveMenuUnavailableNotice("auto-mode complete"), false);
80
+ });
81
+
65
82
  test("terminal prefixes cover the known stop vocabulary", () => {
66
83
  for (const message of ["auto-mode stopped.", "auto-mode complete", "auto-mode idle", "no active milestone"]) {
67
84
  assert.ok(TERMINAL_NOTICE_PREFIXES.some((prefix) => message.startsWith(prefix)), message);
@@ -174,3 +174,22 @@ test('sync-lock: contended fresh lock fails fast without honoring long sync time
174
174
  cleanupDir(base);
175
175
  }
176
176
  });
177
+
178
+ test('sync-lock: uncreatable lock path fails open instead of spinning forever', () => {
179
+ const base = tempDir();
180
+ try {
181
+ // `.gsd` is a dangling symlink to a missing target: the O_EXCL open lands
182
+ // on a missing parent and throws non-EEXIST on every attempt. Without the
183
+ // fail-open guard the retry loop spins forever, blocking the event loop.
184
+ fs.symlinkSync(path.join(base, 'missing-external-state'), path.join(base, '.gsd'), 'junction');
185
+
186
+ const startedAt = performance.now();
187
+ const result = acquireSyncLock(base, 0, 'write-gate.lock');
188
+ const elapsedMs = performance.now() - startedAt;
189
+
190
+ assert.strictEqual(result.acquired, false, 'uncreatable lock path must fail open, not acquire');
191
+ assert.ok(elapsedMs < 250, `must return promptly, not spin; elapsed=${elapsedMs.toFixed(1)}ms`);
192
+ } finally {
193
+ cleanupDir(base);
194
+ }
195
+ });
@@ -4,7 +4,13 @@
4
4
  import { describe, test } from "node:test";
5
5
  import assert from "node:assert/strict";
6
6
 
7
- import { buildContextMessage, stripVolatileCodebaseMetadata } from "../bootstrap/system-context.ts";
7
+ import {
8
+ buildContextMessage,
9
+ GSD_CONTEXT_MESSAGE_SENTINEL,
10
+ stripVolatileCodebaseMetadata,
11
+ } from "../bootstrap/system-context.ts";
12
+
13
+ const SENTINEL = `${GSD_CONTEXT_MESSAGE_SENTINEL}\n`;
8
14
 
9
15
  describe("stripVolatileCodebaseMetadata (#847 — KV cache stability)", () => {
10
16
  const map = [
@@ -63,7 +69,7 @@ describe("buildContextMessage (#5019 — memory routing)", () => {
63
69
  });
64
70
  assert.ok(result, "expected a context message");
65
71
  assert.equal(result.customType, "gsd-memory");
66
- assert.equal(result.content, "[GSD Context Metadata]\n- Memory supplied: yes\n\n[MEMORY]\nrule one\nrule two");
72
+ assert.equal(result.content, `${SENTINEL}[GSD Context Metadata]\n- Memory supplied: yes\n\n[MEMORY]\nrule one\nrule two`);
67
73
  assert.equal(result.display, false);
68
74
  });
69
75
 
@@ -75,7 +81,7 @@ describe("buildContextMessage (#5019 — memory routing)", () => {
75
81
  });
76
82
  assert.ok(result);
77
83
  assert.equal(result.customType, "gsd-guided-context");
78
- assert.equal(result.content, "[GUIDED]\nexecute T01");
84
+ assert.equal(result.content, `${SENTINEL}[GUIDED]\nexecute T01`);
79
85
  });
80
86
 
81
87
  test("forensics injection alone emits gsd-forensics", () => {
@@ -86,7 +92,7 @@ describe("buildContextMessage (#5019 — memory routing)", () => {
86
92
  });
87
93
  assert.ok(result);
88
94
  assert.equal(result.customType, "gsd-forensics");
89
- assert.equal(result.content, "[FORENSICS]\ninvestigation context");
95
+ assert.equal(result.content, `${SENTINEL}[FORENSICS]\ninvestigation context`);
90
96
  });
91
97
 
92
98
  test("memory + guided injection: memory prepended, customType is gsd-guided-context", () => {
@@ -97,7 +103,7 @@ describe("buildContextMessage (#5019 — memory routing)", () => {
97
103
  });
98
104
  assert.ok(result);
99
105
  assert.equal(result.customType, "gsd-guided-context");
100
- assert.equal(result.content, `${markedMemory}\n\n[GUIDED]\nexecute T01`);
106
+ assert.equal(result.content, `${SENTINEL}${markedMemory}\n\n[GUIDED]\nexecute T01`);
101
107
  });
102
108
 
103
109
  test("memory + forensics: memory prepended, customType is gsd-forensics", () => {
@@ -108,7 +114,7 @@ describe("buildContextMessage (#5019 — memory routing)", () => {
108
114
  });
109
115
  assert.ok(result);
110
116
  assert.equal(result.customType, "gsd-forensics");
111
- assert.equal(result.content, `${markedMemory}\n\n[FORENSICS]\ninvestigation context`);
117
+ assert.equal(result.content, `${SENTINEL}${markedMemory}\n\n[FORENSICS]\ninvestigation context`);
112
118
  });
113
119
 
114
120
  test("guided takes precedence over forensics when both are somehow present", () => {
@@ -122,6 +128,6 @@ describe("buildContextMessage (#5019 — memory routing)", () => {
122
128
  });
123
129
  assert.ok(result);
124
130
  assert.equal(result.customType, "gsd-guided-context");
125
- assert.equal(result.content, "[GUIDED]");
131
+ assert.equal(result.content, `${SENTINEL}[GUIDED]`);
126
132
  });
127
133
  });
@@ -25,8 +25,16 @@ function makeMockPi() {
25
25
 
26
26
  console.log('\n── Tool naming: registration count ──');
27
27
 
28
+ // Aliases are hidden from the model-facing surface by default (plan 035);
29
+ // opt in here so this file can keep exercising alias-registration behavior.
30
+ const previousAdvertiseAliases = process.env.GSD_ADVERTISE_TOOL_ALIASES;
31
+ process.env.GSD_ADVERTISE_TOOL_ALIASES = "1";
32
+
28
33
  const pi = makeMockPi();
29
34
  registerDbTools(pi);
35
+
36
+ if (previousAdvertiseAliases === undefined) delete process.env.GSD_ADVERTISE_TOOL_ALIASES;
37
+ else process.env.GSD_ADVERTISE_TOOL_ALIASES = previousAdvertiseAliases;
30
38
  const toolByName = new Map<string, any>(pi.tools.map((tool: any) => [tool.name, tool]));
31
39
  const registeredCanonicalNames = new Set<string>(
32
40
  WORKFLOW_TOOL_CONTRACTS
@@ -43,7 +43,10 @@ import {
43
43
  insertMilestone,
44
44
  upsertMilestonePlanning,
45
45
  insertSlice,
46
+ insertTask,
47
+ saveReworkBrief,
46
48
  } from "../gsd-db.ts";
49
+ import { clearGSDPreferencesCache, getProjectGSDPreferencesPath } from "../preferences.ts";
47
50
 
48
51
  // ─── Pure composer tests ──────────────────────────────────────────────────
49
52
 
@@ -416,6 +419,44 @@ test("Tool Surface composer: planning-dispatch lists allowed subagents", () => {
416
419
  assert.match(out, /\*\*planner\*\*/);
417
420
  });
418
421
 
422
+ test("Tool Surface composer: planning_subagents updates plan-milestone dispatch guidance", (t) => {
423
+ const originalGsdHome = process.env.GSD_HOME;
424
+ const tempProject = mkdtempSync(join(tmpdir(), "gsd-tool-surface-planning-subagents-"));
425
+ const tempGsdHome = mkdtempSync(join(tmpdir(), "gsd-tool-surface-planning-subagents-home-"));
426
+
427
+ t.after(() => {
428
+ clearGSDPreferencesCache();
429
+ if (originalGsdHome === undefined) delete process.env.GSD_HOME;
430
+ else process.env.GSD_HOME = originalGsdHome;
431
+ rmSync(tempProject, { recursive: true, force: true });
432
+ rmSync(tempGsdHome, { recursive: true, force: true });
433
+ });
434
+
435
+ process.env.GSD_HOME = tempGsdHome;
436
+ mkdirSync(join(tempProject, ".gsd"), { recursive: true });
437
+ clearGSDPreferencesCache();
438
+ writeFileSync(
439
+ getProjectGSDPreferencesPath(tempProject),
440
+ [
441
+ "---",
442
+ "version: 1",
443
+ "planning_subagents:",
444
+ " plan-milestone:",
445
+ " allowed: [security]",
446
+ "---",
447
+ "",
448
+ ].join("\n"),
449
+ "utf-8",
450
+ );
451
+
452
+ const out = composeToolSurfaceInstructions("plan-milestone", {
453
+ renderMode: "standalone",
454
+ basePath: tempProject,
455
+ });
456
+ assert.match(out, /Dispatch subagents only to \*\*security\*\*/);
457
+ assert.doesNotMatch(out, /Do not dispatch subagents/);
458
+ });
459
+
419
460
  test("Tool Surface composer: execute-task warns against slice/milestone closeout tools", () => {
420
461
  const out = composeToolSurfaceInstructions("execute-task", { renderMode: "nested" });
421
462
  assert.match(out, /^Tool surface: /);
@@ -518,6 +559,38 @@ test("#4782 phase 2: buildReassessRoadmapPrompt emits composer-shaped context wi
518
559
  assert.ok(!prompt.includes("Slice Context (from discussion)"));
519
560
  });
520
561
 
562
+
563
+ test("execute-task prompt injects unresolved blocking rework findings", async (t) => {
564
+ const base = makeFixtureBase();
565
+ t.after(() => cleanup(base));
566
+ invalidateAllCaches();
567
+
568
+ seed(base, "M001");
569
+ writeArtifacts(base);
570
+ insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "Task", status: "pending" });
571
+ saveReworkBrief({
572
+ briefId: "RB-001",
573
+ milestoneId: "M001",
574
+ sliceId: "S01",
575
+ taskId: "T01",
576
+ findings: [{
577
+ findingId: "F1",
578
+ severity: "blocking",
579
+ description: "Compile regression",
580
+ requiredFix: "Restore typecheck",
581
+ verificationCommands: ["pnpm run typecheck:extensions"],
582
+ }],
583
+ });
584
+
585
+ const prompt = await buildExecuteTaskPrompt("M001", "S01", "First", "T01", "Task", base);
586
+
587
+ assert.match(prompt, /Blocking Rework Findings \(non-optional\)/);
588
+ assert.match(prompt, /F1/);
589
+ assert.match(prompt, /Compile regression/);
590
+ assert.match(prompt, /pnpm run typecheck:extensions/);
591
+ assert.match(prompt, /reworkResolution/);
592
+ });
593
+
521
594
  test("execute-task prompt omits on-demand slice research when the artifact is absent", async (t) => {
522
595
  const base = makeFixtureBase();
523
596
  t.after(() => cleanup(base));
@@ -1,6 +1,6 @@
1
1
  import test from "node:test";
2
2
  import assert from "node:assert/strict";
3
- import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
+ import { mkdtempSync, mkdirSync, readFileSync, rmSync, statSync, utimesSync, writeFileSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { tmpdir } from "node:os";
6
6
 
@@ -239,6 +239,98 @@ test("plan-v2 ensure rejects empty executable graph", () => {
239
239
  assert.equal(isEmptyPlanV2GraphResult(compiled), true);
240
240
  });
241
241
 
242
+ function seedMultiSliceRows(): void {
243
+ insertMilestone({ id: MILESTONE_ID, title: "Milestone", status: "active" });
244
+ const slices: Array<[string, number, Array<[string, number]>]> = [
245
+ ["S01", 1, [["T01", 1], ["T02", 2]]],
246
+ ["S02", 2, [["T03", 1], ["T04", 2]]],
247
+ ];
248
+ for (const [sid, sseq, tasks] of slices) {
249
+ insertSlice({ id: sid, milestoneId: MILESTONE_ID, title: `Slice ${sid}`, status: "in_progress", sequence: sseq });
250
+ for (const [tid, tseq] of tasks) {
251
+ insertTask({
252
+ id: tid,
253
+ milestoneId: MILESTONE_ID,
254
+ sliceId: sid,
255
+ title: `Task ${tid}`,
256
+ status: "pending",
257
+ keyFiles: [`src/${tid}.ts`],
258
+ sequence: tseq,
259
+ });
260
+ }
261
+ }
262
+ }
263
+
264
+ test("plan-v2 batched compile preserves node ids, order, and count", () => {
265
+ const basePath = createBasePath();
266
+ seedMultiSliceRows();
267
+ writeMilestoneFile(basePath, "CONTEXT", "Finalized context.");
268
+
269
+ const compiled = ensurePlanV2Graph(basePath, buildState("executing"));
270
+ assert.equal(compiled.ok, true);
271
+
272
+ const graph = JSON.parse(readFileSync(compiled.graphPath ?? "", "utf-8")) as {
273
+ nodes: Array<{ id: string }>;
274
+ };
275
+ assert.deepEqual(
276
+ graph.nodes.map((n) => n.id),
277
+ [
278
+ "execute-task:M001:S01:T01",
279
+ "execute-task:M001:S01:T02",
280
+ "complete-slice:M001:S01",
281
+ "execute-task:M001:S02:T03",
282
+ "execute-task:M001:S02:T04",
283
+ "complete-slice:M001:S02",
284
+ ],
285
+ );
286
+ });
287
+
288
+ test("plan-v2 skips the disk write when the graph is unchanged", () => {
289
+ const basePath = createBasePath();
290
+ seedMultiSliceRows();
291
+ writeMilestoneFile(basePath, "CONTEXT", "Finalized context.");
292
+
293
+ const first = ensurePlanV2Graph(basePath, buildState("executing"));
294
+ assert.equal(first.ok, true);
295
+ const graphPath = first.graphPath ?? "";
296
+ const before = readFileSync(graphPath, "utf-8");
297
+
298
+ // Backdate mtime so a rewrite is detectable even within the same millisecond.
299
+ utimesSync(graphPath, 1000, 1000);
300
+ const backdatedMtime = statSync(graphPath).mtimeMs;
301
+
302
+ const second = ensurePlanV2Graph(basePath, buildState("executing"));
303
+ assert.equal(second.ok, true);
304
+ assert.equal(statSync(graphPath).mtimeMs, backdatedMtime, "identical state must not rewrite the graph");
305
+ assert.equal(readFileSync(graphPath, "utf-8"), before);
306
+ });
307
+
308
+ test("plan-v2 rewrites the graph when it changes", () => {
309
+ const basePath = createBasePath();
310
+ seedMultiSliceRows();
311
+ writeMilestoneFile(basePath, "CONTEXT", "Finalized context.");
312
+
313
+ const first = ensurePlanV2Graph(basePath, buildState("executing"));
314
+ const graphPath = first.graphPath ?? "";
315
+ const before = readFileSync(graphPath, "utf-8");
316
+ utimesSync(graphPath, 1000, 1000);
317
+
318
+ insertTask({
319
+ id: "T05",
320
+ milestoneId: MILESTONE_ID,
321
+ sliceId: "S02",
322
+ title: "Added task",
323
+ status: "pending",
324
+ keyFiles: ["src/T05.ts"],
325
+ sequence: 3,
326
+ });
327
+
328
+ const second = ensurePlanV2Graph(basePath, buildState("executing"));
329
+ assert.equal(second.ok, true);
330
+ assert.notEqual(statSync(graphPath).mtimeMs, 1000000, "changed graph must rewrite");
331
+ assert.notEqual(readFileSync(graphPath, "utf-8"), before);
332
+ });
333
+
242
334
  test("plan-v2 allows empty graph for milestone terminal phases", () => {
243
335
  const basePath = createBasePath();
244
336
  writeMilestoneFile(basePath, "CONTEXT", "Finalized context.");
@@ -94,6 +94,8 @@ test("complete-slice requires status, closeout, and execution handoff tools", ()
94
94
  "gsd_slice_complete",
95
95
  "gsd_task_reopen",
96
96
  "gsd_replan_slice",
97
+ "gsd_replan_task",
98
+ "gsd_rework_brief_save",
97
99
  "gsd_requirement_update",
98
100
  "gsd_summary_save",
99
101
  ];
@@ -0,0 +1,139 @@
1
+ // GSD Extension - Auto-migration gate tests (plan 026).
2
+ // Covers needsAutoMigration's trigger (empty milestones table + .gsd/milestones
3
+ // present) and validateMigration's engine-vs-markdown count comparison.
4
+
5
+ import { describe, test } from 'node:test';
6
+ import assert from 'node:assert/strict';
7
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
8
+ import { join } from 'node:path';
9
+ import { tmpdir } from 'node:os';
10
+
11
+ import { openDatabase, closeDatabase, insertMilestone, insertSlice } from '../gsd-db.ts';
12
+ import { needsAutoMigration, validateMigration } from '../workflow-migration.ts';
13
+
14
+ function makeProject(): string {
15
+ return mkdtempSync(join(tmpdir(), 'gsd-migration-gates-'));
16
+ }
17
+
18
+ function openProjectDb(base: string): string {
19
+ const gsdDir = join(base, '.gsd');
20
+ mkdirSync(gsdDir, { recursive: true });
21
+ const dbPath = join(gsdDir, 'gsd.db');
22
+ assert.ok(openDatabase(dbPath), 'openDatabase should succeed');
23
+ return dbPath;
24
+ }
25
+
26
+ function cleanup(base: string): void {
27
+ closeDatabase();
28
+ rmSync(base, { recursive: true, force: true });
29
+ }
30
+
31
+ function writeRoadmap(base: string, mId: string, sliceLines: string[]): void {
32
+ const mDir = join(base, '.gsd', 'milestones', mId);
33
+ mkdirSync(mDir, { recursive: true });
34
+ writeFileSync(join(mDir, 'ROADMAP.md'), [
35
+ `# ${mId}: Test`,
36
+ '',
37
+ '## Slices',
38
+ '',
39
+ ...sliceLines,
40
+ '',
41
+ ].join('\n'));
42
+ }
43
+
44
+ describe('needsAutoMigration', () => {
45
+ test('false for a fresh project with no legacy markdown', () => {
46
+ const base = makeProject();
47
+ try {
48
+ openProjectDb(base);
49
+ assert.equal(needsAutoMigration(base), false, 'no .gsd/milestones dir → no migration');
50
+ } finally {
51
+ cleanup(base);
52
+ }
53
+ });
54
+
55
+ test('true when engine tables are empty and .gsd/milestones exists', () => {
56
+ const base = makeProject();
57
+ try {
58
+ openProjectDb(base);
59
+ mkdirSync(join(base, '.gsd', 'milestones', 'M001'), { recursive: true });
60
+ assert.equal(needsAutoMigration(base), true, 'legacy markdown + empty engine → migrate');
61
+ } finally {
62
+ cleanup(base);
63
+ }
64
+ });
65
+
66
+ test('false once the milestones table has rows (migration already done)', () => {
67
+ const base = makeProject();
68
+ try {
69
+ openProjectDb(base);
70
+ mkdirSync(join(base, '.gsd', 'milestones', 'M001'), { recursive: true });
71
+ insertMilestone({ id: 'M001', title: 'Migrated' });
72
+ assert.equal(needsAutoMigration(base), false, 'engine rows present → migration already done');
73
+ } finally {
74
+ cleanup(base);
75
+ }
76
+ });
77
+
78
+ test('false when no database connection is open', () => {
79
+ const base = makeProject();
80
+ try {
81
+ mkdirSync(join(base, '.gsd', 'milestones', 'M001'), { recursive: true });
82
+ closeDatabase();
83
+ assert.equal(needsAutoMigration(base), false, 'no DB → cannot migrate');
84
+ } finally {
85
+ cleanup(base);
86
+ }
87
+ });
88
+ });
89
+
90
+ describe('validateMigration', () => {
91
+ test('reports no discrepancies when engine counts match markdown', () => {
92
+ const base = makeProject();
93
+ try {
94
+ openProjectDb(base);
95
+ writeRoadmap(base, 'M001', ['- [ ] **S01: Test Slice** `risk:low` `depends:[]`']);
96
+ insertMilestone({ id: 'M001', title: 'Test' });
97
+ insertSlice({ id: 'S01', milestoneId: 'M001', title: 'Test Slice' });
98
+
99
+ const result = validateMigration(base);
100
+ assert.deepEqual(result.discrepancies, [], 'matching engine/markdown counts → clean');
101
+ } finally {
102
+ cleanup(base);
103
+ }
104
+ });
105
+
106
+ test('reports discrepancies when engine counts diverge from markdown', () => {
107
+ const base = makeProject();
108
+ try {
109
+ openProjectDb(base);
110
+ writeRoadmap(base, 'M001', [
111
+ '- [ ] **S01: Test Slice** `risk:low` `depends:[]`',
112
+ '- [ ] **S02: Second Slice** `risk:low` `depends:[]`',
113
+ ]);
114
+ // Engine has no rows at all → milestone and slice counts both diverge.
115
+ const result = validateMigration(base);
116
+ assert.ok(
117
+ result.discrepancies.some((d) => d.includes('Milestone count mismatch')),
118
+ `expected milestone mismatch, got: ${result.discrepancies.join('; ')}`,
119
+ );
120
+ assert.ok(
121
+ result.discrepancies.some((d) => d.includes('Slice count mismatch')),
122
+ `expected slice mismatch, got: ${result.discrepancies.join('; ')}`,
123
+ );
124
+ } finally {
125
+ cleanup(base);
126
+ }
127
+ });
128
+
129
+ test('reports a validation failure when no database connection is open', () => {
130
+ const base = makeProject();
131
+ try {
132
+ closeDatabase();
133
+ const result = validateMigration(base);
134
+ assert.deepEqual(result.discrepancies, ['No database connection for validation']);
135
+ } finally {
136
+ cleanup(base);
137
+ }
138
+ });
139
+ });
@@ -352,7 +352,7 @@ test('workflow-projections: regenerateIfMissing SUMMARY is idempotent for flat-p
352
352
  keyDecisions: ['Use centralized task summary paths.'],
353
353
  });
354
354
 
355
- const summaryPath = join(phaseDir, 'T01-SUMMARY.md');
355
+ const summaryPath = join(phaseDir, 'S01-T01-SUMMARY.md');
356
356
  assert.ok(!existsSync(summaryPath), 'precondition: flat-phase task summary absent');
357
357
 
358
358
  const first = await regenerateIfMissing(base, 'M001', 'S01', 'SUMMARY');
@@ -399,7 +399,7 @@ test('workflow-projections: flat-phase SUMMARY regeneration ignores stale nested
399
399
  status: 'complete',
400
400
  });
401
401
 
402
- const rootSummaryPath = join(phaseDir, 'T01-SUMMARY.md');
402
+ const rootSummaryPath = join(phaseDir, 'S01-T01-SUMMARY.md');
403
403
  assert.ok(!existsSync(rootSummaryPath), 'precondition: canonical flat-phase task summary absent');
404
404
 
405
405
  const regenerated = await regenerateIfMissing(base, 'M001', 'S01', 'SUMMARY');
@@ -440,8 +440,8 @@ test('workflow-projections: renderSummaryProjection uses milestone title when cr
440
440
  status: 'complete',
441
441
  });
442
442
 
443
- const titleSummaryPath = join(base, '.gsd', 'phases', '01-milestone', 'T01-SUMMARY.md');
444
- const idSummaryPath = join(base, '.gsd', 'phases', '01-m001', 'T01-SUMMARY.md');
443
+ const titleSummaryPath = join(base, '.gsd', 'phases', '01-milestone', 'S01-T01-SUMMARY.md');
444
+ const idSummaryPath = join(base, '.gsd', 'phases', '01-m001', 'S01-T01-SUMMARY.md');
445
445
 
446
446
  renderSummaryProjection(base, 'M001', 'S01', 'T01');
447
447