gsd-pi 2.63.0 → 2.64.0-dev.05b8a94

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 (612) 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/headless.js +3 -1
  5. package/dist/help-text.js +4 -1
  6. package/dist/onboarding.js +15 -8
  7. package/dist/resource-loader.js +18 -3
  8. package/dist/resources/extensions/bg-shell/bg-shell-lifecycle.js +22 -7
  9. package/dist/resources/extensions/bg-shell/process-manager.js +6 -1
  10. package/dist/resources/extensions/cmux/index.js +21 -12
  11. package/dist/resources/extensions/gsd/auto/detect-stuck.js +27 -0
  12. package/dist/resources/extensions/gsd/auto/finalize-timeout.js +40 -0
  13. package/dist/resources/extensions/gsd/auto/loop.js +4 -0
  14. package/dist/resources/extensions/gsd/auto/phases.js +157 -22
  15. package/dist/resources/extensions/gsd/auto/session.js +12 -0
  16. package/dist/resources/extensions/gsd/auto-dashboard.js +14 -8
  17. package/dist/resources/extensions/gsd/auto-model-selection.js +32 -0
  18. package/dist/resources/extensions/gsd/auto-post-unit.js +222 -11
  19. package/dist/resources/extensions/gsd/auto-prompts.js +25 -0
  20. package/dist/resources/extensions/gsd/auto-recovery.js +15 -7
  21. package/dist/resources/extensions/gsd/auto-start.js +10 -21
  22. package/dist/resources/extensions/gsd/auto-timers.js +2 -1
  23. package/dist/resources/extensions/gsd/auto-tool-tracking.js +17 -0
  24. package/dist/resources/extensions/gsd/auto-verification.js +138 -1
  25. package/dist/resources/extensions/gsd/auto-worktree.js +13 -7
  26. package/dist/resources/extensions/gsd/auto.js +24 -2
  27. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +158 -75
  28. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +13 -0
  29. package/dist/resources/extensions/gsd/bootstrap/notify-interceptor.js +28 -0
  30. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +85 -0
  31. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +3 -0
  32. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +40 -1
  33. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +15 -0
  34. package/dist/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.js +54 -0
  35. package/dist/resources/extensions/gsd/bootstrap/system-context.js +50 -2
  36. package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
  37. package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -0
  38. package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +103 -0
  39. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  40. package/dist/resources/extensions/gsd/commands-handlers.js +9 -4
  41. package/dist/resources/extensions/gsd/constants.js +42 -0
  42. package/dist/resources/extensions/gsd/db-writer.js +72 -4
  43. package/dist/resources/extensions/gsd/forensics.js +20 -4
  44. package/dist/resources/extensions/gsd/gsd-db.js +64 -17
  45. package/dist/resources/extensions/gsd/guided-flow.js +19 -0
  46. package/dist/resources/extensions/gsd/metrics.js +27 -1
  47. package/dist/resources/extensions/gsd/native-git-bridge.js +5 -3
  48. package/dist/resources/extensions/gsd/notification-overlay.js +224 -0
  49. package/dist/resources/extensions/gsd/notification-store.js +268 -0
  50. package/dist/resources/extensions/gsd/notification-widget.js +56 -0
  51. package/dist/resources/extensions/gsd/post-execution-checks.js +407 -0
  52. package/dist/resources/extensions/gsd/pre-execution-checks.js +464 -0
  53. package/dist/resources/extensions/gsd/preferences-types.js +6 -0
  54. package/dist/resources/extensions/gsd/preferences-validation.js +33 -0
  55. package/dist/resources/extensions/gsd/preferences.js +11 -2
  56. package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
  57. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
  58. package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -0
  59. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +1 -0
  60. package/dist/resources/extensions/gsd/prompts/forensics.md +2 -0
  61. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +2 -0
  62. package/dist/resources/extensions/gsd/prompts/system.md +4 -7
  63. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -0
  64. package/dist/resources/extensions/gsd/roadmap-mutations.js +1 -1
  65. package/dist/resources/extensions/gsd/roadmap-slices.js +9 -5
  66. package/dist/resources/extensions/gsd/safety/content-validator.js +73 -0
  67. package/dist/resources/extensions/gsd/safety/destructive-guard.js +34 -0
  68. package/dist/resources/extensions/gsd/safety/evidence-collector.js +109 -0
  69. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +83 -0
  70. package/dist/resources/extensions/gsd/safety/file-change-validator.js +71 -0
  71. package/dist/resources/extensions/gsd/safety/git-checkpoint.js +91 -0
  72. package/dist/resources/extensions/gsd/safety/safety-harness.js +64 -0
  73. package/dist/resources/extensions/gsd/slice-parallel-conflict.js +67 -0
  74. package/dist/resources/extensions/gsd/slice-parallel-eligibility.js +51 -0
  75. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +378 -0
  76. package/dist/resources/extensions/gsd/state.js +74 -14
  77. package/dist/resources/extensions/gsd/status-guards.js +11 -0
  78. package/dist/resources/extensions/gsd/tools/complete-milestone.js +17 -12
  79. package/dist/resources/extensions/gsd/tools/complete-slice.js +40 -26
  80. package/dist/resources/extensions/gsd/tools/complete-task.js +12 -12
  81. package/dist/resources/extensions/gsd/tools/plan-milestone.js +33 -25
  82. package/dist/resources/extensions/gsd/tools/plan-slice.js +5 -8
  83. package/dist/resources/extensions/gsd/verification-evidence.js +18 -0
  84. package/dist/resources/extensions/gsd/workflow-logger.js +8 -0
  85. package/dist/resources/extensions/gsd/workflow-projections.js +21 -5
  86. package/dist/resources/extensions/gsd/worktree-manager.js +82 -29
  87. package/dist/resources/extensions/gsd/worktree-resolver.js +4 -3
  88. package/dist/resources/extensions/mcp-client/auth.js +101 -0
  89. package/dist/resources/extensions/mcp-client/index.js +10 -1
  90. package/dist/resources/extensions/ollama/index.js +28 -22
  91. package/dist/resources/extensions/ollama/model-capabilities.js +37 -34
  92. package/dist/resources/extensions/ollama/ndjson-stream.js +54 -0
  93. package/dist/resources/extensions/ollama/ollama-chat-provider.js +380 -0
  94. package/dist/resources/extensions/ollama/ollama-client.js +23 -32
  95. package/dist/resources/extensions/ollama/ollama-discovery.js +2 -7
  96. package/dist/resources/extensions/ollama/ollama-tool.js +62 -0
  97. package/dist/resources/extensions/ollama/thinking-parser.js +104 -0
  98. package/dist/update-cmd.js +4 -2
  99. package/dist/web/standalone/.next/BUILD_ID +1 -1
  100. package/dist/web/standalone/.next/app-path-routes-manifest.json +20 -19
  101. package/dist/web/standalone/.next/build-manifest.json +3 -3
  102. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  103. package/dist/web/standalone/.next/required-server-files.json +4 -4
  104. package/dist/web/standalone/.next/routes-manifest.json +6 -0
  105. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  106. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  108. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  116. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  119. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  122. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  127. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  130. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  133. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  135. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  136. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  144. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  151. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  154. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  160. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +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.js.nft.json +1 -1
  166. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  172. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  178. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/notifications/route.js +3 -0
  180. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -0
  181. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -0
  182. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  184. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  189. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  192. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  194. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  197. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  200. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  202. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  203. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  206. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  208. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  209. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  214. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  215. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  216. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  217. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  218. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  219. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  220. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  221. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  222. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  223. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  224. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  225. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  226. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  227. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  228. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  229. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  230. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  231. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  232. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  233. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  234. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  235. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  236. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  237. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  238. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  239. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  240. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  241. package/dist/web/standalone/.next/server/app/index.html +1 -1
  242. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  243. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  244. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  245. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  246. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  247. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  248. package/dist/web/standalone/.next/server/app/page.js +2 -2
  249. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  250. package/dist/web/standalone/.next/server/app-paths-manifest.json +20 -19
  251. package/dist/web/standalone/.next/server/chunks/6897.js +12 -0
  252. package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
  253. package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
  254. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  255. package/dist/web/standalone/.next/server/middleware.js +2 -2
  256. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  257. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  258. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  259. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  260. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  261. package/dist/web/standalone/.next/static/Vbx2-SrSBOgta6576xj9m/_buildManifest.js +1 -0
  262. package/dist/web/standalone/.next/static/chunks/app/_global-error/page-8805a20e15762c3c.js +1 -0
  263. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  264. package/dist/web/standalone/.next/static/chunks/app/api/boot/route-8805a20e15762c3c.js +1 -0
  265. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-8805a20e15762c3c.js +1 -0
  266. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-8805a20e15762c3c.js +1 -0
  267. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-8805a20e15762c3c.js +1 -0
  268. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-8805a20e15762c3c.js +1 -0
  269. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-8805a20e15762c3c.js +1 -0
  270. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-8805a20e15762c3c.js +1 -0
  271. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-8805a20e15762c3c.js +1 -0
  272. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-8805a20e15762c3c.js +1 -0
  273. package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-8805a20e15762c3c.js +1 -0
  274. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-8805a20e15762c3c.js +1 -0
  275. package/dist/web/standalone/.next/static/chunks/app/api/files/route-8805a20e15762c3c.js +1 -0
  276. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-8805a20e15762c3c.js +1 -0
  277. package/dist/web/standalone/.next/static/chunks/app/api/git/route-8805a20e15762c3c.js +1 -0
  278. package/dist/web/standalone/.next/static/chunks/app/api/history/route-8805a20e15762c3c.js +1 -0
  279. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-8805a20e15762c3c.js +1 -0
  280. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-8805a20e15762c3c.js +1 -0
  281. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-8805a20e15762c3c.js +1 -0
  282. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-8805a20e15762c3c.js +1 -0
  283. package/dist/web/standalone/.next/static/chunks/app/api/notifications/route-8805a20e15762c3c.js +1 -0
  284. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-8805a20e15762c3c.js +1 -0
  285. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-8805a20e15762c3c.js +1 -0
  286. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-8805a20e15762c3c.js +1 -0
  287. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-8805a20e15762c3c.js +1 -0
  288. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-8805a20e15762c3c.js +1 -0
  289. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-8805a20e15762c3c.js +1 -0
  290. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-8805a20e15762c3c.js +1 -0
  291. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-8805a20e15762c3c.js +1 -0
  292. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-8805a20e15762c3c.js +1 -0
  293. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-8805a20e15762c3c.js +1 -0
  294. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-8805a20e15762c3c.js +1 -0
  295. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-8805a20e15762c3c.js +1 -0
  296. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-8805a20e15762c3c.js +1 -0
  297. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-8805a20e15762c3c.js +1 -0
  298. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-8805a20e15762c3c.js +1 -0
  299. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-8805a20e15762c3c.js +1 -0
  300. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-8805a20e15762c3c.js +1 -0
  301. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-8805a20e15762c3c.js +1 -0
  302. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-8805a20e15762c3c.js +1 -0
  303. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-8805a20e15762c3c.js +1 -0
  304. package/dist/web/standalone/.next/static/chunks/app/api/update/route-8805a20e15762c3c.js +1 -0
  305. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-8805a20e15762c3c.js +1 -0
  306. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  307. package/dist/web/standalone/.next/static/chunks/app/page-0c485498795110d6.js +1 -0
  308. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  309. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-8805a20e15762c3c.js +1 -0
  310. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-8805a20e15762c3c.js +1 -0
  311. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  312. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-8805a20e15762c3c.js +1 -0
  313. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-8805a20e15762c3c.js +1 -0
  314. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  315. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  316. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  317. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  318. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  319. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  320. package/dist/web/standalone/server.js +1 -1
  321. package/dist/welcome-screen.js +1 -1
  322. package/package.json +1 -1
  323. package/packages/pi-agent-core/dist/agent-loop.d.ts +8 -0
  324. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  325. package/packages/pi-agent-core/dist/agent-loop.js +70 -3
  326. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  327. package/packages/pi-agent-core/src/agent-loop.test.ts +317 -5
  328. package/packages/pi-agent-core/src/agent-loop.ts +90 -6
  329. package/packages/pi-ai/dist/types.d.ts +16 -1
  330. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  331. package/packages/pi-ai/dist/types.js.map +1 -1
  332. package/packages/pi-ai/src/types.ts +18 -1
  333. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts +2 -0
  334. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts.map +1 -0
  335. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +38 -0
  336. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -0
  337. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  338. package/packages/pi-coding-agent/dist/core/agent-session.js +11 -0
  339. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  340. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +9 -0
  341. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  342. package/packages/pi-coding-agent/dist/core/auth-storage.js +50 -1
  343. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  344. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +41 -0
  345. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  346. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +7 -0
  347. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  348. package/packages/pi-coding-agent/dist/core/extensions/loader.js +31 -4
  349. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  350. package/packages/pi-coding-agent/dist/core/extensions/loader.test.js +28 -1
  351. package/packages/pi-coding-agent/dist/core/extensions/loader.test.js.map +1 -1
  352. package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.d.ts +2 -0
  353. package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.d.ts.map +1 -0
  354. package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.js +46 -0
  355. package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.js.map +1 -0
  356. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -0
  357. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  358. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  359. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +1 -0
  360. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  361. package/packages/pi-coding-agent/dist/core/model-registry.js +12 -0
  362. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  363. package/packages/pi-coding-agent/dist/core/model-resolver.js +3 -3
  364. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  365. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts +2 -0
  366. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts.map +1 -0
  367. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +24 -0
  368. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -0
  369. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +23 -1
  370. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  371. package/packages/pi-coding-agent/dist/core/resource-loader.js +84 -57
  372. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  373. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  374. package/packages/pi-coding-agent/dist/core/sdk.js +9 -0
  375. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  376. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -0
  377. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  378. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +8 -0
  379. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  380. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +6 -0
  381. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  382. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +36 -0
  383. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  384. package/packages/pi-coding-agent/package.json +1 -1
  385. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +64 -0
  386. package/packages/pi-coding-agent/src/core/agent-session.ts +10 -0
  387. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +53 -0
  388. package/packages/pi-coding-agent/src/core/auth-storage.ts +66 -1
  389. package/packages/pi-coding-agent/src/core/extensions/loader.test.ts +39 -1
  390. package/packages/pi-coding-agent/src/core/extensions/loader.ts +34 -4
  391. package/packages/pi-coding-agent/src/core/extensions/provider-registration.test.ts +81 -0
  392. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -0
  393. package/packages/pi-coding-agent/src/core/model-registry.ts +14 -0
  394. package/packages/pi-coding-agent/src/core/model-resolver.ts +3 -3
  395. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +42 -0
  396. package/packages/pi-coding-agent/src/core/resource-loader.ts +94 -57
  397. package/packages/pi-coding-agent/src/core/sdk.ts +10 -0
  398. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +9 -0
  399. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +33 -0
  400. package/packages/pi-tui/dist/components/loader.d.ts +4 -2
  401. package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
  402. package/packages/pi-tui/dist/components/loader.js +27 -9
  403. package/packages/pi-tui/dist/components/loader.js.map +1 -1
  404. package/packages/pi-tui/dist/components/text.d.ts.map +1 -1
  405. package/packages/pi-tui/dist/components/text.js +2 -0
  406. package/packages/pi-tui/dist/components/text.js.map +1 -1
  407. package/packages/pi-tui/dist/tui.d.ts +2 -0
  408. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  409. package/packages/pi-tui/dist/tui.js +35 -0
  410. package/packages/pi-tui/dist/tui.js.map +1 -1
  411. package/packages/pi-tui/src/components/loader.ts +27 -10
  412. package/packages/pi-tui/src/components/text.ts +1 -0
  413. package/packages/pi-tui/src/tui.ts +32 -0
  414. package/pkg/package.json +1 -1
  415. package/src/resources/extensions/bg-shell/bg-shell-lifecycle.ts +19 -7
  416. package/src/resources/extensions/bg-shell/process-manager.ts +8 -2
  417. package/src/resources/extensions/cmux/index.ts +18 -12
  418. package/src/resources/extensions/gsd/auto/detect-stuck.ts +27 -0
  419. package/src/resources/extensions/gsd/auto/finalize-timeout.ts +46 -0
  420. package/src/resources/extensions/gsd/auto/loop.ts +5 -0
  421. package/src/resources/extensions/gsd/auto/phases.ts +194 -33
  422. package/src/resources/extensions/gsd/auto/session.ts +14 -0
  423. package/src/resources/extensions/gsd/auto-dashboard.ts +16 -7
  424. package/src/resources/extensions/gsd/auto-model-selection.ts +36 -0
  425. package/src/resources/extensions/gsd/auto-post-unit.ts +263 -12
  426. package/src/resources/extensions/gsd/auto-prompts.ts +21 -0
  427. package/src/resources/extensions/gsd/auto-recovery.ts +9 -8
  428. package/src/resources/extensions/gsd/auto-start.ts +11 -20
  429. package/src/resources/extensions/gsd/auto-timers.ts +2 -1
  430. package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
  431. package/src/resources/extensions/gsd/auto-verification.ts +190 -2
  432. package/src/resources/extensions/gsd/auto-worktree.ts +14 -6
  433. package/src/resources/extensions/gsd/auto.ts +26 -1
  434. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +172 -88
  435. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +15 -0
  436. package/src/resources/extensions/gsd/bootstrap/notify-interceptor.ts +34 -0
  437. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +98 -0
  438. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +4 -0
  439. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +44 -1
  440. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +19 -0
  441. package/src/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.ts +57 -0
  442. package/src/resources/extensions/gsd/bootstrap/system-context.ts +59 -2
  443. package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
  444. package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -0
  445. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +139 -0
  446. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  447. package/src/resources/extensions/gsd/commands-handlers.ts +10 -4
  448. package/src/resources/extensions/gsd/constants.ts +44 -0
  449. package/src/resources/extensions/gsd/db-writer.ts +78 -4
  450. package/src/resources/extensions/gsd/forensics.ts +21 -5
  451. package/src/resources/extensions/gsd/gsd-db.ts +64 -17
  452. package/src/resources/extensions/gsd/guided-flow.ts +22 -0
  453. package/src/resources/extensions/gsd/metrics.ts +28 -1
  454. package/src/resources/extensions/gsd/native-git-bridge.ts +5 -3
  455. package/src/resources/extensions/gsd/notification-overlay.ts +267 -0
  456. package/src/resources/extensions/gsd/notification-store.ts +288 -0
  457. package/src/resources/extensions/gsd/notification-widget.ts +68 -0
  458. package/src/resources/extensions/gsd/post-execution-checks.ts +539 -0
  459. package/src/resources/extensions/gsd/pre-execution-checks.ts +573 -0
  460. package/src/resources/extensions/gsd/preferences-types.ts +44 -0
  461. package/src/resources/extensions/gsd/preferences-validation.ts +33 -0
  462. package/src/resources/extensions/gsd/preferences.ts +13 -2
  463. package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
  464. package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
  465. package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -0
  466. package/src/resources/extensions/gsd/prompts/doctor-heal.md +1 -0
  467. package/src/resources/extensions/gsd/prompts/forensics.md +2 -0
  468. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +2 -0
  469. package/src/resources/extensions/gsd/prompts/system.md +4 -7
  470. package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -0
  471. package/src/resources/extensions/gsd/roadmap-mutations.ts +1 -1
  472. package/src/resources/extensions/gsd/roadmap-slices.ts +10 -5
  473. package/src/resources/extensions/gsd/safety/content-validator.ts +98 -0
  474. package/src/resources/extensions/gsd/safety/destructive-guard.ts +49 -0
  475. package/src/resources/extensions/gsd/safety/evidence-collector.ts +151 -0
  476. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +120 -0
  477. package/src/resources/extensions/gsd/safety/file-change-validator.ts +108 -0
  478. package/src/resources/extensions/gsd/safety/git-checkpoint.ts +106 -0
  479. package/src/resources/extensions/gsd/safety/safety-harness.ts +105 -0
  480. package/src/resources/extensions/gsd/slice-parallel-conflict.ts +86 -0
  481. package/src/resources/extensions/gsd/slice-parallel-eligibility.ts +73 -0
  482. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +477 -0
  483. package/src/resources/extensions/gsd/state.ts +67 -12
  484. package/src/resources/extensions/gsd/status-guards.ts +13 -0
  485. package/src/resources/extensions/gsd/tests/artifact-corruption-2630.test.ts +288 -0
  486. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +34 -13
  487. package/src/resources/extensions/gsd/tests/auto-start-time-persistence.test.ts +50 -0
  488. package/src/resources/extensions/gsd/tests/cmux.test.ts +58 -0
  489. package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +51 -0
  490. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +140 -0
  491. package/src/resources/extensions/gsd/tests/complete-slice-string-coercion.test.ts +247 -0
  492. package/src/resources/extensions/gsd/tests/complete-task.test.ts +39 -0
  493. package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +107 -0
  494. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +109 -0
  495. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +13 -9
  496. package/src/resources/extensions/gsd/tests/db-writer.test.ts +134 -0
  497. package/src/resources/extensions/gsd/tests/deferred-slice-dispatch.test.ts +203 -0
  498. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +76 -0
  499. package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +130 -0
  500. package/src/resources/extensions/gsd/tests/doctor-fix-flag.test.ts +92 -0
  501. package/src/resources/extensions/gsd/tests/enhanced-verification-integration.test.ts +526 -0
  502. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +116 -0
  503. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +50 -0
  504. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +103 -0
  505. package/src/resources/extensions/gsd/tests/git-checkpoint.test.ts +94 -0
  506. package/src/resources/extensions/gsd/tests/insert-slice-no-wipe.test.ts +88 -0
  507. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +27 -7
  508. package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +34 -0
  509. package/src/resources/extensions/gsd/tests/metrics.test.ts +116 -1
  510. package/src/resources/extensions/gsd/tests/milestone-status-tool.test.ts +201 -0
  511. package/src/resources/extensions/gsd/tests/notification-store.test.ts +249 -0
  512. package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +2 -1
  513. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +82 -18
  514. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +312 -0
  515. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +813 -0
  516. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +999 -0
  517. package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +266 -0
  518. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +457 -0
  519. package/src/resources/extensions/gsd/tests/preferences.test.ts +10 -0
  520. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +25 -0
  521. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +69 -0
  522. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +30 -0
  523. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +50 -0
  524. package/src/resources/extensions/gsd/tests/slice-parallel-conflict.test.ts +92 -0
  525. package/src/resources/extensions/gsd/tests/slice-parallel-eligibility.test.ts +95 -0
  526. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +83 -0
  527. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +42 -0
  528. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +103 -0
  529. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +349 -0
  530. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +163 -0
  531. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +35 -2
  532. package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +73 -0
  533. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +34 -0
  534. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +1 -1
  535. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +148 -0
  536. package/src/resources/extensions/gsd/tools/complete-milestone.ts +34 -20
  537. package/src/resources/extensions/gsd/tools/complete-slice.ts +41 -26
  538. package/src/resources/extensions/gsd/tools/complete-task.ts +12 -12
  539. package/src/resources/extensions/gsd/tools/plan-milestone.ts +55 -30
  540. package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -8
  541. package/src/resources/extensions/gsd/types.ts +44 -22
  542. package/src/resources/extensions/gsd/verification-evidence.ts +68 -0
  543. package/src/resources/extensions/gsd/workflow-logger.ts +15 -1
  544. package/src/resources/extensions/gsd/workflow-projections.ts +23 -5
  545. package/src/resources/extensions/gsd/worktree-manager.ts +76 -28
  546. package/src/resources/extensions/gsd/worktree-resolver.ts +4 -3
  547. package/src/resources/extensions/mcp-client/auth.ts +149 -0
  548. package/src/resources/extensions/mcp-client/index.ts +16 -1
  549. package/src/resources/extensions/ollama/index.ts +26 -25
  550. package/src/resources/extensions/ollama/model-capabilities.ts +41 -34
  551. package/src/resources/extensions/ollama/ndjson-stream.ts +63 -0
  552. package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +20 -0
  553. package/src/resources/extensions/ollama/ollama-chat-provider.ts +459 -0
  554. package/src/resources/extensions/ollama/ollama-client.ts +30 -30
  555. package/src/resources/extensions/ollama/ollama-discovery.ts +5 -8
  556. package/src/resources/extensions/ollama/ollama-tool.ts +69 -0
  557. package/src/resources/extensions/ollama/tests/ollama-chat-provider-stream.test.ts +82 -0
  558. package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +0 -27
  559. package/src/resources/extensions/ollama/thinking-parser.ts +116 -0
  560. package/src/resources/extensions/ollama/types.ts +23 -0
  561. package/dist/web/standalone/.next/server/chunks/2229.js +0 -12
  562. package/dist/web/standalone/.next/static/5FLUBNdqolRyyehCyChPd/_buildManifest.js +0 -1
  563. package/dist/web/standalone/.next/static/chunks/app/_global-error/page-c4cc189e7b117ea2.js +0 -1
  564. package/dist/web/standalone/.next/static/chunks/app/api/boot/route-c4cc189e7b117ea2.js +0 -1
  565. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-c4cc189e7b117ea2.js +0 -1
  566. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-c4cc189e7b117ea2.js +0 -1
  567. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-c4cc189e7b117ea2.js +0 -1
  568. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-c4cc189e7b117ea2.js +0 -1
  569. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-c4cc189e7b117ea2.js +0 -1
  570. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-c4cc189e7b117ea2.js +0 -1
  571. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-c4cc189e7b117ea2.js +0 -1
  572. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-c4cc189e7b117ea2.js +0 -1
  573. package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-c4cc189e7b117ea2.js +0 -1
  574. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-c4cc189e7b117ea2.js +0 -1
  575. package/dist/web/standalone/.next/static/chunks/app/api/files/route-c4cc189e7b117ea2.js +0 -1
  576. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-c4cc189e7b117ea2.js +0 -1
  577. package/dist/web/standalone/.next/static/chunks/app/api/git/route-c4cc189e7b117ea2.js +0 -1
  578. package/dist/web/standalone/.next/static/chunks/app/api/history/route-c4cc189e7b117ea2.js +0 -1
  579. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-c4cc189e7b117ea2.js +0 -1
  580. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-c4cc189e7b117ea2.js +0 -1
  581. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-c4cc189e7b117ea2.js +0 -1
  582. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-c4cc189e7b117ea2.js +0 -1
  583. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-c4cc189e7b117ea2.js +0 -1
  584. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-c4cc189e7b117ea2.js +0 -1
  585. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-c4cc189e7b117ea2.js +0 -1
  586. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-c4cc189e7b117ea2.js +0 -1
  587. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-c4cc189e7b117ea2.js +0 -1
  588. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-c4cc189e7b117ea2.js +0 -1
  589. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-c4cc189e7b117ea2.js +0 -1
  590. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-c4cc189e7b117ea2.js +0 -1
  591. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-c4cc189e7b117ea2.js +0 -1
  592. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-c4cc189e7b117ea2.js +0 -1
  593. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-c4cc189e7b117ea2.js +0 -1
  594. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-c4cc189e7b117ea2.js +0 -1
  595. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-c4cc189e7b117ea2.js +0 -1
  596. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-c4cc189e7b117ea2.js +0 -1
  597. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-c4cc189e7b117ea2.js +0 -1
  598. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-c4cc189e7b117ea2.js +0 -1
  599. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-c4cc189e7b117ea2.js +0 -1
  600. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-c4cc189e7b117ea2.js +0 -1
  601. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-c4cc189e7b117ea2.js +0 -1
  602. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-c4cc189e7b117ea2.js +0 -1
  603. package/dist/web/standalone/.next/static/chunks/app/api/update/route-c4cc189e7b117ea2.js +0 -1
  604. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-c4cc189e7b117ea2.js +0 -1
  605. package/dist/web/standalone/.next/static/chunks/app/page-62be3b5fa91e4c8f.js +0 -1
  606. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  607. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-c4cc189e7b117ea2.js +0 -1
  608. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-c4cc189e7b117ea2.js +0 -1
  609. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  610. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-c4cc189e7b117ea2.js +0 -1
  611. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-c4cc189e7b117ea2.js +0 -1
  612. /package/dist/web/standalone/.next/static/{5FLUBNdqolRyyehCyChPd → Vbx2-SrSBOgta6576xj9m}/_ssgManifest.js +0 -0
