gsd-pi 2.70.1 → 2.71.0-dev.246c32d

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 (541) 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 +5 -2
  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 +19 -19
  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 +4 -4
  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 +19 -19
  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/retry-handler.d.ts +5 -0
  308. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  309. package/packages/pi-coding-agent/dist/core/retry-handler.js +55 -1
  310. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  311. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +57 -0
  312. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  313. package/packages/pi-coding-agent/dist/core/sdk.d.ts +11 -0
  314. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  315. package/packages/pi-coding-agent/dist/core/sdk.js +38 -5
  316. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  317. package/packages/pi-coding-agent/dist/core/sdk.test.d.ts +2 -0
  318. package/packages/pi-coding-agent/dist/core/sdk.test.d.ts.map +1 -0
  319. package/packages/pi-coding-agent/dist/core/sdk.test.js +71 -0
  320. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -0
  321. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  322. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  323. package/packages/pi-coding-agent/dist/index.js +1 -1
  324. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  325. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts +2 -0
  326. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts.map +1 -0
  327. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js +13 -0
  328. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js.map +1 -0
  329. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts +19 -2
  330. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  331. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +50 -1
  332. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  333. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.d.ts +1 -0
  334. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  335. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.js +1 -0
  336. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.js.map +1 -1
  337. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +4 -0
  338. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  339. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +24 -2
  340. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  341. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  342. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +9 -2
  343. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  344. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +4 -0
  345. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  346. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +43 -0
  347. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  348. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  349. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +175 -25
  350. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  351. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.d.ts.map +1 -1
  352. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js +6 -1
  353. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js.map +1 -1
  354. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
  355. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  356. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  357. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +6 -0
  358. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  359. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +62 -5
  360. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  361. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +4 -2
  362. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  363. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +1 -1
  364. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  365. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts +1 -0
  366. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  367. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.js.map +1 -1
  368. package/packages/pi-coding-agent/package.json +1 -1
  369. package/packages/pi-coding-agent/src/core/agent-session-renderable-tools.test.ts +70 -0
  370. package/packages/pi-coding-agent/src/core/agent-session.ts +2 -1
  371. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +108 -0
  372. package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -0
  373. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +468 -0
  374. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -0
  375. package/packages/pi-coding-agent/src/core/model-resolver-initial-model-auth.test.ts +78 -0
  376. package/packages/pi-coding-agent/src/core/model-resolver.test.ts +85 -0
  377. package/packages/pi-coding-agent/src/core/model-resolver.ts +22 -18
  378. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +83 -0
  379. package/packages/pi-coding-agent/src/core/retry-handler.ts +60 -1
  380. package/packages/pi-coding-agent/src/core/sdk.test.ts +89 -0
  381. package/packages/pi-coding-agent/src/core/sdk.ts +45 -9
  382. package/packages/pi-coding-agent/src/index.ts +1 -0
  383. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/login-dialog.test.ts +24 -0
  384. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +58 -2
  385. package/packages/pi-coding-agent/src/modes/interactive/components/extension-input.ts +2 -0
  386. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +30 -2
  387. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +15 -6
  388. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +47 -0
  389. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +205 -31
  390. package/packages/pi-coding-agent/src/modes/interactive/controllers/model-controller.ts +6 -1
  391. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -0
  392. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +70 -5
  393. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +4 -2
  394. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +1 -1
  395. package/packages/pi-coding-agent/src/modes/rpc/rpc-types.ts +1 -0
  396. package/packages/pi-tui/dist/components/__tests__/input.test.js +9 -0
  397. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
  398. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts +2 -0
  399. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts.map +1 -0
  400. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +66 -0
  401. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -0
  402. package/packages/pi-tui/dist/components/input.d.ts +2 -0
  403. package/packages/pi-tui/dist/components/input.d.ts.map +1 -1
  404. package/packages/pi-tui/dist/components/input.js +7 -4
  405. package/packages/pi-tui/dist/components/input.js.map +1 -1
  406. package/packages/pi-tui/dist/components/markdown.d.ts +3 -0
  407. package/packages/pi-tui/dist/components/markdown.d.ts.map +1 -1
  408. package/packages/pi-tui/dist/components/markdown.js +17 -1
  409. package/packages/pi-tui/dist/components/markdown.js.map +1 -1
  410. package/packages/pi-tui/src/components/__tests__/input.test.ts +11 -0
  411. package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +75 -0
  412. package/packages/pi-tui/src/components/input.ts +7 -4
  413. package/packages/pi-tui/src/components/markdown.ts +22 -1
  414. package/pkg/package.json +1 -1
  415. package/src/resources/GSD-WORKFLOW.md +1 -1
  416. package/src/resources/agents/debugger.md +58 -0
  417. package/src/resources/agents/doc-writer.md +43 -0
  418. package/src/resources/agents/git-ops.md +56 -0
  419. package/src/resources/agents/javascript-pro.md +46 -271
  420. package/src/resources/agents/planner.md +55 -0
  421. package/src/resources/agents/refactorer.md +47 -0
  422. package/src/resources/agents/reviewer.md +48 -0
  423. package/src/resources/agents/security.md +59 -0
  424. package/src/resources/agents/tester.md +50 -0
  425. package/src/resources/agents/typescript-pro.md +41 -235
  426. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +288 -39
  427. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +330 -2
  428. package/src/resources/extensions/get-secrets-from-user.ts +24 -1
  429. package/src/resources/extensions/gsd/auto/infra-errors.ts +38 -0
  430. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
  431. package/src/resources/extensions/gsd/auto/loop.ts +45 -1
  432. package/src/resources/extensions/gsd/auto/phases.ts +6 -0
  433. package/src/resources/extensions/gsd/auto/session.ts +11 -0
  434. package/src/resources/extensions/gsd/auto-dashboard.ts +29 -18
  435. package/src/resources/extensions/gsd/auto-model-selection.ts +9 -1
  436. package/src/resources/extensions/gsd/auto-prompts.ts +111 -33
  437. package/src/resources/extensions/gsd/auto-start.ts +44 -20
  438. package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
  439. package/src/resources/extensions/gsd/auto-worktree.ts +1 -1
  440. package/src/resources/extensions/gsd/auto.ts +72 -0
  441. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
  442. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +6 -0
  443. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +79 -60
  444. package/src/resources/extensions/gsd/bootstrap/system-context.ts +7 -0
  445. package/src/resources/extensions/gsd/commands/context.ts +16 -5
  446. package/src/resources/extensions/gsd/commands/dispatcher.ts +14 -2
  447. package/src/resources/extensions/gsd/commands/handlers/auto.ts +10 -36
  448. package/src/resources/extensions/gsd/commands/handlers/core.ts +58 -11
  449. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +17 -7
  450. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +4 -10
  451. package/src/resources/extensions/gsd/custom-workflow-engine.ts +19 -14
  452. package/src/resources/extensions/gsd/dashboard-overlay.ts +10 -3
  453. package/src/resources/extensions/gsd/dispatch-guard.ts +18 -1
  454. package/src/resources/extensions/gsd/doctor-providers.ts +24 -0
  455. package/src/resources/extensions/gsd/error-classifier.ts +5 -2
  456. package/src/resources/extensions/gsd/file-lock.ts +59 -0
  457. package/src/resources/extensions/gsd/forensics.ts +23 -7
  458. package/src/resources/extensions/gsd/gate-registry.ts +251 -0
  459. package/src/resources/extensions/gsd/gsd-db.ts +51 -0
  460. package/src/resources/extensions/gsd/guided-flow.ts +17 -19
  461. package/src/resources/extensions/gsd/init-wizard.ts +3 -13
  462. package/src/resources/extensions/gsd/interrupted-session.ts +1 -0
  463. package/src/resources/extensions/gsd/metrics.ts +12 -1
  464. package/src/resources/extensions/gsd/milestone-actions.ts +10 -3
  465. package/src/resources/extensions/gsd/milestone-validation-gates.ts +11 -13
  466. package/src/resources/extensions/gsd/notification-overlay.ts +47 -14
  467. package/src/resources/extensions/gsd/notification-store.ts +54 -5
  468. package/src/resources/extensions/gsd/notification-widget.ts +5 -14
  469. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -3
  470. package/src/resources/extensions/gsd/pre-execution-checks.ts +39 -2
  471. package/src/resources/extensions/gsd/prompt-validation.ts +157 -0
  472. package/src/resources/extensions/gsd/prompts/complete-slice.md +5 -3
  473. package/src/resources/extensions/gsd/prompts/discuss.md +33 -13
  474. package/src/resources/extensions/gsd/prompts/execute-task.md +22 -19
  475. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  476. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
  477. package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  478. package/src/resources/extensions/gsd/prompts/queue.md +3 -2
  479. package/src/resources/extensions/gsd/prompts/system.md +1 -0
  480. package/src/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
  481. package/src/resources/extensions/gsd/session-model-override.ts +36 -0
  482. package/src/resources/extensions/gsd/shortcut-defs.ts +56 -0
  483. package/src/resources/extensions/gsd/state.ts +285 -344
  484. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +25 -9
  485. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +28 -0
  486. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +39 -0
  487. package/src/resources/extensions/gsd/tests/complete-slice-gate-closure.test.ts +167 -0
  488. package/src/resources/extensions/gsd/tests/complete-slice-prompt-task-summary-layout.test.ts +18 -0
  489. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +436 -0
  490. package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +9 -0
  491. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
  492. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +36 -0
  493. package/src/resources/extensions/gsd/tests/execute-task-prompt-existing-artifact-guard.test.ts +33 -0
  494. package/src/resources/extensions/gsd/tests/file-lock.test.ts +103 -0
  495. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +62 -0
  496. package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +31 -0
  497. package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +27 -0
  498. package/src/resources/extensions/gsd/tests/gate-registry.test.ts +140 -0
  499. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +73 -0
  500. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +180 -0
  501. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +66 -1
  502. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +36 -51
  503. package/src/resources/extensions/gsd/tests/notification-store.test.ts +35 -0
  504. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +26 -0
  505. package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +90 -0
  506. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +1 -0
  507. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +18 -0
  508. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +49 -0
  509. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +19 -0
  510. package/src/resources/extensions/gsd/tests/prompt-system-gate-coverage.test.ts +208 -0
  511. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +16 -0
  512. package/src/resources/extensions/gsd/tests/register-shortcuts.test.ts +63 -5
  513. package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +45 -0
  514. package/src/resources/extensions/gsd/tests/session-model-override.test.ts +35 -0
  515. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +90 -0
  516. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +7 -0
  517. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +18 -0
  518. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +76 -0
  519. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +155 -1
  520. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +22 -0
  521. package/src/resources/extensions/gsd/tools/complete-slice.ts +63 -0
  522. package/src/resources/extensions/gsd/tools/complete-task.ts +63 -0
  523. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +64 -26
  524. package/src/resources/extensions/gsd/types.ts +26 -0
  525. package/src/resources/extensions/gsd/workflow-events.ts +34 -25
  526. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +76 -0
  527. package/src/resources/extensions/gsd/workflow-mcp.ts +1 -1
  528. package/src/resources/extensions/ollama/index.ts +13 -3
  529. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +28 -0
  530. package/src/resources/extensions/shared/gsd-phase-state.ts +42 -0
  531. package/src/resources/extensions/shared/tests/gsd-phase-state.test.ts +48 -0
  532. package/src/resources/extensions/subagent/agents.ts +10 -0
  533. package/src/resources/extensions/subagent/index.ts +18 -0
  534. package/src/resources/extensions/subagent/tests/agents-conflicts.test.ts +33 -0
  535. package/src/resources/skills/create-skill/SKILL.md +2 -0
  536. package/dist/web/standalone/.next/static/chunks/2826.821e01b07d92e948.js +0 -9
  537. package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
  538. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  539. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  540. /package/dist/web/standalone/.next/static/{9pw9EXtXjdM7EFrCXUEPf → hnGGkVMxIGGpxSJkf5jIV}/_buildManifest.js +0 -0
  541. /package/dist/web/standalone/.next/static/{9pw9EXtXjdM7EFrCXUEPf → hnGGkVMxIGGpxSJkf5jIV}/_ssgManifest.js +0 -0
