gsd-pi 2.71.0 → 2.72.0-dev.3118184

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 (578) hide show
  1. package/README.md +69 -19
  2. package/dist/cli.js +88 -6
  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/onboarding.js +10 -0
  8. package/dist/provider-migrations.d.ts +10 -0
  9. package/dist/provider-migrations.js +12 -0
  10. package/dist/resource-loader.js +139 -13
  11. package/dist/resources/GSD-WORKFLOW.md +1 -1
  12. package/dist/resources/agents/debugger.md +58 -0
  13. package/dist/resources/agents/doc-writer.md +43 -0
  14. package/dist/resources/agents/git-ops.md +56 -0
  15. package/dist/resources/agents/javascript-pro.md +46 -271
  16. package/dist/resources/agents/planner.md +55 -0
  17. package/dist/resources/agents/refactorer.md +47 -0
  18. package/dist/resources/agents/reviewer.md +48 -0
  19. package/dist/resources/agents/security.md +59 -0
  20. package/dist/resources/agents/tester.md +50 -0
  21. package/dist/resources/agents/typescript-pro.md +41 -235
  22. package/dist/resources/extensions/async-jobs/await-tool.js +7 -4
  23. package/dist/resources/extensions/async-jobs/job-manager.js +28 -3
  24. package/dist/resources/extensions/claude-code-cli/partial-builder.js +40 -12
  25. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +142 -14
  26. package/dist/resources/extensions/gsd/auto/infra-errors.js +34 -0
  27. package/dist/resources/extensions/gsd/auto/loop.js +116 -2
  28. package/dist/resources/extensions/gsd/auto/phases.js +5 -1
  29. package/dist/resources/extensions/gsd/auto/session.js +11 -0
  30. package/dist/resources/extensions/gsd/auto-dashboard.js +22 -16
  31. package/dist/resources/extensions/gsd/auto-model-selection.js +10 -2
  32. package/dist/resources/extensions/gsd/auto-post-unit.js +6 -0
  33. package/dist/resources/extensions/gsd/auto-prompts.js +88 -33
  34. package/dist/resources/extensions/gsd/auto-recovery.js +11 -0
  35. package/dist/resources/extensions/gsd/auto-start.js +34 -7
  36. package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
  37. package/dist/resources/extensions/gsd/auto-worktree.js +1 -1
  38. package/dist/resources/extensions/gsd/auto.js +81 -19
  39. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -3
  40. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +11 -11
  41. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +63 -51
  42. package/dist/resources/extensions/gsd/bootstrap/system-context.js +6 -0
  43. package/dist/resources/extensions/gsd/commands/context.js +15 -6
  44. package/dist/resources/extensions/gsd/commands/dispatcher.js +12 -2
  45. package/dist/resources/extensions/gsd/commands/handlers/auto.js +10 -33
  46. package/dist/resources/extensions/gsd/commands/handlers/core.js +56 -11
  47. package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +15 -6
  48. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +4 -10
  49. package/dist/resources/extensions/gsd/commands-handlers.js +4 -1
  50. package/dist/resources/extensions/gsd/context-injector.js +1 -1
  51. package/dist/resources/extensions/gsd/custom-workflow-engine.js +3 -7
  52. package/dist/resources/extensions/gsd/dashboard-overlay.js +8 -3
  53. package/dist/resources/extensions/gsd/definition-io.js +15 -0
  54. package/dist/resources/extensions/gsd/dispatch-guard.js +22 -1
  55. package/dist/resources/extensions/gsd/doctor-providers.js +23 -0
  56. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +6 -3
  57. package/dist/resources/extensions/gsd/error-classifier.js +5 -2
  58. package/dist/resources/extensions/gsd/forensics.js +19 -6
  59. package/dist/resources/extensions/gsd/gate-registry.js +208 -0
  60. package/dist/resources/extensions/gsd/git-service.js +11 -8
  61. package/dist/resources/extensions/gsd/gitignore.js +12 -6
  62. package/dist/resources/extensions/gsd/gsd-db.js +90 -6
  63. package/dist/resources/extensions/gsd/guided-flow.js +5 -10
  64. package/dist/resources/extensions/gsd/key-manager.js +2 -0
  65. package/dist/resources/extensions/gsd/metrics.js +1 -0
  66. package/dist/resources/extensions/gsd/milestone-actions.js +10 -4
  67. package/dist/resources/extensions/gsd/milestone-validation-gates.js +11 -12
  68. package/dist/resources/extensions/gsd/notification-overlay.js +42 -13
  69. package/dist/resources/extensions/gsd/notification-store.js +56 -5
  70. package/dist/resources/extensions/gsd/notification-widget.js +5 -13
  71. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +8 -3
  72. package/dist/resources/extensions/gsd/pre-execution-checks.js +35 -2
  73. package/dist/resources/extensions/gsd/preferences-skills.js +2 -34
  74. package/dist/resources/extensions/gsd/preferences-types.js +15 -0
  75. package/dist/resources/extensions/gsd/preferences.js +16 -3
  76. package/dist/resources/extensions/gsd/prompt-loader.js +4 -1
  77. package/dist/resources/extensions/gsd/prompt-validation.js +126 -0
  78. package/dist/resources/extensions/gsd/prompts/complete-slice.md +5 -3
  79. package/dist/resources/extensions/gsd/prompts/discuss.md +123 -12
  80. package/dist/resources/extensions/gsd/prompts/execute-task.md +22 -19
  81. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  82. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
  83. package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  84. package/dist/resources/extensions/gsd/prompts/queue.md +3 -2
  85. package/dist/resources/extensions/gsd/prompts/system.md +1 -0
  86. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
  87. package/dist/resources/extensions/gsd/session-model-override.js +25 -0
  88. package/dist/resources/extensions/gsd/shortcut-defs.js +40 -0
  89. package/dist/resources/extensions/gsd/state.js +29 -2
  90. package/dist/resources/extensions/gsd/tools/complete-slice.js +52 -1
  91. package/dist/resources/extensions/gsd/tools/complete-task.js +51 -1
  92. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +4 -1
  93. package/dist/resources/extensions/gsd/workflow-projections.js +7 -0
  94. package/dist/resources/extensions/gsd/worktree-manager.js +30 -3
  95. package/dist/resources/extensions/gsd/write-intercept.js +10 -1
  96. package/dist/resources/extensions/ollama/index.js +17 -10
  97. package/dist/resources/extensions/ollama/ollama-client.js +35 -6
  98. package/dist/resources/extensions/ollama/ollama-discovery.js +32 -6
  99. package/dist/resources/extensions/shared/gsd-phase-state.js +35 -0
  100. package/dist/resources/extensions/subagent/agents.js +8 -0
  101. package/dist/resources/extensions/subagent/index.js +17 -0
  102. package/dist/resources/skills/create-skill/SKILL.md +2 -0
  103. package/dist/startup-model-validation.d.ts +0 -1
  104. package/dist/startup-model-validation.js +6 -2
  105. package/dist/web/standalone/.next/BUILD_ID +1 -1
  106. package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
  107. package/dist/web/standalone/.next/build-manifest.json +3 -3
  108. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  109. package/dist/web/standalone/.next/required-server-files.json +3 -3
  110. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  111. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  121. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  125. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  137. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  149. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  169. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  179. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  185. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  199. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  201. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  203. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +3 -3
  205. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  214. package/dist/web/standalone/.next/server/app/index.html +1 -1
  215. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  216. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  217. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  218. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  219. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  220. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  221. package/dist/web/standalone/.next/server/app/page.js +2 -2
  222. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  223. package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
  224. package/dist/web/standalone/.next/server/chunks/2331.js +16 -16
  225. package/dist/web/standalone/.next/server/chunks/4741.js +12 -12
  226. package/dist/web/standalone/.next/server/chunks/5822.js +2 -2
  227. package/dist/web/standalone/.next/server/chunks/63.js +8 -8
  228. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  229. package/dist/web/standalone/.next/server/edge-runtime-webpack.js +2 -0
  230. package/dist/web/standalone/.next/server/functions-config-manifest.json +0 -9
  231. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  232. package/dist/web/standalone/.next/server/middleware-manifest.json +29 -2
  233. package/dist/web/standalone/.next/server/middleware.js +4 -12
  234. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  235. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  236. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  237. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  238. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  239. package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
  240. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  241. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  242. package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +1 -0
  243. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  244. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  245. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  246. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  247. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  248. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  249. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  250. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  251. package/dist/web/standalone/server.js +1 -1
  252. package/package.json +1 -1
  253. package/packages/mcp-server/dist/server.d.ts +12 -1
  254. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  255. package/packages/mcp-server/dist/server.js +90 -42
  256. package/packages/mcp-server/dist/server.js.map +1 -1
  257. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  258. package/packages/mcp-server/dist/workflow-tools.js +22 -12
  259. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  260. package/packages/mcp-server/src/server.ts +110 -38
  261. package/packages/mcp-server/src/workflow-tools.test.ts +110 -0
  262. package/packages/mcp-server/src/workflow-tools.ts +32 -12
  263. package/packages/pi-ai/dist/env-api-keys.js +1 -0
  264. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  265. package/packages/pi-ai/dist/models.custom.d.ts +105 -0
  266. package/packages/pi-ai/dist/models.custom.d.ts.map +1 -1
  267. package/packages/pi-ai/dist/models.custom.js +97 -0
  268. package/packages/pi-ai/dist/models.custom.js.map +1 -1
  269. package/packages/pi-ai/dist/models.generated.d.ts +648 -140
  270. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  271. package/packages/pi-ai/dist/models.generated.js +867 -370
  272. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  273. package/packages/pi-ai/dist/models.generated.test.d.ts +2 -0
  274. package/packages/pi-ai/dist/models.generated.test.d.ts.map +1 -0
  275. package/packages/pi-ai/dist/models.generated.test.js +334 -0
  276. package/packages/pi-ai/dist/models.generated.test.js.map +1 -0
  277. package/packages/pi-ai/dist/models.test.js +105 -0
  278. package/packages/pi-ai/dist/models.test.js.map +1 -1
  279. package/packages/pi-ai/dist/providers/amazon-bedrock.js +11 -2
  280. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  281. package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts +2 -0
  282. package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts.map +1 -0
  283. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +20 -0
  284. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -0
  285. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts +4 -1
  286. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  287. package/packages/pi-ai/dist/providers/anthropic-shared.js +8 -3
  288. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  289. package/packages/pi-ai/dist/providers/anthropic-shared.test.js +44 -1
  290. package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -1
  291. package/packages/pi-ai/dist/providers/anthropic.d.ts +2 -1
  292. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  293. package/packages/pi-ai/dist/providers/anthropic.js +7 -4
  294. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  295. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  296. package/packages/pi-ai/dist/providers/openai-completions.js +11 -0
  297. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  298. package/packages/pi-ai/dist/types.d.ts +1 -1
  299. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  300. package/packages/pi-ai/dist/types.js.map +1 -1
  301. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  302. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +5 -1
  303. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  304. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.d.ts +2 -0
  305. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.d.ts.map +1 -0
  306. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +57 -0
  307. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -0
  308. package/packages/pi-ai/src/env-api-keys.ts +1 -0
  309. package/packages/pi-ai/src/models.custom.ts +98 -0
  310. package/packages/pi-ai/src/models.generated.test.ts +373 -0
  311. package/packages/pi-ai/src/models.generated.ts +867 -370
  312. package/packages/pi-ai/src/models.test.ts +135 -0
  313. package/packages/pi-ai/src/providers/amazon-bedrock.ts +13 -1
  314. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +32 -0
  315. package/packages/pi-ai/src/providers/anthropic-shared.test.ts +55 -1
  316. package/packages/pi-ai/src/providers/anthropic-shared.ts +14 -3
  317. package/packages/pi-ai/src/providers/anthropic.ts +8 -4
  318. package/packages/pi-ai/src/providers/openai-completions.ts +14 -0
  319. package/packages/pi-ai/src/types.ts +1 -0
  320. package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +71 -0
  321. package/packages/pi-ai/src/utils/oauth/github-copilot.ts +4 -1
  322. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts +2 -0
  323. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts.map +1 -0
  324. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js +61 -0
  325. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js.map +1 -0
  326. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  327. package/packages/pi-coding-agent/dist/core/agent-session.js +2 -1
  328. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  329. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +10 -0
  330. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  331. package/packages/pi-coding-agent/dist/core/auth-storage.js +27 -0
  332. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  333. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +85 -0
  334. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  335. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts +2 -0
  336. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts.map +1 -0
  337. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js +64 -0
  338. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js.map +1 -0
  339. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  340. package/packages/pi-coding-agent/dist/core/model-resolver.js +23 -18
  341. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  342. package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts +8 -0
  343. package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts.map +1 -0
  344. package/packages/pi-coding-agent/dist/core/model-resolver.test.js +75 -0
  345. package/packages/pi-coding-agent/dist/core/model-resolver.test.js.map +1 -0
  346. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +5 -0
  347. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  348. package/packages/pi-coding-agent/dist/core/retry-handler.js +55 -1
  349. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  350. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +57 -0
  351. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  352. package/packages/pi-coding-agent/dist/core/sdk.d.ts +11 -0
  353. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  354. package/packages/pi-coding-agent/dist/core/sdk.js +47 -5
  355. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  356. package/packages/pi-coding-agent/dist/core/sdk.test.d.ts +2 -0
  357. package/packages/pi-coding-agent/dist/core/sdk.test.d.ts.map +1 -0
  358. package/packages/pi-coding-agent/dist/core/sdk.test.js +71 -0
  359. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -0
  360. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  361. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  362. package/packages/pi-coding-agent/dist/index.js +1 -1
  363. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  364. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts +2 -0
  365. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts.map +1 -0
  366. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js +13 -0
  367. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js.map +1 -0
  368. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -0
  369. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  370. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +4 -0
  371. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  372. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +24 -2
  373. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  374. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  375. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +9 -2
  376. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  377. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +4 -0
  378. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  379. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +130 -12
  380. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  381. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  382. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +7 -2
  383. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  384. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.d.ts.map +1 -1
  385. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js +6 -1
  386. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js.map +1 -1
  387. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  388. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -3
  389. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  390. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +4 -2
  391. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  392. package/packages/pi-coding-agent/package.json +1 -1
  393. package/packages/pi-coding-agent/src/core/agent-session-renderable-tools.test.ts +70 -0
  394. package/packages/pi-coding-agent/src/core/agent-session.ts +2 -1
  395. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +108 -0
  396. package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -0
  397. package/packages/pi-coding-agent/src/core/model-resolver-initial-model-auth.test.ts +78 -0
  398. package/packages/pi-coding-agent/src/core/model-resolver.test.ts +85 -0
  399. package/packages/pi-coding-agent/src/core/model-resolver.ts +23 -18
  400. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +83 -0
  401. package/packages/pi-coding-agent/src/core/retry-handler.ts +60 -1
  402. package/packages/pi-coding-agent/src/core/sdk.test.ts +89 -0
  403. package/packages/pi-coding-agent/src/core/sdk.ts +55 -9
  404. package/packages/pi-coding-agent/src/index.ts +1 -0
  405. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/login-dialog.test.ts +24 -0
  406. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +72 -0
  407. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +30 -2
  408. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +15 -6
  409. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +131 -12
  410. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +7 -2
  411. package/packages/pi-coding-agent/src/modes/interactive/controllers/model-controller.ts +6 -1
  412. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +4 -3
  413. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +4 -2
  414. package/packages/pi-tui/dist/components/__tests__/editor.test.js +12 -0
  415. package/packages/pi-tui/dist/components/__tests__/editor.test.js.map +1 -1
  416. package/packages/pi-tui/dist/components/__tests__/input.test.js +12 -0
  417. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
  418. package/packages/pi-tui/dist/keys.d.ts.map +1 -1
  419. package/packages/pi-tui/dist/keys.js +27 -0
  420. package/packages/pi-tui/dist/keys.js.map +1 -1
  421. package/packages/pi-tui/src/components/__tests__/editor.test.ts +18 -0
  422. package/packages/pi-tui/src/components/__tests__/input.test.ts +18 -0
  423. package/packages/pi-tui/src/keys.ts +32 -0
  424. package/pkg/package.json +1 -1
  425. package/src/resources/GSD-WORKFLOW.md +1 -1
  426. package/src/resources/agents/debugger.md +58 -0
  427. package/src/resources/agents/doc-writer.md +43 -0
  428. package/src/resources/agents/git-ops.md +56 -0
  429. package/src/resources/agents/javascript-pro.md +46 -271
  430. package/src/resources/agents/planner.md +55 -0
  431. package/src/resources/agents/refactorer.md +47 -0
  432. package/src/resources/agents/reviewer.md +48 -0
  433. package/src/resources/agents/security.md +59 -0
  434. package/src/resources/agents/tester.md +50 -0
  435. package/src/resources/agents/typescript-pro.md +41 -235
  436. package/src/resources/extensions/async-jobs/await-tool.test.ts +40 -7
  437. package/src/resources/extensions/async-jobs/await-tool.ts +7 -4
  438. package/src/resources/extensions/async-jobs/job-manager.ts +33 -3
  439. package/src/resources/extensions/claude-code-cli/partial-builder.ts +45 -12
  440. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +152 -13
  441. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +91 -2
  442. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +301 -6
  443. package/src/resources/extensions/gsd/auto/infra-errors.ts +38 -0
  444. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
  445. package/src/resources/extensions/gsd/auto/loop.ts +134 -2
  446. package/src/resources/extensions/gsd/auto/phases.ts +6 -0
  447. package/src/resources/extensions/gsd/auto/session.ts +11 -0
  448. package/src/resources/extensions/gsd/auto-dashboard.ts +29 -18
  449. package/src/resources/extensions/gsd/auto-model-selection.ts +9 -1
  450. package/src/resources/extensions/gsd/auto-post-unit.ts +7 -0
  451. package/src/resources/extensions/gsd/auto-prompts.ts +111 -33
  452. package/src/resources/extensions/gsd/auto-recovery.ts +10 -0
  453. package/src/resources/extensions/gsd/auto-start.ts +41 -7
  454. package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
  455. package/src/resources/extensions/gsd/auto-worktree.ts +1 -1
  456. package/src/resources/extensions/gsd/auto.ts +97 -20
  457. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
  458. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +10 -10
  459. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +79 -60
  460. package/src/resources/extensions/gsd/bootstrap/system-context.ts +7 -0
  461. package/src/resources/extensions/gsd/commands/context.ts +16 -5
  462. package/src/resources/extensions/gsd/commands/dispatcher.ts +14 -2
  463. package/src/resources/extensions/gsd/commands/handlers/auto.ts +10 -36
  464. package/src/resources/extensions/gsd/commands/handlers/core.ts +58 -11
  465. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +17 -7
  466. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +4 -10
  467. package/src/resources/extensions/gsd/commands-handlers.ts +5 -1
  468. package/src/resources/extensions/gsd/context-injector.ts +1 -1
  469. package/src/resources/extensions/gsd/custom-workflow-engine.ts +4 -8
  470. package/src/resources/extensions/gsd/dashboard-overlay.ts +10 -3
  471. package/src/resources/extensions/gsd/definition-io.ts +18 -0
  472. package/src/resources/extensions/gsd/dispatch-guard.ts +23 -1
  473. package/src/resources/extensions/gsd/doctor-providers.ts +24 -0
  474. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +6 -3
  475. package/src/resources/extensions/gsd/error-classifier.ts +5 -2
  476. package/src/resources/extensions/gsd/forensics.ts +23 -7
  477. package/src/resources/extensions/gsd/gate-registry.ts +251 -0
  478. package/src/resources/extensions/gsd/git-service.ts +11 -8
  479. package/src/resources/extensions/gsd/gitignore.ts +12 -6
  480. package/src/resources/extensions/gsd/gsd-db.ts +105 -6
  481. package/src/resources/extensions/gsd/guided-flow.ts +5 -10
  482. package/src/resources/extensions/gsd/interrupted-session.ts +1 -0
  483. package/src/resources/extensions/gsd/key-manager.ts +2 -0
  484. package/src/resources/extensions/gsd/metrics.ts +12 -1
  485. package/src/resources/extensions/gsd/milestone-actions.ts +10 -3
  486. package/src/resources/extensions/gsd/milestone-validation-gates.ts +11 -13
  487. package/src/resources/extensions/gsd/notification-overlay.ts +47 -14
  488. package/src/resources/extensions/gsd/notification-store.ts +54 -5
  489. package/src/resources/extensions/gsd/notification-widget.ts +5 -14
  490. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -3
  491. package/src/resources/extensions/gsd/pre-execution-checks.ts +39 -2
  492. package/src/resources/extensions/gsd/preferences-skills.ts +2 -36
  493. package/src/resources/extensions/gsd/preferences-types.ts +16 -0
  494. package/src/resources/extensions/gsd/preferences.ts +19 -6
  495. package/src/resources/extensions/gsd/prompt-loader.ts +6 -1
  496. package/src/resources/extensions/gsd/prompt-validation.ts +157 -0
  497. package/src/resources/extensions/gsd/prompts/complete-slice.md +5 -3
  498. package/src/resources/extensions/gsd/prompts/discuss.md +123 -12
  499. package/src/resources/extensions/gsd/prompts/execute-task.md +22 -19
  500. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  501. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
  502. package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  503. package/src/resources/extensions/gsd/prompts/queue.md +3 -2
  504. package/src/resources/extensions/gsd/prompts/system.md +1 -0
  505. package/src/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
  506. package/src/resources/extensions/gsd/session-model-override.ts +36 -0
  507. package/src/resources/extensions/gsd/shortcut-defs.ts +56 -0
  508. package/src/resources/extensions/gsd/state.ts +33 -2
  509. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +27 -0
  510. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +25 -9
  511. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +28 -0
  512. package/src/resources/extensions/gsd/tests/block-db-writes.test.ts +63 -0
  513. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +39 -0
  514. package/src/resources/extensions/gsd/tests/complete-slice-gate-closure.test.ts +167 -0
  515. package/src/resources/extensions/gsd/tests/complete-slice-prompt-task-summary-layout.test.ts +18 -0
  516. package/src/resources/extensions/gsd/tests/definition-io.test.ts +57 -0
  517. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +53 -0
  518. package/src/resources/extensions/gsd/tests/doctor-heal-fixable-warnings.test.ts +14 -0
  519. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +36 -0
  520. package/src/resources/extensions/gsd/tests/execute-task-prompt-existing-artifact-guard.test.ts +33 -0
  521. package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +104 -0
  522. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +62 -0
  523. package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +31 -0
  524. package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +27 -0
  525. package/src/resources/extensions/gsd/tests/gate-registry.test.ts +140 -0
  526. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +107 -5
  527. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +73 -0
  528. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +180 -0
  529. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +66 -1
  530. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +8 -6
  531. package/src/resources/extensions/gsd/tests/key-manager.test.ts +63 -0
  532. package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +54 -0
  533. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +36 -51
  534. package/src/resources/extensions/gsd/tests/notification-store.test.ts +35 -0
  535. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +26 -0
  536. package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +90 -0
  537. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +1 -0
  538. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +18 -0
  539. package/src/resources/extensions/gsd/tests/plan-milestone-artifact-verification.test.ts +62 -0
  540. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +34 -0
  541. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +49 -0
  542. package/src/resources/extensions/gsd/tests/preferences-formatting.test.ts +87 -0
  543. package/src/resources/extensions/gsd/tests/preferences.test.ts +53 -0
  544. package/src/resources/extensions/gsd/tests/projection-regression.test.ts +96 -1
  545. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +19 -0
  546. package/src/resources/extensions/gsd/tests/prompt-loader-working-directory.test.ts +19 -0
  547. package/src/resources/extensions/gsd/tests/prompt-system-gate-coverage.test.ts +208 -0
  548. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +16 -0
  549. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +97 -0
  550. package/src/resources/extensions/gsd/tests/register-shortcuts.test.ts +63 -5
  551. package/src/resources/extensions/gsd/tests/session-model-override.test.ts +35 -0
  552. package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +41 -0
  553. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +90 -0
  554. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +7 -0
  555. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +18 -0
  556. package/src/resources/extensions/gsd/tools/complete-slice.ts +63 -0
  557. package/src/resources/extensions/gsd/tools/complete-task.ts +63 -0
  558. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +4 -1
  559. package/src/resources/extensions/gsd/types.ts +26 -0
  560. package/src/resources/extensions/gsd/workflow-projections.ts +8 -0
  561. package/src/resources/extensions/gsd/worktree-manager.ts +29 -3
  562. package/src/resources/extensions/gsd/write-intercept.ts +10 -1
  563. package/src/resources/extensions/ollama/index.ts +17 -8
  564. package/src/resources/extensions/ollama/ollama-client.ts +35 -6
  565. package/src/resources/extensions/ollama/ollama-discovery.ts +37 -6
  566. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +28 -0
  567. package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +54 -0
  568. package/src/resources/extensions/shared/gsd-phase-state.ts +42 -0
  569. package/src/resources/extensions/shared/tests/gsd-phase-state.test.ts +48 -0
  570. package/src/resources/extensions/subagent/agents.ts +10 -0
  571. package/src/resources/extensions/subagent/index.ts +18 -0
  572. package/src/resources/extensions/subagent/tests/agents-conflicts.test.ts +33 -0
  573. package/src/resources/skills/create-skill/SKILL.md +2 -0
  574. package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
  575. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  576. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  577. /package/dist/web/standalone/.next/static/{nPky_WQC28aBD77eZsRAB → NzO79SOz9jHX-VY5-0t2O}/_buildManifest.js +0 -0
  578. /package/dist/web/standalone/.next/static/{nPky_WQC28aBD77eZsRAB → NzO79SOz9jHX-VY5-0t2O}/_ssgManifest.js +0 -0
