gsd-pi 2.78.0 → 2.78.1-dev.82bcf6b71

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 (577) hide show
  1. package/README.md +60 -23
  2. package/dist/bundled-resource-path.d.ts +7 -0
  3. package/dist/bundled-resource-path.js +34 -2
  4. package/dist/claude-cli-check.js +104 -33
  5. package/dist/cli-policy.d.ts +13 -0
  6. package/dist/cli-policy.js +17 -0
  7. package/dist/cli.js +95 -55
  8. package/dist/headless-query.d.ts +22 -0
  9. package/dist/headless-query.js +43 -8
  10. package/dist/headless.d.ts +10 -0
  11. package/dist/headless.js +16 -1
  12. package/dist/loader.js +9 -13
  13. package/dist/onboarding.d.ts +10 -0
  14. package/dist/onboarding.js +2 -2
  15. package/dist/provider-migrations.d.ts +2 -2
  16. package/dist/provider-migrations.js +5 -2
  17. package/dist/resource-loader.d.ts +5 -2
  18. package/dist/resource-loader.js +30 -13
  19. package/dist/resources/.managed-resources-content-hash +1 -0
  20. package/dist/resources/extensions/claude-code-cli/readiness.js +128 -32
  21. package/dist/resources/extensions/google-search/index.js +2 -6
  22. package/dist/resources/extensions/gsd/auto/loop.js +23 -0
  23. package/dist/resources/extensions/gsd/auto/phases.js +5 -13
  24. package/dist/resources/extensions/gsd/auto/run-unit.js +26 -12
  25. package/dist/resources/extensions/gsd/auto/session.js +5 -6
  26. package/dist/resources/extensions/gsd/auto-dashboard.js +3 -2
  27. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +55 -21
  28. package/dist/resources/extensions/gsd/auto-dispatch.js +18 -6
  29. package/dist/resources/extensions/gsd/auto-prompts.js +69 -2
  30. package/dist/resources/extensions/gsd/auto-recovery.js +43 -4
  31. package/dist/resources/extensions/gsd/auto-runtime-state.js +31 -0
  32. package/dist/resources/extensions/gsd/auto-start.js +1 -1
  33. package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -2
  34. package/dist/resources/extensions/gsd/auto-worktree.js +75 -13
  35. package/dist/resources/extensions/gsd/auto.js +39 -14
  36. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +14 -2
  37. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -5
  38. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
  39. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -4
  40. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +112 -31
  41. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +11 -6
  42. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +22 -0
  43. package/dist/resources/extensions/gsd/bootstrap/system-context.js +45 -8
  44. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +121 -3
  45. package/dist/resources/extensions/gsd/commands/catalog.js +76 -5
  46. package/dist/resources/extensions/gsd/commands/handlers/core.js +23 -1
  47. package/dist/resources/extensions/gsd/commands/handlers/ops.js +8 -0
  48. package/dist/resources/extensions/gsd/commands-config.js +3 -2
  49. package/dist/resources/extensions/gsd/commands-extensions.js +46 -3
  50. package/dist/resources/extensions/gsd/commands-handlers.js +3 -2
  51. package/dist/resources/extensions/gsd/commands-mcp-status.js +3 -1
  52. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +10 -1
  53. package/dist/resources/extensions/gsd/commands-worktree.js +309 -0
  54. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
  55. package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -0
  56. package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
  57. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +39 -1
  58. package/dist/resources/extensions/gsd/error-classifier.js +1 -1
  59. package/dist/resources/extensions/gsd/forensics.js +10 -8
  60. package/dist/resources/extensions/gsd/git-service.js +12 -5
  61. package/dist/resources/extensions/gsd/gsd-db.js +11 -2
  62. package/dist/resources/extensions/gsd/guided-flow.js +25 -24
  63. package/dist/resources/extensions/gsd/home-dir.js +16 -0
  64. package/dist/resources/extensions/gsd/key-manager.js +2 -1
  65. package/dist/resources/extensions/gsd/memory-store.js +66 -31
  66. package/dist/resources/extensions/gsd/migrate/command.js +3 -2
  67. package/dist/resources/extensions/gsd/milestone-id-reservation.js +36 -0
  68. package/dist/resources/extensions/gsd/model-router.js +114 -9
  69. package/dist/resources/extensions/gsd/native-git-bridge.js +7 -1
  70. package/dist/resources/extensions/gsd/preferences-models.js +91 -15
  71. package/dist/resources/extensions/gsd/preferences-types.js +2 -0
  72. package/dist/resources/extensions/gsd/preferences-validation.js +32 -0
  73. package/dist/resources/extensions/gsd/preferences.js +5 -3
  74. package/dist/resources/extensions/gsd/prompt-loader.js +23 -12
  75. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +10 -0
  76. package/dist/resources/extensions/gsd/prompts/complete-slice.md +10 -0
  77. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  78. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +2 -0
  79. package/dist/resources/extensions/gsd/prompts/plan-slice.md +10 -0
  80. package/dist/resources/extensions/gsd/prompts/refine-slice.md +10 -0
  81. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +2 -0
  82. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +9 -3
  83. package/dist/resources/extensions/gsd/state.js +42 -0
  84. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
  85. package/dist/resources/extensions/gsd/tools/memory-tools.js +18 -1
  86. package/dist/resources/extensions/gsd/unit-context-manifest.js +29 -4
  87. package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
  88. package/dist/resources/extensions/gsd/watch/header-renderer.js +3 -1
  89. package/dist/resources/extensions/gsd/worktree-command.js +26 -46
  90. package/dist/resources/extensions/gsd/worktree-manager.js +20 -1
  91. package/dist/resources/extensions/gsd/worktree-resolver.js +28 -13
  92. package/dist/resources/extensions/gsd/worktree-root.js +124 -0
  93. package/dist/resources/extensions/gsd/worktree-session-state.js +33 -0
  94. package/dist/resources/extensions/gsd/worktree.js +4 -115
  95. package/dist/resources/extensions/mcp-client/index.js +6 -9
  96. package/dist/resources/extensions/ollama/index.js +15 -2
  97. package/dist/resources/extensions/ollama/model-capabilities.js +31 -0
  98. package/dist/resources/extensions/ollama/ollama-client.js +40 -4
  99. package/dist/resources/extensions/slash-commands/create-extension.js +36 -22
  100. package/dist/resources/extensions/subagent/index.js +324 -178
  101. package/dist/resources/skills/create-gsd-extension/SKILL.md +9 -5
  102. package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
  103. package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
  104. package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
  105. package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
  106. package/dist/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
  107. package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
  108. package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
  109. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
  110. package/dist/resources/skills/lint/SKILL.md +4 -0
  111. package/dist/resources/skills/review/SKILL.md +4 -0
  112. package/dist/resources/skills/test/SKILL.md +3 -0
  113. package/dist/rtk-shared.d.ts +3 -0
  114. package/dist/rtk-shared.js +17 -0
  115. package/dist/rtk.d.ts +2 -5
  116. package/dist/rtk.js +3 -20
  117. package/dist/runtime-checks.d.ts +27 -0
  118. package/dist/runtime-checks.js +38 -0
  119. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  120. package/dist/web/standalone/.next/BUILD_ID +1 -1
  121. package/dist/web/standalone/.next/app-path-routes-manifest.json +19 -19
  122. package/dist/web/standalone/.next/build-manifest.json +4 -4
  123. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  124. package/dist/web/standalone/.next/react-loadable-manifest.json +44 -4
  125. package/dist/web/standalone/.next/required-server-files.json +3 -3
  126. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  127. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  129. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  137. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  139. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  140. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  141. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  142. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  143. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  144. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  145. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  146. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  153. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  165. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  185. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  195. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/session/events/route.js +4 -2
  201. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  214. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  215. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  216. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  217. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  218. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  219. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  220. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  221. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  222. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  223. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  224. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  225. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  226. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  227. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  228. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  229. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  230. package/dist/web/standalone/.next/server/app/index.html +1 -1
  231. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  232. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  233. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  234. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  235. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  236. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  237. package/dist/web/standalone/.next/server/app/page.js +2 -2
  238. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  239. package/dist/web/standalone/.next/server/app-paths-manifest.json +19 -19
  240. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  241. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  242. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  243. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  244. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  245. package/dist/web/standalone/.next/server/middleware.js +2 -2
  246. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  247. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  248. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  249. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  250. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  251. package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
  252. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +1 -0
  253. package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +1 -0
  254. package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +1 -0
  255. package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +1 -0
  256. package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +1 -0
  257. package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +1 -0
  258. package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +10 -0
  259. package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +2 -0
  260. package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +20 -0
  261. package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +1 -0
  262. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  263. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  264. package/dist/web/standalone/.next/static/chunks/app/page-9bf2e0c50fb2ca05.js +1 -0
  265. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  266. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  267. package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +1 -0
  268. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  269. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  270. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  271. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  272. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  273. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  274. package/dist/web/standalone/package.json +2 -1
  275. package/dist/web/standalone/server.js +1 -1
  276. package/dist/welcome-screen.js +27 -1
  277. package/dist/worktree-cli.d.ts +1 -0
  278. package/dist/worktree-cli.js +9 -3
  279. package/dist/worktree-status-banner.d.ts +1 -0
  280. package/dist/worktree-status-banner.js +132 -0
  281. package/package.json +1 -3
  282. package/packages/daemon/package.json +2 -2
  283. package/packages/mcp-server/dist/alias-telemetry.d.ts +8 -0
  284. package/packages/mcp-server/dist/alias-telemetry.d.ts.map +1 -0
  285. package/packages/mcp-server/dist/alias-telemetry.js +30 -0
  286. package/packages/mcp-server/dist/alias-telemetry.js.map +1 -0
  287. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  288. package/packages/mcp-server/dist/workflow-tools.js +74 -46
  289. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  290. package/packages/mcp-server/package.json +2 -2
  291. package/packages/mcp-server/src/alias-telemetry.test.ts +78 -0
  292. package/packages/mcp-server/src/alias-telemetry.ts +30 -0
  293. package/packages/mcp-server/src/workflow-tools.test.ts +78 -0
  294. package/packages/mcp-server/src/workflow-tools.ts +93 -58
  295. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  296. package/packages/native/package.json +1 -1
  297. package/packages/native/tsconfig.tsbuildinfo +1 -1
  298. package/packages/pi-agent-core/package.json +1 -1
  299. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  300. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts +2 -0
  301. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +1 -0
  302. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +231 -0
  303. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +1 -0
  304. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  305. package/packages/pi-ai/dist/providers/anthropic-shared.js +48 -19
  306. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  307. package/packages/pi-ai/dist/types.d.ts +13 -0
  308. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  309. package/packages/pi-ai/dist/types.js.map +1 -1
  310. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -1
  311. package/packages/pi-ai/dist/utils/repair-tool-json.js +24 -3
  312. package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -1
  313. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +26 -0
  314. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
  315. package/packages/pi-ai/package.json +1 -1
  316. package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +289 -0
  317. package/packages/pi-ai/src/providers/anthropic-shared.ts +52 -20
  318. package/packages/pi-ai/src/types.ts +13 -0
  319. package/packages/pi-ai/src/utils/repair-tool-json.ts +24 -3
  320. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +32 -0
  321. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  322. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  323. package/packages/pi-coding-agent/dist/core/agent-session.js +6 -0
  324. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  325. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  326. package/packages/pi-coding-agent/dist/core/messages.js +4 -0
  327. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  328. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +19 -2
  329. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  330. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +10 -0
  331. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  332. package/packages/pi-coding-agent/dist/core/model-registry.js +18 -0
  333. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  334. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +13 -0
  335. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  336. package/packages/pi-coding-agent/dist/core/system-prompt.js +20 -16
  337. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  338. package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +37 -0
  339. package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +1 -0
  340. package/packages/pi-coding-agent/dist/core/token-telemetry.js +49 -0
  341. package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +1 -0
  342. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +2 -0
  343. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +1 -0
  344. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +133 -0
  345. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -0
  346. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +1 -1
  347. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  348. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -1
  349. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  350. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +2 -0
  351. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +1 -0
  352. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +78 -0
  353. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +1 -0
  354. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +2 -0
  355. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +1 -0
  356. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +181 -0
  357. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +1 -0
  358. package/packages/pi-coding-agent/package.json +1 -1
  359. package/packages/pi-coding-agent/src/core/agent-session.ts +7 -0
  360. package/packages/pi-coding-agent/src/core/messages.ts +4 -0
  361. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +32 -2
  362. package/packages/pi-coding-agent/src/core/model-registry.ts +21 -0
  363. package/packages/pi-coding-agent/src/core/system-prompt.ts +33 -15
  364. package/packages/pi-coding-agent/src/core/token-telemetry.ts +77 -0
  365. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +212 -0
  366. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +17 -1
  367. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
  368. package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +102 -0
  369. package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +200 -0
  370. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  371. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +17 -3
  372. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  373. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +2 -0
  374. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +1 -0
  375. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +161 -0
  376. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +1 -0
  377. package/packages/pi-tui/package.json +1 -1
  378. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -3
  379. package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +219 -0
  380. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  381. package/packages/rpc-client/package.json +1 -1
  382. package/pkg/package.json +1 -1
  383. package/src/resources/extensions/claude-code-cli/readiness.ts +130 -30
  384. package/src/resources/extensions/google-search/index.ts +2 -9
  385. package/src/resources/extensions/gsd/auto/loop.ts +24 -2
  386. package/src/resources/extensions/gsd/auto/phases.ts +6 -14
  387. package/src/resources/extensions/gsd/auto/run-unit.ts +26 -12
  388. package/src/resources/extensions/gsd/auto/session.ts +5 -6
  389. package/src/resources/extensions/gsd/auto/types.ts +1 -0
  390. package/src/resources/extensions/gsd/auto-dashboard.ts +3 -2
  391. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +60 -24
  392. package/src/resources/extensions/gsd/auto-dispatch.ts +18 -6
  393. package/src/resources/extensions/gsd/auto-prompts.ts +66 -2
  394. package/src/resources/extensions/gsd/auto-recovery.ts +46 -8
  395. package/src/resources/extensions/gsd/auto-runtime-state.ts +51 -0
  396. package/src/resources/extensions/gsd/auto-start.ts +1 -1
  397. package/src/resources/extensions/gsd/auto-tool-tracking.ts +2 -4
  398. package/src/resources/extensions/gsd/auto-worktree.ts +97 -12
  399. package/src/resources/extensions/gsd/auto.ts +37 -10
  400. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +15 -13
  401. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +8 -7
  402. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
  403. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +10 -9
  404. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +121 -31
  405. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +12 -6
  406. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +20 -0
  407. package/src/resources/extensions/gsd/bootstrap/system-context.ts +50 -8
  408. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +141 -11
  409. package/src/resources/extensions/gsd/commands/catalog.ts +82 -5
  410. package/src/resources/extensions/gsd/commands/handlers/core.ts +23 -1
  411. package/src/resources/extensions/gsd/commands/handlers/ops.ts +10 -0
  412. package/src/resources/extensions/gsd/commands-config.ts +3 -2
  413. package/src/resources/extensions/gsd/commands-extensions.ts +43 -3
  414. package/src/resources/extensions/gsd/commands-handlers.ts +3 -2
  415. package/src/resources/extensions/gsd/commands-mcp-status.ts +3 -1
  416. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -1
  417. package/src/resources/extensions/gsd/commands-worktree.ts +383 -0
  418. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
  419. package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -0
  420. package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
  421. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +39 -1
  422. package/src/resources/extensions/gsd/doctor-types.ts +3 -1
  423. package/src/resources/extensions/gsd/error-classifier.ts +1 -1
  424. package/src/resources/extensions/gsd/forensics.ts +12 -7
  425. package/src/resources/extensions/gsd/git-service.ts +13 -5
  426. package/src/resources/extensions/gsd/gsd-db.ts +12 -2
  427. package/src/resources/extensions/gsd/guided-flow.ts +27 -26
  428. package/src/resources/extensions/gsd/home-dir.ts +19 -0
  429. package/src/resources/extensions/gsd/journal.ts +4 -1
  430. package/src/resources/extensions/gsd/key-manager.ts +2 -1
  431. package/src/resources/extensions/gsd/memory-store.ts +81 -28
  432. package/src/resources/extensions/gsd/migrate/command.ts +3 -2
  433. package/src/resources/extensions/gsd/milestone-id-reservation.ts +47 -0
  434. package/src/resources/extensions/gsd/model-router.ts +172 -9
  435. package/src/resources/extensions/gsd/native-git-bridge.ts +7 -1
  436. package/src/resources/extensions/gsd/preferences-models.ts +101 -15
  437. package/src/resources/extensions/gsd/preferences-types.ts +6 -0
  438. package/src/resources/extensions/gsd/preferences-validation.ts +35 -0
  439. package/src/resources/extensions/gsd/preferences.ts +16 -2
  440. package/src/resources/extensions/gsd/prompt-loader.ts +26 -12
  441. package/src/resources/extensions/gsd/prompts/complete-milestone.md +10 -0
  442. package/src/resources/extensions/gsd/prompts/complete-slice.md +10 -0
  443. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  444. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +2 -0
  445. package/src/resources/extensions/gsd/prompts/plan-slice.md +10 -0
  446. package/src/resources/extensions/gsd/prompts/refine-slice.md +10 -0
  447. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +2 -0
  448. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +9 -3
  449. package/src/resources/extensions/gsd/state.ts +42 -0
  450. package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
  451. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +179 -1
  452. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +58 -0
  453. package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +24 -5
  454. package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +21 -4
  455. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +1 -1
  456. package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +138 -211
  457. package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +50 -27
  458. package/src/resources/extensions/gsd/tests/commands-extensions-version-compare.test.ts +58 -0
  459. package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +48 -0
  460. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +142 -59
  461. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +7 -4
  462. package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +89 -32
  463. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +41 -23
  464. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +3 -43
  465. package/src/resources/extensions/gsd/tests/debug-logger.test.ts +5 -3
  466. package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +116 -0
  467. package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +22 -87
  468. package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +7 -118
  469. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +18 -60
  470. package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +100 -0
  471. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +14 -76
  472. package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +93 -0
  473. package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +22 -83
  474. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +1 -63
  475. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +47 -0
  476. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +26 -1
  477. package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +63 -0
  478. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +25 -65
  479. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +30 -0
  480. package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +81 -0
  481. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +14 -4
  482. package/src/resources/extensions/gsd/tests/health-widget.test.ts +22 -12
  483. package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +57 -0
  484. package/src/resources/extensions/gsd/tests/home-dir.test.ts +52 -0
  485. package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +145 -0
  486. package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +64 -1
  487. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +72 -1
  488. package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +0 -23
  489. package/src/resources/extensions/gsd/tests/memory-store.test.ts +128 -0
  490. package/src/resources/extensions/gsd/tests/memory-tools.test.ts +33 -1
  491. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +124 -0
  492. package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +152 -0
  493. package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +18 -1
  494. package/src/resources/extensions/gsd/tests/model-router.test.ts +169 -8
  495. package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +50 -0
  496. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +8 -0
  497. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +32 -43
  498. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +4 -10
  499. package/src/resources/extensions/gsd/tests/preferences.test.ts +127 -0
  500. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +16 -0
  501. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
  502. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
  503. package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +93 -0
  504. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +34 -0
  505. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +168 -19
  506. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +7 -1
  507. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +23 -1
  508. package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +8 -2
  509. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +12 -6
  510. package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +17 -1
  511. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +101 -0
  512. package/src/resources/extensions/gsd/tests/token-profile.test.ts +51 -4
  513. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +7 -16
  514. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +38 -3
  515. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -7
  516. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +15 -1
  517. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
  518. package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +235 -0
  519. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +85 -0
  520. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +34 -33
  521. package/src/resources/extensions/gsd/tests/worktree.test.ts +8 -0
  522. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +131 -1
  523. package/src/resources/extensions/gsd/tools/memory-tools.ts +17 -1
  524. package/src/resources/extensions/gsd/unit-context-manifest.ts +44 -12
  525. package/src/resources/extensions/gsd/visualizer-overlay.ts +1 -1
  526. package/src/resources/extensions/gsd/watch/header-renderer.ts +3 -1
  527. package/src/resources/extensions/gsd/workflow-logger.ts +1 -0
  528. package/src/resources/extensions/gsd/worktree-command.ts +31 -44
  529. package/src/resources/extensions/gsd/worktree-manager.ts +40 -1
  530. package/src/resources/extensions/gsd/worktree-resolver.ts +28 -14
  531. package/src/resources/extensions/gsd/worktree-root.ts +144 -0
  532. package/src/resources/extensions/gsd/worktree-session-state.ts +35 -0
  533. package/src/resources/extensions/gsd/worktree.ts +8 -119
  534. package/src/resources/extensions/mcp-client/index.ts +6 -10
  535. package/src/resources/extensions/mcp-client/tests/global-config.test.ts +91 -0
  536. package/src/resources/extensions/ollama/index.ts +16 -2
  537. package/src/resources/extensions/ollama/model-capabilities.ts +34 -0
  538. package/src/resources/extensions/ollama/ollama-client.ts +41 -4
  539. package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +96 -0
  540. package/src/resources/extensions/ollama/tests/ollama-client-timeout-env.test.ts +147 -0
  541. package/src/resources/extensions/slash-commands/create-extension.ts +38 -24
  542. package/src/resources/extensions/subagent/index.ts +165 -7
  543. package/src/resources/skills/create-gsd-extension/SKILL.md +9 -5
  544. package/src/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
  545. package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
  546. package/src/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
  547. package/src/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
  548. package/src/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
  549. package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
  550. package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
  551. package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +2 -2
  552. package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +3 -3
  553. package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +58 -0
  554. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
  555. package/src/resources/skills/lint/SKILL.md +4 -0
  556. package/src/resources/skills/review/SKILL.md +4 -0
  557. package/src/resources/skills/test/SKILL.md +3 -0
  558. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +0 -601
  559. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +0 -651
  560. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +0 -91
  561. package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +0 -53
  562. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +0 -112
  563. package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +0 -23
  564. package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +0 -5
  565. package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
  566. package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +0 -608
  567. package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +0 -11
  568. package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +0 -20
  569. package/dist/web/standalone/.next/static/chunks/app/page-151349214571e2b6.js +0 -1
  570. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  571. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  572. package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.js +0 -1
  573. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +0 -22
  574. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +0 -47
  575. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +0 -75
  576. /package/dist/web/standalone/.next/static/{C1zT2kEfoLhDdbWPWKrXd → hcvW7f3yv1JHzlWe7tIc6}/_buildManifest.js +0 -0
  577. /package/dist/web/standalone/.next/static/{C1zT2kEfoLhDdbWPWKrXd → hcvW7f3yv1JHzlWe7tIc6}/_ssgManifest.js +0 -0
