gsd-pi 2.78.0 → 2.78.1-dev.8a893322c

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 (559) 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 +3 -1
  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-dispatch.js +18 -6
  28. package/dist/resources/extensions/gsd/auto-prompts.js +63 -2
  29. package/dist/resources/extensions/gsd/auto-recovery.js +43 -4
  30. package/dist/resources/extensions/gsd/auto-runtime-state.js +31 -0
  31. package/dist/resources/extensions/gsd/auto-start.js +1 -1
  32. package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -2
  33. package/dist/resources/extensions/gsd/auto-worktree.js +60 -13
  34. package/dist/resources/extensions/gsd/auto.js +14 -5
  35. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +14 -2
  36. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -5
  37. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
  38. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -4
  39. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +112 -31
  40. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +11 -6
  41. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +22 -0
  42. package/dist/resources/extensions/gsd/bootstrap/system-context.js +45 -8
  43. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +121 -3
  44. package/dist/resources/extensions/gsd/commands/catalog.js +76 -5
  45. package/dist/resources/extensions/gsd/commands/handlers/core.js +23 -1
  46. package/dist/resources/extensions/gsd/commands/handlers/ops.js +8 -0
  47. package/dist/resources/extensions/gsd/commands-config.js +3 -2
  48. package/dist/resources/extensions/gsd/commands-extensions.js +46 -3
  49. package/dist/resources/extensions/gsd/commands-handlers.js +3 -2
  50. package/dist/resources/extensions/gsd/commands-mcp-status.js +3 -1
  51. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +10 -1
  52. package/dist/resources/extensions/gsd/commands-worktree.js +309 -0
  53. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
  54. package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -0
  55. package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
  56. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +39 -1
  57. package/dist/resources/extensions/gsd/error-classifier.js +1 -1
  58. package/dist/resources/extensions/gsd/forensics.js +10 -8
  59. package/dist/resources/extensions/gsd/git-service.js +12 -5
  60. package/dist/resources/extensions/gsd/gsd-db.js +11 -2
  61. package/dist/resources/extensions/gsd/guided-flow.js +25 -24
  62. package/dist/resources/extensions/gsd/home-dir.js +16 -0
  63. package/dist/resources/extensions/gsd/key-manager.js +2 -1
  64. package/dist/resources/extensions/gsd/memory-store.js +66 -31
  65. package/dist/resources/extensions/gsd/migrate/command.js +3 -2
  66. package/dist/resources/extensions/gsd/milestone-id-reservation.js +36 -0
  67. package/dist/resources/extensions/gsd/model-router.js +114 -9
  68. package/dist/resources/extensions/gsd/native-git-bridge.js +7 -1
  69. package/dist/resources/extensions/gsd/preferences-models.js +91 -15
  70. package/dist/resources/extensions/gsd/preferences-types.js +2 -0
  71. package/dist/resources/extensions/gsd/preferences-validation.js +32 -0
  72. package/dist/resources/extensions/gsd/preferences.js +5 -3
  73. package/dist/resources/extensions/gsd/prompt-loader.js +23 -12
  74. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +10 -0
  75. package/dist/resources/extensions/gsd/prompts/complete-slice.md +10 -0
  76. package/dist/resources/extensions/gsd/prompts/plan-slice.md +10 -0
  77. package/dist/resources/extensions/gsd/prompts/refine-slice.md +10 -0
  78. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +9 -3
  79. package/dist/resources/extensions/gsd/state.js +42 -0
  80. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
  81. package/dist/resources/extensions/gsd/tools/memory-tools.js +18 -1
  82. package/dist/resources/extensions/gsd/unit-context-manifest.js +29 -4
  83. package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
  84. package/dist/resources/extensions/gsd/watch/header-renderer.js +3 -1
  85. package/dist/resources/extensions/gsd/worktree-command.js +26 -46
  86. package/dist/resources/extensions/gsd/worktree-manager.js +20 -1
  87. package/dist/resources/extensions/gsd/worktree-resolver.js +4 -13
  88. package/dist/resources/extensions/gsd/worktree-root.js +124 -0
  89. package/dist/resources/extensions/gsd/worktree-session-state.js +33 -0
  90. package/dist/resources/extensions/gsd/worktree.js +4 -115
  91. package/dist/resources/extensions/mcp-client/index.js +6 -9
  92. package/dist/resources/extensions/ollama/index.js +15 -2
  93. package/dist/resources/extensions/ollama/model-capabilities.js +31 -0
  94. package/dist/resources/extensions/ollama/ollama-client.js +40 -4
  95. package/dist/resources/extensions/slash-commands/create-extension.js +36 -22
  96. package/dist/resources/extensions/subagent/index.js +324 -178
  97. package/dist/resources/skills/create-gsd-extension/SKILL.md +9 -5
  98. package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
  99. package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
  100. package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
  101. package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
  102. package/dist/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
  103. package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
  104. package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
  105. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
  106. package/dist/rtk-shared.d.ts +3 -0
  107. package/dist/rtk-shared.js +17 -0
  108. package/dist/rtk.d.ts +2 -5
  109. package/dist/rtk.js +3 -20
  110. package/dist/runtime-checks.d.ts +27 -0
  111. package/dist/runtime-checks.js +38 -0
  112. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  113. package/dist/web/standalone/.next/BUILD_ID +1 -1
  114. package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
  115. package/dist/web/standalone/.next/build-manifest.json +4 -4
  116. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  117. package/dist/web/standalone/.next/react-loadable-manifest.json +44 -4
  118. package/dist/web/standalone/.next/required-server-files.json +3 -3
  119. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  120. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  122. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  130. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  133. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  134. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  136. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  146. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  158. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  178. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  188. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/session/events/route.js +4 -2
  194. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  204. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  208. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  210. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  212. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  214. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  215. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  216. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  217. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  218. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  219. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  220. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  221. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  222. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  223. package/dist/web/standalone/.next/server/app/index.html +1 -1
  224. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  225. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  226. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  227. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  228. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  229. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  230. package/dist/web/standalone/.next/server/app/page.js +2 -2
  231. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  232. package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
  233. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  234. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  235. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  236. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  237. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  238. package/dist/web/standalone/.next/server/middleware.js +2 -2
  239. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  240. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  241. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  242. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  243. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  244. package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
  245. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +1 -0
  246. package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +1 -0
  247. package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +1 -0
  248. package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +1 -0
  249. package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +1 -0
  250. package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +1 -0
  251. package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +10 -0
  252. package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +2 -0
  253. package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +20 -0
  254. package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +1 -0
  255. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  256. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  257. package/dist/web/standalone/.next/static/chunks/app/page-9bf2e0c50fb2ca05.js +1 -0
  258. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  259. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  260. package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +1 -0
  261. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  262. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  263. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  264. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  265. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  266. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  267. package/dist/web/standalone/package.json +2 -1
  268. package/dist/web/standalone/server.js +1 -1
  269. package/dist/welcome-screen.js +27 -1
  270. package/dist/worktree-cli.d.ts +1 -0
  271. package/dist/worktree-cli.js +9 -3
  272. package/dist/worktree-status-banner.d.ts +1 -0
  273. package/dist/worktree-status-banner.js +132 -0
  274. package/package.json +1 -3
  275. package/packages/daemon/package.json +2 -2
  276. package/packages/mcp-server/dist/alias-telemetry.d.ts +8 -0
  277. package/packages/mcp-server/dist/alias-telemetry.d.ts.map +1 -0
  278. package/packages/mcp-server/dist/alias-telemetry.js +30 -0
  279. package/packages/mcp-server/dist/alias-telemetry.js.map +1 -0
  280. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  281. package/packages/mcp-server/dist/workflow-tools.js +74 -46
  282. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  283. package/packages/mcp-server/package.json +2 -2
  284. package/packages/mcp-server/src/alias-telemetry.test.ts +78 -0
  285. package/packages/mcp-server/src/alias-telemetry.ts +30 -0
  286. package/packages/mcp-server/src/workflow-tools.test.ts +78 -0
  287. package/packages/mcp-server/src/workflow-tools.ts +93 -58
  288. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  289. package/packages/native/package.json +1 -1
  290. package/packages/native/tsconfig.tsbuildinfo +1 -1
  291. package/packages/pi-agent-core/package.json +1 -1
  292. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  293. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts +2 -0
  294. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +1 -0
  295. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +231 -0
  296. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +1 -0
  297. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  298. package/packages/pi-ai/dist/providers/anthropic-shared.js +48 -19
  299. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  300. package/packages/pi-ai/dist/types.d.ts +13 -0
  301. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  302. package/packages/pi-ai/dist/types.js.map +1 -1
  303. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -1
  304. package/packages/pi-ai/dist/utils/repair-tool-json.js +24 -3
  305. package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -1
  306. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +26 -0
  307. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
  308. package/packages/pi-ai/package.json +1 -1
  309. package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +289 -0
  310. package/packages/pi-ai/src/providers/anthropic-shared.ts +52 -20
  311. package/packages/pi-ai/src/types.ts +13 -0
  312. package/packages/pi-ai/src/utils/repair-tool-json.ts +24 -3
  313. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +32 -0
  314. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  315. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  316. package/packages/pi-coding-agent/dist/core/agent-session.js +6 -0
  317. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  318. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  319. package/packages/pi-coding-agent/dist/core/messages.js +4 -0
  320. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  321. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +19 -2
  322. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  323. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +10 -0
  324. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  325. package/packages/pi-coding-agent/dist/core/model-registry.js +18 -0
  326. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  327. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +13 -0
  328. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  329. package/packages/pi-coding-agent/dist/core/system-prompt.js +20 -16
  330. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  331. package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +37 -0
  332. package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +1 -0
  333. package/packages/pi-coding-agent/dist/core/token-telemetry.js +49 -0
  334. package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +1 -0
  335. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +2 -0
  336. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +1 -0
  337. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +133 -0
  338. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -0
  339. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +1 -1
  340. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  341. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -1
  342. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  343. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +2 -0
  344. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +1 -0
  345. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +78 -0
  346. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +1 -0
  347. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +2 -0
  348. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +1 -0
  349. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +181 -0
  350. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +1 -0
  351. package/packages/pi-coding-agent/package.json +1 -1
  352. package/packages/pi-coding-agent/src/core/agent-session.ts +7 -0
  353. package/packages/pi-coding-agent/src/core/messages.ts +4 -0
  354. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +32 -2
  355. package/packages/pi-coding-agent/src/core/model-registry.ts +21 -0
  356. package/packages/pi-coding-agent/src/core/system-prompt.ts +33 -15
  357. package/packages/pi-coding-agent/src/core/token-telemetry.ts +77 -0
  358. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +212 -0
  359. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +17 -1
  360. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
  361. package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +102 -0
  362. package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +200 -0
  363. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  364. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +17 -3
  365. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  366. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +2 -0
  367. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +1 -0
  368. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +161 -0
  369. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +1 -0
  370. package/packages/pi-tui/package.json +1 -1
  371. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -3
  372. package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +219 -0
  373. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  374. package/packages/rpc-client/package.json +1 -1
  375. package/pkg/package.json +1 -1
  376. package/src/resources/extensions/claude-code-cli/readiness.ts +130 -30
  377. package/src/resources/extensions/google-search/index.ts +2 -9
  378. package/src/resources/extensions/gsd/auto/loop.ts +24 -2
  379. package/src/resources/extensions/gsd/auto/phases.ts +6 -14
  380. package/src/resources/extensions/gsd/auto/run-unit.ts +3 -1
  381. package/src/resources/extensions/gsd/auto/session.ts +5 -6
  382. package/src/resources/extensions/gsd/auto/types.ts +1 -0
  383. package/src/resources/extensions/gsd/auto-dashboard.ts +3 -2
  384. package/src/resources/extensions/gsd/auto-dispatch.ts +18 -6
  385. package/src/resources/extensions/gsd/auto-prompts.ts +60 -2
  386. package/src/resources/extensions/gsd/auto-recovery.ts +46 -8
  387. package/src/resources/extensions/gsd/auto-runtime-state.ts +51 -0
  388. package/src/resources/extensions/gsd/auto-start.ts +1 -1
  389. package/src/resources/extensions/gsd/auto-tool-tracking.ts +2 -4
  390. package/src/resources/extensions/gsd/auto-worktree.ts +82 -12
  391. package/src/resources/extensions/gsd/auto.ts +14 -4
  392. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +15 -13
  393. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +8 -7
  394. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
  395. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +10 -9
  396. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +121 -31
  397. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +12 -6
  398. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +20 -0
  399. package/src/resources/extensions/gsd/bootstrap/system-context.ts +50 -8
  400. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +141 -11
  401. package/src/resources/extensions/gsd/commands/catalog.ts +82 -5
  402. package/src/resources/extensions/gsd/commands/handlers/core.ts +23 -1
  403. package/src/resources/extensions/gsd/commands/handlers/ops.ts +10 -0
  404. package/src/resources/extensions/gsd/commands-config.ts +3 -2
  405. package/src/resources/extensions/gsd/commands-extensions.ts +43 -3
  406. package/src/resources/extensions/gsd/commands-handlers.ts +3 -2
  407. package/src/resources/extensions/gsd/commands-mcp-status.ts +3 -1
  408. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -1
  409. package/src/resources/extensions/gsd/commands-worktree.ts +383 -0
  410. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
  411. package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -0
  412. package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
  413. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +39 -1
  414. package/src/resources/extensions/gsd/doctor-types.ts +3 -1
  415. package/src/resources/extensions/gsd/error-classifier.ts +1 -1
  416. package/src/resources/extensions/gsd/forensics.ts +12 -7
  417. package/src/resources/extensions/gsd/git-service.ts +13 -5
  418. package/src/resources/extensions/gsd/gsd-db.ts +12 -2
  419. package/src/resources/extensions/gsd/guided-flow.ts +27 -26
  420. package/src/resources/extensions/gsd/home-dir.ts +19 -0
  421. package/src/resources/extensions/gsd/journal.ts +4 -1
  422. package/src/resources/extensions/gsd/key-manager.ts +2 -1
  423. package/src/resources/extensions/gsd/memory-store.ts +81 -28
  424. package/src/resources/extensions/gsd/migrate/command.ts +3 -2
  425. package/src/resources/extensions/gsd/milestone-id-reservation.ts +47 -0
  426. package/src/resources/extensions/gsd/model-router.ts +172 -9
  427. package/src/resources/extensions/gsd/native-git-bridge.ts +7 -1
  428. package/src/resources/extensions/gsd/preferences-models.ts +101 -15
  429. package/src/resources/extensions/gsd/preferences-types.ts +6 -0
  430. package/src/resources/extensions/gsd/preferences-validation.ts +35 -0
  431. package/src/resources/extensions/gsd/preferences.ts +16 -2
  432. package/src/resources/extensions/gsd/prompt-loader.ts +26 -12
  433. package/src/resources/extensions/gsd/prompts/complete-milestone.md +10 -0
  434. package/src/resources/extensions/gsd/prompts/complete-slice.md +10 -0
  435. package/src/resources/extensions/gsd/prompts/plan-slice.md +10 -0
  436. package/src/resources/extensions/gsd/prompts/refine-slice.md +10 -0
  437. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +9 -3
  438. package/src/resources/extensions/gsd/state.ts +42 -0
  439. package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
  440. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +178 -1
  441. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +58 -0
  442. package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +24 -5
  443. package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +21 -4
  444. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +1 -1
  445. package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +138 -211
  446. package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +50 -27
  447. package/src/resources/extensions/gsd/tests/commands-extensions-version-compare.test.ts +58 -0
  448. package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +48 -0
  449. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +142 -59
  450. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +7 -4
  451. package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +89 -32
  452. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +41 -23
  453. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +3 -43
  454. package/src/resources/extensions/gsd/tests/debug-logger.test.ts +5 -3
  455. package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +116 -0
  456. package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +22 -87
  457. package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +7 -118
  458. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +18 -60
  459. package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +100 -0
  460. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +14 -76
  461. package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +93 -0
  462. package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +22 -83
  463. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +1 -63
  464. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +47 -0
  465. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +26 -1
  466. package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +63 -0
  467. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +25 -65
  468. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +30 -0
  469. package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +81 -0
  470. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +14 -4
  471. package/src/resources/extensions/gsd/tests/health-widget.test.ts +22 -12
  472. package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +57 -0
  473. package/src/resources/extensions/gsd/tests/home-dir.test.ts +52 -0
  474. package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +145 -0
  475. package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +64 -1
  476. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +72 -1
  477. package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +0 -23
  478. package/src/resources/extensions/gsd/tests/memory-store.test.ts +128 -0
  479. package/src/resources/extensions/gsd/tests/memory-tools.test.ts +33 -1
  480. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +124 -0
  481. package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +152 -0
  482. package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +18 -1
  483. package/src/resources/extensions/gsd/tests/model-router.test.ts +169 -8
  484. package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +50 -0
  485. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +8 -0
  486. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +32 -43
  487. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +4 -10
  488. package/src/resources/extensions/gsd/tests/preferences.test.ts +127 -0
  489. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +16 -0
  490. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
  491. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
  492. package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +93 -0
  493. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +34 -0
  494. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +168 -19
  495. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +7 -1
  496. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +23 -1
  497. package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +17 -1
  498. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +101 -0
  499. package/src/resources/extensions/gsd/tests/token-profile.test.ts +51 -4
  500. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +7 -16
  501. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +38 -3
  502. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -7
  503. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +15 -1
  504. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
  505. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +34 -33
  506. package/src/resources/extensions/gsd/tests/worktree.test.ts +8 -0
  507. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +131 -1
  508. package/src/resources/extensions/gsd/tools/memory-tools.ts +17 -1
  509. package/src/resources/extensions/gsd/unit-context-manifest.ts +44 -12
  510. package/src/resources/extensions/gsd/visualizer-overlay.ts +1 -1
  511. package/src/resources/extensions/gsd/watch/header-renderer.ts +3 -1
  512. package/src/resources/extensions/gsd/workflow-logger.ts +1 -0
  513. package/src/resources/extensions/gsd/worktree-command.ts +31 -44
  514. package/src/resources/extensions/gsd/worktree-manager.ts +40 -1
  515. package/src/resources/extensions/gsd/worktree-resolver.ts +4 -14
  516. package/src/resources/extensions/gsd/worktree-root.ts +144 -0
  517. package/src/resources/extensions/gsd/worktree-session-state.ts +35 -0
  518. package/src/resources/extensions/gsd/worktree.ts +8 -119
  519. package/src/resources/extensions/mcp-client/index.ts +6 -10
  520. package/src/resources/extensions/mcp-client/tests/global-config.test.ts +91 -0
  521. package/src/resources/extensions/ollama/index.ts +16 -2
  522. package/src/resources/extensions/ollama/model-capabilities.ts +34 -0
  523. package/src/resources/extensions/ollama/ollama-client.ts +41 -4
  524. package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +96 -0
  525. package/src/resources/extensions/ollama/tests/ollama-client-timeout-env.test.ts +147 -0
  526. package/src/resources/extensions/slash-commands/create-extension.ts +38 -24
  527. package/src/resources/extensions/subagent/index.ts +165 -7
  528. package/src/resources/skills/create-gsd-extension/SKILL.md +9 -5
  529. package/src/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
  530. package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
  531. package/src/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
  532. package/src/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
  533. package/src/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
  534. package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
  535. package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
  536. package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +2 -2
  537. package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +3 -3
  538. package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +58 -0
  539. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
  540. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +0 -601
  541. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +0 -651
  542. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +0 -91
  543. package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +0 -53
  544. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +0 -112
  545. package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +0 -23
  546. package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +0 -5
  547. package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
  548. package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +0 -608
  549. package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +0 -11
  550. package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +0 -20
  551. package/dist/web/standalone/.next/static/chunks/app/page-151349214571e2b6.js +0 -1
  552. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  553. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  554. package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.js +0 -1
  555. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +0 -22
  556. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +0 -47
  557. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +0 -75
  558. /package/dist/web/standalone/.next/static/{C1zT2kEfoLhDdbWPWKrXd → QK8fABiGPmonfTgboN0Y9}/_buildManifest.js +0 -0
  559. /package/dist/web/standalone/.next/static/{C1zT2kEfoLhDdbWPWKrXd → QK8fABiGPmonfTgboN0Y9}/_ssgManifest.js +0 -0
