gsd-pi 2.71.0 → 2.72.0-dev.8f83716

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (465) hide show
  1. package/README.md +57 -17
  2. package/dist/cli.js +29 -3
  3. package/dist/headless-events.d.ts +2 -0
  4. package/dist/headless-events.js +7 -0
  5. package/dist/headless.js +16 -3
  6. package/dist/mcp-server.js +40 -17
  7. package/dist/provider-migrations.d.ts +10 -0
  8. package/dist/provider-migrations.js +12 -0
  9. package/dist/resource-loader.js +139 -13
  10. package/dist/resources/GSD-WORKFLOW.md +1 -1
  11. package/dist/resources/agents/debugger.md +58 -0
  12. package/dist/resources/agents/doc-writer.md +43 -0
  13. package/dist/resources/agents/git-ops.md +56 -0
  14. package/dist/resources/agents/javascript-pro.md +46 -271
  15. package/dist/resources/agents/planner.md +55 -0
  16. package/dist/resources/agents/refactorer.md +47 -0
  17. package/dist/resources/agents/reviewer.md +48 -0
  18. package/dist/resources/agents/security.md +59 -0
  19. package/dist/resources/agents/tester.md +50 -0
  20. package/dist/resources/agents/typescript-pro.md +41 -235
  21. package/dist/resources/extensions/claude-code-cli/partial-builder.js +40 -12
  22. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +133 -14
  23. package/dist/resources/extensions/gsd/auto/infra-errors.js +34 -0
  24. package/dist/resources/extensions/gsd/auto/loop.js +32 -1
  25. package/dist/resources/extensions/gsd/auto/phases.js +5 -1
  26. package/dist/resources/extensions/gsd/auto/session.js +11 -0
  27. package/dist/resources/extensions/gsd/auto-dashboard.js +22 -16
  28. package/dist/resources/extensions/gsd/auto-model-selection.js +10 -2
  29. package/dist/resources/extensions/gsd/auto-prompts.js +88 -33
  30. package/dist/resources/extensions/gsd/auto-start.js +34 -7
  31. package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
  32. package/dist/resources/extensions/gsd/auto-worktree.js +1 -1
  33. package/dist/resources/extensions/gsd/auto.js +56 -0
  34. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -3
  35. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +2 -0
  36. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +63 -51
  37. package/dist/resources/extensions/gsd/bootstrap/system-context.js +6 -0
  38. package/dist/resources/extensions/gsd/commands/context.js +15 -6
  39. package/dist/resources/extensions/gsd/commands/dispatcher.js +12 -2
  40. package/dist/resources/extensions/gsd/commands/handlers/auto.js +10 -33
  41. package/dist/resources/extensions/gsd/commands/handlers/core.js +56 -11
  42. package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +15 -6
  43. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +4 -10
  44. package/dist/resources/extensions/gsd/dashboard-overlay.js +8 -3
  45. package/dist/resources/extensions/gsd/dispatch-guard.js +18 -1
  46. package/dist/resources/extensions/gsd/doctor-providers.js +23 -0
  47. package/dist/resources/extensions/gsd/error-classifier.js +5 -2
  48. package/dist/resources/extensions/gsd/forensics.js +19 -6
  49. package/dist/resources/extensions/gsd/gate-registry.js +208 -0
  50. package/dist/resources/extensions/gsd/gsd-db.js +41 -0
  51. package/dist/resources/extensions/gsd/guided-flow.js +5 -10
  52. package/dist/resources/extensions/gsd/metrics.js +1 -0
  53. package/dist/resources/extensions/gsd/milestone-actions.js +10 -4
  54. package/dist/resources/extensions/gsd/milestone-validation-gates.js +11 -12
  55. package/dist/resources/extensions/gsd/notification-overlay.js +42 -13
  56. package/dist/resources/extensions/gsd/notification-store.js +56 -5
  57. package/dist/resources/extensions/gsd/notification-widget.js +5 -13
  58. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +8 -3
  59. package/dist/resources/extensions/gsd/pre-execution-checks.js +35 -2
  60. package/dist/resources/extensions/gsd/prompt-validation.js +126 -0
  61. package/dist/resources/extensions/gsd/prompts/complete-slice.md +5 -3
  62. package/dist/resources/extensions/gsd/prompts/discuss.md +2 -0
  63. package/dist/resources/extensions/gsd/prompts/execute-task.md +22 -19
  64. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  65. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
  66. package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  67. package/dist/resources/extensions/gsd/prompts/queue.md +3 -2
  68. package/dist/resources/extensions/gsd/prompts/system.md +1 -0
  69. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
  70. package/dist/resources/extensions/gsd/session-model-override.js +25 -0
  71. package/dist/resources/extensions/gsd/shortcut-defs.js +40 -0
  72. package/dist/resources/extensions/gsd/state.js +9 -2
  73. package/dist/resources/extensions/gsd/tools/complete-slice.js +52 -1
  74. package/dist/resources/extensions/gsd/tools/complete-task.js +51 -1
  75. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +4 -1
  76. package/dist/resources/extensions/ollama/index.js +13 -5
  77. package/dist/resources/extensions/shared/gsd-phase-state.js +35 -0
  78. package/dist/resources/extensions/subagent/agents.js +8 -0
  79. package/dist/resources/extensions/subagent/index.js +17 -0
  80. package/dist/resources/skills/create-skill/SKILL.md +2 -0
  81. package/dist/startup-model-validation.d.ts +0 -1
  82. package/dist/startup-model-validation.js +6 -2
  83. package/dist/web/standalone/.next/BUILD_ID +1 -1
  84. package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
  85. package/dist/web/standalone/.next/build-manifest.json +3 -3
  86. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  87. package/dist/web/standalone/.next/required-server-files.json +3 -3
  88. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  89. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  99. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  115. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  127. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  147. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  157. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  163. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  179. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
  183. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/index.html +1 -1
  193. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  194. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  195. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  196. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  197. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  198. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  199. package/dist/web/standalone/.next/server/app/page.js +2 -2
  200. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
  202. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  203. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  204. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  205. package/dist/web/standalone/.next/server/middleware.js +2 -2
  206. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  207. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  208. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  209. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  210. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  211. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  212. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  213. package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +1 -0
  214. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  215. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  216. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  217. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  218. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  219. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  220. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  221. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  222. package/dist/web/standalone/server.js +1 -1
  223. package/package.json +1 -1
  224. package/packages/mcp-server/dist/server.d.ts +12 -1
  225. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  226. package/packages/mcp-server/dist/server.js +90 -42
  227. package/packages/mcp-server/dist/server.js.map +1 -1
  228. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  229. package/packages/mcp-server/dist/workflow-tools.js +22 -12
  230. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  231. package/packages/mcp-server/src/server.ts +110 -38
  232. package/packages/mcp-server/src/workflow-tools.test.ts +110 -0
  233. package/packages/mcp-server/src/workflow-tools.ts +32 -12
  234. package/packages/pi-ai/dist/providers/amazon-bedrock.js +11 -2
  235. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  236. package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts +2 -0
  237. package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts.map +1 -0
  238. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +20 -0
  239. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -0
  240. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts +4 -1
  241. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  242. package/packages/pi-ai/dist/providers/anthropic-shared.js +8 -3
  243. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  244. package/packages/pi-ai/dist/providers/anthropic-shared.test.js +44 -1
  245. package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -1
  246. package/packages/pi-ai/dist/providers/anthropic.d.ts +2 -1
  247. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  248. package/packages/pi-ai/dist/providers/anthropic.js +7 -4
  249. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  250. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  251. package/packages/pi-ai/dist/providers/openai-completions.js +11 -0
  252. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  253. package/packages/pi-ai/src/providers/amazon-bedrock.ts +13 -1
  254. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +32 -0
  255. package/packages/pi-ai/src/providers/anthropic-shared.test.ts +55 -1
  256. package/packages/pi-ai/src/providers/anthropic-shared.ts +14 -3
  257. package/packages/pi-ai/src/providers/anthropic.ts +8 -4
  258. package/packages/pi-ai/src/providers/openai-completions.ts +14 -0
  259. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts +2 -0
  260. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts.map +1 -0
  261. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js +61 -0
  262. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js.map +1 -0
  263. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  264. package/packages/pi-coding-agent/dist/core/agent-session.js +2 -1
  265. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  266. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +10 -0
  267. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/auth-storage.js +27 -0
  269. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  270. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +85 -0
  271. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts +2 -0
  273. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts.map +1 -0
  274. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js +64 -0
  275. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js.map +1 -0
  276. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  277. package/packages/pi-coding-agent/dist/core/model-resolver.js +22 -18
  278. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts +8 -0
  280. package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts.map +1 -0
  281. package/packages/pi-coding-agent/dist/core/model-resolver.test.js +75 -0
  282. package/packages/pi-coding-agent/dist/core/model-resolver.test.js.map +1 -0
  283. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +5 -0
  284. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/retry-handler.js +55 -1
  286. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +57 -0
  288. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/sdk.d.ts +11 -0
  290. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  291. package/packages/pi-coding-agent/dist/core/sdk.js +38 -5
  292. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/sdk.test.d.ts +2 -0
  294. package/packages/pi-coding-agent/dist/core/sdk.test.d.ts.map +1 -0
  295. package/packages/pi-coding-agent/dist/core/sdk.test.js +71 -0
  296. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -0
  297. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  298. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  299. package/packages/pi-coding-agent/dist/index.js +1 -1
  300. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  301. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts +2 -0
  302. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts.map +1 -0
  303. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js +13 -0
  304. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js.map +1 -0
  305. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -0
  306. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  307. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +4 -0
  308. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  309. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +24 -2
  310. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  311. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  312. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +9 -2
  313. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  314. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +4 -0
  315. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  316. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +130 -12
  317. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  318. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  319. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +7 -2
  320. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  321. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.d.ts.map +1 -1
  322. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js +6 -1
  323. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js.map +1 -1
  324. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  325. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -3
  326. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  327. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +4 -2
  328. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  329. package/packages/pi-coding-agent/package.json +1 -1
  330. package/packages/pi-coding-agent/src/core/agent-session-renderable-tools.test.ts +70 -0
  331. package/packages/pi-coding-agent/src/core/agent-session.ts +2 -1
  332. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +108 -0
  333. package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -0
  334. package/packages/pi-coding-agent/src/core/model-resolver-initial-model-auth.test.ts +78 -0
  335. package/packages/pi-coding-agent/src/core/model-resolver.test.ts +85 -0
  336. package/packages/pi-coding-agent/src/core/model-resolver.ts +22 -18
  337. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +83 -0
  338. package/packages/pi-coding-agent/src/core/retry-handler.ts +60 -1
  339. package/packages/pi-coding-agent/src/core/sdk.test.ts +89 -0
  340. package/packages/pi-coding-agent/src/core/sdk.ts +45 -9
  341. package/packages/pi-coding-agent/src/index.ts +1 -0
  342. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/login-dialog.test.ts +24 -0
  343. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +72 -0
  344. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +30 -2
  345. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +15 -6
  346. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +131 -12
  347. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +7 -2
  348. package/packages/pi-coding-agent/src/modes/interactive/controllers/model-controller.ts +6 -1
  349. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +4 -3
  350. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +4 -2
  351. package/pkg/package.json +1 -1
  352. package/src/resources/GSD-WORKFLOW.md +1 -1
  353. package/src/resources/agents/debugger.md +58 -0
  354. package/src/resources/agents/doc-writer.md +43 -0
  355. package/src/resources/agents/git-ops.md +56 -0
  356. package/src/resources/agents/javascript-pro.md +46 -271
  357. package/src/resources/agents/planner.md +55 -0
  358. package/src/resources/agents/refactorer.md +47 -0
  359. package/src/resources/agents/reviewer.md +48 -0
  360. package/src/resources/agents/security.md +59 -0
  361. package/src/resources/agents/tester.md +50 -0
  362. package/src/resources/agents/typescript-pro.md +41 -235
  363. package/src/resources/extensions/claude-code-cli/partial-builder.ts +45 -12
  364. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +143 -13
  365. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +91 -2
  366. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +281 -6
  367. package/src/resources/extensions/gsd/auto/infra-errors.ts +38 -0
  368. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
  369. package/src/resources/extensions/gsd/auto/loop.ts +45 -1
  370. package/src/resources/extensions/gsd/auto/phases.ts +6 -0
  371. package/src/resources/extensions/gsd/auto/session.ts +11 -0
  372. package/src/resources/extensions/gsd/auto-dashboard.ts +29 -18
  373. package/src/resources/extensions/gsd/auto-model-selection.ts +9 -1
  374. package/src/resources/extensions/gsd/auto-prompts.ts +111 -33
  375. package/src/resources/extensions/gsd/auto-start.ts +41 -7
  376. package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
  377. package/src/resources/extensions/gsd/auto-worktree.ts +1 -1
  378. package/src/resources/extensions/gsd/auto.ts +72 -0
  379. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
  380. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +2 -0
  381. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +79 -60
  382. package/src/resources/extensions/gsd/bootstrap/system-context.ts +7 -0
  383. package/src/resources/extensions/gsd/commands/context.ts +16 -5
  384. package/src/resources/extensions/gsd/commands/dispatcher.ts +14 -2
  385. package/src/resources/extensions/gsd/commands/handlers/auto.ts +10 -36
  386. package/src/resources/extensions/gsd/commands/handlers/core.ts +58 -11
  387. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +17 -7
  388. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +4 -10
  389. package/src/resources/extensions/gsd/dashboard-overlay.ts +10 -3
  390. package/src/resources/extensions/gsd/dispatch-guard.ts +18 -1
  391. package/src/resources/extensions/gsd/doctor-providers.ts +24 -0
  392. package/src/resources/extensions/gsd/error-classifier.ts +5 -2
  393. package/src/resources/extensions/gsd/forensics.ts +23 -7
  394. package/src/resources/extensions/gsd/gate-registry.ts +251 -0
  395. package/src/resources/extensions/gsd/gsd-db.ts +51 -0
  396. package/src/resources/extensions/gsd/guided-flow.ts +5 -10
  397. package/src/resources/extensions/gsd/interrupted-session.ts +1 -0
  398. package/src/resources/extensions/gsd/metrics.ts +12 -1
  399. package/src/resources/extensions/gsd/milestone-actions.ts +10 -3
  400. package/src/resources/extensions/gsd/milestone-validation-gates.ts +11 -13
  401. package/src/resources/extensions/gsd/notification-overlay.ts +47 -14
  402. package/src/resources/extensions/gsd/notification-store.ts +54 -5
  403. package/src/resources/extensions/gsd/notification-widget.ts +5 -14
  404. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -3
  405. package/src/resources/extensions/gsd/pre-execution-checks.ts +39 -2
  406. package/src/resources/extensions/gsd/prompt-validation.ts +157 -0
  407. package/src/resources/extensions/gsd/prompts/complete-slice.md +5 -3
  408. package/src/resources/extensions/gsd/prompts/discuss.md +2 -0
  409. package/src/resources/extensions/gsd/prompts/execute-task.md +22 -19
  410. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  411. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
  412. package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  413. package/src/resources/extensions/gsd/prompts/queue.md +3 -2
  414. package/src/resources/extensions/gsd/prompts/system.md +1 -0
  415. package/src/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
  416. package/src/resources/extensions/gsd/session-model-override.ts +36 -0
  417. package/src/resources/extensions/gsd/shortcut-defs.ts +56 -0
  418. package/src/resources/extensions/gsd/state.ts +13 -2
  419. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +25 -9
  420. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +28 -0
  421. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +39 -0
  422. package/src/resources/extensions/gsd/tests/complete-slice-gate-closure.test.ts +167 -0
  423. package/src/resources/extensions/gsd/tests/complete-slice-prompt-task-summary-layout.test.ts +18 -0
  424. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
  425. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +36 -0
  426. package/src/resources/extensions/gsd/tests/execute-task-prompt-existing-artifact-guard.test.ts +33 -0
  427. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +62 -0
  428. package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +31 -0
  429. package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +27 -0
  430. package/src/resources/extensions/gsd/tests/gate-registry.test.ts +140 -0
  431. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +73 -0
  432. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +180 -0
  433. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +66 -1
  434. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +36 -51
  435. package/src/resources/extensions/gsd/tests/notification-store.test.ts +35 -0
  436. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +26 -0
  437. package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +90 -0
  438. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +1 -0
  439. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +18 -0
  440. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +49 -0
  441. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +19 -0
  442. package/src/resources/extensions/gsd/tests/prompt-system-gate-coverage.test.ts +208 -0
  443. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +16 -0
  444. package/src/resources/extensions/gsd/tests/register-shortcuts.test.ts +63 -5
  445. package/src/resources/extensions/gsd/tests/session-model-override.test.ts +35 -0
  446. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +90 -0
  447. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +7 -0
  448. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +18 -0
  449. package/src/resources/extensions/gsd/tools/complete-slice.ts +63 -0
  450. package/src/resources/extensions/gsd/tools/complete-task.ts +63 -0
  451. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +4 -1
  452. package/src/resources/extensions/gsd/types.ts +26 -0
  453. package/src/resources/extensions/ollama/index.ts +13 -3
  454. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +28 -0
  455. package/src/resources/extensions/shared/gsd-phase-state.ts +42 -0
  456. package/src/resources/extensions/shared/tests/gsd-phase-state.test.ts +48 -0
  457. package/src/resources/extensions/subagent/agents.ts +10 -0
  458. package/src/resources/extensions/subagent/index.ts +18 -0
  459. package/src/resources/extensions/subagent/tests/agents-conflicts.test.ts +33 -0
  460. package/src/resources/skills/create-skill/SKILL.md +2 -0
  461. package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
  462. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  463. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  464. /package/dist/web/standalone/.next/static/{nPky_WQC28aBD77eZsRAB → nCL1Ivw47iAAoKVgerXNi}/_buildManifest.js +0 -0
  465. /package/dist/web/standalone/.next/static/{nPky_WQC28aBD77eZsRAB → nCL1Ivw47iAAoKVgerXNi}/_ssgManifest.js +0 -0
