gsd-pi 2.70.1 → 2.71.0-dev.4c35d99

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 (533) 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 +242 -40
  22. package/dist/resources/extensions/get-secrets-from-user.js +17 -1
  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 +37 -18
  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 +6 -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/custom-workflow-engine.js +16 -12
  45. package/dist/resources/extensions/gsd/dashboard-overlay.js +8 -3
  46. package/dist/resources/extensions/gsd/dispatch-guard.js +18 -1
  47. package/dist/resources/extensions/gsd/doctor-providers.js +23 -0
  48. package/dist/resources/extensions/gsd/error-classifier.js +1 -1
  49. package/dist/resources/extensions/gsd/file-lock.js +60 -0
  50. package/dist/resources/extensions/gsd/forensics.js +19 -6
  51. package/dist/resources/extensions/gsd/gate-registry.js +208 -0
  52. package/dist/resources/extensions/gsd/gsd-db.js +41 -0
  53. package/dist/resources/extensions/gsd/guided-flow.js +17 -20
  54. package/dist/resources/extensions/gsd/init-wizard.js +3 -11
  55. package/dist/resources/extensions/gsd/metrics.js +1 -0
  56. package/dist/resources/extensions/gsd/milestone-actions.js +10 -4
  57. package/dist/resources/extensions/gsd/milestone-validation-gates.js +11 -12
  58. package/dist/resources/extensions/gsd/notification-overlay.js +42 -13
  59. package/dist/resources/extensions/gsd/notification-store.js +56 -5
  60. package/dist/resources/extensions/gsd/notification-widget.js +5 -13
  61. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +8 -3
  62. package/dist/resources/extensions/gsd/pre-execution-checks.js +35 -2
  63. package/dist/resources/extensions/gsd/prompt-validation.js +126 -0
  64. package/dist/resources/extensions/gsd/prompts/complete-slice.md +5 -3
  65. package/dist/resources/extensions/gsd/prompts/discuss.md +33 -13
  66. package/dist/resources/extensions/gsd/prompts/execute-task.md +22 -19
  67. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  68. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
  69. package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  70. package/dist/resources/extensions/gsd/prompts/queue.md +3 -2
  71. package/dist/resources/extensions/gsd/prompts/system.md +1 -0
  72. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
  73. package/dist/resources/extensions/gsd/session-model-override.js +25 -0
  74. package/dist/resources/extensions/gsd/shortcut-defs.js +40 -0
  75. package/dist/resources/extensions/gsd/state.js +241 -332
  76. package/dist/resources/extensions/gsd/tools/complete-slice.js +52 -1
  77. package/dist/resources/extensions/gsd/tools/complete-task.js +51 -1
  78. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +38 -1
  79. package/dist/resources/extensions/gsd/workflow-events.js +25 -13
  80. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +56 -0
  81. package/dist/resources/extensions/gsd/workflow-mcp.js +1 -1
  82. package/dist/resources/extensions/ollama/index.js +13 -5
  83. package/dist/resources/extensions/shared/gsd-phase-state.js +35 -0
  84. package/dist/resources/extensions/subagent/agents.js +8 -0
  85. package/dist/resources/extensions/subagent/index.js +17 -0
  86. package/dist/resources/skills/create-skill/SKILL.md +2 -0
  87. package/dist/startup-model-validation.d.ts +0 -1
  88. package/dist/startup-model-validation.js +6 -2
  89. package/dist/web/standalone/.next/BUILD_ID +1 -1
  90. package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
  91. package/dist/web/standalone/.next/build-manifest.json +4 -4
  92. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  93. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  94. package/dist/web/standalone/.next/required-server-files.json +3 -3
  95. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  96. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  106. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  109. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  110. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  112. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  122. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  134. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  154. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  164. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  170. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  186. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
  190. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/index.html +1 -1
  200. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  201. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  202. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  203. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  204. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  205. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  206. package/dist/web/standalone/.next/server/app/page.js +2 -2
  207. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/app-paths-manifest.json +17 -17
  209. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  210. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  211. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/middleware.js +2 -2
  214. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  215. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  216. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  217. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  218. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  219. package/dist/web/standalone/.next/static/chunks/2826.dd3dc8bbd3025fa5.js +9 -0
  220. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  221. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  222. package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +1 -0
  223. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  224. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  225. package/dist/web/standalone/.next/static/chunks/{webpack-6e4d7e9a4f57bed4.js → webpack-b868033a5834586d.js} +1 -1
  226. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  227. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  228. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  229. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  230. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  231. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  232. package/dist/web/standalone/server.js +1 -1
  233. package/package.json +1 -1
  234. package/packages/mcp-server/dist/env-writer.d.ts +39 -0
  235. package/packages/mcp-server/dist/env-writer.d.ts.map +1 -0
  236. package/packages/mcp-server/dist/env-writer.js +158 -0
  237. package/packages/mcp-server/dist/env-writer.js.map +1 -0
  238. package/packages/mcp-server/dist/server.d.ts +23 -3
  239. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  240. package/packages/mcp-server/dist/server.js +192 -44
  241. package/packages/mcp-server/dist/server.js.map +1 -1
  242. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  243. package/packages/mcp-server/dist/workflow-tools.js +22 -12
  244. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  245. package/packages/mcp-server/src/env-writer.test.ts +280 -0
  246. package/packages/mcp-server/src/env-writer.ts +183 -0
  247. package/packages/mcp-server/src/secure-env-collect.test.ts +265 -0
  248. package/packages/mcp-server/src/server.ts +247 -41
  249. package/packages/mcp-server/src/workflow-tools.test.ts +110 -0
  250. package/packages/mcp-server/src/workflow-tools.ts +32 -12
  251. package/packages/pi-ai/dist/providers/amazon-bedrock.js +11 -2
  252. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  253. package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts +2 -0
  254. package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts.map +1 -0
  255. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +20 -0
  256. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -0
  257. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts +4 -1
  258. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  259. package/packages/pi-ai/dist/providers/anthropic-shared.js +8 -3
  260. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  261. package/packages/pi-ai/dist/providers/anthropic-shared.test.js +44 -1
  262. package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -1
  263. package/packages/pi-ai/dist/providers/anthropic.d.ts +2 -1
  264. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  265. package/packages/pi-ai/dist/providers/anthropic.js +7 -4
  266. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  267. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  268. package/packages/pi-ai/dist/providers/openai-completions.js +11 -0
  269. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  270. package/packages/pi-ai/src/providers/amazon-bedrock.ts +13 -1
  271. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +32 -0
  272. package/packages/pi-ai/src/providers/anthropic-shared.test.ts +55 -1
  273. package/packages/pi-ai/src/providers/anthropic-shared.ts +14 -3
  274. package/packages/pi-ai/src/providers/anthropic.ts +8 -4
  275. package/packages/pi-ai/src/providers/openai-completions.ts +14 -0
  276. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts +2 -0
  277. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts.map +1 -0
  278. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js +61 -0
  279. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js.map +1 -0
  280. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/core/agent-session.js +2 -1
  282. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +10 -0
  284. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/auth-storage.js +27 -0
  286. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +85 -0
  288. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.d.ts +2 -0
  290. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.d.ts.map +1 -0
  291. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +388 -0
  292. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -0
  293. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -0
  294. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  296. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts +2 -0
  297. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts.map +1 -0
  298. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js +64 -0
  299. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js.map +1 -0
  300. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  301. package/packages/pi-coding-agent/dist/core/model-resolver.js +22 -18
  302. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  303. package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts +8 -0
  304. package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts.map +1 -0
  305. package/packages/pi-coding-agent/dist/core/model-resolver.test.js +75 -0
  306. package/packages/pi-coding-agent/dist/core/model-resolver.test.js.map +1 -0
  307. package/packages/pi-coding-agent/dist/core/sdk.d.ts +11 -0
  308. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  309. package/packages/pi-coding-agent/dist/core/sdk.js +38 -5
  310. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  311. package/packages/pi-coding-agent/dist/core/sdk.test.d.ts +2 -0
  312. package/packages/pi-coding-agent/dist/core/sdk.test.d.ts.map +1 -0
  313. package/packages/pi-coding-agent/dist/core/sdk.test.js +71 -0
  314. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -0
  315. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  316. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  317. package/packages/pi-coding-agent/dist/index.js +1 -1
  318. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  319. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts +2 -0
  320. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts.map +1 -0
  321. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js +13 -0
  322. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js.map +1 -0
  323. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts +19 -2
  324. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  325. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +50 -1
  326. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  327. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.d.ts +1 -0
  328. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  329. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.js +1 -0
  330. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.js.map +1 -1
  331. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +4 -0
  332. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  333. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +24 -2
  334. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  335. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  336. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +9 -2
  337. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  338. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +4 -0
  339. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  340. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +43 -0
  341. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  342. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  343. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +175 -25
  344. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  345. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.d.ts.map +1 -1
  346. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js +6 -1
  347. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js.map +1 -1
  348. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
  349. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  350. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  351. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +6 -0
  352. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  353. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +62 -5
  354. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  355. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +4 -2
  356. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  357. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +1 -1
  358. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  359. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts +1 -0
  360. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  361. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.js.map +1 -1
  362. package/packages/pi-coding-agent/package.json +1 -1
  363. package/packages/pi-coding-agent/src/core/agent-session-renderable-tools.test.ts +70 -0
  364. package/packages/pi-coding-agent/src/core/agent-session.ts +2 -1
  365. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +108 -0
  366. package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -0
  367. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +468 -0
  368. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -0
  369. package/packages/pi-coding-agent/src/core/model-resolver-initial-model-auth.test.ts +78 -0
  370. package/packages/pi-coding-agent/src/core/model-resolver.test.ts +85 -0
  371. package/packages/pi-coding-agent/src/core/model-resolver.ts +22 -18
  372. package/packages/pi-coding-agent/src/core/sdk.test.ts +89 -0
  373. package/packages/pi-coding-agent/src/core/sdk.ts +45 -9
  374. package/packages/pi-coding-agent/src/index.ts +1 -0
  375. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/login-dialog.test.ts +24 -0
  376. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +58 -2
  377. package/packages/pi-coding-agent/src/modes/interactive/components/extension-input.ts +2 -0
  378. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +30 -2
  379. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +15 -6
  380. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +47 -0
  381. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +205 -31
  382. package/packages/pi-coding-agent/src/modes/interactive/controllers/model-controller.ts +6 -1
  383. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -0
  384. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +70 -5
  385. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +4 -2
  386. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +1 -1
  387. package/packages/pi-coding-agent/src/modes/rpc/rpc-types.ts +1 -0
  388. package/packages/pi-tui/dist/components/__tests__/input.test.js +9 -0
  389. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
  390. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts +2 -0
  391. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts.map +1 -0
  392. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +66 -0
  393. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -0
  394. package/packages/pi-tui/dist/components/input.d.ts +2 -0
  395. package/packages/pi-tui/dist/components/input.d.ts.map +1 -1
  396. package/packages/pi-tui/dist/components/input.js +7 -4
  397. package/packages/pi-tui/dist/components/input.js.map +1 -1
  398. package/packages/pi-tui/dist/components/markdown.d.ts +3 -0
  399. package/packages/pi-tui/dist/components/markdown.d.ts.map +1 -1
  400. package/packages/pi-tui/dist/components/markdown.js +17 -1
  401. package/packages/pi-tui/dist/components/markdown.js.map +1 -1
  402. package/packages/pi-tui/src/components/__tests__/input.test.ts +11 -0
  403. package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +75 -0
  404. package/packages/pi-tui/src/components/input.ts +7 -4
  405. package/packages/pi-tui/src/components/markdown.ts +22 -1
  406. package/pkg/package.json +1 -1
  407. package/src/resources/GSD-WORKFLOW.md +1 -1
  408. package/src/resources/agents/debugger.md +58 -0
  409. package/src/resources/agents/doc-writer.md +43 -0
  410. package/src/resources/agents/git-ops.md +56 -0
  411. package/src/resources/agents/javascript-pro.md +46 -271
  412. package/src/resources/agents/planner.md +55 -0
  413. package/src/resources/agents/refactorer.md +47 -0
  414. package/src/resources/agents/reviewer.md +48 -0
  415. package/src/resources/agents/security.md +59 -0
  416. package/src/resources/agents/tester.md +50 -0
  417. package/src/resources/agents/typescript-pro.md +41 -235
  418. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +288 -39
  419. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +330 -2
  420. package/src/resources/extensions/get-secrets-from-user.ts +24 -1
  421. package/src/resources/extensions/gsd/auto/infra-errors.ts +38 -0
  422. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
  423. package/src/resources/extensions/gsd/auto/loop.ts +45 -1
  424. package/src/resources/extensions/gsd/auto/phases.ts +6 -0
  425. package/src/resources/extensions/gsd/auto/session.ts +11 -0
  426. package/src/resources/extensions/gsd/auto-dashboard.ts +29 -18
  427. package/src/resources/extensions/gsd/auto-model-selection.ts +9 -1
  428. package/src/resources/extensions/gsd/auto-prompts.ts +111 -33
  429. package/src/resources/extensions/gsd/auto-start.ts +44 -20
  430. package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
  431. package/src/resources/extensions/gsd/auto-worktree.ts +1 -1
  432. package/src/resources/extensions/gsd/auto.ts +72 -0
  433. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
  434. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +6 -0
  435. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +79 -60
  436. package/src/resources/extensions/gsd/bootstrap/system-context.ts +7 -0
  437. package/src/resources/extensions/gsd/commands/context.ts +16 -5
  438. package/src/resources/extensions/gsd/commands/dispatcher.ts +14 -2
  439. package/src/resources/extensions/gsd/commands/handlers/auto.ts +10 -36
  440. package/src/resources/extensions/gsd/commands/handlers/core.ts +58 -11
  441. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +17 -7
  442. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +4 -10
  443. package/src/resources/extensions/gsd/custom-workflow-engine.ts +19 -14
  444. package/src/resources/extensions/gsd/dashboard-overlay.ts +10 -3
  445. package/src/resources/extensions/gsd/dispatch-guard.ts +18 -1
  446. package/src/resources/extensions/gsd/doctor-providers.ts +24 -0
  447. package/src/resources/extensions/gsd/error-classifier.ts +1 -1
  448. package/src/resources/extensions/gsd/file-lock.ts +59 -0
  449. package/src/resources/extensions/gsd/forensics.ts +23 -7
  450. package/src/resources/extensions/gsd/gate-registry.ts +251 -0
  451. package/src/resources/extensions/gsd/gsd-db.ts +51 -0
  452. package/src/resources/extensions/gsd/guided-flow.ts +17 -19
  453. package/src/resources/extensions/gsd/init-wizard.ts +3 -13
  454. package/src/resources/extensions/gsd/interrupted-session.ts +1 -0
  455. package/src/resources/extensions/gsd/metrics.ts +12 -1
  456. package/src/resources/extensions/gsd/milestone-actions.ts +10 -3
  457. package/src/resources/extensions/gsd/milestone-validation-gates.ts +11 -13
  458. package/src/resources/extensions/gsd/notification-overlay.ts +47 -14
  459. package/src/resources/extensions/gsd/notification-store.ts +54 -5
  460. package/src/resources/extensions/gsd/notification-widget.ts +5 -14
  461. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -3
  462. package/src/resources/extensions/gsd/pre-execution-checks.ts +39 -2
  463. package/src/resources/extensions/gsd/prompt-validation.ts +157 -0
  464. package/src/resources/extensions/gsd/prompts/complete-slice.md +5 -3
  465. package/src/resources/extensions/gsd/prompts/discuss.md +33 -13
  466. package/src/resources/extensions/gsd/prompts/execute-task.md +22 -19
  467. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  468. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
  469. package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  470. package/src/resources/extensions/gsd/prompts/queue.md +3 -2
  471. package/src/resources/extensions/gsd/prompts/system.md +1 -0
  472. package/src/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
  473. package/src/resources/extensions/gsd/session-model-override.ts +36 -0
  474. package/src/resources/extensions/gsd/shortcut-defs.ts +56 -0
  475. package/src/resources/extensions/gsd/state.ts +285 -344
  476. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +25 -9
  477. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +28 -0
  478. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +39 -0
  479. package/src/resources/extensions/gsd/tests/complete-slice-gate-closure.test.ts +167 -0
  480. package/src/resources/extensions/gsd/tests/complete-slice-prompt-task-summary-layout.test.ts +18 -0
  481. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +436 -0
  482. package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +9 -0
  483. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
  484. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +36 -0
  485. package/src/resources/extensions/gsd/tests/execute-task-prompt-existing-artifact-guard.test.ts +33 -0
  486. package/src/resources/extensions/gsd/tests/file-lock.test.ts +103 -0
  487. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +62 -0
  488. package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +31 -0
  489. package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +27 -0
  490. package/src/resources/extensions/gsd/tests/gate-registry.test.ts +140 -0
  491. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +73 -0
  492. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +180 -0
  493. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +66 -1
  494. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +36 -51
  495. package/src/resources/extensions/gsd/tests/notification-store.test.ts +35 -0
  496. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +26 -0
  497. package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +90 -0
  498. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +1 -0
  499. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +18 -0
  500. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +49 -0
  501. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +19 -0
  502. package/src/resources/extensions/gsd/tests/prompt-system-gate-coverage.test.ts +208 -0
  503. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
  504. package/src/resources/extensions/gsd/tests/register-shortcuts.test.ts +63 -5
  505. package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +45 -0
  506. package/src/resources/extensions/gsd/tests/session-model-override.test.ts +35 -0
  507. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +90 -0
  508. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +7 -0
  509. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +18 -0
  510. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +76 -0
  511. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +155 -1
  512. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +22 -0
  513. package/src/resources/extensions/gsd/tools/complete-slice.ts +63 -0
  514. package/src/resources/extensions/gsd/tools/complete-task.ts +63 -0
  515. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +64 -26
  516. package/src/resources/extensions/gsd/types.ts +26 -0
  517. package/src/resources/extensions/gsd/workflow-events.ts +34 -25
  518. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +76 -0
  519. package/src/resources/extensions/gsd/workflow-mcp.ts +1 -1
  520. package/src/resources/extensions/ollama/index.ts +13 -3
  521. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +28 -0
  522. package/src/resources/extensions/shared/gsd-phase-state.ts +42 -0
  523. package/src/resources/extensions/shared/tests/gsd-phase-state.test.ts +48 -0
  524. package/src/resources/extensions/subagent/agents.ts +10 -0
  525. package/src/resources/extensions/subagent/index.ts +18 -0
  526. package/src/resources/extensions/subagent/tests/agents-conflicts.test.ts +33 -0
  527. package/src/resources/skills/create-skill/SKILL.md +2 -0
  528. package/dist/web/standalone/.next/static/chunks/2826.821e01b07d92e948.js +0 -9
  529. package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
  530. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  531. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  532. /package/dist/web/standalone/.next/static/{9pw9EXtXjdM7EFrCXUEPf → OI4n_CKC-lM8IQbvGJ_tK}/_buildManifest.js +0 -0
  533. /package/dist/web/standalone/.next/static/{9pw9EXtXjdM7EFrCXUEPf → OI4n_CKC-lM8IQbvGJ_tK}/_ssgManifest.js +0 -0
