gsd-pi 2.71.0 → 2.72.0-dev.de4c4b3

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 (459) 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/stream-adapter.js +113 -10
  22. package/dist/resources/extensions/gsd/auto/infra-errors.js +34 -0
  23. package/dist/resources/extensions/gsd/auto/loop.js +32 -1
  24. package/dist/resources/extensions/gsd/auto/phases.js +5 -1
  25. package/dist/resources/extensions/gsd/auto/session.js +11 -0
  26. package/dist/resources/extensions/gsd/auto-dashboard.js +22 -16
  27. package/dist/resources/extensions/gsd/auto-model-selection.js +10 -2
  28. package/dist/resources/extensions/gsd/auto-prompts.js +88 -33
  29. package/dist/resources/extensions/gsd/auto-start.js +34 -7
  30. package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
  31. package/dist/resources/extensions/gsd/auto-worktree.js +1 -1
  32. package/dist/resources/extensions/gsd/auto.js +56 -0
  33. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -3
  34. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +2 -0
  35. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +63 -51
  36. package/dist/resources/extensions/gsd/bootstrap/system-context.js +6 -0
  37. package/dist/resources/extensions/gsd/commands/context.js +15 -6
  38. package/dist/resources/extensions/gsd/commands/dispatcher.js +12 -2
  39. package/dist/resources/extensions/gsd/commands/handlers/auto.js +10 -33
  40. package/dist/resources/extensions/gsd/commands/handlers/core.js +56 -11
  41. package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +15 -6
  42. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +4 -10
  43. package/dist/resources/extensions/gsd/dashboard-overlay.js +8 -3
  44. package/dist/resources/extensions/gsd/dispatch-guard.js +18 -1
  45. package/dist/resources/extensions/gsd/doctor-providers.js +23 -0
  46. package/dist/resources/extensions/gsd/error-classifier.js +5 -2
  47. package/dist/resources/extensions/gsd/forensics.js +19 -6
  48. package/dist/resources/extensions/gsd/gate-registry.js +208 -0
  49. package/dist/resources/extensions/gsd/gsd-db.js +41 -0
  50. package/dist/resources/extensions/gsd/guided-flow.js +5 -10
  51. package/dist/resources/extensions/gsd/metrics.js +1 -0
  52. package/dist/resources/extensions/gsd/milestone-actions.js +10 -4
  53. package/dist/resources/extensions/gsd/milestone-validation-gates.js +11 -12
  54. package/dist/resources/extensions/gsd/notification-overlay.js +42 -13
  55. package/dist/resources/extensions/gsd/notification-store.js +56 -5
  56. package/dist/resources/extensions/gsd/notification-widget.js +5 -13
  57. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +8 -3
  58. package/dist/resources/extensions/gsd/pre-execution-checks.js +35 -2
  59. package/dist/resources/extensions/gsd/prompt-validation.js +126 -0
  60. package/dist/resources/extensions/gsd/prompts/complete-slice.md +5 -3
  61. package/dist/resources/extensions/gsd/prompts/discuss.md +2 -0
  62. package/dist/resources/extensions/gsd/prompts/execute-task.md +22 -19
  63. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  64. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
  65. package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  66. package/dist/resources/extensions/gsd/prompts/queue.md +3 -2
  67. package/dist/resources/extensions/gsd/prompts/system.md +1 -0
  68. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
  69. package/dist/resources/extensions/gsd/session-model-override.js +25 -0
  70. package/dist/resources/extensions/gsd/shortcut-defs.js +40 -0
  71. package/dist/resources/extensions/gsd/state.js +9 -2
  72. package/dist/resources/extensions/gsd/tools/complete-slice.js +52 -1
  73. package/dist/resources/extensions/gsd/tools/complete-task.js +51 -1
  74. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +4 -1
  75. package/dist/resources/extensions/ollama/index.js +13 -5
  76. package/dist/resources/extensions/shared/gsd-phase-state.js +35 -0
  77. package/dist/resources/extensions/subagent/agents.js +8 -0
  78. package/dist/resources/extensions/subagent/index.js +17 -0
  79. package/dist/resources/skills/create-skill/SKILL.md +2 -0
  80. package/dist/startup-model-validation.d.ts +0 -1
  81. package/dist/startup-model-validation.js +6 -2
  82. package/dist/web/standalone/.next/BUILD_ID +1 -1
  83. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  84. package/dist/web/standalone/.next/build-manifest.json +3 -3
  85. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  86. package/dist/web/standalone/.next/required-server-files.json +3 -3
  87. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  88. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  89. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  90. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  98. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  114. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  126. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  146. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  156. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  162. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  178. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
  182. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/index.html +1 -1
  192. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  193. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  194. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  195. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  196. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  197. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  198. package/dist/web/standalone/.next/server/app/page.js +2 -2
  199. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  201. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  202. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  203. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/middleware.js +2 -2
  205. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  206. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  207. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  208. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  209. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  210. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  211. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  212. package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +1 -0
  213. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  214. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  215. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  216. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  217. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  218. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  219. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  220. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  221. package/dist/web/standalone/server.js +1 -1
  222. package/package.json +1 -1
  223. package/packages/mcp-server/dist/server.d.ts +12 -1
  224. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  225. package/packages/mcp-server/dist/server.js +90 -42
  226. package/packages/mcp-server/dist/server.js.map +1 -1
  227. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  228. package/packages/mcp-server/dist/workflow-tools.js +22 -12
  229. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  230. package/packages/mcp-server/src/server.ts +110 -38
  231. package/packages/mcp-server/src/workflow-tools.test.ts +110 -0
  232. package/packages/mcp-server/src/workflow-tools.ts +32 -12
  233. package/packages/pi-ai/dist/providers/amazon-bedrock.js +11 -2
  234. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  235. package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts +2 -0
  236. package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts.map +1 -0
  237. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +20 -0
  238. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -0
  239. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts +4 -1
  240. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  241. package/packages/pi-ai/dist/providers/anthropic-shared.js +8 -3
  242. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  243. package/packages/pi-ai/dist/providers/anthropic-shared.test.js +44 -1
  244. package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -1
  245. package/packages/pi-ai/dist/providers/anthropic.d.ts +2 -1
  246. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  247. package/packages/pi-ai/dist/providers/anthropic.js +7 -4
  248. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  249. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  250. package/packages/pi-ai/dist/providers/openai-completions.js +11 -0
  251. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  252. package/packages/pi-ai/src/providers/amazon-bedrock.ts +13 -1
  253. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +32 -0
  254. package/packages/pi-ai/src/providers/anthropic-shared.test.ts +55 -1
  255. package/packages/pi-ai/src/providers/anthropic-shared.ts +14 -3
  256. package/packages/pi-ai/src/providers/anthropic.ts +8 -4
  257. package/packages/pi-ai/src/providers/openai-completions.ts +14 -0
  258. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts +2 -0
  259. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts.map +1 -0
  260. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js +61 -0
  261. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js.map +1 -0
  262. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  263. package/packages/pi-coding-agent/dist/core/agent-session.js +2 -1
  264. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  265. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +10 -0
  266. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  267. package/packages/pi-coding-agent/dist/core/auth-storage.js +27 -0
  268. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  269. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +85 -0
  270. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  271. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts +2 -0
  272. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts.map +1 -0
  273. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js +64 -0
  274. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js.map +1 -0
  275. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  276. package/packages/pi-coding-agent/dist/core/model-resolver.js +22 -18
  277. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  278. package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts +8 -0
  279. package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts.map +1 -0
  280. package/packages/pi-coding-agent/dist/core/model-resolver.test.js +75 -0
  281. package/packages/pi-coding-agent/dist/core/model-resolver.test.js.map +1 -0
  282. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +5 -0
  283. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  284. package/packages/pi-coding-agent/dist/core/retry-handler.js +55 -1
  285. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  286. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +57 -0
  287. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  288. package/packages/pi-coding-agent/dist/core/sdk.d.ts +11 -0
  289. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  290. package/packages/pi-coding-agent/dist/core/sdk.js +38 -5
  291. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  292. package/packages/pi-coding-agent/dist/core/sdk.test.d.ts +2 -0
  293. package/packages/pi-coding-agent/dist/core/sdk.test.d.ts.map +1 -0
  294. package/packages/pi-coding-agent/dist/core/sdk.test.js +71 -0
  295. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -0
  296. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  297. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  298. package/packages/pi-coding-agent/dist/index.js +1 -1
  299. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  300. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts +2 -0
  301. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts.map +1 -0
  302. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js +13 -0
  303. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js.map +1 -0
  304. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +4 -0
  305. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  306. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +24 -2
  307. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  308. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  309. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +9 -2
  310. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  311. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +4 -0
  312. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  313. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +43 -0
  314. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  315. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  316. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +7 -2
  317. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  318. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.d.ts.map +1 -1
  319. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js +6 -1
  320. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js.map +1 -1
  321. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  322. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -3
  323. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  324. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +4 -2
  325. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  326. package/packages/pi-coding-agent/package.json +1 -1
  327. package/packages/pi-coding-agent/src/core/agent-session-renderable-tools.test.ts +70 -0
  328. package/packages/pi-coding-agent/src/core/agent-session.ts +2 -1
  329. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +108 -0
  330. package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -0
  331. package/packages/pi-coding-agent/src/core/model-resolver-initial-model-auth.test.ts +78 -0
  332. package/packages/pi-coding-agent/src/core/model-resolver.test.ts +85 -0
  333. package/packages/pi-coding-agent/src/core/model-resolver.ts +22 -18
  334. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +83 -0
  335. package/packages/pi-coding-agent/src/core/retry-handler.ts +60 -1
  336. package/packages/pi-coding-agent/src/core/sdk.test.ts +89 -0
  337. package/packages/pi-coding-agent/src/core/sdk.ts +45 -9
  338. package/packages/pi-coding-agent/src/index.ts +1 -0
  339. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/login-dialog.test.ts +24 -0
  340. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +30 -2
  341. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +15 -6
  342. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +47 -0
  343. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +7 -2
  344. package/packages/pi-coding-agent/src/modes/interactive/controllers/model-controller.ts +6 -1
  345. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +4 -3
  346. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +4 -2
  347. package/pkg/package.json +1 -1
  348. package/src/resources/GSD-WORKFLOW.md +1 -1
  349. package/src/resources/agents/debugger.md +58 -0
  350. package/src/resources/agents/doc-writer.md +43 -0
  351. package/src/resources/agents/git-ops.md +56 -0
  352. package/src/resources/agents/javascript-pro.md +46 -271
  353. package/src/resources/agents/planner.md +55 -0
  354. package/src/resources/agents/refactorer.md +47 -0
  355. package/src/resources/agents/reviewer.md +48 -0
  356. package/src/resources/agents/security.md +59 -0
  357. package/src/resources/agents/tester.md +50 -0
  358. package/src/resources/agents/typescript-pro.md +41 -235
  359. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +122 -8
  360. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +189 -6
  361. package/src/resources/extensions/gsd/auto/infra-errors.ts +38 -0
  362. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
  363. package/src/resources/extensions/gsd/auto/loop.ts +45 -1
  364. package/src/resources/extensions/gsd/auto/phases.ts +6 -0
  365. package/src/resources/extensions/gsd/auto/session.ts +11 -0
  366. package/src/resources/extensions/gsd/auto-dashboard.ts +29 -18
  367. package/src/resources/extensions/gsd/auto-model-selection.ts +9 -1
  368. package/src/resources/extensions/gsd/auto-prompts.ts +111 -33
  369. package/src/resources/extensions/gsd/auto-start.ts +41 -7
  370. package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
  371. package/src/resources/extensions/gsd/auto-worktree.ts +1 -1
  372. package/src/resources/extensions/gsd/auto.ts +72 -0
  373. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
  374. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +2 -0
  375. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +79 -60
  376. package/src/resources/extensions/gsd/bootstrap/system-context.ts +7 -0
  377. package/src/resources/extensions/gsd/commands/context.ts +16 -5
  378. package/src/resources/extensions/gsd/commands/dispatcher.ts +14 -2
  379. package/src/resources/extensions/gsd/commands/handlers/auto.ts +10 -36
  380. package/src/resources/extensions/gsd/commands/handlers/core.ts +58 -11
  381. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +17 -7
  382. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +4 -10
  383. package/src/resources/extensions/gsd/dashboard-overlay.ts +10 -3
  384. package/src/resources/extensions/gsd/dispatch-guard.ts +18 -1
  385. package/src/resources/extensions/gsd/doctor-providers.ts +24 -0
  386. package/src/resources/extensions/gsd/error-classifier.ts +5 -2
  387. package/src/resources/extensions/gsd/forensics.ts +23 -7
  388. package/src/resources/extensions/gsd/gate-registry.ts +251 -0
  389. package/src/resources/extensions/gsd/gsd-db.ts +51 -0
  390. package/src/resources/extensions/gsd/guided-flow.ts +5 -10
  391. package/src/resources/extensions/gsd/interrupted-session.ts +1 -0
  392. package/src/resources/extensions/gsd/metrics.ts +12 -1
  393. package/src/resources/extensions/gsd/milestone-actions.ts +10 -3
  394. package/src/resources/extensions/gsd/milestone-validation-gates.ts +11 -13
  395. package/src/resources/extensions/gsd/notification-overlay.ts +47 -14
  396. package/src/resources/extensions/gsd/notification-store.ts +54 -5
  397. package/src/resources/extensions/gsd/notification-widget.ts +5 -14
  398. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -3
  399. package/src/resources/extensions/gsd/pre-execution-checks.ts +39 -2
  400. package/src/resources/extensions/gsd/prompt-validation.ts +157 -0
  401. package/src/resources/extensions/gsd/prompts/complete-slice.md +5 -3
  402. package/src/resources/extensions/gsd/prompts/discuss.md +2 -0
  403. package/src/resources/extensions/gsd/prompts/execute-task.md +22 -19
  404. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  405. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
  406. package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  407. package/src/resources/extensions/gsd/prompts/queue.md +3 -2
  408. package/src/resources/extensions/gsd/prompts/system.md +1 -0
  409. package/src/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
  410. package/src/resources/extensions/gsd/session-model-override.ts +36 -0
  411. package/src/resources/extensions/gsd/shortcut-defs.ts +56 -0
  412. package/src/resources/extensions/gsd/state.ts +13 -2
  413. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +25 -9
  414. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +28 -0
  415. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +39 -0
  416. package/src/resources/extensions/gsd/tests/complete-slice-gate-closure.test.ts +167 -0
  417. package/src/resources/extensions/gsd/tests/complete-slice-prompt-task-summary-layout.test.ts +18 -0
  418. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
  419. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +36 -0
  420. package/src/resources/extensions/gsd/tests/execute-task-prompt-existing-artifact-guard.test.ts +33 -0
  421. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +62 -0
  422. package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +31 -0
  423. package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +27 -0
  424. package/src/resources/extensions/gsd/tests/gate-registry.test.ts +140 -0
  425. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +73 -0
  426. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +180 -0
  427. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +66 -1
  428. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +36 -51
  429. package/src/resources/extensions/gsd/tests/notification-store.test.ts +35 -0
  430. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +26 -0
  431. package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +90 -0
  432. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +1 -0
  433. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +18 -0
  434. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +49 -0
  435. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +19 -0
  436. package/src/resources/extensions/gsd/tests/prompt-system-gate-coverage.test.ts +208 -0
  437. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +16 -0
  438. package/src/resources/extensions/gsd/tests/register-shortcuts.test.ts +63 -5
  439. package/src/resources/extensions/gsd/tests/session-model-override.test.ts +35 -0
  440. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +90 -0
  441. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +7 -0
  442. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +18 -0
  443. package/src/resources/extensions/gsd/tools/complete-slice.ts +63 -0
  444. package/src/resources/extensions/gsd/tools/complete-task.ts +63 -0
  445. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +4 -1
  446. package/src/resources/extensions/gsd/types.ts +26 -0
  447. package/src/resources/extensions/ollama/index.ts +13 -3
  448. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +28 -0
  449. package/src/resources/extensions/shared/gsd-phase-state.ts +42 -0
  450. package/src/resources/extensions/shared/tests/gsd-phase-state.test.ts +48 -0
  451. package/src/resources/extensions/subagent/agents.ts +10 -0
  452. package/src/resources/extensions/subagent/index.ts +18 -0
  453. package/src/resources/extensions/subagent/tests/agents-conflicts.test.ts +33 -0
  454. package/src/resources/skills/create-skill/SKILL.md +2 -0
  455. package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
  456. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  457. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  458. /package/dist/web/standalone/.next/static/{nPky_WQC28aBD77eZsRAB → f-Gremw0nLxxFUySaHRPw}/_buildManifest.js +0 -0
  459. /package/dist/web/standalone/.next/static/{nPky_WQC28aBD77eZsRAB → f-Gremw0nLxxFUySaHRPw}/_ssgManifest.js +0 -0
