gsd-pi 2.78.0 → 2.78.1-dev.9d08d820b

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 (548) hide show
  1. package/README.md +59 -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/gsd/auto/loop.js +23 -0
  22. package/dist/resources/extensions/gsd/auto/phases.js +5 -13
  23. package/dist/resources/extensions/gsd/auto/run-unit.js +3 -1
  24. package/dist/resources/extensions/gsd/auto/session.js +5 -6
  25. package/dist/resources/extensions/gsd/auto-dashboard.js +3 -2
  26. package/dist/resources/extensions/gsd/auto-dispatch.js +18 -6
  27. package/dist/resources/extensions/gsd/auto-prompts.js +63 -2
  28. package/dist/resources/extensions/gsd/auto-recovery.js +43 -4
  29. package/dist/resources/extensions/gsd/auto-runtime-state.js +31 -0
  30. package/dist/resources/extensions/gsd/auto-start.js +1 -1
  31. package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -2
  32. package/dist/resources/extensions/gsd/auto-worktree.js +60 -13
  33. package/dist/resources/extensions/gsd/auto.js +14 -5
  34. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +14 -2
  35. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -5
  36. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
  37. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -4
  38. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +100 -31
  39. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +11 -6
  40. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +22 -0
  41. package/dist/resources/extensions/gsd/bootstrap/system-context.js +34 -8
  42. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +121 -3
  43. package/dist/resources/extensions/gsd/commands/catalog.js +69 -5
  44. package/dist/resources/extensions/gsd/commands/handlers/core.js +22 -1
  45. package/dist/resources/extensions/gsd/commands-config.js +3 -2
  46. package/dist/resources/extensions/gsd/commands-extensions.js +46 -3
  47. package/dist/resources/extensions/gsd/commands-handlers.js +3 -2
  48. package/dist/resources/extensions/gsd/commands-mcp-status.js +3 -1
  49. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +10 -1
  50. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
  51. package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -0
  52. package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
  53. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +39 -1
  54. package/dist/resources/extensions/gsd/error-classifier.js +1 -1
  55. package/dist/resources/extensions/gsd/forensics.js +10 -8
  56. package/dist/resources/extensions/gsd/git-service.js +12 -5
  57. package/dist/resources/extensions/gsd/gsd-db.js +11 -2
  58. package/dist/resources/extensions/gsd/guided-flow.js +25 -24
  59. package/dist/resources/extensions/gsd/home-dir.js +16 -0
  60. package/dist/resources/extensions/gsd/key-manager.js +2 -1
  61. package/dist/resources/extensions/gsd/memory-store.js +66 -31
  62. package/dist/resources/extensions/gsd/migrate/command.js +3 -2
  63. package/dist/resources/extensions/gsd/milestone-id-reservation.js +36 -0
  64. package/dist/resources/extensions/gsd/model-router.js +114 -9
  65. package/dist/resources/extensions/gsd/native-git-bridge.js +7 -1
  66. package/dist/resources/extensions/gsd/preferences-models.js +91 -15
  67. package/dist/resources/extensions/gsd/preferences-types.js +2 -0
  68. package/dist/resources/extensions/gsd/preferences-validation.js +32 -0
  69. package/dist/resources/extensions/gsd/preferences.js +5 -3
  70. package/dist/resources/extensions/gsd/prompt-loader.js +23 -12
  71. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +10 -0
  72. package/dist/resources/extensions/gsd/prompts/complete-slice.md +10 -0
  73. package/dist/resources/extensions/gsd/prompts/plan-slice.md +10 -0
  74. package/dist/resources/extensions/gsd/prompts/refine-slice.md +10 -0
  75. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +9 -3
  76. package/dist/resources/extensions/gsd/state.js +42 -0
  77. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
  78. package/dist/resources/extensions/gsd/tools/memory-tools.js +18 -1
  79. package/dist/resources/extensions/gsd/unit-context-manifest.js +29 -4
  80. package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
  81. package/dist/resources/extensions/gsd/watch/header-renderer.js +3 -1
  82. package/dist/resources/extensions/gsd/worktree-command.js +26 -46
  83. package/dist/resources/extensions/gsd/worktree-manager.js +20 -1
  84. package/dist/resources/extensions/gsd/worktree-resolver.js +4 -13
  85. package/dist/resources/extensions/gsd/worktree-root.js +124 -0
  86. package/dist/resources/extensions/gsd/worktree-session-state.js +33 -0
  87. package/dist/resources/extensions/gsd/worktree.js +4 -115
  88. package/dist/resources/extensions/mcp-client/index.js +6 -3
  89. package/dist/resources/extensions/ollama/index.js +15 -2
  90. package/dist/resources/extensions/ollama/model-capabilities.js +31 -0
  91. package/dist/resources/extensions/ollama/ollama-client.js +40 -4
  92. package/dist/resources/extensions/slash-commands/create-extension.js +36 -22
  93. package/dist/resources/extensions/subagent/index.js +324 -178
  94. package/dist/resources/skills/create-gsd-extension/SKILL.md +9 -5
  95. package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
  96. package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
  97. package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
  98. package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
  99. package/dist/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
  100. package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
  101. package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
  102. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
  103. package/dist/rtk-shared.d.ts +3 -0
  104. package/dist/rtk-shared.js +17 -0
  105. package/dist/rtk.d.ts +2 -5
  106. package/dist/rtk.js +3 -20
  107. package/dist/runtime-checks.d.ts +27 -0
  108. package/dist/runtime-checks.js +38 -0
  109. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  110. package/dist/web/standalone/.next/BUILD_ID +1 -1
  111. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  112. package/dist/web/standalone/.next/build-manifest.json +4 -4
  113. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  114. package/dist/web/standalone/.next/react-loadable-manifest.json +44 -4
  115. package/dist/web/standalone/.next/required-server-files.json +3 -3
  116. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  117. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  127. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  131. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  133. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  143. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  155. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  175. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  185. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/session/events/route.js +4 -2
  191. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  205. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  207. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  209. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  211. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  214. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  215. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  216. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  217. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  218. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  219. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  220. package/dist/web/standalone/.next/server/app/index.html +1 -1
  221. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  222. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  223. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  224. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  225. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  226. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  227. package/dist/web/standalone/.next/server/app/page.js +2 -2
  228. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  229. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  230. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  231. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  232. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  233. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  234. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  235. package/dist/web/standalone/.next/server/middleware.js +2 -2
  236. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  237. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  238. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  239. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  240. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  241. package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
  242. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +1 -0
  243. package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +1 -0
  244. package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +1 -0
  245. package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +1 -0
  246. package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +1 -0
  247. package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +1 -0
  248. package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +10 -0
  249. package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +2 -0
  250. package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +20 -0
  251. package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +1 -0
  252. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  253. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  254. package/dist/web/standalone/.next/static/chunks/app/page-9bf2e0c50fb2ca05.js +1 -0
  255. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  256. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  257. package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +1 -0
  258. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  259. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  260. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  261. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  262. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  263. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  264. package/dist/web/standalone/package.json +2 -1
  265. package/dist/web/standalone/server.js +1 -1
  266. package/dist/worktree-cli.d.ts +1 -0
  267. package/dist/worktree-cli.js +9 -3
  268. package/dist/worktree-status-banner.d.ts +1 -0
  269. package/dist/worktree-status-banner.js +132 -0
  270. package/package.json +1 -3
  271. package/packages/daemon/package.json +2 -2
  272. package/packages/mcp-server/dist/alias-telemetry.d.ts +8 -0
  273. package/packages/mcp-server/dist/alias-telemetry.d.ts.map +1 -0
  274. package/packages/mcp-server/dist/alias-telemetry.js +30 -0
  275. package/packages/mcp-server/dist/alias-telemetry.js.map +1 -0
  276. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  277. package/packages/mcp-server/dist/workflow-tools.js +74 -46
  278. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  279. package/packages/mcp-server/package.json +2 -2
  280. package/packages/mcp-server/src/alias-telemetry.test.ts +78 -0
  281. package/packages/mcp-server/src/alias-telemetry.ts +30 -0
  282. package/packages/mcp-server/src/workflow-tools.test.ts +78 -0
  283. package/packages/mcp-server/src/workflow-tools.ts +93 -58
  284. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  285. package/packages/native/package.json +1 -1
  286. package/packages/native/tsconfig.tsbuildinfo +1 -1
  287. package/packages/pi-agent-core/package.json +1 -1
  288. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  289. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts +2 -0
  290. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +1 -0
  291. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +231 -0
  292. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +1 -0
  293. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  294. package/packages/pi-ai/dist/providers/anthropic-shared.js +48 -19
  295. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  296. package/packages/pi-ai/dist/types.d.ts +13 -0
  297. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  298. package/packages/pi-ai/dist/types.js.map +1 -1
  299. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -1
  300. package/packages/pi-ai/dist/utils/repair-tool-json.js +24 -3
  301. package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -1
  302. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +26 -0
  303. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
  304. package/packages/pi-ai/package.json +1 -1
  305. package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +289 -0
  306. package/packages/pi-ai/src/providers/anthropic-shared.ts +52 -20
  307. package/packages/pi-ai/src/types.ts +13 -0
  308. package/packages/pi-ai/src/utils/repair-tool-json.ts +24 -3
  309. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +32 -0
  310. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  311. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  312. package/packages/pi-coding-agent/dist/core/agent-session.js +6 -0
  313. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  314. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  315. package/packages/pi-coding-agent/dist/core/messages.js +4 -0
  316. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  317. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +19 -2
  318. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  319. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +10 -0
  320. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  321. package/packages/pi-coding-agent/dist/core/model-registry.js +18 -0
  322. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  323. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +13 -0
  324. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  325. package/packages/pi-coding-agent/dist/core/system-prompt.js +20 -16
  326. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  327. package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +37 -0
  328. package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +1 -0
  329. package/packages/pi-coding-agent/dist/core/token-telemetry.js +49 -0
  330. package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +1 -0
  331. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +2 -0
  332. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +1 -0
  333. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +133 -0
  334. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -0
  335. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +1 -1
  336. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  337. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -1
  338. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  339. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +2 -0
  340. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +1 -0
  341. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +78 -0
  342. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +1 -0
  343. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +2 -0
  344. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +1 -0
  345. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +181 -0
  346. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +1 -0
  347. package/packages/pi-coding-agent/package.json +1 -1
  348. package/packages/pi-coding-agent/src/core/agent-session.ts +7 -0
  349. package/packages/pi-coding-agent/src/core/messages.ts +4 -0
  350. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +32 -2
  351. package/packages/pi-coding-agent/src/core/model-registry.ts +21 -0
  352. package/packages/pi-coding-agent/src/core/system-prompt.ts +33 -15
  353. package/packages/pi-coding-agent/src/core/token-telemetry.ts +77 -0
  354. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +212 -0
  355. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +17 -1
  356. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
  357. package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +102 -0
  358. package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +200 -0
  359. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  360. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +17 -3
  361. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  362. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +2 -0
  363. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +1 -0
  364. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +161 -0
  365. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +1 -0
  366. package/packages/pi-tui/package.json +1 -1
  367. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -3
  368. package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +219 -0
  369. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  370. package/packages/rpc-client/package.json +1 -1
  371. package/pkg/package.json +1 -1
  372. package/src/resources/extensions/claude-code-cli/readiness.ts +130 -30
  373. package/src/resources/extensions/gsd/auto/loop.ts +24 -2
  374. package/src/resources/extensions/gsd/auto/phases.ts +6 -14
  375. package/src/resources/extensions/gsd/auto/run-unit.ts +3 -1
  376. package/src/resources/extensions/gsd/auto/session.ts +5 -6
  377. package/src/resources/extensions/gsd/auto/types.ts +1 -0
  378. package/src/resources/extensions/gsd/auto-dashboard.ts +3 -2
  379. package/src/resources/extensions/gsd/auto-dispatch.ts +18 -6
  380. package/src/resources/extensions/gsd/auto-prompts.ts +60 -2
  381. package/src/resources/extensions/gsd/auto-recovery.ts +46 -8
  382. package/src/resources/extensions/gsd/auto-runtime-state.ts +51 -0
  383. package/src/resources/extensions/gsd/auto-start.ts +1 -1
  384. package/src/resources/extensions/gsd/auto-tool-tracking.ts +2 -4
  385. package/src/resources/extensions/gsd/auto-worktree.ts +82 -12
  386. package/src/resources/extensions/gsd/auto.ts +14 -4
  387. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +15 -13
  388. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +8 -7
  389. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
  390. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +10 -9
  391. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +108 -31
  392. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +12 -6
  393. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +20 -0
  394. package/src/resources/extensions/gsd/bootstrap/system-context.ts +39 -8
  395. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +141 -11
  396. package/src/resources/extensions/gsd/commands/catalog.ts +75 -5
  397. package/src/resources/extensions/gsd/commands/handlers/core.ts +22 -1
  398. package/src/resources/extensions/gsd/commands-config.ts +3 -2
  399. package/src/resources/extensions/gsd/commands-extensions.ts +43 -3
  400. package/src/resources/extensions/gsd/commands-handlers.ts +3 -2
  401. package/src/resources/extensions/gsd/commands-mcp-status.ts +3 -1
  402. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -1
  403. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
  404. package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -0
  405. package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
  406. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +39 -1
  407. package/src/resources/extensions/gsd/doctor-types.ts +3 -1
  408. package/src/resources/extensions/gsd/error-classifier.ts +1 -1
  409. package/src/resources/extensions/gsd/forensics.ts +12 -7
  410. package/src/resources/extensions/gsd/git-service.ts +13 -5
  411. package/src/resources/extensions/gsd/gsd-db.ts +12 -2
  412. package/src/resources/extensions/gsd/guided-flow.ts +27 -26
  413. package/src/resources/extensions/gsd/home-dir.ts +19 -0
  414. package/src/resources/extensions/gsd/journal.ts +4 -1
  415. package/src/resources/extensions/gsd/key-manager.ts +2 -1
  416. package/src/resources/extensions/gsd/memory-store.ts +81 -28
  417. package/src/resources/extensions/gsd/migrate/command.ts +3 -2
  418. package/src/resources/extensions/gsd/milestone-id-reservation.ts +47 -0
  419. package/src/resources/extensions/gsd/model-router.ts +172 -9
  420. package/src/resources/extensions/gsd/native-git-bridge.ts +7 -1
  421. package/src/resources/extensions/gsd/preferences-models.ts +101 -15
  422. package/src/resources/extensions/gsd/preferences-types.ts +6 -0
  423. package/src/resources/extensions/gsd/preferences-validation.ts +35 -0
  424. package/src/resources/extensions/gsd/preferences.ts +16 -2
  425. package/src/resources/extensions/gsd/prompt-loader.ts +26 -12
  426. package/src/resources/extensions/gsd/prompts/complete-milestone.md +10 -0
  427. package/src/resources/extensions/gsd/prompts/complete-slice.md +10 -0
  428. package/src/resources/extensions/gsd/prompts/plan-slice.md +10 -0
  429. package/src/resources/extensions/gsd/prompts/refine-slice.md +10 -0
  430. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +9 -3
  431. package/src/resources/extensions/gsd/state.ts +42 -0
  432. package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
  433. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +178 -1
  434. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +58 -0
  435. package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +24 -5
  436. package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +21 -4
  437. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +1 -1
  438. package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +138 -211
  439. package/src/resources/extensions/gsd/tests/commands-extensions-version-compare.test.ts +58 -0
  440. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +142 -59
  441. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +7 -4
  442. package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +89 -32
  443. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +41 -23
  444. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +3 -43
  445. package/src/resources/extensions/gsd/tests/debug-logger.test.ts +5 -3
  446. package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +116 -0
  447. package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +22 -87
  448. package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +7 -118
  449. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +18 -60
  450. package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +100 -0
  451. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +14 -76
  452. package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +93 -0
  453. package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +22 -83
  454. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +1 -63
  455. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +47 -0
  456. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +26 -1
  457. package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +63 -0
  458. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +30 -0
  459. package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +81 -0
  460. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +14 -4
  461. package/src/resources/extensions/gsd/tests/health-widget.test.ts +22 -12
  462. package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +57 -0
  463. package/src/resources/extensions/gsd/tests/home-dir.test.ts +52 -0
  464. package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +145 -0
  465. package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +64 -1
  466. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +72 -1
  467. package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +0 -23
  468. package/src/resources/extensions/gsd/tests/memory-store.test.ts +128 -0
  469. package/src/resources/extensions/gsd/tests/memory-tools.test.ts +33 -1
  470. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +124 -0
  471. package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +152 -0
  472. package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +18 -1
  473. package/src/resources/extensions/gsd/tests/model-router.test.ts +169 -8
  474. package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +50 -0
  475. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +8 -0
  476. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +32 -43
  477. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +4 -10
  478. package/src/resources/extensions/gsd/tests/preferences.test.ts +127 -0
  479. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +16 -0
  480. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
  481. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
  482. package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +93 -0
  483. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +168 -19
  484. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +7 -1
  485. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +23 -1
  486. package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +17 -1
  487. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +101 -0
  488. package/src/resources/extensions/gsd/tests/token-profile.test.ts +51 -4
  489. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +7 -16
  490. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +38 -3
  491. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -7
  492. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +15 -1
  493. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
  494. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +34 -33
  495. package/src/resources/extensions/gsd/tests/worktree.test.ts +8 -0
  496. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +131 -1
  497. package/src/resources/extensions/gsd/tools/memory-tools.ts +17 -1
  498. package/src/resources/extensions/gsd/unit-context-manifest.ts +44 -12
  499. package/src/resources/extensions/gsd/visualizer-overlay.ts +1 -1
  500. package/src/resources/extensions/gsd/watch/header-renderer.ts +3 -1
  501. package/src/resources/extensions/gsd/workflow-logger.ts +1 -0
  502. package/src/resources/extensions/gsd/worktree-command.ts +31 -44
  503. package/src/resources/extensions/gsd/worktree-manager.ts +40 -1
  504. package/src/resources/extensions/gsd/worktree-resolver.ts +4 -14
  505. package/src/resources/extensions/gsd/worktree-root.ts +144 -0
  506. package/src/resources/extensions/gsd/worktree-session-state.ts +35 -0
  507. package/src/resources/extensions/gsd/worktree.ts +8 -119
  508. package/src/resources/extensions/mcp-client/index.ts +6 -3
  509. package/src/resources/extensions/mcp-client/tests/global-config.test.ts +91 -0
  510. package/src/resources/extensions/ollama/index.ts +16 -2
  511. package/src/resources/extensions/ollama/model-capabilities.ts +34 -0
  512. package/src/resources/extensions/ollama/ollama-client.ts +41 -4
  513. package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +96 -0
  514. package/src/resources/extensions/ollama/tests/ollama-client-timeout-env.test.ts +147 -0
  515. package/src/resources/extensions/slash-commands/create-extension.ts +38 -24
  516. package/src/resources/extensions/subagent/index.ts +165 -7
  517. package/src/resources/skills/create-gsd-extension/SKILL.md +9 -5
  518. package/src/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
  519. package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
  520. package/src/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
  521. package/src/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
  522. package/src/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
  523. package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
  524. package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
  525. package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +2 -2
  526. package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +3 -3
  527. package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +58 -0
  528. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
  529. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +0 -601
  530. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +0 -651
  531. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +0 -91
  532. package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +0 -53
  533. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +0 -112
  534. package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +0 -23
  535. package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +0 -5
  536. package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
  537. package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +0 -608
  538. package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +0 -11
  539. package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +0 -20
  540. package/dist/web/standalone/.next/static/chunks/app/page-151349214571e2b6.js +0 -1
  541. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  542. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  543. package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.js +0 -1
  544. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +0 -22
  545. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +0 -47
  546. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +0 -75
  547. /package/dist/web/standalone/.next/static/{C1zT2kEfoLhDdbWPWKrXd → -Ukk6_YxRd4GY4iUOnRUE}/_buildManifest.js +0 -0
  548. /package/dist/web/standalone/.next/static/{C1zT2kEfoLhDdbWPWKrXd → -Ukk6_YxRd4GY4iUOnRUE}/_ssgManifest.js +0 -0
