gsd-pi 2.71.0 → 2.72.0-dev.8f83716

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 (465) hide show
  1. package/README.md +57 -17
  2. package/dist/cli.js +29 -3
  3. package/dist/headless-events.d.ts +2 -0
  4. package/dist/headless-events.js +7 -0
  5. package/dist/headless.js +16 -3
  6. package/dist/mcp-server.js +40 -17
  7. package/dist/provider-migrations.d.ts +10 -0
  8. package/dist/provider-migrations.js +12 -0
  9. package/dist/resource-loader.js +139 -13
  10. package/dist/resources/GSD-WORKFLOW.md +1 -1
  11. package/dist/resources/agents/debugger.md +58 -0
  12. package/dist/resources/agents/doc-writer.md +43 -0
  13. package/dist/resources/agents/git-ops.md +56 -0
  14. package/dist/resources/agents/javascript-pro.md +46 -271
  15. package/dist/resources/agents/planner.md +55 -0
  16. package/dist/resources/agents/refactorer.md +47 -0
  17. package/dist/resources/agents/reviewer.md +48 -0
  18. package/dist/resources/agents/security.md +59 -0
  19. package/dist/resources/agents/tester.md +50 -0
  20. package/dist/resources/agents/typescript-pro.md +41 -235
  21. package/dist/resources/extensions/claude-code-cli/partial-builder.js +40 -12
  22. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +133 -14
  23. package/dist/resources/extensions/gsd/auto/infra-errors.js +34 -0
  24. package/dist/resources/extensions/gsd/auto/loop.js +32 -1
  25. package/dist/resources/extensions/gsd/auto/phases.js +5 -1
  26. package/dist/resources/extensions/gsd/auto/session.js +11 -0
  27. package/dist/resources/extensions/gsd/auto-dashboard.js +22 -16
  28. package/dist/resources/extensions/gsd/auto-model-selection.js +10 -2
  29. package/dist/resources/extensions/gsd/auto-prompts.js +88 -33
  30. package/dist/resources/extensions/gsd/auto-start.js +34 -7
  31. package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
  32. package/dist/resources/extensions/gsd/auto-worktree.js +1 -1
  33. package/dist/resources/extensions/gsd/auto.js +56 -0
  34. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -3
  35. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +2 -0
  36. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +63 -51
  37. package/dist/resources/extensions/gsd/bootstrap/system-context.js +6 -0
  38. package/dist/resources/extensions/gsd/commands/context.js +15 -6
  39. package/dist/resources/extensions/gsd/commands/dispatcher.js +12 -2
  40. package/dist/resources/extensions/gsd/commands/handlers/auto.js +10 -33
  41. package/dist/resources/extensions/gsd/commands/handlers/core.js +56 -11
  42. package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +15 -6
  43. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +4 -10
  44. package/dist/resources/extensions/gsd/dashboard-overlay.js +8 -3
  45. package/dist/resources/extensions/gsd/dispatch-guard.js +18 -1
  46. package/dist/resources/extensions/gsd/doctor-providers.js +23 -0
  47. package/dist/resources/extensions/gsd/error-classifier.js +5 -2
  48. package/dist/resources/extensions/gsd/forensics.js +19 -6
  49. package/dist/resources/extensions/gsd/gate-registry.js +208 -0
  50. package/dist/resources/extensions/gsd/gsd-db.js +41 -0
  51. package/dist/resources/extensions/gsd/guided-flow.js +5 -10
  52. package/dist/resources/extensions/gsd/metrics.js +1 -0
  53. package/dist/resources/extensions/gsd/milestone-actions.js +10 -4
  54. package/dist/resources/extensions/gsd/milestone-validation-gates.js +11 -12
  55. package/dist/resources/extensions/gsd/notification-overlay.js +42 -13
  56. package/dist/resources/extensions/gsd/notification-store.js +56 -5
  57. package/dist/resources/extensions/gsd/notification-widget.js +5 -13
  58. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +8 -3
  59. package/dist/resources/extensions/gsd/pre-execution-checks.js +35 -2
  60. package/dist/resources/extensions/gsd/prompt-validation.js +126 -0
  61. package/dist/resources/extensions/gsd/prompts/complete-slice.md +5 -3
  62. package/dist/resources/extensions/gsd/prompts/discuss.md +2 -0
  63. package/dist/resources/extensions/gsd/prompts/execute-task.md +22 -19
  64. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  65. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
  66. package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  67. package/dist/resources/extensions/gsd/prompts/queue.md +3 -2
  68. package/dist/resources/extensions/gsd/prompts/system.md +1 -0
  69. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
  70. package/dist/resources/extensions/gsd/session-model-override.js +25 -0
  71. package/dist/resources/extensions/gsd/shortcut-defs.js +40 -0
  72. package/dist/resources/extensions/gsd/state.js +9 -2
  73. package/dist/resources/extensions/gsd/tools/complete-slice.js +52 -1
  74. package/dist/resources/extensions/gsd/tools/complete-task.js +51 -1
  75. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +4 -1
  76. package/dist/resources/extensions/ollama/index.js +13 -5
  77. package/dist/resources/extensions/shared/gsd-phase-state.js +35 -0
  78. package/dist/resources/extensions/subagent/agents.js +8 -0
  79. package/dist/resources/extensions/subagent/index.js +17 -0
  80. package/dist/resources/skills/create-skill/SKILL.md +2 -0
  81. package/dist/startup-model-validation.d.ts +0 -1
  82. package/dist/startup-model-validation.js +6 -2
  83. package/dist/web/standalone/.next/BUILD_ID +1 -1
  84. package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
  85. package/dist/web/standalone/.next/build-manifest.json +3 -3
  86. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  87. package/dist/web/standalone/.next/required-server-files.json +3 -3
  88. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  89. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  99. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  115. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  127. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  147. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  157. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  163. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  179. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
  183. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/index.html +1 -1
  193. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  194. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  195. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  196. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  197. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  198. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  199. package/dist/web/standalone/.next/server/app/page.js +2 -2
  200. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
  202. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  203. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  204. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  205. package/dist/web/standalone/.next/server/middleware.js +2 -2
  206. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  207. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  208. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  209. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  210. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  211. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  212. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  213. package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +1 -0
  214. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  215. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  216. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  217. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  218. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  219. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  220. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  221. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  222. package/dist/web/standalone/server.js +1 -1
  223. package/package.json +1 -1
  224. package/packages/mcp-server/dist/server.d.ts +12 -1
  225. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  226. package/packages/mcp-server/dist/server.js +90 -42
  227. package/packages/mcp-server/dist/server.js.map +1 -1
  228. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  229. package/packages/mcp-server/dist/workflow-tools.js +22 -12
  230. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  231. package/packages/mcp-server/src/server.ts +110 -38
  232. package/packages/mcp-server/src/workflow-tools.test.ts +110 -0
  233. package/packages/mcp-server/src/workflow-tools.ts +32 -12
  234. package/packages/pi-ai/dist/providers/amazon-bedrock.js +11 -2
  235. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  236. package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts +2 -0
  237. package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts.map +1 -0
  238. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +20 -0
  239. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -0
  240. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts +4 -1
  241. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  242. package/packages/pi-ai/dist/providers/anthropic-shared.js +8 -3
  243. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  244. package/packages/pi-ai/dist/providers/anthropic-shared.test.js +44 -1
  245. package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -1
  246. package/packages/pi-ai/dist/providers/anthropic.d.ts +2 -1
  247. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  248. package/packages/pi-ai/dist/providers/anthropic.js +7 -4
  249. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  250. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  251. package/packages/pi-ai/dist/providers/openai-completions.js +11 -0
  252. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  253. package/packages/pi-ai/src/providers/amazon-bedrock.ts +13 -1
  254. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +32 -0
  255. package/packages/pi-ai/src/providers/anthropic-shared.test.ts +55 -1
  256. package/packages/pi-ai/src/providers/anthropic-shared.ts +14 -3
  257. package/packages/pi-ai/src/providers/anthropic.ts +8 -4
  258. package/packages/pi-ai/src/providers/openai-completions.ts +14 -0
  259. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts +2 -0
  260. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts.map +1 -0
  261. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js +61 -0
  262. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js.map +1 -0
  263. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  264. package/packages/pi-coding-agent/dist/core/agent-session.js +2 -1
  265. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  266. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +10 -0
  267. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/auth-storage.js +27 -0
  269. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  270. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +85 -0
  271. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts +2 -0
  273. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts.map +1 -0
  274. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js +64 -0
  275. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js.map +1 -0
  276. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  277. package/packages/pi-coding-agent/dist/core/model-resolver.js +22 -18
  278. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts +8 -0
  280. package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts.map +1 -0
  281. package/packages/pi-coding-agent/dist/core/model-resolver.test.js +75 -0
  282. package/packages/pi-coding-agent/dist/core/model-resolver.test.js.map +1 -0
  283. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +5 -0
  284. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/retry-handler.js +55 -1
  286. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +57 -0
  288. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/sdk.d.ts +11 -0
  290. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  291. package/packages/pi-coding-agent/dist/core/sdk.js +38 -5
  292. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/sdk.test.d.ts +2 -0
  294. package/packages/pi-coding-agent/dist/core/sdk.test.d.ts.map +1 -0
  295. package/packages/pi-coding-agent/dist/core/sdk.test.js +71 -0
  296. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -0
  297. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  298. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  299. package/packages/pi-coding-agent/dist/index.js +1 -1
  300. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  301. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts +2 -0
  302. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts.map +1 -0
  303. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js +13 -0
  304. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js.map +1 -0
  305. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -0
  306. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  307. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +4 -0
  308. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  309. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +24 -2
  310. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  311. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  312. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +9 -2
  313. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  314. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +4 -0
  315. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  316. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +130 -12
  317. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  318. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  319. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +7 -2
  320. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  321. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.d.ts.map +1 -1
  322. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js +6 -1
  323. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js.map +1 -1
  324. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  325. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -3
  326. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  327. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +4 -2
  328. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  329. package/packages/pi-coding-agent/package.json +1 -1
  330. package/packages/pi-coding-agent/src/core/agent-session-renderable-tools.test.ts +70 -0
  331. package/packages/pi-coding-agent/src/core/agent-session.ts +2 -1
  332. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +108 -0
  333. package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -0
  334. package/packages/pi-coding-agent/src/core/model-resolver-initial-model-auth.test.ts +78 -0
  335. package/packages/pi-coding-agent/src/core/model-resolver.test.ts +85 -0
  336. package/packages/pi-coding-agent/src/core/model-resolver.ts +22 -18
  337. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +83 -0
  338. package/packages/pi-coding-agent/src/core/retry-handler.ts +60 -1
  339. package/packages/pi-coding-agent/src/core/sdk.test.ts +89 -0
  340. package/packages/pi-coding-agent/src/core/sdk.ts +45 -9
  341. package/packages/pi-coding-agent/src/index.ts +1 -0
  342. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/login-dialog.test.ts +24 -0
  343. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +72 -0
  344. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +30 -2
  345. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +15 -6
  346. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +131 -12
  347. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +7 -2
  348. package/packages/pi-coding-agent/src/modes/interactive/controllers/model-controller.ts +6 -1
  349. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +4 -3
  350. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +4 -2
  351. package/pkg/package.json +1 -1
  352. package/src/resources/GSD-WORKFLOW.md +1 -1
  353. package/src/resources/agents/debugger.md +58 -0
  354. package/src/resources/agents/doc-writer.md +43 -0
  355. package/src/resources/agents/git-ops.md +56 -0
  356. package/src/resources/agents/javascript-pro.md +46 -271
  357. package/src/resources/agents/planner.md +55 -0
  358. package/src/resources/agents/refactorer.md +47 -0
  359. package/src/resources/agents/reviewer.md +48 -0
  360. package/src/resources/agents/security.md +59 -0
  361. package/src/resources/agents/tester.md +50 -0
  362. package/src/resources/agents/typescript-pro.md +41 -235
  363. package/src/resources/extensions/claude-code-cli/partial-builder.ts +45 -12
  364. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +143 -13
  365. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +91 -2
  366. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +281 -6
  367. package/src/resources/extensions/gsd/auto/infra-errors.ts +38 -0
  368. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
  369. package/src/resources/extensions/gsd/auto/loop.ts +45 -1
  370. package/src/resources/extensions/gsd/auto/phases.ts +6 -0
  371. package/src/resources/extensions/gsd/auto/session.ts +11 -0
  372. package/src/resources/extensions/gsd/auto-dashboard.ts +29 -18
  373. package/src/resources/extensions/gsd/auto-model-selection.ts +9 -1
  374. package/src/resources/extensions/gsd/auto-prompts.ts +111 -33
  375. package/src/resources/extensions/gsd/auto-start.ts +41 -7
  376. package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
  377. package/src/resources/extensions/gsd/auto-worktree.ts +1 -1
  378. package/src/resources/extensions/gsd/auto.ts +72 -0
  379. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
  380. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +2 -0
  381. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +79 -60
  382. package/src/resources/extensions/gsd/bootstrap/system-context.ts +7 -0
  383. package/src/resources/extensions/gsd/commands/context.ts +16 -5
  384. package/src/resources/extensions/gsd/commands/dispatcher.ts +14 -2
  385. package/src/resources/extensions/gsd/commands/handlers/auto.ts +10 -36
  386. package/src/resources/extensions/gsd/commands/handlers/core.ts +58 -11
  387. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +17 -7
  388. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +4 -10
  389. package/src/resources/extensions/gsd/dashboard-overlay.ts +10 -3
  390. package/src/resources/extensions/gsd/dispatch-guard.ts +18 -1
  391. package/src/resources/extensions/gsd/doctor-providers.ts +24 -0
  392. package/src/resources/extensions/gsd/error-classifier.ts +5 -2
  393. package/src/resources/extensions/gsd/forensics.ts +23 -7
  394. package/src/resources/extensions/gsd/gate-registry.ts +251 -0
  395. package/src/resources/extensions/gsd/gsd-db.ts +51 -0
  396. package/src/resources/extensions/gsd/guided-flow.ts +5 -10
  397. package/src/resources/extensions/gsd/interrupted-session.ts +1 -0
  398. package/src/resources/extensions/gsd/metrics.ts +12 -1
  399. package/src/resources/extensions/gsd/milestone-actions.ts +10 -3
  400. package/src/resources/extensions/gsd/milestone-validation-gates.ts +11 -13
  401. package/src/resources/extensions/gsd/notification-overlay.ts +47 -14
  402. package/src/resources/extensions/gsd/notification-store.ts +54 -5
  403. package/src/resources/extensions/gsd/notification-widget.ts +5 -14
  404. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -3
  405. package/src/resources/extensions/gsd/pre-execution-checks.ts +39 -2
  406. package/src/resources/extensions/gsd/prompt-validation.ts +157 -0
  407. package/src/resources/extensions/gsd/prompts/complete-slice.md +5 -3
  408. package/src/resources/extensions/gsd/prompts/discuss.md +2 -0
  409. package/src/resources/extensions/gsd/prompts/execute-task.md +22 -19
  410. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  411. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
  412. package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  413. package/src/resources/extensions/gsd/prompts/queue.md +3 -2
  414. package/src/resources/extensions/gsd/prompts/system.md +1 -0
  415. package/src/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
  416. package/src/resources/extensions/gsd/session-model-override.ts +36 -0
  417. package/src/resources/extensions/gsd/shortcut-defs.ts +56 -0
  418. package/src/resources/extensions/gsd/state.ts +13 -2
  419. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +25 -9
  420. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +28 -0
  421. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +39 -0
  422. package/src/resources/extensions/gsd/tests/complete-slice-gate-closure.test.ts +167 -0
  423. package/src/resources/extensions/gsd/tests/complete-slice-prompt-task-summary-layout.test.ts +18 -0
  424. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
  425. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +36 -0
  426. package/src/resources/extensions/gsd/tests/execute-task-prompt-existing-artifact-guard.test.ts +33 -0
  427. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +62 -0
  428. package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +31 -0
  429. package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +27 -0
  430. package/src/resources/extensions/gsd/tests/gate-registry.test.ts +140 -0
  431. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +73 -0
  432. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +180 -0
  433. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +66 -1
  434. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +36 -51
  435. package/src/resources/extensions/gsd/tests/notification-store.test.ts +35 -0
  436. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +26 -0
  437. package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +90 -0
  438. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +1 -0
  439. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +18 -0
  440. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +49 -0
  441. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +19 -0
  442. package/src/resources/extensions/gsd/tests/prompt-system-gate-coverage.test.ts +208 -0
  443. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +16 -0
  444. package/src/resources/extensions/gsd/tests/register-shortcuts.test.ts +63 -5
  445. package/src/resources/extensions/gsd/tests/session-model-override.test.ts +35 -0
  446. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +90 -0
  447. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +7 -0
  448. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +18 -0
  449. package/src/resources/extensions/gsd/tools/complete-slice.ts +63 -0
  450. package/src/resources/extensions/gsd/tools/complete-task.ts +63 -0
  451. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +4 -1
  452. package/src/resources/extensions/gsd/types.ts +26 -0
  453. package/src/resources/extensions/ollama/index.ts +13 -3
  454. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +28 -0
  455. package/src/resources/extensions/shared/gsd-phase-state.ts +42 -0
  456. package/src/resources/extensions/shared/tests/gsd-phase-state.test.ts +48 -0
  457. package/src/resources/extensions/subagent/agents.ts +10 -0
  458. package/src/resources/extensions/subagent/index.ts +18 -0
  459. package/src/resources/extensions/subagent/tests/agents-conflicts.test.ts +33 -0
  460. package/src/resources/skills/create-skill/SKILL.md +2 -0
  461. package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
  462. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  463. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  464. /package/dist/web/standalone/.next/static/{nPky_WQC28aBD77eZsRAB → nCL1Ivw47iAAoKVgerXNi}/_buildManifest.js +0 -0
  465. /package/dist/web/standalone/.next/static/{nPky_WQC28aBD77eZsRAB → nCL1Ivw47iAAoKVgerXNi}/_ssgManifest.js +0 -0
