@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
@@ -0,0 +1,186 @@
1
+ // GSD Extension - Migration guard tests (plan 026).
2
+ // Covers the newer-DB refusal in migrateSchema, whole-chain rollback atomicity
3
+ // via the _setMigrationFaultForTest seam, the legacy-data guard in initSchema,
4
+ // and getCurrentSchemaVersion's empty-table NULL handling.
5
+
6
+ import { describe, test } from 'node:test';
7
+ import assert from 'node:assert/strict';
8
+ import * as fs from 'node:fs';
9
+ import * as path from 'node:path';
10
+ import * as os from 'node:os';
11
+ import { createRequire } from 'node:module';
12
+
13
+ import {
14
+ openDatabase,
15
+ closeDatabase,
16
+ isDbAvailable,
17
+ SCHEMA_VERSION,
18
+ _setMigrationFaultForTest,
19
+ } from '../gsd-db.ts';
20
+ import { createDbAdapter } from '../db-adapter.ts';
21
+ import { getCurrentSchemaVersion } from '../db-schema-metadata.ts';
22
+
23
+ const _require = createRequire(import.meta.url);
24
+
25
+ function tempDbPath(): string {
26
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-migrate-guards-'));
27
+ return path.join(dir, 'gsd.db');
28
+ }
29
+
30
+ function cleanup(dbPath: string): void {
31
+ closeDatabase();
32
+ fs.rmSync(path.dirname(dbPath), { recursive: true, force: true });
33
+ }
34
+
35
+ interface RawDb {
36
+ exec(sql: string): void;
37
+ prepare(sql: string): { get(...args: unknown[]): Record<string, unknown> | undefined; all(...args: unknown[]): Array<Record<string, unknown>> };
38
+ close(): void;
39
+ }
40
+
41
+ function openRawSqliteForTest(dbPath: string): RawDb {
42
+ try {
43
+ const mod = _require('node:sqlite') as { DatabaseSync: new (path: string) => RawDb };
44
+ return new mod.DatabaseSync(dbPath);
45
+ } catch {
46
+ type SqliteCtor = new (path: string) => RawDb;
47
+ const mod = _require('better-sqlite3') as SqliteCtor | { default: SqliteCtor };
48
+ const DatabaseCtor: SqliteCtor = typeof mod === 'function' ? mod : mod.default;
49
+ return new DatabaseCtor(dbPath);
50
+ }
51
+ }
52
+
53
+ function rawColumnNames(raw: RawDb, table: string): string[] {
54
+ return raw.prepare(`PRAGMA table_info(${table})`).all().map((r) => r['name'] as string);
55
+ }
56
+
57
+ function rawHasTable(raw: RawDb, table: string): boolean {
58
+ const row = raw.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?").get(table);
59
+ return Boolean(row);
60
+ }
61
+
62
+ function rawMaxVersion(raw: RawDb): number | null {
63
+ const row = raw.prepare('SELECT MAX(version) as v FROM schema_version').get();
64
+ return (row?.['v'] as number | null) ?? null;
65
+ }
66
+
67
+ describe('db-engine migrate guards', () => {
68
+ test('getCurrentSchemaVersion returns 0 on an empty schema_version table', () => {
69
+ const sqlite = _require('node:sqlite') as { DatabaseSync: new (path: string) => unknown };
70
+ const adapter = createDbAdapter(new sqlite.DatabaseSync(':memory:'));
71
+ try {
72
+ adapter.exec('CREATE TABLE schema_version (version INTEGER NOT NULL, applied_at TEXT NOT NULL)');
73
+ assert.equal(getCurrentSchemaVersion(adapter), 0);
74
+ } finally {
75
+ adapter.close();
76
+ }
77
+ });
78
+
79
+ test('refuses to open a DB whose schema is newer than this binary', () => {
80
+ const dbPath = tempDbPath();
81
+ try {
82
+ assert.ok(openDatabase(dbPath), 'fresh open should succeed');
83
+ closeDatabase();
84
+
85
+ const raw = openRawSqliteForTest(dbPath);
86
+ raw.exec(
87
+ `INSERT INTO schema_version (version, applied_at) VALUES (${SCHEMA_VERSION + 1}, '2026-01-01T00:00:00Z')`,
88
+ );
89
+ raw.close();
90
+
91
+ assert.throws(() => openDatabase(dbPath), /newer than/);
92
+ assert.equal(isDbAvailable(), false, 'no connection may stay open on refusal');
93
+ } finally {
94
+ cleanup(dbPath);
95
+ }
96
+ });
97
+
98
+ test('a mid-migration failure rolls back to the starting schema version', () => {
99
+ const dbPath = tempDbPath();
100
+ try {
101
+ assert.ok(openDatabase(dbPath), 'fresh open should succeed');
102
+ closeDatabase();
103
+
104
+ // Rewind the DB to v(SCHEMA_VERSION-1): stamp the prior version and drop
105
+ // the objects the last migration adds, so the re-run has real work to redo.
106
+ const startVersion = SCHEMA_VERSION - 2;
107
+ const raw = openRawSqliteForTest(dbPath);
108
+ raw.exec('DELETE FROM schema_version');
109
+ raw.exec(`INSERT INTO schema_version (version, applied_at) VALUES (${startVersion}, '2026-01-01T00:00:00Z')`);
110
+ raw.exec('ALTER TABLE slices DROP COLUMN target_repositories');
111
+ raw.exec('ALTER TABLE tasks DROP COLUMN target_repositories');
112
+ raw.close();
113
+
114
+ _setMigrationFaultForTest(true);
115
+ try {
116
+ assert.throws(() => openDatabase(dbPath), /migration fault injected/);
117
+ } finally {
118
+ _setMigrationFaultForTest(false);
119
+ }
120
+ assert.equal(isDbAvailable(), false, 'no connection may stay open on migration failure');
121
+
122
+ const inspect = openRawSqliteForTest(dbPath);
123
+ try {
124
+ assert.equal(rawMaxVersion(inspect), startVersion, 'version must roll back to the starting version');
125
+ assert.ok(
126
+ !rawColumnNames(inspect, 'slices').includes('target_repositories'),
127
+ 'column added by the failed migration must be rolled back',
128
+ );
129
+ } finally {
130
+ inspect.close();
131
+ }
132
+
133
+ // The DB is intact — a clean re-open migrates to the current version.
134
+ assert.ok(openDatabase(dbPath), 're-open without the fault should succeed');
135
+ closeDatabase();
136
+ const after = openRawSqliteForTest(dbPath);
137
+ try {
138
+ assert.equal(rawMaxVersion(after), SCHEMA_VERSION);
139
+ assert.ok(rawColumnNames(after, 'slices').includes('target_repositories'));
140
+ assert.equal(rawHasTable(after, 'rework_briefs'), true);
141
+ assert.equal(rawHasTable(after, 'rework_brief_findings'), true);
142
+ } finally {
143
+ after.close();
144
+ }
145
+ } finally {
146
+ cleanup(dbPath);
147
+ }
148
+ });
149
+
150
+ test('a DB with data but no version rows migrates from v1 instead of being stamped current', () => {
151
+ const dbPath = tempDbPath();
152
+ try {
153
+ assert.ok(openDatabase(dbPath), 'fresh open should succeed');
154
+ closeDatabase();
155
+
156
+ // Simulate a legacy DB: user data present, version table empty, and a
157
+ // migration-added column missing so we can observe the chain actually run.
158
+ const raw = openRawSqliteForTest(dbPath);
159
+ raw.exec("INSERT INTO milestones (id, title) VALUES ('M001', 'Legacy milestone')");
160
+ raw.exec('DELETE FROM schema_version');
161
+ raw.exec('ALTER TABLE milestones DROP COLUMN vision');
162
+ raw.close();
163
+
164
+ assert.ok(openDatabase(dbPath), 'legacy DB open should succeed');
165
+ closeDatabase();
166
+
167
+ const inspect = openRawSqliteForTest(dbPath);
168
+ try {
169
+ const versions = inspect.prepare('SELECT version FROM schema_version ORDER BY version').all()
170
+ .map((r) => r['version'] as number);
171
+ assert.equal(versions[0], 1, 'baseline v1 must be recorded, not a fresh-install stamp');
172
+ assert.equal(versions[versions.length - 1], SCHEMA_VERSION, 'migration chain must reach the current version');
173
+ assert.ok(
174
+ rawColumnNames(inspect, 'milestones').includes('vision'),
175
+ 'migration-added column must be restored by the chain',
176
+ );
177
+ const row = inspect.prepare('SELECT count(*) as cnt FROM milestones').get();
178
+ assert.equal(row?.['cnt'], 1, 'existing data must survive');
179
+ } finally {
180
+ inspect.close();
181
+ }
182
+ } finally {
183
+ cleanup(dbPath);
184
+ }
185
+ });
186
+ });
@@ -0,0 +1,62 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Verifies GSD_ADVERTISE_TOOL_ALIASES gates alias registration on the native tool path (plan 035).
3
+
4
+ import { test } from 'node:test';
5
+ import assert from 'node:assert/strict';
6
+ import { registerDbTools } from '../bootstrap/db-tools.ts';
7
+ import { WORKFLOW_TOOL_ALIAS_NAMES, WORKFLOW_TOOL_CONTRACTS } from '../workflow-tool-surface.ts';
8
+
9
+ function makeMockPi() {
10
+ const tools: any[] = [];
11
+ return {
12
+ registerTool: (tool: any) => tools.push(tool),
13
+ tools,
14
+ } as any;
15
+ }
16
+
17
+ function withEnv(name: string, value: string | undefined, fn: () => void): void {
18
+ const previous = process.env[name];
19
+ if (value === undefined) delete process.env[name];
20
+ else process.env[name] = value;
21
+ try {
22
+ fn();
23
+ } finally {
24
+ if (previous === undefined) delete process.env[name];
25
+ else process.env[name] = previous;
26
+ }
27
+ }
28
+
29
+ test('default: only canonical names are registered, no aliases', () => {
30
+ withEnv('GSD_ADVERTISE_TOOL_ALIASES', undefined, () => {
31
+ const pi = makeMockPi();
32
+ registerDbTools(pi);
33
+ const names = new Set(pi.tools.map((tool: any) => tool.name));
34
+
35
+ for (const alias of WORKFLOW_TOOL_ALIAS_NAMES) {
36
+ assert.ok(!names.has(alias), `alias "${alias}" should not be registered by default`);
37
+ }
38
+ const registeredCanonical = WORKFLOW_TOOL_CONTRACTS
39
+ .map((tool) => tool.canonicalName)
40
+ .filter((name) => names.has(name));
41
+ assert.ok(registeredCanonical.length > 0, 'canonical tools should still be registered');
42
+ });
43
+ });
44
+
45
+ test('GSD_ADVERTISE_TOOL_ALIASES=1: aliases are registered with the "(alias for ...)" description suffix', () => {
46
+ withEnv('GSD_ADVERTISE_TOOL_ALIASES', '1', () => {
47
+ const pi = makeMockPi();
48
+ registerDbTools(pi);
49
+ const toolByName = new Map<string, any>(pi.tools.map((tool: any) => [tool.name, tool]));
50
+
51
+ const registeredAliases = WORKFLOW_TOOL_ALIAS_NAMES.filter((alias) => toolByName.has(alias));
52
+ assert.ok(registeredAliases.length > 0, 'at least one alias should be registered when opted in');
53
+
54
+ for (const alias of registeredAliases) {
55
+ const aliasTool = toolByName.get(alias);
56
+ assert.ok(
57
+ aliasTool.description.includes('(alias for '),
58
+ `alias "${alias}" description should include "(alias for ...)"`,
59
+ );
60
+ }
61
+ });
62
+ });
@@ -7,6 +7,8 @@ import { join } from 'node:path';
7
7
  import { tmpdir } from 'node:os';