@@ -5,16 +5,21 @@ import { join, resolve } from "node:path";
5
5
  import { tmpdir } from "node:os";
6
6
  import {
7
7
  makeStreamExhaustedErrorMessage,
8
+ getResultErrorMessage,
9
+ makeAbortedMessage,
10
+ mergePendingToolCalls,
11
+ resolveClaudePermissionMode,
8
12
  buildPromptFromContext,
9
13
  buildSdkOptions,
10
14
  createClaudeCodeElicitationHandler,
11
15
  extractToolResultsFromSdkUserMessage,
12
16
  getClaudeLookupCommand,
13
17
  parseAskUserQuestionsElicitation,
18
+ parseTextInputElicitation,
14
19
  parseClaudeLookupOutput,
15
20
  roundResultToElicitationContent,
16
21
  } from "../stream-adapter.ts";
17
- import type { Context, Message } from "@gsd/pi-ai";
22
+ import type { AssistantMessage, Context, Message } from "@gsd/pi-ai";
18
23
  import type { SDKUserMessage } from "../sdk-types.ts";
19
24
 
20
25
  // ---------------------------------------------------------------------------
@@ -39,6 +44,57 @@ describe("stream-adapter — exhausted stream fallback (#2575)", () => {
39
44
  });
40
45
  });
