gsd-pi 2.68.1 → 2.69.0-dev.232905b

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 (304) hide show
  1. package/dist/resources/extensions/gsd/auto-model-selection.js +27 -1
  2. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -0
  3. package/dist/resources/extensions/gsd/bootstrap/system-context.js +6 -2
  4. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -5
  5. package/dist/resources/extensions/gsd/codebase-generator.js +12 -0
  6. package/dist/resources/extensions/gsd/commands-cmux.js +30 -1
  7. package/dist/resources/extensions/gsd/guided-flow.js +25 -70
  8. package/dist/resources/extensions/gsd/model-router.js +85 -2
  9. package/dist/resources/extensions/gsd/prompts/discuss.md +2 -0
  10. package/dist/resources/extensions/gsd/templates/context.md +34 -2
  11. package/dist/resources/extensions/gsd/workflow-mcp.js +53 -6
  12. package/dist/web/standalone/.next/BUILD_ID +1 -1
  13. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  14. package/dist/web/standalone/.next/build-manifest.json +3 -3
  15. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  16. package/dist/web/standalone/.next/required-server-files.json +3 -3
  17. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  18. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  19. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  20. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  21. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  22. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  23. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  24. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  25. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  28. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  29. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  30. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  31. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  32. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  33. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  34. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  35. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  36. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  37. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  38. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  39. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  40. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  41. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  42. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  43. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  44. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  45. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  46. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  47. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  48. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  49. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  50. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  51. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  52. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  53. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  54. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  55. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  56. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  57. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  58. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  59. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  60. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  61. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  62. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  63. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  64. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  65. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  66. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  67. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  74. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  76. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  86. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  92. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  108. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
  112. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/index.html +1 -1
  122. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  123. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  124. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  125. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  127. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/page.js +2 -2
  129. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  131. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  132. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  133. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/middleware.js +2 -2
  135. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  137. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  138. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  139. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  140. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  141. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  142. package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +1 -0
  143. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  144. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  145. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  146. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  147. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  148. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  149. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  150. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  151. package/dist/web/standalone/server.js +1 -1
  152. package/package.json +1 -1
  153. package/packages/daemon/src/orchestrator.ts +9 -84
  154. package/packages/mcp-server/README.md +25 -3
  155. package/packages/mcp-server/dist/cli.d.ts +0 -1
  156. package/packages/mcp-server/dist/cli.d.ts.map +1 -1
  157. package/packages/mcp-server/dist/cli.js +4 -2
  158. package/packages/mcp-server/dist/cli.js.map +1 -1
  159. package/packages/mcp-server/dist/server.d.ts +32 -1
  160. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  161. package/packages/mcp-server/dist/server.js +118 -1
  162. package/packages/mcp-server/dist/server.js.map +1 -1
  163. package/packages/mcp-server/dist/tool-credentials.d.ts +6 -0
  164. package/packages/mcp-server/dist/tool-credentials.d.ts.map +1 -0
  165. package/packages/mcp-server/dist/tool-credentials.js +90 -0
  166. package/packages/mcp-server/dist/tool-credentials.js.map +1 -0
  167. package/packages/mcp-server/dist/workflow-tools.d.ts +1 -0
  168. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  169. package/packages/mcp-server/dist/workflow-tools.js +274 -2
  170. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  171. package/packages/mcp-server/src/cli.ts +5 -3
  172. package/packages/mcp-server/src/mcp-server.test.ts +85 -1
  173. package/packages/mcp-server/src/server.ts +188 -1
  174. package/packages/mcp-server/src/tool-credentials.test.ts +95 -0
  175. package/packages/mcp-server/src/tool-credentials.ts +97 -0
  176. package/packages/mcp-server/src/workflow-tools.test.ts +32 -25
  177. package/packages/mcp-server/src/workflow-tools.ts +365 -2
  178. package/packages/pi-ai/dist/index.d.ts +3 -0
  179. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  180. package/packages/pi-ai/dist/index.js +2 -0
  181. package/packages/pi-ai/dist/index.js.map +1 -1
  182. package/packages/pi-ai/dist/providers/amazon-bedrock.js +2 -2
  183. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  184. package/packages/pi-ai/dist/providers/anthropic-shared.js +2 -2
  185. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  186. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  187. package/packages/pi-ai/dist/providers/anthropic.js +1 -23
  188. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  189. package/packages/pi-ai/dist/providers/google-shared.js +2 -2
  190. package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
  191. package/packages/pi-ai/dist/providers/mistral.js +2 -2
  192. package/packages/pi-ai/dist/providers/mistral.js.map +1 -1
  193. package/packages/pi-ai/dist/providers/openai-completions.js +2 -2
  194. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  195. package/packages/pi-ai/dist/providers/openai-responses-shared.js +2 -2
  196. package/packages/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
  197. package/packages/pi-ai/dist/providers/provider-capabilities.d.ts +59 -0
  198. package/packages/pi-ai/dist/providers/provider-capabilities.d.ts.map +1 -0
  199. package/packages/pi-ai/dist/providers/provider-capabilities.js +173 -0
  200. package/packages/pi-ai/dist/providers/provider-capabilities.js.map +1 -0
  201. package/packages/pi-ai/dist/providers/provider-capabilities.test.d.ts +2 -0
  202. package/packages/pi-ai/dist/providers/provider-capabilities.test.d.ts.map +1 -0
  203. package/packages/pi-ai/dist/providers/provider-capabilities.test.js +132 -0
  204. package/packages/pi-ai/dist/providers/provider-capabilities.test.js.map +1 -0
  205. package/packages/pi-ai/dist/providers/transform-messages-report.test.d.ts +2 -0
  206. package/packages/pi-ai/dist/providers/transform-messages-report.test.d.ts.map +1 -0
  207. package/packages/pi-ai/dist/providers/transform-messages-report.test.js +172 -0
  208. package/packages/pi-ai/dist/providers/transform-messages-report.test.js.map +1 -0
  209. package/packages/pi-ai/dist/providers/transform-messages.d.ts +34 -1
  210. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  211. package/packages/pi-ai/dist/providers/transform-messages.js +73 -2
  212. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  213. package/packages/pi-ai/dist/utils/oauth/index.d.ts +3 -2
  214. package/packages/pi-ai/dist/utils/oauth/index.d.ts.map +1 -1
  215. package/packages/pi-ai/dist/utils/oauth/index.js +3 -5
  216. package/packages/pi-ai/dist/utils/oauth/index.js.map +1 -1
  217. package/packages/pi-ai/src/index.ts +3 -0
  218. package/packages/pi-ai/src/providers/amazon-bedrock.ts +2 -2
  219. package/packages/pi-ai/src/providers/anthropic-shared.ts +2 -2
  220. package/packages/pi-ai/src/providers/anthropic.ts +1 -31
  221. package/packages/pi-ai/src/providers/google-shared.ts +2 -2
  222. package/packages/pi-ai/src/providers/mistral.ts +2 -2
  223. package/packages/pi-ai/src/providers/openai-completions.ts +2 -2
  224. package/packages/pi-ai/src/providers/openai-responses-shared.ts +2 -2
  225. package/packages/pi-ai/src/providers/provider-capabilities.test.ts +174 -0
  226. package/packages/pi-ai/src/providers/provider-capabilities.ts +215 -0
  227. package/packages/pi-ai/src/providers/transform-messages-report.test.ts +189 -0
  228. package/packages/pi-ai/src/providers/transform-messages.ts +94 -1
  229. package/packages/pi-ai/src/utils/oauth/index.ts +3 -5
  230. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  231. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  232. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  233. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  234. package/packages/pi-coding-agent/dist/core/extensions/loader.js +10 -1
  235. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  236. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -1
  237. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  238. package/packages/pi-coding-agent/dist/core/extensions/runner.js +15 -0
  239. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  240. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +41 -0
  241. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  242. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  243. package/packages/pi-coding-agent/dist/core/tools/index.d.ts +1 -0
  244. package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
  245. package/packages/pi-coding-agent/dist/core/tools/index.js +1 -0
  246. package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
  247. package/packages/pi-coding-agent/dist/core/tools/tool-compatibility-registry.d.ts +27 -0
  248. package/packages/pi-coding-agent/dist/core/tools/tool-compatibility-registry.d.ts.map +1 -0
  249. package/packages/pi-coding-agent/dist/core/tools/tool-compatibility-registry.js +69 -0
  250. package/packages/pi-coding-agent/dist/core/tools/tool-compatibility-registry.js.map +1 -0
  251. package/packages/pi-coding-agent/dist/index.d.ts +2 -2
  252. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  253. package/packages/pi-coding-agent/dist/index.js +3 -1
  254. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  255. package/packages/pi-coding-agent/package.json +1 -1
  256. package/packages/pi-coding-agent/src/core/extensions/index.ts +4 -0
  257. package/packages/pi-coding-agent/src/core/extensions/loader.ts +11 -1
  258. package/packages/pi-coding-agent/src/core/extensions/runner.ts +18 -0
  259. package/packages/pi-coding-agent/src/core/extensions/types.ts +45 -0
  260. package/packages/pi-coding-agent/src/core/tools/index.ts +7 -0
  261. package/packages/pi-coding-agent/src/core/tools/tool-compatibility-registry.ts +83 -0
  262. package/packages/pi-coding-agent/src/index.ts +9 -0
  263. package/pkg/package.json +1 -1
  264. package/src/resources/extensions/gsd/auto-model-selection.ts +36 -4
  265. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +8 -0
  266. package/src/resources/extensions/gsd/bootstrap/system-context.ts +9 -5
  267. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -5
  268. package/src/resources/extensions/gsd/codebase-generator.ts +16 -0
  269. package/src/resources/extensions/gsd/commands-cmux.ts +32 -1
  270. package/src/resources/extensions/gsd/guided-flow.ts +22 -84
  271. package/src/resources/extensions/gsd/model-router.ts +117 -10
  272. package/src/resources/extensions/gsd/preferences-types.ts +3 -1
  273. package/src/resources/extensions/gsd/prompts/discuss.md +2 -0
  274. package/src/resources/extensions/gsd/templates/context.md +34 -2
  275. package/src/resources/extensions/gsd/tests/capability-router.test.ts +31 -7
  276. package/src/resources/extensions/gsd/tests/cmux.test.ts +67 -1
  277. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +28 -0
  278. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +6 -2
  279. package/src/resources/extensions/gsd/tests/model-router.test.ts +2 -2
  280. package/src/resources/extensions/gsd/tests/tool-compatibility.test.ts +199 -0
  281. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +23 -7
  282. package/src/resources/extensions/gsd/tests/write-gate.test.ts +13 -16
  283. package/src/resources/extensions/gsd/workflow-mcp.ts +59 -5
  284. package/dist/resources/extensions/gsd/prompt-validation.js +0 -67
  285. package/dist/resources/extensions/gsd/prompts/discuss-prepared.md +0 -424
  286. package/dist/resources/extensions/gsd/templates/context-enhanced.md +0 -138
  287. package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
  288. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  289. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  290. package/packages/pi-ai/dist/utils/oauth/anthropic.d.ts +0 -17
  291. package/packages/pi-ai/dist/utils/oauth/anthropic.d.ts.map +0 -1
  292. package/packages/pi-ai/dist/utils/oauth/anthropic.js +0 -106
  293. package/packages/pi-ai/dist/utils/oauth/anthropic.js.map +0 -1
  294. package/packages/pi-ai/src/utils/oauth/anthropic.ts +0 -140
  295. package/src/resources/extensions/gsd/prompt-validation.ts +0 -88
  296. package/src/resources/extensions/gsd/prompts/discuss-prepared.md +0 -424
  297. package/src/resources/extensions/gsd/templates/context-enhanced.md +0 -138
  298. package/src/resources/extensions/gsd/tests/adversarial-review-fixes.test.ts +0 -223
  299. package/src/resources/extensions/gsd/tests/integration/test-isolation.ts +0 -53
  300. package/src/resources/extensions/gsd/tests/integration-prepared-discussion.test.ts +0 -525
  301. package/src/resources/extensions/gsd/tests/preparation.test.ts +0 -1211
  302. package/src/resources/extensions/gsd/tests/prompt-builder.test.ts +0 -669
  303. /package/dist/web/standalone/.next/static/{u9mQsApZYm8sVYSAaft8g → CHeIRZw-E97oO51g7zDvv}/_buildManifest.js +0 -0
  304. /package/dist/web/standalone/.next/static/{u9mQsApZYm8sVYSAaft8g → CHeIRZw-E97oO51g7zDvv}/_ssgManifest.js +0 -0
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { resolveModelWithFallbacksForUnit, resolveDynamicRoutingConfig } from "./preferences.js";
7
7
  import { classifyUnitComplexity, tierLabel } from "./complexity-classifier.js";
