gsd-pi 2.57.0 → 2.58.0-dev.778d6ac

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 (707) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +49 -35
  3. package/dist/headless-ui.d.ts +17 -0
  4. package/dist/headless-ui.js +97 -3
  5. package/dist/headless.js +67 -6
  6. package/dist/help-text.js +1 -0
  7. package/dist/onboarding.js +44 -0
  8. package/dist/resource-loader.js +16 -1
  9. package/dist/resources/agents/researcher.md +1 -1
  10. package/dist/resources/extensions/ask-user-questions.js +16 -3
  11. package/dist/resources/extensions/async-jobs/extension-manifest.json +1 -1
  12. package/dist/resources/extensions/bg-shell/extension-manifest.json +1 -1
  13. package/dist/resources/extensions/browser-tools/extension-manifest.json +1 -1
  14. package/dist/resources/extensions/claude-code-cli/partial-builder.js +14 -6
  15. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +59 -36
  16. package/dist/resources/extensions/context7/extension-manifest.json +1 -1
  17. package/dist/resources/extensions/get-secrets-from-user.js +8 -5
  18. package/dist/resources/extensions/google-search/extension-manifest.json +1 -1
  19. package/dist/resources/extensions/google-search/index.js +2 -1
  20. package/dist/resources/extensions/gsd/auto/infra-errors.js +4 -0
  21. package/dist/resources/extensions/gsd/auto/phases.js +25 -21
  22. package/dist/resources/extensions/gsd/auto-artifact-paths.js +2 -2
  23. package/dist/resources/extensions/gsd/auto-dashboard.js +37 -20
  24. package/dist/resources/extensions/gsd/auto-dispatch.js +20 -5
  25. package/dist/resources/extensions/gsd/auto-model-selection.js +26 -3
  26. package/dist/resources/extensions/gsd/auto-post-unit.js +16 -4
  27. package/dist/resources/extensions/gsd/auto-prompts.js +1 -1
  28. package/dist/resources/extensions/gsd/auto-recovery.js +13 -5
  29. package/dist/resources/extensions/gsd/auto-start.js +35 -22
  30. package/dist/resources/extensions/gsd/auto-worktree.js +203 -14
  31. package/dist/resources/extensions/gsd/auto.js +4 -0
  32. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +32 -0
  33. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +82 -9
  34. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -1
  35. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -18
  36. package/dist/resources/extensions/gsd/bootstrap/system-context.js +44 -11
  37. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +67 -0
  38. package/dist/resources/extensions/gsd/captures.js +56 -4
  39. package/dist/resources/extensions/gsd/db-writer.js +116 -8
  40. package/dist/resources/extensions/gsd/dispatch-guard.js +11 -1
  41. package/dist/resources/extensions/gsd/doctor-git-checks.js +28 -0
  42. package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
  43. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +5 -4
  44. package/dist/resources/extensions/gsd/doctor.js +3 -1
  45. package/dist/resources/extensions/gsd/error-classifier.js +13 -10
  46. package/dist/resources/extensions/gsd/extension-manifest.json +16 -1
  47. package/dist/resources/extensions/gsd/forensics.js +123 -20
  48. package/dist/resources/extensions/gsd/git-service.js +23 -1
  49. package/dist/resources/extensions/gsd/gitignore.js +33 -0
  50. package/dist/resources/extensions/gsd/gsd-db.js +44 -10
  51. package/dist/resources/extensions/gsd/guided-flow.js +106 -44
  52. package/dist/resources/extensions/gsd/health-widget-core.js +31 -0
  53. package/dist/resources/extensions/gsd/health-widget.js +17 -0
  54. package/dist/resources/extensions/gsd/index.js +1 -1
  55. package/dist/resources/extensions/gsd/memory-extractor.js +7 -0
  56. package/dist/resources/extensions/gsd/migrate-external.js +8 -1
  57. package/dist/resources/extensions/gsd/milestone-validation-gates.js +45 -0
  58. package/dist/resources/extensions/gsd/model-cost-table.js +18 -0
  59. package/dist/resources/extensions/gsd/model-router.js +35 -1
  60. package/dist/resources/extensions/gsd/native-git-bridge.js +17 -0
  61. package/dist/resources/extensions/gsd/notifications.js +16 -1
  62. package/dist/resources/extensions/gsd/parallel-eligibility.js +13 -2
  63. package/dist/resources/extensions/gsd/parallel-merge.js +78 -5
  64. package/dist/resources/extensions/gsd/parallel-orchestrator.js +23 -6
  65. package/dist/resources/extensions/gsd/parsers-legacy.js +20 -3
  66. package/dist/resources/extensions/gsd/paths.js +43 -0
  67. package/dist/resources/extensions/gsd/preferences-models.js +14 -1
  68. package/dist/resources/extensions/gsd/preferences-types.js +2 -1
  69. package/dist/resources/extensions/gsd/preferences.js +42 -31
  70. package/dist/resources/extensions/gsd/prompt-loader.js +4 -1
  71. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  72. package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -2
  73. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
  74. package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
  75. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -1
  76. package/dist/resources/extensions/gsd/prompts/forensics.md +2 -2
  77. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  78. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  79. package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -0
  80. package/dist/resources/extensions/gsd/prompts/rethink.md +1 -1
  81. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -0
  82. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  83. package/dist/resources/extensions/gsd/repo-identity.js +205 -11
  84. package/dist/resources/extensions/gsd/rethink.js +5 -0
  85. package/dist/resources/extensions/gsd/roadmap-slices.js +5 -4
  86. package/dist/resources/extensions/gsd/state.js +85 -27
  87. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
  88. package/dist/resources/extensions/gsd/tools/complete-task.js +34 -71
  89. package/dist/resources/extensions/gsd/tools/plan-milestone.js +12 -2
  90. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +29 -1
  91. package/dist/resources/extensions/gsd/tools/validate-milestone.js +18 -3
  92. package/dist/resources/extensions/gsd/triage-resolution.js +22 -7
  93. package/dist/resources/extensions/gsd/undo.js +2 -2
  94. package/dist/resources/extensions/gsd/unit-ownership.js +164 -33
  95. package/dist/resources/extensions/gsd/verdict-parser.js +20 -8
  96. package/dist/resources/extensions/gsd/workflow-manifest.js +24 -5
  97. package/dist/resources/extensions/gsd/workflow-projections.js +95 -63
  98. package/dist/resources/extensions/gsd/workflow-reconcile.js +35 -5
  99. package/dist/resources/extensions/gsd/workspace-index.js +24 -0
  100. package/dist/resources/extensions/gsd/worktree-manager.js +105 -1
  101. package/dist/resources/extensions/gsd/worktree-resolver.js +20 -3
  102. package/dist/resources/extensions/mcp-client/index.js +11 -7
  103. package/dist/resources/extensions/ollama/index.js +112 -0
  104. package/dist/resources/extensions/ollama/model-capabilities.js +115 -0
  105. package/dist/resources/extensions/ollama/ollama-client.js +168 -0
  106. package/dist/resources/extensions/ollama/ollama-commands.js +194 -0
  107. package/dist/resources/extensions/ollama/ollama-discovery.js +69 -0
  108. package/dist/resources/extensions/ollama/ollama-tool.js +184 -0
  109. package/dist/resources/extensions/ollama/types.js +2 -0
  110. package/dist/resources/extensions/search-the-web/extension-manifest.json +1 -1
  111. package/dist/resources/extensions/shared/interview-ui.js +11 -1
  112. package/dist/resources/skills/create-gsd-extension/SKILL.md +5 -3
  113. package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
  114. package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
  115. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
  116. package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
  117. package/dist/startup-model-validation.d.ts +39 -0
  118. package/dist/startup-model-validation.js +50 -0
  119. package/dist/web/standalone/.next/BUILD_ID +1 -1
  120. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  121. package/dist/web/standalone/.next/build-manifest.json +4 -4
  122. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  123. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  124. package/dist/web/standalone/.next/required-server-files.json +3 -3
  125. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  126. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  128. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  136. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  138. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
  139. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  140. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  141. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  142. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  143. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  144. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  145. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  152. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  164. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  192. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  198. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  204. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  208. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  212. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  214. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  215. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  216. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  217. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  218. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  219. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  220. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  221. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  222. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  223. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  224. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  225. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  226. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  227. package/dist/web/standalone/.next/server/app/index.html +1 -1
  228. package/dist/web/standalone/.next/server/app/index.rsc +5 -5
  229. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  230. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
  231. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  232. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  233. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  234. package/dist/web/standalone/.next/server/app/page.js +2 -2
  235. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  236. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  237. package/dist/web/standalone/.next/server/chunks/2229.js +2 -2
  238. package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
  239. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  240. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  241. package/dist/web/standalone/.next/server/middleware.js +2 -2
  242. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  243. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  244. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  245. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  246. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  247. package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +9 -0
  248. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  249. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  250. package/dist/web/standalone/.next/static/chunks/app/page-0c485498795110d6.js +1 -0
  251. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  252. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  253. package/dist/web/standalone/.next/static/chunks/{webpack-4332cbd5dd1be584.js → webpack-a1c1e452c6b32d04.js} +1 -1
  254. package/dist/web/standalone/.next/static/css/f6e8833d46e738d8.css +1 -0
  255. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  256. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  257. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  258. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  259. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  260. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  261. package/dist/web/standalone/server.js +1 -1
  262. package/dist/web-mode.js +2 -1
  263. package/package.json +2 -2
  264. package/packages/daemon/src/cli.ts +49 -0
  265. package/packages/daemon/src/daemon.test.ts +104 -1
  266. package/packages/daemon/src/daemon.ts +24 -1
  267. package/packages/daemon/src/discord-bot.ts +73 -3
  268. package/packages/daemon/src/event-bridge.ts +15 -9
  269. package/packages/daemon/src/event-formatter.ts +30 -2
  270. package/packages/daemon/src/index.ts +9 -0
  271. package/packages/daemon/src/launchd.test.ts +356 -0
  272. package/packages/daemon/src/launchd.ts +242 -0
  273. package/packages/daemon/src/message-batcher.test.ts +2 -2
  274. package/packages/daemon/src/message-batcher.ts +9 -3
  275. package/packages/daemon/src/orchestrator.test.ts +1 -0
  276. package/packages/daemon/src/orchestrator.ts +106 -2
  277. package/packages/native/dist/ast/index.js +9 -5
  278. package/packages/native/dist/ast/types.js +2 -1
  279. package/packages/native/dist/clipboard/index.js +12 -7
  280. package/packages/native/dist/clipboard/types.js +2 -1
  281. package/packages/native/dist/diff/index.js +12 -7
  282. package/packages/native/dist/diff/types.js +2 -1
  283. package/packages/native/dist/fd/index.js +6 -3
  284. package/packages/native/dist/fd/types.js +2 -1
  285. package/packages/native/dist/glob/index.js +9 -5
  286. package/packages/native/dist/glob/types.js +2 -1
  287. package/packages/native/dist/grep/index.js +9 -5
  288. package/packages/native/dist/grep/types.js +2 -1
  289. package/packages/native/dist/gsd-parser/index.js +18 -11
  290. package/packages/native/dist/gsd-parser/types.js +2 -1
  291. package/packages/native/dist/highlight/index.js +12 -7
  292. package/packages/native/dist/highlight/types.js +2 -1
  293. package/packages/native/dist/html/index.js +6 -3
  294. package/packages/native/dist/html/types.js +2 -1
  295. package/packages/native/dist/image/index.js +10 -5
  296. package/packages/native/dist/image/types.js +7 -4
  297. package/packages/native/dist/index.js +70 -17
  298. package/packages/native/dist/json-parse/index.js +13 -8
  299. package/packages/native/dist/native.js +47 -10
  300. package/packages/native/dist/ps/index.js +15 -9
  301. package/packages/native/dist/ps/types.js +2 -1
  302. package/packages/native/dist/stream-process/index.js +12 -7
  303. package/packages/native/dist/text/index.js +24 -14
  304. package/packages/native/dist/text/types.js +5 -2
  305. package/packages/native/dist/truncate/index.js +12 -7
  306. package/packages/native/dist/ttsr/index.js +12 -7
  307. package/packages/native/dist/ttsr/types.js +2 -1
  308. package/packages/native/dist/xxhash/index.js +9 -5
  309. package/packages/native/package.json +19 -19
  310. package/packages/native/src/__tests__/module-compat.test.mjs +91 -0
  311. package/packages/native/src/native.ts +9 -8
  312. package/packages/pi-agent-core/dist/agent-loop.js +3 -2
  313. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  314. package/packages/pi-agent-core/dist/proxy.d.ts +1 -1
  315. package/packages/pi-agent-core/dist/proxy.d.ts.map +1 -1
  316. package/packages/pi-agent-core/dist/proxy.js.map +1 -1
  317. package/packages/pi-agent-core/src/agent-loop.test.ts +45 -0
  318. package/packages/pi-agent-core/src/agent-loop.ts +3 -2
  319. package/packages/pi-agent-core/src/proxy.ts +1 -1
  320. package/packages/pi-ai/dist/env-api-keys.js +1 -0
  321. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  322. package/packages/pi-ai/dist/index.d.ts +1 -0
  323. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  324. package/packages/pi-ai/dist/index.js +1 -0
  325. package/packages/pi-ai/dist/index.js.map +1 -1
  326. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  327. package/packages/pi-ai/dist/providers/anthropic-shared.js +19 -2
  328. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  329. package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts +2 -0
  330. package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts.map +1 -0
  331. package/packages/pi-ai/dist/providers/anthropic-shared.test.js +25 -0
  332. package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -0
  333. package/packages/pi-ai/dist/types.d.ts +3 -3
  334. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  335. package/packages/pi-ai/dist/types.js.map +1 -1
  336. package/packages/pi-ai/dist/utils/json-parse.d.ts +3 -0
  337. package/packages/pi-ai/dist/utils/json-parse.d.ts.map +1 -1
  338. package/packages/pi-ai/dist/utils/json-parse.js +24 -1
  339. package/packages/pi-ai/dist/utils/json-parse.js.map +1 -1
  340. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts +37 -0
  341. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -0
  342. package/packages/pi-ai/dist/utils/repair-tool-json.js +75 -0
  343. package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -0
  344. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts +2 -0
  345. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts.map +1 -0
  346. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +73 -0
  347. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -0
  348. package/packages/pi-ai/src/env-api-keys.ts +1 -0
  349. package/packages/pi-ai/src/index.ts +1 -0
  350. package/packages/pi-ai/src/providers/anthropic-shared.test.ts +29 -0
  351. package/packages/pi-ai/src/providers/anthropic-shared.ts +17 -2
  352. package/packages/pi-ai/src/types.ts +3 -2
  353. package/packages/pi-ai/src/utils/json-parse.ts +28 -1
  354. package/packages/pi-ai/src/utils/repair-tool-json.ts +88 -0
  355. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +102 -0
  356. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +4 -0
  357. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  358. package/packages/pi-coding-agent/dist/core/agent-session.js +31 -0
  359. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  360. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +17 -1
  361. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  362. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +62 -2
  363. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  364. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts +6 -0
  365. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts.map +1 -0
  366. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +176 -0
  367. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -0
  368. package/packages/pi-coding-agent/dist/core/exec.d.ts.map +1 -1
  369. package/packages/pi-coding-agent/dist/core/exec.js +3 -1
  370. package/packages/pi-coding-agent/dist/core/exec.js.map +1 -1
  371. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts +28 -0
  372. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts.map +1 -0
  373. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js +37 -0
  374. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js.map +1 -0
  375. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts +2 -0
  376. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts.map +1 -0
  377. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js +63 -0
  378. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js.map +1 -0
  379. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts +19 -0
  380. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts.map +1 -0
  381. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js +115 -0
  382. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js.map +1 -0
  383. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts +2 -0
  384. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts.map +1 -0
  385. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js +109 -0
  386. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js.map +1 -0
  387. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +4 -0
  388. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  389. package/packages/pi-coding-agent/dist/core/extensions/index.js +2 -0
  390. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  391. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
  392. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  393. package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -0
  394. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  395. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts +44 -0
  396. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts.map +1 -0
  397. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js +97 -0
  398. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js.map +1 -0
  399. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts +2 -0
  400. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts.map +1 -0
  401. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js +181 -0
  402. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js.map +1 -0
  403. package/packages/pi-coding-agent/dist/core/index.d.ts +1 -1
  404. package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
  405. package/packages/pi-coding-agent/dist/core/index.js +1 -1
  406. package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
  407. package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
  408. package/packages/pi-coding-agent/dist/core/lsp/index.js +3 -0
  409. package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
  410. package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
  411. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +3 -0
  412. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js.map +1 -1
  413. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  414. package/packages/pi-coding-agent/dist/core/messages.js +31 -2
  415. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  416. package/packages/pi-coding-agent/dist/core/messages.test.d.ts +9 -0
  417. package/packages/pi-coding-agent/dist/core/messages.test.d.ts.map +1 -0
  418. package/packages/pi-coding-agent/dist/core/messages.test.js +86 -0
  419. package/packages/pi-coding-agent/dist/core/messages.test.js.map +1 -0
  420. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  421. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
  422. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  423. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +10 -0
  424. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  425. package/packages/pi-coding-agent/dist/core/resource-loader.js +12 -1
  426. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  427. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +6 -0
  428. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  429. package/packages/pi-coding-agent/dist/core/retry-handler.js +48 -1
  430. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  431. package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts +9 -0
  432. package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts.map +1 -0
  433. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +193 -0
  434. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -0
  435. package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
  436. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +10 -3
  437. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
  438. package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  439. package/packages/pi-coding-agent/dist/core/tools/read.js +13 -4
  440. package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  441. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts +16 -0
  442. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts.map +1 -0
  443. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +80 -0
  444. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -0
  445. package/packages/pi-coding-agent/dist/index.d.ts +2 -2
  446. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  447. package/packages/pi-coding-agent/dist/index.js +1 -1
  448. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  449. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  450. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +4 -0
  451. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  452. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts +1 -0
  453. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts.map +1 -1
  454. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js +5 -0
  455. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js.map +1 -1
  456. package/packages/pi-coding-agent/package.json +1 -1
  457. package/packages/pi-coding-agent/src/core/agent-session.ts +38 -1
  458. package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +236 -0
  459. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +94 -1
  460. package/packages/pi-coding-agent/src/core/exec.ts +3 -1
  461. package/packages/pi-coding-agent/src/core/extensions/extension-manifest.test.ts +77 -0
  462. package/packages/pi-coding-agent/src/core/extensions/extension-manifest.ts +62 -0
  463. package/packages/pi-coding-agent/src/core/extensions/extension-sort.test.ts +134 -0
  464. package/packages/pi-coding-agent/src/core/extensions/extension-sort.ts +137 -0
  465. package/packages/pi-coding-agent/src/core/extensions/index.ts +4 -0
  466. package/packages/pi-coding-agent/src/core/extensions/loader.ts +5 -0
  467. package/packages/pi-coding-agent/src/core/image-overflow-recovery.test.ts +228 -0
  468. package/packages/pi-coding-agent/src/core/image-overflow-recovery.ts +118 -0
  469. package/packages/pi-coding-agent/src/core/index.ts +6 -0
  470. package/packages/pi-coding-agent/src/core/lsp/index.ts +3 -0
  471. package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +3 -0
  472. package/packages/pi-coding-agent/src/core/messages.test.ts +114 -0
  473. package/packages/pi-coding-agent/src/core/messages.ts +29 -2
  474. package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
  475. package/packages/pi-coding-agent/src/core/resource-loader.ts +20 -1
  476. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +255 -0
  477. package/packages/pi-coding-agent/src/core/retry-handler.ts +52 -1
  478. package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +11 -3
  479. package/packages/pi-coding-agent/src/core/tools/read.ts +14 -4
  480. package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +92 -0
  481. package/packages/pi-coding-agent/src/index.ts +6 -0
  482. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +7 -0
  483. package/packages/pi-coding-agent/src/modes/rpc/remote-terminal.ts +6 -0
  484. package/packages/pi-tui/dist/terminal.d.ts +2 -0
  485. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  486. package/packages/pi-tui/dist/terminal.js +9 -0
  487. package/packages/pi-tui/dist/terminal.js.map +1 -1
  488. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  489. package/packages/pi-tui/dist/tui.js +9 -0
  490. package/packages/pi-tui/dist/tui.js.map +1 -1
  491. package/packages/pi-tui/src/terminal.ts +14 -0
  492. package/packages/pi-tui/src/tui.ts +8 -0
  493. package/pkg/package.json +1 -1
  494. package/scripts/ensure-workspace-builds.cjs +45 -14
  495. package/src/resources/agents/researcher.md +1 -1
  496. package/src/resources/extensions/ask-user-questions.ts +21 -3
  497. package/src/resources/extensions/async-jobs/extension-manifest.json +1 -1
  498. package/src/resources/extensions/bg-shell/extension-manifest.json +1 -1
  499. package/src/resources/extensions/browser-tools/extension-manifest.json +1 -1
  500. package/src/resources/extensions/claude-code-cli/partial-builder.ts +13 -6
  501. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +63 -35
  502. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +28 -0
  503. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -1
  504. package/src/resources/extensions/context7/extension-manifest.json +1 -1
  505. package/src/resources/extensions/get-secrets-from-user.ts +8 -5
  506. package/src/resources/extensions/google-search/extension-manifest.json +1 -1
  507. package/src/resources/extensions/google-search/index.ts +2 -1
  508. package/src/resources/extensions/gsd/auto/infra-errors.ts +3 -0
  509. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  510. package/src/resources/extensions/gsd/auto/phases.ts +43 -34
  511. package/src/resources/extensions/gsd/auto-artifact-paths.ts +2 -2
  512. package/src/resources/extensions/gsd/auto-dashboard.ts +37 -19
  513. package/src/resources/extensions/gsd/auto-dispatch.ts +21 -5
  514. package/src/resources/extensions/gsd/auto-model-selection.ts +26 -5
  515. package/src/resources/extensions/gsd/auto-post-unit.ts +18 -4
  516. package/src/resources/extensions/gsd/auto-prompts.ts +1 -1
  517. package/src/resources/extensions/gsd/auto-recovery.ts +12 -5
  518. package/src/resources/extensions/gsd/auto-start.ts +35 -26
  519. package/src/resources/extensions/gsd/auto-worktree.ts +197 -11
  520. package/src/resources/extensions/gsd/auto.ts +5 -0
  521. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +31 -0
  522. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +87 -9
  523. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +38 -1
  524. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +31 -19
  525. package/src/resources/extensions/gsd/bootstrap/system-context.ts +50 -11
  526. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +75 -0
  527. package/src/resources/extensions/gsd/captures.ts +63 -3
  528. package/src/resources/extensions/gsd/db-writer.ts +140 -7
  529. package/src/resources/extensions/gsd/dispatch-guard.ts +12 -1
  530. package/src/resources/extensions/gsd/doctor-git-checks.ts +26 -0
  531. package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
  532. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +5 -4
  533. package/src/resources/extensions/gsd/doctor.ts +3 -1
  534. package/src/resources/extensions/gsd/error-classifier.ts +14 -11
  535. package/src/resources/extensions/gsd/extension-manifest.json +16 -1
  536. package/src/resources/extensions/gsd/forensics.ts +144 -20
  537. package/src/resources/extensions/gsd/git-service.ts +26 -3
  538. package/src/resources/extensions/gsd/gitignore.ts +33 -0
  539. package/src/resources/extensions/gsd/gsd-db.ts +49 -8
  540. package/src/resources/extensions/gsd/guided-flow.ts +114 -45
  541. package/src/resources/extensions/gsd/health-widget-core.ts +34 -0
  542. package/src/resources/extensions/gsd/health-widget.ts +17 -0
  543. package/src/resources/extensions/gsd/index.ts +1 -0
  544. package/src/resources/extensions/gsd/memory-extractor.ts +8 -0
  545. package/src/resources/extensions/gsd/migrate-external.ts +9 -1
  546. package/src/resources/extensions/gsd/milestone-validation-gates.ts +56 -0
  547. package/src/resources/extensions/gsd/model-cost-table.ts +19 -0
  548. package/src/resources/extensions/gsd/model-router.ts +35 -1
  549. package/src/resources/extensions/gsd/native-git-bridge.ts +17 -0
  550. package/src/resources/extensions/gsd/notifications.ts +16 -0
  551. package/src/resources/extensions/gsd/parallel-eligibility.ts +15 -2
  552. package/src/resources/extensions/gsd/parallel-merge.ts +87 -4
  553. package/src/resources/extensions/gsd/parallel-orchestrator.ts +23 -6
  554. package/src/resources/extensions/gsd/parsers-legacy.ts +22 -3
  555. package/src/resources/extensions/gsd/paths.ts +42 -0
  556. package/src/resources/extensions/gsd/preferences-models.ts +14 -1
  557. package/src/resources/extensions/gsd/preferences-types.ts +2 -1
  558. package/src/resources/extensions/gsd/preferences.ts +45 -29
  559. package/src/resources/extensions/gsd/prompt-loader.ts +4 -1
  560. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  561. package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -2
  562. package/src/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
  563. package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
  564. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -1
  565. package/src/resources/extensions/gsd/prompts/forensics.md +2 -2
  566. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  567. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  568. package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -0
  569. package/src/resources/extensions/gsd/prompts/rethink.md +1 -1
  570. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -0
  571. package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  572. package/src/resources/extensions/gsd/repo-identity.ts +186 -11
  573. package/src/resources/extensions/gsd/rethink.ts +6 -0
  574. package/src/resources/extensions/gsd/roadmap-slices.ts +5 -4
  575. package/src/resources/extensions/gsd/state.ts +84 -32
  576. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +47 -0
  577. package/src/resources/extensions/gsd/tests/auto-mode-interactive-guard.test.ts +71 -0
  578. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +71 -1
  579. package/src/resources/extensions/gsd/tests/captures.test.ts +103 -0
  580. package/src/resources/extensions/gsd/tests/cli-provider-rate-limit.test.ts +47 -0
  581. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +27 -0
  582. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +21 -0
  583. package/src/resources/extensions/gsd/tests/completion-hierarchy-guards.test.ts +192 -0
  584. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +131 -0
  585. package/src/resources/extensions/gsd/tests/db-writer.test.ts +7 -12
  586. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +78 -5
  587. package/src/resources/extensions/gsd/tests/derive-state.test.ts +29 -0
  588. package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +47 -0
  589. package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +127 -0
  590. package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +40 -0
  591. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +47 -0
  592. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
  593. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +117 -0
  594. package/src/resources/extensions/gsd/tests/dynamic-routing-default.test.ts +20 -0
  595. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +74 -0
  596. package/src/resources/extensions/gsd/tests/event-replay-idempotency.test.ts +140 -0
  597. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +129 -0
  598. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +96 -0
  599. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +31 -0
  600. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +125 -12
  601. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +164 -0
  602. package/src/resources/extensions/gsd/tests/guided-flow-dynamic-routing.test.ts +135 -0
  603. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +97 -0
  604. package/src/resources/extensions/gsd/tests/health-widget.test.ts +67 -0
  605. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +107 -0
  606. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +111 -1
  607. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +101 -0
  608. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +59 -0
  609. package/src/resources/extensions/gsd/tests/integration/doctor-false-positives.test.ts +243 -0
  610. package/src/resources/extensions/gsd/tests/integration/gitignore-staging-2570.test.ts +150 -0
  611. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +110 -0
  612. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +1 -1
  613. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +959 -0
  614. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +85 -2
  615. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +105 -0
  616. package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +116 -0
  617. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +34 -0
  618. package/src/resources/extensions/gsd/tests/model-router.test.ts +68 -3
  619. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +28 -0
  620. package/src/resources/extensions/gsd/tests/notifications.test.ts +45 -0
  621. package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +159 -0
  622. package/src/resources/extensions/gsd/tests/parallel-eligibility-ghost.test.ts +150 -0
  623. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +9 -8
  624. package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +70 -0
  625. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +33 -1
  626. package/src/resources/extensions/gsd/tests/preferences.test.ts +34 -0
  627. package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +297 -0
  628. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +36 -0
  629. package/src/resources/extensions/gsd/tests/prompt-loader-replacement.test.ts +178 -0
  630. package/src/resources/extensions/gsd/tests/prompt-tool-names.test.ts +69 -0
  631. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +38 -0
  632. package/src/resources/extensions/gsd/tests/queue-execution-guard.test.ts +157 -0
  633. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +90 -0
  634. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +117 -0
  635. package/src/resources/extensions/gsd/tests/reconciliation-edge-cases.test.ts +162 -0
  636. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +97 -0
  637. package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +134 -0
  638. package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +233 -0
  639. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +305 -0
  640. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +405 -0
  641. package/src/resources/extensions/gsd/tests/state-derivation-parity.test.ts +257 -0
  642. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +1628 -0
  643. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +106 -0
  644. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +174 -0
  645. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +221 -0
  646. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +2 -1
  647. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +8 -0
  648. package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +289 -0
  649. package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +100 -17
  650. package/src/resources/extensions/gsd/tests/vacuum-recovery.test.ts +154 -0
  651. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +27 -2
  652. package/src/resources/extensions/gsd/tests/validation-gate-patterns.test.ts +44 -2
  653. package/src/resources/extensions/gsd/tests/verdict-parser.test.ts +156 -0
  654. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +82 -0
  655. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +48 -0
  656. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +92 -0
  657. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -2
  658. package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +140 -0
  659. package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +175 -0
  660. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +101 -0
  661. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +48 -1
  662. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +29 -5
  663. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +95 -0
  664. package/src/resources/extensions/gsd/tools/complete-task.ts +36 -74
  665. package/src/resources/extensions/gsd/tools/plan-milestone.ts +13 -1
  666. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +36 -0
  667. package/src/resources/extensions/gsd/tools/validate-milestone.ts +25 -2
  668. package/src/resources/extensions/gsd/triage-resolution.ts +23 -6
  669. package/src/resources/extensions/gsd/types.ts +4 -2
  670. package/src/resources/extensions/gsd/undo.ts +2 -2
  671. package/src/resources/extensions/gsd/unit-ownership.ts +206 -35
  672. package/src/resources/extensions/gsd/verdict-parser.ts +21 -6
  673. package/src/resources/extensions/gsd/workflow-logger.ts +3 -1
  674. package/src/resources/extensions/gsd/workflow-manifest.ts +22 -5
  675. package/src/resources/extensions/gsd/workflow-projections.ts +97 -64
  676. package/src/resources/extensions/gsd/workflow-reconcile.ts +39 -10
  677. package/src/resources/extensions/gsd/workspace-index.ts +30 -0
  678. package/src/resources/extensions/gsd/worktree-manager.ts +120 -1
  679. package/src/resources/extensions/gsd/worktree-resolver.ts +22 -3
  680. package/src/resources/extensions/mcp-client/index.ts +13 -7
  681. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +55 -0
  682. package/src/resources/extensions/ollama/index.ts +130 -0
  683. package/src/resources/extensions/ollama/model-capabilities.ts +145 -0
  684. package/src/resources/extensions/ollama/ollama-client.ts +196 -0
  685. package/src/resources/extensions/ollama/ollama-commands.ts +248 -0
  686. package/src/resources/extensions/ollama/ollama-discovery.ts +106 -0
  687. package/src/resources/extensions/ollama/ollama-tool.ts +218 -0
  688. package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +162 -0
  689. package/src/resources/extensions/ollama/tests/ollama-client.test.ts +38 -0
  690. package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +28 -0
  691. package/src/resources/extensions/ollama/types.ts +130 -0
  692. package/src/resources/extensions/search-the-web/extension-manifest.json +1 -1
  693. package/src/resources/extensions/shared/interview-ui.ts +12 -1
  694. package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +156 -0
  695. package/src/resources/skills/create-gsd-extension/SKILL.md +5 -3
  696. package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
  697. package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
  698. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
  699. package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
  700. package/dist/web/standalone/.next/static/chunks/6502.2305d0afd2385711.js +0 -9
  701. package/dist/web/standalone/.next/static/chunks/app/page-62be3b5fa91e4c8f.js +0 -1
  702. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  703. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  704. package/dist/web/standalone/.next/static/css/a58ef8a151aa0493.css +0 -1
  705. package/src/resources/extensions/gsd/tests/empty-db-reconciliation.test.ts +0 -79
  706. /package/dist/web/standalone/.next/static/{yowc5qPtuKxjOr22KmOAy → R0D4xaIPl5kg93edN7Oo0}/_buildManifest.js +0 -0
  707. /package/dist/web/standalone/.next/static/{yowc5qPtuKxjOr22KmOAy → R0D4xaIPl5kg93edN7Oo0}/_ssgManifest.js +0 -0