@@ -12,6 +12,7 @@ import { PartialMessageBuilder, ZERO_USAGE, mapUsage } from "./partial-builder.j
12
12
  import { buildWorkflowMcpServers } from "../gsd/workflow-mcp.js";
13
13
  import { showInterviewRound } from "../shared/tui.js";
14
14
  const OTHER_OPTION_LABEL = "None of the above";
15
+ const SENSITIVE_FIELD_PATTERN = /(password|passphrase|secret|token|api[_\s-]*key|private[_\s-]*key|credential)/i;
15
16
  // ---------------------------------------------------------------------------
16
17
  // Stream factory
17
18
  // ---------------------------------------------------------------------------
@@ -28,6 +29,15 @@ function createAssistantStream() {
28
29
  throw new Error("Unexpected event type for final result");
29
30
  });
30
31
  }
32
+ export function getResultErrorMessage(result) {
33
+ if ("errors" in result && Array.isArray(result.errors) && result.errors.length > 0) {
34
+ return result.errors.join("; ");
35
+ }
36
+ if ("result" in result && typeof result.result === "string" && result.result.trim().length > 0) {
37
+ return result.result.trim();
38
+ }
39
+ return result.subtype === "success" ? "claude_code_request_failed" : result.subtype;
40
+ }
31
41
  // ---------------------------------------------------------------------------