8
- import { resolveModelForComplexity, escalateTier, getEligibleModels, loadCapabilityOverrides } from "./model-router.js";
8
+ import { resolveModelForComplexity, escalateTier, getEligibleModels, loadCapabilityOverrides, adjustToolSet } from "./model-router.js";
9
9
  import { getLedger, getProjectTotals } from "./metrics.js";
10
10
  import { unitPhaseLabel } from "./auto-dashboard.js";
11
11
  export function resolvePreferredModelConfig(unitType, autoModeStartModel) {
@@ -177,12 +177,38 @@ export async function selectAndApplyModel(ctx, pi, unitType, unitId, basePath, p
177
177
  const ok = await pi.setModel(model, { persist: false });
178
178
  if (ok) {
179
179
  appliedModel = model;
180
+ // ADR-005: Adjust active tool set for the selected model's provider capabilities.
181
+ // Hard-filter incompatible tools, then let extensions override via adjust_tool_set hook.
182
+ const activeToolNames = pi.getActiveTools();
183
+ const { toolNames: compatibleTools, removedTools } = adjustToolSet(activeToolNames, model.api);
184
+ let finalToolNames = compatibleTools;
185
+ // Fire adjust_tool_set hook — extensions can override the filtered tool set
186
+ if (routingConfig.hooks !== false) {
187
+ const hookResult = await pi.emitAdjustToolSet({
188
+ selectedModelApi: model.api,
189
+ selectedModelProvider: model.provider,
190
+ selectedModelId: model.id,
191
+ activeToolNames,
192
+ filteredTools: removedTools,
193
+ });
194
+ if (hookResult?.toolNames) {
195
+ finalToolNames = hookResult.toolNames;
196
+ }
197
+ }
198
+ // Apply the filtered tool set if any tools were removed
199
+ if (removedTools.length > 0 || finalToolNames.length !== activeToolNames.length) {
200
+ pi.setActiveTools(finalToolNames);
201
+ }
180
202
  if (verbose) {
181
203
  const fallbackNote = modelId === effectiveModelConfig.primary
182
204
  ? ""
183
205
  : ` (fallback from ${effectiveModelConfig.primary})`;
184
206
  const phase = unitPhaseLabel(unitType);
185
207
  ctx.ui.notify(`Model [${phase}]${routingTierLabel}: ${model.provider}/${model.id}${fallbackNote}`, "info");
208
+ // ADR-005: Report tools filtered due to provider incompatibility
209
+ if (removedTools.length > 0) {
210
+ ctx.ui.notify(`Tool compatibility: ${removedTools.length} tools filtered for ${model.api} — ${removedTools.join(", ")}`, "info");
211
+ }
186
212
  }
187
213
  break;
188
214
  }
@@ -415,4 +415,11 @@ export function registerHooks(pi) {
415
415
  // Default: no override — let capability scoring handle selection
416
416
  return undefined;
417
417
  });
418
+ // Tool set adaptation hook (ADR-005 Phase 4)
419
+ // Extensions can override tool set after model selection by returning { toolNames: [...] }
420
+ // Return undefined to let the built-in provider compatibility filtering proceed.
421
+ pi.on("adjust_tool_set", async (_event) => {
422
+ // Default: no override — let provider capability filtering handle tool set
423
+ return undefined;
424
+ });
418
425
  }