@@ -3,6 +3,7 @@ import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
3
3
  import { parseRoadmap, parsePlan } from "./parsers-legacy.js";
4
4
  import { resolveMilestoneFile, resolveSliceFile, resolveTaskFile, resolveTasksDir, } from "./paths.js";
5
5
  import { deriveState } from "./state.js";
6
+ import { extractVerdict } from "./verdict-parser.js";
6
7
  import { findMilestoneIds } from "./guided-flow.js";
7
8
  import { getSliceBranchName, detectWorktreeName } from "./worktree.js";
8
9
  // Extract milestone title from roadmap header without using parsers.
@@ -116,6 +117,29 @@ export async function indexWorkspace(basePath, opts = {}) {
116
117
  taskId: state.activeTask?.id,
117
118
  phase: state.phase,
118
119
  };
120
+ // Enrich milestones with authoritative status from state registry (#2807)
121
+ if (state.registry) {
122
+ const registryMap = new Map(state.registry.map(e => [e.id, e]));
123
+ for (const milestone of milestones) {
124
+ const entry = registryMap.get(milestone.id);
125
+ if (entry) {
126
+ milestone.status = entry.status;
127
+ }
128
+ }
129
+ }
130
+ // Populate validationVerdict from VALIDATION files (#2807)
131
+ for (const milestone of milestones) {
132
+ const validationPath = resolveMilestoneFile(basePath, milestone.id, "VALIDATION");
133
+ if (validationPath) {
134
+ const validationContent = await loadFile(validationPath);
135
+ if (validationContent) {
136
+ const verdict = extractVerdict(validationContent);
137
+ if (verdict === "pass" || verdict === "needs-attention" || verdict === "needs-remediation") {
138
+ milestone.validationVerdict = verdict;
139
+ }
140
+ }
141
+ }
142
+ }
119
143
  const scopes = [{ scope: "project", label: "project", kind: "project" }];