8
8
 
9
9
  import { deriveState, invalidateStateCache, _deriveStateImpl, deriveStateFromDb, isGhostMilestone } from '../state.ts';
10
+ import { readCachedDeriveState, writeCachedDeriveState } from '../state/derive/cache.ts';
11
+ import type { GSDState } from '../types.ts';
10
12
  import {
11
13
  openDatabase,
12
14
  closeDatabase,
@@ -582,6 +584,33 @@ describe('derive-state-db', async () => {
582
584
  }
583
585
  });
584
586
 
587
+ // ─── Test 7b: lock flip must not serve a basePath-keyed cache hit ─────
588
+ // The derive cache is keyed on basePath only, but deriveStateFromDb filters
589
+ // by GSD_MILESTONE_LOCK. auto.ts's capture/restoreMilestoneLockEnv call
590
+ // invalidateStateCache() on every flip; this guards that the cache is
591
+ // genuinely lock-blind (so that invalidate call is load-bearing, not
592
+ // redundant) and that invalidation defeats the stale read.
593
+ test('derive-state-db: a milestone-lock flip needs explicit cache invalidation', () => {
594
+ const prevLock = process.env.GSD_MILESTONE_LOCK;
595
+ try {
596
+ const base = '/tmp/gsd-lock-flip-fixture';
597
+ const stateA = { phase: 'planning' } as unknown as GSDState;
598
+ process.env.GSD_MILESTONE_LOCK = 'M001';
599
+ writeCachedDeriveState(base, stateA);
600
+
601
+ // Lock flips but basePath is unchanged → the cache still hits.
602
+ process.env.GSD_MILESTONE_LOCK = 'M002';
603
+ assert.strictEqual(readCachedDeriveState(base), stateA, 'basePath-only cache ignores the lock flip');
604
+
605
+ // What the lock-env functions do on flip:
606
+ invalidateStateCache();
607
+ assert.strictEqual(readCachedDeriveState(base), null, 'invalidation defeats the stale-lock read');
608
+ } finally {
609
+ if (prevLock === undefined) delete process.env.GSD_MILESTONE_LOCK;
610
+ else process.env.GSD_MILESTONE_LOCK = prevLock;
611
+ }
612
+ });
613
+
585
614
  // ═════════════════════════════════════════════════════════════════════════