@@ -10,7 +10,7 @@
10
10
  import { describe, test } from "node:test";
11
11
  import assert from "node:assert/strict";
12
12
 
13
- import { _resolveReportBasePath } from "../auto/phases.ts";
13
+ import { _resolveDispatchGuardBasePath, _resolveReportBasePath } from "../auto/phases.ts";
14
14
 
15
15
  describe("_resolveReportBasePath", () => {
16
16
  test("uses originalBasePath when set (worktree scenario)", () => {
@@ -48,4 +48,21 @@ describe("_resolveReportBasePath", () => {
48
48
 
49
49
  assert.equal(_resolveReportBasePath(session), "/home/user/repo");
50
50
  });
51
+
52
+ test("uses GSD_PROJECT_ROOT for symlink-resolved worktree paths", () => {
53
+ const savedProjectRoot = process.env.GSD_PROJECT_ROOT;
54
+ process.env.GSD_PROJECT_ROOT = "/real/project";
55
+ try {
56
+ const session = {
57
+ originalBasePath: "",
58
+ basePath: "/Users/dev/.gsd/projects/abc123/worktrees/M001/slices/S01",
59
+ };
60
+
61
+ assert.equal(_resolveReportBasePath(session), "/real/project");
62
+ assert.equal(_resolveDispatchGuardBasePath(session), "/real/project");
63
+ } finally {
64
+ if (savedProjectRoot === undefined) delete process.env.GSD_PROJECT_ROOT;
65
+ else process.env.GSD_PROJECT_ROOT = savedProjectRoot;
66
+ }
67
+ });
51
68
  });
@@ -5,6 +5,7 @@ import {
5
5
  resolveModelForComplexity,
6
6
  escalateTier,
7
7
  defaultRoutingConfig,
8
+ resolveModelForTier,
8
9
  scoreModel,
9
10
  computeTaskRequirements,
10
11
  scoreEligibleModels,
@@ -248,6 +249,172 @@ test("#2192: known model is still downgraded normally", () => {
248
249
  assert.notEqual(result.modelId, "claude-opus-4-6");
249
250
  });
250
251
 
252
+ // ─── Cross-provider fallback ──────────────────────────────────────────────────
253
+
254
+ test("uses cross-provider equivalent when configured primary is unavailable", () => {
255
+ const config = { ...defaultRoutingConfig(), enabled: true };
256
+ // Profile default says claude-opus-4-6 for planning, but user is on GPT only
257
+ const result = resolveModelForComplexity(
258
+ makeClassification("heavy"),
259
+ { primary: "claude-opus-4-6", fallbacks: [] },
260
+ config,
261
+ ["gpt-4o", "gpt-4o-mini", "o1"],
262
+ );
263
+ // o1 is the heavy-tier GPT model — should be selected as cross-provider equivalent
264
+ assert.equal(result.modelId, "o1");
265
+ assert.equal(result.wasDowngraded, false);
266
+ assert.match(result.reason, /cross-provider/);
267
+ });
268
+
269
+ test("cross-provider: selects standard-tier equivalent when primary unavailable", () => {
270
+ const config = { ...defaultRoutingConfig(), enabled: true };
271
+ // Planning configured with Opus, but only GPT standard models available
272
+ const result = resolveModelForComplexity(
273
+ makeClassification("heavy"),
274
+ { primary: "claude-opus-4-6", fallbacks: [] },
275
+ config,
276
+ ["gpt-4o", "gpt-4o-mini"],
277
+ );
278
+ // gpt-4o is standard tier, not heavy — no heavy-tier model available
279
+ // Should fall back to gpt-4o (best available)
280
+ assert.ok(result.modelId === "gpt-4o" || result.modelId === "claude-opus-4-6");
281
+ assert.equal(result.wasDowngraded, false);
282
+ });
283
+
284
+ test("cross-provider: configured primary available by bare ID wins over equivalent", () => {
285
+ const config = { ...defaultRoutingConfig(), enabled: true };
286
+ // Provider-prefixed ID — bare match should find it
287
+ const result = resolveModelForComplexity(
288
+ makeClassification("heavy"),
289
+ { primary: "claude-opus-4-6", fallbacks: [] },
290
+ config,
291
+ ["anthropic/claude-opus-4-6", "o1"],
292
+ );
293
+ assert.equal(result.modelId, "claude-opus-4-6");
294
+ assert.equal(result.wasDowngraded, false);
295
+ });
296
+
297
+ // ─── resolveModelForTier (provider-agnostic tier resolution) ────────────────
298
+
299
+ test("resolveModelForTier: returns canonical Anthropic model when no available models", () => {
300
+ assert.equal(resolveModelForTier("heavy", []), "claude-opus-4-6");
301
+ assert.equal(resolveModelForTier("standard", []), "claude-sonnet-4-6");
302
+ assert.equal(resolveModelForTier("light", []), "claude-haiku-4-5");
303
+ });
304
+
305
+ test("resolveModelForTier: returns canonical model when it is available", () => {
306
+ assert.equal(
307
+ resolveModelForTier("heavy", ["claude-opus-4-6", "claude-sonnet-4-6"]),
308
+ "claude-opus-4-6",
309
+ );
310
+ });
311
+
312
+ test("resolveModelForTier: does not prefer canonical over cheaper same-tier model", () => {
313
+ const result = resolveModelForTier("light", ["claude-haiku-4-5", "gpt-4o-mini"]);
314
+ assert.equal(result, "gpt-4o-mini");
315
+ });
316
+
317
+ test("resolveModelForTier: honors configured tier_models pins", () => {
318
+ const config: DynamicRoutingConfig = {
319
+ ...defaultRoutingConfig(),
320
+ tier_models: { light: "claude-haiku-4-5" },
321
+ };
322
+ const result = resolveModelForTier("light", ["claude-haiku-4-5", "gpt-4o-mini"], config);
323
+ assert.equal(result, "claude-haiku-4-5");
324
+ });
325
+
326
+ test("resolveModelForTier: picks cross-provider equivalent when Anthropic unavailable", () => {
327
+ // Only OpenAI models available
328
+ const result = resolveModelForTier("heavy", ["gpt-4o", "gpt-4o-mini", "o1"]);
329
+ // o1 is the heavy-tier model in the OpenAI lineup
330
+ assert.equal(result, "o1");
331
+ });
332
+
333
+ test("resolveModelForTier: picks standard-tier cross-provider model", () => {
334
+ const result = resolveModelForTier("standard", ["gpt-4o", "gpt-4o-mini"]);
335
+ assert.equal(result, "gpt-4o");
336
+ });
337
+
338
+ test("resolveModelForTier: picks light-tier cross-provider model", () => {
339
+ const result = resolveModelForTier("light", ["gpt-4o", "gpt-4o-mini"]);
340
+ assert.equal(result, "gpt-4o-mini");
341
+ });
342
+
343
+ test("resolveModelForTier: falls back to canonical when no tier match available", () => {
344
+ // Only unknown models available — getModelTier classifies unknowns as
345
+ // "standard", so a request for "heavy" finds no match and the canonical
346
+ // Anthropic ID is returned as a documented fallback.
347
+ const result = resolveModelForTier("heavy", ["some-custom-model"]);
348
+ assert.equal(result, "claude-opus-4-6");
349
+ });
350
+
351
+ test("resolveModelForTier: handles provider-prefixed available models", () => {
352
+ const result = resolveModelForTier("heavy", ["anthropic/claude-opus-4-6"]);
353
+ assert.equal(result, "claude-opus-4-6");
354
+ });
355
+
356
+ test("resolveModelForTier: picks Gemini models when only Google available", () => {
357
+ const result = resolveModelForTier("light", ["gemini-2.5-pro", "gemini-2.0-flash"]);
358
+ assert.equal(result, "gemini-2.0-flash");
359
+ });
360
+
361
+ // ─── Behavioral: profile defaults are provider-agnostic at runtime ──────────
362
+
363
+ test("resolveProfileDefaults: balanced with only OpenAI models returns OpenAI IDs", async () => {
364
+ const { resolveProfileDefaults } = await import("../preferences-models.js");
365
+ const defaults = resolveProfileDefaults("balanced", ["gpt-4o", "gpt-4o-mini"]);
366
+ assert.ok(defaults.models, "balanced should populate models");
367
+ // All slots must resolve to an available OpenAI ID — not a claude- canonical.
368
+ for (const [phase, modelId] of Object.entries(defaults.models!)) {
369
+ assert.ok(typeof modelId === "string" && modelId.length > 0, `${phase} should resolve to a model ID`);
370
+ assert.ok(
371
+ !String(modelId).startsWith("claude-"),
372
+ `${phase} resolved to ${modelId} but no claude-* model is available — should be OpenAI`,
373
+ );
374
+ }
375
+ });
376
+
377
+ test("resolveProfileDefaults: budget with only OpenAI models picks gpt-4o-mini for light slots", async () => {
378
+ const { resolveProfileDefaults } = await import("../preferences-models.js");
379
+ const defaults = resolveProfileDefaults("budget", ["gpt-4o", "gpt-4o-mini"]);
380
+ // light-tier slots in budget: research, execution_simple, completion, subagent
381
+ assert.equal(defaults.models?.research, "gpt-4o-mini");
382
+ assert.equal(defaults.models?.execution_simple, "gpt-4o-mini");
383
+ assert.equal(defaults.models?.completion, "gpt-4o-mini");
384
+ assert.equal(defaults.models?.subagent, "gpt-4o-mini");
385
+ // standard-tier slots: planning, execution
386
+ assert.equal(defaults.models?.planning, "gpt-4o");
387
+ assert.equal(defaults.models?.execution, "gpt-4o");
388
+ });
389
+
390
+ test("resolveProfileDefaults: honors dynamic routing tier_models pins", async () => {
391
+ const { resolveProfileDefaults } = await import("../preferences-models.js");
392
+ const defaults = resolveProfileDefaults(
393
+ "budget",
394
+ ["claude-haiku-4-5", "gpt-4o-mini", "gpt-4o"],
395
+ { ...defaultRoutingConfig(), tier_models: { light: "claude-haiku-4-5" } },
396
+ );
397
+ assert.equal(defaults.models?.research, "claude-haiku-4-5");
398
+ assert.equal(defaults.models?.execution_simple, "claude-haiku-4-5");
399
+ assert.equal(defaults.models?.completion, "claude-haiku-4-5");
400
+ assert.equal(defaults.models?.subagent, "claude-haiku-4-5");
401
+ });
402
+
403
+ test("resolveProfileDefaults: empty availableModelIds falls back to canonical Anthropic IDs", async () => {
404
+ const { resolveProfileDefaults } = await import("../preferences-models.js");
405
+ const defaults = resolveProfileDefaults("balanced", []);
406
+ // Documented fallback only — when registry is unavailable at bootstrap.
407
+ const planningModel = defaults.models?.planning;
408
+ assert.ok(typeof planningModel === "string" && planningModel.startsWith("claude-"));
409
+ });
410
+
411
+ test("resolveProfileDefaults: burn-max omits models so user choice is preserved", async () => {
412
+ const { resolveProfileDefaults } = await import("../preferences-models.js");
413
+ const defaults = resolveProfileDefaults("burn-max", ["gpt-4o"]);
414
+ assert.equal(defaults.models, undefined, "burn-max must not write model defaults");
415
+ assert.equal(defaults.dynamic_routing?.enabled, false);
416
+ });
417
+
251
418
  // ─── Capability Scoring (ADR-004 Phase 2) ───────────────────────────────────
252
419
 
253
420
  test("defaultRoutingConfig includes capability_routing: true", () => {
@@ -279,14 +446,8 @@ test("scoreModel computes weighted average of capability × requirement", () =>
279
446
  assert.ok(Math.abs(score - 88.21) < 0.1, `score ${score} should be ~88.21`);
280
447
  });
281
448
 
282
- test("scoreModel returns 50 for empty requirements", () => {
283
- const caps: ModelCapabilities = {
284
- coding: 90, debugging: 80, research: 70,
285
- reasoning: 85, speed: 50, longContext: 60, instruction: 75,
286
- };
287
- const score = scoreModel(caps, {});
288
- assert.equal(score, 50);
289
- });
449
+ // (Removed duplicate "scoreModel returns 50 for empty requirements" the
450
+ // `describe("scoreModel")` block below has the same scenario.)
290
451
 
291
452
  test("computeTaskRequirements returns base vector for known unit type", () => {
292
453
  const reqs = computeTaskRequirements("execute-task");
@@ -0,0 +1,50 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { chmodSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+
7
+ import { git } from "./test-utils.ts";
8
+ import { GSD_GIT_ERROR } from "../errors.js";
9
+
10
+ test("nativeAddAllWithExclusions preserves infrastructure failures from git add", async () => {
11
+ const base = mkdtempSync(join(tmpdir(), "gsd-native-git-infra-"));
12
+ const repo = join(base, "repo");
13
+ const bin = join(base, "bin");
14
+ mkdirSync(repo);
15
+ mkdirSync(bin);
16
+
17
+ const fakeGit = join(bin, "git");
18
+ writeFileSync(
19
+ fakeGit,
20
+ "#!/bin/sh\n" +
21
+ "echo 'fatal: ENFILE: file table overflow' >&2\n" +
22
+ "exit 1\n",
23
+ "utf-8",
24
+ );
25
+ chmodSync(fakeGit, 0o755);
26
+
27
+ const originalPath = process.env.PATH ?? "";
28
+ try {
29
+ git(repo, "init");
30
+ git(repo, "config", "user.email", "test@example.com");
31
+ git(repo, "config", "user.name", "Test User");
32
+ writeFileSync(join(repo, "README.md"), "# Test\n", "utf-8");
33
+
34
+ process.env.PATH = `${bin}:${originalPath}`;
35
+ const { nativeAddAllWithExclusions } = await import("../native-git-bridge.ts");
36
+
37
+ assert.throws(
38
+ () => nativeAddAllWithExclusions(repo, [".gsd/activity/"]),
39
+ (err) => {
40
+ const shaped = err as { code?: string; stderr?: string; message?: string };
41
+ assert.notEqual(shaped.code, GSD_GIT_ERROR);
42
+ assert.match(`${shaped.stderr ?? ""}${shaped.message ?? ""}`, /ENFILE/);
43
+ return true;
44
+ },
45
+ );
46
+ } finally {
47
+ process.env.PATH = originalPath;
48
+ rmSync(base, { recursive: true, force: true });
49
+ }
50
+ });
@@ -101,6 +101,14 @@ describe("auditOrphanedMilestoneBranches", () => {
101
101
  result.warnings.some(w => w.includes("NOT merged")),
102
102
  "should warn about unmerged branch",
103
103
  );
104
+ assert.ok(
105
+ result.warnings.some(w => w.includes("/gsd doctor fix")),
106
+ `warning should suggest the real remediation command; got: ${JSON.stringify(result.warnings)}`,
107
+ );
108
+ assert.ok(
109
+ result.warnings.every(w => !w.includes("/gsd health --fix")),
110
+ `warning must not suggest the removed health --fix command; got: ${JSON.stringify(result.warnings)}`,
111
+ );
104
112
 
105
113
  // Branch should still exist (data safety)
106
114
  const branches = run("git branch --list milestone/M001", dir);
@@ -19,13 +19,15 @@ import { join } from "node:path";
19
19
  import { tmpdir } from "node:os";
20
20
 
21
21
  import {
22
- persistState,
23
22
  restoreState,
24
23
  resetOrchestrator,
25
- getOrchestratorState,
26
24
  type PersistedState,
27
25
  } from "../parallel-orchestrator.ts";
28
- import { writeSessionStatus, readAllSessionStatuses, removeSessionStatus } from "../session-status-io.ts";
26
+ import {
27
+ writeSessionStatus,
28
+ readAllSessionStatuses,
29
+ cleanupStaleSessions,
30
+ } from "../session-status-io.ts";
29
31
  // ─── Helpers ──────────────────────────────────────────────────────────────────
30
32
 
31
33
  function makeTempDir(): string {
@@ -57,17 +59,20 @@ function makePersistedState(overrides: Partial<PersistedState> = {}): PersistedS
57
59
 
58
60
 
59
61
  describe('parallel-crash-recovery', () => {
60
- test('Test 1: persistState writes valid JSON', () => {
62
+ test('Test 1: orchestrator.json round-trips through restoreState (preserves worker fields)', () => {
61
63
  const basePath = makeTempDir();
62
64
  try {
63
- // We can't call persistState directly without internal state set up,
64
- // so we test the round-trip by writing a state file and reading it back
65
+ // Write a full state file to disk and then exercise the real production
66
+ // restoreState() reader against it. This verifies the persisted file
67
+ // schema (the contract between persistState's writer and the reader)
68
+ // — earlier this test inlined a test-only writer and re-parsed JSON,
69
+ // bypassing production code entirely.
65
70
  const state = makePersistedState({
66
71
  workers: [
67
72
  {
68
73
  milestoneId: "M001",
69
74
  title: "M001",
70
- pid: process.pid,
75
+ pid: process.pid, // alive — survives restoreState's PID filter
71
76
  worktreePath: "/tmp/wt-M001",
72
77
  startedAt: Date.now(),
73
78
  state: "running",
@@ -78,13 +83,13 @@ test('Test 1: persistState writes valid JSON', () => {
78
83
  });
79
84
  writeStateFile(basePath, state);
80
85
 
81
- const raw = readFileSync(stateFilePath(basePath), "utf-8");
82
- const parsed = JSON.parse(raw) as PersistedState;
83
- assert.deepStrictEqual(parsed.active, true, "persistState: active field preserved");
84
- assert.deepStrictEqual(parsed.workers.length, 1, "persistState: worker count preserved");
85
- assert.deepStrictEqual(parsed.workers[0].milestoneId, "M001", "persistState: milestoneId preserved");
86
- assert.deepStrictEqual(parsed.workers[0].cost, 0.15, "persistState: cost preserved");
87
- assert.deepStrictEqual(parsed.totalCost, 0.15, "persistState: totalCost preserved");
86
+ const restored = restoreState(basePath);
87
+ assert.ok(restored !== null, "restoreState: returns state for live worker");
88
+ assert.deepStrictEqual(restored!.active, true, "active field preserved through round-trip");
89
+ assert.deepStrictEqual(restored!.workers.length, 1, "worker count preserved");
90
+ assert.deepStrictEqual(restored!.workers[0].milestoneId, "M001", "milestoneId preserved");
91
+ assert.deepStrictEqual(restored!.workers[0].cost, 0.15, "cost preserved");
92
+ assert.deepStrictEqual(restored!.totalCost, 0.15, "totalCost preserved");
88
93
  } finally {
89
94
  rmSync(basePath, { recursive: true, force: true });
90
95
  }
@@ -201,11 +206,12 @@ test('Test 5: restoreState skips stopped/error workers even with alive PIDs', ()
201
206
  }
202
207
  });
203
208
 
204
- test('Test 6: orphan detection finds stale sessions', () => {
209
+ test('Test 6: cleanupStaleSessions removes dead-PID sessions and keeps live ones', () => {
205
210
  const basePath = makeTempDir();
206
211
  try {
207
- // Write a session status with a dead PID
208
212
  mkdirSync(join(basePath, ".gsd", "parallel"), { recursive: true });
213
+
214
+ // Dead PID
209
215
  writeSessionStatus(basePath, {
210
216
  milestoneId: "M001",
211
217
  pid: 99999999,
@@ -218,7 +224,7 @@ test('Test 6: orphan detection finds stale sessions', () => {
218
224
  worktreePath: "/tmp/wt-M001",
219
225
  });
220
226
 
221
- // Write a session status with alive PID
227
+ // Live PID (this process)
222
228
  writeSessionStatus(basePath, {
223
229
  milestoneId: "M002",
224
230
  pid: process.pid,
@@ -231,37 +237,20 @@ test('Test 6: orphan detection finds stale sessions', () => {
231
237
  worktreePath: "/tmp/wt-M002",
232
238
  });
233
239
 
234
- // Read all sessions — both should exist initially
235
240
  const before = readAllSessionStatuses(basePath);
236
- assert.deepStrictEqual(before.length, 2, "orphan: both sessions exist before detection");
241
+ assert.deepStrictEqual(before.length, 2, "both sessions exist before cleanup");
237
242
 
238
- // Now simulate orphan detection logic (same as prepareParallelStart)
239
- const sessions = readAllSessionStatuses(basePath);
240
- const orphans: Array<{ milestoneId: string; pid: number; alive: boolean }> = [];
241
- for (const session of sessions) {
242
- let alive: boolean;
243
- try {
244
- process.kill(session.pid, 0);
245
- alive = true;
246
- } catch {
247
- alive = false;
248
- }
249
- orphans.push({ milestoneId: session.milestoneId, pid: session.pid, alive });
250
- if (!alive) {
251
- removeSessionStatus(basePath, session.milestoneId);
252
- }
253
- }
243
+ // Drive the real production cleanup function. Earlier this test
244
+ // re-implemented the cleanup loop inline (process.kill + remove*) and
245
+ // never exercised cleanupStaleSessions itself so changes to the
246
+ // production sweep would not have been caught.
247
+ const removed = cleanupStaleSessions(basePath);
254
248
 
255
- assert.ok(orphans.length === 2, "orphan: detected both sessions");
256
- const deadOrphan = orphans.find(o => o.milestoneId === "M001");
257
- assert.ok(deadOrphan !== undefined && !deadOrphan.alive, "orphan: M001 detected as dead");
258
- const aliveOrphan = orphans.find(o => o.milestoneId === "M002");
259
- assert.ok(aliveOrphan !== undefined && aliveOrphan.alive, "orphan: M002 detected as alive");
249
+ assert.deepStrictEqual(removed, ["M001"], "dead-PID session id is reported as removed");
260
250
 
261
- // Dead session should be cleaned up
262
251
  const after = readAllSessionStatuses(basePath);
263
- assert.deepStrictEqual(after.length, 1, "orphan: dead session cleaned up");
264
- assert.deepStrictEqual(after[0].milestoneId, "M002", "orphan: alive session remains");
252
+ assert.deepStrictEqual(after.length, 1, "dead session cleaned up");
253
+ assert.deepStrictEqual(after[0].milestoneId, "M002", "alive session remains");
265
254
  } finally {
266
255
  rmSync(basePath, { recursive: true, force: true });
267
256
  }
@@ -18,20 +18,14 @@ const phasesSrc = readFileSync(phasesPath, "utf-8");
18
18
 
19
19
  console.log("\n=== #2766: Non-MergeConflictError stops auto mode ===");
20
20
 
21
- // ── Test 1: phases.ts calls logError for non-conflict merge errors ──────
22
-
23
- assertTrue(
24
- phasesPath.length > 0 && phasesPath.endsWith("phases.ts"),
25
- "phases.ts file exists and is readable",
26
- );
21
+ // ── Test 1: every mergeAndExit call site has a catch (mergeErr) block ──
27
22
 
28
23
  // Count all mergeAndExit catch blocks by finding "} catch (mergeErr)" patterns
29
- const mergeErrCatches = [...phasesPath.matchAll(/\} catch \(mergeErr\)/g)];
30
- // Use the source itself for matching
24
+ const mergeAndExitCallCount = [...phasesSrc.matchAll(/\.mergeAndExit\(/g)].length;
31
25
  const mergeErrCatchCount = [...phasesSrc.matchAll(/\} catch \(mergeErr\)/g)].length;
32
26
  assertTrue(
33
- mergeErrCatchCount >= 3,
34
- `all mergeAndExit call sites have catch (mergeErr) blocks (found ${mergeErrCatchCount}, expected >= 3)`,
27
+ mergeErrCatchCount === mergeAndExitCallCount && mergeAndExitCallCount > 0,
28
+ `every mergeAndExit call site has a catch (mergeErr) block (calls=${mergeAndExitCallCount}, catches=${mergeErrCatchCount})`,
35
29
  );
36
30
 
37
31
  // ── Test 2: Every mergeErr catch block handles non-MergeConflictError ───
@@ -236,6 +236,20 @@ test("valid values pass through correctly", () => {
236
236
  assert.equal(p3.auto_supervisor?.model, "claude-opus-4-6");
237
237
  });
238
238
 
239
+ test("min_request_interval_ms floors decimals and rejects timer overflow values", () => {
240
+ const valid = validatePreferences({ min_request_interval_ms: 1000.9 });
241
+ assert.equal(valid.errors.length, 0);
242
+ assert.equal(valid.preferences.min_request_interval_ms, 1000);
243
+
244
+ const max = validatePreferences({ min_request_interval_ms: 2_147_483_647 });
245
+ assert.equal(max.errors.length, 0);
246
+ assert.equal(max.preferences.min_request_interval_ms, 2_147_483_647);
247
+
248
+ const tooHigh = validatePreferences({ min_request_interval_ms: 2_147_483_648 });
249
+ assert.ok(tooHigh.errors.some(e => e.includes("min_request_interval_ms must be a non-negative number <= 2147483647")));
250
+ assert.equal(tooHigh.preferences.min_request_interval_ms, undefined);
251
+ });
252
+
239
253
  test("mixed valid/invalid/unknown keys handled correctly", () => {
240
254
  const { preferences, errors, warnings } = validatePreferences({
241
255
  uat_dispatch: true, totally_made_up: "value", budget_ceiling: "garbage",
@@ -246,6 +260,71 @@ test("mixed valid/invalid/unknown keys handled correctly", () => {
246
260
  assert.equal(preferences.budget_ceiling, undefined);
247
261
  });
248
262
 
263
+ test("disabled_model_providers validates and normalizes string arrays", () => {
264
+ const { preferences, errors } = validatePreferences({
265
+ disabled_model_providers: ["google-gemini-cli", " google-gemini-cli ", "openai-codex", " "],
266
+ });
267
+ assert.equal(errors.length, 0);
268
+ assert.deepEqual(preferences.disabled_model_providers, ["google-gemini-cli", "openai-codex"]);
269
+ });
270
+
271
+ test("disabled_model_providers rejects non-array values", () => {
272
+ const { errors } = validatePreferences({ disabled_model_providers: "google-gemini-cli" as any });
273
+ assert.ok(errors.some((e) => e.includes("disabled_model_providers must be an array of strings")));
274
+ });
275
+
276
+ test("loadEffectiveGSDPreferences preserves disabled_model_providers across merge layers", () => {
277
+ const originalCwd = process.cwd();
278
+ const originalGsdHome = process.env.GSD_HOME;
279
+ const tempProject = mkdtempSync(join(tmpdir(), "gsd-disabled-provider-project-"));
280
+ const tempGsdHome = mkdtempSync(join(tmpdir(), "gsd-disabled-provider-home-"));
281
+
282
+ try {
283
+ mkdirSync(join(tempProject, ".gsd"), { recursive: true });
284
+
285
+ writeFileSync(
286
+ join(tempGsdHome, "PREFERENCES.md"),
287
+ [
288
+ "---",
289
+ "version: 1",
290
+ "disabled_model_providers:",
291
+ " - google-gemini-cli",
292
+ "---",
293
+ ].join("\n"),
294
+ "utf-8",
295
+ );
296
+
297
+ writeFileSync(
298
+ join(tempProject, ".gsd", "PREFERENCES.md"),
299
+ [
300
+ "---",
301
+ "version: 1",
302
+ "disabled_model_providers:",
303
+ " - openai-codex",
304
+ " - google-gemini-cli",
305
+ "---",
306
+ ].join("\n"),
307
+ "utf-8",
308
+ );
309
+
310
+ process.env.GSD_HOME = tempGsdHome;
311
+ process.chdir(tempProject);
312
+
313
+ const loaded = loadEffectiveGSDPreferences();
314
+ assert.notEqual(loaded, null);
315
+ assert.deepEqual(
316
+ loaded!.preferences.disabled_model_providers,
317
+ ["google-gemini-cli", "openai-codex"],
318
+ );
319
+ } finally {
320
+ process.chdir(originalCwd);
321
+ if (originalGsdHome === undefined) delete process.env.GSD_HOME;
322
+ else process.env.GSD_HOME = originalGsdHome;
323
+ rmSync(tempProject, { recursive: true, force: true });
324
+ rmSync(tempGsdHome, { recursive: true, force: true });
325
+ }
326
+ });
327
+
249
328
  // ── Wizard fields ────────────────────────────────────────────────────────────
250
329
 
251
330
  test("budget fields validate correctly", () => {
@@ -683,6 +762,54 @@ test("loadEffectiveGSDPreferences exposes slice_parallel prefs to runtime caller
683
762
  }
684
763
  });
685
764
 
765
+ test("loadEffectiveGSDPreferences merges min_request_interval_ms with project overriding global (#2996)", () => {
766
+ const originalCwd = process.cwd();
767
+ const originalGsdHome = process.env.GSD_HOME;
768
+ const tempProject = mkdtempSync(join(tmpdir(), "gsd-rate-limit-project-"));
769
+ const tempGsdHome = mkdtempSync(join(tmpdir(), "gsd-rate-limit-home-"));
770
+
771
+ try {
772
+ mkdirSync(join(tempProject, ".gsd"), { recursive: true });
773
+
774
+ writeFileSync(
775
+ join(tempGsdHome, "PREFERENCES.md"),
776
+ [
777
+ "---",
778
+ "version: 1",
779
+ "min_request_interval_ms: 250",
780
+ "budget_ceiling: 45",
781
+ "---",
782
+ ].join("\n"),
783
+ "utf-8",
784
+ );
785
+
786
+ writeFileSync(
787
+ join(tempProject, ".gsd", "PREFERENCES.md"),
788
+ [
789
+ "---",
790
+ "version: 1",
791
+ "min_request_interval_ms: 100",
792
+ "---",
793
+ ].join("\n"),
794
+ "utf-8",
795
+ );
796
+
797
+ process.env.GSD_HOME = tempGsdHome;
798
+ process.chdir(tempProject);
799
+
800
+ const loaded = loadEffectiveGSDPreferences();
801
+ assert.notEqual(loaded, null);
802
+ assert.equal(loaded!.preferences.min_request_interval_ms, 100);
803
+ assert.equal(loaded!.preferences.budget_ceiling, 45);
804
+ } finally {
805
+ process.chdir(originalCwd);
806
+ if (originalGsdHome === undefined) delete process.env.GSD_HOME;
807
+ else process.env.GSD_HOME = originalGsdHome;
808
+ rmSync(tempProject, { recursive: true, force: true });
809
+ rmSync(tempGsdHome, { recursive: true, force: true });
810
+ }
811
+ });
812
+
686
813
  test("preferences paths use canonical uppercase filenames", () => {
687
814
  const originalCwd = process.cwd();
688
815
  const originalGsdHome = process.env.GSD_HOME;
@@ -93,4 +93,20 @@ describe('register-hooks session_before_compact (#3696)', () => {
93
93
  'session_before_compact should not check isAutoPaused',
94
94
  );
95
95
  });
96
+
97
+ test('session_before_compact does not gate checkpointing to executing phase (#4258)', () => {
98
+ const compactIdx = registerHooksSrc.indexOf('session_before_compact');
99
+ assert.ok(compactIdx > -1, 'session_before_compact hook should exist');
100
+
101
+ const preCheckpointSection = registerHooksSrc.slice(
102
+ compactIdx,
103
+ registerHooksSrc.indexOf('const sliceDir', compactIdx),
104
+ );
105
+
106
+ const normalized = preCheckpointSection.replace(/\/\/.*$/gm, '');
107
+ assert.ok(
108
+ !/if\s*\(\s*state\.phase\s*!==\s*['"]executing['"]\s*\)\s*\{?\s*return\b/.test(normalized),
109
+ 'session_before_compact should not early-return on non-executing phases',
110
+ );
111
+ });
96
112
  });
@@ -103,6 +103,13 @@ test("classifyError detects Codex server_error from extracted message", () => {
103
103
  assert.ok("retryAfterMs" in result && result.retryAfterMs === 30_000);
104
104
  });
105
105
 
106
+ test("classifyError detects stream INTERNAL_ERROR received from peer as transient server", () => {
107
+ const result = classifyError("stream error: stream ID 75; INTERNAL_ERROR; received from peer");
108
+ assert.ok(isTransient(result));
109
+ assert.equal(result.kind, "server");
110
+ assert.ok("retryAfterMs" in result && result.retryAfterMs === 30_000);
111
+ });
112
+
106
113
  test("classifyError detects overloaded error", () => {
107
114
  const result = classifyError("overloaded_error: Overloaded");
108
115
  assert.ok(isTransient(result));