41
46
 
47
+ describe("stream-adapter — result error text (#3776)", () => {
48
+ test("prefers SDK result text when an error arrives with subtype success", () => {
49
+ const message = getResultErrorMessage({
50
+ type: "result",
51
+ subtype: "success",
52
+ uuid: "uuid-1",
53
+ session_id: "session-1",
54
+ duration_ms: 1,
55
+ duration_api_ms: 1,
56
+ is_error: true,
57
+ num_turns: 1,
58
+ result: 'API Error: 529 {"type":"error","error":{"type":"overloaded_error","message":"Overloaded"}}',
59
+ stop_reason: null,
60
+ total_cost_usd: 0,
61
+ usage: {
62
+ input_tokens: 0,
63
+ output_tokens: 0,
64
+ cache_read_input_tokens: 0,
65
+ cache_creation_input_tokens: 0,
66
+ },
67
+ });
68
+
69
+ assert.match(message, /API Error: 529/);
70
+ assert.doesNotMatch(message, /^success$/i);
71
+ });
72
+
73
+ test("falls back to a stable classifier when success errors have no text", () => {
74
+ const message = getResultErrorMessage({
75
+ type: "result",
76
+ subtype: "success",
77
+ uuid: "uuid-2",
78
+ session_id: "session-2",
79
+ duration_ms: 1,
80
+ duration_api_ms: 1,
81
+ is_error: true,
82
+ num_turns: 1,
83
+ result: " ",
84
+ stop_reason: null,
85
+ total_cost_usd: 0,
86
+ usage: {
87
+ input_tokens: 0,
88
+ output_tokens: 0,
89
+ cache_read_input_tokens: 0,
90
+ cache_creation_input_tokens: 0,
91
+ },
92
+ });
93
+
94
+ assert.equal(message, "claude_code_request_failed");
95
+ });
96
+ });
97
+
42
98
  // ---------------------------------------------------------------------------
43
99
  // Bug #2859 — stateless provider regression tests
44
100
  // ---------------------------------------------------------------------------