586
615
  // New: deriveStateFromDb() cross-validation tests
587
616
  // ═════════════════════════════════════════════════════════════════════════
@@ -18,6 +18,7 @@ import test from "node:test";
18
18
  import assert from "node:assert/strict";
19
19
 
20
20
  import { registerHooks } from "../bootstrap/register-hooks.ts";
21
+ import { autoSession } from "../auto-runtime-state.ts";
21
22
  import { classifyCommand } from "../safety/destructive-guard.ts";
22
23
  import {
23
24
  DESTRUCTIVE_CONFIRM_GATE_MARKER,
@@ -232,6 +233,38 @@ test("integration: real hooks block a force push, then allow it once after confi
232
233
  assert.equal(thirdAttempt?.block, true, "second run of the same command re-blocks (one-shot)");
233
234
  });
234
235
 
236
+ test("integration: auto-mode destructive block does not pause before confirmation can be asked", async (t) => {
237
+ const dir = "/tmp/gsd-destructive-confirm-int-auto-defer";
238
+ const notifications: string[] = [];
239
+ const ctx = {
240
+ cwd: dir,
241
+ isIdle: () => true,
242
+ sessionManager: { getSessionFile: () => null },
243
+ ui: { notify: (message: string) => notifications.push(message) },
244
+ } as any;
245
+ resetDestructiveConfirmation(dir);
246
+ autoSession.reset();
247
+ autoSession.active = true;
248
+ autoSession.basePath = dir;
249
+ t.after(() => {
250
+ resetDestructiveConfirmation(dir);
251
+ autoSession.reset();
252
+ });
253
+
254
+ const { handlers, pi } = makeHookHarness();
255
+ registerHooks(pi, []);
256
+
257
+ const block = await runBashGuard(handlers, FORCE_PUSH, ctx);
258
+
259
+ assert.equal(block?.block, true, "real guard blocks the first destructive attempt");
260
+ assert.equal(autoSession.active, true, "auto-mode must remain active so ask_user_questions can run");
261
+ assert.deepEqual(
262
+ notifications.filter((message) => message.includes("Destructive-command confirmation")),
263
+ [],
264
+ "destructive confirmation pause must not fire from the bash tool_call hook",
265
+ );
266
+ });
267
+
235
268
  test("integration: declining the confirm gate leaves the command blocked", async (t) => {
236
269
  const dir = "/tmp/gsd-destructive-confirm-int-decline";
237
270
  const ctx = { cwd: dir, ui: { notify: () => undefined } } as any;
@@ -29,6 +29,7 @@ test("destructive guard still detects direct and wrapper-prefixed recursive dele
29
29
  "find . -exec rm -rf {} \\;",
30
30
  "cat doomed.txt | xargs rm -rf /tmp/x",
31
31
  'rm -rf "/tmp/my build"',
32
+ "rm --recursive build",
32
33
  ];
33
34
 
34
35
  for (const command of destructiveCommands) {
@@ -39,6 +40,19 @@ test("destructive guard still detects direct and wrapper-prefixed recursive dele
39
40
  }
40
41
  });
41
42
 
43
+ test("destructive guard does not classify force-only rm as recursive delete", () => {
44
+ const nonRecursiveCommands = [
45
+ "rm -f single-file.md",
46
+ "rm -fv single-file.md",
47
+ "rm single-file.md -f",
48
+ "rm --force single-file.md",
49
+ ];
50
+
51
+ for (const command of nonRecursiveCommands) {
52
+ assert.deepEqual(classifyCommand(command), { destructive: false, labels: [] }, command);
53
+ }
54
+ });
55
+
42
56
  test("destructive guard treats quoted interpreter payloads as literals", () => {
43
57
  assert.deepEqual(classifyCommand('bash -c "rm -rf /"'), { destructive: false, labels: [] });
44
58
  });
@@ -80,6 +80,43 @@ function makeDiscussCtx(notifications: Array<{ message: string; level?: string }
80
80
  };
81
81
  }
