gsd-pi 2.63.0 → 2.64.0-dev.1a85e85

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 (583) hide show
  1. package/README.md +46 -134
  2. package/dist/cli.js +48 -6
  3. package/dist/headless-query.js +11 -1
  4. package/dist/help-text.js +4 -1
  5. package/dist/onboarding.js +15 -8
  6. package/dist/resource-loader.js +18 -3
  7. package/dist/resources/extensions/cmux/index.js +21 -12
  8. package/dist/resources/extensions/gsd/auto/detect-stuck.js +27 -0
  9. package/dist/resources/extensions/gsd/auto/finalize-timeout.js +40 -0
  10. package/dist/resources/extensions/gsd/auto/loop.js +4 -0
  11. package/dist/resources/extensions/gsd/auto/phases.js +157 -22
  12. package/dist/resources/extensions/gsd/auto/session.js +12 -0
  13. package/dist/resources/extensions/gsd/auto-dashboard.js +14 -8
  14. package/dist/resources/extensions/gsd/auto-model-selection.js +32 -0
  15. package/dist/resources/extensions/gsd/auto-post-unit.js +222 -11
  16. package/dist/resources/extensions/gsd/auto-prompts.js +25 -0
  17. package/dist/resources/extensions/gsd/auto-recovery.js +15 -7
  18. package/dist/resources/extensions/gsd/auto-start.js +10 -21
  19. package/dist/resources/extensions/gsd/auto-timers.js +2 -1
  20. package/dist/resources/extensions/gsd/auto-tool-tracking.js +17 -0
  21. package/dist/resources/extensions/gsd/auto-verification.js +138 -1
  22. package/dist/resources/extensions/gsd/auto-worktree.js +13 -7
  23. package/dist/resources/extensions/gsd/auto.js +24 -2
  24. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +147 -75
  25. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +13 -0
  26. package/dist/resources/extensions/gsd/bootstrap/notify-interceptor.js +28 -0
  27. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +85 -0
  28. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +3 -0
  29. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +40 -1
  30. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +15 -0
  31. package/dist/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.js +54 -0
  32. package/dist/resources/extensions/gsd/bootstrap/system-context.js +50 -2
  33. package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
  34. package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -0
  35. package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +103 -0
  36. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  37. package/dist/resources/extensions/gsd/commands-handlers.js +9 -4
  38. package/dist/resources/extensions/gsd/constants.js +42 -0
  39. package/dist/resources/extensions/gsd/db-writer.js +72 -4
  40. package/dist/resources/extensions/gsd/forensics.js +20 -4
  41. package/dist/resources/extensions/gsd/gsd-db.js +64 -17
  42. package/dist/resources/extensions/gsd/guided-flow.js +19 -0
  43. package/dist/resources/extensions/gsd/metrics.js +27 -1
  44. package/dist/resources/extensions/gsd/native-git-bridge.js +5 -3
  45. package/dist/resources/extensions/gsd/notification-overlay.js +224 -0
  46. package/dist/resources/extensions/gsd/notification-store.js +268 -0
  47. package/dist/resources/extensions/gsd/notification-widget.js +56 -0
  48. package/dist/resources/extensions/gsd/post-execution-checks.js +407 -0
  49. package/dist/resources/extensions/gsd/pre-execution-checks.js +464 -0
  50. package/dist/resources/extensions/gsd/preferences-types.js +6 -0
  51. package/dist/resources/extensions/gsd/preferences-validation.js +33 -0
  52. package/dist/resources/extensions/gsd/preferences.js +11 -2
  53. package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
  54. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
  55. package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -0
  56. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +1 -0
  57. package/dist/resources/extensions/gsd/prompts/forensics.md +2 -0
  58. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +2 -0
  59. package/dist/resources/extensions/gsd/prompts/system.md +4 -7
  60. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -0
  61. package/dist/resources/extensions/gsd/roadmap-mutations.js +1 -1
  62. package/dist/resources/extensions/gsd/roadmap-slices.js +9 -5
  63. package/dist/resources/extensions/gsd/safety/content-validator.js +73 -0
  64. package/dist/resources/extensions/gsd/safety/destructive-guard.js +34 -0
  65. package/dist/resources/extensions/gsd/safety/evidence-collector.js +109 -0
  66. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +83 -0
  67. package/dist/resources/extensions/gsd/safety/file-change-validator.js +71 -0
  68. package/dist/resources/extensions/gsd/safety/git-checkpoint.js +91 -0
  69. package/dist/resources/extensions/gsd/safety/safety-harness.js +64 -0
  70. package/dist/resources/extensions/gsd/slice-parallel-conflict.js +67 -0
  71. package/dist/resources/extensions/gsd/slice-parallel-eligibility.js +51 -0
  72. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +378 -0
  73. package/dist/resources/extensions/gsd/state.js +74 -14
  74. package/dist/resources/extensions/gsd/status-guards.js +11 -0
  75. package/dist/resources/extensions/gsd/tools/complete-milestone.js +17 -12
  76. package/dist/resources/extensions/gsd/tools/complete-slice.js +40 -26
  77. package/dist/resources/extensions/gsd/tools/complete-task.js +12 -12
  78. package/dist/resources/extensions/gsd/tools/plan-milestone.js +33 -25
  79. package/dist/resources/extensions/gsd/tools/plan-slice.js +5 -8
  80. package/dist/resources/extensions/gsd/verification-evidence.js +18 -0
  81. package/dist/resources/extensions/gsd/workflow-logger.js +8 -0
  82. package/dist/resources/extensions/gsd/workflow-projections.js +21 -5
  83. package/dist/resources/extensions/gsd/worktree-manager.js +82 -29
  84. package/dist/resources/extensions/gsd/worktree-resolver.js +4 -3
  85. package/dist/resources/extensions/mcp-client/auth.js +101 -0
  86. package/dist/resources/extensions/mcp-client/index.js +10 -1
  87. package/dist/resources/extensions/ollama/index.js +28 -22
  88. package/dist/resources/extensions/ollama/model-capabilities.js +37 -34
  89. package/dist/resources/extensions/ollama/ndjson-stream.js +54 -0
  90. package/dist/resources/extensions/ollama/ollama-chat-provider.js +380 -0
  91. package/dist/resources/extensions/ollama/ollama-client.js +23 -32
  92. package/dist/resources/extensions/ollama/ollama-discovery.js +2 -7
  93. package/dist/resources/extensions/ollama/ollama-tool.js +62 -0
  94. package/dist/resources/extensions/ollama/thinking-parser.js +104 -0
  95. package/dist/update-cmd.js +4 -2
  96. package/dist/web/standalone/.next/BUILD_ID +1 -1
  97. package/dist/web/standalone/.next/app-path-routes-manifest.json +19 -18
  98. package/dist/web/standalone/.next/build-manifest.json +3 -3
  99. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  100. package/dist/web/standalone/.next/required-server-files.json +4 -4
  101. package/dist/web/standalone/.next/routes-manifest.json +6 -0
  102. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  103. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  105. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  113. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  115. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  116. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  117. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  119. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  124. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  127. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  130. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  132. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  133. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  138. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  146. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  148. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  154. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  160. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  163. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  166. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +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.js.nft.json +1 -1
  172. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/notifications/route.js +3 -0
  177. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -0
  178. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -0
  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.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  186. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  189. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  191. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  194. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  197. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  199. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  200. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  203. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  206. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  208. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  211. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  214. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  215. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  216. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  217. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  218. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  219. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  220. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  221. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  222. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  223. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  224. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  225. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  226. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  227. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  228. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  229. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  230. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  231. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  232. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  233. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  234. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  235. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  236. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  237. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  238. package/dist/web/standalone/.next/server/app/index.html +1 -1
  239. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  240. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  241. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  242. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  243. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  244. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  245. package/dist/web/standalone/.next/server/app/page.js +2 -2
  246. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  247. package/dist/web/standalone/.next/server/app-paths-manifest.json +19 -18
  248. package/dist/web/standalone/.next/server/chunks/6897.js +12 -0
  249. package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
  250. package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
  251. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  252. package/dist/web/standalone/.next/server/middleware.js +2 -2
  253. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  254. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  255. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  256. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  257. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  258. package/dist/web/standalone/.next/static/chunks/app/_global-error/page-8805a20e15762c3c.js +1 -0
  259. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  260. package/dist/web/standalone/.next/static/chunks/app/api/boot/route-8805a20e15762c3c.js +1 -0
  261. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-8805a20e15762c3c.js +1 -0
  262. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-8805a20e15762c3c.js +1 -0
  263. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-8805a20e15762c3c.js +1 -0
  264. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-8805a20e15762c3c.js +1 -0
  265. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-8805a20e15762c3c.js +1 -0
  266. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-8805a20e15762c3c.js +1 -0
  267. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-8805a20e15762c3c.js +1 -0
  268. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-8805a20e15762c3c.js +1 -0
  269. package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-8805a20e15762c3c.js +1 -0
  270. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-8805a20e15762c3c.js +1 -0
  271. package/dist/web/standalone/.next/static/chunks/app/api/files/route-8805a20e15762c3c.js +1 -0
  272. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-8805a20e15762c3c.js +1 -0
  273. package/dist/web/standalone/.next/static/chunks/app/api/git/route-8805a20e15762c3c.js +1 -0
  274. package/dist/web/standalone/.next/static/chunks/app/api/history/route-8805a20e15762c3c.js +1 -0
  275. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-8805a20e15762c3c.js +1 -0
  276. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-8805a20e15762c3c.js +1 -0
  277. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-8805a20e15762c3c.js +1 -0
  278. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-8805a20e15762c3c.js +1 -0
  279. package/dist/web/standalone/.next/static/chunks/app/api/notifications/route-8805a20e15762c3c.js +1 -0
  280. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-8805a20e15762c3c.js +1 -0
  281. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-8805a20e15762c3c.js +1 -0
  282. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-8805a20e15762c3c.js +1 -0
  283. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-8805a20e15762c3c.js +1 -0
  284. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-8805a20e15762c3c.js +1 -0
  285. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-8805a20e15762c3c.js +1 -0
  286. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-8805a20e15762c3c.js +1 -0
  287. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-8805a20e15762c3c.js +1 -0
  288. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-8805a20e15762c3c.js +1 -0
  289. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-8805a20e15762c3c.js +1 -0
  290. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-8805a20e15762c3c.js +1 -0
  291. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-8805a20e15762c3c.js +1 -0
  292. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-8805a20e15762c3c.js +1 -0
  293. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-8805a20e15762c3c.js +1 -0
  294. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-8805a20e15762c3c.js +1 -0
  295. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-8805a20e15762c3c.js +1 -0
  296. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-8805a20e15762c3c.js +1 -0
  297. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-8805a20e15762c3c.js +1 -0
  298. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-8805a20e15762c3c.js +1 -0
  299. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-8805a20e15762c3c.js +1 -0
  300. package/dist/web/standalone/.next/static/chunks/app/api/update/route-8805a20e15762c3c.js +1 -0
  301. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-8805a20e15762c3c.js +1 -0
  302. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  303. package/dist/web/standalone/.next/static/chunks/app/page-0c485498795110d6.js +1 -0
  304. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  305. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-8805a20e15762c3c.js +1 -0
  306. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-8805a20e15762c3c.js +1 -0
  307. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  308. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-8805a20e15762c3c.js +1 -0
  309. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-8805a20e15762c3c.js +1 -0
  310. package/dist/web/standalone/.next/static/ffabZXz8JdN3EzX9EKt-R/_buildManifest.js +1 -0
  311. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  312. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  313. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  314. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  315. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  316. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  317. package/dist/web/standalone/server.js +1 -1
  318. package/dist/welcome-screen.js +1 -1
  319. package/package.json +1 -1
  320. package/packages/pi-agent-core/dist/agent-loop.d.ts +8 -0
  321. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  322. package/packages/pi-agent-core/dist/agent-loop.js +70 -3
  323. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  324. package/packages/pi-agent-core/src/agent-loop.test.ts +317 -5
  325. package/packages/pi-agent-core/src/agent-loop.ts +90 -6
  326. package/packages/pi-ai/dist/types.d.ts +16 -1
  327. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  328. package/packages/pi-ai/dist/types.js.map +1 -1
  329. package/packages/pi-ai/src/types.ts +18 -1
  330. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts +2 -0
  331. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts.map +1 -0
  332. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +38 -0
  333. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -0
  334. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  335. package/packages/pi-coding-agent/dist/core/agent-session.js +11 -0
  336. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  337. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +9 -0
  338. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  339. package/packages/pi-coding-agent/dist/core/auth-storage.js +50 -1
  340. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  341. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +41 -0
  342. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  343. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +7 -0
  344. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  345. package/packages/pi-coding-agent/dist/core/extensions/loader.js +31 -4
  346. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  347. package/packages/pi-coding-agent/dist/core/extensions/loader.test.js +28 -1
  348. package/packages/pi-coding-agent/dist/core/extensions/loader.test.js.map +1 -1
  349. package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.d.ts +2 -0
  350. package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.d.ts.map +1 -0
  351. package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.js +46 -0
  352. package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.js.map +1 -0
  353. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -0
  354. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  355. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  356. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +1 -0
  357. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  358. package/packages/pi-coding-agent/dist/core/model-registry.js +12 -0
  359. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  360. package/packages/pi-coding-agent/dist/core/model-resolver.js +3 -3
  361. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  362. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts +2 -0
  363. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts.map +1 -0
  364. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +24 -0
  365. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -0
  366. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +23 -1
  367. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  368. package/packages/pi-coding-agent/dist/core/resource-loader.js +84 -57
  369. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  370. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  371. package/packages/pi-coding-agent/dist/core/sdk.js +9 -0
  372. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  373. package/packages/pi-coding-agent/package.json +1 -1
  374. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +64 -0
  375. package/packages/pi-coding-agent/src/core/agent-session.ts +10 -0
  376. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +53 -0
  377. package/packages/pi-coding-agent/src/core/auth-storage.ts +66 -1
  378. package/packages/pi-coding-agent/src/core/extensions/loader.test.ts +39 -1
  379. package/packages/pi-coding-agent/src/core/extensions/loader.ts +34 -4
  380. package/packages/pi-coding-agent/src/core/extensions/provider-registration.test.ts +81 -0
  381. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -0
  382. package/packages/pi-coding-agent/src/core/model-registry.ts +14 -0
  383. package/packages/pi-coding-agent/src/core/model-resolver.ts +3 -3
  384. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +42 -0
  385. package/packages/pi-coding-agent/src/core/resource-loader.ts +94 -57
  386. package/packages/pi-coding-agent/src/core/sdk.ts +10 -0
  387. package/pkg/package.json +1 -1
  388. package/src/resources/extensions/cmux/index.ts +18 -12
  389. package/src/resources/extensions/gsd/auto/detect-stuck.ts +27 -0
  390. package/src/resources/extensions/gsd/auto/finalize-timeout.ts +46 -0
  391. package/src/resources/extensions/gsd/auto/loop.ts +5 -0
  392. package/src/resources/extensions/gsd/auto/phases.ts +194 -33
  393. package/src/resources/extensions/gsd/auto/session.ts +14 -0
  394. package/src/resources/extensions/gsd/auto-dashboard.ts +16 -7
  395. package/src/resources/extensions/gsd/auto-model-selection.ts +36 -0
  396. package/src/resources/extensions/gsd/auto-post-unit.ts +263 -12
  397. package/src/resources/extensions/gsd/auto-prompts.ts +21 -0
  398. package/src/resources/extensions/gsd/auto-recovery.ts +9 -8
  399. package/src/resources/extensions/gsd/auto-start.ts +11 -20
  400. package/src/resources/extensions/gsd/auto-timers.ts +2 -1
  401. package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
  402. package/src/resources/extensions/gsd/auto-verification.ts +190 -2
  403. package/src/resources/extensions/gsd/auto-worktree.ts +14 -6
  404. package/src/resources/extensions/gsd/auto.ts +26 -1
  405. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +160 -88
  406. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +15 -0
  407. package/src/resources/extensions/gsd/bootstrap/notify-interceptor.ts +34 -0
  408. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +98 -0
  409. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +4 -0
  410. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +44 -1
  411. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +19 -0
  412. package/src/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.ts +57 -0
  413. package/src/resources/extensions/gsd/bootstrap/system-context.ts +59 -2
  414. package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
  415. package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -0
  416. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +139 -0
  417. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  418. package/src/resources/extensions/gsd/commands-handlers.ts +10 -4
  419. package/src/resources/extensions/gsd/constants.ts +44 -0
  420. package/src/resources/extensions/gsd/db-writer.ts +78 -4
  421. package/src/resources/extensions/gsd/forensics.ts +21 -5
  422. package/src/resources/extensions/gsd/gsd-db.ts +64 -17
  423. package/src/resources/extensions/gsd/guided-flow.ts +22 -0
  424. package/src/resources/extensions/gsd/metrics.ts +28 -1
  425. package/src/resources/extensions/gsd/native-git-bridge.ts +5 -3
  426. package/src/resources/extensions/gsd/notification-overlay.ts +267 -0
  427. package/src/resources/extensions/gsd/notification-store.ts +288 -0
  428. package/src/resources/extensions/gsd/notification-widget.ts +68 -0
  429. package/src/resources/extensions/gsd/post-execution-checks.ts +539 -0
  430. package/src/resources/extensions/gsd/pre-execution-checks.ts +573 -0
  431. package/src/resources/extensions/gsd/preferences-types.ts +44 -0
  432. package/src/resources/extensions/gsd/preferences-validation.ts +33 -0
  433. package/src/resources/extensions/gsd/preferences.ts +13 -2
  434. package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
  435. package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
  436. package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -0
  437. package/src/resources/extensions/gsd/prompts/doctor-heal.md +1 -0
  438. package/src/resources/extensions/gsd/prompts/forensics.md +2 -0
  439. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +2 -0
  440. package/src/resources/extensions/gsd/prompts/system.md +4 -7
  441. package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -0
  442. package/src/resources/extensions/gsd/roadmap-mutations.ts +1 -1
  443. package/src/resources/extensions/gsd/roadmap-slices.ts +10 -5
  444. package/src/resources/extensions/gsd/safety/content-validator.ts +98 -0
  445. package/src/resources/extensions/gsd/safety/destructive-guard.ts +49 -0
  446. package/src/resources/extensions/gsd/safety/evidence-collector.ts +151 -0
  447. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +120 -0
  448. package/src/resources/extensions/gsd/safety/file-change-validator.ts +108 -0
  449. package/src/resources/extensions/gsd/safety/git-checkpoint.ts +106 -0
  450. package/src/resources/extensions/gsd/safety/safety-harness.ts +105 -0
  451. package/src/resources/extensions/gsd/slice-parallel-conflict.ts +86 -0
  452. package/src/resources/extensions/gsd/slice-parallel-eligibility.ts +73 -0
  453. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +477 -0
  454. package/src/resources/extensions/gsd/state.ts +67 -12
  455. package/src/resources/extensions/gsd/status-guards.ts +13 -0
  456. package/src/resources/extensions/gsd/tests/artifact-corruption-2630.test.ts +288 -0
  457. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +34 -13
  458. package/src/resources/extensions/gsd/tests/auto-start-time-persistence.test.ts +50 -0
  459. package/src/resources/extensions/gsd/tests/cmux.test.ts +58 -0
  460. package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +51 -0
  461. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +140 -0
  462. package/src/resources/extensions/gsd/tests/complete-slice-string-coercion.test.ts +211 -0
  463. package/src/resources/extensions/gsd/tests/complete-task.test.ts +39 -0
  464. package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +107 -0
  465. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +109 -0
  466. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +13 -9
  467. package/src/resources/extensions/gsd/tests/db-writer.test.ts +134 -0
  468. package/src/resources/extensions/gsd/tests/deferred-slice-dispatch.test.ts +203 -0
  469. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +76 -0
  470. package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +130 -0
  471. package/src/resources/extensions/gsd/tests/doctor-fix-flag.test.ts +92 -0
  472. package/src/resources/extensions/gsd/tests/enhanced-verification-integration.test.ts +526 -0
  473. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +116 -0
  474. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +50 -0
  475. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +103 -0
  476. package/src/resources/extensions/gsd/tests/git-checkpoint.test.ts +94 -0
  477. package/src/resources/extensions/gsd/tests/insert-slice-no-wipe.test.ts +88 -0
  478. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +27 -7
  479. package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +34 -0
  480. package/src/resources/extensions/gsd/tests/metrics.test.ts +116 -1
  481. package/src/resources/extensions/gsd/tests/milestone-status-tool.test.ts +201 -0
  482. package/src/resources/extensions/gsd/tests/notification-store.test.ts +249 -0
  483. package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +2 -1
  484. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +82 -18
  485. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +312 -0
  486. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +813 -0
  487. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +999 -0
  488. package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +266 -0
  489. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +457 -0
  490. package/src/resources/extensions/gsd/tests/preferences.test.ts +10 -0
  491. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +25 -0
  492. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +69 -0
  493. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +30 -0
  494. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +50 -0
  495. package/src/resources/extensions/gsd/tests/slice-parallel-conflict.test.ts +92 -0
  496. package/src/resources/extensions/gsd/tests/slice-parallel-eligibility.test.ts +95 -0
  497. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +83 -0
  498. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +42 -0
  499. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +103 -0
  500. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +349 -0
  501. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +163 -0
  502. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +35 -2
  503. package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +73 -0
  504. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +34 -0
  505. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +1 -1
  506. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +148 -0
  507. package/src/resources/extensions/gsd/tools/complete-milestone.ts +34 -20
  508. package/src/resources/extensions/gsd/tools/complete-slice.ts +41 -26
  509. package/src/resources/extensions/gsd/tools/complete-task.ts +12 -12
  510. package/src/resources/extensions/gsd/tools/plan-milestone.ts +55 -30
  511. package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -8
  512. package/src/resources/extensions/gsd/types.ts +44 -22
  513. package/src/resources/extensions/gsd/verification-evidence.ts +68 -0
  514. package/src/resources/extensions/gsd/workflow-logger.ts +15 -1
  515. package/src/resources/extensions/gsd/workflow-projections.ts +23 -5
  516. package/src/resources/extensions/gsd/worktree-manager.ts +76 -28
  517. package/src/resources/extensions/gsd/worktree-resolver.ts +4 -3
  518. package/src/resources/extensions/mcp-client/auth.ts +149 -0
  519. package/src/resources/extensions/mcp-client/index.ts +16 -1
  520. package/src/resources/extensions/ollama/index.ts +26 -25
  521. package/src/resources/extensions/ollama/model-capabilities.ts +41 -34
  522. package/src/resources/extensions/ollama/ndjson-stream.ts +63 -0
  523. package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +20 -0
  524. package/src/resources/extensions/ollama/ollama-chat-provider.ts +459 -0
  525. package/src/resources/extensions/ollama/ollama-client.ts +30 -30
  526. package/src/resources/extensions/ollama/ollama-discovery.ts +5 -8
  527. package/src/resources/extensions/ollama/ollama-tool.ts +69 -0
  528. package/src/resources/extensions/ollama/tests/ollama-chat-provider-stream.test.ts +82 -0
  529. package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +0 -27
  530. package/src/resources/extensions/ollama/thinking-parser.ts +116 -0
  531. package/src/resources/extensions/ollama/types.ts +23 -0
  532. package/dist/web/standalone/.next/server/chunks/2229.js +0 -12
  533. package/dist/web/standalone/.next/static/5FLUBNdqolRyyehCyChPd/_buildManifest.js +0 -1
  534. package/dist/web/standalone/.next/static/chunks/app/_global-error/page-c4cc189e7b117ea2.js +0 -1
  535. package/dist/web/standalone/.next/static/chunks/app/api/boot/route-c4cc189e7b117ea2.js +0 -1
  536. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-c4cc189e7b117ea2.js +0 -1
  537. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-c4cc189e7b117ea2.js +0 -1
  538. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-c4cc189e7b117ea2.js +0 -1
  539. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-c4cc189e7b117ea2.js +0 -1
  540. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-c4cc189e7b117ea2.js +0 -1
  541. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-c4cc189e7b117ea2.js +0 -1
  542. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-c4cc189e7b117ea2.js +0 -1
  543. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-c4cc189e7b117ea2.js +0 -1
  544. package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-c4cc189e7b117ea2.js +0 -1
  545. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-c4cc189e7b117ea2.js +0 -1
  546. package/dist/web/standalone/.next/static/chunks/app/api/files/route-c4cc189e7b117ea2.js +0 -1
  547. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-c4cc189e7b117ea2.js +0 -1
  548. package/dist/web/standalone/.next/static/chunks/app/api/git/route-c4cc189e7b117ea2.js +0 -1
  549. package/dist/web/standalone/.next/static/chunks/app/api/history/route-c4cc189e7b117ea2.js +0 -1
  550. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-c4cc189e7b117ea2.js +0 -1
  551. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-c4cc189e7b117ea2.js +0 -1
  552. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-c4cc189e7b117ea2.js +0 -1
  553. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-c4cc189e7b117ea2.js +0 -1
  554. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-c4cc189e7b117ea2.js +0 -1
  555. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-c4cc189e7b117ea2.js +0 -1
  556. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-c4cc189e7b117ea2.js +0 -1
  557. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-c4cc189e7b117ea2.js +0 -1
  558. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-c4cc189e7b117ea2.js +0 -1
  559. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-c4cc189e7b117ea2.js +0 -1
  560. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-c4cc189e7b117ea2.js +0 -1
  561. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-c4cc189e7b117ea2.js +0 -1
  562. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-c4cc189e7b117ea2.js +0 -1
  563. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-c4cc189e7b117ea2.js +0 -1
  564. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-c4cc189e7b117ea2.js +0 -1
  565. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-c4cc189e7b117ea2.js +0 -1
  566. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-c4cc189e7b117ea2.js +0 -1
  567. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-c4cc189e7b117ea2.js +0 -1
  568. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-c4cc189e7b117ea2.js +0 -1
  569. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-c4cc189e7b117ea2.js +0 -1
  570. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-c4cc189e7b117ea2.js +0 -1
  571. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-c4cc189e7b117ea2.js +0 -1
  572. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-c4cc189e7b117ea2.js +0 -1
  573. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-c4cc189e7b117ea2.js +0 -1
  574. package/dist/web/standalone/.next/static/chunks/app/api/update/route-c4cc189e7b117ea2.js +0 -1
  575. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-c4cc189e7b117ea2.js +0 -1
  576. package/dist/web/standalone/.next/static/chunks/app/page-62be3b5fa91e4c8f.js +0 -1
  577. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  578. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-c4cc189e7b117ea2.js +0 -1
  579. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-c4cc189e7b117ea2.js +0 -1
  580. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  581. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-c4cc189e7b117ea2.js +0 -1
  582. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-c4cc189e7b117ea2.js +0 -1
  583. /package/dist/web/standalone/.next/static/{5FLUBNdqolRyyehCyChPd → ffabZXz8JdN3EzX9EKt-R}/_ssgManifest.js +0 -0