@@ -220,6 +276,35 @@ describe("stream-adapter — session persistence (#2859)", () => {
220
276
  assert.equal(srv.env.GSD_CLI_PATH, "/tmp/gsd");
221
277
  assert.equal(srv.env.GSD_PERSIST_WRITE_GATE_STATE, "1");
222
278
  assert.equal(srv.env.GSD_WORKFLOW_PROJECT_ROOT, "/tmp/project");
279
+ assert.deepEqual(options.disallowedTools, ["AskUserQuestion"]);
280
+ } finally {
281
+ process.env.GSD_WORKFLOW_MCP_COMMAND = prev.GSD_WORKFLOW_MCP_COMMAND;
282
+ process.env.GSD_WORKFLOW_MCP_NAME = prev.GSD_WORKFLOW_MCP_NAME;
283
+ process.env.GSD_WORKFLOW_MCP_ARGS = prev.GSD_WORKFLOW_MCP_ARGS;
284
+ process.env.GSD_WORKFLOW_MCP_ENV = prev.GSD_WORKFLOW_MCP_ENV;
285
+ process.env.GSD_WORKFLOW_MCP_CWD = prev.GSD_WORKFLOW_MCP_CWD;
286
+ }
287
+ });
288
+
289
+ test("buildSdkOptions disables AskUserQuestion for custom workflow MCP server names", () => {
290
+ const prev = {
291
+ GSD_WORKFLOW_MCP_COMMAND: process.env.GSD_WORKFLOW_MCP_COMMAND,
292
+ GSD_WORKFLOW_MCP_NAME: process.env.GSD_WORKFLOW_MCP_NAME,
293
+ GSD_WORKFLOW_MCP_ARGS: process.env.GSD_WORKFLOW_MCP_ARGS,
294
+ GSD_WORKFLOW_MCP_ENV: process.env.GSD_WORKFLOW_MCP_ENV,
295
+ GSD_WORKFLOW_MCP_CWD: process.env.GSD_WORKFLOW_MCP_CWD,
296
+ };
297
+ try {
298
+ process.env.GSD_WORKFLOW_MCP_COMMAND = "node";
299
+ process.env.GSD_WORKFLOW_MCP_NAME = "custom-workflow";
300
+ process.env.GSD_WORKFLOW_MCP_ARGS = JSON.stringify(["packages/mcp-server/dist/cli.js"]);
301
+ process.env.GSD_WORKFLOW_MCP_ENV = JSON.stringify({ GSD_CLI_PATH: "/tmp/gsd" });
302
+ process.env.GSD_WORKFLOW_MCP_CWD = "/tmp/project";
303
+
304
+ const options = buildSdkOptions("claude-sonnet-4-20250514", "test");
305
+ const mcpServers = options.mcpServers as Record<string, any>;
306
+ assert.ok(mcpServers?.["custom-workflow"], "expected custom workflow server config");
307
+ assert.deepEqual(options.disallowedTools, ["AskUserQuestion"]);
223
308
  } finally {
224
309
  process.env.GSD_WORKFLOW_MCP_COMMAND = prev.GSD_WORKFLOW_MCP_COMMAND;
225
310
  process.env.GSD_WORKFLOW_MCP_NAME = prev.GSD_WORKFLOW_MCP_NAME;
@@ -255,6 +340,9 @@ describe("stream-adapter — session persistence (#2859)", () => {
255
340
  const mcpServers = (options as any).mcpServers;
256
341
  if (mcpServers) {
257
342
  assert.ok(mcpServers["gsd-workflow"], "if present, must be gsd-workflow");
343
+ assert.deepEqual((options as any).disallowedTools, ["AskUserQuestion"]);
344
+ } else {
345
+ assert.deepEqual((options as any).disallowedTools, ["AskUserQuestion"]);
258
346
  }
259
347
  rmSync(emptyDir, { recursive: true, force: true });
260
348
  } finally {
@@ -301,6 +389,7 @@ describe("stream-adapter — session persistence (#2859)", () => {
301
389
  assert.equal(srv.env.GSD_CLI_PATH, "/tmp/gsd");
302
390
  assert.equal(srv.env.GSD_PERSIST_WRITE_GATE_STATE, "1");
303
391
  assert.equal(srv.env.GSD_WORKFLOW_PROJECT_ROOT, resolvedRepoDir);
392
+ assert.deepEqual(options.disallowedTools, ["AskUserQuestion"]);
304
393
  } finally {
305
394
  process.chdir(originalCwd);
306
395
  rmSync(repoDir, { recursive: true, force: true });
@@ -328,7 +417,7 @@ describe("stream-adapter — session persistence (#2859)", () => {
328
417
  delete process.env.GSD_WORKFLOW_MCP_ARGS;
329
418
  delete process.env.GSD_WORKFLOW_MCP_ENV;
330
419
  delete process.env.GSD_WORKFLOW_MCP_CWD;
331
- const options = buildSdkOptions("claude-sonnet-4-20250514", "test", { onElicitation });
420
+ const options = buildSdkOptions("claude-sonnet-4-20250514", "test", undefined, { onElicitation });
332
421
  assert.equal(options.onElicitation, onElicitation);
333
422
  } finally {
334
423
  process.env.GSD_WORKFLOW_MCP_COMMAND = prev.GSD_WORKFLOW_MCP_COMMAND;
@@ -481,6 +570,245 @@ describe("stream-adapter — MCP elicitation bridge", () => {
481
570
  },
482
571
  });
483
572
  });
573
+
574
+ test("parseTextInputElicitation recognizes secure free-text MCP forms", () => {
575
+ const request = {
576
+ serverName: "gsd-workflow",
577
+ message: "Enter values for environment variables.",
578
+ mode: "form" as const,
579
+ requestedSchema: {
580
+ type: "object" as const,
581
+ properties: {
582
+ TEST_PASSWORD: {
583
+ type: "string",
584
+ title: "TEST_PASSWORD",
585
+ description: "Format: min 8 characters\nLeave empty to skip.",
586
+ },
587
+ PROJECT_NAME: {
588
+ type: "string",
589
+ title: "PROJECT_NAME",
590
+ description: "Human-readable project name.",
591
+ },
592
+ },
593
+ },
594
+ };
595
+
596
+ const parsed = parseTextInputElicitation(request as any);
597
+ assert.deepEqual(parsed, [
598
+ {
599
+ id: "TEST_PASSWORD",
600
+ title: "TEST_PASSWORD",
601
+ description: "Format: min 8 characters\nLeave empty to skip.",
602
+ required: false,
603
+ secure: true,
604
+ },
605
+ {
606
+ id: "PROJECT_NAME",
607
+ title: "PROJECT_NAME",
608
+ description: "Human-readable project name.",
609
+ required: false,
610
+ secure: false,
611
+ },
612
+ ]);
613
+ });
614
+
615
+ test("parseTextInputElicitation accepts legacy keys schema and skips unsupported fields", () => {
616
+ const request = {
617
+ serverName: "gsd-workflow",
618
+ message: "Enter secure values",
619
+ mode: "form" as const,
620
+ requestedSchema: {
621
+ type: "object" as const,
622
+ keys: {
623
+ API_TOKEN: {
624
+ type: "string",
625
+ title: "API_TOKEN",
626
+ description: "Leave empty to skip.",
627
+ },
628
+ META: {
629
+ type: "object",
630
+ title: "metadata",
631
+ },
632
+ },
633
+ },
634
+ };
635
+
636
+ const parsed = parseTextInputElicitation(request as any);
637
+ assert.deepEqual(parsed, [
638
+ {
639
+ id: "API_TOKEN",
640
+ title: "API_TOKEN",
641
+ description: "Leave empty to skip.",
642
+ required: false,
643
+ secure: true,
644
+ },
645
+ ]);
646
+ });
647
+
648
+ test("createClaudeCodeElicitationHandler collects secure_env_collect fields through input dialogs", async () => {
649
+ const secureRequest = {
650
+ serverName: "gsd-workflow",
651
+ message: "Enter values for environment variables.",
652
+ mode: "form" as const,
653
+ requestedSchema: {
654
+ type: "object" as const,
655
+ properties: {
656
+ TEST_SECURE_FIELD: {
657
+ type: "string",
658
+ title: "TEST_SECURE_FIELD",
659
+ description: "Format: Your secure testing password\nLeave empty to skip.",
660
+ },
661
+ },
662
+ },
663
+ };
664
+
665
+ const inputCalls: Array<{ opts?: { secure?: boolean } }> = [];
666
+ const handler = createClaudeCodeElicitationHandler({
667
+ input: async (_title: string, _placeholder?: string, opts?: { secure?: boolean }) => {
668
+ inputCalls.push({ opts });
669
+ return "example-secure-input";
670
+ },
671
+ } as any);
672
+ assert.ok(handler);
673
+
674
+ const result = await handler!(secureRequest as any, { signal: new AbortController().signal });
675
+ assert.deepEqual(result, {
676
+ action: "accept",
677
+ content: {
678
+ TEST_SECURE_FIELD: "example-secure-input",
679
+ },
680
+ });
681
+ assert.equal(inputCalls.length, 1);
682
+ assert.equal(inputCalls[0]?.opts?.secure, true, "secure_env_collect fields should request secure input");
683
+ });
684
+ });
685
+
686
+ // ---------------------------------------------------------------------------
687
+ // F2 — abort vs stream-exhausted classification
688
+ // ---------------------------------------------------------------------------
689
+
690
+ describe("stream-adapter — abort classification (F2)", () => {
691
+ test("makeAbortedMessage sets stopReason to 'aborted', not 'error'", () => {
692
+ const message = makeAbortedMessage("claude-sonnet-4-6", "");
693
+ assert.equal(message.stopReason, "aborted");
694
+ assert.equal(message.errorMessage, undefined);
695
+ });
696
+
697
+ test("makeAbortedMessage preserves last-seen text content", () => {
698
+ const message = makeAbortedMessage("claude-sonnet-4-6", "partial mid-stream text");
699
+ assert.deepEqual(message.content, [{ type: "text", text: "partial mid-stream text" }]);
700
+ });
701
+
702
+ test("aborted message is distinguishable from stream-exhausted error", () => {
703
+ const aborted = makeAbortedMessage("claude-sonnet-4-6", "");
704
+ const exhausted = makeStreamExhaustedErrorMessage("claude-sonnet-4-6", "");
705
+ assert.notEqual(aborted.stopReason, exhausted.stopReason);
706
+ assert.equal(exhausted.errorMessage, "stream_exhausted_without_result");
707
+ });
708
+ });
709
+
710
+ // ---------------------------------------------------------------------------
711
+ // F3 — final-turn tool calls not dropped
712
+ // ---------------------------------------------------------------------------
713
+
714
+ describe("stream-adapter — final-turn tool-call merge (F3)", () => {
715
+ function toolCall(id: string, name = "bash"): AssistantMessage["content"][number] {
716
+ return { type: "toolCall", id, name, arguments: {} };
717
+ }
718
+
719
+ test("mergePendingToolCalls appends tool calls not already in intermediate", () => {
720
+ const intermediate: AssistantMessage["content"] = [toolCall("tool-1")];
721
+ const pending: AssistantMessage["content"] = [
722
+ toolCall("tool-2"),
723
+ { type: "text", text: "trailing text" },
724
+ ];
725
+ const merged = mergePendingToolCalls(intermediate, pending);
726
+ assert.equal(merged.length, 2);
727
+ assert.equal((merged[0] as any).id, "tool-1");
728
+ assert.equal((merged[1] as any).id, "tool-2");
729
+ });
730
+
731
+ test("mergePendingToolCalls is idempotent across duplicate ids", () => {
732
+ const intermediate: AssistantMessage["content"] = [toolCall("tool-1")];
733
+ const pending: AssistantMessage["content"] = [toolCall("tool-1"), toolCall("tool-2")];
734
+ const merged = mergePendingToolCalls(intermediate, pending);
735
+ assert.equal(merged.length, 2);
736
+ assert.deepEqual(
737
+ merged.map((b) => (b as any).id),
738
+ ["tool-1", "tool-2"],
739
+ );
740
+ });
741
+
742
+ test("mergePendingToolCalls ignores non-toolCall blocks from pending", () => {
743
+ const intermediate: AssistantMessage["content"] = [];
744
+ const pending: AssistantMessage["content"] = [
745
+ { type: "text", text: "hello" },
746
+ { type: "thinking", thinking: "pondering" },
747
+ toolCall("tool-1"),
748
+ ];
749
+ const merged = mergePendingToolCalls(intermediate, pending);
750
+ assert.equal(merged.length, 1);
751
+ assert.equal((merged[0] as any).id, "tool-1");
752
+ });
753
+ });
754
+
755
+ // ---------------------------------------------------------------------------
756
+ // F10 — permission mode is configurable
757
+ // ---------------------------------------------------------------------------
758
+
759
+ describe("stream-adapter — permission mode (F10)", () => {
760
+ // Earlier tests in this file set GSD_WORKFLOW_MCP_* env vars and restore
761
+ // them by reassigning from `prev.*`. When `prev.*` was undefined, node
762
+ // coerces the assignment to the literal string "undefined", which then
763
+ // fails JSON.parse inside buildWorkflowMcpServers. Clear the relevant
764
+ // slots before each permission-mode test so buildSdkOptions doesn't throw.
765
+ function clearWorkflowMcpEnv(): void {
766
+ for (const key of [
767
+ "GSD_WORKFLOW_MCP_COMMAND",
768
+ "GSD_WORKFLOW_MCP_NAME",
769
+ "GSD_WORKFLOW_MCP_ARGS",
770
+ "GSD_WORKFLOW_MCP_ENV",
771
+ "GSD_WORKFLOW_MCP_CWD",
772
+ ]) {
773
+ if (process.env[key] === undefined || process.env[key] === "undefined") {
774
+ delete process.env[key];
775
+ }
776
+ }
777
+ }
778
+
779
+ test("buildSdkOptions defaults to bypassPermissions for backwards compatibility", () => {
780
+ clearWorkflowMcpEnv();
781
+ const opts = buildSdkOptions("claude-sonnet-4-6", "test");
782
+ assert.equal(opts.permissionMode, "bypassPermissions");
783
+ assert.equal(opts.allowDangerouslySkipPermissions, true);
784
+ });
785
+
786
+ test("buildSdkOptions respects explicit acceptEdits override", () => {
787
+ clearWorkflowMcpEnv();
788
+ const opts = buildSdkOptions("claude-sonnet-4-6", "test", { permissionMode: "acceptEdits" });
789
+ assert.equal(opts.permissionMode, "acceptEdits");
790
+ assert.equal(
791
+ opts.allowDangerouslySkipPermissions,
792
+ false,
793
+ "allowDangerouslySkipPermissions must be false for non-bypass modes",
794
+ );
795
+ });
796
+
797
+ test("resolveClaudePermissionMode honours the GSD_CLAUDE_CODE_PERMISSION_MODE env override", async () => {
798
+ const env = { GSD_CLAUDE_CODE_PERMISSION_MODE: "acceptEdits" } as NodeJS.ProcessEnv;
799
+ const mode = await resolveClaudePermissionMode(env);
800
+ assert.equal(mode, "acceptEdits");
801
+ });
802
+
803
+ test("resolveClaudePermissionMode rejects unknown override values (fallback path)", async () => {
804
+ const env = { GSD_CLAUDE_CODE_PERMISSION_MODE: "nonsense" } as NodeJS.ProcessEnv;
805
+ const mode = await resolveClaudePermissionMode(env);
806
+ // Unknown override falls back to auto-detect → either bypass or acceptEdits
807
+ assert.ok(
808
+ mode === "bypassPermissions" || mode === "acceptEdits",
809
+ `expected bypass or acceptEdits, got ${mode}`,
810
+ );
811
+ });
484
812
  });
485
813
 
486
814
  describe("stream-adapter — Windows Claude path lookup (#3770)", () => {
@@ -126,7 +126,7 @@ async function collectOneSecret(
126
126
  ): Promise<string | null> {
127
127
  if (!ctx.hasUI) return null;
128
128
 
129
- return ctx.ui.custom((tui: any, theme: any, _kb: any, done: (r: string | null) => void) => {
129
+ const customResult = await ctx.ui.custom((tui: any, theme: any, _kb: any, done: (r: string | null) => void) => {
130
130
  let value = "";
131
131
  let cachedLines: string[] | undefined;
132
132
 
@@ -223,6 +223,29 @@ async function collectOneSecret(
223
223
  handleInput,
224
224
  };
225
225
  });
226
+
227
+ // RPC/web surfaces may not implement ctx.ui.custom(). Fall back to a
228
+ // standard input prompt so users can still provide the secret.
229
+ if (customResult !== undefined) {
230
+ return customResult;
231
+ }
232
+
233
+ if (typeof ctx.ui?.input !== "function") {
234
+ return null;
235
+ }
236
+
237
+ const inputTitle = `Secure value for ${keyName} (${pageIndex + 1}/${totalPages})`;
238
+ const inputPlaceholder = hint || "Enter secret value";
239
+ const inputResult = await ctx.ui.input(
240
+ inputTitle,
241
+ inputPlaceholder,
242
+ { secure: true },
243
+ );
244
+ if (typeof inputResult !== "string") {
245
+ return null;
246
+ }
247
+ const trimmed = inputResult.trim();
248
+ return trimmed.length > 0 ? trimmed : null;
226
249
  }
227
250
 
228
251
  /**
@@ -46,3 +46,41 @@ export function isInfrastructureError(err: unknown): string | null {
46
46
  if (msg.includes("database disk image is malformed")) return "SQLITE_CORRUPT";
47
47
  return null;
48
48
  }
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
+
57
+ /** Maximum consecutive cooldown retries before the auto-loop gives up. */
58
+ export const MAX_COOLDOWN_RETRIES = 5;
59
+
60
+ /**
61
+ * Detect whether an error is a transient credential cooldown that should
62
+ * be waited out rather than counted as a consecutive failure.
63
+ *
64
+ * Prefers the structured `CredentialCooldownError` (code: AUTH_COOLDOWN)
65
+ * thrown by sdk.ts. Falls back to message matching for errors that
66
+ * propagated across process boundaries without the typed class.
67
+ */
68
+ export function isTransientCooldownError(err: unknown): boolean {
69
+ if (err && typeof err === "object" && (err as Record<string, unknown>).code === "AUTH_COOLDOWN") {
70
+ return true;
71
+ }
72
+ // Fallback: message match for cross-process error propagation
73
+ const msg = err instanceof Error ? err.message : String(err);
74
+ return /in a cooldown window/i.test(msg);
75
+ }
76
+
77
+ /**
78
+ * Extract retryAfterMs from a CredentialCooldownError, if available.
79
+ * Returns undefined for unstructured errors or when no retry hint exists.
80
+ */
81
+ export function getCooldownRetryAfterMs(err: unknown): number | undefined {
82
+ if (err && typeof err === "object" && (err as Record<string, unknown>).code === "AUTH_COOLDOWN") {
83
+ return (err as Record<string, unknown>).retryAfterMs as number | undefined;
84
+ }
85
+ return undefined;
86
+ }
@@ -211,6 +211,8 @@ export interface LoopDeps {
211
211
  verbose: boolean,
212
212
  startModel: { provider: string; id: string } | null,
213
213
  retryContext?: { isRetry: boolean; previousTier?: string },
214
+ isAutoMode?: boolean,
215
+ sessionModelOverride?: { provider: string; id: string } | null,
214
216
  ) => Promise<{
215
217
  routing: { tier: string; modelDowngraded: boolean } | null;
216
218
  appliedModel: { provider: string; id: string } | null;
@@ -27,7 +27,7 @@ import {
27
27
  runFinalize,
28
28
  } from "./phases.js";
29
29
  import { debugLog } from "../debug-logger.js";
30
- import { isInfrastructureError } from "./infra-errors.js";
30
+ import { isInfrastructureError, isTransientCooldownError, getCooldownRetryAfterMs, COOLDOWN_FALLBACK_WAIT_MS, MAX_COOLDOWN_RETRIES } from "./infra-errors.js";
31
31
  import { resolveEngine } from "../engine-resolver.js";
32
32
 
33
33
  /**
@@ -48,6 +48,7 @@ export async function autoLoop(
48
48
  let iteration = 0;
49
49
  const loopState: LoopState = { recentUnits: [], stuckRecoveryAttempts: 0, consecutiveFinalizeTimeouts: 0 };
50
50
  let consecutiveErrors = 0;
51
+ let consecutiveCooldowns = 0;
51
52
  const recentErrorMessages: string[] = [];
52
53
 
53
54
  while (s.active) {
@@ -203,6 +204,7 @@ export async function autoLoop(
203
204
 
204
205
  deps.clearUnitTimeout();
205
206
  consecutiveErrors = 0;
207
+ consecutiveCooldowns = 0;
206
208
  recentErrorMessages.length = 0;
207
209
  deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
208
210
  debugLog("autoLoop", { phase: "iteration-complete", iteration });
@@ -265,6 +267,7 @@ export async function autoLoop(
265
267
  if (finalizeResult.action === "continue") continue;
266
268
 
267
269
  consecutiveErrors = 0; // Iteration completed successfully
270
+ consecutiveCooldowns = 0;
268
271
  recentErrorMessages.length = 0;
269
272
  deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
270
273
  debugLog("autoLoop", { phase: "iteration-complete", iteration });
@@ -300,6 +303,47 @@ export async function autoLoop(
300
303
  break;
301
304
  }
302
305
 
306
+ // ── Credential cooldown: wait and retry with bounded budget ──
307
+ // A 429 triggers a 30s credential backoff in AuthStorage. If the SDK's
308
+ // getApiKey() retries couldn't outlast the window, the error surfaces
309
+ // here. Wait for the cooldown to clear rather than counting it as a
310
+ // consecutive failure — but cap retries so we don't spin for hours
311
+ // on persistent quota exhaustion.
312
+ if (isTransientCooldownError(loopErr)) {
313
+ consecutiveCooldowns++;
314
+ const retryAfterMs = getCooldownRetryAfterMs(loopErr);
315
+ debugLog("autoLoop", {
316
+ phase: "cooldown-wait",
317
+ iteration,
318
+ consecutiveCooldowns,
319
+ retryAfterMs,
320
+ error: msg,
321
+ });
322
+
323
+ if (consecutiveCooldowns > MAX_COOLDOWN_RETRIES) {
324
+ ctx.ui.notify(
325
+ `Auto-mode stopped: ${consecutiveCooldowns} consecutive credential cooldowns — rate limit or quota may be persistently exhausted.`,
326
+ "error",
327
+ );
328
+ await deps.stopAuto(
329
+ ctx,
330
+ pi,
331
+ `${consecutiveCooldowns} consecutive credential cooldowns exceeded retry budget`,
332
+ );
333
+ break;
334
+ }
335
+
336
+ const waitMs = (retryAfterMs !== undefined && retryAfterMs > 0 && retryAfterMs <= 60_000)
337
+ ? retryAfterMs + 500 // Use structured hint + small buffer
338
+ : COOLDOWN_FALLBACK_WAIT_MS;
339
+ ctx.ui.notify(
340
+ `Credentials in cooldown (${consecutiveCooldowns}/${MAX_COOLDOWN_RETRIES}) — waiting ${Math.round(waitMs / 1000)}s before retrying.`,
341
+ "warning",
342
+ );
343
+ await new Promise(resolve => setTimeout(resolve, waitMs));
344
+ continue; // Retry iteration without incrementing consecutiveErrors
345
+ }
346
+
303
347
  consecutiveErrors++;
304
348
  recentErrorMessages.push(msg.length > 120 ? msg.slice(0, 120) + "..." : msg);
305
349
  debugLog("autoLoop", {
@@ -27,6 +27,7 @@ import { runUnit } from "./run-unit.js";
27
27
  import { debugLog } from "../debug-logger.js";
28
28
  import { PROJECT_FILES } from "../detection.js";
29
29
  import { MergeConflictError } from "../git-service.js";
30
+ import { setCurrentPhase, clearCurrentPhase } from "../../shared/gsd-phase-state.js";
30
31
  import { join, basename, dirname, parse as parsePath } from "node:path";
31
32
  import { existsSync, cpSync, readdirSync } from "node:fs";
32
33
  import { logWarning, logError } from "../workflow-logger.js";
@@ -1068,6 +1069,7 @@ export async function runUnitPhase(
1068
1069
  const previousTier = s.currentUnitRouting?.tier;
1069
1070
 
1070
1071
  s.currentUnit = { type: unitType, id: unitId, startedAt: Date.now() };
1072
+ setCurrentPhase(unitType);
1071
1073
  s.lastToolInvocationError = null; // #2883: clear stale error from previous unit
1072
1074
  const unitStartSeq = ic.nextSeq();
1073
1075
  deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: unitStartSeq, eventType: "unit-start", data: { unitType, unitId } });
@@ -1183,6 +1185,8 @@ export async function runUnitPhase(
1183
1185
  s.verbose,
1184
1186
  s.autoModeStartModel,
1185
1187
  sidecarItem ? undefined : { isRetry, previousTier },
1188
+ undefined,
1189
+ s.manualSessionModelOverride,
1186
1190
  );
1187
1191
  s.currentUnitRouting =
1188
1192
  modelResult.routing as AutoSession["currentUnitRouting"];
@@ -1527,6 +1531,7 @@ export async function runFinalize(
1527
1531
  // Detach session from the timed-out unit so late async completions
1528
1532
  // cannot mutate state for the next unit (#3757).
1529
1533
  s.currentUnit = null;
1534
+ clearCurrentPhase();
1530
1535
  loopState.consecutiveFinalizeTimeouts++;
1531
1536
  debugLog("autoLoop", {
1532
1537
  phase: "pre-verification-timeout",
@@ -1624,6 +1629,7 @@ export async function runFinalize(
1624
1629
  // Detach session from the timed-out unit so late async completions
1625
1630
  // cannot mutate state for the next unit (#3757).
1626
1631
  s.currentUnit = null;
1632
+ clearCurrentPhase();
1627
1633
  loopState.consecutiveFinalizeTimeouts++;
1628
1634
  debugLog("autoLoop", {
1629
1635
  phase: "post-verification-timeout",
@@ -87,6 +87,10 @@ export class AutoSession {
87
87
  previousProjectRootEnv: string | null = null;
88
88
  hadProjectRootEnv = false;
89
89
  projectRootEnvCaptured = false;
90
+ previousMilestoneLockEnv: string | null = null;
91
+ hadMilestoneLockEnv = false;
92
+ milestoneLockEnvCaptured = false;
93
+ sessionMilestoneLock: string | null = null;
90
94
  gitService: GitServiceImpl | null = null;
91
95
 
92
96
  // ── Dispatch counters ────────────────────────────────────────────────────
@@ -107,6 +111,8 @@ export class AutoSession {
107
111
 
108
112
  // ── Model state ──────────────────────────────────────────────────────────
109
113
  autoModeStartModel: StartModel | null = null;
114
+ /** Explicit /gsd model pin captured at bootstrap (session-scoped policy override). */
115
+ manualSessionModelOverride: StartModel | null = null;
110
116
  currentUnitModel: Model<Api> | null = null;
111
117
  /** Fully-qualified model ID (provider/id) set after selectAndApplyModel + hook overrides (#2899). */
112
118
  currentDispatchedModelId: string | null = null;
@@ -200,6 +206,10 @@ export class AutoSession {
200
206
  this.previousProjectRootEnv = null;
201
207
  this.hadProjectRootEnv = false;
202
208
  this.projectRootEnvCaptured = false;
209
+ this.previousMilestoneLockEnv = null;
210
+ this.hadMilestoneLockEnv = false;
211
+ this.milestoneLockEnvCaptured = false;
212
+ this.sessionMilestoneLock = null;
203
213
  this.gitService = null;
204
214
 
205
215
  // Dispatch
@@ -214,6 +224,7 @@ export class AutoSession {
214
224
 
215
225
  // Model
216
226
  this.autoModeStartModel = null;
227
+ this.manualSessionModelOverride = null;
217
228
  this.currentUnitModel = null;
218
229
  this.currentDispatchedModelId = null;
219
230
  this.originalModelId = null;