82
82
 
83
+ async function runDiscussTargetFixture(
84
+ target: string,
85
+ milestones: Array<{ id: string; title?: string; status?: string }>,
86
+ writeArtifacts?: (base: string) => void,
87
+ ) {
88
+ const base = mkdtempSync(join(tmpdir(), "gsd-discuss-target-"));
89
+ const notifications: Array<{ message: string; level?: string }> = [];
90
+ const harness = makeDiscussPi();
91
+ try {
92
+ mkdirSync(join(base, ".gsd", "milestones"), { recursive: true });
93
+ writeArtifacts?.(base);
94
+ const dbPath = join(base, ".gsd", "gsd.db");
95
+ assert.equal(openDatabase(dbPath), true);
96
+ for (const milestone of milestones) {
97
+ insertMilestone(milestone);
98
+ }
99
+
100
+ await showDiscuss(
101
+ makeDiscussCtx(notifications) as any,
102
+ harness.pi as any,
103
+ base,
104
+ { target },
105
+ );
106
+
107
+ return {
108
+ notifications: [...notifications],
109
+ sent: [...harness.sent],
110
+ };
111
+ } finally {
112
+ harness.restore();
113
+ if (isDbAvailable()) closeDatabase();
114
+ invalidateStateCache();
115
+ clearGuidedUnitContext();
116
+ rmSync(base, { recursive: true, force: true });
117
+ }
118
+ }
119
+
83
120
  describe("discuss target normalization", () => {
84
121
  test("canonicalizes milestone and slice casing", () => {
85
122
  assert.equal(normalizeDiscussTarget("m014"), "M014");
@@ -90,6 +127,92 @@ describe("discuss target normalization", () => {
90
127
  });
91
128
  });
92
129
 
130
+ describe("showDiscuss targeted milestone guardrails (#1320)", () => {
131
+ test("missing, complete, and parked milestone targets get actionable messages", async () => {
132
+ const cases = [
133
+ {
134
+ target: "M006",
135
+ milestones: [{ id: "M005", title: "Current", status: "active" }],
136
+ level: "warning",
137
+ message: /Milestone M006 was not found in the roadmap\. Use \/gsd new-milestone to add it, or \/gsd status to see available milestones\./,
138
+ },
139
+ {
140
+ target: "M006/S01",
141
+ milestones: [{ id: "M005", title: "Current", status: "active" }],
142
+ level: "warning",
143
+ message: /Milestone M006 was not found in the roadmap\. Use \/gsd new-milestone to add it, or \/gsd status to see available milestones\./,
144
+ },
145
+ {
146
+ target: "M006",
147
+ milestones: [{ id: "M006", title: "Done", status: "complete" }],
148
+ level: "info",
149
+ message: /Milestone M006 is already complete\./,
150
+ },
151
+ {
152
+ target: "M006/S01",
153
+ milestones: [{ id: "M006", title: "Done", status: "complete" }],
154
+ level: "info",
155
+ message: /Milestone M006 is already complete\./,
156
+ },
157
+ {
158
+ target: "M006",
159
+ milestones: [{ id: "M006", title: "Deferred", status: "parked" }],
160
+ level: "warning",
161
+ message: /Milestone M006 is parked\. Run \/gsd unpark M006 to reactivate\./,
162
+ },
163
+ {
164
+ target: "M006/S01",
165
+ milestones: [{ id: "M006", title: "Deferred", status: "parked" }],
166
+ level: "warning",
167
+ message: /Milestone M006 is parked\. Run \/gsd unpark M006 to reactivate\./,
168
+ },
169
+ ];
170
+
171
+ for (const testCase of cases) {
172
+ const result = await runDiscussTargetFixture(testCase.target, testCase.milestones);
173
+ assert.equal(result.sent.length, 0, `${testCase.target} must not dispatch`);
174
+ assert.equal(result.notifications.length, 1, `${testCase.target} must emit one notification`);
175
+ assert.equal(result.notifications[0]?.level, testCase.level);
176
+ assert.match(result.notifications[0]?.message ?? "", testCase.message);
177
+ assert.doesNotMatch(result.notifications[0]?.message ?? "", /not discussable/i);
178
+ }
179
+ });
180
+
181
+ test("bare milestone targets match unique-suffix milestone IDs", async () => {
182
+ const result = await runDiscussTargetFixture("M006", [
183
+ { id: "M006-abc123", title: "Unique milestone", status: "active" },
184
+ ]);
185
+
186
+ assert.equal(result.notifications.length, 0);
187
+ assert.equal(result.sent.length, 1, "bare ID must dispatch the suffixed milestone");
188
+ assert.match(String(result.sent[0]?.content), /M006-abc123|Unique milestone|guided-discuss-milestone/i);
189
+ });
190
+
191
+ test("bare slice targets match unique-suffix milestone IDs", async () => {
192
+ const result = await runDiscussTargetFixture(
193
+ "M006/S01",
194
+ [{ id: "M006-abc123", title: "Unique milestone", status: "active" }],
195
+ (base) => {
196
+ mkdirSync(join(base, ".gsd", "milestones", "M006-abc123"), { recursive: true });
197
+ writeFileSync(
198
+ join(base, ".gsd", "milestones", "M006-abc123", "M006-abc123-ROADMAP.md"),
199
+ `# M006-abc123 Roadmap
200
+
201
+ ## Slices
202
+ - [ ] **S01: Unique slice** \`risk:medium\` \`depends:[]\`
203
+ > After this: the suffixed milestone slice can be discussed
204
+ `,
205
+ "utf-8",
206
+ );
207
+ },
208
+ );
209
+
210
+ assert.equal(result.notifications.length, 0);
211
+ assert.equal(result.sent.length, 1, "bare ID slice target must dispatch through the suffixed milestone");
212
+ assert.match(String(result.sent[0]?.content), /M006-abc123|S01|Unique slice|guided-discuss-slice/i);
213
+ });
214
+ });
215
+
93
216
  describe("loadDiscussNormSlices roadmap fallback (#2892)", () => {
94
217
  test("falls back to ROADMAP when DB has no slice rows", async () => {
95
218
  const base = mkdtempSync(join(tmpdir(), "gsd-discuss-slices-"));
@@ -330,6 +330,56 @@ test("dispatch: session milestone mismatch stops before missing-task-plan recove
330
330
  assert.match(result.reason, /context mid "M001" does not match session\.currentMilestoneId "M002"/);
331
331
  });
332
332
 
333
+ test("dispatch: bare context milestone maps to suffixed active session milestone", async (t) => {
334
+ const tmp = mkdtempSync(join(tmpdir(), "gsd-suffixed-session-milestone-"));
335
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
336
+
337
+ const worktreeRoot = join(tmp, ".gsd", "worktrees", "M003-vaz73w");
338
+ scaffoldLegacyMilestoneContext(worktreeRoot, "M003-vaz73w");
339
+ scaffoldLegacySlicePlan(worktreeRoot, "M003-vaz73w", "S01");
340
+ scaffoldLegacyTaskPlan(worktreeRoot, "M003-vaz73w", "S01", "T02");
341
+
342
+ const ctx = makeContextFor(tmp, "M003", "S01", "T02", {
343
+ basePath: worktreeRoot,
344
+ originalBasePath: tmp,
345
+ currentMilestoneId: "M003-vaz73w",
346
+ });
347
+ const result = await resolveDispatch(ctx);
348
+
349
+ assert.equal(result.action, "dispatch");
350
+ assert.ok(result.action === "dispatch" && result.unitType === "execute-task",
351
+ `unitType should be execute-task, got: ${result.action === "dispatch" ? result.unitType : "(stop)"}`);
352
+ assert.ok(result.action === "dispatch" && result.unitId === "M003-vaz73w/S01/T02",
353
+ `unitId should use suffixed milestone, got: ${result.action === "dispatch" ? result.unitId : "(stop)"}`);
354
+ });
355
+
356
+ test("dispatch: suffixed context milestone keeps suffix when scoped alias is bare", async (t) => {
357
+ // Inverse of the case above: dispatch context carries the suffixed id but the
358
+ // scoped alias (session.currentMilestoneId) is bare. resolveEffectiveDispatchMilestoneId
359
+ // must keep the suffixed id so slice/task artifacts resolve under the suffixed
360
+ // worktree layout (milestones/M003-xxxxxx/) rather than the bare milestones/M003/.
361
+ const tmp = mkdtempSync(join(tmpdir(), "gsd-suffixed-context-bare-scope-"));
362
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
363
+
364
+ const worktreeRoot = join(tmp, ".gsd", "worktrees", "M003-vaz73w");
365
+ scaffoldLegacyMilestoneContext(worktreeRoot, "M003-vaz73w");
366
+ scaffoldLegacySlicePlan(worktreeRoot, "M003-vaz73w", "S01");
367
+ scaffoldLegacyTaskPlan(worktreeRoot, "M003-vaz73w", "S01", "T02");
368
+
369
+ const ctx = makeContextFor(tmp, "M003-vaz73w", "S01", "T02", {
370
+ basePath: worktreeRoot,
371
+ originalBasePath: tmp,
372
+ currentMilestoneId: "M003",
373
+ });
374
+ const result = await resolveDispatch(ctx);
375
+
376
+ assert.equal(result.action, "dispatch");
377
+ assert.ok(result.action === "dispatch" && result.unitType === "execute-task",
378
+ `unitType should be execute-task, got: ${result.action === "dispatch" ? result.unitType : "(stop)"}`);
379
+ assert.ok(result.action === "dispatch" && result.unitId === "M003-vaz73w/S01/T02",
380
+ `unitId should keep suffixed milestone, got: ${result.action === "dispatch" ? result.unitId : "(stop)"}`);
381
+ });
382
+
333
383
  test("dispatch: worktree path mismatch stops before planning a different milestone", async (t) => {
334
384
  const tmp = mkdtempSync(join(tmpdir(), "gsd-worktree-path-milestone-mismatch-"));
335
385
  t.after(() => rmSync(tmp, { recursive: true, force: true }));
@@ -146,6 +146,55 @@ test("dispatch-rule-coverage: pre-planning, no CONTEXT → discuss-milestone", a
146
146
  );
147
147
  });
148
148
 
149
+ test("dispatch-rule-coverage: pre-planning worktree sees project-root CONTEXT", async (t) => {
150
+ const tmp = mkdtempSync(join(tmpdir(), "gsd-disp-cov-wt-context-"));
151
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
152
+
153
+ const projectPhaseDir = join(tmp, ".gsd", "phases", "01-foundation");
154
+ mkdirSync(projectPhaseDir, { recursive: true });
155
+ writeFileSync(join(projectPhaseDir, "01-CONTEXT.md"), "# Context\n");
156
+
157
+ const worktree = join(tmp, ".gsd", "worktrees", "M001");
158
+ mkdirSync(join(worktree, ".gsd", "milestones", "M001"), { recursive: true });
159
+ writeFileSync(
160
+ join(worktree, ".gsd", "milestones", "M001", "M001-META.json"),
161
+ '{"branch":"milestone/M001"}',
162
+ );
163
+
164
+ const rule = DISPATCH_RULES.find(
165
+ (candidate) => candidate.name === "pre-planning (no context) → discuss-milestone",
166
+ );
167
+ assert.ok(rule, "pre-planning missing-context rule should exist");
168
+
169
+ const result = await rule.match(makeCtx(worktree, makeState({ phase: "pre-planning" })));
170
+ assert.equal(result, null, "project-root CONTEXT must prevent a second discuss-milestone dispatch");
171
+ });
172
+
173
+ test("dispatch-rule-coverage: pre-planning worktree sees worktree-only CONTEXT", async (t) => {
174
+ // Mirror image of the project-root test: discuss-milestone mirrors CONTEXT into
175
+ // the worktree's own .gsd, and it may not yet exist at the project root (the
176
+ // worktree→root sync deliberately does not flow markdown projections back).
177
+ // A project-root-only check would miss it and re-fire discuss-milestone.
178
+ const tmp = mkdtempSync(join(tmpdir(), "gsd-disp-cov-wt-only-context-"));
179
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
180
+
181
+ // No CONTEXT at the project root — only the milestone dir exists there.
182
+ mkdirSync(join(tmp, ".gsd", "phases"), { recursive: true });
183
+
184
+ const worktree = join(tmp, ".gsd", "worktrees", "M001");
185
+ const worktreePhaseDir = join(worktree, ".gsd", "phases", "01-foundation");
186
+ mkdirSync(worktreePhaseDir, { recursive: true });
187
+ writeFileSync(join(worktreePhaseDir, "01-CONTEXT.md"), "# WT Context\n");
188
+
189
+ const rule = DISPATCH_RULES.find(
190
+ (candidate) => candidate.name === "pre-planning (no context) → discuss-milestone",
191
+ );
192
+ assert.ok(rule, "pre-planning missing-context rule should exist");
193
+
194
+ const result = await rule.match(makeCtx(worktree, makeState({ phase: "pre-planning" })));
195
+ assert.equal(result, null, "worktree-only CONTEXT must prevent a second discuss-milestone dispatch");
196
+ });
197
+
149
198
  test("dispatch-rule-coverage: pre-planning, has CONTEXT, no RESEARCH → research-milestone", async (t) => {
150
199
  const tmp = mkdtempSync(join(tmpdir(), "gsd-disp-cov-res-"));
151
200
  t.after(() => rmSync(tmp, { recursive: true, force: true }));