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
@@ -0,0 +1,42 @@
1
+ // GSD-2 — Regression test for #3616: reload() must reset jiti extension loader cache
2
+ // Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
3
+
4
+ import test, { describe } from "node:test";
5
+ import assert from "node:assert/strict";
6
+ import { readFileSync } from "node:fs";
7
+ import { join } from "node:path";
8
+
9
+ const source = readFileSync(
10
+ join(process.cwd(), "packages/pi-coding-agent/src/core/resource-loader.ts"),
11
+ "utf-8",
12
+ );
13
+
14
+ describe("#3616 — reload() must invalidate jiti module cache", () => {
15
+ test("resource-loader imports resetExtensionLoaderCache from loader.js", () => {
16
+ assert.ok(
17
+ source.includes("resetExtensionLoaderCache"),
18
+ "resource-loader.ts should import resetExtensionLoaderCache",
19
+ );
20
+ assert.ok(
21
+ source.includes('from "./extensions/loader.js"'),
22
+ "resetExtensionLoaderCache should be imported from extensions/loader.js",
23
+ );
24
+ });
25
+
26
+ test("reload() calls resetExtensionLoaderCache before loadExtensions", () => {
27
+ const reloadStart = source.indexOf("async reload(): Promise<void>");
28
+ assert.ok(reloadStart >= 0, "should find reload() method");
29
+ const reloadBody = source.slice(reloadStart, reloadStart + 4000);
30
+
31
+ const resetIdx = reloadBody.indexOf("resetExtensionLoaderCache()");
32
+ assert.ok(resetIdx >= 0, "reload() should call resetExtensionLoaderCache()");
33
+
34
+ const loadIdx = reloadBody.indexOf("loadExtensions(");
35
+ assert.ok(loadIdx >= 0, "reload() should call loadExtensions");
36
+
37
+ assert.ok(
38
+ resetIdx < loadIdx,
39
+ "resetExtensionLoaderCache() must be called BEFORE loadExtensions to ensure fresh modules",
40
+ );
41
+ });
42
+ });
@@ -1,6 +1,6 @@
1
1
  import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
- import { basename, dirname, join, resolve, sep } from "node:path";
3
+ import { basename, dirname, join, relative, resolve, sep } from "node:path";
4
4
  import chalk from "chalk";
5
5
  import { CONFIG_DIR_NAME, getAgentDir } from "../config.js";
6
6
  import { loadThemeFromPath, type Theme } from "../modes/interactive/theme/theme.js";
@@ -9,7 +9,7 @@ import type { ResourceCollision, ResourceDiagnostic } from "./diagnostics.js";
9
9
  export type { ResourceCollision, ResourceDiagnostic } from "./diagnostics.js";
10
10
 
11
11
  import { createEventBus, type EventBus } from "./event-bus.js";
12
- import { createExtensionRuntime, loadExtensionFromFactory, loadExtensions } from "./extensions/loader.js";
12
+ import { createExtensionRuntime, loadExtensionFromFactory, loadExtensions, resetExtensionLoaderCache } from "./extensions/loader.js";
13
13
  import type { Extension, ExtensionFactory, ExtensionRuntime, LoadExtensionsResult } from "./extensions/types.js";
14
14
  import { DefaultPackageManager, type PathMetadata } from "./package-manager.js";
15
15
  import type { PromptTemplate } from "./prompt-templates.js";