120
144
  for (const milestone of milestones) {
121
145
  scopes.push({ scope: milestone.id, label: `${milestone.id}: ${milestone.title}`, kind: "milestone" });
@@ -14,7 +14,7 @@
14
14
  * 3. merge() — LLM-guided reconciliation of .gsd/ artifacts back to main
15
15
  * 4. remove() — git worktree remove + branch cleanup
16
16
  */
17
- import { existsSync, mkdirSync, readFileSync, realpathSync, rmSync } from "node:fs";
17
+ import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, realpathSync, rmSync } from "node:fs";
18
18
  import { execFileSync } from "node:child_process";
19
19
  import { join, resolve, sep } from "node:path";
20
20
  import { GSDError, GSD_PARSE_ERROR, GSD_STALE_STATE, GSD_LOCK_HELD, GSD_GIT_ERROR, GSD_MERGE_CONFLICT } from "./errors.js";
@@ -203,6 +203,73 @@ export function listWorktrees(basePath) {
203
203
  }
204
204
  return worktrees;
205
205
  }
206
+ // ─── Nested .git Detection (#2616) ──────────────────────────────────────
207
+ //
208
+ // Scaffolding tools (create-next-app, cargo init, etc.) create nested .git
209
+ // directories inside worktrees. Git records these as gitlinks (mode 160000)
210
+ // without a .gitmodules entry — so worktree cleanup destroys the only copy
211
+ // of their object database, causing permanent silent data loss.
212
+ /** Directories to skip when scanning for nested .git dirs. */
213
+ const NESTED_GIT_SKIP_DIRS = new Set([
214
+ ".git", ".gsd", "node_modules", ".next", ".nuxt", "dist", "build",
215
+ "__pycache__", ".tox", ".venv", "venv", "target", "vendor",
216
+ ]);
217
+ /**
218
+ * Recursively find nested .git directories inside a worktree root.
219
+ * Returns paths to directories that contain their own .git (directory, not file).
220
+ * Skips node_modules, .gsd, and other non-project directories for performance.
221
+ *
222
+ * A nested .git *directory* (not a .git file — which is a legitimate worktree
223
+ * pointer) indicates a scaffolded repo that will become an orphaned gitlink.
224
+ */
225
+ export function findNestedGitDirs(rootPath) {
226
+ const results = [];
227
+ function walk(dir, depth) {
228
+ // Cap recursion depth to avoid runaway scanning
229
+ if (depth > 10)
230
+ return;
231
+ let entries;
232
+ try {
233
+ entries = readdirSync(dir);
234
+ }
235
+ catch {
236
+ return; // Permission denied, broken symlink, etc.
237
+ }
238
+ for (const entry of entries) {
239
+ if (NESTED_GIT_SKIP_DIRS.has(entry))
240
+ continue;
241
+ const fullPath = join(dir, entry);
242
+ // Only follow real directories, not symlinks
243
+ let stat;
244
+ try {
245
+ stat = lstatSync(fullPath);
246
+ }
247
+ catch {
248
+ continue;
249
+ }
250
+ if (!stat.isDirectory())
251
+ continue;
252
+ // Check if this directory contains a .git *directory* (not a .git file).
253
+ // A .git file is a worktree pointer and is legitimate.
254
+ // A .git directory is a standalone repo created by scaffolding.
255
+ const innerGit = join(fullPath, ".git");
256
+ try {
257
+ const innerStat = lstatSync(innerGit);
258
+ if (innerStat.isDirectory()) {
259
+ results.push(fullPath);
260
+ // Don't recurse into the nested repo — we found what we need
261
+ continue;
262
+ }
263
+ }
264
+ catch {
265
+ // No .git here — continue scanning
266
+ }
267
+ walk(fullPath, depth + 1);
268
+ }
269
+ }
270
+ walk(rootPath, 0);
271
+ return results;
272
+ }
206
273
  /**
207
274
  * Remove a worktree and optionally delete its branch.
208
275
  * If the process is currently inside the worktree, chdir out first.
@@ -269,6 +336,24 @@ export function removeWorktree(basePath, name, opts = {}) {
269
336
  // submodule status failed — proceed with normal removal
270
337
  }
271
338
  }
339
+ // Nested .git safety (#2616): detect nested .git directories created by
340
+ // scaffolding tools (create-next-app, cargo init, etc.). These produce
341
+ // gitlink entries (mode 160000) without .gitmodules — cleanup would destroy
342
+ // the only copy of the nested object database, causing permanent data loss.
343
+ // Fix: remove the nested .git dirs so git tracks the files as regular content.
344
+ const nestedGitDirs = findNestedGitDirs(resolvedWtPath);
345
+ if (nestedGitDirs.length > 0) {
346
+ for (const nestedDir of nestedGitDirs) {
347
+ const nestedGitPath = join(nestedDir, ".git");
348
+ try {
349
+ rmSync(nestedGitPath, { recursive: true, force: true });
350
+ logWarning("reconcile", `Removed nested .git directory from scaffolded project to prevent data loss (#2616)`, { worktree: name, nestedRepo: nestedDir });
351
+ }
352
+ catch {
353
+ logWarning("reconcile", `Failed to remove nested .git directory — files may be lost as orphaned gitlink`, { worktree: name, nestedRepo: nestedDir });
354
+ }
355
+ }
356
+ }
272
357
  // Remove worktree: try non-force first when submodules have changes,
273
358
  // falling back to force only after submodule state has been preserved.
274
359
  const useForce = hasSubmoduleChanges ? false : force;
@@ -283,6 +368,25 @@ export function removeWorktree(basePath, name, opts = {}) {
283
368
  }
284
369
  catch { /* may fail */ }