@@ -919,12 +919,12 @@ export function registerDbTools(pi) {
919
919
  const saveGateResultTool = {
920
920
  name: "gsd_save_gate_result",
921
921
  label: "Save Gate Result",
922
- description: "Save the result of a quality gate evaluation (Q3-Q8) to the GSD database. " +
922
+ description: "Save the result of a quality gate evaluation (Q3-Q8 or MV01-MV04) to the GSD database. " +
923
923
  "Called by gate evaluation sub-agents after analyzing a specific quality question.",
924
924
  promptSnippet: "Save quality gate evaluation result (verdict, rationale, findings)",
925
925
  promptGuidelines: [
926
926
  "Use gsd_save_gate_result after evaluating a quality gate question.",
927
- "gateId must be one of: Q3, Q4, Q5, Q6, Q7, Q8.",
927
+ "gateId must be one of: Q3, Q4, Q5, Q6, Q7, Q8, MV01, MV02, MV03, MV04.",
928
928
  "verdict must be: pass (no concerns), flag (concerns found), or omitted (not applicable).",
929
929
  "rationale should be a one-sentence justification for the verdict.",
930
930
  "findings should contain detailed markdown analysis (or empty string if omitted).",
@@ -932,7 +932,7 @@ export function registerDbTools(pi) {
932
932
  parameters: Type.Object({
933
933
  milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
934
934
  sliceId: Type.String({ description: "Slice ID (e.g. S01)" }),
935
- gateId: Type.String({ description: "Gate ID: Q3, Q4, Q5, Q6, Q7, or Q8" }),
935
+ gateId: Type.String({ description: "Gate ID: Q3, Q4, Q5, Q6, Q7, Q8, MV01, MV02, MV03, or MV04" }),
936
936
  taskId: Type.Optional(Type.String({ description: "Task ID for task-scoped gates (Q5/Q6/Q7)" })),
937
937
  verdict: Type.String({ description: "pass, flag, or omitted" }),
938
938
  rationale: Type.String({ description: "One-sentence justification" }),
@@ -111,6 +111,8 @@ export function registerHooks(pi) {
111
111
  return { cancel: true };
112
112
  }
113
113
  const basePath = process.cwd();
114
+ const { ensureDbOpen } = await import("./dynamic-tools.js");
115
+ await ensureDbOpen();
114
116
  const state = await deriveState(basePath);
115
117
  if (!state.activeMilestone || !state.activeSlice || !state.activeTask)
116
118
  return;
@@ -4,61 +4,73 @@ import { Key } from "@gsd/pi-tui";
4
4
  import { GSDDashboardOverlay } from "../dashboard-overlay.js";
5
5
  import { GSDNotificationOverlay } from "../notification-overlay.js";
6
6
  import { ParallelMonitorOverlay } from "../parallel-monitor-overlay.js";
7
+ import { GSD_SHORTCUTS } from "../shortcut-defs.js";
7
8
  import { projectRoot } from "../commands/context.js";
8
9
  import { shortcutDesc } from "../../shared/mod.js";
9
10
  export function registerShortcuts(pi) {
10
- pi.registerShortcut(Key.ctrlAlt("g"), {
11
- description: shortcutDesc("Open GSD dashboard", "/gsd status"),
12
- handler: async (ctx) => {
13
- const basePath = projectRoot();
14
- if (!existsSync(join(basePath, ".gsd"))) {
15
- ctx.ui.notify("No .gsd/ directory found. Run /gsd to start.", "info");
16
- return;
17
- }
18
- await ctx.ui.custom((tui, theme, _kb, done) => new GSDDashboardOverlay(tui, theme, () => done(true)), {
19
- overlay: true,
20
- overlayOptions: {
21
- width: "90%",
22
- minWidth: 80,
23
- maxHeight: "92%",
24
- anchor: "center",
25
- },
26
- });
27
- },
11
+ const overlayOptions = {
12
+ width: "90%",
13
+ minWidth: 80,
14
+ maxHeight: "92%",
15
+ anchor: "center",
16
+ };
17
+ const openDashboardOverlay = async (ctx) => {
18
+ const basePath = projectRoot();
19
+ if (!existsSync(join(basePath, ".gsd"))) {
20
+ ctx.ui.notify("No .gsd/ directory found. Run /gsd to start.", "info");
21
+ return;
22
+ }
23
+ await ctx.ui.custom((tui, theme, _kb, done) => new GSDDashboardOverlay(tui, theme, () => done(true)), {
24
+ overlay: true,
25
+ overlayOptions,
26
+ });
27
+ };
28
+ const openNotificationsOverlay = async (ctx) => {
29
+ await ctx.ui.custom((tui, theme, _kb, done) => new GSDNotificationOverlay(tui, theme, () => done(true)), {
30
+ overlay: true,
31
+ overlayOptions: {
32
+ width: "80%",
33
+ minWidth: 60,
34
+ maxHeight: "88%",
35
+ anchor: "center",
36
+ backdrop: true,
37
+ },
38
+ });
39
+ };
40
+ const openParallelOverlay = async (ctx) => {
41
+ const basePath = projectRoot();
42
+ const parallelDir = join(basePath, ".gsd", "parallel");
43
+ if (!existsSync(parallelDir)) {
44
+ ctx.ui.notify("No parallel workers found. Run /gsd parallel start first.", "info");
45
+ return;
46
+ }
47
+ await ctx.ui.custom((tui, theme, _kb, done) => new ParallelMonitorOverlay(tui, theme, () => done(true), basePath), {
48
+ overlay: true,
49
+ overlayOptions,
50
+ });
51
+ };
52
+ pi.registerShortcut(Key.ctrlAlt(GSD_SHORTCUTS.dashboard.key), {
53
+ description: shortcutDesc(GSD_SHORTCUTS.dashboard.action, GSD_SHORTCUTS.dashboard.command),
54
+ handler: openDashboardOverlay,
28
55
  });
29
- pi.registerShortcut(Key.ctrlAlt("n"), {
30
- description: shortcutDesc("Open notification history", "/gsd notifications"),
31
- handler: async (ctx) => {
32
- await ctx.ui.custom((tui, theme, _kb, done) => new GSDNotificationOverlay(tui, theme, () => done(true)), {
33
- overlay: true,
34
- overlayOptions: {
35
- width: "80%",
36
- minWidth: 60,
37
- maxHeight: "88%",
38
- anchor: "center",
39
- backdrop: true,
40
- },
41
- });
42
- },
56
+ // Fallback for terminals where Ctrl+Alt letter chords are not forwarded reliably.
57
+ pi.registerShortcut(Key.ctrlShift(GSD_SHORTCUTS.dashboard.key), {
58
+ description: shortcutDesc(`${GSD_SHORTCUTS.dashboard.action} (fallback)`, GSD_SHORTCUTS.dashboard.command),
59
+ handler: openDashboardOverlay,
43
60
  });
44
- pi.registerShortcut(Key.ctrlAlt("p"), {
45
- description: shortcutDesc("Open parallel worker monitor", "/gsd parallel watch"),
46
- handler: async (ctx) => {
47
- const basePath = projectRoot();
48
- const parallelDir = join(basePath, ".gsd", "parallel");
49
- if (!existsSync(parallelDir)) {
50
- ctx.ui.notify("No parallel workers found. Run /gsd parallel start first.", "info");
51
- return;
52
- }
53
- await ctx.ui.custom((tui, theme, _kb, done) => new ParallelMonitorOverlay(tui, theme, () => done(true)), {
54
- overlay: true,
55
- overlayOptions: {
56
- width: "90%",
57
- minWidth: 80,
58
- maxHeight: "92%",
59
- anchor: "center",
60
- },
61
- });
62
- },
61
+ pi.registerShortcut(Key.ctrlAlt(GSD_SHORTCUTS.notifications.key), {
62
+ description: shortcutDesc(GSD_SHORTCUTS.notifications.action, GSD_SHORTCUTS.notifications.command),
63
+ handler: openNotificationsOverlay,
63
64
  });
65
+ // Fallback for terminals where Ctrl+Alt letter chords are not forwarded reliably.
66
+ pi.registerShortcut(Key.ctrlShift(GSD_SHORTCUTS.notifications.key), {
67
+ description: shortcutDesc(`${GSD_SHORTCUTS.notifications.action} (fallback)`, GSD_SHORTCUTS.notifications.command),
68
+ handler: openNotificationsOverlay,
69
+ });
70
+ pi.registerShortcut(Key.ctrlAlt(GSD_SHORTCUTS.parallel.key), {
71
+ description: shortcutDesc(GSD_SHORTCUTS.parallel.action, GSD_SHORTCUTS.parallel.command),
72
+ handler: openParallelOverlay,
73
+ });
74
+ // No Ctrl+Shift+P fallback — conflicts with cycleModelBackward (shift+ctrl+p).
75
+ // Use Ctrl+Alt+P or /gsd parallel watch instead.
64
76
  }
@@ -257,6 +257,10 @@ function buildWorktreeContextBlock() {
257
257
  */
258
258
  const RESUME_INTENT_PATTERNS = /^(continue|resume|ok|go|go ahead|proceed|keep going|carry on|next|yes|yeah|yep|sure|do it|let's go|pick up where you left off)$/;
259
259
  async function buildGuidedExecuteContextInjection(prompt, basePath) {
260
+ const ensureStateDbOpen = async () => {
261
+ const { ensureDbOpen } = await import("./dynamic-tools.js");
262
+ await ensureDbOpen();
263
+ };
260
264
  const executeMatch = prompt.match(/Execute the next task:\s+(T\d+)\s+\("([^"]+)"\)\s+in slice\s+(S\d+)\s+of milestone\s+(M\d+(?:-[a-z0-9]{6})?)/i);
261
265
  if (executeMatch) {
262
266
  const [, taskId, taskTitle, sliceId, milestoneId] = executeMatch;
@@ -265,6 +269,7 @@ async function buildGuidedExecuteContextInjection(prompt, basePath) {
265
269
  const resumeMatch = prompt.match(/Resume interrupted work\.[\s\S]*?slice\s+(S\d+)\s+of milestone\s+(M\d+(?:-[a-z0-9]{6})?)/i);
266
270
  if (resumeMatch) {
267
271
  const [, sliceId, milestoneId] = resumeMatch;
272
+ await ensureStateDbOpen();
268
273
  const state = await deriveState(basePath);
269
274
  if (state.activeMilestone?.id === milestoneId && state.activeSlice?.id === sliceId && state.activeTask) {
270
275
  return buildTaskExecutionContextInjection(basePath, milestoneId, sliceId, state.activeTask.id, state.activeTask.title);
@@ -279,6 +284,7 @@ async function buildGuidedExecuteContextInjection(prompt, basePath) {
279
284
  // replanning, gate evaluation, or other non-execution phases.
280
285
  const trimmed = prompt.trim().toLowerCase().replace(/[.!?,]+$/g, "");
281
286
  if (RESUME_INTENT_PATTERNS.test(trimmed)) {
287
+ await ensureStateDbOpen();
282
288
  const state = await deriveState(basePath);
283
289
  if (state.phase === "executing" && state.activeTask && state.activeMilestone && state.activeSlice) {
284
290
  return buildTaskExecutionContextInjection(basePath, state.activeMilestone.id, state.activeSlice.id, state.activeTask.id, state.activeTask.title);
@@ -1,8 +1,18 @@
1
1
  import { checkRemoteAutoSession, isAutoActive, isAutoPaused, stopAutoRemote } from "../auto.js";
2
- import { assertSafeDirectory } from "../validate-directory.js";
2
+ import { validateDirectory } from "../validate-directory.js";
3
3
  import { resolveProjectRoot } from "../worktree.js";
4
4
  import { showNextAction } from "../../shared/tui.js";
5
5
  import { handleStatus } from "./handlers/core.js";
6
+ /**
7
+ * Typed error for when GSD is run outside a valid project directory.
8
+ * Command handlers catch this to show a friendly message instead of a raw exception.
9
+ */
10
+ export class GSDNoProjectError extends Error {
11
+ constructor(reason) {
12
+ super(reason);
13
+ this.name = "GSDNoProjectError";
14
+ }
15
+ }
6
16
  export function projectRoot() {
7
17
  let cwd;
8
18
  try {
@@ -13,11 +23,10 @@ export function projectRoot() {
13
23
  cwd = process.env.HOME ?? "/";
14
24
  }
15
25
  const root = resolveProjectRoot(cwd);
16
- if (root !== cwd) {
17
- assertSafeDirectory(cwd);
18
- }
19
- else {
20
- assertSafeDirectory(root);
26
+ const pathToCheck = root !== cwd ? cwd : root;
27
+ const result = validateDirectory(pathToCheck);
28
+ if (result.severity === "blocked") {
29
+ throw new GSDNoProjectError(result.reason ?? "GSD must be run inside a project directory.");
21
30
  }
22
31
  return root;
23
32
  }
@@ -1,3 +1,4 @@
1
+ import { GSDNoProjectError } from "./context.js";
1
2
  import { handleAutoCommand } from "./handlers/auto.js";
2
3
  import { handleCoreCommand } from "./handlers/core.js";
3
4
  import { handleOpsCommand } from "./handlers/ops.js";
@@ -12,10 +13,19 @@ export async function handleGSDCommand(args, ctx, pi) {
12
13
  () => handleWorkflowCommand(trimmed, ctx, pi),
13
14
  () => handleOpsCommand(trimmed, ctx, pi),
14
15
  ];
15
- for (const handler of handlers) {
16
- if (await handler()) {
16
+ try {
17
+ for (const handler of handlers) {
18
+ if (await handler()) {
19
+ return;
20
+ }
21
+ }
22
+ }
23
+ catch (err) {
24
+ if (err instanceof GSDNoProjectError) {
25
+ ctx.ui.notify(`${err.message} \`cd\` into a project directory first.`, "warning");
17
26
  return;
18
27
  }
28
+ throw err;
19
29
  }
20
30
  ctx.ui.notify(`Unknown: /gsd ${trimmed}. Run /gsd help for available commands.`, "warning");
21
31
  }
@@ -1,7 +1,7 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { resolve } from "node:path";
3
3
  import { enableDebug } from "../../debug-logger.js";
4
- import { isAutoActive, isAutoPaused, pauseAuto, startAuto, stopAuto, stopAutoRemote } from "../../auto.js";
4
+ import { isAutoActive, isAutoPaused, pauseAuto, startAutoDetached, stopAuto, stopAutoRemote } from "../../auto.js";
5
5
  import { handleRate } from "../../commands-rate.js";
6
6
  import { guardRemoteSession, projectRoot } from "../context.js";
7
7
  import { findMilestoneIds } from "../../milestone-id-utils.js";
@@ -36,27 +36,6 @@ export function parseMilestoneTarget(input) {
36
36
  const rest = input.replace(match[0], "").replace(/\s+/g, " ").trim();
37
37
  return { milestoneId: match[1], rest };
38
38
  }
39
- /**
40
- * Set GSD_MILESTONE_LOCK to target a specific milestone, then run `fn`.
41
- * Clears the env var when `fn` resolves or rejects, so the lock does not
42
- * leak into subsequent commands in the same process.
43
- */
44
- async function withMilestoneLock(milestoneId, fn) {
45
- const previous = process.env.GSD_MILESTONE_LOCK;
46
- process.env.GSD_MILESTONE_LOCK = milestoneId;
47
- try {
48
- await fn();
49
- }
50
- finally {
51
- // Restore previous value (undefined → delete, else restore).
52
- if (previous === undefined) {
53
- delete process.env.GSD_MILESTONE_LOCK;
54
- }
55
- else {
56
- process.env.GSD_MILESTONE_LOCK = previous;
57
- }
58
- }
59
- }
60
39
  export async function handleAutoCommand(trimmed, ctx, pi) {
61
40
  if (trimmed === "next" || trimmed.startsWith("next ")) {
62
41
  if (trimmed.includes("--dry-run")) {
@@ -79,12 +58,10 @@ export async function handleAutoCommand(trimmed, ctx, pi) {
79
58
  return true;
80
59
  }
81
60
  }
82
- if (milestoneId) {
83
- await withMilestoneLock(milestoneId, () => startAuto(ctx, pi, projectRoot(), verboseMode, { step: true }));
84
- }
85
- else {
86
- await startAuto(ctx, pi, projectRoot(), verboseMode, { step: true });
87
- }
61
+ startAutoDetached(ctx, pi, projectRoot(), verboseMode, {
62
+ step: true,
63
+ milestoneLock: milestoneId,
64
+ });
88
65
  return true;
89
66
  }
90
67
  if (trimmed === "auto" || trimmed.startsWith("auto ")) {
@@ -122,12 +99,12 @@ export async function handleAutoCommand(trimmed, ctx, pi) {
122
99
  await showHeadlessMilestoneCreation(ctx, pi, projectRoot(), seedContent);
123
100
  }
124
101
  else if (milestoneId) {
125
- // Target a specific milestone — use GSD_MILESTONE_LOCK so state
126
- // derivation only sees this milestone (#2521).
127
- await withMilestoneLock(milestoneId, () => startAuto(ctx, pi, projectRoot(), verboseMode));
102
+ startAutoDetached(ctx, pi, projectRoot(), verboseMode, {
103
+ milestoneLock: milestoneId,
104
+ });
128
105
  }
129
106
  else {
130
- await startAuto(ctx, pi, projectRoot(), verboseMode);
107
+ startAutoDetached(ctx, pi, projectRoot(), verboseMode);
131
108
  }
132
109
  return true;
133
110
  }
@@ -168,7 +145,7 @@ export async function handleAutoCommand(trimmed, ctx, pi) {
168
145
  if (trimmed === "") {
169
146
  if (!(await guardRemoteSession(ctx, pi)))
170
147
  return true;
171
- await startAuto(ctx, pi, projectRoot(), false, { step: true });
148
+ startAutoDetached(ctx, pi, projectRoot(), false, { step: true });
172
149
  return true;
173
150
  }
174
151
  return false;
@@ -4,10 +4,43 @@ import { ensurePreferencesFile, handlePrefs, handlePrefsMode, handlePrefsWizard
4
4
  import { runEnvironmentChecks } from "../../doctor-environment.js";
5
5
  import { deriveState } from "../../state.js";
6
6
  import { handleCmux } from "../../commands-cmux.js";
7
+ import { setSessionModelOverride } from "../../session-model-override.js";
7
8
  import { projectRoot } from "../context.js";
8
- import { formatShortcut } from "../../files.js";
9
- export function showHelp(ctx) {
10
- const lines = [
9
+ import { formattedShortcutPair } from "../../shortcut-defs.js";
10
+ export function showHelp(ctx, args = "") {
11
+ const summaryLines = [
12
+ "GSD — Get Shit Done\n",
13
+ "QUICK START",
14
+ " /gsd start <tpl> Start a workflow template",
15
+ " /gsd Run next unit (same as /gsd next)",
16
+ " /gsd auto Run all queued units continuously",
17
+ " /gsd pause Pause auto-mode",
18
+ " /gsd stop Stop auto-mode gracefully",
19
+ "",
20
+ "VISIBILITY",
21
+ ` /gsd status Dashboard (${formattedShortcutPair("dashboard")})`,
22
+ ` /gsd parallel watch Parallel monitor (${formattedShortcutPair("parallel")})`,
23
+ ` /gsd notifications Notification history (${formattedShortcutPair("notifications")})`,
24
+ " /gsd visualize Interactive 10-tab TUI",
25
+ " /gsd queue Show queued/dispatched units",
26
+ "",
27
+ "COURSE CORRECTION",
28
+ " /gsd steer <desc> Apply user override to active work",
29
+ " /gsd capture <text> Quick-capture a thought to CAPTURES.md",
30
+ " /gsd triage Classify and route pending captures",
31
+ " /gsd undo Revert last completed unit [--force]",
32
+ " /gsd rethink Conversational project reorganization",
33
+ "",
34
+ "SETUP",
35
+ " /gsd init Project init wizard",
36
+ " /gsd setup Global setup status [llm|search|remote|keys|prefs]",
37
+ " /gsd model Switch active session model",
38
+ " /gsd prefs Manage preferences",
39
+ " /gsd doctor Diagnose and repair .gsd/ state",
40
+ "",
41
+ "Use /gsd help full for the complete command reference.",
42
+ ];
43
+ const fullLines = [
11
44
  "GSD — Get Shit Done\n",
12
45
  "WORKFLOW",
13
46
  " /gsd start <tpl> Start a workflow template (bugfix, spike, feature, hotfix, etc.)",
@@ -21,12 +54,13 @@ export function showHelp(ctx) {
21
54
  " /gsd new-milestone Create milestone from headless context (used by gsd headless)",
22
55
  "",
23
56
  "VISIBILITY",
24
- ` /gsd status Show progress dashboard (${formatShortcut("Ctrl+Alt+G")})`,
57
+ ` /gsd status Show progress dashboard (${formattedShortcutPair("dashboard")})`,
58
+ ` /gsd parallel watch Open parallel worker monitor (${formattedShortcutPair("parallel")})`,
25
59
  " /gsd visualize Interactive 10-tab TUI (progress, timeline, deps, metrics, health, agent, changes, knowledge, captures, export)",
26
60
  " /gsd queue Show queued/dispatched units and execution order",
27
61
  " /gsd history View execution history [--cost] [--phase] [--model] [N]",
28
62
  " /gsd changelog Show categorized release notes [version]",
29
- ` /gsd notifications View persistent notification history [clear|tail|filter] (${formatShortcut("Ctrl+Alt+N")})`,
63
+ ` /gsd notifications View persistent notification history [clear|tail|filter] (${formattedShortcutPair("notifications")})`,
30
64
  "",
31
65
  "COURSE CORRECTION",
32
66
  " /gsd steer <desc> Apply user override to active work",
@@ -66,7 +100,8 @@ export function showHelp(ctx) {
66
100
  " /gsd inspect Show SQLite DB diagnostics (schema, row counts, recent entries)",
67
101
  " /gsd update Update GSD to the latest version via npm",
68
102
  ];
69
- ctx.ui.notify(lines.join("\n"), "info");
103
+ const full = ["full", "--full", "all"].includes(args.trim().toLowerCase());
104
+ ctx.ui.notify((full ? fullLines : summaryLines).join("\n"), "info");
70
105
  }
71
106
  export async function handleStatus(ctx) {
72
107
  const basePath = projectRoot();
@@ -82,9 +117,9 @@ export async function handleStatus(ctx) {
82
117
  const result = await ctx.ui.custom((tui, theme, _kb, done) => new GSDDashboardOverlay(tui, theme, () => done(true)), {
83
118
  overlay: true,
84
119
  overlayOptions: {
85
- width: "70%",
86
- minWidth: 60,
87
- maxHeight: "90%",
120
+ width: "90%",
121
+ minWidth: 80,
122
+ maxHeight: "92%",
88
123
  anchor: "center",
89
124
  },
90
125
  });
@@ -251,11 +286,21 @@ async function handleModel(trimmedArgs, ctx, pi) {
251
286
  ctx.ui.notify(`No API key for ${targetModel.provider}/${targetModel.id}`, "warning");
252
287
  return;
253
288
  }
289
+ // /gsd model is an explicit per-session pin for GSD dispatches.
290
+ // This is captured at auto bootstrap so it survives internal session
291
+ // switches during /gsd auto and /gsd next runs.
292
+ const sessionId = ctx.sessionManager?.getSessionId?.();
293
+ if (sessionId) {
294
+ setSessionModelOverride(sessionId, {
295
+ provider: targetModel.provider,
296
+ id: targetModel.id,
297
+ });
298
+ }
254
299
  ctx.ui.notify(`Model: ${targetModel.provider}/${targetModel.id}`, "info");
255
300
  }
256
301
  export async function handleCoreCommand(trimmed, ctx, pi) {
257
- if (trimmed === "help" || trimmed === "h" || trimmed === "?") {
258
- showHelp(ctx);
302
+ if (trimmed === "help" || trimmed === "h" || trimmed === "?" || trimmed.startsWith("help ")) {
303
+ showHelp(ctx, trimmed.startsWith("help ") ? trimmed.slice(5).trim() : "");
259
304
  return true;
260
305
  }
261
306
  if (trimmed === "status") {
@@ -2,6 +2,7 @@
2
2
  // View, filter, and clear the persistent notification history.
3
3
  import { readNotifications, clearNotifications, getUnreadCount, suppressPersistence, unsuppressPersistence, } from "../../notification-store.js";
4
4
  import { GSDNotificationOverlay } from "../../notification-overlay.js";
5
+ const MAX_INLINE_ENTRIES = 40;
5
6
  function severityIcon(severity) {
6
7
  switch (severity) {
7
8
  case "error": return "✗";
@@ -38,14 +39,18 @@ export async function handleNotificationsCommand(args, ctx, pi) {
38
39
  if (args === "tail" || args.startsWith("tail ")) {
39
40
  const countStr = args.replace(/^tail\s*/, "").trim();
40
41
  const count = countStr ? parseInt(countStr, 10) : 20;
41
- const n = isNaN(count) || count < 1 ? 20 : Math.min(count, 100);
42
- const entries = readNotifications().slice(0, n);
42
+ const all = readNotifications();
43
+ const n = isNaN(count) || count < 1 ? 20 : Math.min(count, MAX_INLINE_ENTRIES);
44
+ const entries = all.slice(0, n);
43
45
  if (entries.length === 0) {
44
46
  ctx.ui.notify("No notifications.", "info");
45
47
  return true;
46
48
  }
47
49
  const lines = entries.map((e) => `${severityIcon(e.severity)} [${formatTimestamp(e.ts)}] ${e.message}`);
48
- ctx.ui.notify(`Last ${entries.length} notification(s):\n${lines.join("\n")}`, "info");
50
+ const suffix = all.length > entries.length
51
+ ? `\n... and ${all.length - entries.length} more (open /gsd notifications to browse all)`
52
+ : "";
53
+ ctx.ui.notify(`Last ${entries.length} notification(s):\n${lines.join("\n")}${suffix}`, "info");
49
54
  return true;
50
55
  }
51
56
  // /gsd notifications filter <severity>
@@ -61,7 +66,9 @@ export async function handleNotificationsCommand(args, ctx, pi) {
61
66
  return true;
62
67
  }
63
68
  const lines = entries.slice(0, 20).map((e) => `${severityIcon(e.severity)} [${formatTimestamp(e.ts)}] ${e.message}`);
64
- const suffix = entries.length > 20 ? `\n... and ${entries.length - 20} more` : "";
69
+ const suffix = entries.length > 20
70
+ ? `\n... and ${entries.length - 20} more (open /gsd notifications to browse all)`
71
+ : "";
65
72
  ctx.ui.notify(`${severity} notifications (${entries.length}):\n${lines.join("\n")}${suffix}`, "info");
66
73
  return true;
67
74
  }
@@ -70,7 +77,7 @@ export async function handleNotificationsCommand(args, ctx, pi) {
70
77
  // Try overlay first (TUI mode)
71
78
  if (ctx.hasUI) {
72
79
  try {
73
- await ctx.ui.custom((tui, theme, _kb, done) => new GSDNotificationOverlay(tui, theme, () => done()), {
80
+ const result = await ctx.ui.custom((tui, theme, _kb, done) => new GSDNotificationOverlay(tui, theme, () => done(true)), {
74
81
  overlay: true,
75
82
  overlayOptions: {
76
83
  width: "80%",
@@ -80,7 +87,9 @@ export async function handleNotificationsCommand(args, ctx, pi) {
80
87
  backdrop: true,
81
88
  },
82
89
  });
83
- return true;
90
+ if (result !== undefined) {
91
+ return true;
92
+ }
84
93
  }
85
94
  catch {
86
95
  // Fall through to text output if overlay fails
@@ -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"