@@ -7,20 +7,20 @@
7
7
  *
8
8
  * Testing strategy:
9
9
  * 1. Source-code regression guards: structural checks on register-hooks.ts.
10
- * 2. Behavioral integration test: fires the live session_start handler with a
11
- * fake ctx when isAutoActive() is false (default) and confirms neither
12
- * setFooter nor setWidget("gsd-health") is called.
10
+ * 2. Behavioral integration tests: fire the live session handlers with fake
11
+ * contexts and confirm footer/widget behavior from runtime effects.
13
12
  *
14
13
  * Relates to #4314.
15
14
  */
16
15
 
17
16
  import test from "node:test";
18
17
  import assert from "node:assert/strict";
19
- import { mkdirSync, readFileSync, rmSync } from "node:fs";
18
+ import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
20
19
  import { join, dirname } from "node:path";
21
20
  import { tmpdir } from "node:os";
22
21
  import { fileURLToPath } from "node:url";
23
22
 
23
+ import { autoSession } from "../auto-runtime-state.ts";
24
24
  import { registerHooks } from "../bootstrap/register-hooks.ts";
25
25
 
26
26
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -68,27 +68,89 @@ test("session_start handler guards initHealthWidget with !isAutoActive()", () =>
68
68
  );
69
69
  });
70
70
 