@@ -5,6 +5,10 @@ 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,
@@ -15,7 +19,7 @@ import {
15
19
  parseClaudeLookupOutput,
16
20
  roundResultToElicitationContent,
17
21
  } from "../stream-adapter.ts";
18
- import type { Context, Message } from "@gsd/pi-ai";
22
+ import type { AssistantMessage, Context, Message } from "@gsd/pi-ai";
19
23
  import type { SDKUserMessage } from "../sdk-types.ts";
20
24
 
21
25
  // ---------------------------------------------------------------------------
@@ -40,6 +44,57 @@ describe("stream-adapter — exhausted stream fallback (#2575)", () => {
40
44
  });
41
45
  });
42
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
+
43
98
  // ---------------------------------------------------------------------------
44
99
  // Bug #2859 — stateless provider regression tests
45
100
  // ---------------------------------------------------------------------------
@@ -112,6 +167,98 @@ describe("stream-adapter — full context prompt (#2859)", () => {
112
167
  });
113
168
  });
114
169
 
170
+ // ---------------------------------------------------------------------------
171
+ // Bug #4102 — transcript fabrication regression tests
172
+ // ---------------------------------------------------------------------------
173
+
174
+ describe("stream-adapter — no transcript fabrication (#4102)", () => {
175
+ test("buildPromptFromContext never emits forbidden [User]/[Assistant] bracket headers", () => {
176
+ const context: Context = {
177
+ systemPrompt: "You are a helpful assistant.",
178
+ messages: [
179
+ { role: "user", content: "First" } as Message,
180
+ {
181
+ role: "assistant",
182
+ content: [{ type: "text", text: "Second" }],
183
+ api: "anthropic-messages",
184
+ provider: "claude-code",
185
+ model: "claude-sonnet-4-20250514",
186
+ usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
187
+ stopReason: "stop",
188
+ timestamp: Date.now(),
189
+ } as Message,
190
+ { role: "user", content: "Third" } as Message,
191
+ ],
192
+ };
193
+
194
+ const prompt = buildPromptFromContext(context);
195
+
196
+ assert.ok(!prompt.includes("[User]"), "prompt must not include literal [User] bracket header");
197
+ assert.ok(!prompt.includes("[Assistant]"), "prompt must not include literal [Assistant] bracket header");
198
+ assert.ok(!prompt.includes("[System]"), "prompt must not include literal [System] bracket header");
199
+ });
200
+
201
+ test("buildPromptFromContext wraps history in XML-tag structure", () => {
202
+ const context: Context = {
203
+ systemPrompt: "You are helpful.",
204
+ messages: [
205
+ { role: "user", content: "Hello" } as Message,
206
+ {
207
+ role: "assistant",
208
+ content: [{ type: "text", text: "Hi there" }],
209
+ api: "anthropic-messages",
210
+ provider: "claude-code",
211
+ model: "claude-sonnet-4-20250514",
212
+ usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
213
+ stopReason: "stop",
214
+ timestamp: Date.now(),
215
+ } as Message,
216
+ ],
217
+ };
218
+
219
+ const prompt = buildPromptFromContext(context);
220
+
221
+ assert.ok(prompt.includes("<conversation_history>"), "prompt must wrap history in <conversation_history>");
222
+ assert.ok(prompt.includes("</conversation_history>"), "prompt must close <conversation_history>");
223
+ assert.ok(prompt.includes("<user_message>\nHello\n</user_message>"), "user turn must use <user_message> tags");
224
+ assert.ok(prompt.includes("<assistant_message>\nHi there\n</assistant_message>"), "assistant turn must use <assistant_message> tags");
225
+ assert.ok(prompt.includes("<prior_system_context>\nYou are helpful.\n</prior_system_context>"), "system prompt must use <prior_system_context> tags");
226
+ });
227
+
228
+ test("buildPromptFromContext includes a do-not-echo-tags directive as primary instruction", () => {
229
+ const context: Context = {
230
+ messages: [{ role: "user", content: "Anything" } as Message],
231
+ };
232
+
233
+ const prompt = buildPromptFromContext(context);
234
+
235
+ assert.ok(
236
+ prompt.startsWith("Respond only to the final user message"),
237
+ "primary directive must lead the prompt",
238
+ );
239
+ assert.ok(prompt.includes("Do not emit <user_message>"), "directive must forbid emitting user_message tag");
240
+ assert.ok(prompt.includes("<assistant_message>"), "directive must mention assistant_message tag");
241
+ });
242
+
243
+ test("buildPromptFromContext omits <conversation_history> when there are no messages but a system prompt", () => {
244
+ const context: Context = {
245
+ systemPrompt: "Seed",
246
+ messages: [],
247
+ };
248
+
249
+ const prompt = buildPromptFromContext(context);
250
+
251
+ assert.ok(prompt.includes("<prior_system_context>"), "system prompt must still render");
252
+ assert.ok(!prompt.includes("<conversation_history>"), "no history wrapper when messages are empty");
253
+ });
254
+
255
+ test("buildPromptFromContext still returns empty string when context is entirely empty", () => {
256
+ const context: Context = { messages: [] };
257
+ const prompt = buildPromptFromContext(context);
258
+ assert.equal(prompt, "", "empty context must not emit a bare directive");
259
+ });
260
+ });
261
+
115
262
  describe("stream-adapter — Claude Code external tool results", () => {
116
263
  test("extractToolResultsFromSdkUserMessage maps tool_result content to tool payloads", () => {
117
264
  const message: SDKUserMessage = {
@@ -222,6 +369,16 @@ describe("stream-adapter — session persistence (#2859)", () => {
222
369
  assert.equal(srv.env.GSD_PERSIST_WRITE_GATE_STATE, "1");
223
370
  assert.equal(srv.env.GSD_WORKFLOW_PROJECT_ROOT, "/tmp/project");
224
371
  assert.deepEqual(options.disallowedTools, ["AskUserQuestion"]);
372
+ assert.deepEqual(options.allowedTools, [
373
+ "Read",
374
+ "Write",
375
+ "Edit",
376
+ "Glob",
377
+ "Grep",
378
+ "Bash(ls:*)",
379
+ "Bash(pwd)",
380
+ "mcp__gsd-workflow__*",
381
+ ]);
225
382
  } finally {
226
383
  process.env.GSD_WORKFLOW_MCP_COMMAND = prev.GSD_WORKFLOW_MCP_COMMAND;
227
384
  process.env.GSD_WORKFLOW_MCP_NAME = prev.GSD_WORKFLOW_MCP_NAME;
@@ -250,6 +407,16 @@ describe("stream-adapter — session persistence (#2859)", () => {
250
407
  const mcpServers = options.mcpServers as Record<string, any>;
251
408
  assert.ok(mcpServers?.["custom-workflow"], "expected custom workflow server config");
252
409
  assert.deepEqual(options.disallowedTools, ["AskUserQuestion"]);
410
+ assert.deepEqual(options.allowedTools, [
411
+ "Read",
412
+ "Write",
413
+ "Edit",
414
+ "Glob",
415
+ "Grep",
416
+ "Bash(ls:*)",
417
+ "Bash(pwd)",
418
+ "mcp__custom-workflow__*",
419
+ ]);
253
420
  } finally {
254
421
  process.env.GSD_WORKFLOW_MCP_COMMAND = prev.GSD_WORKFLOW_MCP_COMMAND;
255
422
  process.env.GSD_WORKFLOW_MCP_NAME = prev.GSD_WORKFLOW_MCP_NAME;
@@ -362,7 +529,7 @@ describe("stream-adapter — session persistence (#2859)", () => {
362
529
  delete process.env.GSD_WORKFLOW_MCP_ARGS;
363
530
  delete process.env.GSD_WORKFLOW_MCP_ENV;
364
531
  delete process.env.GSD_WORKFLOW_MCP_CWD;
365
- const options = buildSdkOptions("claude-sonnet-4-20250514", "test", { onElicitation });
532
+ const options = buildSdkOptions("claude-sonnet-4-20250514", "test", undefined, { onElicitation });
366
533
  assert.equal(options.onElicitation, onElicitation);
367
534
  } finally {
368
535
  process.env.GSD_WORKFLOW_MCP_COMMAND = prev.GSD_WORKFLOW_MCP_COMMAND;
@@ -598,9 +765,9 @@ describe("stream-adapter — MCP elicitation bridge", () => {
598
765
  requestedSchema: {
599
766
  type: "object" as const,
600
767
  properties: {
601
- TEST_PASSWORD: {
768
+ TEST_SECURE_FIELD: {
602
769
  type: "string",
603
- title: "TEST_PASSWORD",
770
+ title: "TEST_SECURE_FIELD",
604
771
  description: "Format: Your secure testing password\nLeave empty to skip.",
605
772
  },
606
773
  },
@@ -611,7 +778,7 @@ describe("stream-adapter — MCP elicitation bridge", () => {
611
778
  const handler = createClaudeCodeElicitationHandler({
612
779
  input: async (_title: string, _placeholder?: string, opts?: { secure?: boolean }) => {
613
780
  inputCalls.push({ opts });
614
- return "super-secret";
781
+ return "example-secure-input";
615
782
  },
616
783
  } as any);
617
784
  assert.ok(handler);
@@ -620,7 +787,7 @@ describe("stream-adapter — MCP elicitation bridge", () => {
620
787
  assert.deepEqual(result, {
621
788
  action: "accept",
622
789
  content: {
623
- TEST_PASSWORD: "super-secret",
790
+ TEST_SECURE_FIELD: "example-secure-input",
624
791
  },
625
792
  });
626
793
  assert.equal(inputCalls.length, 1);
@@ -628,6 +795,134 @@ describe("stream-adapter — MCP elicitation bridge", () => {
628
795
  });
629
796
  });
630
797
 
798
+ // ---------------------------------------------------------------------------
799
+ // F2 — abort vs stream-exhausted classification
800
+ // ---------------------------------------------------------------------------
801
+
802
+ describe("stream-adapter — abort classification (F2)", () => {
803
+ test("makeAbortedMessage sets stopReason to 'aborted', not 'error'", () => {
804
+ const message = makeAbortedMessage("claude-sonnet-4-6", "");
805
+ assert.equal(message.stopReason, "aborted");
806
+ assert.equal(message.errorMessage, undefined);
807
+ });
808
+
809
+ test("makeAbortedMessage preserves last-seen text content", () => {
810
+ const message = makeAbortedMessage("claude-sonnet-4-6", "partial mid-stream text");
811
+ assert.deepEqual(message.content, [{ type: "text", text: "partial mid-stream text" }]);
812
+ });
813
+
814
+ test("aborted message is distinguishable from stream-exhausted error", () => {
815
+ const aborted = makeAbortedMessage("claude-sonnet-4-6", "");
816
+ const exhausted = makeStreamExhaustedErrorMessage("claude-sonnet-4-6", "");
817
+ assert.notEqual(aborted.stopReason, exhausted.stopReason);
818
+ assert.equal(exhausted.errorMessage, "stream_exhausted_without_result");
819
+ });
820
+ });
821
+
822
+ // ---------------------------------------------------------------------------
823
+ // F3 — final-turn tool calls not dropped
824
+ // ---------------------------------------------------------------------------
825
+
826
+ describe("stream-adapter — final-turn tool-call merge (F3)", () => {
827
+ function toolCall(id: string, name = "bash"): AssistantMessage["content"][number] {
828
+ return { type: "toolCall", id, name, arguments: {} };
829
+ }
830
+
831
+ test("mergePendingToolCalls appends tool calls not already in intermediate", () => {
832
+ const intermediate: AssistantMessage["content"] = [toolCall("tool-1")];
833
+ const pending: AssistantMessage["content"] = [
834
+ toolCall("tool-2"),
835
+ { type: "text", text: "trailing text" },
836
+ ];
837
+ const merged = mergePendingToolCalls(intermediate, pending);
838
+ assert.equal(merged.length, 2);
839
+ assert.equal((merged[0] as any).id, "tool-1");
840
+ assert.equal((merged[1] as any).id, "tool-2");
841
+ });
842
+
843
+ test("mergePendingToolCalls is idempotent across duplicate ids", () => {
844
+ const intermediate: AssistantMessage["content"] = [toolCall("tool-1")];
845
+ const pending: AssistantMessage["content"] = [toolCall("tool-1"), toolCall("tool-2")];
846
+ const merged = mergePendingToolCalls(intermediate, pending);
847
+ assert.equal(merged.length, 2);
848
+ assert.deepEqual(
849
+ merged.map((b) => (b as any).id),
850
+ ["tool-1", "tool-2"],
851
+ );
852
+ });
853
+
854
+ test("mergePendingToolCalls ignores non-toolCall blocks from pending", () => {
855
+ const intermediate: AssistantMessage["content"] = [];
856
+ const pending: AssistantMessage["content"] = [
857
+ { type: "text", text: "hello" },
858
+ { type: "thinking", thinking: "pondering" },
859
+ toolCall("tool-1"),
860
+ ];
861
+ const merged = mergePendingToolCalls(intermediate, pending);
862
+ assert.equal(merged.length, 1);
863
+ assert.equal((merged[0] as any).id, "tool-1");
864
+ });
865
+ });
866
+
867
+ // ---------------------------------------------------------------------------
868
+ // F10 — permission mode is configurable
869
+ // ---------------------------------------------------------------------------
870
+
871
+ describe("stream-adapter — permission mode (F10)", () => {
872
+ // Earlier tests in this file set GSD_WORKFLOW_MCP_* env vars and restore
873
+ // them by reassigning from `prev.*`. When `prev.*` was undefined, node
874
+ // coerces the assignment to the literal string "undefined", which then
875
+ // fails JSON.parse inside buildWorkflowMcpServers. Clear the relevant
876
+ // slots before each permission-mode test so buildSdkOptions doesn't throw.
877
+ function clearWorkflowMcpEnv(): void {
878
+ for (const key of [
879
+ "GSD_WORKFLOW_MCP_COMMAND",
880
+ "GSD_WORKFLOW_MCP_NAME",
881
+ "GSD_WORKFLOW_MCP_ARGS",
882
+ "GSD_WORKFLOW_MCP_ENV",
883
+ "GSD_WORKFLOW_MCP_CWD",
884
+ ]) {
885
+ if (process.env[key] === undefined || process.env[key] === "undefined") {
886
+ delete process.env[key];
887
+ }
888
+ }
889
+ }
890
+
891
+ test("buildSdkOptions defaults to bypassPermissions for backwards compatibility", () => {
892
+ clearWorkflowMcpEnv();
893
+ const opts = buildSdkOptions("claude-sonnet-4-6", "test");
894
+ assert.equal(opts.permissionMode, "bypassPermissions");
895
+ assert.equal(opts.allowDangerouslySkipPermissions, true);
896
+ });
897
+
898
+ test("buildSdkOptions respects explicit acceptEdits override", () => {
899
+ clearWorkflowMcpEnv();
900
+ const opts = buildSdkOptions("claude-sonnet-4-6", "test", { permissionMode: "acceptEdits" });
901
+ assert.equal(opts.permissionMode, "acceptEdits");
902
+ assert.equal(
903
+ opts.allowDangerouslySkipPermissions,
904
+ false,
905
+ "allowDangerouslySkipPermissions must be false for non-bypass modes",
906
+ );
907
+ });
908
+
909
+ test("resolveClaudePermissionMode honours the GSD_CLAUDE_CODE_PERMISSION_MODE env override", async () => {
910
+ const env = { GSD_CLAUDE_CODE_PERMISSION_MODE: "acceptEdits" } as NodeJS.ProcessEnv;
911
+ const mode = await resolveClaudePermissionMode(env);
912
+ assert.equal(mode, "acceptEdits");
913
+ });
914
+
915
+ test("resolveClaudePermissionMode rejects unknown override values (fallback path)", async () => {
916
+ const env = { GSD_CLAUDE_CODE_PERMISSION_MODE: "nonsense" } as NodeJS.ProcessEnv;
917
+ const mode = await resolveClaudePermissionMode(env);
918
+ // Unknown override falls back to auto-detect → either bypass or acceptEdits
919
+ assert.ok(
920
+ mode === "bypassPermissions" || mode === "acceptEdits",
921
+ `expected bypass or acceptEdits, got ${mode}`,
922
+ );
923
+ });
924
+ });
925
+
631
926
  describe("stream-adapter — Windows Claude path lookup (#3770)", () => {
632
927
  test("getClaudeLookupCommand uses where on Windows", () => {
633
928
  assert.equal(getClaudeLookupCommand("win32"), "where claude");
@@ -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,8 +27,71 @@ 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
+ import { logWarning } from "../workflow-logger.js";
33
+ import { gsdRoot } from "../paths.js";
34
+ import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
35
+ import { join } from "node:path";
36
+
37
+ // ── Stuck detection persistence (#3704) ──────────────────────────────────
38
+ // Persist stuck detection state to disk so it survives session restarts.
39
+ // Without this, restarting auto-mode resets all counters, allowing the
40
+ // same blocked unit to burn a full retry budget each session.
41
+ function stuckStatePath(basePath: string): string {
42
+ return join(gsdRoot(basePath), "runtime", "stuck-state.json");
43
+ }
44
+
45
+ function loadStuckState(basePath: string): { recentUnits: Array<{ key: string }>; stuckRecoveryAttempts: number } {
46
+ try {
47
+ const data = JSON.parse(readFileSync(stuckStatePath(basePath), "utf-8"));
48
+ return {
49
+ recentUnits: Array.isArray(data.recentUnits) ? data.recentUnits : [],
50
+ stuckRecoveryAttempts: typeof data.stuckRecoveryAttempts === "number" ? data.stuckRecoveryAttempts : 0,
51
+ };
52
+ } catch (err) {
53
+ debugLog("autoLoop", { phase: "load-stuck-state-failed", error: err instanceof Error ? err.message : String(err) });
54
+ return { recentUnits: [], stuckRecoveryAttempts: 0 };
55
+ }
56
+ }
57
+
58
+ function saveStuckState(basePath: string, state: LoopState): void {
59
+ try {
60
+ const filePath = stuckStatePath(basePath);
61
+ mkdirSync(join(gsdRoot(basePath), "runtime"), { recursive: true });
62
+ writeFileSync(filePath, JSON.stringify({
63
+ recentUnits: state.recentUnits.slice(-20), // keep last 20 entries
64
+ stuckRecoveryAttempts: state.stuckRecoveryAttempts,
65
+ updatedAt: new Date().toISOString(),
66
+ }) + "\n");
67
+ } catch (err) {
68
+ debugLog("autoLoop", { phase: "save-stuck-state-failed", error: err instanceof Error ? err.message : String(err) });
69
+ }
70
+ }
71
+
72
+ // ── Memory pressure monitoring (#3331) ──────────────────────────────────
73
+ // Check heap usage every N iterations and trigger graceful shutdown before
74
+ // the OS OOM killer sends SIGKILL. The threshold is 90% of the V8 heap
75
+ // limit (--max-old-space-size or default ~1.5-4GB depending on platform).
76
+ const MEMORY_CHECK_INTERVAL = 5; // check every 5 iterations
77
+ const MEMORY_PRESSURE_THRESHOLD = 0.85; // 85% of heap limit
78
+
79
+ function checkMemoryPressure(): { pressured: boolean; heapMB: number; limitMB: number; pct: number } {
80
+ const mem = process.memoryUsage();
81
+ // v8.getHeapStatistics() gives heap_size_limit but requires import
82
+ // Use a conservative estimate: RSS > 3GB is danger zone on most systems
83
+ const heapMB = Math.round(mem.heapUsed / 1024 / 1024);
84
+ const rssMB = Math.round(mem.rss / 1024 / 1024);
85
+ // Try to get the actual V8 heap limit
86
+ let limitMB = 4096; // conservative default
87
+ try {
88
+ const v8 = require("node:v8");
89
+ const stats = v8.getHeapStatistics();
90
+ limitMB = Math.round(stats.heap_size_limit / 1024 / 1024);
91
+ } catch { limitMB = 4096; /* v8 stats unavailable — use conservative default */ }
92
+ const pct = heapMB / limitMB;
93
+ return { pressured: pct > MEMORY_PRESSURE_THRESHOLD, heapMB, limitMB, pct };
94
+ }
32
95
 
33
96
  /**
34
97
  * Main auto-mode execution loop. Iterates: derive → dispatch → guards →
@@ -46,8 +109,15 @@ export async function autoLoop(
46
109
  ): Promise<void> {
47
110
  debugLog("autoLoop", { phase: "enter" });
48
111
  let iteration = 0;
49
- const loopState: LoopState = { recentUnits: [], stuckRecoveryAttempts: 0, consecutiveFinalizeTimeouts: 0 };
112
+ // Load persisted stuck state so counters survive session restarts (#3704)
113
+ const persisted = loadStuckState(s.basePath);
114
+ const loopState: LoopState = {
115
+ recentUnits: persisted.recentUnits,
116
+ stuckRecoveryAttempts: persisted.stuckRecoveryAttempts,
117
+ consecutiveFinalizeTimeouts: 0,
118
+ };
50
119
  let consecutiveErrors = 0;
120
+ let consecutiveCooldowns = 0;
51
121
  const recentErrorMessages: string[] = [];
52
122
 
53
123
  while (s.active) {
@@ -73,6 +143,24 @@ export async function autoLoop(
73
143
  break;
74
144
  }
75
145
 
146
+ // ── Memory pressure check (#3331) ──
147
+ // Graceful shutdown before OOM killer sends SIGKILL.
148
+ if (iteration % MEMORY_CHECK_INTERVAL === 0) {
149
+ const mem = checkMemoryPressure();
150
+ debugLog("autoLoop", { phase: "memory-check", ...mem });
151
+ if (mem.pressured) {
152
+ logWarning("dispatch", `Memory pressure: ${mem.heapMB}MB / ${mem.limitMB}MB (${Math.round(mem.pct * 100)}%) — stopping auto-mode to prevent OOM kill`);
153
+ await deps.stopAuto(
154
+ ctx,
155
+ pi,
156
+ `Memory pressure: heap at ${mem.heapMB}MB / ${mem.limitMB}MB (${Math.round(mem.pct * 100)}%). ` +
157
+ `Stopping gracefully to prevent OOM kill after ${iteration} iterations. ` +
158
+ `Resume with /gsd auto to continue from where you left off.`,
159
+ );
160
+ break;
161
+ }
162
+ }
163
+
76
164
  if (!s.cmdCtx) {
77
165
  debugLog("autoLoop", { phase: "exit", reason: "no-cmdCtx" });
78
166
  break;
@@ -203,8 +291,10 @@ export async function autoLoop(
203
291
 
204
292
  deps.clearUnitTimeout();
205
293
  consecutiveErrors = 0;
294
+ consecutiveCooldowns = 0;
206
295
  recentErrorMessages.length = 0;
207
296
  deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
297
+ saveStuckState(s.basePath, loopState); // persist across session restarts (#3704)
208
298
  debugLog("autoLoop", { phase: "iteration-complete", iteration });
209
299
 
210
300
  if (reconcileResult.outcome === "milestone-complete") {
@@ -265,6 +355,7 @@ export async function autoLoop(
265
355
  if (finalizeResult.action === "continue") continue;
266
356
 
267
357
  consecutiveErrors = 0; // Iteration completed successfully
358
+ consecutiveCooldowns = 0;
268
359
  recentErrorMessages.length = 0;
269
360
  deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
270
361
  debugLog("autoLoop", { phase: "iteration-complete", iteration });
@@ -300,6 +391,47 @@ export async function autoLoop(
300
391
  break;
301
392
  }
302
393
 
394
+ // ── Credential cooldown: wait and retry with bounded budget ──
395
+ // A 429 triggers a 30s credential backoff in AuthStorage. If the SDK's
396
+ // getApiKey() retries couldn't outlast the window, the error surfaces
397
+ // here. Wait for the cooldown to clear rather than counting it as a
398
+ // consecutive failure — but cap retries so we don't spin for hours
399
+ // on persistent quota exhaustion.
400
+ if (isTransientCooldownError(loopErr)) {
401
+ consecutiveCooldowns++;
402
+ const retryAfterMs = getCooldownRetryAfterMs(loopErr);
403
+ debugLog("autoLoop", {
404
+ phase: "cooldown-wait",
405
+ iteration,
406
+ consecutiveCooldowns,
407
+ retryAfterMs,
408
+ error: msg,
409
+ });
410
+
411
+ if (consecutiveCooldowns > MAX_COOLDOWN_RETRIES) {
412
+ ctx.ui.notify(
413
+ `Auto-mode stopped: ${consecutiveCooldowns} consecutive credential cooldowns — rate limit or quota may be persistently exhausted.`,
414
+ "error",
415
+ );
416
+ await deps.stopAuto(
417
+ ctx,
418
+ pi,
419
+ `${consecutiveCooldowns} consecutive credential cooldowns exceeded retry budget`,
420
+ );
421
+ break;
422
+ }
423
+
424
+ const waitMs = (retryAfterMs !== undefined && retryAfterMs > 0 && retryAfterMs <= 60_000)
425
+ ? retryAfterMs + 500 // Use structured hint + small buffer
426
+ : COOLDOWN_FALLBACK_WAIT_MS;
427
+ ctx.ui.notify(
428
+ `Credentials in cooldown (${consecutiveCooldowns}/${MAX_COOLDOWN_RETRIES}) — waiting ${Math.round(waitMs / 1000)}s before retrying.`,
429
+ "warning",
430
+ );
431
+ await new Promise(resolve => setTimeout(resolve, waitMs));
432
+ continue; // Retry iteration without incrementing consecutiveErrors
433
+ }
434
+
303
435
  consecutiveErrors++;
304
436
  recentErrorMessages.push(msg.length > 120 ? msg.slice(0, 120) + "..." : msg);
305
437
  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",