285
370
  }
371
+ // (#2821) If the worktree directory STILL exists after both native removal
372
+ // attempts (e.g. untracked files like ASSESSMENT/UAT-RESULT prevent git
373
+ // worktree remove), force-remove the git internal worktree metadata first,
374
+ // then remove the filesystem directory. Without this, the .git/worktrees/<name>
375
+ // lock prevents rmSync from cleaning up, and the orphaned worktree directory
376
+ // causes every subsequent `/gsd auto` to re-enter the stale worktree.
377
+ if (existsSync(resolvedWtPath)) {
378
+ try {
379
+ const wtInternalDir = join(basePath, ".git", "worktrees", name);
380
+ if (existsSync(wtInternalDir)) {
381
+ rmSync(wtInternalDir, { recursive: true, force: true });
382
+ }
383
+ rmSync(resolvedWtPath, { recursive: true, force: true });
384
+ }
385
+ catch {
386
+ logWarning("reconcile", `Worktree directory could not be removed after git internal cleanup: ${resolvedWtPath}. ` +
387
+ `Manual cleanup: rm -rf "${resolvedWtPath.replaceAll("\\", "/")}"`, { worktree: name });
388
+ }
389
+ }
286
390
  // Prune stale entries so git knows the worktree is gone
287
391
  nativeWorktreePrune(basePath);