@@ -121,6 +121,7 @@ export interface DefaultResourceLoaderOptions {
121
121
  additionalPromptTemplatePaths?: string[];
122
122
  additionalThemePaths?: string[];
123
123
  extensionFactories?: ExtensionFactory[];
124
+ bundledExtensionKeys?: Set<string>;
124
125
  noExtensions?: boolean;
125
126
  noSkills?: boolean;
126
127
  noPromptTemplates?: boolean;
@@ -161,6 +162,7 @@ export class DefaultResourceLoader implements ResourceLoader {
161
162
  private settingsManager: SettingsManager;
162
163
  private eventBus: EventBus;
163
164
  private packageManager: DefaultPackageManager;
165
+ private bundledExtensionKeys: Set<string>;
164
166
  private additionalExtensionPaths: string[];
165
167
  private additionalSkillPaths: string[];
166
168
  private additionalPromptTemplatePaths: string[];
@@ -218,6 +220,7 @@ export class DefaultResourceLoader implements ResourceLoader {
218
220
  agentDir: this.agentDir,
219
221
  settingsManager: this.settingsManager,
220
222
  });
223
+ this.bundledExtensionKeys = options.bundledExtensionKeys ?? new Set();
221
224
  this.additionalExtensionPaths = options.additionalExtensionPaths ?? [];
222
225
  this.additionalSkillPaths = options.additionalSkillPaths ?? [];
223
226
  this.additionalPromptTemplatePaths = options.additionalPromptTemplatePaths ?? [];
@@ -317,6 +320,10 @@ export class DefaultResourceLoader implements ResourceLoader {
317
320
  }
318
321
 
319
322
  async reload(): Promise<void> {
323
+ // Invalidate the shared jiti module cache so updated extension code
324
+ // on disk is re-compiled instead of served from the stale cache (#3616).
325
+ resetExtensionLoaderCache();
326
+
320
327
  const resolvedPaths = await this.packageManager.resolve();
321
328
  const cliExtensionPaths = await this.packageManager.resolveExtensionSources(this.additionalExtensionPaths, {
322
329
  temporary: true,
@@ -827,66 +834,96 @@ export class DefaultResourceLoader implements ResourceLoader {
827
834
  }
828
835
 
829
836
  private detectExtensionConflicts(extensions: Extension[]): Array<{ path: string; message: string }> {
830
- const conflicts: Array<{ path: string; message: string }> = [];
831
-
832
- // Track which extension registered each tool, command, and flag
833
- const toolOwners = new Map<string, string>();
834
- const commandOwners = new Map<string, string>();
835
- const flagOwners = new Map<string, string>();
836
-
837
- for (const ext of extensions) {
838
- // Check tools
839
- for (const toolName of ext.tools.keys()) {
840
- const existingOwner = toolOwners.get(toolName);
841
- if (existingOwner && existingOwner !== ext.path) {
842
- // Determine if the existing owner is a bundled extension by checking
843
- // its name against the canonical bundled extensions list
844
- const ownerName = this.getExtensionNameFromPath(existingOwner);
845
- const isBuiltIn = this.bundledExtensionNames.has(ownerName);
846
- const hint = isBuiltIn
847
- ? ` (built-in tool supersedes — consider removing ${ext.path})`
848
- : "";
849
- conflicts.push({
850
- path: ext.path,
851
- message: `Tool "${toolName}" conflicts with ${existingOwner}${hint}`,
852
- });
853
- } else {
854
- toolOwners.set(toolName, ext.path);
855
- }
856
- }
837
+ return detectExtensionConflicts(extensions, this.bundledExtensionKeys, join(this.agentDir, "extensions"));
838
+ }
839
+ }
857
840
 
858
- // Check commands
859
- for (const commandName of ext.commands.keys()) {
860
- const existingOwner = commandOwners.get(commandName);
861
- if (existingOwner && existingOwner !== ext.path) {
862
- const ownerName = this.getExtensionNameFromPath(existingOwner);
863
- const isBuiltIn = this.bundledExtensionNames.has(ownerName);
864
- const hint = isBuiltIn
865
- ? ` (built-in command supersedes consider removing ${ext.path})`
866
- : "";
867
- conflicts.push({
868
- path: ext.path,
869
- message: `Command "/${commandName}" conflicts with ${existingOwner}${hint}`,
870
- });
871
- } else {
872
- commandOwners.set(commandName, ext.path);
873
- }
841
+ /**
842
+ * Extract the extension directory name (key) from a full extension path.
843
+ * Given extensionsDir `/home/user/.gsd/agent/extensions` and
844
+ * ownerPath `/home/user/.gsd/agent/extensions/mcp-client/index.js`,
845
+ * returns `"mcp-client"`. Returns `undefined` when the path is not
846
+ * under extensionsDir.
847
+ */
848
+ export function extractExtensionKey(ownerPath: string, extensionsDir: string): string | undefined {
849
+ const normalizedDir = resolve(extensionsDir);
850
+ const normalizedPath = resolve(ownerPath);
851
+ const prefix = normalizedDir.endsWith(sep) ? normalizedDir : `${normalizedDir}${sep}`;
852
+ if (!normalizedPath.startsWith(prefix)) {
853
+ return undefined;
854
+ }
855
+ const relPath = relative(normalizedDir, normalizedPath);
856
+ const firstSegment = relPath.split(/[\\/]/)[0];
857
+ return firstSegment?.replace(/\.(?:ts|js)$/, "") || undefined;
858
+ }
859
+
860
+ /**
861
+ * Detect tool/command/flag name collisions across loaded extensions.
862
+ *
863
+ * When the first-registered owner of a name is a bundled extension
864
+ * (its key appears in `bundledExtensionKeys`), the conflict message
865
+ * includes a "supersedes" hint so downstream display can downgrade the
866
+ * severity from "Extension load error" to "Extension conflict".
867
+ */
868
+ export function detectExtensionConflicts(
869
+ extensions: Extension[],
870
+ bundledExtensionKeys: Set<string>,
871
+ extensionsDir: string,
872
+ ): Array<{ path: string; message: string }> {
873
+ const conflicts: Array<{ path: string; message: string }> = [];
874
+
875
+ const toolOwners = new Map<string, string>();
876
+ const commandOwners = new Map<string, string>();
877
+ const flagOwners = new Map<string, string>();
878
+
879
+ const isBundled = (ownerPath: string): boolean => {
880
+ const key = extractExtensionKey(ownerPath, extensionsDir);
881
+ return key !== undefined && bundledExtensionKeys.has(key);
882
+ };
883
+
884
+ for (const ext of extensions) {
885
+ for (const toolName of ext.tools.keys()) {
886
+ const existingOwner = toolOwners.get(toolName);
887
+ if (existingOwner && existingOwner !== ext.path) {
888
+ const hint = isBundled(existingOwner)
889
+ ? ` (built-in tool supersedes — consider removing ${ext.path})`
890
+ : "";
891
+ conflicts.push({
892
+ path: ext.path,
893
+ message: `Tool "${toolName}" conflicts with ${existingOwner}${hint}`,
894
+ });
895
+ } else {
896
+ toolOwners.set(toolName, ext.path);
874
897
  }
898
+ }
875
899
 
876
- // Check flags
877
- for (const flagName of ext.flags.keys()) {
878
- const existingOwner = flagOwners.get(flagName);
879
- if (existingOwner && existingOwner !== ext.path) {
880
- conflicts.push({
881
- path: ext.path,
882
- message: `Flag "--${flagName}" conflicts with ${existingOwner}`,
883
- });
884
- } else {
885
- flagOwners.set(flagName, ext.path);
886
- }
900
+ for (const commandName of ext.commands.keys()) {
901
+ const existingOwner = commandOwners.get(commandName);
902
+ if (existingOwner && existingOwner !== ext.path) {
903
+ const hint = isBundled(existingOwner)
904
+ ? ` (built-in command supersedes — consider removing ${ext.path})`
905
+ : "";
906
+ conflicts.push({
907
+ path: ext.path,
908
+ message: `Command "/${commandName}" conflicts with ${existingOwner}${hint}`,
909
+ });
910
+ } else {
911
+ commandOwners.set(commandName, ext.path);
887
912
  }
888
913
  }
889
914
 
890
- return conflicts;
915
+ for (const flagName of ext.flags.keys()) {
916
+ const existingOwner = flagOwners.get(flagName);
917
+ if (existingOwner && existingOwner !== ext.path) {
918
+ conflicts.push({
919
+ path: ext.path,
920
+ message: `Flag "--${flagName}" conflicts with ${existingOwner}`,
921
+ });
922
+ } else {
923
+ flagOwners.set(flagName, ext.path);
924
+ }
925
+ }
891
926
  }
927
+
928
+ return conflicts;
892
929
  }
@@ -214,6 +214,16 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
214
214
  }
215
215
  }
216
216
 
217
+ // Flush extension provider registrations so extension-provided models (e.g. claude-code/*)
218
+ // are available in the registry before model resolution. Without this, findInitialModel()
219
+ // cannot find extension models and falls back to built-in providers (#3534).
220
+ const extensionsForModelResolution = resourceLoader.getExtensions();
221
+ for (const { name, config } of extensionsForModelResolution.runtime.pendingProviderRegistrations) {
222
+ modelRegistry.registerProvider(name, config);
223
+ }
224
+ // Clear the queue so bindCore() doesn't re-register the same providers.
225
+ extensionsForModelResolution.runtime.pendingProviderRegistrations = [];
226
+
217
227
  // If still no model, use findInitialModel (checks settings default, then provider defaults)
218
228
  if (!model) {
219
229
  const result = await findInitialModel({
package/pkg/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glittercowboy/gsd",
3
- "version": "2.63.0",
3
+ "version": "2.64.0",
4
4
  "piConfig": {
5
5
  "name": "gsd",
6
6
  "configDir": ".gsd"
@@ -1,12 +1,9 @@
1
- import { execFile, execFileSync } from "node:child_process";
1
+ import { execFileSync, spawn } from "node:child_process";
2
2
  import { existsSync } from "node:fs";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
- import { promisify } from "node:util";
6
5
  import type { GSDPreferences } from "../gsd/preferences.js";
7
6
  import type { GSDState, Phase } from "../gsd/types.js";
8
-
9
- const execFileAsync = promisify(execFile);
10
7
  const DEFAULT_SOCKET_PATH = "/tmp/cmux.sock";
11
8
  const STATUS_KEY = "gsd";
12
9
  const lastSidebarSnapshots = new Map<string, string>();
@@ -200,6 +197,7 @@ export class CmuxClient {
200
197
  return execFileSync("cmux", args, {
201
198
  encoding: "utf-8",
202
199
  timeout: 3000,
200
+ stdio: ["ignore", "pipe", "pipe"],
203
201
  env: process.env,
204
202
  });
205
203
  } catch {
@@ -209,16 +207,24 @@ export class CmuxClient {
209
207
 
210
208
  private async runAsync(args: string[]): Promise<string | null> {
211
209
  if (!this.canRun()) return null;
212
- try {
213
- const result = await execFileAsync("cmux", args, {
214
- encoding: "utf-8",
215
- timeout: 5000,
210
+ return new Promise<string | null>((resolve) => {
211
+ const child = spawn("cmux", args, {
212
+ stdio: ["ignore", "pipe", "pipe"],
216
213
  env: process.env,
217
214
  });
218
- return result.stdout;
219
- } catch {
220
- return null;
221
- }
215
+ const chunks: Buffer[] = [];
216
+ let settled = false;
217
+ const done = (result: string | null) => {
218
+ if (!settled) { settled = true; resolve(result); }
219
+ };
220
+ const timer = setTimeout(() => { child.kill(); done(null); }, 5000);
221
+ child.stdout!.on("data", (chunk: Buffer) => chunks.push(chunk));
222
+ child.on("close", (code) => {
223
+ clearTimeout(timer);
224
+ done(code === 0 ? Buffer.concat(chunks).toString("utf-8") : null);
225
+ });
226
+ child.on("error", () => { clearTimeout(timer); done(null); });
227
+ });
222
228
  }
223
229
 
224
230
  getCapabilities(): unknown | null {
@@ -6,6 +6,13 @@
6
6
 
7
7
  import type { WindowEntry } from "./types.js";
8
8
 
9
+ /**
10
+ * Pattern matching ENOENT errors with a file path.
11
+ * Matches: "ENOENT: no such file or directory, access '/path/to/file'"
12
+ * and similar Node.js filesystem error messages.
13
+ */
14
+ const ENOENT_PATH_RE = /ENOENT[^']*'([^']+)'/;
15
+
9
16
  /**
10
17
  * Analyze a sliding window of recent unit dispatches for stuck patterns.
11
18
  * Returns a signal with reason if stuck, null otherwise.
@@ -13,6 +20,8 @@ import type { WindowEntry } from "./types.js";
13
20
  * Rule 1: Same error string twice in a row → stuck immediately.
14
21
  * Rule 2: Same unit key 3+ consecutive times → stuck (preserves prior behavior).
15
22
  * Rule 3: Oscillation A→B→A→B in last 4 entries → stuck.
23
+ * Rule 4: Same ENOENT path in any 2 entries within the window → stuck (#3575).
24
+ * Missing files don't self-heal between retries — retrying wastes budget.
16
25
  */
17
26
  export function detectStuck(
18
27
  window: readonly WindowEntry[],
@@ -56,5 +65,23 @@ export function detectStuck(
56
65
  }
57
66
  }
58
67
 
68
+ // Rule 4: Same ENOENT path seen twice in window (#3575)
69
+ // Missing files don't appear between retries — stop immediately.
70
+ const enoentPaths = new Map<string, number>();
71
+ for (const entry of window) {
72
+ if (!entry.error) continue;
73
+ const match = ENOENT_PATH_RE.exec(entry.error);
74
+ if (!match) continue;
75
+ const filePath = match[1];
76
+ const count = (enoentPaths.get(filePath) ?? 0) + 1;
77
+ if (count >= 2) {
78
+ return {
79
+ stuck: true,
80
+ reason: `Missing file referenced twice: ${filePath} (ENOENT)`,
81
+ };
82
+ }
83
+ enoentPaths.set(filePath, count);
84
+ }
85
+
59
86
  return null;
60
87
  }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * auto/finalize-timeout.ts — Timeout guard for post-unit finalization.
3
+ *
4
+ * Prevents the auto-loop from hanging indefinitely when
5
+ * postUnitPostVerification() never resolves (#2344).
6
+ *
7
+ * Leaf module — no imports from auto/ to avoid circular dependencies.
8
+ */
9
+
10
+ /** Timeout for postUnitPostVerification in runFinalize (ms). */
11
+ export const FINALIZE_POST_TIMEOUT_MS = 60_000;
12
+
13
+ /**
14
+ * Race a promise against a timeout. Returns an object indicating whether
15
+ * the timeout fired and the resolved value (if any).
16
+ *
17
+ * Unlike Promise.race with a rejection, this returns a discriminated
18
+ * result so callers can handle timeouts as a recoverable condition
19
+ * rather than an exception.
20
+ *
21
+ * The timeout timer is always cleaned up, whether the promise resolves
22
+ * or the timeout fires.
23
+ */
24
+ export async function withTimeout<T>(
25
+ promise: Promise<T>,
26
+ timeoutMs: number,
27
+ label: string,
28
+ ): Promise<{ value: T; timedOut: false } | { value: undefined; timedOut: true }> {
29
+ let timeoutHandle: ReturnType<typeof setTimeout> | undefined;
30
+
31
+ const timeoutPromise = new Promise<{ value: undefined; timedOut: true }>((resolve) => {
32
+ timeoutHandle = setTimeout(() => {
33
+ resolve({ value: undefined, timedOut: true });
34
+ }, timeoutMs);
35
+ });
36
+
37
+ try {
38
+ const result = await Promise.race([
39
+ promise.then((value) => ({ value, timedOut: false as const })),
40
+ timeoutPromise,
41
+ ]);
42
+ return result;
43
+ } finally {
44
+ if (timeoutHandle) clearTimeout(timeoutHandle);
45
+ }
46
+ }
@@ -259,6 +259,11 @@ export async function autoLoop(
259
259
  // ── Blanket catch: absorb unexpected exceptions, apply graduated recovery ──
260
260
  const msg = loopErr instanceof Error ? loopErr.message : String(loopErr);
261
261
 
262
+ // Always emit iteration-end on error so the journal records iteration
263
+ // completion even on failure (#2344). Without this, errors in
264
+ // runFinalize leave the journal incomplete, making diagnosis harder.
265
+ deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration, error: msg } });
266
+
262
267
  // ── Infrastructure errors: immediate stop, no retry ──
263
268
  // These are unrecoverable (disk full, OOM, etc.). Retrying just burns
264
269
  // LLM budget on guaranteed failures.