@@ -16,6 +16,7 @@ import { deriveState } from "../state.js";
16
16
  import { formatOverridesSection, formatShortcut, loadActiveOverrides, loadFile, parseContinue, parseSummary } from "../files.js";
17
17
  import { toPosixPath } from "../../shared/mod.js";
18
18
  import { markCmuxPromptShown, shouldPromptToEnableCmux } from "../../cmux/index.js";
19
+ import { autoEnableCmuxPreferences } from "../commands-cmux.js";
19
20
  const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
20
21
  /**
21
22
  * Bundled skill triggers — resolved dynamically at runtime instead of
@@ -64,10 +65,13 @@ export async function buildBeforeAgentStartResult(event, ctx) {
64
65
  shortcutDashboard: formatShortcut("Ctrl+Alt+G"),
65
66
  shortcutShell: formatShortcut("Ctrl+Alt+B"),
66
67
  });
67
- const loadedPreferences = loadEffectiveGSDPreferences();
68
+ let loadedPreferences = loadEffectiveGSDPreferences();
68
69
  if (shouldPromptToEnableCmux(loadedPreferences?.preferences)) {
69
70
  markCmuxPromptShown();
70
- ctx.ui.notify("cmux detected. Run /gsd cmux on to enable sidebar metadata, notifications, and visual subagent splits for this project.", "info");
71
+ if (autoEnableCmuxPreferences()) {
72
+ loadedPreferences = loadEffectiveGSDPreferences();
73
+ ctx.ui.notify("cmux detected — auto-enabled. Run /gsd cmux off to disable.", "info");
74
+ }
71
75
  }
72
76
  let preferenceBlock = "";
73
77
  if (loadedPreferences) {
@@ -40,13 +40,9 @@ let activeQueuePhase = false;
40
40
  let pendingGateId = null;
41
41
  /**
42
42
  * Recognized gate question ID patterns.
43
- * These appear in both discuss-prepared.md (4-layer) and discuss.md (depth/requirements/roadmap).
43
+ * These appear in discuss.md (depth/requirements/roadmap).
44
44
  */
45
45
  const GATE_QUESTION_PATTERNS = [
46
- "layer1_scope_gate",
47
- "layer2_architecture_gate",
48
- "layer3_error_gate",
49
- "layer4_quality_gate",
50
46
  "depth_verification",
51
47
  ];
