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
@@ -25,46 +25,60 @@ import { logWarning } from "../workflow-logger.js";
25
25
  */
26
26
  function renderSliceSummaryMarkdown(params) {
27
27
  const now = new Date().toISOString();
28
- const providesYaml = params.provides.length > 0
29
- ? params.provides.map(p => ` - ${p}`).join("\n")
28
+ // Apply defaults for optional enrichment arrays (#2771)
29
+ const provides = params.provides ?? [];
30
+ const requires = params.requires ?? [];
31
+ const affects = params.affects ?? [];
32
+ const keyFiles = params.keyFiles ?? [];
33
+ const keyDecisions = params.keyDecisions ?? [];
34
+ const patternsEstablished = params.patternsEstablished ?? [];
35
+ const observabilitySurfaces = params.observabilitySurfaces ?? [];
36
+ const drillDownPaths = params.drillDownPaths ?? [];
37
+ const requirementsAdvanced = params.requirementsAdvanced ?? [];
38
+ const requirementsValidated = params.requirementsValidated ?? [];
39
+ const requirementsSurfaced = params.requirementsSurfaced ?? [];
40
+ const requirementsInvalidated = params.requirementsInvalidated ?? [];
41
+ const filesModified = params.filesModified ?? [];
42
+ const providesYaml = provides.length > 0
43
+ ? provides.map(p => ` - ${p}`).join("\n")
30
44
  : " - (none)";
31
- const requiresYaml = params.requires.length > 0
32
- ? params.requires.map(r => ` - slice: ${r.slice}\n provides: ${r.provides}`).join("\n")
45
+ const requiresYaml = requires.length > 0
46
+ ? requires.map(r => ` - slice: ${r.slice}\n provides: ${r.provides}`).join("\n")
33
47
  : " []";
34
- const affectsYaml = params.affects.length > 0
35
- ? params.affects.map(a => ` - ${a}`).join("\n")
48
+ const affectsYaml = affects.length > 0
49
+ ? affects.map(a => ` - ${a}`).join("\n")
36
50
  : " []";
37
- const keyFilesYaml = params.keyFiles.length > 0
38
- ? params.keyFiles.map(f => ` - ${f}`).join("\n")
51
+ const keyFilesYaml = keyFiles.length > 0
52
+ ? keyFiles.map(f => ` - ${f}`).join("\n")
39
53
  : " - (none)";
40
- const keyDecisionsYaml = params.keyDecisions.length > 0
41
- ? params.keyDecisions.map(d => ` - ${d}`).join("\n")
54
+ const keyDecisionsYaml = keyDecisions.length > 0
55
+ ? keyDecisions.map(d => ` - ${d}`).join("\n")
42
56
  : " - (none)";
43
- const patternsYaml = params.patternsEstablished.length > 0
44
- ? params.patternsEstablished.map(p => ` - ${p}`).join("\n")
57
+ const patternsYaml = patternsEstablished.length > 0
58
+ ? patternsEstablished.map(p => ` - ${p}`).join("\n")
45
59
  : " - (none)";
46
- const observabilityYaml = params.observabilitySurfaces.length > 0
47
- ? params.observabilitySurfaces.map(o => ` - ${o}`).join("\n")
60
+ const observabilityYaml = observabilitySurfaces.length > 0
61
+ ? observabilitySurfaces.map(o => ` - ${o}`).join("\n")
48
62
  : " - none";
49
- const drillDownYaml = params.drillDownPaths.length > 0
50
- ? params.drillDownPaths.map(d => ` - ${d}`).join("\n")
63
+ const drillDownYaml = drillDownPaths.length > 0
64
+ ? drillDownPaths.map(d => ` - ${d}`).join("\n")
51
65
  : " []";
52
66
  // Requirements sections
53
- const reqAdvanced = params.requirementsAdvanced.length > 0
54
- ? params.requirementsAdvanced.map(r => `- ${r.id} — ${r.how}`).join("\n")
67
+ const reqAdvanced = requirementsAdvanced.length > 0
68
+ ? requirementsAdvanced.map(r => `- ${r.id} — ${r.how}`).join("\n")
55
69
  : "None.";
56
- const reqValidated = params.requirementsValidated.length > 0
57
- ? params.requirementsValidated.map(r => `- ${r.id} — ${r.proof}`).join("\n")
70
+ const reqValidated = requirementsValidated.length > 0
71
+ ? requirementsValidated.map(r => `- ${r.id} — ${r.proof}`).join("\n")
58
72
  : "None.";
59
- const reqSurfaced = params.requirementsSurfaced.length > 0
60
- ? params.requirementsSurfaced.map(r => `- ${r}`).join("\n")
73
+ const reqSurfaced = requirementsSurfaced.length > 0
74
+ ? requirementsSurfaced.map(r => `- ${r}`).join("\n")
61
75
  : "None.";
62
- const reqInvalidated = params.requirementsInvalidated.length > 0
63
- ? params.requirementsInvalidated.map(r => `- ${r.id} — ${r.what}`).join("\n")
76
+ const reqInvalidated = requirementsInvalidated.length > 0
77
+ ? requirementsInvalidated.map(r => `- ${r.id} — ${r.what}`).join("\n")
64
78
  : "None.";
65
79
  // Files modified
66
- const filesMod = params.filesModified.length > 0
67
- ? params.filesModified.map(f => `- \`${f.path}\` — ${f.description}`).join("\n")
80
+ const filesMod = filesModified.length > 0
81
+ ? filesModified.map(f => `- \`${f.path}\` — ${f.description}`).join("\n")
68
82
  : "None.";
69
83
  return `---
70
84
  id: ${params.sliceId}
@@ -35,11 +35,11 @@ function paramsToTaskRow(params, completedAt) {
35
35
  verification_result: params.verification,
36
36
  duration: "",
37
37
  completed_at: completedAt,
38
- blocker_discovered: params.blockerDiscovered,
39
- deviations: params.deviations,
40
- known_issues: params.knownIssues,
41
- key_files: params.keyFiles,
42
- key_decisions: params.keyDecisions,
38
+ blocker_discovered: params.blockerDiscovered ?? false,
39
+ deviations: params.deviations ?? "",
40
+ known_issues: params.knownIssues ?? "",
41
+ key_files: params.keyFiles ?? [],
42
+ key_decisions: params.keyDecisions ?? [],
43
43
  full_summary_md: "",
44
44
  description: "",
45
45
  estimate: "",
@@ -113,13 +113,13 @@ export async function handleCompleteTask(params, basePath) {
113
113
  narrative: params.narrative,
114
114
  verificationResult: params.verification,
115
115
  duration: "",
116
- blockerDiscovered: params.blockerDiscovered,
117
- deviations: params.deviations,
118
- knownIssues: params.knownIssues,
119
- keyFiles: params.keyFiles,
120
- keyDecisions: params.keyDecisions,
116
+ blockerDiscovered: params.blockerDiscovered ?? false,
117
+ deviations: params.deviations ?? "None.",
118
+ knownIssues: params.knownIssues ?? "None.",
119
+ keyFiles: params.keyFiles ?? [],
120
+ keyDecisions: params.keyDecisions ?? [],
121
121
  });
122
- for (const evidence of params.verificationEvidence) {
122
+ for (const evidence of (params.verificationEvidence ?? [])) {
123
123
  insertVerificationEvidence({
124
124
  taskId: params.taskId,
125
125
  sliceId: params.sliceId,
@@ -139,7 +139,7 @@ export async function handleCompleteTask(params, basePath) {
139
139
  // verifyExpectedArtifact() stay consistent (both say "not done").
140
140
  // Render summary markdown via the single source of truth (#2720)
141
141
  const taskRow = paramsToTaskRow(params, completedAt);
142
- const summaryMd = renderSummaryContent(taskRow, params.sliceId, params.milestoneId, params.verificationEvidence);
142
+ const summaryMd = renderSummaryContent(taskRow, params.sliceId, params.milestoneId, params.verificationEvidence ?? []);
143
143
  // Resolve and write summary to disk
144
144
  let summaryPath;
145
145
  const tasksDir = resolveTasksDir(basePath, params.milestoneId, params.sliceId);
@@ -1,7 +1,7 @@
1
1
  import { clearParseCache } from "../files.js";
2
2
  import { isClosedStatus } from "../status-guards.js";
3
3
  import { isNonEmptyString, validateStringArray } from "../validation.js";
4
- import { transaction, getMilestone, getMilestoneSlices, insertMilestone, insertSlice, upsertMilestonePlanning, upsertSlicePlanning, } from "../gsd-db.js";
4
+ import { transaction, getMilestone, getMilestoneSlices, getSlice, insertMilestone, insertSlice, upsertMilestonePlanning, upsertSlicePlanning, } from "../gsd-db.js";
5
5
  import { invalidateStateCache } from "../state.js";
6
6
  import { renderRoadmapFromDb } from "../markdown-renderer.js";
7
7
  import { renderAllProjections } from "../workflow-projections.js";
@@ -106,25 +106,20 @@ function validateParams(params) {
106
106
  throw new Error("title is required");
107
107
  if (!isNonEmptyString(params?.vision))
108
108
  throw new Error("vision is required");
109
- if (!isNonEmptyString(params?.verificationContract))
110
- throw new Error("verificationContract is required");
111
- if (!isNonEmptyString(params?.verificationIntegration))
112
- throw new Error("verificationIntegration is required");
113
- if (!isNonEmptyString(params?.verificationOperational))
114
- throw new Error("verificationOperational is required");
115
- if (!isNonEmptyString(params?.verificationUat))
116
- throw new Error("verificationUat is required");
117
- if (!isNonEmptyString(params?.requirementCoverage))
118
- throw new Error("requirementCoverage is required");
119
- if (!isNonEmptyString(params?.boundaryMapMarkdown))
120
- throw new Error("boundaryMapMarkdown is required");
121
109
  return {
122
110
  ...params,
123
111
  dependsOn: params.dependsOn ? validateStringArray(params.dependsOn, "dependsOn") : [],
124
- successCriteria: validateStringArray(params.successCriteria, "successCriteria"),
125
- keyRisks: validateRiskEntries(params.keyRisks),
126
- proofStrategy: validateProofStrategy(params.proofStrategy),
127
- definitionOfDone: validateStringArray(params.definitionOfDone, "definitionOfDone"),
112
+ // Apply defaults for optional enrichment fields (#2771)
113
+ successCriteria: params.successCriteria ? validateStringArray(params.successCriteria, "successCriteria") : [],
114
+ keyRisks: params.keyRisks ? validateRiskEntries(params.keyRisks) : [],
115
+ proofStrategy: params.proofStrategy ? validateProofStrategy(params.proofStrategy) : [],
116
+ verificationContract: params.verificationContract ?? "Not provided.",
117
+ verificationIntegration: params.verificationIntegration ?? "Not provided.",
118
+ verificationOperational: params.verificationOperational ?? "Not provided.",
119
+ verificationUat: params.verificationUat ?? "Not provided.",
120
+ definitionOfDone: params.definitionOfDone ? validateStringArray(params.definitionOfDone, "definitionOfDone") : [],
121
+ requirementCoverage: params.requirementCoverage ?? "Not provided.",
122
+ boundaryMapMarkdown: params.boundaryMapMarkdown ?? "Not provided.",
128
123
  slices: validateSlices(params.slices),
129
124
  };
130
125
  }
@@ -147,15 +142,19 @@ export async function handlePlanMilestone(rawParams, basePath) {
147
142
  guardError = `cannot re-plan milestone ${params.milestoneId}: it is already complete`;
148
143
  return;
149
144
  }
150
- // Guard: refuse to re-plan a milestone that has completed slices (#2960).
151
- // INSERT OR IGNORE on slices won't overwrite existing rows, but a full
152
- // re-plan after worktree recreation or DB resync can create new slice rows
153
- // that shadow completed work. Block early when any slice is already done.
145
+ // Guard: refuse to re-plan a milestone that would drop completed slices (#2960).
146
+ // Allow re-planning when all completed slices are still present in the
147
+ // incoming plan their status is preserved below (#2558). Block only when
148
+ // the new plan omits a completed slice, which could shadow completed work.
154
149
  const existingSlices = getMilestoneSlices(params.milestoneId);
155
150
  const completedSlices = existingSlices.filter(s => isClosedStatus(s.status));
156
151
  if (completedSlices.length > 0) {
157
- guardError = `cannot re-plan milestone ${params.milestoneId}: ${completedSlices.length} slice(s) already completed (${completedSlices.map(s => s.id).join(", ")}). Use gsd_reassess_roadmap to modify the roadmap.`;
158
- return;
152
+ const incomingSliceIds = new Set(params.slices.map(s => s.sliceId));
153
+ const droppedCompleted = completedSlices.filter(s => !incomingSliceIds.has(s.id));
154
+ if (droppedCompleted.length > 0) {
155
+ guardError = `cannot re-plan milestone ${params.milestoneId}: ${droppedCompleted.length} completed slice(s) would be dropped (${droppedCompleted.map(s => s.id).join(", ")}). Use gsd_reassess_roadmap to modify the roadmap.`;
156
+ return;
157
+ }
159
158
  }
160
159
  // Validate depends_on: all dependencies must exist and be complete
161
160
  if (params.dependsOn && params.dependsOn.length > 0) {
@@ -178,6 +177,8 @@ export async function handlePlanMilestone(rawParams, basePath) {
178
177
  depends_on: params.dependsOn ?? [],
179
178
  });
180
179
  upsertMilestonePlanning(params.milestoneId, {
180
+ title: params.title,
181
+ status: params.status ?? "active",
181
182
  vision: params.vision,
182
183
  successCriteria: params.successCriteria,
183
184
  keyRisks: params.keyRisks,
@@ -189,13 +190,20 @@ export async function handlePlanMilestone(rawParams, basePath) {
189
190
  definitionOfDone: params.definitionOfDone,
190
191
  requirementCoverage: params.requirementCoverage,
191
192
  boundaryMapMarkdown: params.boundaryMapMarkdown,
192
- }, params.title);
193
+ });
193
194
  for (const slice of params.slices) {
195
+ // Preserve completed/done status on re-plan (#2558).
196
+ // Without this, a re-plan after milestone transition would reset
197
+ // already-completed slices back to "pending".
198
+ const existing = getSlice(params.milestoneId, slice.sliceId);
199
+ const status = existing && (existing.status === "complete" || existing.status === "done")
200
+ ? existing.status
201
+ : "pending";
194
202
  insertSlice({
195
203
  id: slice.sliceId,
196
204
  milestoneId: params.milestoneId,
197
205
  title: slice.title,
198
- status: "pending",
206
+ status,
199
207
  risk: slice.risk,
200
208
  depends: slice.depends,
201
209
  demo: slice.demo,
@@ -72,16 +72,13 @@ function validateParams(params) {
72
72
  throw new Error("sliceId is required");
73
73
  if (!isNonEmptyString(params?.goal))
74
74
  throw new Error("goal is required");
75
- if (!isNonEmptyString(params?.successCriteria))
76
- throw new Error("successCriteria is required");
77
- if (!isNonEmptyString(params?.proofLevel))
78
- throw new Error("proofLevel is required");
79
- if (!isNonEmptyString(params?.integrationClosure))
80
- throw new Error("integrationClosure is required");
81
- if (!isNonEmptyString(params?.observabilityImpact))
82
- throw new Error("observabilityImpact is required");
83
75
  return {
84
76
  ...params,
77
+ // Apply defaults for optional enrichment fields (#2771)
78
+ successCriteria: params.successCriteria ?? "Not provided.",
79
+ proofLevel: params.proofLevel ?? "Not provided.",
80
+ integrationClosure: params.integrationClosure ?? "Not provided.",
81
+ observabilityImpact: params.observabilityImpact ?? "Not provided.",
85
82
  tasks: validateTasks(params.tasks),
86
83
  };
87
84
  }
@@ -55,6 +55,24 @@ export function writeVerificationJSON(result, tasksDir, taskId, unitId, retryAtt
55
55
  const filePath = join(tasksDir, `${taskId}-VERIFY.json`);
56
56
  writeFileSync(filePath, JSON.stringify(evidence, null, 2) + "\n", "utf-8");
57
57
  }
58
+ /**
59
+ * Write pre-execution check results to a PRE-EXEC-VERIFY.json artifact
60
+ * in the slice directory.
61
+ */
62
+ export function writePreExecutionEvidence(result, sliceDir, milestoneId, sliceId) {
63
+ mkdirSync(sliceDir, { recursive: true });
64
+ const evidence = {
65
+ schemaVersion: 1,
66
+ milestoneId,
67
+ sliceId,
68
+ timestamp: Date.now(),
69
+ status: result.status,
70
+ durationMs: result.durationMs,
71
+ checks: result.checks,
72
+ };
73
+ const filePath = join(sliceDir, `${sliceId}-PRE-EXEC-VERIFY.json`);
74
+ writeFileSync(filePath, JSON.stringify(evidence, null, 2) + "\n", "utf-8");
75
+ }
58
76
  // ─── Markdown Evidence Table ─────────────────────────────────────────────────
59
77
  /**
60
78
  * Format duration in milliseconds as seconds with 1 decimal place.
@@ -17,6 +17,7 @@
17
17
  // Node process.
18
18
  import { appendFileSync, readFileSync, existsSync, mkdirSync } from "node:fs";
19
19
  import { join } from "node:path";
20
+ import { appendNotification } from "./notification-store.js";
20
21
  // ─── Buffer & Persistent Audit ──────────────────────────────────────────
21
22
  const MAX_BUFFER = 100;
22
23
  let _buffer = [];
@@ -179,6 +180,13 @@ function _push(severity, component, message, context) {
179
180
  const prefix = severity === "error" ? "ERROR" : "WARN";
180
181
  const ctxStr = context ? ` ${JSON.stringify(context)}` : "";
181
182
  process.stderr.write(`[gsd:${component}] ${prefix}: ${message}${ctxStr}\n`);
183
+ // Persist to notification store (both warnings and errors)
184
+ try {
185
+ appendNotification(`[${component}] ${message}`, severity === "error" ? "error" : "warning", "workflow-logger");
186
+ }
187
+ catch (notifErr) {
188
+ process.stderr.write(`[gsd:workflow-logger] notification-store append failed: ${notifErr.message}\n`);
189
+ }
182
190
  // Buffer for auto-loop to drain
183
191
  _buffer.push(entry);
184
192
  if (_buffer.length > MAX_BUFFER) {
@@ -7,6 +7,20 @@ import { join } from "node:path";
7
7
  import { mkdirSync, existsSync } from "node:fs";
8
8
  import { logWarning } from "./workflow-logger.js";
9
9
  import { deriveState } from "./state.js";
10
+ // ─── Helpers ─────────────────────────────────────────────────────────────
11
+ /**
12
+ * Strip a leading ID prefix (e.g. "M001: " or "S04: ") from a title
13
+ * to prevent double-prefixing when the renderer adds its own prefix.
14
+ * Handles repeated prefixes (e.g. "M001: M001: M001: Title" → "Title").
15
+ */
16
+ export function stripIdPrefix(title, id) {
17
+ const prefix = `${id}: `;
18
+ let result = title;
19
+ while (result.startsWith(prefix)) {
20
+ result = result.slice(prefix.length);
21
+ }
22
+ return result.trim() || title;
23
+ }
10
24
  // ─── PLAN.md Projection ──────────────────────────────────────────────────
11
25
  /**
12
26
  * Render PLAN.md content from a slice row and its task rows.
@@ -14,7 +28,8 @@ import { deriveState } from "./state.js";
14
28
  */
15
29
  export function renderPlanContent(sliceRow, taskRows) {
16
30
  const lines = [];
17
- lines.push(`# ${sliceRow.id}: ${sliceRow.title}`);
31
+ const displayTitle = stripIdPrefix(sliceRow.title, sliceRow.id);
32
+ lines.push(`# ${sliceRow.id}: ${displayTitle}`);
18
33
  lines.push("");
19
34
  // #2945: never use full_summary_md/full_uat_md as display fallbacks —
20
35
  // they contain multi-line rendered markdown that corrupts single-line fields.
@@ -71,7 +86,8 @@ export function renderPlanProjection(basePath, milestoneId, sliceId) {
71
86
  */
72
87
  export function renderRoadmapContent(milestoneRow, sliceRows) {
73
88
  const lines = [];
74
- lines.push(`# ${milestoneRow.id}: ${milestoneRow.title}`);
89
+ const displayTitle = stripIdPrefix(milestoneRow.title, milestoneRow.id);
90
+ lines.push(`# ${milestoneRow.id}: ${displayTitle}`);
75
91
  lines.push("");
76
92
  lines.push("## Vision");
77
93
  lines.push(milestoneRow.vision || milestoneRow.title || "TBD");
@@ -218,14 +234,14 @@ export function renderStateContent(state) {
218
234
  const lines = [];
219
235
  lines.push("# GSD State", "");
220
236
  const activeSlice = state.activeSlice
221
- ? `${state.activeSlice.id}: ${state.activeSlice.title}`
237
+ ? `${state.activeSlice.id}: ${stripIdPrefix(state.activeSlice.title, state.activeSlice.id)}`
222
238
  : "None";
223
239
  if (state.phase === 'complete' && state.lastCompletedMilestone) {
224
240
  lines.push(`**Last Completed Milestone:** ${state.lastCompletedMilestone.id}: ${state.lastCompletedMilestone.title}`);
225
241
  }
226
242
  else {
227
243
  const activeMilestone = state.activeMilestone
228
- ? `${state.activeMilestone.id}: ${state.activeMilestone.title}`
244
+ ? `${state.activeMilestone.id}: ${stripIdPrefix(state.activeMilestone.title, state.activeMilestone.id)}`
229
245
  : "None";
230
246
  lines.push(`**Active Milestone:** ${activeMilestone}`);
231
247
  }
@@ -238,7 +254,7 @@ export function renderStateContent(state) {
238
254
  lines.push("## Milestone Registry");
239
255
  for (const entry of state.registry) {
240
256
  const glyph = entry.status === "complete" ? "\u2705" : entry.status === "active" ? "\uD83D\uDD04" : entry.status === "parked" ? "\u23F8\uFE0F" : "\u2B1C";
241
- lines.push(`- ${glyph} **${entry.id}:** ${entry.title}`);
257
+ lines.push(`- ${glyph} **${entry.id}:** ${stripIdPrefix(entry.title, entry.id)}`);
242
258
  }
243
259
  lines.push("");
244
260
  lines.push("## Recent Decisions");
@@ -65,6 +65,21 @@ export function worktreePath(basePath, name) {
65
65
  export function worktreeBranchName(name) {
66
66
  return `worktree/${name}`;
67
67
  }
68
+ /**
69
+ * Validate that a path is inside the .gsd/worktrees/ directory.
70
+ * Resolves symlinks and normalizes ".." traversals before comparison
71
+ * so that a symlink-resolved or crafted path cannot escape containment.
72
+ *
73
+ * Used as a safety gate before any destructive operation (rmSync,
74
+ * nativeWorktreeRemove --force) to prevent #2365-style data loss.
75
+ */
76
+ export function isInsideWorktreesDir(basePath, targetPath) {
77
+ const wtDir = resolve(worktreesDir(basePath));
78
+ const resolved = resolve(targetPath);
79
+ // The resolved path must start with the worktrees dir followed by a separator,
80
+ // not merely be a prefix match (e.g. ".gsd/worktrees-extra" must not match).
81
+ return resolved === wtDir || resolved.startsWith(wtDir + sep);
82
+ }
68
83
  // ─── Core Operations ───────────────────────────────────────────────────────
69
84
  /**
70
85
  * Create a new git worktree under .gsd/worktrees/<name>/ with branch worktree/<name>.
@@ -286,17 +301,40 @@ export function removeWorktree(basePath, name, opts = {}) {
286
301
  // time, so its registered path points to the resolved external location.
287
302
  // If syncStateToProjectRoot later creates a real .gsd/ directory that
288
303
  // shadows the symlink, the computed path diverges from git's record.
304
+ let gitReportedPath = null;
289
305
  try {
290
306
  const entries = nativeWorktreeList(basePath);
291
307
  const entry = entries.find(e => e.branch === branch);
292
308
  if (entry?.path) {
293
- wtPath = entry.path;
309
+ gitReportedPath = entry.path;
294
310
  }
295
311
  }
296
312
  catch (e) {
297
313
  logWarning("worktree", `nativeWorktreeList parse failed: ${e.message}`);
298
314
  }
315
+ // Safety gate (#2365): only use the git-reported path if it is actually
316
+ // inside .gsd/worktrees/. When .gsd/ was a symlink, git may have resolved
317
+ // it to an external directory (e.g. a project data folder). Using that
318
+ // path for removal would destroy user data.
319
+ if (gitReportedPath && isInsideWorktreesDir(basePath, gitReportedPath)) {
320
+ wtPath = gitReportedPath;
321
+ }
322
+ else if (gitReportedPath) {
323
+ console.error(`[GSD] WARNING: git worktree list reported path outside .gsd/worktrees/: ${gitReportedPath}\n` +
324
+ ` Refusing to use it for removal — falling back to computed path: ${wtPath}`);
325
+ // Still tell git to unregister the worktree entry via its reported path,
326
+ // but do NOT use force and do NOT fall back to rmSync on this path.
327
+ try {
328
+ nativeWorktreeRemove(basePath, gitReportedPath, false);
329
+ }
330
+ catch (e) {
331
+ logWarning("worktree", `non-force worktree remove failed for ${gitReportedPath}: ${e instanceof Error ? e.message : String(e)}`);
332
+ }
333
+ }
299
334
  const resolvedWtPath = existsSync(wtPath) ? realpathSync(wtPath) : wtPath;
335
+ // Double-check: the resolved path (after symlink resolution) must also be
336
+ // inside .gsd/worktrees/ — a symlink inside the directory could point out.
337
+ const resolvedPathSafe = isInsideWorktreesDir(basePath, resolvedWtPath);
300
338
  // If we're inside the worktree, move out first — git can't remove an in-use directory
301
339
  const cwd = process.cwd();
302
340
  const resolvedCwd = existsSync(cwd) ? realpathSync(cwd) : cwd;
@@ -360,41 +398,56 @@ export function removeWorktree(basePath, name, opts = {}) {
360
398
  }
361
399
  }
362
400
  }
363
- // Remove worktree: try non-force first when submodules have changes,
364
- // falling back to force only after submodule state has been preserved.
365
- const useForce = hasSubmoduleChanges ? false : force;
366
- try {
367
- nativeWorktreeRemove(basePath, resolvedWtPath, useForce);
368
- }
369
- catch (e) {
370
- logWarning("worktree", `nativeWorktreeRemove failed: ${e.message}`);
371
- }
372
- // If the directory is still there (e.g. locked), try harder with force
373
- if (existsSync(resolvedWtPath)) {
401
+ // Remove worktree only use force/rmSync when the path is safely contained
402
+ if (resolvedPathSafe) {
403
+ // Remove worktree: try non-force first when submodules have changes,
404
+ // falling back to force only after submodule state has been preserved.
405
+ const useForce = hasSubmoduleChanges ? false : force;
374
406
  try {
375
- nativeWorktreeRemove(basePath, resolvedWtPath, true);
407
+ nativeWorktreeRemove(basePath, resolvedWtPath, useForce);
376
408
  }
377
409
  catch (e) {
378
- logWarning("worktree", `nativeWorktreeRemove (force) failed: ${e.message}`);
410
+ logWarning("worktree", `nativeWorktreeRemove failed: ${e.message}`);
411
+ }
412
+ // If the directory is still there (e.g. locked), try harder with force
413
+ if (existsSync(resolvedWtPath)) {
414
+ try {
415
+ nativeWorktreeRemove(basePath, resolvedWtPath, true);
416
+ }
417
+ catch (e) {
418
+ logWarning("worktree", `nativeWorktreeRemove (force) failed: ${e.message}`);
419
+ }
420
+ }
421
+ // (#2821) If the worktree directory STILL exists after both native removal
422
+ // attempts (e.g. untracked files like ASSESSMENT/UAT-RESULT prevent git
423
+ // worktree remove), force-remove the git internal worktree metadata first,
424
+ // then remove the filesystem directory. Without this, the .git/worktrees/<name>
425
+ // lock prevents rmSync from cleaning up, and the orphaned worktree directory
426
+ // causes every subsequent `/gsd auto` to re-enter the stale worktree.
427
+ if (existsSync(resolvedWtPath)) {
428
+ try {
429
+ const wtInternalDir = join(basePath, ".git", "worktrees", name);
430
+ if (existsSync(wtInternalDir)) {
431
+ rmSync(wtInternalDir, { recursive: true, force: true });
432
+ }
433
+ rmSync(resolvedWtPath, { recursive: true, force: true });
434
+ }
435
+ catch {
436
+ logWarning("reconcile", `Worktree directory could not be removed after git internal cleanup: ${resolvedWtPath}. ` +
437
+ `Manual cleanup: rm -rf "${resolvedWtPath.replaceAll("\\", "/")}"`, { worktree: name });
438
+ }
379
439
  }
380
440
  }
381
- // (#2821) If the worktree directory STILL exists after both native removal
382
- // attempts (e.g. untracked files like ASSESSMENT/UAT-RESULT prevent git
383
- // worktree remove), force-remove the git internal worktree metadata first,
384
- // then remove the filesystem directory. Without this, the .git/worktrees/<name>
385
- // lock prevents rmSync from cleaning up, and the orphaned worktree directory
386
- // causes every subsequent `/gsd auto` to re-enter the stale worktree.
387
- if (existsSync(resolvedWtPath)) {
441
+ else {
442
+ // Path is outside containment only do a non-force git worktree remove
443
+ // (which refuses to delete dirty worktrees) and never fall back to rmSync.
444
+ console.error(`[GSD] WARNING: Resolved worktree path is outside .gsd/worktrees/: ${resolvedWtPath}\n` +
445
+ ` Skipping forced removal to prevent data loss.`);
388
446
  try {
389
- const wtInternalDir = join(basePath, ".git", "worktrees", name);
390
- if (existsSync(wtInternalDir)) {
391
- rmSync(wtInternalDir, { recursive: true, force: true });
392
- }
393
- rmSync(resolvedWtPath, { recursive: true, force: true });
447
+ nativeWorktreeRemove(basePath, resolvedWtPath, false);
394
448
  }
395
- catch {
396
- logWarning("reconcile", `Worktree directory could not be removed after git internal cleanup: ${resolvedWtPath}. ` +
397
- `Manual cleanup: rm -rf "${resolvedWtPath.replaceAll("\\", "/")}"`, { worktree: name });
449
+ catch (e) {
450
+ logWarning("worktree", `non-force worktree remove failed for ${resolvedWtPath}: ${e instanceof Error ? e.message : String(e)}`);
398
451
  }
399
452
  }
400
453
  // Prune stale entries so git knows the worktree is gone
@@ -365,9 +365,10 @@ export class WorktreeResolver {
365
365
  });
366
366
  // Surface a clear, actionable error. The worktree and milestone branch are
367
367
  // intentionally preserved — nothing has been deleted. The user can retry
368
- // /gsd dispatch complete-milestone or merge manually once the underlying issue is fixed
369
- // (e.g. checkout to wrong branch, unresolved conflicts). (#1668)
370
- ctx.notify(`Milestone merge failed: ${msg}. Your worktree and milestone branch are preserved — retry /gsd dispatch complete-milestone or merge manually.`, "warning");
368
+ // /gsd dispatch complete-milestone or merge manually once the underlying
369
+ // issue is fixed (e.g. checkout to wrong branch, unresolved conflicts).
370
+ // (#1668, #1891)
371
+ ctx.notify(`Milestone merge failed: ${msg}. Your worktree and milestone branch are preserved — retry with \`/gsd dispatch complete-milestone\` or merge manually.`, "warning");
371
372
  // Clean up stale merge state left by failed squash-merge (#1389)
372
373
  try {
373
374
  const gitDir = join(originalBase || this.s.basePath, ".git");
@@ -0,0 +1,101 @@
1
+ /**
2
+ * MCP Client OAuth / Auth helpers
3
+ *
4
+ * Builds transport options (headers, OAuthClientProvider) from MCP server
5
+ * config entries so that HTTP transports can authenticate with remote
6
+ * servers (Sentry, Linear, etc.).
7
+ *
8
+ * Fixes #2160 — MCP HTTP transport lacked an OAuth auth provider.
9
+ */
10
+ // ─── Env resolution ───────────────────────────────────────────────────────────
11
+ /** Resolve `${VAR}` references in a string against `process.env`. */
12
+ function resolveEnvValue(value) {
13
+ return value.replace(/\$\{([^}]+)\}/g, (_match, varName) => process.env[varName] ?? "");
14
+ }
15
+ function resolveHeaders(raw) {
16
+ const resolved = {};
17
+ for (const [key, value] of Object.entries(raw)) {
18
+ resolved[key] = typeof value === "string" ? resolveEnvValue(value) : value;
19
+ }
20
+ return resolved;
21
+ }
22
+ // ─── OAuth provider (minimal CLI-friendly implementation) ─────────────────────
23
+ /**
24
+ * Creates a minimal `OAuthClientProvider` suitable for CLI / headless use.
25
+ *
26
+ * This provider supports:
27
+ * - Pre-configured client credentials (client_id, optional client_secret)
28
+ * - Token storage in memory (per-session)
29
+ * - Scopes
30
+ *
31
+ * For full interactive OAuth flows (browser redirect), a richer provider would
32
+ * be needed, but for server-to-server and pre-authed scenarios this is
33
+ * sufficient.
34
+ */
35
+ function createCliOAuthProvider(config) {
36
+ let storedTokens;
37
+ let storedCodeVerifier = "";
38
+ return {
39
+ get redirectUrl() {
40
+ return config.redirectUrl ?? "http://localhost:0/callback";
41
+ },
42
+ get clientMetadata() {
43
+ return {
44
+ redirect_uris: [config.redirectUrl ?? "http://localhost:0/callback"],
45
+ client_name: "gsd",
46
+ ...(config.scopes ? { scope: config.scopes.join(" ") } : {}),
47
+ };
48
+ },
49
+ clientInformation() {
50
+ return {
51
+ client_id: config.clientId,
52
+ ...(config.clientSecret ? { client_secret: config.clientSecret } : {}),
53
+ };
54
+ },
55
+ tokens() {
56
+ return storedTokens;
57
+ },
58
+ saveTokens(tokens) {
59
+ storedTokens = tokens;
60
+ },
61
+ redirectToAuthorization(authorizationUrl) {
62
+ // In a CLI context we can't open a browser automatically.
63
+ // Log the URL so the user can manually visit it.
64
+ // eslint-disable-next-line no-console
65
+ console.error(`[MCP OAuth] Authorization required. Visit:\n ${authorizationUrl.toString()}`);
66
+ },
67
+ saveCodeVerifier(codeVerifier) {
68
+ storedCodeVerifier = codeVerifier;
69
+ },
70
+ codeVerifier() {
71
+ return storedCodeVerifier;
72
+ },
73
+ };
74
+ }
75
+ // ─── Public API ───────────────────────────────────────────────────────────────
76
+ /**
77
+ * Build `StreamableHTTPClientTransportOptions` from an MCP server config's
78
+ * auth-related fields.
79
+ *
80
+ * Supports two auth strategies:
81
+ * 1. **`headers`** — static Authorization (or other) headers, with `${VAR}` env resolution.
82
+ * 2. **`oauth`** — full OAuthClientProvider for servers that implement MCP OAuth.
83
+ *
84
+ * When both are provided, `oauth` takes precedence (the SDK's built-in OAuth
85
+ * flow handles token refresh automatically).
86
+ */
87
+ export function buildHttpTransportOpts(authConfig) {
88
+ const opts = {};
89
+ // OAuth takes precedence
90
+ if (authConfig.oauth) {
91
+ opts.authProvider = createCliOAuthProvider(authConfig.oauth);
92
+ return opts;
93
+ }
94
+ // Static headers (with env var resolution)
95
+ if (authConfig.headers && Object.keys(authConfig.headers).length > 0) {
96
+ opts.requestInit = {
97
+ headers: resolveHeaders(authConfig.headers),
98
+ };
99
+ }
100
+ return opts;
101
+ }