package/README.md CHANGED
@@ -27,36 +27,68 @@ One command. Walk away. Come back to a built project with clean git history.
27
27
 
28
28
  ---
29
29
 
30
- ## What's New in v2.68
30
+ ## What's New in v2.71
31
31
 
32
- ### MCP Workflow Tools
32
+ ### MCP Secure Env Collect
33
33
 
34
- - **Full workflow over MCP** — slice replanning, milestone management, slice completion, task completion, and core planning tools are now exposed over MCP for external integrations.
35
- - **Transport-gated MCP** — workflow tool availability adapts to provider transport capabilities automatically.
36
- - **Write gate enforcement** — workflow MCP respects write gates, preventing unauthorized state mutations from external clients.
34
+ - **Secure credential collection over MCP** — the new `secure_env_collect` tool uses MCP form elicitation to collect secrets (API keys, tokens) from external clients without exposing values in tool output. Masks input in interactive mode.
35
+ - **Hardened elicitation schema** — MCP elicitation schema handling is stricter, with proper validation and fallback for providers that don't support forms.
37
36
 
38
- ### Reliability & Recovery
37
+ ### MCP Reliability
39
38
 
40
- - **False degraded-mode fix** — eliminates spurious degraded-mode warnings when the DB hasn't been initialized yet.
41
- - **Stale session resume suppression** — prevents stale interrupted-session resume prompts from hijacking fresh sessions.
42
- - **Merge conflict recovery** — `autoCommitDirtyState` guarded with cwd restore on `MergeConflictError`.
43
- - **Auto-resume hardening** — `autoStartTime` restored on resume, managed resources resynced on auto resume.
39
+ - **Stream ordering preserved** — MCP tool output now renders in the correct order, fixing interleaved output in Claude Code and other MCP clients.
40
+ - **isError flag propagation** — workflow tool execution failures now correctly return `isError: true`, so MCP clients can distinguish success from failure.
41
+ - **Multi-round discuss questions** — new-project discuss phase supports multi-round questioning with structured question gates.
44
42
 