71
- test("session_switch handler suppresses gsd-health when isAutoActive()", () => {
72
- const sessionSwitchIdx = HOOKS_SOURCE.indexOf('"session_switch"');
73
- assert.ok(sessionSwitchIdx > -1, "session_switch handler must exist");
71
+ test("session_switch toggles gsd-health from runtime auto state without touching the footer", async (t) => {
72
+ const dir = join(
73
+ tmpdir(),
74
+ `gsd-session-switch-widget-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
75
+ );
76
+ mkdirSync(join(dir, ".gsd"), { recursive: true });
77
+ const tempGsdHome = join(dir, "home");
78
+ mkdirSync(tempGsdHome, { recursive: true });
74
79
 
75
- const beforeAgentStartIdx = HOOKS_SOURCE.indexOf('"before_agent_start"');
76
- assert.ok(beforeAgentStartIdx > sessionSwitchIdx, "before_agent_start handler must follow session_switch");
80
+ const originalCwd = process.cwd();
81
+ const originalGsdHome = process.env.GSD_HOME;
82
+ process.env.GSD_HOME = tempGsdHome;
83
+ process.chdir(dir);
84
+ autoSession.reset();
85
+ t.after(() => {
86
+ autoSession.reset();
87
+ process.chdir(originalCwd);
88
+ if (originalGsdHome === undefined) delete process.env.GSD_HOME;
89
+ else process.env.GSD_HOME = originalGsdHome;
90
+ try { rmSync(dir, { recursive: true, force: true }); } catch { /* best-effort */ }
91
+ });
77
92
 
78
- const sessionSwitchBody = HOOKS_SOURCE.slice(sessionSwitchIdx, beforeAgentStartIdx);
93
+ const handlers = new Map<string, (event: unknown, ctx: any) => Promise<void> | void>();
94
+ const pi = {
95
+ on(event: string, handler: (event: unknown, ctx: any) => Promise<void> | void) {
96
+ handlers.set(event, handler);
97
+ },
98
+ } as any;
79
99
 
80
- assert.ok(
81
- sessionSwitchBody.includes("isAutoActive()"),
82
- "session_switch handler must call isAutoActive()",
83
- );
84
- assert.ok(
85
- sessionSwitchBody.includes('setWidget("gsd-health", undefined)'),
86
- "session_switch handler must call setWidget(\"gsd-health\", undefined) when auto is active",
100
+ registerHooks(pi, []);
101
+
102
+ const sessionSwitch = handlers.get("session_switch");
103
+ assert.ok(sessionSwitch, "session_switch handler must be registered");
104
+
105
+ let setFooterCallCount = 0;
106
+ const widgetCalls: Array<{ key: string; value: unknown }> = [];
107
+ const ctx = {
108
+ hasUI: true,
109
+ ui: {
110
+ notify: () => {},
111
+ setStatus: () => {},
112
+ setFooter: (_footer: unknown) => {
113
+ setFooterCallCount++;
114
+ },
115
+ setWorkingMessage: () => {},
116
+ onTerminalInput: () => () => {},
117
+ setWidget: (key: string, value: unknown) => {
118
+ widgetCalls.push({ key, value });
119
+ },
120
+ },
121
+ sessionManager: { getSessionId: () => null },
122
+ model: null,
123
+ modelRegistry: {
124
+ setDisabledModelProviders: () => {},
125
+ getProviderAuthMode: () => undefined,
126
+ isProviderRequestReady: () => false,
127
+ },
128
+ };
129
+
130
+ autoSession.active = true;
131
+ await sessionSwitch!({ reason: "resume" }, ctx);
132
+ assert.deepEqual(
133
+ widgetCalls.filter((call) => call.key === "gsd-health").map((call) => call.value),
134
+ [undefined],
135
+ "session_switch should hide gsd-health when auto is active",
87
136
  );
137
+ assert.equal(setFooterCallCount, 0, "session_switch must not call setFooter when auto is active");
138
+
139
+ widgetCalls.length = 0;
140
+ autoSession.active = false;
141
+ await sessionSwitch!({ reason: "resume" }, ctx);
142
+ const healthWidgetValues = widgetCalls
143
+ .filter((call) => call.key === "gsd-health")
144
+ .map((call) => call.value);
145
+
146
+ assert.ok(healthWidgetValues.length >= 2, "session_switch should initialize gsd-health when auto is inactive");
88
147
  assert.ok(
89
- !sessionSwitchBody.includes("setFooter"),
90
- "session_switch handler must NOT call setFooter",
148
+ healthWidgetValues.every((value) => value !== undefined),
149
+ "session_switch must not hide gsd-health when auto is inactive",
91
150
  );
151
+ assert.ok(Array.isArray(healthWidgetValues[0]), "initHealthWidget should publish initial health lines");
152
+ assert.equal(typeof healthWidgetValues.at(-1), "function", "initHealthWidget should register the live widget factory");
153
+ assert.equal(setFooterCallCount, 0, "session_switch must not call setFooter when auto is inactive");
92
154
  });
93
155
 
94
156
  // ─── Behavioral test: neither setFooter nor health suppression when auto inactive ─
@@ -143,3 +205,90 @@ test("session_start does NOT call setFooter or suppress gsd-health when isAutoAc
143
205
  assert.equal(setFooterCallCount, 0, "setFooter must NOT be called when isAutoActive() is false");
144
206
  assert.equal(healthWidgetHideCount, 0, "gsd-health must NOT be hidden when isAutoActive() is false");
145
207
  });
208
+
209
+ test("session_start and session_switch apply disabled model provider policy from current preferences", async (t) => {
210
+ const dir = join(
211
+ tmpdir(),
212
+ `gsd-disabled-provider-policy-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
213
+ );
214
+ mkdirSync(join(dir, ".gsd"), { recursive: true });
215
+ const tempGsdHome = join(dir, "home");
216
+ mkdirSync(tempGsdHome, { recursive: true });
217
+
218
+ const originalCwd = process.cwd();
219
+ const originalGsdHome = process.env.GSD_HOME;
220
+ process.env.GSD_HOME = tempGsdHome;
221
+ process.chdir(dir);
222
+ t.after(() => {
223
+ process.chdir(originalCwd);
224
+ if (originalGsdHome === undefined) delete process.env.GSD_HOME;
225
+ else process.env.GSD_HOME = originalGsdHome;
226
+ try { rmSync(dir, { recursive: true, force: true }); } catch { /* best-effort */ }
227
+ });
228
+
229
+ const writePrefs = (providers: string[]) => {
230
+ writeFileSync(
231
+ join(dir, ".gsd", "PREFERENCES.md"),
232
+ [
233
+ "---",
234
+ "version: 1",
235
+ "disabled_model_providers:",
236
+ ...providers.map((provider) => ` - ${provider}`),
237
+ "---",
238
+ "",
239
+ ].join("\n"),
240
+ "utf-8",
241
+ );
242
+ };
243
+
244
+ const appliedPolicies: string[][] = [];
245
+ const handlers = new Map<string, (event: unknown, ctx: any) => Promise<void> | void>();
246
+ const pi = {
247
+ on(event: string, handler: (event: unknown, ctx: any) => Promise<void> | void) {
248
+ handlers.set(event, handler);
249
+ },
250
+ } as any;
251
+ const ctx = {
252
+ hasUI: true,
253
+ ui: {
254
+ notify: () => {},
255
+ setStatus: () => {},
256
+ setFooter: () => {},
257
+ setWorkingMessage: () => {},
258
+ onTerminalInput: () => () => {},
259
+ setWidget: () => {},
260
+ },
261
+ sessionManager: { getSessionId: () => null },
262
+ model: null,
263
+ modelRegistry: {
264
+ setDisabledModelProviders: (providers: string[]) => {
265
+ appliedPolicies.push([...providers]);
266
+ },
267
+ getProviderAuthMode: () => undefined,
268
+ isProviderRequestReady: () => false,
269
+ },
270
+ };
271
+
272
+ registerHooks(pi, []);
273
+
274
+ const sessionStart = handlers.get("session_start");
275
+ const sessionSwitch = handlers.get("session_switch");
276
+ assert.ok(sessionStart, "session_start handler must be registered");
277
+ assert.ok(sessionSwitch, "session_switch handler must be registered");
278
+
279
+ writePrefs(["google-gemini-cli", " google-gemini-cli ", "openai-codex"]);
280
+ await sessionStart!({}, ctx);
281
+ assert.deepEqual(
282
+ appliedPolicies.at(-1),
283
+ ["google-gemini-cli", "openai-codex"],
284
+ "session_start should apply normalized disabled providers before the first agent turn",
285
+ );
286
+
287
+ writePrefs(["anthropic"]);
288
+ await sessionSwitch!({ reason: "resume" }, ctx);
289
+ assert.deepEqual(
290
+ appliedPolicies.at(-1),
291
+ ["anthropic"],
292
+ "session_switch should re-read preferences for the switched project/session context",
293
+ );
294
+ });
@@ -11,7 +11,7 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync
11
11
  import { join, dirname } from "node:path";
12
12
  import { tmpdir } from "node:os";
13
13
  import { fileURLToPath } from "node:url";
14
- import { restoreSliceState } from "../slice-parallel-orchestrator.ts";
14
+ import { restoreSliceState, SLICE_WORKER_AUTO_ARGS } from "../slice-parallel-orchestrator.ts";
15
15
 
16
16
  const __dirname = dirname(fileURLToPath(import.meta.url));
17
17
  const gsdDir = join(__dirname, "..");
@@ -100,6 +100,12 @@ describe("slice-parallel-orchestrator structural tests", () => {
100
100
  );
101
101
  });
102
102
 
103
+ it("slice workers use headless auto instead of print-mode slash commands", () => {
104
+ const args: readonly string[] = SLICE_WORKER_AUTO_ARGS;
105
+ assert.deepEqual([...args], ["headless", "--json", "auto"]);
106
+ assert.equal(args.includes("--print"), false);
107
+ });
108
+
103
109
  it("maxWorkers default is 2", () => {
104
110
  const source = readFileSync(join(gsdDir, "slice-parallel-orchestrator.ts"), "utf-8");
105
111
  // Check that default max workers is 2 (in opts.maxWorkers ?? 2 or similar)
@@ -48,6 +48,28 @@ test("guided-flow complete branch offers a chooser for next milestone or status"
48
48
 
49
49
  assert.match(branchChunk, /showNextAction\(/, "complete branch should present a chooser");
50
50
  assert.match(branchChunk, /findMilestoneIds\(basePath\)/, "complete branch should compute the next milestone id");
51
- assert.match(branchChunk, /nextMilestoneId(?:Reserved)?\(milestoneIds, uniqueMilestoneIds\)/, "complete branch should derive the next milestone id");
51
+ assert.match(
52
+ branchChunk,
53
+ /nextMilestoneIdReserved\(milestoneIds,\s*uniqueMilestoneIds,\s*basePath\)/,
54
+ "complete branch should derive the next milestone id",
55
+ );
52
56
  assert.match(branchChunk, /dispatchWorkflow\(pi, await prepareAndBuildDiscussPrompt\(/, "complete branch should dispatch the prepared discuss prompt");
53
57
  });
58
+
59
+ test("guided-flow needs-discussion skip branch opens the project DB before reserving a new milestone", () => {
60
+ const guidedFlowSource = readFileSync(join(import.meta.dirname, "..", "guided-flow.ts"), "utf-8");
61
+ const laterDbOpenIdx = guidedFlowSource.indexOf("// Ensure DB is open before querying slices (#2560).");
62
+ assert.ok(laterDbOpenIdx > -1, "guided-flow.ts should contain the post-draft DB-open guard");
63
+
64
+ const branchPrefix = guidedFlowSource.slice(0, laterDbOpenIdx);
65
+ const skipBranchIdx = branchPrefix.lastIndexOf('choice === "skip_milestone"');
66
+ assert.ok(skipBranchIdx > -1, "needs-discussion skip branch should be present");
67
+
68
+ const branchChunk = branchPrefix.slice(skipBranchIdx);
69
+ const ensureIdx = branchChunk.indexOf("ensureDbOpen(basePath)");
70
+ const reserveIdx = branchChunk.indexOf("nextMilestoneIdReserved");
71
+
72
+ assert.ok(ensureIdx > -1, "skip branch should open the project DB");
73
+ assert.ok(reserveIdx > -1, "skip branch should reserve the next milestone ID");
74
+ assert.ok(ensureIdx < reserveIdx, "project DB must be opened before milestone ID reservation");
75
+ });
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { describe, test, beforeEach, afterEach } from "node:test";
6
6
  import assert from "node:assert/strict";
7
- import { mkdtempSync, mkdirSync, existsSync, readFileSync, rmSync } from "node:fs";
7
+ import { mkdtempSync, mkdirSync, existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
8
8
  import { join } from "node:path";
9
9
  import { tmpdir } from "node:os";
10
10
  import { appendOverride, loadActiveOverrides } from "../files.ts";
@@ -73,6 +73,22 @@ describe("steer worktree path resolution (#3476)", () => {
73
73
  assert.equal(result, null, "returns null for worktree without .git file");
74
74
  });
75
75
 
76
+ test("getAutoWorktreePath returns null when .git is a directory", () => {
77
+ mkdirSync(join(worktreePath, ".git"), { recursive: true });
78
+
79
+ const result = getAutoWorktreePath(projectRoot, "M001");
80
+
81
+ assert.equal(result, null, "returns null for standalone .git directories");
82
+ });
83
+
84
+ test("getAutoWorktreePath returns null when .git file is not a gitdir pointer", () => {
85
+ writeFileSync(join(worktreePath, ".git"), "not-a-gitdir\n", "utf-8");
86
+
87
+ const result = getAutoWorktreePath(projectRoot, "M001");
88
+
89
+ assert.equal(result, null, "returns null for invalid .git files");
90
+ });
91
+
76
92
  test("override routing: inactive worktree directory should not receive overrides", async () => {
77
93
  // Simulate the handleSteer path-resolution logic:
78
94
  // When no auto-mode is running, even if a worktree dir exists,
@@ -0,0 +1,101 @@
1
+ // GSD bootstrap + system-context-message-routing.test — regression coverage
2
+ // for #5019. `memoryBlock` is FTS-queried against the user prompt and changes
3
+ // per call; embedding it in the cached system prefix invalidates Anthropic
4
+ // prompt-cache hits on every request. The fix routes memory through the
5
+ // existing context-message channel (volatile user-message suffix) and combines
6
+ // it with any active guided-execute or forensics injection.
7
+
8
+ import { describe, test } from "node:test";
9
+ import assert from "node:assert/strict";
10
+
11
+ import { buildContextMessage } from "../bootstrap/system-context.ts";
12
+
13
+ describe("buildContextMessage (#5019 — memory routing)", () => {
14
+ test("returns null when nothing to inject", () => {
15
+ const result = buildContextMessage({
16
+ memoryBlock: "",
17
+ injection: null,
18
+ forensicsInjection: null,
19
+ });
20
+ assert.equal(result, null);
21
+ });
22
+
23
+ test("whitespace-only memoryBlock counts as empty", () => {
24
+ const result = buildContextMessage({
25
+ memoryBlock: " \n\n ",
26
+ injection: null,
27
+ forensicsInjection: null,
28
+ });
29
+ assert.equal(result, null);
30
+ });
31
+
32
+ test("memory-only path emits gsd-memory message with trimmed content", () => {
33
+ const result = buildContextMessage({
34
+ memoryBlock: "\n\n[MEMORY]\nrule one\nrule two\n\n",
35
+ injection: null,
36
+ forensicsInjection: null,
37
+ });
38
+ assert.ok(result, "expected a context message");
39
+ assert.equal(result.customType, "gsd-memory");
40
+ assert.equal(result.content, "[MEMORY]\nrule one\nrule two");
41
+ assert.equal(result.display, false);
42
+ });
43
+
44
+ test("guided-execute injection alone emits gsd-guided-context", () => {
45
+ const result = buildContextMessage({
46
+ memoryBlock: "",
47
+ injection: "[GUIDED]\nexecute T01",
48
+ forensicsInjection: null,
49
+ });
50
+ assert.ok(result);
51
+ assert.equal(result.customType, "gsd-guided-context");
52
+ assert.equal(result.content, "[GUIDED]\nexecute T01");
53
+ });
54
+
55
+ test("forensics injection alone emits gsd-forensics", () => {
56
+ const result = buildContextMessage({
57
+ memoryBlock: "",
58
+ injection: null,
59
+ forensicsInjection: "[FORENSICS]\ninvestigation context",
60
+ });
61
+ assert.ok(result);
62
+ assert.equal(result.customType, "gsd-forensics");
63
+ assert.equal(result.content, "[FORENSICS]\ninvestigation context");
64
+ });
65
+
66
+ test("memory + guided injection: memory prepended, customType is gsd-guided-context", () => {
67
+ const result = buildContextMessage({
68
+ memoryBlock: "[MEMORY]\nrule one",
69
+ injection: "[GUIDED]\nexecute T01",
70
+ forensicsInjection: null,
71
+ });
72
+ assert.ok(result);
73
+ assert.equal(result.customType, "gsd-guided-context");
74
+ assert.equal(result.content, "[MEMORY]\nrule one\n\n[GUIDED]\nexecute T01");
75
+ });
76
+
77
+ test("memory + forensics: memory prepended, customType is gsd-forensics", () => {
78
+ const result = buildContextMessage({
79
+ memoryBlock: "[MEMORY]\nrule one",
80
+ injection: null,
81
+ forensicsInjection: "[FORENSICS]\ninvestigation context",
82
+ });
83
+ assert.ok(result);
84
+ assert.equal(result.customType, "gsd-forensics");
85
+ assert.equal(result.content, "[MEMORY]\nrule one\n\n[FORENSICS]\ninvestigation context");
86
+ });
87
+
88
+ test("guided takes precedence over forensics when both are somehow present", () => {
89
+ // The caller in buildBeforeAgentStartResult already gates forensics on
90
+ // `!injection`, but the helper's documented priority is guided > forensics.
91
+ // Test the contract directly so a future refactor can't silently flip it.
92
+ const result = buildContextMessage({
93
+ memoryBlock: "",
94
+ injection: "[GUIDED]",
95
+ forensicsInjection: "[FORENSICS]",
96
+ });
97
+ assert.ok(result);
98
+ assert.equal(result.customType, "gsd-guided-context");
99
+ assert.equal(result.content, "[GUIDED]");
100
+ });
101
+ });
@@ -107,6 +107,50 @@ test("profile: resolveProfileDefaults exists and handles all 4 tiers", () => {
107
107
  );
108
108
  });
109
109
 
110
+ test("profile: PROFILE_TIER_MAP defines tier intentions for all profiles", async () => {
111
+ const { getProfileTierMap } = await import("../preferences-models.ts");
112
+ const profileMaps = {
113
+ budget: getProfileTierMap("budget"),
114
+ balanced: getProfileTierMap("balanced"),
115
+ quality: getProfileTierMap("quality"),
116
+ };
117
+
118
+ assert.deepEqual(
119
+ Object.keys(profileMaps).sort(),
120
+ ["balanced", "budget", "quality"],
121
+ "PROFILE_TIER_MAP should include the profile default tiers",
122
+ );
123
+
124
+ const expectedPhaseKeys = ["completion", "execution", "execution_simple", "planning", "research", "subagent"];
125
+ const validTiers = new Set(["light", "standard", "heavy"]);
126
+ for (const [profile, tierMap] of Object.entries(profileMaps)) {
127
+ assert.deepEqual(
128
+ Object.keys(tierMap).sort(),
129
+ expectedPhaseKeys,
130
+ `${profile} should define all model-bearing phases`,
131
+ );
132
+ for (const [phase, tier] of Object.entries(tierMap)) {
133
+ assert.ok(validTiers.has(tier), `${profile}.${phase} should be a tier name`);
134
+ assert.ok(!tier.includes("claude-"), `${profile}.${phase} should not be a model ID`);
135
+ }
136
+ }
137
+ });
138
+
139
+ test("profile: resolveProfileDefaults is provider-agnostic — picks OpenAI when only OpenAI is available", async () => {
140
+ // Behavioral check: with only OpenAI models in the available list, no slot
141
+ // should resolve to a claude-* model. Source-grep cannot prove this — only
142
+ // exercising the function with a controlled available-model list can.
143
+ const { resolveProfileDefaults } = await import("../preferences-models.ts");
144
+ const defaults = resolveProfileDefaults("balanced", ["gpt-4o", "gpt-4o-mini"]);
145
+ assert.ok(defaults.models, "balanced profile should populate models");
146
+ for (const [phase, modelId] of Object.entries(defaults.models!)) {
147
+ assert.ok(
148
+ typeof modelId === "string" && !String(modelId).startsWith("claude-"),
149
+ `${phase} resolved to ${modelId} but only OpenAI is available`,
150
+ );
151
+ }
152
+ });
153
+
110
154
  test("profile: budget profile sets phase skips to true", () => {
111
155
  // Extract the budget case block
112
156
  const budgetIdx = preferencesSrc.indexOf('case "budget":');
@@ -222,11 +266,14 @@ test("merge: mergePreferences handles phases with spread", () => {
222
266
  // Subagent Model Routing
223
267
  // ═══════════════════════════════════════════════════════════════════════════
224
268
 
225
- test("subagent: budget profile sets subagent model", () => {
226
- const budgetIdx = preferencesSrc.indexOf('case "budget":');
227
- const balancedIdx = preferencesSrc.indexOf('case "balanced":');
269
+ test("subagent: budget profile assigns light tier for subagent", () => {
270
+ // PROFILE_TIER_MAP.budget.subagent should be "light"
271
+ const tierMapIdx = preferencesSrc.indexOf("PROFILE_TIER_MAP");
272
+ const budgetIdx = preferencesSrc.indexOf("budget:", tierMapIdx);
273
+ const balancedIdx = preferencesSrc.indexOf("balanced:", tierMapIdx);
228
274
  const budgetBlock = preferencesSrc.slice(budgetIdx, balancedIdx);
229
- assert.ok(budgetBlock.includes("subagent:"), "budget profile should set subagent model");
275
+ assert.ok(budgetBlock.includes("subagent:"), "budget profile should define subagent tier");
276
+ assert.ok(budgetBlock.includes('"light"'), "budget subagent should use light tier");
230
277
  });
231
278
 
232
279
  test("subagent: resolveModelWithFallbacksForUnit handles subagent unit types", () => {
@@ -144,19 +144,10 @@ test("recoverTimedOutUnit: no top-level bumpTurnGeneration — steering branches
144
144
  );
145
145
  });
146
146
 
147
- test("recoverTimedOutUnit: bumpAndResolveSynthetic appears exactly four times (one per advance branch)", async () => {
148
- const fs = await import("node:fs");
149
- const path = await import("node:path");
150
- const url = await import("node:url");
151
- const here = path.dirname(url.fileURLToPath(import.meta.url));
152
- const src = fs.readFileSync(
153
- path.join(here, "..", "auto-timeout-recovery.ts"),
154
- "utf-8",
155
- );
156
- const matches = src.match(/bumpAndResolveSynthetic\s*\(/g) ?? [];
157
- assert.equal(
158
- matches.length,
159
- 4,
160
- `expected 4 advance-branch supersede sites (durableComplete, execute-task-exhausted, artifact-already-exists, non-execute-exhausted); found ${matches.length}`,
161
- );
162
- });
147
+ // Removed: source-grep count of `bumpAndResolveSynthetic\s*\(` occurrences.
148
+ // A literal 4 hardcodes the current branch shape, not behaviour. The
149
+ // behavioural invariant "advance branches supersede atomically; non-advance
150
+ // branches do not bump" — is enforced by the previous test (no direct
151
+ // bumpTurnGeneration calls) plus the per-branch behavioural tests above
152
+ // (`recoverTimedOutUnit: …`). Refactors that split a branch into two would
153
+ // trip a count test without affecting correctness. Refs #4851.
@@ -199,8 +199,8 @@ test("#4934: every manifest declares a tools policy", () => {
199
199
  }
200
200
  });
201
201
 
202
- test("#4934: tools.mode is one of the four declared policies", () => {
203
- const validModes = new Set(["all", "read-only", "planning", "docs"]);
202
+ test("#4934: tools.mode is one of the declared policies", () => {
203
+ const validModes = new Set(["all", "read-only", "planning", "planning-dispatch", "docs"]);
204
204
  for (const [unitType, manifest] of Object.entries(UNIT_MANIFESTS)) {
205
205
  const mode = (manifest as { tools: { mode: string } }).tools.mode;
206
206
  assert.ok(
@@ -219,7 +219,42 @@ test('#4934: only execute-task and reactive-execute may use tools.mode "all" (fu
219
219
  allowedAllUnits.has(unitType),
220
220
  `manifest "${unitType}" declares tools.mode = "all" but is not on the execute-track. ` +
221
221
  'Only execute-task and reactive-execute should have full source write access; ' +
222
- 'planning/discuss/research units must use "planning" (or "docs" for rewrite-docs).',
222
+ 'planning/discuss/research units must use "planning" or "planning-dispatch" (or "docs" for rewrite-docs).',
223
+ );
224
+ }
225
+ }
226
+ });
227
+
228
+ test('planning-dispatch mode is reserved for slice-level decomposition and completion units', () => {
229
+ const allowedDispatchUnits = new Set([
230
+ "plan-slice",
231
+ "refine-slice",
232
+ "complete-slice",
233
+ "complete-milestone",
234
+ ]);
235
+ for (const [unitType, manifest] of Object.entries(UNIT_MANIFESTS)) {
236
+ const mode = (manifest as { tools: { mode: string } }).tools.mode;
237
+ if (mode === "planning-dispatch") {
238
+ assert.ok(
239
+ allowedDispatchUnits.has(unitType),
240
+ `manifest "${unitType}" declares tools.mode = "planning-dispatch" but is not on the dispatch-allowed allowlist. ` +
241
+ 'planning-dispatch is intentionally narrow — extend the allowlist consciously when a new unit type genuinely benefits from subagent delegation.',
242
+ );
243
+ }
244
+ }
245
+ });
246
+
247
+ test('planning-dispatch manifests declare non-empty allowedSubagents lists', () => {
248
+ for (const [unitType, manifest] of Object.entries(UNIT_MANIFESTS)) {
249
+ if (manifest.tools.mode !== "planning-dispatch") continue;
250
+ assert.ok(
251
+ Array.isArray(manifest.tools.allowedSubagents) && manifest.tools.allowedSubagents.length > 0,
252
+ `manifest "${unitType}" has planning-dispatch policy but no allowedSubagents — explicit allowlist is required for runtime dispatch gating`,
253
+ );
254
+ for (const agent of manifest.tools.allowedSubagents) {
255
+ assert.ok(
256
+ typeof agent === "string" && agent.length > 0,
257
+ `manifest "${unitType}" has empty/invalid allowedSubagents entry: ${JSON.stringify(agent)}`,
223
258
  );
224
259
  }
225
260
  }
@@ -76,13 +76,11 @@ describe("#3615 — structural: fallback exists with correct guards", () => {
76
76
  );
77
77
  });
78
78
 
79
- test("only one return null at the end", () => {
80
- const returnNulls = fnBody.match(/return null;/g);
81
- assert.ok(
82
- returnNulls && returnNulls.length === 1,
83
- `expected exactly 1 'return null' (at end after fallback), got ${returnNulls?.length ?? 0}`,
84
- );
85
- });
79
+ // Removed: source-grep count of `return null;` occurrences. The behaviour
80
+ // we care about ("function returns null only when no auto-dispatch /
81
+ // guided-resume / fallback path matches") is exercised by the behavioural
82
+ // tests below counting literal `return null;` tokens encodes statement
83
+ // shape, not contract. Refs #4851.
86
84
  });
87
85
 
88
86
  // ── Behavioral tests: RESUME_INTENT_PATTERNS ────────────────────────
@@ -4,7 +4,7 @@ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { tmpdir } from "node:os";
5
5
  import { join } from "node:path";
6
6
  import { execSync } from "node:child_process";
7
- import { runTurnGitAction } from "../git-service.ts";
7
+ import { handleTurnGitActionError, runTurnGitAction } from "../git-service.ts";
8
8
 
9
9
  function run(cmd: string, cwd: string): string {
10
10
  return execSync(cmd, { cwd, stdio: "pipe", encoding: "utf-8" }).trim();
@@ -83,3 +83,17 @@ test("uok gitops turn action commit creates commit with unit trailer", () => {
83
83
  rmSync(repo, { recursive: true, force: true });
84
84
  }
85
85
  });
86
+
87
+ test("uok gitops turn action rethrows infrastructure failures", () => {
88
+ const err = Object.assign(new Error("ENFILE: file table overflow"), { code: "ENFILE" });
89
+
90
+ assert.throws(() => handleTurnGitActionError("commit", err), (thrown) => thrown === err);
91
+ });
92
+
93
+ test("uok gitops turn action keeps non-infrastructure git failures recoverable", () => {
94
+ const result = handleTurnGitActionError("commit", new Error("nothing to commit"));
95
+
96
+ assert.equal(result.action, "commit");
97
+ assert.equal(result.status, "failed");
98
+ assert.equal(result.error, "nothing to commit");
99
+ });
@@ -13,7 +13,7 @@
13
13
  import { test } from "node:test";
14
14
  import assert from "node:assert/strict";
15
15
 
16
- import { GSDVisualizerOverlay } from "../visualizer-overlay.ts";
16
+ import { GSDVisualizerOverlay, TAB_COUNT } from "../visualizer-overlay.ts";
17
17
 
18
18
  function makeTui() {
19
19
  const renders: number[] = [];
@@ -93,16 +93,16 @@ test("overlay switches tabs via 1–9,0 digit keys", (t) => {
93
93
 
94
94
  test("overlay Tab key cycles forward and wraps around at TAB_COUNT", (t) => {
95
95
  const { overlay } = makeOverlay(t);
96
- overlay.activeTab = 9;
96
+ overlay.activeTab = TAB_COUNT - 1;
97
97
  overlay.handleInput("\t");
98
- assert.equal(overlay.activeTab, 0, "Tab wraps from 9 back to 0");
98
+ assert.equal(overlay.activeTab, 0, `Tab wraps from ${TAB_COUNT - 1} back to 0`);
99
99
  });
100
100
 
101
101
  test("overlay Shift+Tab cycles backward and wraps", (t) => {
102
102
  const { overlay } = makeOverlay(t);
103
103
  overlay.activeTab = 0;
104
104
  overlay.handleInput("\u001b[Z");
105
- assert.equal(overlay.activeTab, 9, "Shift+Tab wraps from 0 to 9");
105
+ assert.equal(overlay.activeTab, TAB_COUNT - 1, `Shift+Tab wraps from 0 to ${TAB_COUNT - 1}`);
106
106
  });
107
107
 
108
108
  // ─── Filter mode ─────────────────────────────────────────────────────────
@@ -331,9 +331,9 @@ test("overlay footer hint mentions tab navigation, filter, scroll, and help", (t
331
331
 
332
332
  // ─── Scroll offsets array is sized to TAB_COUNT ──────────────────────────
333
333
 
334
- test("overlay scrollOffsets array has one slot per tab (10 tabs total)", (t) => {
334
+ test("overlay scrollOffsets array has one slot per tab", (t) => {
335
335
  const { overlay } = makeOverlay(t);
336
- assert.equal(overlay.scrollOffsets.length, 10, "scrollOffsets sized to TAB_COUNT=10");
336
+ assert.equal(overlay.scrollOffsets.length, TAB_COUNT, "scrollOffsets sized to TAB_COUNT");
337
337
  assert.ok(overlay.scrollOffsets.every((n: number) => n === 0), "initialized to zero");
338
338
  });
339
339