@@ -12,7 +12,7 @@ import { nextMilestoneId } from "../../milestone-ids.js";
12
12
  import { findMilestoneIds } from "../../guided-flow.js";
13
13
  import { projectRoot } from "../context.js";
14
14
  import { createRun, listRuns } from "../../run-manager.js";
15
- import { setActiveEngineId, setActiveRunDir, startAuto, pauseAuto, isAutoActive, getActiveEngineId, } from "../../auto.js";
15
+ import { setActiveEngineId, setActiveRunDir, startAutoDetached, pauseAuto, isAutoActive, getActiveEngineId, } from "../../auto.js";
16
16
  import { validateDefinition } from "../../definition-loader.js";
17
17
  // ─── Custom Workflow Subcommands ─────────────────────────────────────────
18
18
  const WORKFLOW_USAGE = [
@@ -58,7 +58,7 @@ async function handleCustomWorkflow(sub, ctx, pi) {
58
58
  setActiveEngineId("custom");
59
59
  setActiveRunDir(runDir);
60
60
  ctx.ui.notify(`Created workflow run: ${defName}\nRun dir: ${runDir}`, "info");
61
- await startAuto(ctx, pi, base, false);
61
+ startAutoDetached(ctx, pi, base, false);
62
62
  }
63
63
  catch (err) {
64
64
  // Clean up engine state so a failed workflow run doesn't pollute the next /gsd auto
@@ -137,14 +137,8 @@ async function handleCustomWorkflow(sub, ctx, pi) {
137
137
  ctx.ui.notify("No custom workflow to resume. Use /gsd auto for dev workflow.", "warning");
138
138
  return true;
139
139
  }
140
- try {
141
- await startAuto(ctx, pi, projectRoot(), false);
142
- ctx.ui.notify("Custom workflow resumed.", "info");
143
- }
144
- catch (err) {
145
- const msg = err instanceof Error ? err.message : String(err);
146
- ctx.ui.notify(`Failed to resume workflow: ${msg}`, "error");
147
- }
140
+ startAutoDetached(ctx, pi, projectRoot(), false);
141
+ ctx.ui.notify("Custom workflow resumed.", "info");
148
142
  return true;
149
143
  }
150
144
  // Unknown subcommand — show usage
@@ -3,7 +3,8 @@
3
3
  *
4
4
  * Full-screen overlay showing auto-mode progress: milestone/slice/task
5
5
  * breakdown, current unit, completed units, timing, and activity log.
6
- * Toggled with Ctrl+Alt+G (⌃⌥G on macOS) or opened from /gsd status.
6
+ * Toggled with Ctrl+Alt+G (⌃⌥G on macOS), Ctrl+Shift+G fallback,
7
+ * or opened from /gsd status.
7
8
  */
8
9
  import { truncateToWidth, visibleWidth, matchesKey, Key } from "@gsd/pi-tui";
9
10
  import { deriveState } from "./state.js";
@@ -19,6 +20,7 @@ import { formatDuration, padRight, joinColumns, centerLine, fitColumns, STATUS_G
19
20
  import { estimateTimeRemaining } from "./auto-dashboard.js";
20
21
  import { computeProgressScore } from "./progress-score.js";
21
22
  import { runEnvironmentChecks } from "./doctor-environment.js";
23
+ import { formattedShortcutPair } from "./shortcut-defs.js";
22
24
  function unitLabel(type) {
23
25
  switch (type) {
24
26
  case "discuss-milestone":
@@ -174,7 +176,10 @@ export class GSDDashboardOverlay {
174
176
  }
175
177
  }
176
178
  handleInput(data) {
177
- if (matchesKey(data, Key.escape) || matchesKey(data, Key.ctrl("c")) || matchesKey(data, Key.ctrlAlt("g"))) {
179
+ if (matchesKey(data, Key.escape) ||
180
+ matchesKey(data, Key.ctrl("c")) ||
181
+ matchesKey(data, Key.ctrlAlt("g")) ||
182
+ matchesKey(data, Key.ctrlShift("g"))) {
178
183
  this.dispose();
179
184
  this.onClose();
180
185
  return;
@@ -507,7 +512,7 @@ export class GSDDashboardOverlay {
507
512
  }
508
513
  lines.push(blank());
509
514
  lines.push(hr());
510
- lines.push(centered(th.fg("dim", "↑↓ scroll · g/G top/end · esc close")));
515
+ lines.push(centered(th.fg("dim", `↑↓ scroll · g/G top/end · Esc/${formattedShortcutPair("dashboard")} close`)));
511
516
  return lines;
512
517
  }
513
518
  renderProgressRow(label, done, total, color, width) {
@@ -102,10 +102,27 @@ export function getPriorSliceCompletionBlocker(base, _mainBranch, unitType, unit
102
102
  }
103
103
  }
104
104
  else {
105
+ // Positional fallback is only a heuristic for legacy slices with no
106
+ // declared dependencies. Skip any earlier slice that depends on the
107
+ // target, directly or transitively, or we can deadlock a valid zero-dep
108
+ // slice behind its own downstream dependents (#3720).
109
+ const reverseDependents = new Set();
110
+ let changed = true;
111
+ while (changed) {
112
+ changed = false;
113
+ for (const slice of slices) {
114
+ if (reverseDependents.has(slice.id))
115
+ continue;
116
+ if (slice.depends.some((depId) => depId === targetSid || reverseDependents.has(depId))) {
117
+ reverseDependents.add(slice.id);
118
+ changed = true;
119
+ }
120
+ }
121
+ }
105
122
  const targetIndex = slices.findIndex((slice) => slice.id === targetSid);
106
123
  const incomplete = slices
107
124
  .slice(0, targetIndex)
108
- .find((slice) => !slice.done);
125
+ .find((slice) => !slice.done && !reverseDependents.has(slice.id));
109
126
  if (incomplete) {
110
127
  return `Cannot dispatch ${unitType} ${unitId}: earlier slice ${targetMid}/${incomplete.id} is not complete.`;
111
128
  }
@@ -147,10 +147,33 @@ const PROVIDER_ROUTES = {
147
147
  openai: ["github-copilot", "openai-codex"],
148
148
  google: ["google-gemini-cli"],
149
149
  };
150
+ /**
151
+ * Providers that use external CLI authentication (not API keys).
152
+ * These are always considered "ok" — the host CLI handles auth.
153
+ */
154
+ const CLI_AUTH_PROVIDERS = new Set([
155
+ "claude-code",
156
+ "openai-codex",
157
+ "google-gemini-cli",
158
+ "google-antigravity",
159
+ ]);
150
160
  function checkLlmProviders() {
151
161
  const required = collectConfiguredModelProviders();
152
162
  const results = [];
153
163
  for (const providerId of required) {
164
+ // CLI-authenticated providers don't need API keys — skip key check
165
+ if (CLI_AUTH_PROVIDERS.has(providerId)) {
166
+ const info = PROVIDER_REGISTRY.find(p => p.id === providerId);
167
+ results.push({
168
+ name: providerId,
169
+ label: info?.label ?? providerId,
170
+ category: "llm",
171
+ status: "ok",
172
+ message: `${info?.label ?? providerId} — CLI auth (no key needed)`,
173
+ required: true,
174
+ });
175
+ continue;
176
+ }
154
177
  const info = PROVIDER_REGISTRY.find(p => p.id === providerId);
155
178
  const label = providerId === "anthropic-vertex"
156
179
  ? "Anthropic Vertex"
@@ -20,10 +20,13 @@ export function resetRetryState(state) {
20
20
  // ── Classification ──────────────────────────────────────────────────────────
21
21
  const PERMANENT_RE = /auth|unauthorized|forbidden|invalid.*key|invalid.*api|billing|quota exceeded|account/i;
22
22
  const RATE_LIMIT_RE = /rate.?limit|too many requests|429/i;
23
+ // OpenRouter affordability-style quota errors should be treated as transient
24
+ // so core retry logic can lower maxTokens and continue in-session.
25
+ const AFFORDABILITY_RE = /requires more credits|can only afford|insufficient credits|not enough credits|fewer max_tokens/i;
23
26
  const NETWORK_RE = /network|ECONNRESET|ETIMEDOUT|ECONNREFUSED|socket hang up|fetch failed|connection.*reset|dns/i;
24
27
  const SERVER_RE = /internal server error|500|502|503|overloaded|server_error|api_error|service.?unavailable/i;
25
28
  // ECONNRESET/ECONNREFUSED are in NETWORK_RE (same-model retry first).
26
- const CONNECTION_RE = /terminated|connection.?refused|other side closed|EPIPE|network.?(?:is\s+)?unavailable|stream_exhausted(?:_without_result)?/i;
29
+ const CONNECTION_RE = /terminated|connection.?(?:refused|error)|other side closed|EPIPE|network.?(?:is\s+)?unavailable|stream_exhausted(?:_without_result)?/i;
27
30
  // Catch-all for V8 JSON.parse errors: all modern variants end with "in JSON at position \d+".
28
31
  // This eliminates the need to enumerate every error message variant individually.
29
32
  const STREAM_RE = /in JSON at position \d+|Unexpected end of JSON|SyntaxError.*JSON/i;
@@ -42,7 +45,7 @@ const RESET_DELAY_RE = /reset in (\d+)s/i;
42
45
  */
43
46
  export function classifyError(errorMsg, retryAfterMs) {
44
47
  const isPermanent = PERMANENT_RE.test(errorMsg);
45
- const isRateLimit = RATE_LIMIT_RE.test(errorMsg);
48
+ const isRateLimit = RATE_LIMIT_RE.test(errorMsg) || AFFORDABILITY_RE.test(errorMsg);
46
49
  // 1. Permanent — but rate limit takes precedence
47
50
  if (isPermanent && !isRateLimit) {
48
51
  return { kind: "permanent" };
@@ -508,19 +508,30 @@ function getDbCompletionCounts() {
508
508
  * Exported for testability.
509
509
  */
510
510
  export function detectStuckLoops(units, anomalies) {
511
- // First, collect unique startedAt values per type/id key
511
+ // First, collect unique startedAt values per type/id key, bucketed by
512
+ // autoSessionKey when available so cross-session recovery does not look
513
+ // like a within-session stuck loop.
512
514
  const dispatchMap = new Map();
513
515
  for (const u of units) {
514
516
  const key = `${u.type}/${u.id}`;
515
- let starts = dispatchMap.get(key);
517
+ let sessionBuckets = dispatchMap.get(key);
518
+ if (!sessionBuckets) {
519
+ sessionBuckets = new Map();
520
+ dispatchMap.set(key, sessionBuckets);
521
+ }
522
+ const sessionKey = u.autoSessionKey ?? "__legacy__";
523
+ let starts = sessionBuckets.get(sessionKey);
516
524
  if (!starts) {
517
525
  starts = new Set();
518
- dispatchMap.set(key, starts);
526
+ sessionBuckets.set(sessionKey, starts);
519
527
  }
520
528
  starts.add(u.startedAt);
521
529
  }
522
- for (const [key, starts] of dispatchMap) {
523
- const count = starts.size;
530
+ for (const [key, sessionBuckets] of dispatchMap) {
531
+ const hasSessionAwareData = Array.from(sessionBuckets.keys()).some((sessionKey) => sessionKey !== "__legacy__");
532
+ const count = hasSessionAwareData
533
+ ? Math.max(...Array.from(sessionBuckets.values(), (starts) => starts.size))
534
+ : (sessionBuckets.get("__legacy__")?.size ?? 0);
524
535
  if (count > 1) {
525
536
  const [unitType, ...idParts] = key.split("/");
526
537
  anomalies.push({
@@ -529,7 +540,9 @@ export function detectStuckLoops(units, anomalies) {
529
540
  unitType,
530
541
  unitId: idParts.join("/"),
531
542
  summary: `Unit ${key} was dispatched ${count} times`,
532
- details: `Repeated dispatch suggests the unit completed but its artifacts weren't verified, or the state machine kept returning it.`,
543
+ details: hasSessionAwareData
544
+ ? `Repeated dispatch within the same auto session suggests the unit completed but its artifacts were not verified, or the state machine kept returning it. Cross-session recovery runs are ignored.`
545
+ : `Repeated dispatch suggests the unit completed but its artifacts weren't verified, or the state machine kept returning it.`,
533
546
  });
534
547
  }
535
548
  }
@@ -0,0 +1,208 @@
1
+ /**
2
+ * GSD Gate Registry — single source of truth for quality-gate ownership.
3
+ *
4
+ * Each gate declares which workflow turn owns it, the scope at which it is
5
+ * persisted in the `quality_gates` table, and the question/guidance text used
6
+ * in the prompt that turn sends. The registry replaces the ad-hoc
7
+ * `GATE_QUESTIONS` table that used to live in `auto-prompts.ts`, and every
8
+ * layer of the prompt system (prompt builders, dispatch rules, state
9
+ * derivation, tool handlers) consults it so a pending gate can never be
10
+ * silently dropped.
11
+ *
12
+ * Design notes:
13
+ * - `GATE_REGISTRY` is exhaustiveness-checked against `GateId` via
14
+ * `satisfies Record<GateId, GateDefinition>`, so adding a new GateId
15
+ * without a registry entry is a compile error.
16
+ * - `getGatesForTurn(turn)` returns the definitions a turn owns.
17
+ * - `assertGateCoverage(pending, turn)` throws a GSDError if the pending
18
+ * list for a turn contains unknown gates, or if any gate owned by the
19
+ * turn is missing from the pending list.
20
+ */
21
+ import { GSDError, GSD_PARSE_ERROR } from "./errors.js";
22
+ export const GATE_REGISTRY = {
23
+ Q3: {
24
+ id: "Q3",
25
+ scope: "slice",
26
+ ownerTurn: "gate-evaluate",
27
+ question: "How can this be exploited?",
28
+ guidance: [
29
+ "Identify abuse scenarios: parameter tampering, replay attacks, privilege escalation.",
30
+ "Map data exposure risks: PII, tokens, secrets accessible through this slice.",
31
+ "Define input trust boundaries: untrusted user input reaching DB, API, or filesystem.",
32
+ "If none apply, return verdict 'omitted' with rationale explaining why.",
33
+ ].join("\n"),
34
+ promptSection: "Abuse Surface",
35
+ },
36
+ Q4: {
37
+ id: "Q4",
38
+ scope: "slice",
39
+ ownerTurn: "gate-evaluate",
40
+ question: "What existing promises does this break?",
41
+ guidance: [
42
+ "List which existing requirements (R001, R003, etc.) are touched by this slice.",
43
+ "Identify what must be re-tested after shipping.",
44
+ "Flag decisions that should be revisited given the new scope.",
45
+ "If no existing requirements are affected, return verdict 'omitted'.",
46
+ ].join("\n"),
47
+ promptSection: "Broken Promises",
48
+ },
49
+ Q5: {
50
+ id: "Q5",
51
+ scope: "task",
52
+ ownerTurn: "execute-task",
53
+ question: "What breaks when dependencies fail?",
54
+ guidance: [
55
+ "Enumerate the task's external dependencies (APIs, filesystem, network, subprocesses).",
56
+ "Describe the failure path for each: timeout, malformed response, connection loss.",
57
+ "Verify the implementation handles each failure or explicitly bubbles the error.",
58
+ "Return verdict 'omitted' only if the task has no external dependencies.",
59
+ ].join("\n"),
60
+ promptSection: "Failure Modes",
61
+ },
62
+ Q6: {
63
+ id: "Q6",
64
+ scope: "task",
65
+ ownerTurn: "execute-task",
66
+ question: "What is the 10x load breakpoint?",
67
+ guidance: [
68
+ "Identify the resource that saturates first at 10x the expected load.",
69
+ "Describe the protection applied (pool sizing, rate limiting, pagination, caching).",
70
+ "Return verdict 'omitted' if the task has no runtime load dimension.",
71
+ ].join("\n"),
72
+ promptSection: "Load Profile",
73
+ },
74
+ Q7: {
75
+ id: "Q7",
76
+ scope: "task",
77
+ ownerTurn: "execute-task",
78
+ question: "What negative tests protect this task?",
79
+ guidance: [
80
+ "List malformed inputs, error paths, and boundary conditions the tests cover.",
81
+ "Point to the specific test files or cases that assert each negative scenario.",
82
+ "Return verdict 'omitted' only if the task has no meaningful negative surface.",
83
+ ].join("\n"),
84
+ promptSection: "Negative Tests",
85
+ },
86
+ Q8: {
87
+ id: "Q8",
88
+ scope: "slice",
89
+ ownerTurn: "complete-slice",
90
+ question: "How will ops know this slice is healthy or broken?",
91
+ guidance: [
92
+ "Describe the health signal (metric, log line, dashboard) that proves the slice works.",
93
+ "Describe the failure signal that triggers an alert or paging.",
94
+ "Document the recovery procedure and any monitoring gaps.",
95
+ "Return verdict 'omitted' only for slices with no runtime behavior at all.",
96
+ ].join("\n"),
97
+ promptSection: "Operational Readiness",
98
+ },
99
+ MV01: {
100
+ id: "MV01",
101
+ scope: "milestone",
102
+ ownerTurn: "validate-milestone",
103
+ question: "Is every success criterion in the milestone roadmap satisfied?",
104
+ guidance: [
105
+ "Walk the success-criteria checklist from the milestone roadmap.",
106
+ "For each criterion, point to the slice / assessment / verification evidence that proves it.",
107
+ "Return verdict 'flag' if any criterion is unmet or unverifiable.",
108
+ ].join("\n"),
109
+ promptSection: "Success Criteria Checklist",
110
+ },
111
+ MV02: {
112
+ id: "MV02",
113
+ scope: "milestone",
114
+ ownerTurn: "validate-milestone",
115
+ question: "Does every slice have a SUMMARY.md and a passing assessment?",
116
+ guidance: [
117
+ "Confirm every slice listed in the roadmap has a SUMMARY.md.",
118
+ "Confirm each slice has an ASSESSMENT verdict of 'pass' (or justified 'omitted').",
119
+ "Flag missing artifacts and slices with outstanding follow-ups or known limitations.",
120
+ ].join("\n"),
121
+ promptSection: "Slice Delivery Audit",
122
+ },
123
+ MV03: {
124
+ id: "MV03",
125
+ scope: "milestone",
126
+ ownerTurn: "validate-milestone",
127
+ question: "Do the slices integrate end-to-end?",
128
+ guidance: [
129
+ "Trace at least one cross-slice flow proving the pieces compose.",
130
+ "Flag gaps where two slices were built in isolation with no integration evidence.",
131
+ ].join("\n"),
132
+ promptSection: "Cross-Slice Integration",
133
+ },
134
+ MV04: {
135
+ id: "MV04",
136
+ scope: "milestone",
137
+ ownerTurn: "validate-milestone",
138
+ question: "Are all touched requirements covered and still coherent?",
139
+ guidance: [
140
+ "For each requirement advanced, validated, surfaced, or invalidated across the milestone's slices, confirm the milestone-level evidence matches.",
141
+ "Flag requirements that slices claim to advance but no artifact proves.",
142
+ ].join("\n"),
143
+ promptSection: "Requirement Coverage",
144
+ },
145
+ };
146
+ /** Stable ordered lists per owner turn — iteration order matches declaration. */
147
+ const ORDERED_GATES = Object.values(GATE_REGISTRY);
148
+ /** Return every gate owned by a turn, in stable declaration order. */
149
+ export function getGatesForTurn(turn) {
150
+ return ORDERED_GATES.filter((g) => g.ownerTurn === turn);
151
+ }
152
+ /** Return the set of gate ids a turn owns. */
153
+ export function getGateIdsForTurn(turn) {
154
+ return new Set(getGatesForTurn(turn).map((g) => g.id));
155
+ }
156
+ /** Look up a definition by gate id, or undefined if unknown. */
157
+ export function getGateDefinition(id) {
158
+ return GATE_REGISTRY[id];
159
+ }
160
+ /** Look up the owner turn for a gate id. Throws if the gate is unknown. */
161
+ export function getOwnerTurn(id) {
162
+ const def = GATE_REGISTRY[id];
163
+ if (!def) {
164
+ throw new GSDError(GSD_PARSE_ERROR, `gate-registry: unknown gate id "${id}"`);
165
+ }
166
+ return def.ownerTurn;
167
+ }
168
+ /**
169
+ * Assert that the pending gate rows for a turn match what the registry says
170
+ * the turn owns. Fails loudly rather than silently skipping.
171
+ *
172
+ * - Every row in `pending` must have a definition whose `ownerTurn` matches `turn`.
173
+ * (The caller is responsible for scoping the pending list — e.g. filtering
174
+ * by slice scope before passing it in.)
175
+ * - `options.requireAll` (default true): every gate the turn owns must appear
176
+ * in `pending`. Set to false for turns like `execute-task` that only need
177
+ * coverage for the subset of gates that were seeded (e.g. tasks with no
178
+ * external dependencies have no Q5 row).
179
+ */
180
+ export function assertGateCoverage(pending, turn, options = {}) {
181
+ const requireAll = options.requireAll ?? true;
182
+ const expected = getGateIdsForTurn(turn);
183
+ const pendingIds = new Set(pending.map((g) => g.gate_id));
184
+ const unknown = [];
185
+ for (const id of pendingIds) {
186
+ const def = getGateDefinition(id);
187
+ if (!def) {
188
+ unknown.push(id);
189
+ continue;
190
+ }
191
+ if (def.ownerTurn !== turn) {
192
+ unknown.push(`${id} (owned by ${def.ownerTurn}, not ${turn})`);
193
+ }
194
+ }
195
+ if (unknown.length > 0) {
196
+ throw new GSDError(GSD_PARSE_ERROR, `assertGateCoverage: turn "${turn}" received pending gates it does not own: ${unknown.join(", ")}`);
197
+ }
198
+ if (requireAll) {
199
+ const missing = [];
200
+ for (const id of expected) {
201
+ if (!pendingIds.has(id))
202
+ missing.push(id);
203
+ }
204
+ if (missing.length > 0) {
205
+ throw new GSDError(GSD_PARSE_ERROR, `assertGateCoverage: turn "${turn}" is missing required gates: ${missing.join(", ")}`);
206
+ }
207
+ }
208
+ }
@@ -8,6 +8,7 @@ import { createRequire } from "node:module";
8
8
  import { existsSync, copyFileSync, mkdirSync, realpathSync } from "node:fs";
9
9
  import { dirname } from "node:path";
10
10
  import { GSDError, GSD_STALE_STATE } from "./errors.js";
11
+ import { getGateIdsForTurn } from "./gate-registry.js";
11
12
  import { logError, logWarning } from "./workflow-logger.js";
12
13
  const _require = createRequire(import.meta.url);
13
14
  let providerName = null;
@@ -1927,3 +1928,43 @@ export function getPendingSliceGateCount(milestoneId, sliceId) {
1927
1928
  WHERE milestone_id = :mid AND slice_id = :sid AND scope = 'slice' AND status = 'pending'`).get({ ":mid": milestoneId, ":sid": sliceId });
1928
1929
  return row ? row["cnt"] : 0;
1929
1930
  }
1931
+ /**
1932
+ * Return pending gate rows owned by a specific workflow turn.
1933
+ *
1934
+ * Unlike `getPendingGates(..., scope)`, this filters by the registry's
1935
+ * `ownerTurn` metadata so callers can distinguish Q3/Q4 (owned by
1936
+ * gate-evaluate) from Q8 (owned by complete-slice) even though both are
1937
+ * scope:"slice". Pass `taskId` to narrow task-scoped results to one task.
1938
+ */
1939
+ export function getPendingGatesForTurn(milestoneId, sliceId, turn, taskId) {
1940
+ if (!currentDb)
1941
+ return [];
1942
+ const ids = getGateIdsForTurn(turn);
1943
+ if (ids.size === 0)
1944
+ return [];
1945
+ const idList = [...ids];
1946
+ const placeholders = idList.map((_, i) => `:gid${i}`).join(",");
1947
+ const params = {
1948
+ ":mid": milestoneId,
1949
+ ":sid": sliceId,
1950
+ };
1951
+ idList.forEach((id, i) => {
1952
+ params[`:gid${i}`] = id;
1953
+ });
1954
+ let sql = `SELECT * FROM quality_gates
1955
+ WHERE milestone_id = :mid AND slice_id = :sid
1956
+ AND status = 'pending'
1957
+ AND gate_id IN (${placeholders})`;
1958
+ if (taskId !== undefined) {
1959
+ sql += ` AND task_id = :tid`;
1960
+ params[":tid"] = taskId;
1961
+ }
1962
+ return currentDb.prepare(sql).all(params).map(rowToGate);
1963
+ }
1964
+ /**
1965
+ * Count pending gates for a turn. Convenience wrapper used by state
1966
+ * derivation to decide whether a phase transition should pause.
1967
+ */
1968
+ export function getPendingGateCountForTurn(milestoneId, sliceId, turn) {
1969
+ return getPendingGatesForTurn(milestoneId, sliceId, turn).length;
1970
+ }
@@ -13,7 +13,7 @@ import { loadPrompt, inlineTemplate } from "./prompt-loader.js";
13
13
  import { buildSkillActivationBlock } from "./auto-prompts.js";
14
14
  import { deriveState } from "./state.js";
15
15
  import { invalidateAllCaches } from "./cache.js";
16
- import { startAuto } from "./auto.js";
16
+ import { startAutoDetached } from "./auto.js";
17
17
  import { clearLock } from "./crash-recovery.js";
18
18
  import { assessInterruptedSession, formatInterruptedSessionRunningMessage, formatInterruptedSessionSummary, } from "./interrupted-session.js";
19
19
  import { listUnitRuntimeRecords, clearUnitRuntimeRecord } from "./unit-runtime.js";
@@ -40,7 +40,6 @@ import { runPreparation, formatCodebaseBrief, formatPriorContextBrief, } from ".
40
40
  // ─── Re-exports (preserve public API for existing importers) ────────────────
41
41
  export { MILESTONE_ID_RE, generateMilestoneSuffix, nextMilestoneId, extractMilestoneSeq, parseMilestoneId, milestoneIdSort, maxMilestoneNum, findMilestoneIds, reserveMilestoneId, claimReservedId, getReservedMilestoneIds, clearReservedMilestoneIds, } from "./milestone-ids.js";
42
42
  export { showQueue, handleQueueReorder, showQueueAdd, buildExistingMilestonesContext, } from "./guided-flow-queue.js";
43
- import { getErrorMessage } from "./error-utils.js";
44
43
  import { logWarning } from "./workflow-logger.js";
45
44
  // ─── ID Generation with Reservation ─────────────────────────────────────────
46
45
  /**
@@ -200,11 +199,7 @@ export function checkAutoStartAfterDiscuss() {
200
199
  }
201
200
  pendingAutoStartMap.delete(basePath);
202
201
  ctx.ui.notify(`Milestone ${milestoneId} ready.`, "info");
203
- startAuto(ctx, pi, basePath, false, { step }).catch((err) => {
204
- ctx.ui.notify(`Auto-start failed: ${getErrorMessage(err)}`, "error");
205
- logWarning("guided", `auto start error: ${getErrorMessage(err)}`);
206
- debugLog("auto-start-failed", { error: getErrorMessage(err) });
207
- });
202
+ startAutoDetached(ctx, pi, basePath, false, { step });
208
203
  return true;
209
204
  }
210
205
  /**
@@ -1097,7 +1092,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
1097
1092
  ],
1098
1093
  });
1099
1094
  if (resume === "resume") {
1100
- await startAuto(ctx, pi, basePath, false, {
1095
+ startAutoDetached(ctx, pi, basePath, false, {
1101
1096
  interrupted,
1102
1097
  step: interrupted.pausedSession?.stepMode ?? false,
1103
1098
  });
@@ -1409,7 +1404,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
1409
1404
  notYetMessage: "Run /gsd status for details.",
1410
1405
  });
1411
1406
  if (choice === "auto") {
1412
- await startAuto(ctx, pi, basePath, false);
1407
+ startAutoDetached(ctx, pi, basePath, false);
1413
1408
  }
1414
1409
  else if (choice === "status") {
1415
1410
  const { fireStatusViaCommand } = await import("./commands.js");
@@ -1622,7 +1617,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
1622
1617
  notYetMessage: "Run /gsd when ready.",
1623
1618
  });
1624
1619
  if (choice === "auto") {
1625
- await startAuto(ctx, pi, basePath, false);
1620
+ startAutoDetached(ctx, pi, basePath, false);
1626
1621
  return;
1627
1622
  }
1628
1623
  if (choice === "execute") {
@@ -113,6 +113,7 @@ export function snapshotUnitMetrics(ctx, unitType, unitId, startedAt, model, opt
113
113
  model,
114
114
  startedAt,
115
115
  finishedAt: Date.now(),
116
+ ...(opts?.autoSessionKey ? { autoSessionKey: opts.autoSessionKey } : {}),
116
117
  tokens,
117
118
  cost,
118
119
  toolCalls,
@@ -15,7 +15,7 @@ import { join } from "node:path";
15
15
  import { resolveMilestonePath, resolveMilestoneFile, buildMilestoneFileName, } from "./paths.js";
16
16
  import { invalidateAllCaches } from "./cache.js";
17
17
  import { loadQueueOrder, saveQueueOrder } from "./queue-order.js";
18
- import { isDbAvailable, updateMilestoneStatus } from "./gsd-db.js";
18
+ import { getMilestone, isDbAvailable, updateMilestoneStatus } from "./gsd-db.js";
19
19
  import { logWarning } from "./workflow-logger.js";
20
20
  // ─── Park ──────────────────────────────────────────────────────────────────
21
21
  /**
@@ -68,9 +68,15 @@ export function unparkMilestone(basePath, milestoneId) {
68
68
  if (!mDir || !existsSync(mDir))
69
69
  return false;
70
70
  const parkedPath = join(mDir, buildMilestoneFileName(milestoneId, "PARKED"));
71
- if (!existsSync(parkedPath))
72
- return false; // not parked
73
- unlinkSync(parkedPath);
71
+ const hadParkedFile = existsSync(parkedPath);
72
+ const dbThinksParked = isDbAvailable() && getMilestone(milestoneId)?.status === "parked";
73
+ // Recover the reverse desync too: DB can still say "parked" even when the
74
+ // PARKED marker was lost on disk, and /gsd unpark should repair that state.
75
+ if (!hadParkedFile && !dbThinksParked)
76
+ return false;
77
+ if (hadParkedFile) {
78
+ unlinkSync(parkedPath);
79
+ }
74
80
  // Sync DB status so deriveStateFromDb picks up the unparked milestone (#2694)
75
81
  if (isDbAvailable()) {
76
82
  try {
@@ -6,17 +6,12 @@
6
6
  * records in the DB. This module inserts milestone-level validation gates
7
7
  * that correspond to the validation checks performed.
8
8
  *
9
- * Gate IDs for milestone validation:
10
- * MV01 Success criteria checklist
11
- * MV02 Slice delivery audit
12
- * MV03 — Cross-slice integration
13
- * MV04 — Requirement coverage
14
- *
15
- * These use the existing quality_gates table with scope "milestone".
9
+ * Gate IDs for milestone validation (MV01–MV04) are sourced from the
10
+ * gate registry so the definitions stay in lockstep with prompt builders,
11
+ * dispatch rules, and state derivation. See gate-registry.ts.
16
12
  */
17
13
  import { _getAdapter } from "./gsd-db.js";
18
- /** Milestone validation gate IDs. */
19
- const MILESTONE_GATE_IDS = ["MV01", "MV02", "MV03", "MV04"];
14
+ import { getGatesForTurn } from "./gate-registry.js";
20
15
  /**
21
16
  * Insert milestone-level quality_gates records for a validation run.
22
17
  *
@@ -24,21 +19,25 @@ const MILESTONE_GATE_IDS = ["MV01", "MV02", "MV03", "MV04"];
24
19
  * from the overall milestone validation verdict. Individual gate-level
25
20
  * verdicts are not available (the handler receives a single verdict),
26
21
  * so all gates share the overall verdict.
22
+ *
23
+ * Gate IDs come from the registry — adding/removing an MV-scoped gate
24
+ * in gate-registry.ts automatically flows through here.
27
25
  */
28
26
  export function insertMilestoneValidationGates(milestoneId, sliceId, verdict, evaluatedAt) {
29
27
  const db = _getAdapter();
30
28
  if (!db)
31
29
  return;
32
30
  const gateVerdict = verdict === "pass" ? "pass" : "flag";
33
- for (const gateId of MILESTONE_GATE_IDS) {
31
+ const milestoneGates = getGatesForTurn("validate-milestone");
32
+ for (const def of milestoneGates) {
34
33
  db.prepare(`INSERT OR REPLACE INTO quality_gates
35
34
  (milestone_id, slice_id, gate_id, scope, task_id, status, verdict, rationale, findings, evaluated_at)
36
35
  VALUES (:mid, :sid, :gid, 'milestone', '', 'complete', :verdict, :rationale, '', :evaluated_at)`).run({
37
36
  ":mid": milestoneId,
38
37
  ":sid": sliceId,
39
- ":gid": gateId,
38
+ ":gid": def.id,
40
39
  ":verdict": gateVerdict,
41
- ":rationale": `Milestone validation verdict: ${verdict}`,
40
+ ":rationale": `${def.promptSection} — milestone validation verdict: ${verdict}`,
42
41
  ":evaluated_at": evaluatedAt,
43
42
  });
44
43
  }