@@ -24,6 +24,7 @@ import {
24
24
  saveDecisionToDb,
25
25
  updateRequirementInDb,
26
26
  saveArtifactToDb,
27
+ extractDeferredSliceRef,
27
28
  } from '../db-writer.ts';
28
29
  import type { Decision, Requirement } from '../types.ts';
29
30
 
@@ -475,6 +476,71 @@ describe('db-writer', () => {
475
476
  }
476
477
  });
477
478
 
479
+ test('updateRequirementInDb — seeds from REQUIREMENTS.md when DB empty (#3346)', async () => {
480
+ const tmpDir = makeTmpDir();
481
+ const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
482
+ openDatabase(dbPath);
483
+
484
+ try {
485
+ // Write a REQUIREMENTS.md with real content (simulating discussion phase output)
486
+ const reqContent = [
487
+ '# Requirements',
488
+ '',
489
+ '## Active',
490
+ '',
491
+ '### R005 — User authentication',
492
+ '- Class: functional',
493
+ '- Why: Users need secure access',
494
+ '- Source: user-research',
495
+ '- Primary owner: M001/S02',
496
+ '',
497
+ '### R007 — API rate limiting',
498
+ '- Class: non-functional',
499
+ '- Why: Prevent abuse',
500
+ '- Source: architecture',
501
+ '- Primary owner: M001/S03',
502
+ '',
503
+ '## Validated',
504
+ '',
505
+ '### R001 — Database schema',
506
+ '- Class: functional',
507
+ '- Why: Foundation for storage',
508
+ '- Source: design',
509
+ '- Validation: S01 verified',
510
+ ].join('\n');
511
+ fs.writeFileSync(path.join(tmpDir, '.gsd', 'REQUIREMENTS.md'), reqContent);
512
+
513
+ // DB is empty — no requirements seeded. Update R005 to "validated".
514
+ // Before #3346 fix: this would create a skeleton with empty fields.
515
+ // After fix: this seeds all 3 requirements from REQUIREMENTS.md first.
516
+ await updateRequirementInDb('R005', {
517
+ status: 'validated',
518
+ validation: 'S02 — auth flow verified',
519
+ }, tmpDir);
520
+
521
+ // R005 should have the update AND the original content from markdown
522
+ const r005 = getRequirementById('R005');
523
+ assert.ok(r005, 'R005 should exist');
524
+ assert.equal(r005!.status, 'validated', 'status should be updated');
525
+ assert.equal(r005!.validation, 'S02 — auth flow verified', 'validation should be updated');
526
+ assert.equal(r005!.class, 'functional', 'class should be preserved from REQUIREMENTS.md');
527
+ assert.ok(r005!.description?.includes('authentication') || r005!.full_content?.includes('authentication'),
528
+ 'original content should be preserved');
529
+
530
+ // R007 and R001 should also be seeded (not just the one being updated)
531
+ const r007 = getRequirementById('R007');
532
+ assert.ok(r007, 'R007 should be seeded from REQUIREMENTS.md');
533
+ assert.equal(r007!.status, 'active', 'R007 status should be active');
534
+
535
+ const r001 = getRequirementById('R001');
536
+ assert.ok(r001, 'R001 should be seeded from REQUIREMENTS.md');
537
+ assert.equal(r001!.status, 'validated', 'R001 status should be validated (from section heading)');
538
+ } finally {
539
+ closeDatabase();
540
+ cleanupDir(tmpDir);
541
+ }
542
+ });
543
+
478
544
  // ═══════════════════════════════════════════════════════════════════════════