45
- ### TUI & Developer Experience
43
+ ### Model Selection Hardening
46
44
 
47
- - **Contextual tips system** — TUI and web terminal now surface contextual tips based on workflow state.
48
- - **Claude Code MCP streaming** — real-time streaming and tool output rendering for Claude Code MCP connections.
45
+ - **Unconfigured models blocked** — models without a configured provider are filtered from selection surfaces, preventing dispatch failures.
46
+ - **Provider readiness required** — saved default model selection now verifies the provider is ready before accepting it.
47
+ - **Session override honored** — `/gsd model` selection persists as a session override across all dispatch phases.
48
+ - **Minimal context guard** — model override logic is skipped in minimal command contexts where it doesn't apply.
49
49
 
50
- ### Infrastructure
50
+ ### Auto-Mode Resilience
51
51
 
52
- - **Weekly model registry refresh** — CI workflow auto-regenerates the model registry on a weekly schedule.
53
- - **Codebase cache auto-refresh** — stale codebase cache is refreshed automatically without manual intervention.
52
+ - **Credential cooldown recovery** — auto-mode survives transient 429 rate-limit responses with structured cooldown errors and a bounded retry budget.
53
+ - **Fire-and-forget auto start** — auto start is detached from active turns to prevent blocking.
54
+ - **Scoped forensics** — stuck-loop forensics are now scoped to auto sessions only, preventing false positives in interactive use.
55
+
56
+ ### TUI Improvements
57
+
58
+ - **Overlay subscription fix** — resolved overlay subscription lifecycle and `Ctrl+Shift+P` shortcut conflict.
59
+ - **Improved overlays and shortcuts** — GSD overlays, keyboard shortcuts, and notification flows redesigned for consistency.
60
+ - **Pinned output restored** — pinned output bar displays above the editor during tool execution again.
61
+ - **Turn completion cleanup** — pinned latest output is cleared on turn completion, preventing stale output from persisting.
62
+ - **Secure input masking** — extension input values are masked in interactive mode when collecting secrets.
63
+
64
+ ### Provider Fixes
65
+
66
+ - **Full OAuth login URLs** — OAuth login URLs are now displayed in full instead of being truncated.
67
+ - **MiniMax bearer auth** — MiniMax Anthropic API requests use proper bearer authentication.
68
+ - **Case-insensitive tool rendering** — renderable tool matching is now case-insensitive, fixing missed tool output.
69
+ - **Headless idle timeout** — idle timeout is kept off during interactive tool execution in headless mode.
70
+
71
+ ### Reliability & Internals
72
+
73
+ - **TOCTOU file locking** — race conditions in event log and custom workflow graph file locking are fixed with proper atomic lock acquisition.
74
+ - **State derive refactor** — `deriveStateFromDb` god function extracted into composable, testable helpers.
75
+ - **Windows portability** — hardened cross-platform portability across runtime, tooling, and CI.
76
+ - **Model routing transparency** — dynamic routing is skipped for interactive dispatches; model changes are always shown in the banner.
77
+ - **Capability-aware routing (ADR-004)** — full implementation of capability scoring, `before_model_select` hook, and task metadata extraction.
78
+ - **Multi-model provider strategy (ADR-005)** — infrastructure for multi-provider model selection wired into live paths.
79
+ - **Anti-fabrication guardrails** — discuss prompts enforce turn-taking to prevent fabricated user responses.
80
+ - **Milestone worktree cleanup** — merged worktree cleanup uses the milestone branch instead of generic lookups.
81
+ - **Tool cache control** — `cache_control` breakpoints added to tool definitions for improved prompt caching.
54
82
 