@@ -39,6 +39,11 @@ import {
39
39
  nativeWorktreeRemove,
40
40
  } from "./native-git-bridge.js";
41
41
  import { emitCanonicalRootRedirect } from "./worktree-telemetry.js";
42
+ import {
43
+ isGsdWorktreePath,
44
+ normalizeWorktreePathForCompare,
45
+ resolveWorktreeProjectRoot,
46
+ } from "./worktree-root.js";
42
47
 
43
48
  // ─── Types ─────────────────────────────────────────────────────────────────
44
49
 
@@ -75,6 +80,20 @@ function normalizePathForComparison(path: string): string {
75
80
  return process.platform === "win32" ? normalized.toLowerCase() : normalized;
76
81
  }
77
82
 
83
+ function normalizeBasePathForWorktreeOps(basePath: string): string {
84
+ const resolved = resolveWorktreeProjectRoot(basePath);
85
+ if (
86
+ isGsdWorktreePath(basePath) &&
87
+ normalizeWorktreePathForCompare(resolved) === normalizeWorktreePathForCompare(basePath)
88
+ ) {
89
+ throw new GSDError(
90
+ GSD_GIT_ERROR,
91
+ `Cannot resolve project root from worktree path: ${basePath}. Run the command from the project root or set GSD_PROJECT_ROOT.`,
92
+ );
93
+ }
94
+ return resolved;
95
+ }
96
+
78
97
  // ─── resolveGitDir ─────────────────────────────────────────────────────────