479
545
  // saveArtifactToDb Tests
480
546
  // ═══════════════════════════════════════════════════════════════════════════
@@ -694,4 +760,72 @@ describe('db-writer', () => {
694
760
 
695
761
  // ═══════════════════════════════════════════════════════════════════════════
696
762
 
763
+ // ═══════════════════════════════════════════════════════════════════════════
764
+ // extractDeferredSliceRef
765
+ // ═══════════════════════════════════════════════════════════════════════════
766
+
767
+ describe('extractDeferredSliceRef', () => {
768
+ const fields = (scope: string, choice: string, decision: string) => ({
769
+ scope,
770
+ choice,
771
+ decision,
772
+ });
773
+
774
+ test('detects deferral in scope with M###/S## pattern in choice', () => {
775
+ const result = extractDeferredSliceRef(
776
+ fields('deferral of low-priority work', 'Move M001/S03 to backlog', ''),
777
+ );
778
+ assert.deepStrictEqual(result, { milestoneId: 'M001', sliceId: 'S03' });
779
+ });
780
+
781
+ test('detects deferral in choice field', () => {
782
+ const result = extractDeferredSliceRef(
783
+ fields('slice prioritization', 'defer M002/S01 until next sprint', ''),
784
+ );
785
+ assert.deepStrictEqual(result, { milestoneId: 'M002', sliceId: 'S01' });
786
+ });
787
+
788
+ test('detects deferral in decision field', () => {
789
+ const result = extractDeferredSliceRef(
790
+ fields('resource constraints', '', 'deferred M010/S12 pending review'),
791
+ );
792
+ assert.deepStrictEqual(result, { milestoneId: 'M010', sliceId: 'S12' });
793
+ });
794
+
795
+ test('returns null when no M###/S## pattern is present', () => {
796
+ const result = extractDeferredSliceRef(
797
+ fields('deferral of work', 'will revisit later', 'deferred indefinitely'),
798
+ );
799
+ assert.strictEqual(result, null);
800
+ });
801
+
802
+ test('recognises "deferring" variant', () => {
803
+ const result = extractDeferredSliceRef(
804
+ fields('deferring this slice', 'M005/S02 can wait', ''),
805
+ );
806
+ assert.deepStrictEqual(result, { milestoneId: 'M005', sliceId: 'S02' });
807
+ });
808
+
809
+ test('recognises "defers" variant', () => {
810
+ const result = extractDeferredSliceRef(
811
+ fields('team defers slice', 'M100/S10 not urgent', ''),
812
+ );
813
+ assert.deepStrictEqual(result, { milestoneId: 'M100', sliceId: 'S10' });
814
+ });
815
+
816
+ test('returns first M###/S## match when multiple patterns exist', () => {
817
+ const result = extractDeferredSliceRef(
818
+ fields('', 'defer M003/S01 and M003/S02', ''),
819
+ );
820
+ assert.deepStrictEqual(result, { milestoneId: 'M003', sliceId: 'S01' });
821
+ });
822
+
823
+ test('returns null when no deferral keyword is present', () => {
824
+ const result = extractDeferredSliceRef(
825
+ fields('approved work', 'M001/S01 is ready', 'proceed with M001/S01'),
826
+ );
827
+ assert.strictEqual(result, null);
828
+ });
829
+ });
830
+
697
831
  });
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Regression test for #2661: Auto-mode dispatches deferred slices.
3
+ *
4
+ * When a decision defers a slice, the dispatcher must skip it and advance
5
+ * to the next eligible slice. This tests both:
6
+ * 1. deriveStateFromDb skips slices with status "deferred"
7
+ * 2. saveDecisionToDb updates the slice status when the decision is a deferral
8
+ */
9
+
10
+ import { describe, test } from "node:test";
11
+ import assert from "node:assert/strict";
12
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
13
+ import { join } from "node:path";
14
+ import { tmpdir } from "node:os";
15
+
16
+ import { deriveStateFromDb, invalidateStateCache } from "../state.ts";
17
+ import {
18
+ openDatabase,
19
+ closeDatabase,
20
+ isDbAvailable,
21
+ insertMilestone,
22
+ insertSlice,
23
+ insertTask,
24
+ insertArtifact,
25
+ updateSliceStatus,
26
+ } from "../gsd-db.ts";
27
+ import { isDeferredStatus } from "../status-guards.ts";
28
+
29
+ // ─── Helpers ──────────────────────────────────────────────────────────────
30
+
31
+ function createFixtureBase(): string {
32
+ const base = mkdtempSync(join(tmpdir(), "gsd-deferred-dispatch-"));
33
+ mkdirSync(join(base, ".gsd", "milestones"), { recursive: true });
34
+ return base;
35
+ }
36
+
37
+ function writeFile(base: string, relativePath: string, content: string): void {
38
+ const full = join(base, ".gsd", relativePath);
39
+ mkdirSync(join(full, ".."), { recursive: true });
40
+ writeFileSync(full, content);
41
+ }
42
+
43
+ function cleanup(base: string): void {
44
+ rmSync(base, { recursive: true, force: true });
45
+ }
46
+
47
+ // ─── Tests ────────────────────────────────────────────────────────────────
48
+
49
+ describe("deferred-slice-dispatch (#2661)", () => {
50
+ test("isDeferredStatus returns true for 'deferred'", () => {
51
+ assert.ok(isDeferredStatus("deferred"), "should recognize 'deferred'");
52
+ assert.ok(!isDeferredStatus("active"), "should not match 'active'");
53
+ assert.ok(!isDeferredStatus("complete"), "should not match 'complete'");
54
+ assert.ok(!isDeferredStatus("pending"), "should not match 'pending'");
55
+ });
56
+
57
+ test("deriveStateFromDb skips deferred slice and picks next eligible", async () => {
58
+ const base = createFixtureBase();
59
+ try {
60
+ openDatabase(":memory:");
61
+ assert.ok(isDbAvailable());
62
+
63
+ // M001 with three slices: S01 complete, S02 deferred, S03 pending
64
+ insertMilestone({ id: "M001", title: "Test Milestone", status: "active" });
65
+
66
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Done Slice", status: "complete", risk: "low", depends: [] });
67
+ insertSlice({ id: "S02", milestoneId: "M001", title: "Deferred Slice", status: "deferred", risk: "low", depends: [] });
68
+ insertSlice({ id: "S03", milestoneId: "M001", title: "Next Slice", status: "pending", risk: "low", depends: [] });
69
+
70
+ // S01 needs a SUMMARY file to count as complete for milestone-level checks
71
+ writeFile(base, "milestones/M001/M001-ROADMAP.md", `# M001: Test Milestone
72
+
73
+ **Vision:** Test deferred slices.
74
+
75
+ ## Slices
76
+
77
+ - [x] **S01: Done Slice** \`risk:low\` \`depends:[]\`
78
+ > Done.
79
+
80
+ - [ ] **S02: Deferred Slice** \`risk:low\` \`depends:[]\`
81
+ > Deferred.
82
+
83
+ - [ ] **S03: Next Slice** \`risk:low\` \`depends:[]\`
84
+ > Next.
85
+ `);
86
+ writeFile(base, "milestones/M001/slices/S01/S01-SUMMARY.md", "# S01 Summary\nDone.");
87
+
88
+ invalidateStateCache();
89
+ const state = await deriveStateFromDb(base);
90
+
91
+ // The active slice must be S03, NOT S02 (which is deferred)
92
+ assert.equal(state.activeMilestone?.id, "M001", "active milestone is M001");
93
+ assert.equal(state.activeSlice?.id, "S03", "active slice should skip deferred S02 and land on S03");
94
+ assert.notEqual(state.activeSlice?.id, "S02", "active slice must NOT be the deferred S02");
95
+
96
+ closeDatabase();
97
+ } finally {
98
+ closeDatabase();
99
+ cleanup(base);
100
+ }
101
+ });
102
+
103
+ test("deriveStateFromDb does not count deferred slices as done for progress", async () => {
104
+ const base = createFixtureBase();
105
+ try {
106
+ openDatabase(":memory:");
107
+
108
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
109
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Complete", status: "complete", risk: "low", depends: [] });
110
+ insertSlice({ id: "S02", milestoneId: "M001", title: "Deferred", status: "deferred", risk: "low", depends: [] });
111
+ insertSlice({ id: "S03", milestoneId: "M001", title: "Pending", status: "pending", risk: "low", depends: [] });
112
+
113
+ writeFile(base, "milestones/M001/M001-ROADMAP.md", `# M001
114
+ ## Slices
115
+ - [x] **S01: Complete** \`risk:low\` \`depends:[]\`
116
+ - [ ] **S02: Deferred** \`risk:low\` \`depends:[]\`
117
+ - [ ] **S03: Pending** \`risk:low\` \`depends:[]\`
118
+ `);
119
+ writeFile(base, "milestones/M001/slices/S01/S01-SUMMARY.md", "# Done");
120
+
121
+ invalidateStateCache();
122
+ const state = await deriveStateFromDb(base);
123
+
124
+ // Deferred slices should not count as "done" in progress
125
+ // Only S01 (complete) counts as done
126
+ assert.equal(state.progress?.slices?.done, 1, "only 1 slice (S01) should be done");
127
+ // Total should still be 3 (deferred slices are still part of the milestone)
128
+ assert.equal(state.progress?.slices?.total, 3, "all 3 slices counted in total");
129
+
130
+ closeDatabase();
131
+ } finally {
132
+ closeDatabase();
133
+ cleanup(base);
134
+ }
135
+ });
136
+
137
+ test("all slices deferred results in blocked state", async () => {
138
+ const base = createFixtureBase();
139
+ try {
140
+ openDatabase(":memory:");
141
+
142
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
143
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Deferred A", status: "deferred", risk: "low", depends: [] });
144
+ insertSlice({ id: "S02", milestoneId: "M001", title: "Deferred B", status: "deferred", risk: "low", depends: [] });
145
+
146
+ writeFile(base, "milestones/M001/M001-ROADMAP.md", `# M001
147
+ ## Slices
148
+ - [ ] **S01: Deferred A** \`risk:low\` \`depends:[]\`
149
+ - [ ] **S02: Deferred B** \`risk:low\` \`depends:[]\`
150
+ `);
151
+
152
+ invalidateStateCache();
153
+ const state = await deriveStateFromDb(base);
154
+
155
+ // No eligible slice — should be blocked
156
+ assert.equal(state.activeSlice, null, "no active slice when all deferred");
157
+ assert.equal(state.phase, "blocked", "phase should be blocked when all slices deferred");
158
+
159
+ closeDatabase();
160
+ } finally {
161
+ closeDatabase();
162
+ cleanup(base);
163
+ }
164
+ });
165
+
166
+ test("saveDecisionToDb marks slice as deferred when decision is a deferral", async () => {
167
+ const base = createFixtureBase();
168
+ try {
169
+ openDatabase(":memory:");
170
+
171
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
172
+ insertSlice({ id: "S03", milestoneId: "M001", title: "Target Slice", status: "active", risk: "low", depends: [] });
173
+
174
+ writeFile(base, "milestones/M001/M001-ROADMAP.md", `# M001
175
+ ## Slices
176
+ - [ ] **S03: Target Slice** \`risk:low\` \`depends:[]\`
177
+ `);
178
+
179
+ const { saveDecisionToDb } = await import("../db-writer.ts");
180
+ const { getSlice } = await import("../gsd-db.ts");
181
+
182
+ // Save a deferral decision that references M001/S03
183
+ await saveDecisionToDb(
184
+ {
185
+ scope: "deferral",
186
+ decision: "Defer S03 to focus on higher priority work",
187
+ choice: "defer M001/S03",
188
+ rationale: "Not ready yet",
189
+ },
190
+ base,
191
+ );
192
+
193
+ // The slice status should now be "deferred"
194
+ const slice = getSlice("M001", "S03");
195
+ assert.equal(slice?.status, "deferred", "slice status should be updated to 'deferred' after deferral decision");
196
+
197
+ closeDatabase();
198
+ } finally {
199
+ closeDatabase();
200
+ cleanup(base);
201
+ }
202
+ });
203
+ });
@@ -0,0 +1,76 @@
1
+ // GSD-2 — Regression test for #3616: discuss tool scoping must not leak into subsequent sessions
2
+ // Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
3
+
4
+ /**
5
+ * Bug #3616: After a discuss session narrows the active tool set via
6
+ * setActiveTools(), the narrowed list persisted into the next auto-mode
7
+ * session because newSession() did not restore extension tools when cwd
8
+ * was unchanged. This caused gsd_plan_slice and other DB tools to be
9
+ * missing from plan-slice subagent sessions.
10
+ *
11
+ * This test verifies the structural properties that prevent the leak:
12
+ * 1. guided-flow.ts narrows tools ONLY for discuss-* unit types
13
+ * 2. The narrowed set explicitly excludes gsd_plan_slice (a HEAVY_TOOL)
14
+ * 3. agent-session.ts:newSession() has an else-branch that restores
15
+ * all extension tools even when cwd hasn't changed
16
+ */
17
+
18
+ import { describe, test } from "node:test";
19
+ import assert from "node:assert/strict";
20
+ import { readFileSync } from "node:fs";
21
+ import { join, dirname } from "node:path";
22
+ import { fileURLToPath } from "node:url";
23
+
24
+ import { DISCUSS_TOOLS_ALLOWLIST } from "../constants.ts";
25
+
26
+ const __dirname = dirname(fileURLToPath(import.meta.url));
27
+ const guidedFlowSource = readFileSync(join(__dirname, "..", "guided-flow.ts"), "utf-8");
28
+
29
+ describe("#3616 — discuss tool scoping must not leak across sessions", () => {
30
+ test("gsd_plan_slice is NOT in DISCUSS_TOOLS_ALLOWLIST", () => {
31
+ assert.ok(
32
+ !DISCUSS_TOOLS_ALLOWLIST.includes("gsd_plan_slice"),
33
+ "gsd_plan_slice should be excluded from discuss scope (it's a heavy planning tool)",
34
+ );
35
+ });
36
+
37
+ test("tool scoping only activates for discuss-* unit types", () => {
38
+ // The guard must be: if (unitType?.startsWith("discuss-"))
39
+ assert.ok(
40
+ guidedFlowSource.includes('unitType?.startsWith("discuss-")'),
41
+ "tool scoping should only trigger for discuss-* unit types",
42
+ );
43
+ });
44
+
45
+ test("discuss tool scoping uses setActiveTools (not setTools) for reversibility", () => {
46
+ // setActiveTools changes the active subset but doesn't remove tools from
47
+ // the registry. newSession()'s _refreshToolRegistry can restore them.
48
+ assert.ok(
49
+ guidedFlowSource.includes("pi.setActiveTools(scopedTools)"),
50
+ "should use pi.setActiveTools to narrow tools (preserving registry)",
51
+ );
52
+ });
53
+
54
+ test("newSession() in agent-session.ts has defense against tool narrowing persistence", () => {
55
+ const agentSessionSource = readFileSync(
56
+ join(process.cwd(), "packages/pi-coding-agent/src/core/agent-session.ts"),
57
+ "utf-8",
58
+ );
59
+ const newSessionStart = agentSessionSource.indexOf("async newSession(options?:");
60
+ assert.ok(newSessionStart >= 0, "should find newSession");
61
+ const body = agentSessionSource.slice(newSessionStart, newSessionStart + 3000);
62
+
63
+ // Both branches (cwd-changed and cwd-unchanged) must include extension tools
64
+ assert.ok(
65
+ body.includes("includeAllExtensionTools: true"),
66
+ "newSession() must include all extension tools in both branches",
67
+ );
68
+
69
+ // Count occurrences — should be at least 2 (one per branch)
70
+ const matches = body.match(/includeAllExtensionTools:\s*true/g);
71
+ assert.ok(
72
+ matches && matches.length >= 2,
73
+ `expected >=2 includeAllExtensionTools:true in newSession(), got ${matches?.length ?? 0}`,
74
+ );
75
+ });
76
+ });
@@ -0,0 +1,130 @@
1
+ /**
2
+ * discuss-tool-scoping.test.ts — Tests for #2949.
3
+ *
4
+ * xAI/Grok returns "Grammar is too complex" (400) when the combined tool
5
+ * schemas exceed the provider's grammar limit. The GSD discuss flow only
6
+ * needs a small subset of tools (summary_save, decision_save, etc.), but
7
+ * was sending ALL ~30+ tools to the provider.
8
+ *
9
+ * These tests verify:
10
+ * 1. DISCUSS_TOOLS_ALLOWLIST is exported and contains only the tools
11
+ * needed during discuss flows (no heavy planning/execution/completion tools).
12
+ * 2. Heavy execution tools are NOT in the allowlist.
13
+ * 3. The allowlist includes the tools actually referenced by discuss prompts.
14
+ * 4. dispatchWorkflow scopes tools when unitType is a discuss variant.
15
+ */
16
+
17
+ import { describe, test } from "node:test";
18
+ import assert from "node:assert/strict";
19
+ import { readFileSync } from "node:fs";
20
+ import { join, dirname } from "node:path";
21
+ import { fileURLToPath } from "node:url";
22
+
23
+ import { DISCUSS_TOOLS_ALLOWLIST } from "../constants.ts";
24
+
25
+ const __dirname = dirname(fileURLToPath(import.meta.url));
26
+ const promptsDir = join(__dirname, "..", "prompts");
27
+ const guidedFlowPath = join(__dirname, "..", "guided-flow.ts");
28
+
29
+ // ─── Heavy tools that should NOT be in discuss scope ─────────────────────────
30
+
31
+ /** Tools that are only needed during planning, execution, or completion phases */
32
+ const HEAVY_TOOLS = [
33
+ "gsd_plan_slice",
34
+ "gsd_slice_plan",
35
+ "gsd_plan_task",
36
+ "gsd_task_plan",
37
+ "gsd_task_complete",
38
+ "gsd_complete_task",
39
+ "gsd_slice_complete",
40
+ "gsd_complete_slice",
41
+ "gsd_complete_milestone",
42
+ "gsd_milestone_complete",
43
+ "gsd_validate_milestone",
44
+ "gsd_milestone_validate",
45
+ "gsd_replan_slice",
46
+ "gsd_slice_replan",
47
+ "gsd_reassess_roadmap",
48
+ "gsd_roadmap_reassess",
49
+ "gsd_save_gate_result",
50
+ ];
51
+
52
+ // ─── Tools that discuss prompts reference ────────────────────────────────────
53
+
54
+ /** Tools explicitly called by discuss prompt templates */
55
+ const DISCUSS_REQUIRED_TOOLS = [
56
+ "gsd_summary_save", // guided-discuss-slice.md, guided-discuss-milestone.md, discuss.md
57
+ "gsd_decision_save", // discuss.md output phase
58
+ "gsd_plan_milestone", // discuss.md output phase (single + multi milestone)
59
+ "gsd_milestone_generate_id", // discuss.md multi-milestone Phase 1
60
+ "gsd_requirement_update", // used during discuss for requirement updates
61
+ ];
62
+
63
+ // ─── Tests ───────────────────────────────────────────────────────────────────
64
+
65
+ describe("discuss tool scoping (#2949)", () => {
66
+ test("DISCUSS_TOOLS_ALLOWLIST is exported and non-empty", () => {
67
+ assert.ok(Array.isArray(DISCUSS_TOOLS_ALLOWLIST), "should be an array");
68
+ assert.ok(DISCUSS_TOOLS_ALLOWLIST.length > 0, "should not be empty");
69
+ });
70
+
71
+ test("DISCUSS_TOOLS_ALLOWLIST excludes heavy execution/completion tools", () => {
72
+ for (const heavy of HEAVY_TOOLS) {
73
+ assert.ok(
74
+ !DISCUSS_TOOLS_ALLOWLIST.includes(heavy),
75
+ `allowlist should NOT include heavy tool "${heavy}"`,
76
+ );
77
+ }
78
+ });
79
+
80
+ test("DISCUSS_TOOLS_ALLOWLIST includes tools referenced by discuss prompts", () => {
81
+ for (const required of DISCUSS_REQUIRED_TOOLS) {
82
+ assert.ok(
83
+ DISCUSS_TOOLS_ALLOWLIST.includes(required),
84
+ `allowlist should include "${required}" (used by discuss prompts)`,
85
+ );
86
+ }
87
+ });
88
+
89
+ test("DISCUSS_TOOLS_ALLOWLIST is significantly smaller than full tool set", () => {
90
+ // Full set is 27 DB tools + dynamic + journal = 33+
91
+ // Discuss set should be roughly 10 GSD tools (5 canonical + 5 aliases)
92
+ assert.ok(
93
+ DISCUSS_TOOLS_ALLOWLIST.length <= 12,
94
+ `allowlist should have at most 12 GSD tools, got ${DISCUSS_TOOLS_ALLOWLIST.length}`,
95
+ );
96
+ });
97
+
98
+ test("guided-discuss-slice.md references gsd_summary_save", () => {
99
+ const prompt = readFileSync(join(promptsDir, "guided-discuss-slice.md"), "utf-8");
100
+ assert.ok(
101
+ prompt.includes("gsd_summary_save"),
102
+ "guided-discuss-slice.md should reference gsd_summary_save",
103
+ );
104
+ });
105
+
106
+ test("discuss.md references gsd_plan_milestone and gsd_decision_save", () => {
107
+ const prompt = readFileSync(join(promptsDir, "discuss.md"), "utf-8");
108
+ assert.ok(
109
+ prompt.includes("gsd_plan_milestone"),
110
+ "discuss.md should reference gsd_plan_milestone",
111
+ );
112
+ assert.ok(
113
+ prompt.includes("gsd_decision_save"),
114
+ "discuss.md should reference gsd_decision_save",
115
+ );
116
+ });
117
+
118
+ test("dispatchWorkflow source code scopes tools for discuss unit types", () => {
119
+ const source = readFileSync(guidedFlowPath, "utf-8");
120
+ // Verify that dispatchWorkflow references the allowlist for tool scoping
121
+ assert.ok(
122
+ source.includes("DISCUSS_TOOLS_ALLOWLIST"),
123
+ "guided-flow.ts should reference DISCUSS_TOOLS_ALLOWLIST for tool scoping",
124
+ );
125
+ assert.ok(
126
+ source.includes("setActiveTools"),
127
+ "guided-flow.ts should call setActiveTools to scope tools during discuss",
128
+ );
129
+ });
130
+ });
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Regression test for #1919: --fix flag not stripped before positional parse.
3
+ *
4
+ * parseDoctorArgs("--fix") must:
5
+ * 1. Set fixFlag = true
6
+ * 2. Not leak "--fix" into requestedScope
7
+ * 3. Keep mode as "doctor" (the flag is not a positional subcommand)
8
+ */
9
+
10
+ import { parseDoctorArgs } from "../commands-handlers.js";
11
+ import { createTestContext } from "./test-helpers.ts";
12
+
13
+ const { assertEq, assertTrue, report } = createTestContext();
14
+
15
+ async function main(): Promise<void> {
16
+ // ── 1. Bare --fix flag ──────────────────────────────────────────────────────
17
+ console.log("\n=== bare --fix flag (#1919) ===");
18
+ {
19
+ const r = parseDoctorArgs("--fix");
20
+ assertTrue(r.fixFlag, "--fix sets fixFlag to true");
21
+ assertEq(r.mode, "doctor", "--fix does not change mode from doctor");
22
+ assertEq(r.requestedScope, undefined, "--fix is stripped and does not become requestedScope");
23
+ }
24
+
25
+ // ── 2. --fix with a scope ──────────────────────────────────────────────────
26
+ console.log("\n=== --fix with scope ===");
27
+ {
28
+ const r = parseDoctorArgs("--fix M001/S01");
29
+ assertTrue(r.fixFlag, "--fix M001/S01 sets fixFlag to true");
30
+ assertEq(r.mode, "doctor", "--fix M001/S01 keeps mode as doctor");
31
+ assertEq(r.requestedScope, "M001/S01", "scope is M001/S01 after stripping --fix");
32
+ }
33
+
34
+ // ── 3. Positional fix still works ──────────────────────────────────────────
35
+ console.log("\n=== positional fix subcommand ===");
36
+ {
37
+ const r = parseDoctorArgs("fix");
38
+ assertEq(r.fixFlag, false, "positional fix does not set fixFlag");
39
+ assertEq(r.mode, "fix", "positional fix sets mode to fix");
40
+ assertEq(r.requestedScope, undefined, "no scope with bare positional fix");
41
+ }
42
+
43
+ // ── 4. Positional fix with scope ───────────────────────────────────────────
44
+ console.log("\n=== positional fix with scope ===");
45
+ {
46
+ const r = parseDoctorArgs("fix M001");
47
+ assertEq(r.mode, "fix", "fix M001 sets mode to fix");
48
+ assertEq(r.requestedScope, "M001", "fix M001 parses scope as M001");
49
+ }
50
+
51
+ // ── 5. --fix combined with other flags ─────────────────────────────────────
52
+ console.log("\n=== --fix combined with --dry-run ===");
53
+ {
54
+ const r = parseDoctorArgs("--fix --dry-run");
55
+ assertTrue(r.fixFlag, "--fix --dry-run sets fixFlag");
56
+ assertTrue(r.dryRun, "--fix --dry-run sets dryRun");
57
+ assertEq(r.requestedScope, undefined, "no scope leaked from combined flags");
58
+ }
59
+
60
+ // ── 6. --fix combined with --json ──────────────────────────────────────────
61
+ console.log("\n=== --fix with --json ===");
62
+ {
63
+ const r = parseDoctorArgs("--fix --json");
64
+ assertTrue(r.fixFlag, "--fix --json sets fixFlag");
65
+ assertTrue(r.jsonMode, "--fix --json sets jsonMode");
66
+ assertEq(r.requestedScope, undefined, "no scope leaked from --fix --json");
67
+ }
68
+
69
+ // ── 7. Empty args (baseline) ───────────────────────────────────────────────
70
+ console.log("\n=== empty args baseline ===");
71
+ {
72
+ const r = parseDoctorArgs("");
73
+ assertEq(r.fixFlag, false, "empty args: fixFlag false");
74
+ assertEq(r.mode, "doctor", "empty args: mode is doctor");
75
+ assertEq(r.requestedScope, undefined, "empty args: no scope");
76
+ }
77
+
78
+ // ── 8. heal and audit modes unaffected ─────────────────────────────────────
79
+ console.log("\n=== heal and audit modes ===");
80
+ {
81
+ const rh = parseDoctorArgs("heal M001/S01");
82
+ assertEq(rh.mode, "heal", "heal mode parsed correctly");
83
+ assertEq(rh.requestedScope, "M001/S01", "heal scope parsed correctly");
84
+
85
+ const ra = parseDoctorArgs("audit");
86
+ assertEq(ra.mode, "audit", "audit mode parsed correctly");
87
+ }
88
+
89
+ report();
90
+ }
91
+
92
+ main();