55
83
  See the full [Changelog](./CHANGELOG.md) for details on every release.
56
84
 
57
85
  <details>
58
- <summary>Previous highlights (v2.67 and earlier)</summary>
86
+ <summary>Previous highlights (v2.70 and earlier)</summary>
59
87
 
88
+ - **Full workflow over MCP (v2.68)** — slice replanning, milestone management, slice completion, task completion, and core planning tools exposed over MCP
89
+ - **Transport-gated MCP (v2.68)** — workflow tool availability adapts to provider transport capabilities automatically
90
+ - **Contextual tips system (v2.68)** — TUI and web terminal surface contextual tips based on workflow state
91
+ - **Ask user questions over MCP (v2.70)** — interactive questions exposed via elicitation for external integrations
60
92
  - **Tiered Context Injection (M005)** — relevance-scoped context with 65%+ token reduction
61
93
  - **Resilient transient error recovery** — defers to Core RetryHandler and fixes cmdCtx race conditions
62
94
  - **Anthropic subscription routing** — auto-routed through Claude Code CLI provider with proper display names
@@ -725,6 +757,14 @@ Use expensive models where quality matters (planning, complex execution) and che
725
757
 
726
758
  ---
727
759
 
760
+ ## Ecosystem
761
+
762
+ | Project | Description |
763
+ | ------- | ----------- |
764
+ | [GSD2 Config Utility](https://github.com/jeremymcs/gsd2-config) | Standalone configuration tool for managing GSD preferences, providers, and API keys |
765
+
766
+ ---
767
+
728
768
  ## Star History
729
769
 
730
770
  <a href="https://star-history.com/#gsd-build/gsd-2&Date">
package/dist/cli.js CHANGED
@@ -7,6 +7,7 @@ import { ensureManagedTools } from './tool-bootstrap.js';
7
7
  import { loadStoredEnvKeys } from './wizard.js';
8
8
  import { migratePiCredentials } from './pi-migration.js';
9
9
  import { validateConfiguredModel } from './startup-model-validation.js';
10
+ import { shouldMigrateAnthropicToClaudeCode } from './provider-migrations.js';
10
11
  import { shouldRunOnboarding, runOnboarding } from './onboarding.js';
11
12
  import chalk from 'chalk';
12
13
  import { checkForUpdates } from './update-check.js';
@@ -233,6 +234,14 @@ if (cliFlags.messages[0] === 'sessions') {
233
234
  rl.question(chalk.bold(' Enter session number to resume (or q to quit): '), resolve);
234
235
  });
235
236
  rl.close();
237
+ // Clean up stdin state left by readline.createInterface().
238
+ // Without this, downstream TUI initialization gets corrupted listeners and exhibits
239
+ // duplicate terminal I/O. Match the pattern used after onboarding cleanup.
240
+ process.stdin.removeAllListeners('data');
241
+ process.stdin.removeAllListeners('keypress');
242
+ if (process.stdin.setRawMode)
243
+ process.stdin.setRawMode(false);
244
+ process.stdin.pause();
236
245
  const choice = parseInt(answer, 10);