@@ -264,6 +264,146 @@ describe("complete-milestone", () => {
264
264
  );
265
265
  });
266
266
 
267
+ test("sanitizeCompleteMilestoneParams normalizes string parameters", async () => {
268
+ const { sanitizeCompleteMilestoneParams } = await import("../bootstrap/sanitize-complete-milestone.ts");
269
+
270
+ // Simulate params as they might arrive from the SDK after partial JSON parse:
271
+ // - numbers instead of strings
272
+ // - null instead of arrays
273
+ // - extra whitespace in strings
274
+ // - undefined optional fields
275
+ const raw: any = {
276
+ milestoneId: " M011 ",
277
+ title: 42, // number instead of string
278
+ oneLiner: " One-liner with spaces ",
279
+ narrative: "# Big markdown\n\nWith newlines and `backticks`\n\n```ts\ncode();\n```\n",
280
+ successCriteriaResults: null, // null instead of string
281
+ definitionOfDoneResults: undefined, // undefined instead of string
282
+ requirementOutcomes: 12345, // number instead of string
283
+ keyDecisions: "not an array", // string instead of array
284
+ keyFiles: null, // null instead of array
285
+ lessonsLearned: [" lesson one ", null, "", " lesson two "],
286
+ followUps: " follow up ",
287
+ deviations: undefined,
288
+ verificationPassed: "true", // string instead of boolean
289
+ };
290
+
291
+ const sanitized = sanitizeCompleteMilestoneParams(raw);
292
+
293
+ // String fields are trimmed and coerced
294
+ assert.strictEqual(sanitized.milestoneId, "M011");
295
+ assert.strictEqual(sanitized.title, "42");
296
+ assert.strictEqual(sanitized.oneLiner, "One-liner with spaces");
297
+ assert.ok(sanitized.narrative.includes("# Big markdown"), "narrative preserves markdown");
298
+ assert.strictEqual(sanitized.successCriteriaResults, "");
299
+ assert.strictEqual(sanitized.definitionOfDoneResults, "");
300
+ assert.strictEqual(sanitized.requirementOutcomes, "12345");
301
+
302
+ // Array fields are normalized
303
+ assert.ok(Array.isArray(sanitized.keyDecisions), "keyDecisions is an array");
304
+ assert.deepStrictEqual(sanitized.keyDecisions, []);
305
+ assert.ok(Array.isArray(sanitized.keyFiles), "keyFiles is an array");
306
+ assert.deepStrictEqual(sanitized.keyFiles, []);
307
+ assert.deepStrictEqual(sanitized.lessonsLearned, ["lesson one", "lesson two"]);
308
+
309
+ // Optional fields — toStr() returns "" for undefined/null
310
+ assert.strictEqual(sanitized.followUps, "follow up");
311
+ assert.strictEqual(sanitized.deviations, "");
312
+
313
+ // Boolean coercion
314
+ assert.strictEqual(sanitized.verificationPassed, true);
315
+ });
316
+
317
+ test("sanitizeCompleteMilestoneParams handles large markdown content", async () => {
318
+ const { sanitizeCompleteMilestoneParams } = await import("../bootstrap/sanitize-complete-milestone.ts");
319
+
320
+ // Generate a large markdown string (~25k characters to exceed the 23667 position from the bug)
321
+ const largeMd = "# Milestone Summary\n\n" +
322
+ Array.from({ length: 500 }, (_, i) =>
323
+ `## Section ${i}\n\n` +
324
+ `- [x] Task ${i} completed with \`code\` and **bold** text\n` +
325
+ ` - Sub-item with special chars: <, >, &, ", '\n` +
326
+ ` - Another sub-item: \`\`\`ts\nconst x = ${i};\n\`\`\`\n`
327
+ ).join("\n");
328
+
329
+ assert.ok(largeMd.length > 23667, `generated markdown is ${largeMd.length} chars, must exceed 23667`);
330
+
331
+ const raw: any = {
332
+ milestoneId: "M011",
333
+ title: "Content Depth, Narrative & Onboarding",
334
+ oneLiner: "Large milestone with many slices",
335
+ narrative: largeMd,
336
+ successCriteriaResults: largeMd,
337
+ definitionOfDoneResults: largeMd,
338
+ requirementOutcomes: largeMd,
339
+ keyDecisions: ["decision 1", "decision 2"],
340
+ keyFiles: ["file1.ts", "file2.ts"],
341
+ lessonsLearned: ["lesson 1"],
342
+ followUps: "Some follow-ups",
343
+ deviations: "Some deviations",
344
+ verificationPassed: true,
345
+ };
346
+
347
+ const sanitized = sanitizeCompleteMilestoneParams(raw);
348
+
349
+ // Large content should pass through without truncation or corruption
350
+ assert.strictEqual(sanitized.narrative, largeMd.trim());
351
+ assert.strictEqual(sanitized.successCriteriaResults, largeMd.trim());
352
+ assert.strictEqual(sanitized.definitionOfDoneResults, largeMd.trim());
353
+ assert.strictEqual(sanitized.requirementOutcomes, largeMd.trim());
354
+ });
355
+
356
+ test("milestoneCompleteExecute uses sanitized params", async () => {
357
+ // This test verifies that the execute function sanitizes params before passing
358
+ // to handleCompleteMilestone. We test indirectly: if we pass numeric milestoneId,
359
+ // the handler should still receive a string (and return a meaningful error, not a crash).
360
+ const { handleCompleteMilestone } = await import("../tools/complete-milestone.ts");
361
+ const { sanitizeCompleteMilestoneParams } = await import("../bootstrap/sanitize-complete-milestone.ts");
362
+ const base = createFixtureBase();
363
+ try {
364
+ // Simulate what milestoneCompleteExecute should do: sanitize then call handler
365
+ const raw: any = {
366
+ milestoneId: 42, // number — would crash without sanitization
367
+ title: "Test",
368
+ oneLiner: "Test",
369
+ narrative: "Test narrative",
370
+ successCriteriaResults: "Results",
371
+ definitionOfDoneResults: "Done",
372
+ requirementOutcomes: "Outcomes",
373
+ keyDecisions: null, // null — would crash .length without sanitization
374
+ keyFiles: "not-array", // string — would crash .map without sanitization
375
+ lessonsLearned: undefined, // undefined — would crash .map without sanitization
376
+ followUps: "",
377
+ deviations: "",
378
+ verificationPassed: true,
379
+ };
380
+
381
+ const sanitized = sanitizeCompleteMilestoneParams(raw);
382
+
383
+ // Verify sanitization didn't crash and produced valid typed params
384
+ assert.strictEqual(typeof sanitized.milestoneId, "string", "milestoneId is a string after sanitization");
385
+ assert.ok(Array.isArray(sanitized.keyDecisions), "keyDecisions is array after sanitization");
386
+ assert.ok(Array.isArray(sanitized.keyFiles), "keyFiles is array after sanitization");
387
+ assert.ok(Array.isArray(sanitized.lessonsLearned), "lessonsLearned is array after sanitization");
388
+ assert.strictEqual(typeof sanitized.verificationPassed, "boolean", "verificationPassed is boolean after sanitization");
389
+
390
+ // Calling handleCompleteMilestone may throw GSD_STALE_STATE (no DB in test env)
391
+ // but it should NOT throw TypeError from type mismatches — that's the bug fix.
392
+ try {
393
+ await handleCompleteMilestone(sanitized, base);
394
+ } catch (err: any) {
395
+ // GSD_STALE_STATE or "No database open" is acceptable — it means we got past
396
+ // the type-sensitive code and failed on DB access, which is expected in tests.
397
+ assert.ok(
398
+ err.code === "GSD_STALE_STATE" || err.message?.includes("database"),
399
+ `expected DB error, got: ${err.message}`,
400
+ );
401
+ }
402
+ } finally {
403
+ cleanup(base);
404
+ }
405
+ });
406
+
267
407
  test("deriveState completing-milestone integration", async () => {
268
408
  const { deriveState, isMilestoneComplete } = await import("../state.ts");
269
409
  const { invalidateAllCaches: invalidateAllCachesDynamic } = await import("../cache.ts");
@@ -0,0 +1,247 @@
1
+ // GSD Extension — String coercion regression tests for complete-slice/task tools
2
+
3
+ import { describe, test, beforeEach, afterEach } from "node:test";
4
+ import assert from "node:assert/strict";
5
+ import * as fs from "node:fs";
6
+ import * as path from "node:path";
7
+ import * as os from "node:os";
8
+ import {
9
+ openDatabase,
10
+ closeDatabase,
11
+ insertMilestone,
12
+ insertSlice,
13
+ insertTask,
14
+ } from "../gsd-db.ts";
15
+ import { handleCompleteSlice } from "../tools/complete-slice.ts";
16
+ import type { CompleteSliceParams } from "../types.ts";
17
+
18
+ // ─── Helpers ─────────────────────────────────────────────────────────────
19
+
20
+ /**
21
+ * The splitPair coercion logic extracted from db-tools.ts sliceCompleteExecute.
22
+ * Duplicated here so we can unit-test it directly.
23
+ */
24
+ function splitPair(s: string): [string, string] {
25
+ const m = s.match(/^(.+?)\s*(?:—|-)\s+(.+)$/);
26
+ return m ? [m[1].trim(), m[2].trim()] : [s.trim(), ""];
27
+ }
28
+
29
+ function makeValidSliceParams(): CompleteSliceParams {
30
+ return {
31
+ sliceId: "S01",
32
+ milestoneId: "M001",
33
+ sliceTitle: "Test Slice",
34
+ oneLiner: "Implemented test slice",
35
+ narrative: "Built and tested.",
36
+ verification: "All tests pass.",
37
+ deviations: "None.",
38
+ knownLimitations: "None.",
39
+ followUps: "None.",
40
+ keyFiles: ["src/foo.ts"],
41
+ keyDecisions: ["D001"],
42
+ patternsEstablished: [],
43
+ observabilitySurfaces: [],
44
+ provides: ["test handler"],
45
+ requirementsSurfaced: [],
46
+ drillDownPaths: [],
47
+ affects: [],
48
+ requirementsAdvanced: [{ id: "R001", how: "Handler validates" }],
49
+ requirementsValidated: [],
50
+ requirementsInvalidated: [],
51
+ filesModified: [{ path: "src/foo.ts", description: "Handler" }],
52
+ requires: [],
53
+ uatContent: "## Smoke Test\n\nVerify all assertions pass.",
54
+ };
55
+ }
56
+
57
+ // ─── splitPair unit tests ────────────────────────────────────────────────
58
+
59
+ describe("splitPair coercion helper (#3565)", () => {
60
+ test("plain string without delimiter returns string + empty", () => {
61
+ const [a, b] = splitPair("src/foo.ts");
62
+ assert.equal(a, "src/foo.ts");
63
+ assert.equal(b, "");
64
+ });
65
+
66
+ test("em-dash delimiter parses both parts", () => {
67
+ const [id, how] = splitPair("R001 — Handler validates task completion");
68
+ assert.equal(id, "R001");
69
+ assert.equal(how, "Handler validates task completion");
70
+ });
71
+
72
+ test("hyphen delimiter parses both parts", () => {
73
+ const [id, proof] = splitPair("R002 - Tests pass");
74
+ assert.equal(id, "R002");
75
+ assert.equal(proof, "Tests pass");
76
+ });
77
+
78
+ test("string with no space around hyphen is treated as plain", () => {
79
+ // e.g. a file path like "src/foo-bar.ts" should not split
80
+ const [a, b] = splitPair("src/foo-bar.ts");
81
+ assert.equal(a, "src/foo-bar.ts");
82
+ assert.equal(b, "");
83
+ });
84
+
85
+ test("whitespace is trimmed from both parts", () => {
86
+ const [id, how] = splitPair(" R003 — Trimmed value ");
87
+ assert.equal(id, "R003");
88
+ assert.equal(how, "Trimmed value");
89
+ });
90
+ });
91
+
92
+ // ─── verificationEvidence sentinel tests ─────────────────────────────────
93
+
94
+ describe("verificationEvidence sentinel coercion (#3565)", () => {
95
+ function coerceEvidence(v: any) {
96
+ return typeof v === "string"
97
+ ? { command: v, exitCode: -1, verdict: "unknown (coerced from string)", durationMs: 0 }
98
+ : v;
99
+ }
100
+
101
+ test("string input produces non-passing sentinel", () => {
102
+ const result = coerceEvidence("npm test");
103
+ assert.equal(result.command, "npm test");
104
+ assert.equal(result.exitCode, -1);
105
+ assert.equal(result.verdict, "unknown (coerced from string)");
106
+ assert.equal(result.durationMs, 0);
107
+ });
108
+
109
+ test("object input passes through unchanged", () => {
110
+ const obj = { command: "npm test", exitCode: 0, verdict: "pass", durationMs: 1234 };
111
+ const result = coerceEvidence(obj);
112
+ assert.equal(result.exitCode, 0);
113
+ assert.equal(result.verdict, "pass");
114
+ assert.equal(result.durationMs, 1234);
115
+ });
116
+
117
+ test("sentinel exitCode is not 0 (must not fabricate success)", () => {
118
+ const result = coerceEvidence("anything");
119
+ assert.notEqual(result.exitCode, 0, "exitCode must not be 0 for coerced strings");
120
+ assert.ok(
121
+ !result.verdict.includes("pass"),
122
+ "verdict must not contain 'pass' for coerced strings",
123
+ );
124
+ });
125
+ });
126
+
127
+ // ─── wrapArray coercion unit tests (#3585) ──────────────────────────────
128
+
129
+ describe("wrapArray coercion for simple string-array fields (#3585)", () => {
130
+ /**
131
+ * The wrapArray coercion logic extracted from db-tools.ts sliceCompleteExecute.
132
+ * Duplicated here so we can unit-test it directly.
133
+ */
134
+ function wrapArray(v: any): any[] {
135
+ return v == null ? [] : Array.isArray(v) ? v : [v];
136
+ }
137
+
138
+ test("null returns empty array", () => {
139
+ assert.deepEqual(wrapArray(null), []);
140
+ });
141
+
142
+ test("undefined returns empty array", () => {
143
+ assert.deepEqual(wrapArray(undefined), []);
144
+ });
145
+
146
+ test("plain string wraps into single-element array", () => {
147
+ assert.deepEqual(
148
+ wrapArray("Validated Tech UI flows and Portal self-service flows"),
149
+ ["Validated Tech UI flows and Portal self-service flows"],
150
+ );
151
+ });
152
+
153
+ test("array passes through unchanged", () => {
154
+ const arr = ["item1", "item2"];
155
+ assert.deepEqual(wrapArray(arr), arr);
156
+ });
157
+
158
+ test("empty array passes through unchanged", () => {
159
+ assert.deepEqual(wrapArray([]), []);
160
+ });
161
+ });
162
+
163
+ // ─── Handler integration with coerced params ─────────────────────────────
164
+
165
+ describe("handleCompleteSlice with coerced string arrays (#3565)", () => {
166
+ let dbPath: string;
167
+ let basePath: string;
168
+
169
+ beforeEach(() => {
170
+ dbPath = path.join(
171
+ fs.mkdtempSync(path.join(os.tmpdir(), "gsd-coerce-")),
172
+ "test.db",
173
+ );
174
+ openDatabase(dbPath);
175
+
176
+ basePath = fs.mkdtempSync(path.join(os.tmpdir(), "gsd-coerce-handler-"));
177
+ const sliceDir = path.join(basePath, ".gsd", "milestones", "M001", "slices", "S01", "tasks");
178
+ fs.mkdirSync(sliceDir, { recursive: true });
179
+
180
+ const roadmapPath = path.join(basePath, ".gsd", "milestones", "M001", "M001-ROADMAP.md");
181
+ fs.writeFileSync(
182
+ roadmapPath,
183
+ [
184
+ "# M001: Test Milestone",
185
+ "",
186
+ "## Slices",
187
+ "",
188
+ '- [ ] **S01: Test Slice** `risk:medium` `depends:[]`',
189
+ " - After this: basic functionality works",
190
+ ].join("\n"),
191
+ );
192
+
193
+ insertMilestone({ id: "M001" });
194
+ insertSlice({ id: "S01", milestoneId: "M001" });
195
+ insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", status: "complete", title: "Task 1" });
196
+ });
197
+
198
+ afterEach(() => {
199
+ closeDatabase();
200
+ fs.rmSync(path.dirname(dbPath), { recursive: true, force: true });
201
+ fs.rmSync(basePath, { recursive: true, force: true });
202
+ });
203
+
204
+ test("handler succeeds with coerced filesModified and requirementsAdvanced", async () => {
205
+ const params = makeValidSliceParams();
206
+ // Simulate coercion from plain strings
207
+ params.filesModified = ["src/foo.ts", "src/bar.ts"].map((f) => {
208
+ const [p, d] = splitPair(f);
209
+ return { path: p, description: d };
210
+ });
211
+ params.requirementsAdvanced = ["R001 — Handler validates task completion"].map((r) => {
212
+ const [id, how] = splitPair(r);
213
+ return { id, how };
214
+ });
215
+
216
+ const result = await handleCompleteSlice(params, basePath);
217
+ assert.ok(!("error" in result), "handler should succeed");
218
+ if (!("error" in result)) {
219
+ const summary = fs.readFileSync(result.summaryPath, "utf-8");
220
+ assert.match(summary, /src\/foo\.ts/);
221
+ assert.match(summary, /R001/);
222
+ assert.match(summary, /Handler validates task completion/);
223
+ }
224
+ });
225
+
226
+ test("handler succeeds with coerced requires and requirementsValidated", async () => {
227
+ const params = makeValidSliceParams();
228
+ params.requires = ["S00 — Provided base infrastructure"].map((r) => {
229
+ const [slice, provides] = splitPair(r);
230
+ return { slice, provides };
231
+ });
232
+ params.requirementsValidated = ["R002 - Tests pass"].map((r) => {
233
+ const [id, proof] = splitPair(r);
234
+ return { id, proof };
235
+ });
236
+
237
+ const result = await handleCompleteSlice(params, basePath);
238
+ assert.ok(!("error" in result), "handler should succeed");
239
+ if (!("error" in result)) {
240
+ const summary = fs.readFileSync(result.summaryPath, "utf-8");
241
+ assert.match(summary, /S00/);
242
+ assert.match(summary, /Provided base infrastructure/);
243
+ assert.match(summary, /R002/);
244
+ assert.match(summary, /Tests pass/);
245
+ }
246
+ });
247
+ });
@@ -449,6 +449,45 @@ console.log('\n=== complete-task: handler with missing plan file ===');
449
449
  cleanup(dbPath);
450
450
  }
451
451
 
452
+ // ═══════════════════════════════════════════════════════════════════════════
453
+ // complete-task: minimal params — no optional fields (#2771 regression)
454
+ // ═══════════════════════════════════════════════════════════════════════════
455
+
456
+ console.log('\n=== complete-task: minimal params (no keyFiles, keyDecisions, verificationEvidence, blockerDiscovered) ===');
457
+ {
458
+ const dbPath = tempDbPath();
459
+ openDatabase(dbPath);
460
+
461
+ const { basePath, planPath } = createTempProject();
462
+
463
+ insertMilestone({ id: 'M001', title: 'Test Milestone' });
464
+ insertSlice({ id: 'S01', milestoneId: 'M001', title: 'Test Slice' });
465
+
466
+ // Minimal params — only required fields, all optional enrichment fields omitted
467
+ const minimalParams = {
468
+ taskId: 'T01',
469
+ sliceId: 'S01',
470
+ milestoneId: 'M001',
471
+ oneLiner: 'Basic task',
472
+ narrative: 'Did the work.',
473
+ verification: 'Looks good.',
474
+ // keyFiles, keyDecisions, verificationEvidence, blockerDiscovered intentionally omitted
475
+ };
476
+
477
+ const result = await handleCompleteTask(minimalParams as any, basePath);
478
+
479
+ assertTrue(!('error' in result), 'handler should not crash with minimal params (no optional fields)');
480
+ if (!('error' in result)) {
481
+ assertTrue(fs.existsSync(result.summaryPath), 'summary file should be written with minimal params');
482
+ const summaryContent = fs.readFileSync(result.summaryPath, 'utf-8');
483
+ assertMatch(summaryContent, /blocker_discovered:\s*false/, 'blocker_discovered should default to false');
484
+ assertMatch(summaryContent, /\(none\)/, 'key_files/key_decisions should show (none) placeholder');
485
+ }
486
+
487
+ cleanupDir(basePath);
488
+ cleanup(dbPath);
489
+ }
490
+
452
491
  // ═══════════════════════════════════════════════════════════════════════════
453
492
 
454
493
  report();
@@ -0,0 +1,107 @@
1
+ /**
2
+ * dashboard-model-label-ordering.test.ts — Regression test for #2899.
3
+ *
4
+ * The dashboard model label was showing the previous unit's model because
5
+ * updateProgressWidget was called before selectAndApplyModel in phases.ts.
6
+ * This test verifies:
7
+ * 1. updateProgressWidget is called AFTER selectAndApplyModel in phases.ts
8
+ * 2. session.ts has a currentDispatchedModelId field
9
+ * 3. auto.ts exposes getCurrentDispatchedModelId in widgetStateAccessors
10
+ * 4. auto-dashboard.ts reads from a dispatched model accessor, not cmdCtx?.model
11
+ */
12
+
13
+ import { readFileSync } from "node:fs";
14
+ import { join } from "node:path";
15
+ import { createTestContext } from "./test-helpers.ts";
16
+
17
+ const { assertTrue, assertMatch, report } = createTestContext();
18
+
19
+ const phasesPath = join(import.meta.dirname, "..", "auto", "phases.ts");
20
+ const sessionPath = join(import.meta.dirname, "..", "auto", "session.ts");
21
+ const autoPath = join(import.meta.dirname, "..", "auto.ts");
22
+ const dashboardPath = join(import.meta.dirname, "..", "auto-dashboard.ts");
23
+
24
+ const phasesSrc = readFileSync(phasesPath, "utf-8");
25
+ const sessionSrc = readFileSync(sessionPath, "utf-8");
26
+ const autoSrc = readFileSync(autoPath, "utf-8");
27
+ const dashboardSrc = readFileSync(dashboardPath, "utf-8");
28
+
29
+ console.log("\n=== #2899: Dashboard model label shows correct (dispatched) model ===");
30
+
31
+ // ── Test 1: updateProgressWidget is called AFTER selectAndApplyModel ──────
32
+
33
+ // Find the positions of the calls in the dispatch function body.
34
+ // selectAndApplyModel must appear BEFORE updateProgressWidget.
35
+ const selectModelPos = phasesSrc.indexOf("deps.selectAndApplyModel(");
36
+ const updateWidgetPos = phasesSrc.indexOf("deps.updateProgressWidget(");
37
+
38
+ assertTrue(
39
+ selectModelPos > 0,
40
+ "phases.ts contains deps.selectAndApplyModel call",
41
+ );
42
+
43
+ assertTrue(
44
+ updateWidgetPos > 0,
45
+ "phases.ts contains deps.updateProgressWidget call",
46
+ );
47
+
48
+ assertTrue(
49
+ selectModelPos < updateWidgetPos,
50
+ `selectAndApplyModel (pos ${selectModelPos}) must be called BEFORE updateProgressWidget (pos ${updateWidgetPos}) — widget needs fresh model`,
51
+ );
52
+
53
+ // ── Test 2: session.ts declares currentDispatchedModelId ──────────────────
54
+
55
+ assertTrue(
56
+ sessionSrc.includes("currentDispatchedModelId"),
57
+ "session.ts has currentDispatchedModelId field",
58
+ );
59
+
60
+ // ── Test 3: auto.ts exposes getCurrentDispatchedModelId in widgetStateAccessors ──
61
+
62
+ assertTrue(
63
+ autoSrc.includes("getCurrentDispatchedModelId"),
64
+ "auto.ts exposes getCurrentDispatchedModelId accessor",
65
+ );
66
+
67
+ // Verify it's in the widgetStateAccessors object
68
+ const accessorsBlock = autoSrc.slice(
69
+ autoSrc.indexOf("const widgetStateAccessors"),
70
+ autoSrc.indexOf("};", autoSrc.indexOf("const widgetStateAccessors")) + 2,
71
+ );
72
+
73
+ assertTrue(
74
+ accessorsBlock.includes("getCurrentDispatchedModelId"),
75
+ "getCurrentDispatchedModelId is in the widgetStateAccessors object",
76
+ );
77
+
78
+ // ── Test 4: WidgetStateAccessors interface has getCurrentDispatchedModelId ──
79
+
80
+ assertTrue(
81
+ dashboardSrc.includes("getCurrentDispatchedModelId"),
82
+ "auto-dashboard.ts references getCurrentDispatchedModelId",
83
+ );
84
+
85
+ // The dashboard render closure should NOT read model from cmdCtx?.model for display.
86
+ // It should use the accessor for the dispatched model ID.
87
+ // Check that the "Model display" section uses the accessor, not cmdCtx?.model directly.
88
+ const modelDisplaySection = dashboardSrc.slice(
89
+ dashboardSrc.indexOf("// Model display"),
90
+ dashboardSrc.indexOf("// Model display") + 500,
91
+ );
92
+
93
+ assertTrue(
94
+ modelDisplaySection.includes("getCurrentDispatchedModelId") ||
95
+ modelDisplaySection.includes("getDispatchedModelId"),
96
+ "Model display section reads from dispatched model accessor, not cmdCtx?.model alone",
97
+ );
98
+
99
+ // ── Test 5: currentDispatchedModelId is set after selectAndApplyModel in phases.ts ──
100
+
101
+ // After selectAndApplyModel returns, phases.ts should store the dispatched model ID
102
+ assertTrue(
103
+ phasesSrc.includes("currentDispatchedModelId"),
104
+ "phases.ts stores currentDispatchedModelId after model selection",
105
+ );
106
+
107
+ report();
@@ -0,0 +1,109 @@
1
+ // GSD2 — Regression tests: DB anti-pattern guardrails in prompt templates
2
+
3
+ import test from "node:test";
4
+ import assert from "node:assert/strict";
5
+ import { readFileSync, readdirSync } from "node:fs";
6
+ import { join } from "node:path";
7
+
8
+ const promptsDir = join(process.cwd(), "src/resources/extensions/gsd/prompts");
9
+
10
+ function readPrompt(name: string): string {
11
+ return readFileSync(join(promptsDir, `${name}.md`), "utf-8");
12
+ }
13
+
14
+ // ─── Layer 1: system.md global guardrail ──────────────────────────────────────
15
+
16
+ test("system.md anti-patterns section prohibits direct .gsd/gsd.db access", () => {
17
+ const prompt = readPrompt("system");
18
+ assert.match(
19
+ prompt,
20
+ /Never query.*\.gsd\/gsd\.db.*directly/i,
21
+ "system.md must prohibit direct .gsd/gsd.db access in the anti-patterns section",
22
+ );
23
+ assert.match(prompt, /sqlite3/, "system.md DB guardrail must name the sqlite3 CLI");
24
+ assert.match(prompt, /better-sqlite3/, "system.md DB guardrail must name better-sqlite3");
25
+ assert.match(prompt, /gsd_\*/, "system.md DB guardrail must redirect to gsd_* tools");
26
+ });
27
+
28
+ test("system.md DB guardrail explains single-writer WAL risk", () => {
29
+ const prompt = readPrompt("system");
30
+ assert.match(prompt, /single-writer WAL/i, "system.md must explain the WAL architecture risk");
31
+ });
32
+
33
+ // ─── Layer 2: high-risk prompt guardrails ─────────────────────────────────────
34
+
35
+ test("validate-milestone.md contains DB access safety guardrail with tool redirect", () => {
36
+ const prompt = readPrompt("validate-milestone");
37
+ assert.match(prompt, /DB access safety/i, "validate-milestone.md must have DB access safety section");
38
+ assert.match(prompt, /gsd_milestone_status/, "validate-milestone.md must name gsd_milestone_status as alternative");
39
+ assert.match(prompt, /Do NOT query.*\.gsd\/gsd\.db/i, "validate-milestone.md must prohibit direct DB queries");
40
+ });
41
+
42
+ test("complete-milestone.md contains DB access safety guardrail with tool redirect", () => {
43
+ const prompt = readPrompt("complete-milestone");
44
+ assert.match(prompt, /DB access safety/i, "complete-milestone.md must have DB access safety section");
45
+ assert.match(prompt, /gsd_milestone_status/, "complete-milestone.md must name gsd_milestone_status as alternative");
46
+ assert.match(prompt, /Do NOT query.*\.gsd\/gsd\.db/i, "complete-milestone.md must prohibit direct DB queries");
47
+ });
48
+
49
+ test("doctor-heal.md contains DB access guardrail naming gsd_milestone_status", () => {
50
+ const prompt = readPrompt("doctor-heal");
51
+ assert.match(prompt, /gsd_milestone_status/, "doctor-heal.md must name gsd_milestone_status as the DB inspection tool");
52
+ assert.match(prompt, /Do NOT query.*\.gsd\/gsd\.db/i, "doctor-heal.md must prohibit direct DB queries");
53
+ });
54
+
55
+ test("forensics.md contains DB inspection guardrail", () => {
56
+ const prompt = readPrompt("forensics");
57
+ assert.match(prompt, /gsd_milestone_status/, "forensics.md must name gsd_milestone_status as the DB inspection tool");
58
+ assert.match(prompt, /sqlite3.*\.gsd\/gsd\.db/i, "forensics.md must prohibit sqlite3 against .gsd/gsd.db");
59
+ });
60
+
61
+ test("reassess-roadmap.md contains DB access safety guardrail", () => {
62
+ const prompt = readPrompt("reassess-roadmap");
63
+ assert.match(prompt, /DB access safety/i, "reassess-roadmap.md must have DB access safety section");
64
+ assert.match(prompt, /gsd_milestone_status/, "reassess-roadmap.md must name gsd_milestone_status as alternative");
65
+ });
66
+
67
+ // ─── Negative assertion: no prompt instructs running sqlite3 as a command ─────
68
+
69
+ test("no prompt file contains an unguarded sqlite3 command invocation", () => {
70
+ const files = readdirSync(promptsDir).filter((f) => f.endsWith(".md"));
71
+ assert.ok(files.length >= 35, `Expected at least 35 prompt files, found ${files.length}`);
72
+
73
+ const violations: string[] = [];
74
+
75
+ for (const file of files) {
76
+ const content = readFileSync(join(promptsDir, file), "utf-8");
77
+ const lines = content.split("\n");
78
+
79
+ for (let i = 0; i < lines.length; i++) {
80
+ const line = lines[i];
81
+ const trimmed = line.trim();
82
+
83
+ // Match lines containing sqlite3 targeting gsd.db in any common form:
84
+ // sqlite3 .gsd/gsd.db, sqlite3 ./.gsd/gsd.db, sqlite3 "/path/.gsd/gsd.db",
85
+ // sqlite3 -header .gsd/gsd.db, etc.
86
+ // Guardrail text that says "Never run" or "Do NOT query" is fine — only flag
87
+ // lines where these appear without a surrounding prohibition keyword.
88
+ if (/sqlite3\b.*gsd\.db/.test(trimmed)) {
89
+ const context = lines.slice(Math.max(0, i - 3), i + 1).join(" ");
90
+ if (!/Never|Do NOT|do not|don't|prohibited|forbidden|never run/i.test(context)) {
91
+ violations.push(`${file}:${i + 1} — unguarded sqlite3 command: ${trimmed}`);
92
+ }
93
+ }
94
+ // Match node -e with better-sqlite3 require in any quoting style
95
+ if (/node\s+-e\s+.*(?:require|import).*better-sqlite3/.test(trimmed)) {
96
+ const context = lines.slice(Math.max(0, i - 3), i + 1).join(" ");
97
+ if (!/Never|Do NOT|do not|don't|prohibited|forbidden|never run/i.test(context)) {
98
+ violations.push(`${file}:${i + 1} — unguarded node -e require command: ${trimmed}`);
99
+ }
100
+ }
101
+ }
102
+ }
103
+
104
+ assert.deepEqual(
105
+ violations,
106
+ [],
107
+ `Found prompts with unguarded sqlite3/better-sqlite3 invocations:\n${violations.join("\n")}`,
108
+ );
109
+ });