32
42
  // Claude binary resolution
33
43
  // ---------------------------------------------------------------------------
@@ -182,6 +192,56 @@ export function parseAskUserQuestionsElicitation(request) {
182
192
  }
183
193
  return questions.length > 0 ? questions : null;
184
194
  }
195
+ function isSecureElicitationField(requestMessage, fieldId, field) {
196
+ if (field.format === "password")
197
+ return true;
198
+ if (field.writeOnly === true)
199
+ return true;
200
+ const rawField = field;
201
+ if (rawField.sensitive === true || rawField["x-sensitive"] === true)
202
+ return true;
203
+ const haystack = [
204
+ requestMessage,
205
+ fieldId.replace(/[_-]+/g, " "),
206
+ typeof field.title === "string" ? field.title : "",
207
+ typeof field.description === "string" ? field.description : "",
208
+ ]
209
+ .join(" ")
210
+ .toLowerCase();
211
+ return SENSITIVE_FIELD_PATTERN.test(haystack);
212
+ }
213
+ export function parseTextInputElicitation(request) {
214
+ if (request.mode && request.mode !== "form")
215
+ return null;
216
+ const schema = request.requestedSchema;
217
+ const fieldsSource = schema?.properties && typeof schema.properties === "object"
218
+ ? schema.properties
219
+ : schema?.keys && typeof schema.keys === "object"
220
+ ? schema.keys
221
+ : undefined;
222
+ if (!fieldsSource)
223
+ return null;
224
+ const requiredSet = new Set(Array.isArray(request.requestedSchema?.required)
225
+ ? request.requestedSchema.required.filter((value) => typeof value === "string")
226
+ : []);
227
+ const fields = [];
228
+ for (const [fieldId, field] of Object.entries(fieldsSource)) {
229
+ if (!field || typeof field !== "object")
230
+ continue;
231
+ if (field.type !== "string")
232
+ continue;
233
+ if (Array.isArray(field.oneOf) && field.oneOf.length > 0)
234
+ continue;
235
+ fields.push({
236
+ id: fieldId,
237
+ title: typeof field.title === "string" && field.title.length > 0 ? field.title : fieldId,
238
+ description: typeof field.description === "string" ? field.description : "",
239
+ required: requiredSet.has(fieldId),
240
+ secure: isSecureElicitationField(request.message, fieldId, field),
241
+ });
242
+ }
243
+ return fields.length > 0 ? fields : null;
244
+ }
185
245
  export function roundResultToElicitationContent(questions, result) {
186
246
  const content = {};
187
247
  for (const question of questions) {
@@ -246,6 +306,38 @@ async function promptElicitationWithDialogs(request, questions, ui, signal) {
246
306
  }
247
307
  return { action: "accept", content };
248
308
  }
309
+ function buildTextInputPromptTitle(request, field) {
310
+ const parts = [
311
+ request.serverName ? `[${request.serverName}]` : "",
312
+ field.title,
313
+ field.description,
314
+ ].filter((part) => typeof part === "string" && part.trim().length > 0);
315
+ return parts.join("\n\n");
316
+ }
317
+ function buildTextInputPlaceholder(field) {
318
+ const desc = field.description.trim();
319
+ if (!desc)
320
+ return field.required ? "Required" : "Leave empty to skip";
321
+ const formatLine = desc
322
+ .split(/\r?\n/)
323
+ .map((line) => line.trim())
324
+ .find((line) => /^format:/i.test(line));
325
+ if (!formatLine)
326
+ return field.required ? "Required" : "Leave empty to skip";
327
+ const hint = formatLine.replace(/^format:\s*/i, "").trim();
328
+ return hint.length > 0 ? hint : field.required ? "Required" : "Leave empty to skip";
329
+ }
330
+ async function promptTextInputElicitation(request, fields, ui, signal) {
331
+ const content = {};
332
+ for (const field of fields) {
333
+ const value = await ui.input(buildTextInputPromptTitle(request, field), buildTextInputPlaceholder(field), { signal, ...(field.secure ? { secure: true } : {}) });
334
+ if (value === undefined) {
335
+ return { action: "cancel" };
336
+ }
337
+ content[field.id] = value;
338
+ }
339
+ return { action: "accept", content };
340
+ }
249
341
  export function createClaudeCodeElicitationHandler(ui) {
250
342
  if (!ui)
251
343
  return undefined;
@@ -254,40 +346,102 @@ export function createClaudeCodeElicitationHandler(ui) {
254
346
  return { action: "decline" };
255
347
  }
256
348
  const questions = parseAskUserQuestionsElicitation(request);
257
- if (!questions) {
258
- return { action: "decline" };
349
+ if (questions) {
350
+ const interviewResult = await showInterviewRound(questions, { signal }, { ui }).catch(() => undefined);
351
+ if (interviewResult && Object.keys(interviewResult.answers).length > 0) {
352
+ return {
353
+ action: "accept",
354
+ content: roundResultToElicitationContent(questions, interviewResult),
355
+ };
356
+ }
357
+ return promptElicitationWithDialogs(request, questions, ui, signal);
259
358
  }
260
- const interviewResult = await showInterviewRound(questions, { signal }, { ui }).catch(() => undefined);
261
- if (interviewResult && Object.keys(interviewResult.answers).length > 0) {
262
- return {
263
- action: "accept",
264
- content: roundResultToElicitationContent(questions, interviewResult),
265
- };
359
+ const textFields = parseTextInputElicitation(request);
360
+ if (textFields) {
361
+ return promptTextInputElicitation(request, textFields, ui, signal);
266
362
  }
267
- return promptElicitationWithDialogs(request, questions, ui, signal);
363
+ return { action: "decline" };
364
+ };
365
+ }
366
+ /**
367
+ * Aborted by the caller's AbortSignal — distinct from exhaustion. GSD's
368
+ * agent loop keys off `stopReason === "aborted"` to treat this as a clean
369
+ * user cancel instead of a retry-eligible provider failure.
370
+ */
371
+ export function makeAbortedMessage(model, lastTextContent) {
372
+ const message = {
373
+ role: "assistant",
374
+ content: lastTextContent
375
+ ? [{ type: "text", text: lastTextContent }]
376
+ : [{ type: "text", text: "Claude Code stream aborted by caller" }],
377
+ api: "anthropic-messages",
378
+ provider: "claude-code",
379
+ model,
380
+ usage: { ...ZERO_USAGE },
381
+ stopReason: "aborted",
382
+ timestamp: Date.now(),
268
383
  };
384
+ return message;
269
385
  }
270
386
  // ---------------------------------------------------------------------------
271
387
  // SDK options builder
272
388
  // ---------------------------------------------------------------------------
389
+ /**
390
+ * Resolve the Claude Code permission mode for the current run.
391
+ *
392
+ * - Auto-mode / headless runs bypass permissions so tool calls don't block
393
+ * on prompts the user isn't watching.
394
+ * - Interactive runs default to `acceptEdits` so file/bash writes still
395
+ * land quickly but the SDK retains a permission gate.
396
+ * - `GSD_CLAUDE_CODE_PERMISSION_MODE` forces a specific mode when set.
397
+ *
398
+ * Cross-extension coupling is kept minimal by dynamically importing
399
+ * `isAutoActive` and falling back to the bypass default if the import
400
+ * fails (e.g. in unit tests that load stream-adapter in isolation).
401
+ */
402
+ export async function resolveClaudePermissionMode(env = process.env) {
403
+ const override = env.GSD_CLAUDE_CODE_PERMISSION_MODE?.trim();
404
+ if (override === "bypassPermissions" || override === "acceptEdits" || override === "default" || override === "plan") {
405
+ return override;
406
+ }
407
+ try {
408
+ const autoMod = (await import("../gsd/auto.js"));
409
+ if (typeof autoMod.isAutoActive === "function" && autoMod.isAutoActive()) {
410
+ return "bypassPermissions";
411
+ }
412
+ return "acceptEdits";
413
+ }
414
+ catch {
415
+ // auto.ts unavailable (tests, non-GSD contexts) — stay permissive.
416
+ return "bypassPermissions";
417
+ }
418
+ }
273
419
  /**
274
420
  * Build the options object passed to the Claude Agent SDK's `query()` call.
275
421
  *
276
422
  * Extracted for testability — callers can verify session persistence,
277
423
  * beta flags, and other configuration without mocking the full SDK.
424
+ *
425
+ * `permissionMode` / `allowDangerouslySkipPermissions` are resolved through
426
+ * {@link resolveClaudePermissionMode} so interactive runs don't silently
427
+ * bypass the SDK's permission gate. Callers that want the old always-bypass
428
+ * behaviour pass `permissionMode: "bypassPermissions"` explicitly.
278
429
  */
279
- export function buildSdkOptions(modelId, prompt, extraOptions = {}) {
430
+ export function buildSdkOptions(modelId, prompt, overrides, extraOptions = {}) {
280
431
  const mcpServers = buildWorkflowMcpServers();
432
+ const permissionMode = overrides?.permissionMode ?? "bypassPermissions";
433
+ const disallowedTools = ["AskUserQuestion"];
281
434
  return {
282
435
  pathToClaudeCodeExecutable: getClaudePath(),
283
436
  model: modelId,
284
437
  includePartialMessages: true,
285
438
  persistSession: true,
286
439
  cwd: process.cwd(),
287
- permissionMode: "bypassPermissions",
288
- allowDangerouslySkipPermissions: true,
440
+ permissionMode,
441
+ allowDangerouslySkipPermissions: permissionMode === "bypassPermissions",
289
442
  settingSources: ["project"],
290
443
  systemPrompt: { type: "preset", preset: "claude_code" },
444
+ disallowedTools,
291
445
  ...(mcpServers ? { mcpServers } : {}),
292
446
  betas: modelId.includes("sonnet") ? ["context-1m-2025-08-07"] : [],
293
447
  ...extraOptions,
@@ -371,9 +525,9 @@ export function extractToolResultsFromSdkUserMessage(message) {
371
525
  }
372
526
  return extracted;
373
527
  }
374
- function attachExternalResultsToToolCalls(toolCalls, toolResultsById) {
375
- for (const block of toolCalls) {
376
- if (block.type !== "toolCall")
528
+ function attachExternalResultsToToolBlocks(toolBlocks, toolResultsById) {
529
+ for (const block of toolBlocks) {
530
+ if (block.type !== "toolCall" && block.type !== "serverToolUse")
377
531
  continue;
378
532
  const externalResult = toolResultsById.get(block.id);
379
533
  if (!externalResult)
@@ -381,6 +535,28 @@ function attachExternalResultsToToolCalls(toolCalls, toolResultsById) {
381
535
  block.externalResult = externalResult;
382
536
  }
383
537
  }
538
+ /**
539
+ * Merge tool-call blocks from the active partial-message builder into the
540
+ * running list of intermediate tool calls, preserving order and de-duping
541
+ * by tool-call id. Exposed for testing the F3 fix (final-turn tool calls
542
+ * dropped when `result` arrives without a preceding synthetic `user`).
543
+ */
544
+ export function mergePendingToolCalls(intermediate, pending) {
545
+ const alreadyIncluded = new Set();
546
+ for (const block of intermediate) {
547
+ if (block.type === "toolCall")
548
+ alreadyIncluded.add(block.id);
549
+ }
550
+ for (const block of pending) {
551
+ if (block.type !== "toolCall")
552
+ continue;
553
+ if (alreadyIncluded.has(block.id))
554
+ continue;
555
+ alreadyIncluded.add(block.id);
556
+ intermediate.push(block);
557
+ }
558
+ return intermediate;
559
+ }
384
560
  // ---------------------------------------------------------------------------
385
561
  // streamSimple implementation
386
562
  // ---------------------------------------------------------------------------
@@ -402,8 +578,8 @@ async function pumpSdkMessages(model, context, options, stream) {
402
578
  /** Track the last text content seen across all assistant turns for the final message. */
403
579
  let lastTextContent = "";
404
580
  let lastThinkingContent = "";
405
- /** Collect tool calls from intermediate SDK turns for tool_execution events. */
406
- const intermediateToolCalls = [];
581
+ /** Collect tool blocks from intermediate SDK turns for tool execution rendering. */
582
+ const intermediateToolBlocks = [];
407
583
  /** Preserve real external tool results from Claude Code's synthetic user messages. */
408
584
  const toolResultsById = new Map();
409
585
  try {
@@ -416,7 +592,8 @@ async function pumpSdkMessages(model, context, options, stream) {
416
592
  options.signal.addEventListener("abort", () => controller.abort(), { once: true });
417
593
  }
418
594
  const prompt = buildPromptFromContext(context);
419
- const sdkOpts = buildSdkOptions(modelId, prompt, typeof options?.extensionUIContext === "object"
595
+ const permissionMode = await resolveClaudePermissionMode();
596
+ const sdkOpts = buildSdkOptions(modelId, prompt, { permissionMode }, typeof options?.extensionUIContext === "object"
420
597
  ? {
421
598
  onElicitation: createClaudeCodeElicitationHandler(options?.extensionUIContext),
422
599
  }
@@ -441,8 +618,17 @@ async function pumpSdkMessages(model, context, options, stream) {
441
618
  };
442
619
  stream.push({ type: "start", partial: initialPartial });
443
620
  for await (const msg of queryResult) {
444
- if (options?.signal?.aborted)
445
- break;
621
+ if (options?.signal?.aborted) {
622
+ // User-initiated cancel — emit an aborted error so the agent
623
+ // loop classifies this as a deliberate stop, not a transient
624
+ // provider failure that should be retried.
625
+ stream.push({
626
+ type: "error",
627
+ reason: "aborted",
628
+ error: makeAbortedMessage(modelId, lastTextContent),
629
+ });
630
+ return;
631
+ }
446
632
  switch (msg.type) {
447
633
  // -- Init --
448
634
  case "system": {
@@ -491,9 +677,9 @@ async function pumpSdkMessages(model, context, options, stream) {
491
677
  else if (block.type === "thinking" && block.thinking) {
492
678
  lastThinkingContent = block.thinking;
493
679
  }
494
- else if (block.type === "toolCall") {
495
- // Collect tool calls for externalToolExecution rendering
496
- intermediateToolCalls.push(block);
680
+ else if (block.type === "toolCall" || block.type === "serverToolUse") {
681
+ // Collect tool blocks for externalToolExecution rendering
682
+ intermediateToolBlocks.push(block);
497
683
  }
498
684
  }
499
685
  }
@@ -502,25 +688,35 @@ async function pumpSdkMessages(model, context, options, stream) {
502
688
  for (const { toolUseId, result } of extractToolResultsFromSdkUserMessage(msg)) {
503
689
  toolResultsById.set(toolUseId, result);
504
690
  }
505
- attachExternalResultsToToolCalls(intermediateToolCalls, toolResultsById);
691
+ attachExternalResultsToToolBlocks(intermediateToolBlocks, toolResultsById);
506
692
  // Push a synthetic toolcall_end for each tool call from this turn
507
693
  // so the TUI can render tool results in real-time during the SDK
508
694
  // session instead of waiting until the entire session completes.
509
695
  if (builder) {
510
696
  for (const block of builder.message.content) {
511
- if (block.type !== "toolCall")
512
- continue;
513
697
  const extResult = block.externalResult;
514
698
  if (!extResult)
515
699
  continue;
516
- // Push a toolcall_end with result attached so the chat-controller
517
- // can call updateResult on the pending ToolExecutionComponent.
518
- stream.push({
519
- type: "toolcall_end",
520
- contentIndex: builder.message.content.indexOf(block),
521
- toolCall: block,
522
- partial: builder.message,
523
- });
700
+ const contentIndex = builder.message.content.indexOf(block);
701
+ if (contentIndex < 0)
702
+ continue;
703
+ // Push synthetic completion events with result attached so the
704
+ // chat-controller can update pending ToolExecutionComponents.
705
+ if (block.type === "toolCall") {
706
+ stream.push({
707
+ type: "toolcall_end",
708
+ contentIndex,
709
+ toolCall: block,
710
+ partial: builder.message,
711
+ });
712
+ }
713
+ else if (block.type === "serverToolUse") {
714
+ stream.push({
715
+ type: "server_tool_use",
716
+ contentIndex,
717
+ partial: builder.message,
718
+ });
719
+ }
524
720
  }
525
721
  }
526
722
  builder = null;
@@ -533,9 +729,18 @@ async function pumpSdkMessages(model, context, options, stream) {
533
729
  // agent loop's externalToolExecution path emits tool_execution
534
730
  // events for proper TUI rendering, followed by the text response.
535
731
  const finalContent = [];
732
+ // If the final turn ended without a synthetic user message
733
+ // (e.g. stop_reason: "tool_use" followed directly by result,
734
+ // or a turn with text but no tool execution), the `builder`
735
+ // still holds toolCall blocks that were never pushed into
736
+ // `intermediateToolBlocks`. Fold them in here so they aren't
737
+ // dropped from the final AssistantMessage.
738
+ if (builder) {
739
+ mergePendingToolCalls(intermediateToolBlocks, builder.message.content);
740
+ }
536
741
  // Add tool calls from intermediate turns first (renders above text)
537
- attachExternalResultsToToolCalls(intermediateToolCalls, toolResultsById);
538
- finalContent.push(...intermediateToolCalls);
742
+ attachExternalResultsToToolBlocks(intermediateToolBlocks, toolResultsById);
743
+ finalContent.push(...intermediateToolBlocks);
539
744
  // Add text/thinking from the last turn
540
745
  if (builder && builder.message.content.length > 0) {
541
746
  for (const block of builder.message.content) {
@@ -567,10 +772,7 @@ async function pumpSdkMessages(model, context, options, stream) {
567
772
  timestamp: Date.now(),
568
773
  };
569
774
  if (result.is_error) {
570
- const errText = "errors" in result
571
- ? result.errors?.join("; ")
572
- : result.subtype;
573
- finalMessage.errorMessage = errText;
775
+ finalMessage.errorMessage = getResultErrorMessage(result);
574
776
  stream.push({ type: "error", reason: "error", error: finalMessage });
575
777
  }
576
778
  else {
@@ -93,7 +93,7 @@ export function detectDestination(basePath) {
93
93
  async function collectOneSecret(ctx, pageIndex, totalPages, keyName, hint, guidance) {
94
94
  if (!ctx.hasUI)
95
95
  return null;
96
- return ctx.ui.custom((tui, theme, _kb, done) => {
96
+ const customResult = await ctx.ui.custom((tui, theme, _kb, done) => {
97
97
  let value = "";
98
98
  let cachedLines;
99
99
  const editorTheme = {
@@ -178,6 +178,22 @@ async function collectOneSecret(ctx, pageIndex, totalPages, keyName, hint, guida
178
178
  handleInput,
179
179
  };
180
180
  });
181
+ // RPC/web surfaces may not implement ctx.ui.custom(). Fall back to a
182
+ // standard input prompt so users can still provide the secret.
183
+ if (customResult !== undefined) {
184
+ return customResult;
185
+ }
186
+ if (typeof ctx.ui?.input !== "function") {
187
+ return null;
188
+ }
189
+ const inputTitle = `Secure value for ${keyName} (${pageIndex + 1}/${totalPages})`;
190
+ const inputPlaceholder = hint || "Enter secret value";
191
+ const inputResult = await ctx.ui.input(inputTitle, inputPlaceholder, { secure: true });
192
+ if (typeof inputResult !== "string") {
193
+ return null;
194
+ }
195
+ const trimmed = inputResult.trim();
196
+ return trimmed.length > 0 ? trimmed : null;
181
197
  }
182
198
  /**
183
199
  * Exported wrapper around collectOneSecret for testing.
@@ -47,3 +47,37 @@ export function isInfrastructureError(err) {
47
47
  return "SQLITE_CORRUPT";
48
48
  return null;
49
49
  }
50
+ /**
51
+ * Default wait duration when a cooldown error is detected but no specific
52
+ * expiry is available from AuthStorage (e.g., error propagated across
53
+ * process boundary without structured backoff data).
54
+ */
55
+ export const COOLDOWN_FALLBACK_WAIT_MS = 35_000; // 35s — slightly longer than the 30s rate-limit backoff
56
+ /** Maximum consecutive cooldown retries before the auto-loop gives up. */
57
+ export const MAX_COOLDOWN_RETRIES = 5;
58
+ /**
59
+ * Detect whether an error is a transient credential cooldown that should
60
+ * be waited out rather than counted as a consecutive failure.
61
+ *
62
+ * Prefers the structured `CredentialCooldownError` (code: AUTH_COOLDOWN)
63
+ * thrown by sdk.ts. Falls back to message matching for errors that
64
+ * propagated across process boundaries without the typed class.
65
+ */
66
+ export function isTransientCooldownError(err) {
67
+ if (err && typeof err === "object" && err.code === "AUTH_COOLDOWN") {
68
+ return true;
69
+ }
70
+ // Fallback: message match for cross-process error propagation
71
+ const msg = err instanceof Error ? err.message : String(err);
72
+ return /in a cooldown window/i.test(msg);
73
+ }
74
+ /**
75
+ * Extract retryAfterMs from a CredentialCooldownError, if available.
76
+ * Returns undefined for unstructured errors or when no retry hint exists.
77
+ */
78
+ export function getCooldownRetryAfterMs(err) {
79
+ if (err && typeof err === "object" && err.code === "AUTH_COOLDOWN") {
80
+ return err.retryAfterMs;
81
+ }
82
+ return undefined;
83
+ }
@@ -11,7 +11,7 @@ import { MAX_LOOP_ITERATIONS, } from "./types.js";
11
11
  import { _clearCurrentResolve } from "./resolve.js";
12
12
  import { runPreDispatch, runDispatch, runGuards, runUnitPhase, runFinalize, } from "./phases.js";
13
13
  import { debugLog } from "../debug-logger.js";
14
- import { isInfrastructureError } from "./infra-errors.js";
14
+ import { isInfrastructureError, isTransientCooldownError, getCooldownRetryAfterMs, COOLDOWN_FALLBACK_WAIT_MS, MAX_COOLDOWN_RETRIES } from "./infra-errors.js";
15
15
  import { resolveEngine } from "../engine-resolver.js";
16
16
  /**
17
17
  * Main auto-mode execution loop. Iterates: derive → dispatch → guards →
@@ -26,6 +26,7 @@ export async function autoLoop(ctx, pi, s, deps) {
26
26
  let iteration = 0;
27
27
  const loopState = { recentUnits: [], stuckRecoveryAttempts: 0, consecutiveFinalizeTimeouts: 0 };
28
28
  let consecutiveErrors = 0;
29
+ let consecutiveCooldowns = 0;
29
30
  const recentErrorMessages = [];
30
31
  while (s.active) {
31
32
  iteration++;
@@ -158,6 +159,7 @@ export async function autoLoop(ctx, pi, s, deps) {
158
159
  });
159
160
  deps.clearUnitTimeout();
160
161
  consecutiveErrors = 0;
162
+ consecutiveCooldowns = 0;
161
163
  recentErrorMessages.length = 0;
162
164
  deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
163
165
  debugLog("autoLoop", { phase: "iteration-complete", iteration });
@@ -220,6 +222,7 @@ export async function autoLoop(ctx, pi, s, deps) {
220
222
  if (finalizeResult.action === "continue")
221
223
  continue;
222
224
  consecutiveErrors = 0; // Iteration completed successfully
225
+ consecutiveCooldowns = 0;
223
226
  recentErrorMessages.length = 0;
224
227
  deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
225
228
  debugLog("autoLoop", { phase: "iteration-complete", iteration });
@@ -246,6 +249,34 @@ export async function autoLoop(ctx, pi, s, deps) {
246
249
  await deps.stopAuto(ctx, pi, `Infrastructure error (${infraCode}): not recoverable by retry`);
247
250
  break;
248
251
  }
252
+ // ── Credential cooldown: wait and retry with bounded budget ──
253
+ // A 429 triggers a 30s credential backoff in AuthStorage. If the SDK's
254
+ // getApiKey() retries couldn't outlast the window, the error surfaces
255
+ // here. Wait for the cooldown to clear rather than counting it as a
256
+ // consecutive failure — but cap retries so we don't spin for hours
257
+ // on persistent quota exhaustion.
258
+ if (isTransientCooldownError(loopErr)) {
259
+ consecutiveCooldowns++;
260
+ const retryAfterMs = getCooldownRetryAfterMs(loopErr);
261
+ debugLog("autoLoop", {
262
+ phase: "cooldown-wait",
263
+ iteration,
264
+ consecutiveCooldowns,
265
+ retryAfterMs,
266
+ error: msg,
267
+ });
268
+ if (consecutiveCooldowns > MAX_COOLDOWN_RETRIES) {
269
+ ctx.ui.notify(`Auto-mode stopped: ${consecutiveCooldowns} consecutive credential cooldowns — rate limit or quota may be persistently exhausted.`, "error");
270
+ await deps.stopAuto(ctx, pi, `${consecutiveCooldowns} consecutive credential cooldowns exceeded retry budget`);
271
+ break;
272
+ }
273
+ const waitMs = (retryAfterMs !== undefined && retryAfterMs > 0 && retryAfterMs <= 60_000)
274
+ ? retryAfterMs + 500 // Use structured hint + small buffer
275
+ : COOLDOWN_FALLBACK_WAIT_MS;
276
+ ctx.ui.notify(`Credentials in cooldown (${consecutiveCooldowns}/${MAX_COOLDOWN_RETRIES}) — waiting ${Math.round(waitMs / 1000)}s before retrying.`, "warning");
277
+ await new Promise(resolve => setTimeout(resolve, waitMs));
278
+ continue; // Retry iteration without incrementing consecutiveErrors
279
+ }
249
280
  consecutiveErrors++;
250
281
  recentErrorMessages.push(msg.length > 120 ? msg.slice(0, 120) + "..." : msg);
251
282
  debugLog("autoLoop", {
@@ -13,6 +13,7 @@ import { runUnit } from "./run-unit.js";
13
13
  import { debugLog } from "../debug-logger.js";
14
14
  import { PROJECT_FILES } from "../detection.js";
15
15
  import { MergeConflictError } from "../git-service.js";
16
+ import { setCurrentPhase, clearCurrentPhase } from "../../shared/gsd-phase-state.js";
16
17
  import { join, basename, dirname, parse as parsePath } from "node:path";
17
18
  import { existsSync, cpSync, readdirSync } from "node:fs";
18
19
  import { logWarning, logError } from "../workflow-logger.js";
@@ -770,6 +771,7 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
770
771
  s.currentUnit.id === unitId);
771
772
  const previousTier = s.currentUnitRouting?.tier;
772
773
  s.currentUnit = { type: unitType, id: unitId, startedAt: Date.now() };
774
+ setCurrentPhase(unitType);
773
775
  s.lastToolInvocationError = null; // #2883: clear stale error from previous unit
774
776
  const unitStartSeq = ic.nextSeq();
775
777
  deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: unitStartSeq, eventType: "unit-start", data: { unitType, unitId } });
@@ -857,7 +859,7 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
857
859
  logWarning("engine", "Prompt reorder failed", { error: msg });
858
860
  }
859
861
  // Select and apply model (with tier escalation on retry — normal units only)
860
- const modelResult = await deps.selectAndApplyModel(ctx, pi, unitType, unitId, s.basePath, prefs, s.verbose, s.autoModeStartModel, sidecarItem ? undefined : { isRetry, previousTier });
862
+ const modelResult = await deps.selectAndApplyModel(ctx, pi, unitType, unitId, s.basePath, prefs, s.verbose, s.autoModeStartModel, sidecarItem ? undefined : { isRetry, previousTier }, undefined, s.manualSessionModelOverride);
861
863
  s.currentUnitRouting =
862
864
  modelResult.routing;
863
865
  s.currentUnitModel =
@@ -1115,6 +1117,7 @@ export async function runFinalize(ic, iterData, loopState, sidecarItem) {
1115
1117
  // Detach session from the timed-out unit so late async completions
1116
1118
  // cannot mutate state for the next unit (#3757).
1117
1119
  s.currentUnit = null;
1120
+ clearCurrentPhase();
1118
1121
  loopState.consecutiveFinalizeTimeouts++;
1119
1122
  debugLog("autoLoop", {
1120
1123
  phase: "pre-verification-timeout",
@@ -1189,6 +1192,7 @@ export async function runFinalize(ic, iterData, loopState, sidecarItem) {
1189
1192
  // Detach session from the timed-out unit so late async completions
1190
1193
  // cannot mutate state for the next unit (#3757).
1191
1194
  s.currentUnit = null;
1195
+ clearCurrentPhase();
1192
1196
  loopState.consecutiveFinalizeTimeouts++;
1193
1197
  debugLog("autoLoop", {
1194
1198
  phase: "post-verification-timeout",
@@ -36,6 +36,10 @@ export class AutoSession {
36
36
  previousProjectRootEnv = null;
37
37
  hadProjectRootEnv = false;
38
38
  projectRootEnvCaptured = false;
39
+ previousMilestoneLockEnv = null;
40
+ hadMilestoneLockEnv = false;
41
+ milestoneLockEnvCaptured = false;
42
+ sessionMilestoneLock = null;
39
43
  gitService = null;
40
44
  // ── Dispatch counters ────────────────────────────────────────────────────
41
45
  unitDispatchCount = new Map();
@@ -52,6 +56,8 @@ export class AutoSession {
52
56
  currentMilestoneId = null;
53
57
  // ── Model state ──────────────────────────────────────────────────────────
54
58
  autoModeStartModel = null;
59
+ /** Explicit /gsd model pin captured at bootstrap (session-scoped policy override). */
60
+ manualSessionModelOverride = null;
55
61
  currentUnitModel = null;
56
62
  /** Fully-qualified model ID (provider/id) set after selectAndApplyModel + hook overrides (#2899). */
57
63
  currentDispatchedModelId = null;
@@ -140,6 +146,10 @@ export class AutoSession {
140
146
  this.previousProjectRootEnv = null;
141
147
  this.hadProjectRootEnv = false;
142
148
  this.projectRootEnvCaptured = false;
149
+ this.previousMilestoneLockEnv = null;
150
+ this.hadMilestoneLockEnv = false;
151
+ this.milestoneLockEnvCaptured = false;
152
+ this.sessionMilestoneLock = null;
143
153
  this.gitService = null;
144
154
  // Dispatch
145
155
  this.unitDispatchCount.clear();
@@ -151,6 +161,7 @@ export class AutoSession {
151
161
  this.currentMilestoneId = null;
152
162
  // Model
153
163
  this.autoModeStartModel = null;
164
+ this.manualSessionModelOverride = null;
154
165
  this.currentUnitModel = null;
155
166
  this.currentDispatchedModelId = null;
156
167
  this.originalModelId = null;