79
98
 
80
99
  /**
@@ -106,7 +125,7 @@ export function resolveGitDir(basePath: string): string {
106
125
  }
107
126
 
108
127
  export function worktreesDir(basePath: string): string {
109
- return join(basePath, ".gsd", "worktrees");
128
+ return join(resolveWorktreeProjectRoot(basePath), ".gsd", "worktrees");
110
129
  }
111
130
 
112
131
  export function worktreePath(basePath: string, name: string): string {
@@ -195,6 +214,8 @@ export function resolveCanonicalMilestoneRoot(
195
214
  * @param opts.branch — override the default `worktree/<name>` branch name
196
215
  */
197
216
  export function createWorktree(basePath: string, name: string, opts: { branch?: string; startPoint?: string; reuseExistingBranch?: boolean } = {}): WorktreeInfo {
217
+ basePath = normalizeBasePathForWorktreeOps(basePath);
218
+
198
219
  // Validate name: alphanumeric, hyphens, underscores only
199
220
  if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
200
221
  throw new GSDError(GSD_PARSE_ERROR, `Invalid worktree name "${name}". Use only letters, numbers, hyphens, and underscores.`);
@@ -297,6 +318,8 @@ export function createWorktree(basePath: string, name: string, opts: { branch?:
297
318
  * Uses native worktree list and filters to those under .gsd/worktrees/.
298
319
  */
299
320
  export function listWorktrees(basePath: string): WorktreeInfo[] {
321
+ basePath = normalizeBasePathForWorktreeOps(basePath);
322
+
300
323
  const baseVariants = [resolve(basePath)];
301
324
  if (existsSync(basePath)) {
302
325
  baseVariants.push(realpathSync(basePath));
@@ -459,6 +482,8 @@ export function removeWorktree(
459
482
  name: string,
460
483
  opts: { deleteBranch?: boolean; force?: boolean; branch?: string } = {},
461
484
  ): void {
485
+ basePath = normalizeBasePathForWorktreeOps(basePath);
486
+
462
487
  let wtPath = worktreePath(basePath, name);
463
488
  const branch = opts.branch ?? worktreeBranchName(name);
464
489
  const { deleteBranch = true, force = true } = opts;
@@ -714,6 +739,8 @@ function parseDiffNameStatus(entries: { status: string; path: string }[]): Workt
714
739
  * Returns a summary of added, modified, and removed GSD artifacts.
715
740
  */
716
741
  export function diffWorktreeGSD(basePath: string, name: string): WorktreeDiffSummary {
742
+ basePath = normalizeBasePathForWorktreeOps(basePath);
743
+
717
744
  const branch = worktreeBranchName(name);
718
745
  const mainBranch = nativeDetectMainBranch(basePath);
719
746
 
@@ -729,6 +756,8 @@ export function diffWorktreeGSD(basePath: string, name: string): WorktreeDiffSum
729
756
  * content, this correctly returns an empty diff.
730
757
  */
731
758
  export function diffWorktreeAll(basePath: string, name: string): WorktreeDiffSummary {
759
+ basePath = normalizeBasePathForWorktreeOps(basePath);
760
+
732
761
  const branch = worktreeBranchName(name);
733
762
  const mainBranch = nativeDetectMainBranch(basePath);
734
763
 
@@ -742,6 +771,8 @@ export function diffWorktreeAll(basePath: string, name: string): WorktreeDiffSum
742
771
  * Uses direct diff (not merge-base) so the preview matches the actual merge outcome.
743
772
  */
744
773
  export function diffWorktreeNumstat(basePath: string, name: string): FileLineStat[] {
774
+ basePath = normalizeBasePathForWorktreeOps(basePath);
775
+
745
776
  const branch = worktreeBranchName(name);
746
777
  const mainBranch = nativeDetectMainBranch(basePath);
747
778
 
@@ -760,6 +791,8 @@ export function diffWorktreeNumstat(basePath: string, name: string): FileLineSta
760
791
  * Returns the raw unified diff for LLM consumption.
761
792
  */
762
793
  export function getWorktreeGSDDiff(basePath: string, name: string): string {
794
+ basePath = normalizeBasePathForWorktreeOps(basePath);
795
+
763
796
  const branch = worktreeBranchName(name);
764
797
  const mainBranch = nativeDetectMainBranch(basePath);
765
798
 
@@ -771,6 +804,8 @@ export function getWorktreeGSDDiff(basePath: string, name: string): string {
771
804
  * Returns the raw unified diff for LLM consumption.
772
805
  */
773
806
  export function getWorktreeCodeDiff(basePath: string, name: string): string {
807
+ basePath = normalizeBasePathForWorktreeOps(basePath);
808
+
774
809
  const branch = worktreeBranchName(name);
775
810
  const mainBranch = nativeDetectMainBranch(basePath);
776
811
 
@@ -781,6 +816,8 @@ export function getWorktreeCodeDiff(basePath: string, name: string): string {
781
816
  * Get commit log for the worktree branch since it diverged from main.
782
817
  */
783
818
  export function getWorktreeLog(basePath: string, name: string): string {
819
+ basePath = normalizeBasePathForWorktreeOps(basePath);
820
+
784
821
  const branch = worktreeBranchName(name);
785
822
  const mainBranch = nativeDetectMainBranch(basePath);
786
823
 
@@ -795,6 +832,8 @@ export function getWorktreeLog(basePath: string, name: string): string {
795
832
  * Returns the merge commit message.
796
833
  */
797
834
  export function mergeWorktreeToMain(basePath: string, name: string, commitMessage: string): string {
835
+ basePath = normalizeBasePathForWorktreeOps(basePath);
836
+
798
837
  const branch = worktreeBranchName(name);
799
838
  const mainBranch = nativeDetectMainBranch(basePath);
800
839
  const current = nativeGetCurrentBranch(basePath);
@@ -23,6 +23,7 @@ import { emitJournalEvent } from "./journal.js";
23
23
  import { emitWorktreeCreated, emitWorktreeMerged } from "./worktree-telemetry.js";
24
24
  import { getCollapseCadence, getMilestoneResquash, resquashMilestoneOnMain } from "./slice-cadence.js";
25
25
  import { loadEffectiveGSDPreferences } from "./preferences.js";
26
+ import { resolveWorktreeProjectRoot } from "./worktree-root.js";
26
27
 
27
28
  // ─── Dependency Interface ──────────────────────────────────────────────────
28
29
 
@@ -84,31 +85,20 @@ export interface NotifyCtx {
84
85
 
85
86
  // ─── Path Helpers ──────────────────────────────────────────────────────────
86
87
 
87
- /**
88
- * Worktree marker segment — present in any path produced by worktreePath().
89
- * Used to strip the worktree suffix and recover the project root (#3729).
90
- */
91
- const WORKTREE_MARKER = "/.gsd/worktrees/";
92
-
93
88
  /**
94
89
  * Resolve the project root from session path state.
95
90
  *
96
91
  * Prefers `originalBasePath` (always the project root when set), but falls
97
92
  * back to `basePath` when `originalBasePath` is falsy (e.g. fresh AutoSession
98
93
  * with default empty string). If `basePath` itself is inside a worktree
99
- * directory (contains `/.gsd/worktrees/`), strip that suffix to recover the
100
- * actual project root preventing double-nested worktree paths (#3729).
94
+ * directory (including symlink-resolved ~/.gsd/projects/<hash>/worktrees
95
+ * paths), recover the actual project root to prevent double nesting (#3729).
101
96
  */
102
97
  export function resolveProjectRoot(
103
98
  originalBasePath: string,
104
99
  basePath: string,
105
100
  ): string {
106
- let resolved = originalBasePath || basePath;
107
- const markerIdx = resolved.indexOf(WORKTREE_MARKER);
108
- if (markerIdx !== -1) {
109
- resolved = resolved.slice(0, markerIdx);
110
- }
111
- return resolved;
101
+ return resolveWorktreeProjectRoot(basePath, originalBasePath);
112
102
  }
113
103
 
114
104
  // ─── WorktreeResolver ──────────────────────────────────────────────────────
@@ -414,6 +404,30 @@ export class WorktreeResolver {
414
404
  mergeAndExit(milestoneId: string, ctx: NotifyCtx): void {
415
405
  this.validateMilestoneId(milestoneId);
416
406
 
407
+ // Anchor cwd at the project root before any merge work. Some merge code
408
+ // paths (mergeMilestoneToMain, slice-cadence) chdir explicitly; others
409
+ // (branch-mode, isolation-degraded skip, missing-original-base skip)
410
+ // do not. If the worktree dir is later torn down while cwd still points
411
+ // into it, every subsequent process.cwd() throws ENOENT — and after
412
+ // de73fb43d that surfaces as a session-failed cancel and (in headless
413
+ // mode) terminates the whole gsd process. Best-effort: silent on
414
+ // failure so existing test fixtures that use synthetic paths still pass.
415
+ if (this.s.originalBasePath) {
416
+ try {
417
+ // process.cwd() can throw ENOENT when cwd was removed, so attempt
418
+ // recovery directly.
419
+ process.chdir(this.s.originalBasePath);
420
+ } catch (err) {
421
+ debugLog("WorktreeResolver", {
422
+ action: "mergeAndExit",
423
+ phase: "pre-merge-chdir-failed",
424
+ milestoneId,
425
+ originalBasePath: this.s.originalBasePath,
426
+ error: err instanceof Error ? err.message : String(err),
427
+ });
428
+ }
429
+ }
430
+
417
431
  // #4764 — telemetry: record start timestamp so we can emit merge duration.
418
432
  const mergeStartedAt = new Date().toISOString();
419
433
  const mergeStartMs = Date.now();
@@ -0,0 +1,144 @@
1
+ import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join, resolve } from "node:path";
4
+
5
+ export interface WorktreeSegment {
6
+ gsdIdx: number;
7
+ afterWorktrees: number;
8
+ }
9
+
10
+ export function normalizeWorktreePathForCompare(path: string): string {
11
+ let normalized: string;
12
+ try {
13
+ normalized = realpathSync(path);
14
+ } catch {
15
+ normalized = resolve(path);
16
+ }
17
+ const slashed = normalized.replaceAll("\\", "/");
18
+ const trimmed = slashed.replace(/\/+$/, "");
19
+ return process.platform === "win32" ? (trimmed || "/").toLowerCase() : (trimmed || "/");
20
+ }
21
+
22
+ /**
23
+ * Find the GSD worktree segment in both direct project layout and the
24
+ * symlink-resolved external-state layout used by ~/.gsd/projects/<hash>.
25
+ */
26
+ export function findWorktreeSegment(normalizedPath: string): WorktreeSegment | null {
27
+ const directMarker = "/.gsd/worktrees/";
28
+ const directIdx = normalizedPath.indexOf(directMarker);
29
+ if (directIdx !== -1) {
30
+ return { gsdIdx: directIdx, afterWorktrees: directIdx + directMarker.length };
31
+ }
32
+
33
+ const externalRe = /\/\.gsd\/projects\/[^/]+\/worktrees\//;
34
+ const externalMatch = normalizedPath.match(externalRe);
35
+ if (externalMatch && externalMatch.index !== undefined) {
36
+ return {
37
+ gsdIdx: externalMatch.index,
38
+ afterWorktrees: externalMatch.index + externalMatch[0].length,
39
+ };
40
+ }
41
+
42
+ return null;
43
+ }
44
+
45
+ export function isGsdWorktreePath(path: string): boolean {
46
+ return findWorktreeSegment(path.replaceAll("\\", "/")) !== null;
47
+ }
48
+
49
+ /**
50
+ * Resolve the canonical project root for worktree operations.
51
+ *
52
+ * `originalBasePath` wins when available because session state already knows the
53
+ * root. `GSD_PROJECT_ROOT` is the next strongest signal for worker processes.
54
+ * Otherwise, derive the root from direct `.gsd/worktrees` paths, or recover it
55
+ * from the worktree `.git` file for symlink-resolved ~/.gsd/project paths.
56
+ */
57
+ export function resolveWorktreeProjectRoot(
58
+ basePath: string,
59
+ originalBasePath?: string | null,
60
+ ): string {
61
+ const preferred =
62
+ originalBasePath?.trim() ||
63
+ process.env.GSD_PROJECT_ROOT?.trim() ||
64
+ basePath;
65
+
66
+ return resolveProjectRootFromPath(preferred);
67
+ }
68
+
69
+ function resolveProjectRootFromPath(path: string): string {
70
+ const normalizedPath = path.replaceAll("\\", "/");
71
+ const segment = findWorktreeSegment(normalizedPath);
72
+ if (!segment) return resolveGitWorkingTreeRoot(path) ?? path;
73
+
74
+ const sepChar = path.includes("\\") ? "\\" : "/";
75
+ const gsdMarker = `${sepChar}.gsd${sepChar}`;
76
+ const markerIdx = path.indexOf(gsdMarker);
77
+ const candidate = markerIdx !== -1
78
+ ? path.slice(0, markerIdx)
79
+ : path.slice(0, segment.gsdIdx);
80
+
81
+ const gsdHome = normalizeWorktreePathForCompare(process.env.GSD_HOME || join(homedir(), ".gsd"));
82
+ const candidateGsdPath = normalizeWorktreePathForCompare(join(candidate, ".gsd"));
83
+
84
+ if (candidateGsdPath === gsdHome || candidateGsdPath.startsWith(`${gsdHome}/`)) {
85
+ const realRoot = resolveProjectRootFromGitFile(path);
86
+ return realRoot ?? path;
87
+ }
88
+
89
+ return candidate;
90
+ }
91
+
92
+ function resolveGitWorkingTreeRoot(path: string): string | null {
93
+ try {
94
+ let dir = existsSync(path) && !statSync(path).isDirectory()
95
+ ? resolve(path, "..")
96
+ : path;
97
+
98
+ for (let i = 0; i < 30; i++) {
99
+ const gitPath = join(dir, ".git");
100
+ if (existsSync(gitPath)) return dir;
101
+
102
+ const parent = resolve(dir, "..");
103
+ if (parent === dir) break;
104
+ dir = parent;
105
+ }
106
+ } catch {
107
+ // Non-fatal: callers either keep the original path or fail closed.
108
+ }
109
+ return null;
110
+ }
111
+
112
+ function resolveProjectRootFromGitFile(worktreePath: string): string | null {
113
+ try {
114
+ let dir = worktreePath;
115
+ for (let i = 0; i < 30; i++) {
116
+ const gitPath = join(dir, ".git");
117
+ if (existsSync(gitPath)) {
118
+ const content = readFileSync(gitPath, "utf8").trim();
119
+ if (content.startsWith("gitdir: ")) {
120
+ const gitDir = resolve(dir, content.slice(8));
121
+ const dotGitDir = resolve(gitDir, "..", "..");
122
+ if (dotGitDir.endsWith(".git") || dotGitDir.endsWith(".git/") || dotGitDir.endsWith(".git\\")) {
123
+ return resolve(dotGitDir, "..");
124
+ }
125
+
126
+ const commonDirPath = join(gitDir, "commondir");
127
+ if (existsSync(commonDirPath)) {
128
+ const commonDir = readFileSync(commonDirPath, "utf8").trim();
129
+ const resolvedCommonDir = resolve(gitDir, commonDir);
130
+ return resolve(resolvedCommonDir, "..");
131
+ }
132
+ }
133
+ break;
134
+ }
135
+
136
+ const parent = resolve(dir, "..");
137
+ if (parent === dir) break;
138
+ dir = parent;
139
+ }
140
+ } catch {
141
+ // Non-fatal: callers either keep the original path or fail closed.
142
+ }
143
+ return null;
144
+ }
@@ -0,0 +1,35 @@
1
+ // GSD worktree session state
2
+ let originalCwd: string | null = null;
3
+
4
+ export function getWorktreeOriginalCwd(): string | null {
5
+ return originalCwd;
6
+ }
7
+
8
+ export function setWorktreeOriginalCwd(cwd: string): void {
9
+ originalCwd = cwd;
10
+ }
11
+
12
+ export function clearWorktreeOriginalCwd(): void {
13
+ originalCwd = null;
14
+ }
15
+
16
+ export function ensureWorktreeOriginalCwdFromPath(cwd: string = process.cwd()): string | null {
17
+ if (originalCwd) return originalCwd;
18
+ const marker = `${/\\/.test(cwd) ? "\\" : "/"}.gsd${/\\/.test(cwd) ? "\\" : "/"}worktrees${/\\/.test(cwd) ? "\\" : "/"}`;
19
+ const markerIdx = cwd.indexOf(marker);
20
+ if (markerIdx !== -1) {
21
+ originalCwd = cwd.slice(0, markerIdx);
22
+ }
23
+ return originalCwd;
24
+ }
25
+
26
+ export function getActiveWorktreeName(): string | null {
27
+ if (!originalCwd) return null;
28
+ const cwd = process.cwd();
29
+ const wtDir = `${originalCwd.replace(/[\\/]+$/, "")}/.gsd/worktrees`.replaceAll("\\", "/");
30
+ const normalizedCwd = cwd.replaceAll("\\", "/");
31
+ if (!normalizedCwd.startsWith(`${wtDir}/`)) return null;
32
+ const rel = normalizedCwd.slice(wtDir.length + 1);
33
+ const name = rel.split("/")[0];
34
+ return name || null;
35
+ }
@@ -12,12 +12,16 @@
12
12
  * SLICE_BRANCH_RE) remain for backwards compatibility with legacy branches.
13
13
  */
14
14
 
15
- import { existsSync, readFileSync, realpathSync, utimesSync } from "node:fs";
16
- import { join, resolve, sep } from "node:path";
17
- import { homedir } from "node:os";
15
+ import { existsSync, readFileSync, utimesSync } from "node:fs";
16
+ import { join, resolve } from "node:path";
18
17
 
19
18
  import { GitServiceImpl, writeIntegrationBranch, type TaskCommitContext } from "./git-service.js";
20
19
  import { loadEffectiveGSDPreferences } from "./preferences.js";
20
+ import {
21
+ findWorktreeSegment,
22
+ resolveWorktreeProjectRoot,
23
+ } from "./worktree-root.js";
24
+ export { resolveWorktreeProjectRoot } from "./worktree-root.js";
21
25
 
22
26
  export { MergeConflictError } from "./git-service.js";
23
27
  export type { TaskCommitContext } from "./git-service.js";
@@ -78,29 +82,6 @@ export function captureIntegrationBranch(basePath: string, milestoneId: string):
78
82
 
79
83
  // ─── Pure Utility Functions (unchanged) ────────────────────────────────────
80
84
 
81
- /**
82
- * Find the worktrees segment in a path, supporting both direct
83
- * (`/.gsd/worktrees/`) and symlink-resolved (`/.gsd/projects/<hash>/worktrees/`)
84
- * layouts. When `.gsd` is a symlink to `~/.gsd/projects/<hash>`, resolved
85
- * paths contain the intermediate `projects/<hash>/` segment that the old
86
- * single-marker check missed.
87
- */
88
- function findWorktreeSegment(normalizedPath: string): { gsdIdx: number; afterWorktrees: number } | null {
89
- // Direct layout: /.gsd/worktrees/<name>
90
- const directMarker = "/.gsd/worktrees/";
91
- const idx = normalizedPath.indexOf(directMarker);
92
- if (idx !== -1) {
93
- return { gsdIdx: idx, afterWorktrees: idx + directMarker.length };
94
- }
95
- // Symlink-resolved layout: /.gsd/projects/<hash>/worktrees/<name>
96
- const symlinkRe = /\/\.gsd\/projects\/[a-f0-9]+\/worktrees\//;
97
- const match = normalizedPath.match(symlinkRe);
98
- if (match && match.index !== undefined) {
99
- return { gsdIdx: match.index, afterWorktrees: match.index + match[0].length };
100
- }
101
- return null;
102
- }
103
-
104
85
  /**
105
86
  * Detect the active worktree name from the current working directory.
106
87
  * Returns null if not inside a GSD worktree (.gsd/worktrees/<name>/).
@@ -133,99 +114,7 @@ export function detectWorktreeName(basePath: string): string | null {
133
114
  * operate against the real project root, not a worktree subdirectory.
134
115
  */
135
116
  export function resolveProjectRoot(basePath: string): string {
136
- // Layer 1: If the coordinator passed the real project root, use it.
137
- if (process.env.GSD_PROJECT_ROOT) {
138
- return process.env.GSD_PROJECT_ROOT;
139
- }
140
-
141
- const normalizedPath = basePath.replaceAll("\\", "/");
142
- const seg = findWorktreeSegment(normalizedPath);
143
- if (!seg) return basePath;
144
-
145
- // Candidate root via the string-slice heuristic
146
- const sepChar = basePath.includes("\\") ? "\\" : "/";
147
- const gsdMarker = `${sepChar}.gsd${sepChar}`;
148
- const gsdIdx = basePath.indexOf(gsdMarker);
149
- const candidate = gsdIdx !== -1
150
- ? basePath.slice(0, gsdIdx)
151
- : basePath.slice(0, seg.gsdIdx);
152
-
153
- // Layer 2: Guard against resolving to the user's home directory.
154
- // When .gsd is a symlink into ~/.gsd/projects/<hash>, the resolved path
155
- // contains /.gsd/ at the user-level boundary. Slicing there yields ~ — wrong.
156
- const gsdHome = normalizePathForCompare(process.env.GSD_HOME || join(homedir(), ".gsd"));
157
- const candidateGsdPath = normalizePathForCompare(join(candidate, ".gsd"));
158
-
159
- if (candidateGsdPath === gsdHome || candidateGsdPath.startsWith(gsdHome + "/")) {
160
- // The candidate is the home directory (or within it in a way that .gsd
161
- // maps to the user-level GSD dir). Try to recover the real project root
162
- // from the worktree's .git file.
163
- const realRoot = resolveProjectRootFromGitFile(basePath);
164
- if (realRoot) return realRoot;
165
- // If git file resolution failed, return basePath unchanged rather than ~
166
- return basePath;
167
- }
168
-
169
- return candidate;
170
- }
171
-
172
- /**
173
- * Recover the real project root from a worktree's .git file.
174
- *
175
- * Each git worktree has a `.git` file (not directory) containing:
176
- * gitdir: /real/project/.git/worktrees/<name>
177
- *
178
- * Walking up from that gitdir gives us `/real/project/.git`, and its
179
- * parent is the real project root.
180
- */
181
- function resolveProjectRootFromGitFile(worktreePath: string): string | null {
182
- try {
183
- // Walk up from the worktree path to find the .git file
184
- let dir = worktreePath;
185
- for (let i = 0; i < 30; i++) {
186
- const gitPath = join(dir, ".git");
187
- if (existsSync(gitPath)) {
188
- const content = readFileSync(gitPath, "utf8").trim();
189
- if (content.startsWith("gitdir: ")) {
190
- // gitdir points to: <real-project>/.git/worktrees/<name>
191
- const gitDir = resolve(dir, content.slice(8));
192
- // Walk up: .git/worktrees/<name> → .git/worktrees → .git → project root
193
- const dotGitDir = resolve(gitDir, "..", "..");
194
- // Verify this looks like a .git directory
195
- if (dotGitDir.endsWith(".git") || dotGitDir.endsWith(".git/") || dotGitDir.endsWith(".git\\")) {
196
- return resolve(dotGitDir, "..");
197
- }
198
- // Alternative: the commondir file inside the worktree gitdir
199
- // points to the main .git directory
200
- const commonDirPath = join(gitDir, "commondir");
201
- if (existsSync(commonDirPath)) {
202
- const commonDir = readFileSync(commonDirPath, "utf8").trim();
203
- const resolvedCommonDir = resolve(gitDir, commonDir);
204
- return resolve(resolvedCommonDir, "..");
205
- }
206
- }
207
- break;
208
- }
209
- const parent = resolve(dir, "..");
210
- if (parent === dir) break;
211
- dir = parent;
212
- }
213
- } catch {
214
- // Non-fatal — caller will use fallback
215
- }
216
- return null;
217
- }
218
-
219
- function normalizePathForCompare(path: string): string {
220
- let normalized: string;
221
- try {
222
- normalized = realpathSync(path);
223
- } catch {
224
- normalized = resolve(path);
225
- }
226
- const slashed = normalized.replaceAll("\\", "/");
227
- const trimmed = slashed.replace(/\/+$/, "");
228
- return trimmed || "/";
117
+ return resolveWorktreeProjectRoot(basePath);
229
118
  }
230
119
 
231
120
  /**
@@ -2,7 +2,8 @@
2
2
  * MCP Client Extension — Native MCP server integration for pi
3
3
  *
4
4
  * Provides on-demand access to MCP servers configured in project files
5
- * (.mcp.json, .gsd/mcp.json) using the @modelcontextprotocol/sdk Client
5
+ * (.mcp.json, .gsd/mcp.json) and the global ~/.gsd/mcp.json (or
6
+ * $GSD_HOME/mcp.json) using the @modelcontextprotocol/sdk Client
6
7
  * directly — no external CLI dependency required.
7
8
  *
8
9
  * Three tools:
@@ -24,6 +25,7 @@ import { Client } from "@modelcontextprotocol/sdk/client";
24
25
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
25
26
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
26
27
  import { readFileSync, existsSync } from "node:fs";
28
+ import { homedir } from "node:os";
27
29
  import { join } from "node:path";
28
30
  import { buildHttpTransportOpts } from "./auth.js";
29
31
  import type { McpHttpAuthConfig } from "./auth.js";
@@ -102,6 +104,7 @@ function readConfigs(): McpServerConfig[] {
102
104
  const configPaths = [
103
105
  join(process.cwd(), ".mcp.json"),
104
106
  join(process.cwd(), ".gsd", "mcp.json"),
107
+ join(process.env.GSD_HOME || join(homedir(), ".gsd"), "mcp.json"),
105
108
  ];
106
109
 
107
110
  for (const configPath of configPaths) {
@@ -321,7 +324,7 @@ async function closeAll(): Promise<void> {
321
324
  // ─── Formatters ───────────────────────────────────────────────────────────────
322
325
 
323
326
  function formatServerList(servers: McpServerConfig[]): string {
324
- if (servers.length === 0) return "No MCP servers configured. Add servers to .mcp.json or .gsd/mcp.json.";
327
+ if (servers.length === 0) return "No MCP servers configured. Add servers to .mcp.json, .gsd/mcp.json, or $GSD_HOME/mcp.json (default: ~/.gsd/mcp.json).";
325
328
 
326
329
  const lines: string[] = [`${servers.length} MCP servers configured:\n`];
327
330
 
@@ -384,7 +387,7 @@ export default function (pi: ExtensionAPI) {
384
387
  name: "mcp_servers",
385
388
  label: "MCP Servers",
386
389
  description:
387
- "List all available MCP servers configured in project files (.mcp.json, .gsd/mcp.json). " +
390
+ "List all available MCP servers configured in project files (.mcp.json, .gsd/mcp.json) or globally ($GSD_HOME/mcp.json, default: ~/.gsd/mcp.json). " +
388
391
  "Shows server names, transport type, and connection status. Use mcp_discover to get full tool schemas for a server.",
389
392
  promptSnippet:
390
393
  "List available MCP servers from project configuration",
@@ -624,13 +627,6 @@ export default function (pi: ExtensionAPI) {
624
627
 
625
628
  // ── Lifecycle ─────────────────────────────────────────────────────────────
626
629
 
627
- pi.on("session_start", async (_event, ctx) => {
628
- const servers = readConfigs();
629
- if (servers.length > 0) {
630
- ctx.ui.notify(`MCP client ready — ${servers.length} server(s) configured`, "info");
631
- }
632
- });
633
-
634
630
  pi.on("session_shutdown", async () => {
635
631
  await closeAll();
636
632
  });
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Regression test for #4757 — readConfigs() must also read the global
3
+ * ~/.gsd/mcp.json (resolved as $GSD_HOME/mcp.json when GSD_HOME is set).
4
+ *
5
+ * Behaviour test against the exported getServerConfig — no source grep.
6
+ * The fixture is anchored via $GSD_HOME so the test never touches the
7
+ * developer's real ~/.gsd directory.
8
+ */
9
+
10
+ import test, { before, after } from "node:test";
11
+ import assert from "node:assert/strict";
12
+ import { writeFileSync, mkdtempSync, realpathSync, rmSync } from "node:fs";
13
+ import { tmpdir } from "node:os";
14
+ import { join } from "node:path";
15
+
16
+ import { getServerConfig } from "../index.js";
17
+
18
+ let cwdDir: string;
19
+ let gsdHomeDir: string;
20
+ let originalCwd: string;
21
+ let originalGsdHome: string | undefined;
22
+
23
+ before(() => {
24
+ originalCwd = process.cwd();
25
+ originalGsdHome = process.env.GSD_HOME;
26
+
27
+ // realpathSync resolves any symlink in tmpdir() — on macOS /var → /private/var
28
+ // so process.cwd() after chdir matches what mkdtempSync returned.
29
+ cwdDir = realpathSync(mkdtempSync(join(tmpdir(), "mcp-cwd-")));
30
+ gsdHomeDir = realpathSync(mkdtempSync(join(tmpdir(), "mcp-gsdhome-")));
31
+
32
+ // Project-local fixture (also defines `shared-server` for the precedence test)
33
+ writeFileSync(
34
+ join(cwdDir, ".mcp.json"),
35
+ JSON.stringify({
36
+ mcpServers: {
37
+ "project-server": { command: "echo", args: ["proj"] },
38
+ "shared-server": { command: "echo", args: ["from-project"] },
39
+ },
40
+ }),
41
+ "utf-8",
42
+ );
43
+
44
+ // Global fixture rooted at $GSD_HOME (also defines `shared-server` to test
45
+ // that project-local takes precedence on name collision)
46
+ writeFileSync(
47
+ join(gsdHomeDir, "mcp.json"),
48
+ JSON.stringify({
49
+ mcpServers: {
50
+ "global-server": { command: "echo", args: ["glob"] },
51
+ "shared-server": { command: "echo", args: ["from-global"] },
52
+ },
53
+ }),
54
+ "utf-8",
55
+ );
56
+
57
+ process.chdir(cwdDir);
58
+ process.env.GSD_HOME = gsdHomeDir;
59
+ });
60
+
61
+ after(() => {
62
+ process.chdir(originalCwd);
63
+ if (originalGsdHome === undefined) delete process.env.GSD_HOME;
64
+ else process.env.GSD_HOME = originalGsdHome;
65
+ try { rmSync(cwdDir, { recursive: true, force: true }); } catch { /* best-effort */ }
66
+ try { rmSync(gsdHomeDir, { recursive: true, force: true }); } catch { /* best-effort */ }
67
+ });
68
+
69
+ test("#4757: getServerConfig resolves servers declared in $GSD_HOME/mcp.json", () => {
70
+ const cfg = getServerConfig("global-server");
71
+ assert.ok(cfg, "server defined in $GSD_HOME/mcp.json must resolve");
72
+ assert.equal(cfg?.name, "global-server");
73
+ assert.equal(cfg?.sourcePath, join(gsdHomeDir, "mcp.json"));
74
+ });
75
+
76
+ test("#4757: project-local servers still resolve when global config exists", () => {
77
+ const cfg = getServerConfig("project-server");
78
+ assert.ok(cfg, "project-local server must continue to resolve");
79
+ assert.equal(cfg?.sourcePath, join(cwdDir, ".mcp.json"));
80
+ });
81
+
82
+ test("#4757: project-local config wins on server-name collision", () => {
83
+ const cfg = getServerConfig("shared-server");
84
+ assert.ok(cfg, "shared server must resolve");
85
+ assert.equal(
86
+ cfg?.sourcePath,
87
+ join(cwdDir, ".mcp.json"),
88
+ "project-local config must take precedence over $GSD_HOME on name collision",
89
+ );
90
+ assert.deepEqual(cfg?.args, ["from-project"]);
91
+ });