237
246
  if (isNaN(choice) || choice < 1 || choice > toShow.length) {
238
247
  process.stderr.write(chalk.dim('Cancelled.\n'));
@@ -285,7 +294,7 @@ const { resolveModelsJsonPath } = await import('./models-resolver.js');
285
294
  const modelsJsonPath = resolveModelsJsonPath();
286
295
  const modelRegistry = new ModelRegistry(authStorage, modelsJsonPath);
287
296
  markStartup('ModelRegistry');
288
- const settingsManager = SettingsManager.create(agentDir);
297
+ const settingsManager = SettingsManager.create(process.cwd(), agentDir);
289
298
  applySecurityOverrides(settingsManager);
290
299
  markStartup('SettingsManager.create');
291
300
  // Run onboarding wizard on first launch (no LLM provider configured)
@@ -401,7 +410,11 @@ if (isPrintMode) {
401
410
  // Migrate anthropic OAuth users to claude-code provider when CLI is available (#3772).
402
411
  // Anthropic blocks third-party apps from using subscription quotas — routing through
403
412
  // the local claude CLI binary is TOS-compliant.
404
- if (modelRegistry.isProviderRequestReady('claude-code') && settingsManager.getDefaultProvider() === 'anthropic') {
413
+ if (shouldMigrateAnthropicToClaudeCode({
414
+ authStorage,
415
+ isClaudeCodeReady: modelRegistry.isProviderRequestReady('claude-code'),
416
+ defaultProvider: settingsManager.getDefaultProvider(),
417
+ })) {
405
418
  const currentModelId = settingsManager.getDefaultModel();
406
419
  if (currentModelId) {
407
420
  const ccModel = modelRegistry.find('claude-code', currentModelId);
@@ -466,6 +479,15 @@ if (isPrintMode) {
466
479
  if (mode === 'mcp') {
467
480
  printStartupTimings();
468
481
  const { startMcpServer } = await import('./mcp-server.js');
482
+ // Activate every registered tool before starting the MCP transport.
483
+ // `session.agent.state.tools` is the *active* subset, not the full
484
+ // registry — if we expose only the active set, extension-registered
485
+ // tools (gsd workflow, browser-tools, mac-tools, search-the-web, …)
486
+ // are invisible to MCP clients. Flipping the active set to every
487
+ // known tool name makes `state.tools` mirror the full registry for
488
+ // this MCP session, which is what an external client expects.
489
+ const allToolNames = session.getAllTools().map((t) => t.name);
490
+ session.setActiveToolsByName(allToolNames);
469
491
  await startMcpServer({
470
492
  tools: session.agent.state.tools ?? [],
471
493
  version: process.env.GSD_VERSION || '0.0.0',
@@ -576,7 +598,11 @@ markStartup('createAgentSession');
576
598
  // Migrate anthropic OAuth users to claude-code provider when CLI is available (#3772).
577
599
  // Anthropic blocks third-party apps from using subscription quotas — routing through
578
600
  // the local claude CLI binary is TOS-compliant.
579
- if (modelRegistry.isProviderRequestReady('claude-code') && settingsManager.getDefaultProvider() === 'anthropic') {
601
+ if (shouldMigrateAnthropicToClaudeCode({
602
+ authStorage,
603
+ isClaudeCodeReady: modelRegistry.isProviderRequestReady('claude-code'),
604
+ defaultProvider: settingsManager.getDefaultProvider(),
605
+ })) {
580
606
  const currentModelId = settingsManager.getDefaultModel();
581
607
  if (currentModelId) {
582
608
  const ccModel = modelRegistry.find('claude-code', currentModelId);
@@ -43,6 +43,8 @@ export declare const NEW_MILESTONE_IDLE_TIMEOUT_MS = 120000;
43
43
  export declare function isTerminalNotification(event: Record<string, unknown>): boolean;
44
44
  export declare function isBlockedNotification(event: Record<string, unknown>): boolean;
45
45
  export declare function isMilestoneReadyNotification(event: Record<string, unknown>): boolean;
46
+ export declare function isInteractiveHeadlessTool(toolName: string | undefined): boolean;
47
+ export declare function shouldArmHeadlessIdleTimeout(toolCallCount: number, interactiveToolCount: number): boolean;
46
48
  export declare const FIRE_AND_FORGET_METHODS: Set<string>;
47
49
  export declare const QUICK_COMMANDS: Set<string>;
48
50
  export declare function isQuickCommand(command: string): boolean;
@@ -65,6 +65,7 @@ export const IDLE_TIMEOUT_MS = 15_000;
65
65
  // between tool calls (e.g. after mkdir, before writing files). Use a
66
66
  // longer idle timeout to avoid killing the session prematurely (#808).
67
67
  export const NEW_MILESTONE_IDLE_TIMEOUT_MS = 120_000;
68
+ const INTERACTIVE_HEADLESS_TOOLS = new Set(['ask_user_questions', 'secure_env_collect']);
68
69
  export function isTerminalNotification(event) {
69
70
  if (event.type !== 'extension_ui_request' || event.method !== 'notify')
70
71
  return false;
@@ -83,6 +84,12 @@ export function isMilestoneReadyNotification(event) {
83
84
  return false;
84
85
  return /milestone\s+m\d+.*ready/i.test(String(event.message ?? ''));
85
86
  }
87
+ export function isInteractiveHeadlessTool(toolName) {
88
+ return INTERACTIVE_HEADLESS_TOOLS.has(String(toolName ?? ''));
89
+ }
90
+ export function shouldArmHeadlessIdleTimeout(toolCallCount, interactiveToolCount) {
91
+ return toolCallCount > 0 && interactiveToolCount === 0;
92
+ }
86
93
  // ---------------------------------------------------------------------------
87
94
  // Quick Command Detection
88
95
  // ---------------------------------------------------------------------------
package/dist/headless.js CHANGED
@@ -17,7 +17,7 @@ import { resolve } from 'node:path';
17
17
  import { RpcClient, SessionManager } from '@gsd/pi-coding-agent';
18
18
  import { getProjectSessionsDir } from './project-sessions.js';
19
19
  import { loadAndValidateAnswerFile, AnswerInjector } from './headless-answers.js';
20
- import { isTerminalNotification, isBlockedNotification, isMilestoneReadyNotification, isQuickCommand, FIRE_AND_FORGET_METHODS, IDLE_TIMEOUT_MS, NEW_MILESTONE_IDLE_TIMEOUT_MS, EXIT_SUCCESS, EXIT_ERROR, EXIT_BLOCKED, EXIT_CANCELLED, mapStatusToExitCode, } from './headless-events.js';
20
+ import { isTerminalNotification, isBlockedNotification, isMilestoneReadyNotification, isQuickCommand, FIRE_AND_FORGET_METHODS, IDLE_TIMEOUT_MS, NEW_MILESTONE_IDLE_TIMEOUT_MS, isInteractiveHeadlessTool, shouldArmHeadlessIdleTimeout, EXIT_SUCCESS, EXIT_ERROR, EXIT_BLOCKED, EXIT_CANCELLED, mapStatusToExitCode, } from './headless-events.js';
21
21
  import { VALID_OUTPUT_FORMATS } from './headless-types.js';
22
22
  import { handleExtensionUIRequest, formatProgress, formatThinkingLine, formatTextStart, formatTextEnd, formatThinkingStart, formatThinkingEnd, startSupervisedStdinReader, } from './headless-ui.js';
23
23
  import { loadContext, bootstrapGsdProject, } from './headless-context.js';
@@ -282,6 +282,7 @@ async function runHeadlessOnce(options, restartCount) {
282
282
  let exitCode = 0;
283
283
  let milestoneReady = false; // tracks "Milestone X ready." for auto-chaining
284
284
  const recentEvents = [];
285
+ const interactiveToolCallIds = new Set();
285
286
  // JSON batch mode: cost aggregation (cumulative-max pattern per K004)
286
287
  let cumulativeCostUsd = 0;
287
288
  let cumulativeInputTokens = 0;
@@ -365,7 +366,7 @@ async function runHeadlessOnce(options, restartCount) {
365
366
  function resetIdleTimer() {
366
367
  if (idleTimer)
367
368
  clearTimeout(idleTimer);
368
- if (toolCallCount > 0) {
369
+ if (shouldArmHeadlessIdleTimeout(toolCallCount, interactiveToolCallIds.size)) {
369
370
  idleTimer = setTimeout(() => {
370
371
  completed = true;
371
372
  resolveCompletion();
@@ -386,13 +387,25 @@ async function runHeadlessOnce(options, restartCount) {
386
387
  client.onEvent((event) => {
387
388
  const eventObj = event;
388
389
  trackEvent(eventObj);
390
+ const eventType = String(eventObj.type ?? '');
391
+ if (eventType === 'tool_execution_start') {
392
+ const toolCallId = String(eventObj.toolCallId ?? eventObj.id ?? '');
393
+ if (toolCallId && isInteractiveHeadlessTool(String(eventObj.toolName ?? ''))) {
394
+ interactiveToolCallIds.add(toolCallId);
395
+ }
396
+ }
397
+ else if (eventType === 'tool_execution_end') {
398
+ const toolCallId = String(eventObj.toolCallId ?? eventObj.id ?? '');
399
+ if (toolCallId) {
400
+ interactiveToolCallIds.delete(toolCallId);
401
+ }
402
+ }
389
403
  resetIdleTimer();
390
404
  // Answer injector: observe events for question metadata
391
405
  injector?.observeEvent(eventObj);
392
406
  // --json / --output-format stream-json: forward events as JSONL to stdout (filtered if --events)
393
407
  // --output-format json (batch mode): suppress streaming, track cost for final result
394
408
  if (options.json && options.outputFormat === 'stream-json') {
395
- const eventType = String(eventObj.type ?? '');
396
409
  if (!options.eventFilter || options.eventFilter.has(eventType)) {
397
410
  process.stdout.write(JSON.stringify(eventObj) + '\n');
398
411
  }
@@ -1,10 +1,15 @@
1
- // MCP SDK subpath imports use wildcard exports (./*) that NodeNext resolves
2
- // at runtime but TypeScript cannot statically type-check. We construct the
3
- // specifiers dynamically so tsc treats them as `any`.
4
- // Use createRequire to resolve wildcard subpaths CJS resolver auto-appends
5
- // .js, which the ESM wildcard export map does not (#3603).
6
- import { createRequire } from 'node:module';
7
- const _require = createRequire(import.meta.url);
1
+ // MCP SDK subpath imports use wildcard exports (./*) in @modelcontextprotocol/sdk's
2
+ // package.json export map. The wildcard maps "./foo" "./dist/cjs/foo" (no .js
3
+ // suffix), so bare subpath specifiers like `${MCP_PKG}/server/stdio` resolve to
4
+ // a non-existent file. Historically the workaround (#3603) used createRequire so
5
+ // the CJS resolver could auto-append `.js`; that no longer works with current
6
+ // Node + SDK releases (#3914) — `_require.resolve` also fails with
7
+ // "Cannot find module .../dist/cjs/server/stdio".
8
+ //
9
+ // The reliable convention (matching packages/mcp-server/{server,cli}.ts) is to
10
+ // write the `.js` suffix explicitly on every wildcard subpath. Specifiers are
11
+ // built via a template string so TypeScript's NodeNext resolver treats them as
12
+ // `any` and skips static checking.
8
13
  const MCP_PKG = '@modelcontextprotocol/sdk';
9
14
  /**
10
15
  * Starts a native MCP (Model Context Protocol) server over stdin/stdout.
@@ -22,9 +27,9 @@ const MCP_PKG = '@modelcontextprotocol/sdk';
22
27
  */
23
28
  export async function startMcpServer(options) {
24
29
  const { tools, version = '0.0.0' } = options;
25
- const serverMod = await import(`${MCP_PKG}/server`);
26
- const stdioMod = await import(_require.resolve(`${MCP_PKG}/server/stdio`));
27
- const typesMod = await import(_require.resolve(`${MCP_PKG}/types`));
30
+ const serverMod = await import(`${MCP_PKG}/server/index.js`);
31
+ const stdioMod = await import(`${MCP_PKG}/server/stdio.js`);
32
+ const typesMod = await import(`${MCP_PKG}/types.js`);
28
33
  const Server = serverMod.Server;
29
34
  const StdioServerTransport = stdioMod.StdioServerTransport;
30
35
  const { ListToolsRequestSchema, CallToolRequestSchema } = typesMod;
@@ -42,8 +47,14 @@ export async function startMcpServer(options) {
42
47
  inputSchema: t.parameters,
43
48
  })),
44
49
  }));
45
- // tools/call — execute the requested tool and return content blocks
46
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
50
+ // tools/call — execute the requested tool and return content blocks.
51
+ //
52
+ // The MCP SDK passes an `extra` argument to request handlers that includes
53
+ // an AbortSignal scoped to the RPC request (cancelled when the client
54
+ // cancels the tool call or the transport closes). Threading it into
55
+ // AgentTool.execute ensures long-running tools (Bash, WebFetch, grep on
56
+ // huge trees) actually stop when the client gives up on the result.
57
+ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
47
58
  const { name, arguments: args } = request.params;
48
59
  const tool = toolMap.get(name);
49
60
  if (!tool) {
@@ -52,20 +63,32 @@ export async function startMcpServer(options) {
52
63
  content: [{ type: 'text', text: `Unknown tool: ${name}` }],
53
64
  };
54
65
  }
66
+ const signal = extra?.signal;
55
67
  try {
56
- const result = await tool.execute(`mcp-${Date.now()}`, args ?? {}, undefined, // no AbortSignal
57
- undefined);
58
- // Convert AgentToolResult content blocks to MCP content format
68
+ const result = await tool.execute(`mcp-${Date.now()}`, args ?? {}, signal, undefined);
69
+ // Convert AgentToolResult content blocks to MCP content format.
70
+ // text and image pass through; any other shape is serialized as text
71
+ // so the client sees the payload rather than an empty response.
59
72
  const content = result.content.map((block) => {
60
73
  if (block.type === 'text')
61
74
  return { type: 'text', text: block.text ?? '' };
62
- if (block.type === 'image')
63
- return { type: 'image', data: block.data ?? '', mimeType: block.mimeType ?? 'image/png' };
75
+ if (block.type === 'image') {
76
+ return {
77
+ type: 'image',
78
+ data: block.data ?? '',
79
+ mimeType: block.mimeType ?? 'image/png',
80
+ };
81
+ }
82
+ // Preserve unknown block types (resource, resource_link, audio, ...)
83
+ // by stringifying into a text block so clients see the payload.
64
84
  return { type: 'text', text: JSON.stringify(block) };
65
85
  });
66
86
  return { content };
67
87
  }
68
88
  catch (err) {
89
+ // AbortError from a cancelled tool surfaces as a normal error — MCP
90
+ // clients interpret `isError: true` as a failed call, which is the
91
+ // correct behaviour for a cancelled request.
69
92
  const message = err instanceof Error ? err.message : String(err);
70
93
  return { isError: true, content: [{ type: 'text', text: message }] };
71
94
  }
@@ -0,0 +1,10 @@
1
+ import type { AuthStorage } from "@gsd/pi-coding-agent";
2
+ type AnthropicMigrationDeps = {
3
+ authStorage: Pick<AuthStorage, "getCredentialsForProvider">;
4
+ isClaudeCodeReady: boolean;
5
+ defaultProvider: string | undefined;
6
+ env?: NodeJS.ProcessEnv;
7
+ };
8
+ export declare function hasDirectAnthropicApiKey(authStorage: Pick<AuthStorage, "getCredentialsForProvider">, env?: NodeJS.ProcessEnv): boolean;
9
+ export declare function shouldMigrateAnthropicToClaudeCode({ authStorage, isClaudeCodeReady, defaultProvider, env, }: AnthropicMigrationDeps): boolean;
10
+ export {};
@@ -0,0 +1,12 @@
1
+ export function hasDirectAnthropicApiKey(authStorage, env = process.env) {
2
+ if ((env.ANTHROPIC_API_KEY ?? "").trim()) {
3
+ return true;
4
+ }
5
+ return authStorage.getCredentialsForProvider("anthropic").some((credential) => credential?.type === "api_key" && typeof credential?.key === "string" && credential.key.trim().length > 0);
6
+ }
7
+ export function shouldMigrateAnthropicToClaudeCode({ authStorage, isClaudeCodeReady, defaultProvider, env = process.env, }) {
8
+ if (!isClaudeCodeReady || defaultProvider !== "anthropic") {
9
+ return false;
10
+ }
11
+ return !hasDirectAnthropicApiKey(authStorage, env);
12
+ }
@@ -2,7 +2,7 @@ import { DefaultResourceLoader, sortExtensionPaths } from '@gsd/pi-coding-agent'
2
2
  import { createHash } from 'node:crypto';
3
3
  import { homedir } from 'node:os';
4
4
  import { chmodSync, copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, openSync, closeSync, readFileSync, readlinkSync, readdirSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync } from 'node:fs';
5
- import { dirname, join, relative, resolve } from 'node:path';
5
+ import { basename, dirname, join, relative, resolve } from 'node:path';
6
6
  import { fileURLToPath } from 'node:url';
7
7
  import { compareSemver } from './update-check.js';
8
8
  import { discoverExtensionEntryPaths } from './extension-discovery.js';
@@ -254,34 +254,160 @@ function copyDirRecursive(src, dest) {
254
254
  * ~/.gsd/agent/extensions/ have no ancestor node_modules, so imports of
255
255
  * @gsd/* packages fail. The symlink makes Node's standard resolution find
256
256
  * them without requiring every call site to use jiti.
257
+ *
258
+ * Layout differences by install method:
259
+ * - Source/monorepo: packageRoot/node_modules has everything → simple symlink
260
+ * - npm/bun global: deps hoisted to dirname(packageRoot), including @gsd/* → simple symlink
261
+ * - pnpm global: external deps hoisted, but @gsd/* stays in packageRoot/node_modules
262
+ * → merged directory with symlinks from both roots (#3529, #3564)
257
263
  */
258
264
  function ensureNodeModulesSymlink(agentDir) {
259
265
  const agentNodeModules = join(agentDir, 'node_modules');
260
- const gsdNodeModules = join(packageRoot, 'node_modules');
266
+ const internalNodeModules = join(packageRoot, 'node_modules');
267
+ const hoistedNodeModules = dirname(packageRoot);
268
+ const isGlobalInstall = basename(hoistedNodeModules) === 'node_modules';
269
+ if (!isGlobalInstall) {
270
+ // Source/monorepo: internal node_modules has everything
271
+ reconcileSymlink(agentNodeModules, internalNodeModules);
272
+ return;
273
+ }
274
+ // Global install: check if workspace scopes (@gsd/*) are hoisted.
275
+ // npm/bun hoist everything; pnpm keeps workspace packages internal.
276
+ if (!hasMissingWorkspaceScopes(hoistedNodeModules, internalNodeModules)) {
277
+ // Everything is hoisted — simple symlink to parent node_modules
278
+ reconcileSymlink(agentNodeModules, hoistedNodeModules);
279
+ return;
280
+ }
281
+ // pnpm-style layout: create a real directory merging both roots
282
+ reconcileMergedNodeModules(agentNodeModules, hoistedNodeModules, internalNodeModules);
283
+ }
284
+ /** Check if any @gsd* scopes exist in internal but not in hoisted node_modules */
285
+ function hasMissingWorkspaceScopes(hoisted, internal) {
286
+ if (!existsSync(internal))
287
+ return false;
261
288
  try {
262
- const stat = lstatSync(agentNodeModules);
289
+ for (const entry of readdirSync(internal, { withFileTypes: true })) {
290
+ if (entry.isDirectory() && entry.name.startsWith('@gsd') &&
291
+ !existsSync(join(hoisted, entry.name))) {
292
+ return true;
293
+ }
294
+ }
295
+ }
296
+ catch { /* non-fatal */ }
297
+ return false;
298
+ }
299
+ /** Ensure a symlink at `link` points to `target`, fixing stale/wrong entries */
300
+ function reconcileSymlink(link, target) {
301
+ try {
302
+ const stat = lstatSync(link);
263
303
  if (stat.isSymbolicLink()) {
264
- const existing = readlinkSync(agentNodeModules);
265
- // Symlink exists verify it points to the correct, existing target
266
- if (existing === gsdNodeModules && existsSync(agentNodeModules))
304
+ const existing = readlinkSync(link);
305
+ if (existing === target && existsSync(link))
267
306
  return; // correct and target exists
268
- // Stale or wrong target — remove and recreate
307
+ unlinkSync(link);
308
+ }
309
+ else {
310
+ // Real directory (or merged dir from previous pnpm fix) — remove it
311
+ rmSync(link, { recursive: true, force: true });
312
+ }
313
+ }
314
+ catch {
315
+ // lstatSync throws if path doesn't exist — fine, we'll create below
316
+ }
317
+ try {
318
+ symlinkSync(target, link, 'junction');
319
+ }
320
+ catch (err) {
321
+ console.error(`[gsd] WARN: Failed to symlink ${link} → ${target}: ${err instanceof Error ? err.message : err}`);
322
+ }
323
+ }
324
+ /**
325
+ * Create a real node_modules directory containing symlinks from both the
326
+ * hoisted root (external deps) and internal root (@gsd/* workspace packages).
327
+ * Used for pnpm global installs where @gsd/* isn't hoisted.
328
+ */
329
+ function reconcileMergedNodeModules(agentNodeModules, hoisted, internal) {
330
+ // Fast path: if already merged for this packageRoot + same directory contents, skip.
331
+ // The fingerprint includes entry names from both roots so `pnpm add/remove` triggers rebuild.
332
+ const marker = join(agentNodeModules, '.gsd-merged');
333
+ const fingerprint = mergedFingerprint(hoisted, internal);
334
+ try {
335
+ if (existsSync(marker) && readFileSync(marker, 'utf-8').trim() === fingerprint)
336
+ return;
337
+ }
338
+ catch { /* rebuild */ }
339
+ // Remove any existing symlink or stale merged directory
340
+ try {
341
+ const stat = lstatSync(agentNodeModules);
342
+ if (stat.isSymbolicLink()) {
269
343
  unlinkSync(agentNodeModules);
270
344
  }
271
345
  else {
272
- // Real directory (not a symlink) is blocking — remove it
273
346
  rmSync(agentNodeModules, { recursive: true, force: true });
274
347
  }
275
348
  }
276
- catch {
277
- // lstatSync throws if path doesn't exist — that's fine, we'll create below
349
+ catch { /* doesn't exist */ }
350
+ mkdirSync(agentNodeModules, { recursive: true });
351
+ let linkedCount = 0;
352
+ // Symlink entries from the hoisted node_modules (external deps)
353
+ try {
354
+ for (const entry of readdirSync(hoisted, { withFileTypes: true })) {
355
+ // Skip the gsd-pi package itself and dotfiles
356
+ if (entry.name === basename(packageRoot))
357
+ continue;
358
+ if (entry.name.startsWith('.'))
359
+ continue;
360
+ try {
361
+ symlinkSync(join(hoisted, entry.name), join(agentNodeModules, entry.name));
362
+ linkedCount++;
363
+ }
364
+ catch { /* skip individual */ }
365
+ }
278
366
  }
367
+ catch (err) {
368
+ console.error(`[gsd] WARN: Failed to read hoisted node_modules at ${hoisted}: ${err instanceof Error ? err.message : err}`);
369
+ }
370
+ // Overlay internal node_modules entries that weren't hoisted.
371
+ // This covers @gsd/* workspace packages AND optional deps like
372
+ // @anthropic-ai/claude-agent-sdk that npm keeps internal.
279
373
  try {
280
- symlinkSync(gsdNodeModules, agentNodeModules, 'junction');
374
+ for (const entry of readdirSync(internal, { withFileTypes: true })) {
375
+ if (entry.name.startsWith('.'))
376
+ continue;
377
+ const link = join(agentNodeModules, entry.name);
378
+ // Replace hoisted symlink with internal version (internal takes precedence)
379
+ try {
380
+ lstatSync(link);
381
+ unlinkSync(link);
382
+ }
383
+ catch { /* didn't exist — will create below */ }
384
+ try {
385
+ symlinkSync(join(internal, entry.name), link);
386
+ linkedCount++;
387
+ }
388
+ catch { /* skip individual */ }
389
+ }
281
390
  }
282
391
  catch (err) {
283
- // This failure makes GSD non-functional extensions can't resolve @gsd/* packages
284
- console.error(`[gsd] WARN: Failed to symlink ${agentNodeModules} → ${gsdNodeModules}: ${err instanceof Error ? err.message : err}`);
392
+ console.error(`[gsd] WARN: Failed to read internal node_modules at ${internal}: ${err instanceof Error ? err.message : err}`);
393
+ }
394
+ // Only stamp marker if we actually linked something — avoids caching a broken state
395
+ if (linkedCount > 0) {
396
+ try {
397
+ writeFileSync(marker, fingerprint);
398
+ }
399
+ catch { /* non-fatal */ }
400
+ }
401
+ }
402
+ /** Build a cache fingerprint from packageRoot + sorted entry names of both directories */
403
+ function mergedFingerprint(hoisted, internal) {
404
+ try {
405
+ const h = readdirSync(hoisted).sort().join(',');
406
+ const i = readdirSync(internal).sort().join(',');
407
+ return `${packageRoot}\n${h}\n${i}`;
408
+ }
409
+ catch {
410
+ return packageRoot; // fallback: at least invalidate on version change
285
411
  }
286
412
  }
287
413
  /**
@@ -275,7 +275,7 @@ Work flows through these phases. Each phase produces a file.
275
275
  **How to do it manually:**
276
276
  1. Read the roadmap to understand the scope.
277
277
  2. Identify 3-5 gray areas — implementation decisions the user cares about.
278
- 3. Use `ask_user_questions` to discuss each area.
278
+ 3. Use `ask_user_questions` to discuss each area, one round at a time. Never fabricate user input; wait for the user's actual response before the next round.
279
279
  4. Write decisions to the appropriate context file (`M###-CONTEXT.md` or `S##-CONTEXT.md`).
280
280
  5. Do NOT discuss how to implement — only what the user wants.
281
281
 
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: debugger
3
+ description: Hypothesis-driven bug investigation with root cause analysis
4
+ model: sonnet
5
+ ---
6
+
7
+ You are a debugger. Investigate bugs using a systematic, hypothesis-driven approach. Your goal is to find the root cause, not just suppress symptoms.
8
+
9
+ ## Process
10
+
11
+ 1. **Reproduce**: Understand the symptoms — what happens vs. what should happen
12
+ 2. **Hypothesize**: List 2-3 most likely causes based on symptoms
13
+ 3. **Investigate**: For each hypothesis, gather evidence (read code, check logs, trace execution)
14
+ 4. **Narrow**: Eliminate hypotheses that don't match the evidence
15
+ 5. **Root cause**: Identify the actual cause with file:line references
16
+ 6. **Fix**: Propose the minimal change that addresses the root cause
17
+
18
+ ## Investigation Tools
19
+
20
+ - Read source files at specific line ranges
21
+ - Grep for error messages, function names, variable usage
22
+ - Check git blame for recent changes to suspect areas
23
+ - Read test files to understand expected behavior
24
+ - Run tests to reproduce failures
25
+
26
+ ## Output Format
27
+
28
+ ## Symptoms
29
+
30
+ What's happening vs. what's expected.
31
+
32
+ ## Hypotheses
33
+
34
+ 1. **[hypothesis]** — why this could be the cause
35
+ 2. **[hypothesis]** — why this could be the cause
36
+
37
+ ## Investigation
38
+
39
+ ### Hypothesis 1: [name]
40
+
41
+ Evidence gathered, files read, what was found.
42
+ **Verdict:** Confirmed / Eliminated — reason.
43
+
44
+ ### Hypothesis 2: [name]
45
+
46
+ (same structure)
47
+
48
+ ## Root Cause
49
+
50
+ **File:** `path/to/file.ts:42`
51
+ **Cause:** Clear explanation of the bug.
52
+ **Why it wasn't caught:** Missing test, edge case, etc.
53
+
54
+ ## Recommended Fix
55
+
56
+ ```typescript
57
+ // minimal fix with explanation
58
+ ```