288
392
  if (deleteBranch) {
@@ -248,7 +248,12 @@ export class WorktreeResolver {
248
248
  eventType: "worktree-merge-start",
249
249
  data: { milestoneId, mode },
250
250
  });
251
- if (mode === "none") {
251
+ // #2625: If we are physically inside an auto-worktree, we MUST merge
252
+ // regardless of the current isolation config. This prevents data loss when
253
+ // the default isolation mode changes between versions (e.g., "worktree" ->
254
+ // "none"): the worktree branch still holds real commits that need merging.
255
+ const inWorktree = this.deps.isInAutoWorktree(this.s.basePath) && this.s.originalBasePath;
256
+ if (mode === "none" && !inWorktree) {
252
257
  debugLog("WorktreeResolver", {
253
258
  action: "mergeAndExit",
254
259
  milestoneId,
@@ -257,8 +262,7 @@ export class WorktreeResolver {
257
262
  });
258
263
  return;
259
264
  }
260
- if (mode === "worktree" ||
261
- (this.deps.isInAutoWorktree(this.s.basePath) && this.s.originalBasePath)) {
265
+ if (mode === "worktree" || inWorktree) {
262
266
  this._mergeWorktreeMode(milestoneId, ctx);
263
267
  }
264
268
  else if (mode === "branch") {
@@ -308,6 +312,19 @@ export class WorktreeResolver {
308
312
  if (roadmapPath) {
309
313
  const roadmapContent = this.deps.readFileSync(roadmapPath, "utf-8");
310
314
  const mergeResult = this.deps.mergeMilestoneToMain(originalBase, milestoneId, roadmapContent);
315
+ // #2945 Bug 3: mergeMilestoneToMain performs best-effort worktree
316
+ // cleanup internally (step 12), but it can silently fail on Windows
317
+ // or when the worktree directory is locked. Perform a secondary
318
+ // teardown here to ensure the worktree is properly cleaned up.
319
+ // This is idempotent — if the worktree was already removed,
320
+ // teardownAutoWorktree handles the no-op case gracefully.
321
+ try {
322
+ this.deps.teardownAutoWorktree(originalBase, milestoneId);
323
+ }
324
+ catch {
325
+ // Best-effort — the primary cleanup in mergeMilestoneToMain may
326
+ // have already removed the worktree.
327
+ }
311
328
  if (mergeResult.codeFilesChanged) {
312
329
  ctx.notify(`Milestone ${milestoneId} merged to main.${mergeResult.pushed ? " Pushed to remote." : ""}`, "info");
313
330
  }
@@ -74,7 +74,9 @@ function readConfigs() {
74
74
  return servers;
75
75
  }
76
76
  function getServerConfig(name) {
77
- return readConfigs().find((s) => s.name === name);
77
+ const trimmed = name.trim();
78
+ return readConfigs().find((s) => s.name === trimmed ||
79
+ s.name.toLowerCase() === trimmed.toLowerCase());
78
80
  }
79
81
  /** Resolve ${VAR} references in env values against process.env. */
80
82
  function resolveEnv(env) {
@@ -90,12 +92,14 @@ function resolveEnv(env) {
90
92
  return resolved;
91
93
  }
92
94
  async function getOrConnect(name, signal) {
93
- const existing = connections.get(name);
94
- if (existing)
95
- return existing.client;
96
95
  const config = getServerConfig(name);
97
96
  if (!config)
98
97
  throw new Error(`Unknown MCP server: "${name}". Use mcp_servers to list available servers.`);
98
+ // Always use config.name as the canonical cache key so that variant
99
+ // casing / whitespace still hits the same connection.
100
+ const existing = connections.get(config.name);
101
+ if (existing)
102
+ return existing.client;
99
103
  const client = new Client({ name: "gsd", version: "1.0.0" });
100
104
  let transport;
101
105
  if (config.transport === "stdio" && config.command) {
@@ -108,14 +112,14 @@ async function getOrConnect(name, signal) {
108
112
  });
109
113
  }
110
114
  else if (config.transport === "http" && config.url) {
111
- const resolvedUrl = config.url.replace(/\$\{([^}]+)\}/g, (_, name) => process.env[name] ?? "");
115
+ const resolvedUrl = config.url.replace(/\$\{([^}]+)\}/g, (_, varName) => process.env[varName] ?? "");
112
116
  transport = new StreamableHTTPClientTransport(new URL(resolvedUrl));
113
117
  }
114
118
  else {
115
- throw new Error(`Server "${name}" has unsupported transport: ${config.transport}`);
119
+ throw new Error(`Server "${config.name}" has unsupported transport: ${config.transport}`);
116
120
  }
117
121
  await client.connect(transport, { signal, timeout: 30000 });
118
- connections.set(name, { client, transport });
122
+ connections.set(config.name, { client, transport });
119
123
  return client;
120
124
  }
121
125
  async function closeAll() {
@@ -0,0 +1,112 @@
1
+ // GSD2 — Ollama Extension: First-class local LLM support
2
+ /**
3
+ * Ollama Extension
4
+ *
5
+ * Auto-detects a running Ollama instance, discovers locally pulled models,
6
+ * and registers them as a first-class provider. No configuration required —
7
+ * if Ollama is running, models appear automatically.
8
+ *
9
+ * Features:
10
+ * - Auto-discovery of local models via /api/tags
11
+ * - Capability detection (vision, reasoning, context window)
12
+ * - /ollama slash commands for model management
13
+ * - ollama_manage tool for LLM-driven model operations
14
+ * - Zero-cost model registration (local inference)
15
+ *
16
+ * Respects OLLAMA_HOST env var for non-default endpoints.
17
+ */
18
+ import { importExtensionModule } from "@gsd/pi-coding-agent";
19
+ import * as client from "./ollama-client.js";
20
+ import { discoverModels, getOllamaOpenAIBaseUrl } from "./ollama-discovery.js";
21
+ import { registerOllamaCommands } from "./ollama-commands.js";
22
+ /** Default compat settings for Ollama models via OpenAI-compat endpoint */
23
+ const OLLAMA_COMPAT = {
24
+ supportsDeveloperRole: false,
25
+ supportsReasoningEffort: false,
26
+ supportsUsageInStreaming: false,
27
+ maxTokensField: "max_tokens",
28
+ supportsStore: false,
29
+ };
30
+ let toolsPromise = null;
31
+ async function registerOllamaTools(pi) {
32
+ if (!toolsPromise) {
33
+ toolsPromise = (async () => {
34
+ const { registerOllamaTool } = await importExtensionModule(import.meta.url, "./ollama-tool.js");
35
+ registerOllamaTool(pi);
36
+ })().catch((error) => {
37
+ toolsPromise = null;
38
+ throw error;
39
+ });
40
+ }
41
+ return toolsPromise;
42
+ }
43
+ /** Track whether we've registered models so we can clean up on shutdown */
44
+ let providerRegistered = false;
45
+ /**
46
+ * Probe Ollama and register discovered models.
47
+ * Safe to call multiple times — re-discovers and re-registers.
48
+ */
49
+ async function probeAndRegister(pi) {
50
+ const running = await client.isRunning();
51
+ if (!running) {
52
+ if (providerRegistered) {
53
+ pi.unregisterProvider("ollama");
54
+ providerRegistered = false;
55
+ }
56
+ return false;
57
+ }
58
+ const models = await discoverModels();
59
+ if (models.length === 0)
60
+ return true; // Running but no models pulled
61
+ const baseUrl = getOllamaOpenAIBaseUrl();
62
+ pi.registerProvider("ollama", {
63
+ authMode: "none",
64
+ baseUrl,
65
+ api: "openai-completions",
66
+ isReady: () => true,
67
+ models: models.map((m) => ({
68
+ id: m.id,
69
+ name: m.name,
70
+ reasoning: m.reasoning,
71
+ input: m.input,
72
+ cost: m.cost,
73
+ contextWindow: m.contextWindow,
74
+ maxTokens: m.maxTokens,
75
+ compat: OLLAMA_COMPAT,
76
+ })),
77
+ });
78
+ providerRegistered = true;
79
+ return true;
80
+ }
81
+ export default function ollama(pi) {
82
+ // Register slash commands immediately (they check Ollama availability themselves)
83
+ registerOllamaCommands(pi);
84
+ pi.on("session_start", async (_event, ctx) => {
85
+ // Register tool (deferred to avoid blocking startup)
86
+ if (ctx.hasUI) {
87
+ void registerOllamaTools(pi).catch((error) => {
88
+ ctx.ui.notify(`Ollama tool failed to load: ${error instanceof Error ? error.message : String(error)}`, "warning");
89
+ });
90
+ }
91
+ else {
92
+ await registerOllamaTools(pi);
93
+ }
94
+ // Async probe — don't block startup
95
+ probeAndRegister(pi)
96
+ .then((found) => {
97
+ if (found && ctx.hasUI) {
98
+ ctx.ui.setStatus("ollama", "Ollama");
99
+ }
100
+ })
101
+ .catch(() => {
102
+ // Silently ignore probe failures
103
+ });
104
+ });
105
+ pi.on("session_shutdown", async () => {
106
+ if (providerRegistered) {
107
+ pi.unregisterProvider("ollama");
108
+ providerRegistered = false;
109
+ }
110
+ toolsPromise = null;
111
+ });
112
+ }
@@ -0,0 +1,115 @@
1
+ // GSD2 — Known model capability table for Ollama models
2
+ /**
3
+ * Known model family capabilities.
4
+ * Keys are matched as prefixes against the model name (before the colon/tag).
5
+ * More specific entries should appear first.
6
+ */
7
+ const KNOWN_MODELS = [
8
+ // ─── Reasoning models ───────────────────────────────────────────────
9
+ ["deepseek-r1", { contextWindow: 131072, reasoning: true }],
10
+ ["qwq", { contextWindow: 131072, reasoning: true }],
11
+ // ─── Vision models ──────────────────────────────────────────────────
12
+ ["llava", { contextWindow: 4096, input: ["text", "image"] }],
13
+ ["bakllava", { contextWindow: 4096, input: ["text", "image"] }],
14
+ ["moondream", { contextWindow: 8192, input: ["text", "image"] }],
15
+ ["llama3.2-vision", { contextWindow: 131072, input: ["text", "image"] }],
16
+ ["minicpm-v", { contextWindow: 4096, input: ["text", "image"] }],
17
+ // ─── Code models ────────────────────────────────────────────────────
18
+ ["codestral", { contextWindow: 262144, maxTokens: 32768 }],
19
+ ["qwen2.5-coder", { contextWindow: 131072, maxTokens: 32768 }],
20
+ ["deepseek-coder-v2", { contextWindow: 131072, maxTokens: 16384 }],
21
+ ["starcoder2", { contextWindow: 16384, maxTokens: 8192 }],
22
+ ["codegemma", { contextWindow: 8192, maxTokens: 8192 }],
23
+ ["codellama", { contextWindow: 16384, maxTokens: 8192 }],
24
+ ["devstral", { contextWindow: 131072, maxTokens: 32768 }],
25
+ // ─── Llama family ───────────────────────────────────────────────────
26
+ ["llama3.3", { contextWindow: 131072, maxTokens: 16384 }],
27
+ ["llama3.2", { contextWindow: 131072, maxTokens: 16384 }],
28
+ ["llama3.1", { contextWindow: 131072, maxTokens: 16384 }],
29
+ ["llama3", { contextWindow: 8192, maxTokens: 8192 }],
30
+ ["llama2", { contextWindow: 4096, maxTokens: 4096 }],
31
+ // ─── Qwen family ────────────────────────────────────────────────────
32
+ ["qwen3", { contextWindow: 131072, maxTokens: 32768 }],
33
+ ["qwen2.5", { contextWindow: 131072, maxTokens: 32768 }],
34
+ ["qwen2", { contextWindow: 131072, maxTokens: 32768 }],
35
+ // ─── Gemma family ───────────────────────────────────────────────────
36
+ ["gemma3", { contextWindow: 131072, maxTokens: 16384 }],
37
+ ["gemma2", { contextWindow: 8192, maxTokens: 8192 }],
38
+ // ─── Mistral family ─────────────────────────────────────────────────
39
+ ["mistral-large", { contextWindow: 131072, maxTokens: 16384 }],
40
+ ["mistral-small", { contextWindow: 131072, maxTokens: 16384 }],
41
+ ["mistral-nemo", { contextWindow: 131072, maxTokens: 16384 }],
42
+ ["mistral", { contextWindow: 32768, maxTokens: 8192 }],
43
+ ["mixtral", { contextWindow: 32768, maxTokens: 8192 }],
44
+ // ─── Phi family ─────────────────────────────────────────────────────
45
+ ["phi4", { contextWindow: 16384, maxTokens: 16384 }],
46
+ ["phi3.5", { contextWindow: 131072, maxTokens: 16384 }],
47
+ ["phi3", { contextWindow: 131072, maxTokens: 4096 }],
48
+ // ─── Command R ──────────────────────────────────────────────────────
49
+ ["command-r-plus", { contextWindow: 131072, maxTokens: 16384 }],
50
+ ["command-r", { contextWindow: 131072, maxTokens: 16384 }],
51
+ ];
52
+ /**
53
+ * Look up capabilities for a model by name.
54
+ * Matches the longest prefix from the known models table.
55
+ */
56
+ export function getModelCapabilities(modelName) {
57
+ // Strip tag (everything after the colon) for matching
58
+ const baseName = modelName.split(":")[0].toLowerCase();
59
+ for (const [pattern, caps] of KNOWN_MODELS) {
60
+ if (baseName === pattern || baseName.startsWith(pattern)) {
61
+ return caps;
62
+ }
63
+ }
64
+ return {};
65
+ }
66
+ /**
67
+ * Estimate context window from parameter size string (e.g. "7B", "70B", "1.5B").
68
+ * Used as fallback when model isn't in the known table.
69
+ */
70
+ export function estimateContextFromParams(parameterSize) {
71
+ const match = parameterSize.match(/([\d.]+)\s*([BbMm])/);
72
+ if (!match)
73
+ return 8192;
74
+ const size = parseFloat(match[1]);
75
+ const unit = match[2].toUpperCase();
76
+ // Convert to billions
77
+ const billions = unit === "M" ? size / 1000 : size;
78
+ // Rough heuristics: larger models tend to support larger contexts
79
+ if (billions >= 70)
80
+ return 131072;
81
+ if (billions >= 30)
82
+ return 65536;
83
+ if (billions >= 13)
84
+ return 32768;
85
+ if (billions >= 7)
86
+ return 16384;
87
+ return 8192;
88
+ }
89
+ /**
90
+ * Humanize a model name for display (e.g. "llama3.1:8b" → "Llama 3.1 8B").
91
+ */
92
+ export function humanizeModelName(modelName) {
93
+ const [base, tag] = modelName.split(":");
94
+ // Capitalize first letter, add spaces around version numbers
95
+ let name = base
96
+ .replace(/([a-z])(\d)/g, "$1 $2")
97
+ .replace(/(\d)([a-z])/g, "$1 $2")
98
+ .replace(/^./, (c) => c.toUpperCase());
99
+ // Clean up common patterns
100
+ name = name.replace(/\s*-\s*/g, " ");
101
+ if (tag && tag !== "latest") {
102
+ name += ` ${tag.toUpperCase()}`;
103
+ }
104
+ return name;
105
+ }
106
+ /**
107
+ * Format byte size for display (e.g. 4700000000 → "4.7 GB").
108
+ */
109
+ export function formatModelSize(bytes) {
110
+ if (bytes >= 1e9)
111
+ return `${(bytes / 1e9).toFixed(1)} GB`;
112
+ if (bytes >= 1e6)
113
+ return `${(bytes / 1e6).toFixed(1)} MB`;
114
+ return `${(bytes / 1e3).toFixed(0)} KB`;
115
+ }
@@ -0,0 +1,168 @@
1
+ // GSD2 — HTTP client for Ollama REST API
2
+ const DEFAULT_HOST = "http://localhost:11434";
3
+ const PROBE_TIMEOUT_MS = 1500;
4
+ const REQUEST_TIMEOUT_MS = 10000;
5
+ /**
6
+ * Get the Ollama host URL from OLLAMA_HOST or default.
7
+ */
8
+ export function getOllamaHost() {
9
+ const host = process.env.OLLAMA_HOST;
10
+ if (!host)
11
+ return DEFAULT_HOST;
12
+ // OLLAMA_HOST can be just a host:port without scheme
13
+ if (host.startsWith("http://") || host.startsWith("https://"))
14
+ return host;
15
+ return `http://${host}`;
16
+ }
17
+ async function fetchWithTimeout(url, options = {}, timeoutMs = REQUEST_TIMEOUT_MS) {
18
+ const controller = new AbortController();
19
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
20
+ try {
21
+ return await fetch(url, { ...options, signal: controller.signal });
22
+ }
23
+ finally {
24
+ clearTimeout(timeout);
25
+ }
26
+ }
27
+ /**
28
+ * Check if Ollama is running and reachable.
29
+ */
30
+ export async function isRunning() {
31
+ try {
32
+ const response = await fetchWithTimeout(`${getOllamaHost()}/`, {}, PROBE_TIMEOUT_MS);
33
+ return response.ok;
34
+ }
35
+ catch {
36
+ return false;
37
+ }
38
+ }
39
+ /**
40
+ * Get Ollama version.
41
+ */
42
+ export async function getVersion() {
43
+ try {
44
+ const response = await fetchWithTimeout(`${getOllamaHost()}/api/version`);
45
+ if (!response.ok)
46
+ return null;
47
+ const data = (await response.json());
48
+ return data.version;
49
+ }
50
+ catch {
51
+ return null;
52
+ }
53
+ }
54
+ /**
55
+ * List all locally available models.
56
+ */
57
+ export async function listModels() {
58
+ const response = await fetchWithTimeout(`${getOllamaHost()}/api/tags`);
59
+ if (!response.ok) {
60
+ throw new Error(`Ollama /api/tags returned ${response.status}: ${response.statusText}`);
61
+ }
62
+ return (await response.json());
63
+ }
64
+ /**
65
+ * Get detailed information about a specific model.
66
+ */
67
+ export async function showModel(name) {
68
+ const response = await fetchWithTimeout(`${getOllamaHost()}/api/show`, {
69
+ method: "POST",
70
+ headers: { "Content-Type": "application/json" },
71
+ body: JSON.stringify({ name }),
72
+ });
73
+ if (!response.ok) {
74
+ throw new Error(`Ollama /api/show returned ${response.status}: ${response.statusText}`);
75
+ }
76
+ return (await response.json());
77
+ }
78
+ /**
79
+ * List currently loaded/running models.
80
+ */
81
+ export async function getRunningModels() {
82
+ const response = await fetchWithTimeout(`${getOllamaHost()}/api/ps`);
83
+ if (!response.ok) {
84
+ throw new Error(`Ollama /api/ps returned ${response.status}: ${response.statusText}`);
85
+ }
86
+ return (await response.json());
87
+ }
88
+ /**
89
+ * Pull a model with streaming progress.
90
+ * Calls onProgress for each progress update.
91
+ * Returns when the pull is complete.
92
+ */
93
+ export async function pullModel(name, onProgress, signal) {
94
+ const response = await fetch(`${getOllamaHost()}/api/pull`, {
95
+ method: "POST",
96
+ headers: { "Content-Type": "application/json" },
97
+ body: JSON.stringify({ name, stream: true }),
98
+ signal,
99
+ });
100
+ if (!response.ok) {
101
+ const text = await response.text();
102
+ throw new Error(`Ollama /api/pull returned ${response.status}: ${text}`);
103
+ }
104
+ if (!response.body) {
105
+ throw new Error("Ollama /api/pull returned no body");
106
+ }
107
+ const reader = response.body.getReader();
108
+ const decoder = new TextDecoder();
109
+ let buffer = "";
110
+ while (true) {
111
+ const { done, value } = await reader.read();
112
+ if (done)
113
+ break;
114
+ buffer += decoder.decode(value, { stream: true });
115
+ const lines = buffer.split("\n");
116
+ buffer = lines.pop() ?? "";
117
+ for (const line of lines) {
118
+ const trimmed = line.trim();
119
+ if (!trimmed)
120
+ continue;
121
+ try {
122
+ const progress = JSON.parse(trimmed);
123
+ onProgress?.(progress);
124
+ }
125
+ catch {
126
+ // Skip malformed lines
127
+ }
128
+ }
129
+ }
130
+ // Process remaining buffer
131
+ if (buffer.trim()) {
132
+ try {
133
+ const progress = JSON.parse(buffer.trim());
134
+ onProgress?.(progress);
135
+ }
136
+ catch {
137
+ // Ignore
138
+ }
139
+ }
140
+ }
141
+ /**
142
+ * Delete a local model.
143
+ */
144
+ export async function deleteModel(name) {
145
+ const response = await fetchWithTimeout(`${getOllamaHost()}/api/delete`, {
146
+ method: "DELETE",
147
+ headers: { "Content-Type": "application/json" },
148
+ body: JSON.stringify({ name }),
149
+ });
150
+ if (!response.ok) {
151
+ const text = await response.text();
152
+ throw new Error(`Ollama /api/delete returned ${response.status}: ${text}`);
153
+ }
154
+ }
155
+ /**
156
+ * Copy a model to a new name.
157
+ */
158
+ export async function copyModel(source, destination) {
159
+ const response = await fetchWithTimeout(`${getOllamaHost()}/api/copy`, {
160
+ method: "POST",
161
+ headers: { "Content-Type": "application/json" },
162
+ body: JSON.stringify({ source, destination }),
163
+ });
164
+ if (!response.ok) {
165
+ const text = await response.text();
166
+ throw new Error(`Ollama /api/copy returned ${response.status}: ${text}`);
167
+ }
168
+ }