52
48
  /**
@@ -14,13 +14,20 @@ import { execSync } from "node:child_process";
14
14
  import { gsdRoot } from "./paths.js";
15
15
  // ─── Defaults ────────────────────────────────────────────────────────────────
16
16
  const DEFAULT_EXCLUDES = [
17
+ // ── AI / tooling meta ──
18
+ ".agents/",
17
19
  ".gsd/",
18
20
  ".planning/",
19
21
  ".plans/",
20
22
  ".claude/",
21
23
  ".cursor/",
24
+ ".bg-shell/",
25
+ // ── Editor / IDE ──
22
26
  ".vscode/",
27
+ ".idea/",
28
+ // ── VCS ──
23
29
  ".git/",
30
+ // ── Dependencies & build artifacts ──
24
31
  "node_modules/",
25
32
  "dist/",
26
33
  "build/",
@@ -28,7 +35,12 @@ const DEFAULT_EXCLUDES = [
28
35
  "coverage/",
29
36
  "__pycache__/",
30
37
  ".venv/",
38
+ "venv/",
31
39
  "vendor/",
40
+ "target/",
41
+ // ── Misc ──
42
+ ".cache/",
43
+ "tmp/",
32
44
  ];
33
45
  const DEFAULT_MAX_FILES = 500;
34
46
  const DEFAULT_COLLAPSE_THRESHOLD = 20;
@@ -1,8 +1,37 @@
1
- import { existsSync, readFileSync } from "node:fs";
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import { clearCmuxSidebar, CmuxClient, detectCmuxEnvironment, resolveCmuxConfig } from "../cmux/index.js";
3
3
  import { saveFile } from "./files.js";
4
4
  import { getProjectGSDPreferencesPath, loadEffectiveGSDPreferences, loadProjectGSDPreferences, } from "./preferences.js";
5
5
  import { ensurePreferencesFile, serializePreferencesToFrontmatter } from "./commands-prefs-wizard.js";
6
+ /**
7
+ * Auto-enable cmux in project preferences when detected but never configured.
8
+ * Called at boot (before agent start) — no ExtensionCommandContext needed.
9
+ * Returns true if preferences were written, false if skipped.
10
+ */
11
+ export function autoEnableCmuxPreferences() {
12
+ const path = getProjectGSDPreferencesPath();
13
+ if (!existsSync(path))
14
+ return false;
15
+ const existing = loadProjectGSDPreferences();
16
+ const prefs = existing?.preferences ? { ...existing.preferences } : { version: 1 };
17
+ prefs.cmux = {
18
+ enabled: true,
19
+ notifications: true,
20
+ sidebar: true,
21
+ splits: false,
22
+ browser: false,
23
+ ...(prefs.cmux ?? {}),
24
+ };
25
+ prefs.cmux.enabled = true;
26
+ prefs.version = prefs.version || 1;
27
+ const frontmatter = serializePreferencesToFrontmatter(prefs);
28
+ let body = "\n# GSD Skill Preferences\n\nSee `~/.gsd/agent/extensions/gsd/docs/preferences-reference.md` for full field documentation and examples.\n";
29
+ const preserved = extractBodyAfterFrontmatter(readFileSync(path, "utf-8"));
30
+ if (preserved)
31
+ body = preserved;
32
+ writeFileSync(path, `---\n${frontmatter}---${body}`, "utf-8");
33
+ return true;
34
+ }
6
35
  function extractBodyAfterFrontmatter(content) {
7
36
  const start = content.startsWith("---\n") ? 4 : content.startsWith("---\r\n") ? 5 : -1;
8
37
  if (start === -1)
@@ -36,19 +36,7 @@ import { parkMilestone, discardMilestone } from "./milestone-actions.js";
36
36
  import { selectAndApplyModel } from "./auto-model-selection.js";
37
37
  import { DISCUSS_TOOLS_ALLOWLIST } from "./constants.js";
38
38
  import { getWorkflowTransportSupportError, getRequiredWorkflowToolsForGuidedUnit, } from "./workflow-mcp.js";
39
- import { runPreparation, formatCodebaseBrief, formatPriorContextBrief, formatEcosystemBrief, } from "./preparation.js";
40
- // ─── Preparation result storage ─────────────────────────────────────────────
41
- // Stores the most recent preparation result for injection into discuss prompts.
42
- // S02 will consume this when building the prepared discussion prompt.
43
- let lastPreparationResult = null;
44
- /** Get the most recent preparation result (for S02 prompt building). */
45
- export function getLastPreparationResult() {
46
- return lastPreparationResult;
47
- }
48
- /** Clear the preparation result (called after discussion completes). */
49
- export function clearPreparationResult() {
50
- lastPreparationResult = null;
51
- }
39
+ import { runPreparation, formatCodebaseBrief, formatPriorContextBrief, } from "./preparation.js";
52
40
  // ─── Re-exports (preserve public API for existing importers) ────────────────
53
41
  export { MILESTONE_ID_RE, generateMilestoneSuffix, nextMilestoneId, extractMilestoneSeq, parseMilestoneId, milestoneIdSort, maxMilestoneNum, findMilestoneIds, reserveMilestoneId, claimReservedId, getReservedMilestoneIds, clearReservedMilestoneIds, } from "./milestone-ids.js";
54
42
  export { showQueue, handleQueueReorder, showQueueAdd, buildExistingMilestonesContext, } from "./guided-flow-queue.js";
@@ -335,7 +323,7 @@ function resolveAvailableModel(modelId, availableModels, currentProvider) {
335
323
  * Build the discuss-and-plan prompt for a new milestone.
336
324
  * Used by all three "new milestone" paths (first ever, no active, all complete).
337
325
  */
338
- function buildDiscussPrompt(nextId, preamble, _basePath) {
326
+ function buildDiscussPrompt(nextId, preamble, _basePath, preparationContext) {
339
327
  const milestoneRel = `.gsd/milestones/${nextId}`;
340
328
  const inlinedTemplates = [
341
329
  inlineTemplate("project", "Project"),
@@ -347,6 +335,7 @@ function buildDiscussPrompt(nextId, preamble, _basePath) {
347
335
  return loadPrompt("discuss", {
348
336
  milestoneId: nextId,
349
337
  preamble,
338
+ preparationContext: preparationContext ?? "",
350
339
  contextPath: `${milestoneRel}/${nextId}-CONTEXT.md`,
351
340
  roadmapPath: `${milestoneRel}/${nextId}-ROADMAP.md`,
352
341
  inlinedTemplates,
@@ -377,50 +366,12 @@ function buildHeadlessDiscussPrompt(nextId, seedContext, _basePath) {
377
366
  multiMilestoneCommitInstruction: buildDocsCommitInstruction("docs: project plan — N milestones"),
378
367
  });
379
368
  }
380
- /**
381
- * Build the prepared discuss prompt with brief injection.
382
- * Uses the discuss-prepared template which encodes the 4-layer discussion protocol.
383
- *
384
- * @param nextId - The milestone ID being discussed
385
- * @param preamble - Preamble text for the discuss prompt
386
- * @param _basePath - Root directory of the project (unused, kept for signature consistency)
387
- * @param prepResult - Preparation result containing briefs to inject
388
- * @returns The prepared discuss prompt string
389
- */
390
- function buildPreparedPrompt(nextId, preamble, _basePath, prepResult) {
391
- const milestoneRel = `.gsd/milestones/${nextId}`;
392
- // Use context-enhanced instead of context for prepared discussions
393
- const inlinedTemplates = [
394
- inlineTemplate("project", "Project"),
395
- inlineTemplate("requirements", "Requirements"),
396
- inlineTemplate("context-enhanced", "Context Enhanced"),
397
- inlineTemplate("roadmap", "Roadmap"),
398
- inlineTemplate("decisions", "Decisions"),
399
- ].join("\n\n---\n\n");
400
- // Format the briefs from the preparation result
401
- const codebaseBrief = prepResult.codebaseBrief || formatCodebaseBrief(prepResult.codebase);
402
- const priorContextBrief = prepResult.priorContextBrief || formatPriorContextBrief(prepResult.priorContext);
403
- const ecosystemBrief = prepResult.ecosystemBrief || formatEcosystemBrief(prepResult.ecosystem);
404
- return loadPrompt("discuss-prepared", {
405
- milestoneId: nextId,
406
- preamble,
407
- codebaseBrief,
408
- priorContextBrief,
409
- ecosystemBrief,
410
- contextPath: `${milestoneRel}/${nextId}-CONTEXT.md`,
411
- roadmapPath: `${milestoneRel}/${nextId}-ROADMAP.md`,
412
- inlinedTemplates,
413
- commitInstruction: buildDocsCommitInstruction(`docs(${nextId}): context, requirements, and roadmap`),
414
- multiMilestoneCommitInstruction: buildDocsCommitInstruction("docs: project plan — N milestones"),
415
- });
416
- }
417
369
  /**
418
370
  * Run preparation phase if enabled, then build the discuss prompt.
419
- * This is the main entry point for new milestone discussions with preparation.
420
- * Stores the preparation result for S02 to inject into the discuss prompt.
421
- *
422
- * When preparation succeeds, uses the discuss-prepared template with brief injection.
423
- * Falls back to the standard discuss template when preparation is disabled or fails.
371
+ * Preparation analyzes the codebase and prior context, injecting the results
372
+ * as supplementary context into the standard discuss template. The discuss
373
+ * template drives the conversation (asks "What's the vision?" first), while
374
+ * the preparation briefs give the agent grounding in the existing codebase.
424
375
  *
425
376
  * @param ctx - Extension command context with UI for progress notifications
426
377
  * @param nextId - The milestone ID being discussed
@@ -429,12 +380,12 @@ function buildPreparedPrompt(nextId, preamble, _basePath, prepResult) {
429
380
  * @returns The discuss prompt string
430
381
  */
431
382
  async function prepareAndBuildDiscussPrompt(ctx, nextId, preamble, basePath) {
432
- // Clear stale preparation result immediately to prevent cross-session/project
433
- // state leaks. This ensures data from a prior milestone/project never leaks
434
- // into subsequent discussions (adversarial review fix #3602).
435
- lastPreparationResult = null;
436
383
  const prefs = loadEffectiveGSDPreferences()?.preferences ?? {};
437
- // Run preparation if enabled (default: true)
384
+ // Run preparation if enabled (default: true) — results are injected as
385
+ // supplementary context into the standard discuss prompt, NOT as a
386
+ // replacement template. The discuss prompt always leads with "What's the
387
+ // vision?" so the user defines the scope, not the codebase analysis.
388
+ let preparationContext = "";
438
389
  if (prefs.discuss_preparation !== false) {
439
390
  try {
440
391
  const prepResult = await runPreparation(basePath, ctx.ui, {
@@ -442,20 +393,24 @@ async function prepareAndBuildDiscussPrompt(ctx, nextId, preamble, basePath) {
442
393
  discuss_web_research: prefs.discuss_web_research,
443
394
  discuss_depth: prefs.discuss_depth,
444
395
  });
445
- lastPreparationResult = prepResult;
446
- // Use prepared prompt if preparation was enabled and produced results
447
396
  if (prepResult.enabled) {
448
- return buildPreparedPrompt(nextId, preamble, basePath, prepResult);
397
+ const codebaseBrief = prepResult.codebaseBrief || formatCodebaseBrief(prepResult.codebase);
398
+ const priorContextBrief = prepResult.priorContextBrief || formatPriorContextBrief(prepResult.priorContext);
399
+ const parts = [];
400
+ if (codebaseBrief)
401
+ parts.push(`### Codebase Brief\n\n${codebaseBrief}`);
402
+ if (priorContextBrief)
403
+ parts.push(`### Prior Context Brief\n\n${priorContextBrief}`);
404
+ if (parts.length > 0) {
405
+ preparationContext = `\n\n## Preparation Context\n\nThe system analyzed the codebase before this discussion. Use these findings as background context — they describe what already exists, NOT what the user wants to build. Always ask the user what they want to build first.\n\n${parts.join("\n\n")}`;
406
+ }
449
407
  }
450
408
  }
451
- catch {
452
- // If preparation throws, ensure stale data doesn't persist
453
- lastPreparationResult = null;
409
+ catch (err) {
410
+ logWarning("guided", `preparation failed, proceeding without context: ${err.message}`);
454
411
  }
455
412
  }
456
- // Fall back to standard discuss prompt for backward compatibility
457
- // lastPreparationResult is already null (cleared at entry or on error)
458
- return buildDiscussPrompt(nextId, preamble, basePath);
413
+ return buildDiscussPrompt(nextId, preamble, basePath, preparationContext);
459
414
  }
460
415
  /**
461
416
  * Bootstrap a .gsd/ project from scratch for headless use.
@@ -2,10 +2,12 @@
2
2
  // Maps complexity tiers to models, enforcing downgrade-only semantics.
3
3
  // The user's configured model is always the ceiling.
4
4
  import { tierOrdinal } from "./complexity-classifier.js";
5
+ import { getProviderCapabilities } from "@gsd/pi-ai";
6
+ import { getToolCompatibility } from "@gsd/pi-coding-agent";
5
7
  // ─── Known Model Tiers ───────────────────────────────────────────────────────
6
8
  // Maps known model IDs to their capability tier. Used when tier_models is not
7
9
  // explicitly configured to pick the best available model for each tier.
8
- const MODEL_CAPABILITY_TIER = {
10
+ export const MODEL_CAPABILITY_TIER = {
9
11
  // Light-tier models (cheapest)
10
12
  "claude-haiku-4-5": "light",
11
13
  "claude-3-5-haiku-latest": "light",
@@ -80,15 +82,45 @@ const MODEL_COST_PER_1K_INPUT = {
80
82
  // Per-model capability profiles (0–100 scale). Used for capability-aware
81
83
  // model selection within an eligible tier set.
82
84
  export const MODEL_CAPABILITY_PROFILES = {
85
+ // ── Anthropic ──────────────────────────────────────────────────────────────
83
86
  "claude-opus-4-6": { coding: 95, debugging: 90, research: 85, reasoning: 95, speed: 30, longContext: 80, instruction: 90 },
84
87
  "claude-sonnet-4-6": { coding: 85, debugging: 80, research: 75, reasoning: 80, speed: 60, longContext: 75, instruction: 85 },
88
+ "claude-sonnet-4-5-20250514": { coding: 85, debugging: 80, research: 75, reasoning: 80, speed: 60, longContext: 75, instruction: 85 },
89
+ "claude-3-5-sonnet-latest": { coding: 82, debugging: 78, research: 72, reasoning: 78, speed: 62, longContext: 70, instruction: 82 },
85
90
  "claude-haiku-4-5": { coding: 60, debugging: 50, research: 45, reasoning: 50, speed: 95, longContext: 50, instruction: 75 },
91
+ "claude-3-5-haiku-latest": { coding: 60, debugging: 50, research: 45, reasoning: 50, speed: 95, longContext: 50, instruction: 75 },
92
+ "claude-3-haiku-20240307": { coding: 50, debugging: 40, research: 35, reasoning: 40, speed: 95, longContext: 40, instruction: 65 },
93
+ "claude-3-opus-latest": { coding: 90, debugging: 85, research: 82, reasoning: 90, speed: 35, longContext: 75, instruction: 88 },
94
+ // ── OpenAI GPT ─────────────────────────────────────────────────────────────
86
95
  "gpt-4o": { coding: 80, debugging: 75, research: 70, reasoning: 75, speed: 65, longContext: 70, instruction: 80 },
87
96
  "gpt-4o-mini": { coding: 55, debugging: 45, research: 40, reasoning: 45, speed: 90, longContext: 45, instruction: 70 },
97
+ "gpt-4-turbo": { coding: 78, debugging: 72, research: 68, reasoning: 72, speed: 50, longContext: 65, instruction: 78 },
98
+ "gpt-4.1": { coding: 82, debugging: 78, research: 72, reasoning: 78, speed: 62, longContext: 72, instruction: 82 },
99
+ "gpt-4.1-mini": { coding: 58, debugging: 48, research: 42, reasoning: 48, speed: 88, longContext: 48, instruction: 72 },
100
+ "gpt-4.1-nano": { coding: 40, debugging: 30, research: 25, reasoning: 30, speed: 95, longContext: 30, instruction: 60 },
101
+ "gpt-5": { coding: 92, debugging: 88, research: 85, reasoning: 92, speed: 40, longContext: 85, instruction: 90 },
102
+ "gpt-5-mini": { coding: 62, debugging: 52, research: 48, reasoning: 52, speed: 88, longContext: 52, instruction: 74 },
103
+ "gpt-5-nano": { coding: 42, debugging: 32, research: 28, reasoning: 32, speed: 95, longContext: 32, instruction: 62 },
104
+ "gpt-5-pro": { coding: 94, debugging: 90, research: 88, reasoning: 94, speed: 35, longContext: 88, instruction: 92 },
105
+ "gpt-5.1": { coding: 93, debugging: 89, research: 86, reasoning: 93, speed: 42, longContext: 86, instruction: 91 },
106
+ "gpt-5.1-codex-max": { coding: 90, debugging: 85, research: 70, reasoning: 85, speed: 55, longContext: 75, instruction: 85 },
107
+ "gpt-5.1-codex-mini": { coding: 65, debugging: 55, research: 40, reasoning: 50, speed: 88, longContext: 48, instruction: 72 },
108
+ "gpt-5.2": { coding: 93, debugging: 90, research: 87, reasoning: 93, speed: 42, longContext: 87, instruction: 91 },
109
+ "gpt-5.2-codex": { coding: 93, debugging: 90, research: 72, reasoning: 88, speed: 50, longContext: 78, instruction: 88 },
110
+ "gpt-5.3-codex": { coding: 94, debugging: 91, research: 74, reasoning: 89, speed: 50, longContext: 80, instruction: 89 },
111
+ "gpt-5.3-codex-spark": { coding: 68, debugging: 58, research: 42, reasoning: 52, speed: 90, longContext: 50, instruction: 74 },
112
+ "gpt-5.4": { coding: 95, debugging: 92, research: 88, reasoning: 94, speed: 42, longContext: 88, instruction: 92 },
113
+ // ── OpenAI o-series (reasoning-first) ──────────────────────────────────────
114
+ "o1": { coding: 78, debugging: 82, research: 78, reasoning: 90, speed: 20, longContext: 65, instruction: 82 },
115
+ "o3": { coding: 80, debugging: 85, research: 80, reasoning: 92, speed: 25, longContext: 70, instruction: 85 },
116
+ "o4-mini": { coding: 75, debugging: 80, research: 72, reasoning: 88, speed: 60, longContext: 65, instruction: 80 },
117
+ "o4-mini-deep-research": { coding: 75, debugging: 80, research: 85, reasoning: 88, speed: 30, longContext: 80, instruction: 80 },
118
+ // ── Google ─────────────────────────────────────────────────────────────────
88
119
  "gemini-2.5-pro": { coding: 75, debugging: 70, research: 85, reasoning: 75, speed: 55, longContext: 90, instruction: 75 },
89
120
  "gemini-2.0-flash": { coding: 50, debugging: 40, research: 50, reasoning: 40, speed: 95, longContext: 60, instruction: 65 },
121
+ "gemini-flash-2.0": { coding: 50, debugging: 40, research: 50, reasoning: 40, speed: 95, longContext: 60, instruction: 65 },
122
+ // ── DeepSeek ───────────────────────────────────────────────────────────────
90
123
  "deepseek-chat": { coding: 75, debugging: 65, research: 55, reasoning: 70, speed: 70, longContext: 55, instruction: 65 },
91
- "o3": { coding: 80, debugging: 85, research: 80, reasoning: 92, speed: 25, longContext: 70, instruction: 85 },
92
124
  };
93
125
  // ─── Base Task Requirements Data Table ───────────────────────────────────────
94
126
  // Per-unit-type base requirement vectors. Weights indicate how important each
@@ -398,3 +430,54 @@ function getModelCost(modelId) {
398
430
  // Unknown cost — assume expensive to avoid routing to unknown cheap models
399
431
  return 999;
400
432
  }
433
+ // ─── Tool Compatibility Filter (ADR-005 Phase 3) ───────────────────────────
434
+ /**
435
+ * Check if a tool is compatible with a provider's capabilities.
436
+ * Returns true if the tool can be used with the provider.
437
+ */
438
+ export function isToolCompatibleWithProvider(toolName, providerCaps) {
439
+ const compat = getToolCompatibility(toolName);
440
+ if (!compat)
441
+ return true; // no metadata = always compatible
442
+ // Hard filter: provider doesn't support image tool results
443
+ if (compat.producesImages && !providerCaps.imageToolResults)
444
+ return false;
445
+ // Hard filter: tool uses schema features provider doesn't support
446
+ if (compat.schemaFeatures?.some(f => providerCaps.unsupportedSchemaFeatures.includes(f))) {
447
+ return false;
448
+ }
449
+ return true;
450
+ }
451
+ /**
452
+ * Filter a list of tool names to only those compatible with a provider.
453
+ * Used by the routing pipeline to adjust tool sets when switching providers.
454
+ */
455
+ export function filterToolsForProvider(toolNames, providerApi) {
456
+ const providerCaps = getProviderCapabilities(providerApi);
457
+ // Provider doesn't support tool calling at all
458
+ if (!providerCaps.toolCalling) {
459
+ return { compatible: [], filtered: toolNames };
460
+ }
461
+ const compatible = [];
462
+ const filtered = [];
463
+ for (const name of toolNames) {
464
+ if (isToolCompatibleWithProvider(name, providerCaps)) {
465
+ compatible.push(name);
466
+ }
467
+ else {
468
+ filtered.push(name);
469
+ }
470
+ }
471
+ return { compatible, filtered };
472
+ }
473
+ /**
474
+ * Adjust the active tool set for a selected model's provider capabilities.
475
+ * Returns tool names that should be active — removes incompatible tools.
476
+ *
477
+ * This is a hard filter only — it removes tools that would fail at the
478
+ * provider level. It does NOT remove tools based on soft heuristics.
479
+ */
480
+ export function adjustToolSet(activeToolNames, selectedModelApi) {
481
+ const { compatible, filtered } = filterToolsForProvider(activeToolNames, selectedModelApi);
482
+ return { toolNames: compatible, removedTools: filtered };
483
+ }
@@ -28,6 +28,8 @@ After reflection is confirmed, decide the approach based on the actual scope —
28
28
 
29
29
  **Anti-reduction rule:** If the user describes a big vision, plan the big vision. Do not ask "what's the minimum viable version?" or try to reduce scope unless the user explicitly asks for an MVP or minimal version. When something is complex or risky, phase it into a later milestone — do not cut it. The user's ambition is the target, and your job is to sequence it intelligently, not shrink it.
30
30
 
31
+ {{preparationContext}}
32
+
31
33
  ## Mandatory Investigation Before First Question Round
32
34
 
33
35
  Before asking your first question, do a mandatory investigation pass. This is not optional.
@@ -38,6 +38,28 @@ To call this milestone complete, we must prove:
38
38
  - {{one real end-to-end scenario}}
39
39
  - {{what cannot be simulated if this milestone is to be considered truly done}}
40
40
 
41
+ ## Architectural Decisions
42
+
43
+ ### {{decisionTitle}}
44
+
45
+ **Decision:** {{decisionStatement}}
46
+
47
+ **Rationale:** {{rationale}}
48
+
49
+ **Alternatives Considered:**
50
+ - {{alternative}} — {{whyNotChosen}}
51
+
52
+ ---
53
+
54
+ > Add additional decisions as separate `### Decision Title` blocks following the same structure above.
55
+ > See `.gsd/DECISIONS.md` for the full append-only register of all project decisions.
56
+
57
+ ## Error Handling Strategy
58
+
59
+ {{errorHandlingStrategy}}
60
+
61
+ > Describe the approach for handling failures, edge cases, and error propagation. Include retry policies, fallback behaviors, and user-facing error messages where relevant.
62
+
41
63
  ## Risks and Unknowns
42
64
 
43
65
  - {{riskOrUnknown}} — {{whyItMatters}}
@@ -47,8 +69,6 @@ To call this milestone complete, we must prove:
47
69
  - `{{fileOrModule}}` — {{howItRelates}}
48
70
  - `{{fileOrModule}}` — {{howItRelates}}
49
71
 
50
- > See `.gsd/DECISIONS.md` for all architectural and pattern decisions — it is an append-only register; read it during planning, append to it during execution.
51
-
52
72
  ## Relevant Requirements
53
73
 
54
74
  - {{requirementId}} — {{howThisMilestoneAdvancesIt}}
@@ -71,6 +91,18 @@ To call this milestone complete, we must prove:
71
91
 
72
92
  - {{systemOrService}} — {{howThisMilestoneInteractsWithIt}}
73
93
 
94
+ ## Testing Requirements
95
+
96
+ {{testingRequirements}}
97
+
98
+ > Specify test types (unit, integration, e2e), coverage expectations, and specific test scenarios that must pass.
99
+
100
+ ## Acceptance Criteria
101
+
102
+ {{acceptanceCriteria}}
103
+
104
+ > Per-slice acceptance criteria gathered during discussion. Each slice should have clear, testable criteria.
105
+
74
106
  ## Open Questions
75
107
 
76
108
  - {{question}} — {{currentThinking}}
@@ -1,24 +1,37 @@
1
1
  import { execSync } from "node:child_process";
2
2
  import { existsSync } from "node:fs";
3
3
  import { dirname, resolve } from "node:path";
4
- import { fileURLToPath } from "node:url";
4
+ import { fileURLToPath, pathToFileURL } from "node:url";
5
5
  const MCP_WORKFLOW_TOOL_SURFACE = new Set([
6
+ "ask_user_questions",
7
+ "gsd_decision_save",
6
8
  "gsd_complete_milestone",
7
9
  "gsd_complete_task",
8
10
  "gsd_complete_slice",
11
+ "gsd_generate_milestone_id",
12
+ "gsd_journal_query",
9
13
  "gsd_milestone_complete",
14
+ "gsd_milestone_generate_id",
10
15
  "gsd_milestone_status",
11
16
  "gsd_milestone_validate",
17
+ "gsd_plan_task",
12
18
  "gsd_plan_milestone",
13
19
  "gsd_plan_slice",
14
20
  "gsd_replan_slice",
15
21
  "gsd_reassess_roadmap",
22
+ "gsd_requirement_save",
23
+ "gsd_requirement_update",
16
24
  "gsd_roadmap_reassess",
25
+ "gsd_save_decision",
17
26
  "gsd_save_gate_result",
27
+ "gsd_save_requirement",
28
+ "gsd_skip_slice",
18
29
  "gsd_slice_replan",
19
30
  "gsd_slice_complete",
20
31
  "gsd_summary_save",
32
+ "gsd_task_plan",
21
33
  "gsd_task_complete",
34
+ "gsd_update_requirement",
22
35
  "gsd_validate_milestone",
23
36
  ]);
24
37
  function parseLookupOutput(output) {
@@ -73,6 +86,8 @@ function getBundledWorkflowMcpCliPath(env) {
73
86
  return candidate;
74
87
  }
75
88
  const candidates = [
89
+ resolve(fileURLToPath(new URL("../../../../packages/mcp-server/src/cli.ts", import.meta.url))),
90
+ resolve(fileURLToPath(new URL("../../../../../packages/mcp-server/src/cli.ts", import.meta.url))),
76
91
  resolve(fileURLToPath(new URL("../../../../packages/mcp-server/dist/cli.js", import.meta.url))),
77
92
  resolve(fileURLToPath(new URL("../../../../../packages/mcp-server/dist/cli.js", import.meta.url))),
78
93
  ];
@@ -84,9 +99,9 @@ function getBundledWorkflowMcpCliPath(env) {
84
99
  }
85
100
  function getBundledWorkflowExecutorModulePath() {
86
101
  const candidates = [
87
- resolve(fileURLToPath(new URL("../../../../dist/resources/extensions/gsd/tools/workflow-tool-executors.js", import.meta.url))),
88
102
  resolve(fileURLToPath(new URL("./tools/workflow-tool-executors.js", import.meta.url))),
89
103
  resolve(fileURLToPath(new URL("./tools/workflow-tool-executors.ts", import.meta.url))),
104
+ resolve(fileURLToPath(new URL("../../../../dist/resources/extensions/gsd/tools/workflow-tool-executors.js", import.meta.url))),
90
105
  ];
91
106
  for (const candidate of candidates) {
92
107
  if (existsSync(candidate))
@@ -96,9 +111,20 @@ function getBundledWorkflowExecutorModulePath() {
96
111
  }
97
112
  function getBundledWorkflowWriteGateModulePath() {
98
113
  const candidates = [
99
- resolve(fileURLToPath(new URL("../../../../dist/resources/extensions/gsd/bootstrap/write-gate.js", import.meta.url))),
100
114
  resolve(fileURLToPath(new URL("./bootstrap/write-gate.js", import.meta.url))),
101
115
  resolve(fileURLToPath(new URL("./bootstrap/write-gate.ts", import.meta.url))),
116
+ resolve(fileURLToPath(new URL("../../../../dist/resources/extensions/gsd/bootstrap/write-gate.js", import.meta.url))),
117
+ ];
118
+ for (const candidate of candidates) {
119
+ if (existsSync(candidate))
120
+ return candidate;
121
+ }
122
+ return null;
123
+ }
124
+ function getResolveTsHookPath() {
125
+ const candidates = [
126
+ resolve(fileURLToPath(new URL("./tests/resolve-ts.mjs", import.meta.url))),
127
+ resolve(fileURLToPath(new URL("../../../../src/resources/extensions/gsd/tests/resolve-ts.mjs", import.meta.url))),
102
128
  ];
103
129
  for (const candidate of candidates) {
104
130
  if (existsSync(candidate))
@@ -106,14 +132,35 @@ function getBundledWorkflowWriteGateModulePath() {
106
132
  }
107
133
  return null;
108
134
  }
109
- function buildWorkflowLaunchEnv(projectRoot, gsdCliPath, explicitEnv) {
135
+ function mergeNodeOptions(existing, additions) {
136
+ const tokens = (existing ?? "").split(/\s+/).map((value) => value.trim()).filter(Boolean);
137
+ for (const addition of additions) {
138
+ if (!tokens.includes(addition)) {
139
+ tokens.push(addition);
140
+ }
141
+ }
142
+ return tokens.length > 0 ? tokens.join(" ") : undefined;
143
+ }
144
+ function buildWorkflowLaunchEnv(projectRoot, gsdCliPath, explicitEnv, workflowCliPath) {
110
145
  const executorModulePath = getBundledWorkflowExecutorModulePath();
111
146
  const writeGateModulePath = getBundledWorkflowWriteGateModulePath();
147
+ const resolveTsHookPath = getResolveTsHookPath();
148
+ const wantsSourceTs = Boolean(resolveTsHookPath) &&
149
+ ((workflowCliPath?.endsWith(".ts") ?? false) ||
150
+ (executorModulePath?.endsWith(".ts") ?? false) ||
151
+ (writeGateModulePath?.endsWith(".ts") ?? false));
152
+ const nodeOptions = wantsSourceTs
153
+ ? mergeNodeOptions(explicitEnv?.NODE_OPTIONS, [
154
+ "--experimental-strip-types",
155
+ `--import=${pathToFileURL(resolveTsHookPath).href}`,
156
+ ])
157
+ : explicitEnv?.NODE_OPTIONS;
112
158
  return {
113
159
  ...(explicitEnv ?? {}),
114
160
  ...(gsdCliPath ? { GSD_CLI_PATH: gsdCliPath } : {}),
115
161
  ...(executorModulePath ? { GSD_WORKFLOW_EXECUTORS_MODULE: executorModulePath } : {}),
116
162
  ...(writeGateModulePath ? { GSD_WORKFLOW_WRITE_GATE_MODULE: writeGateModulePath } : {}),
163
+ ...(nodeOptions ? { NODE_OPTIONS: nodeOptions } : {}),
117
164
  GSD_PERSIST_WRITE_GATE_STATE: "1",
118
165
  GSD_WORKFLOW_PROJECT_ROOT: projectRoot,
119
166
  };
@@ -148,7 +195,7 @@ export function detectWorkflowMcpLaunchConfig(projectRoot = process.cwd(), env =
148
195
  command: process.execPath,
149
196
  args: [distCli],
150
197
  cwd: resolvedWorkflowProjectRoot,
151
- env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath),
198
+ env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath, undefined, distCli),
152
199
  };
153
200
  }
154
201
  const bundledCli = getBundledWorkflowMcpCliPath(env);
@@ -158,7 +205,7 @@ export function detectWorkflowMcpLaunchConfig(projectRoot = process.cwd(), env =
158
205
  command: process.execPath,
159
206
  args: [bundledCli],
160
207
  cwd: resolvedWorkflowProjectRoot,
161
- env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath),
208
+ env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath, undefined, bundledCli),
162
209
  };
163
210
  }
164
211
  const binPath = lookupCommand("gsd-mcp-server");
@@ -1 +1 @@
1
- u9mQsApZYm8sVYSAaft8g
1
+ CHeIRZw-E97oO51g7zDvv