gsd-pi 2.60.0-dev.d9052f5 → 2.61.0

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 (308) hide show
  1. package/dist/resources/extensions/ask-user-questions.js +7 -4
  2. package/dist/resources/extensions/gsd/auto/phases.js +15 -7
  3. package/dist/resources/extensions/gsd/auto-dashboard.js +21 -8
  4. package/dist/resources/extensions/gsd/auto-dispatch.js +6 -3
  5. package/dist/resources/extensions/gsd/auto-model-selection.js +58 -9
  6. package/dist/resources/extensions/gsd/auto-post-unit.js +3 -2
  7. package/dist/resources/extensions/gsd/auto-prompts.js +36 -20
  8. package/dist/resources/extensions/gsd/auto-recovery.js +37 -18
  9. package/dist/resources/extensions/gsd/auto-start.js +9 -5
  10. package/dist/resources/extensions/gsd/auto-timers.js +11 -5
  11. package/dist/resources/extensions/gsd/auto-unit-closeout.js +5 -3
  12. package/dist/resources/extensions/gsd/auto-verification.js +3 -2
  13. package/dist/resources/extensions/gsd/auto-worktree.js +120 -55
  14. package/dist/resources/extensions/gsd/auto.js +39 -17
  15. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +6 -3
  16. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +2 -2
  17. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +4 -10
  18. package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +2 -1
  19. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -0
  20. package/dist/resources/extensions/gsd/bootstrap/system-context.js +11 -10
  21. package/dist/resources/extensions/gsd/commands/catalog.js +2 -0
  22. package/dist/resources/extensions/gsd/commands-codebase.js +48 -21
  23. package/dist/resources/extensions/gsd/commands-inspect.js +2 -1
  24. package/dist/resources/extensions/gsd/commands-maintenance.js +32 -19
  25. package/dist/resources/extensions/gsd/complexity-classifier.js +8 -4
  26. package/dist/resources/extensions/gsd/custom-verification.js +3 -2
  27. package/dist/resources/extensions/gsd/gsd-db.js +33 -13
  28. package/dist/resources/extensions/gsd/guided-flow.js +19 -9
  29. package/dist/resources/extensions/gsd/init-wizard.js +12 -0
  30. package/dist/resources/extensions/gsd/markdown-renderer.js +11 -9
  31. package/dist/resources/extensions/gsd/md-importer.js +5 -4
  32. package/dist/resources/extensions/gsd/milestone-actions.js +3 -2
  33. package/dist/resources/extensions/gsd/milestone-ids.js +2 -1
  34. package/dist/resources/extensions/gsd/model-router.js +156 -121
  35. package/dist/resources/extensions/gsd/parallel-merge.js +5 -3
  36. package/dist/resources/extensions/gsd/parallel-orchestrator.js +26 -14
  37. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  38. package/dist/resources/extensions/gsd/preferences-validation.js +45 -0
  39. package/dist/resources/extensions/gsd/preferences.js +15 -3
  40. package/dist/resources/extensions/gsd/prompt-loader.js +3 -2
  41. package/dist/resources/extensions/gsd/prompts/rethink.md +1 -1
  42. package/dist/resources/extensions/gsd/rule-registry.js +7 -6
  43. package/dist/resources/extensions/gsd/safe-fs.js +6 -8
  44. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
  45. package/dist/resources/extensions/gsd/tools/complete-slice.js +3 -2
  46. package/dist/resources/extensions/gsd/tools/complete-task.js +3 -2
  47. package/dist/resources/extensions/gsd/tools/plan-milestone.js +3 -2
  48. package/dist/resources/extensions/gsd/tools/plan-slice.js +3 -2
  49. package/dist/resources/extensions/gsd/tools/plan-task.js +2 -1
  50. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +4 -4
  51. package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -1
  52. package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -1
  53. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -1
  54. package/dist/resources/extensions/gsd/tools/validate-milestone.js +2 -1
  55. package/dist/resources/extensions/gsd/triage-resolution.js +11 -4
  56. package/dist/resources/extensions/gsd/workflow-events.js +2 -1
  57. package/dist/resources/extensions/gsd/workflow-logger.js +37 -4
  58. package/dist/resources/extensions/gsd/workflow-migration.js +14 -12
  59. package/dist/resources/extensions/gsd/workflow-projections.js +2 -2
  60. package/dist/resources/extensions/gsd/workflow-reconcile.js +2 -2
  61. package/dist/resources/extensions/gsd/worktree-manager.js +26 -14
  62. package/dist/resources/extensions/shared/interview-ui.js +3 -1
  63. package/dist/web/standalone/.next/BUILD_ID +1 -1
  64. package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
  65. package/dist/web/standalone/.next/build-manifest.json +3 -3
  66. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  67. package/dist/web/standalone/.next/required-server-files.json +3 -3
  68. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  69. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  70. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  71. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  75. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  79. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  80. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  81. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  82. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  83. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  85. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  95. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  107. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  135. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  141. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  155. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  157. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  159. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  161. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/index.html +1 -1
  171. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  172. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  173. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  174. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  175. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  176. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  177. package/dist/web/standalone/.next/server/app/page.js +2 -2
  178. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  180. package/dist/web/standalone/.next/server/chunks/2229.js +1 -1
  181. package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
  182. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/middleware.js +2 -2
  184. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  186. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  187. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  188. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  189. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
  190. package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
  191. package/dist/web/standalone/.next/static/chunks/app/page-62be3b5fa91e4c8f.js +1 -0
  192. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
  193. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
  194. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  195. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  196. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  197. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  198. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  199. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  200. package/dist/web/standalone/server.js +1 -1
  201. package/package.json +1 -1
  202. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  203. package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -0
  204. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  205. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -1
  206. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  207. package/packages/pi-coding-agent/dist/core/extensions/runner.js +16 -0
  208. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  209. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +26 -0
  210. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  211. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  212. package/packages/pi-coding-agent/dist/core/lsp/config.d.ts.map +1 -1
  213. package/packages/pi-coding-agent/dist/core/lsp/config.js +6 -1
  214. package/packages/pi-coding-agent/dist/core/lsp/config.js.map +1 -1
  215. package/packages/pi-coding-agent/dist/core/lsp/defaults.json +2 -2
  216. package/packages/pi-coding-agent/dist/core/lsp/lsp-legacy-alias.test.d.ts +2 -0
  217. package/packages/pi-coding-agent/dist/core/lsp/lsp-legacy-alias.test.d.ts.map +1 -0
  218. package/packages/pi-coding-agent/dist/core/lsp/lsp-legacy-alias.test.js +47 -0
  219. package/packages/pi-coding-agent/dist/core/lsp/lsp-legacy-alias.test.js.map +1 -0
  220. package/packages/pi-coding-agent/package.json +1 -1
  221. package/packages/pi-coding-agent/src/core/extensions/loader.ts +6 -0
  222. package/packages/pi-coding-agent/src/core/extensions/runner.ts +19 -0
  223. package/packages/pi-coding-agent/src/core/extensions/types.ts +26 -0
  224. package/packages/pi-coding-agent/src/core/lsp/config.ts +7 -1
  225. package/packages/pi-coding-agent/src/core/lsp/defaults.json +2 -2
  226. package/packages/pi-coding-agent/src/core/lsp/lsp-legacy-alias.test.ts +70 -0
  227. package/pkg/package.json +1 -1
  228. package/src/resources/extensions/ask-user-questions.ts +7 -3
  229. package/src/resources/extensions/gsd/auto/phases.ts +17 -7
  230. package/src/resources/extensions/gsd/auto-dashboard.ts +22 -8
  231. package/src/resources/extensions/gsd/auto-dispatch.ts +7 -3
  232. package/src/resources/extensions/gsd/auto-model-selection.ts +77 -15
  233. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -4
  234. package/src/resources/extensions/gsd/auto-prompts.ts +37 -20
  235. package/src/resources/extensions/gsd/auto-recovery.ts +38 -18
  236. package/src/resources/extensions/gsd/auto-start.ts +10 -9
  237. package/src/resources/extensions/gsd/auto-timers.ts +12 -5
  238. package/src/resources/extensions/gsd/auto-unit-closeout.ts +6 -2
  239. package/src/resources/extensions/gsd/auto-verification.ts +3 -6
  240. package/src/resources/extensions/gsd/auto-worktree.ts +121 -55
  241. package/src/resources/extensions/gsd/auto.ts +40 -17
  242. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +4 -3
  243. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +2 -2
  244. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +4 -16
  245. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +2 -1
  246. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +8 -0
  247. package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -10
  248. package/src/resources/extensions/gsd/commands/catalog.ts +2 -0
  249. package/src/resources/extensions/gsd/commands-codebase.ts +52 -20
  250. package/src/resources/extensions/gsd/commands-inspect.ts +2 -1
  251. package/src/resources/extensions/gsd/commands-maintenance.ts +28 -19
  252. package/src/resources/extensions/gsd/complexity-classifier.ts +9 -4
  253. package/src/resources/extensions/gsd/custom-verification.ts +3 -2
  254. package/src/resources/extensions/gsd/gsd-db.ts +12 -14
  255. package/src/resources/extensions/gsd/guided-flow.ts +9 -8
  256. package/src/resources/extensions/gsd/init-wizard.ts +12 -0
  257. package/src/resources/extensions/gsd/markdown-renderer.ts +11 -17
  258. package/src/resources/extensions/gsd/md-importer.ts +5 -4
  259. package/src/resources/extensions/gsd/milestone-actions.ts +3 -2
  260. package/src/resources/extensions/gsd/milestone-ids.ts +2 -1
  261. package/src/resources/extensions/gsd/model-router.ts +199 -173
  262. package/src/resources/extensions/gsd/parallel-merge.ts +5 -3
  263. package/src/resources/extensions/gsd/parallel-orchestrator.ts +18 -14
  264. package/src/resources/extensions/gsd/preferences-types.ts +13 -0
  265. package/src/resources/extensions/gsd/preferences-validation.ts +45 -0
  266. package/src/resources/extensions/gsd/preferences.ts +16 -3
  267. package/src/resources/extensions/gsd/prompt-loader.ts +3 -2
  268. package/src/resources/extensions/gsd/prompts/rethink.md +1 -1
  269. package/src/resources/extensions/gsd/rule-registry.ts +7 -6
  270. package/src/resources/extensions/gsd/safe-fs.ts +6 -5
  271. package/src/resources/extensions/gsd/tests/capability-router.test.ts +347 -0
  272. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +63 -0
  273. package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +27 -2
  274. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +4 -4
  275. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +1188 -0
  276. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +841 -0
  277. package/src/resources/extensions/gsd/tests/model-router.test.ts +403 -3
  278. package/src/resources/extensions/gsd/tests/preferences.test.ts +62 -0
  279. package/src/resources/extensions/gsd/tests/remote-questions.test.ts +21 -0
  280. package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +284 -0
  281. package/src/resources/extensions/gsd/tests/workflow-logger-audit.test.ts +120 -0
  282. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +6 -6
  283. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -6
  284. package/src/resources/extensions/gsd/tools/complete-slice.ts +3 -6
  285. package/src/resources/extensions/gsd/tools/complete-task.ts +3 -6
  286. package/src/resources/extensions/gsd/tools/plan-milestone.ts +3 -6
  287. package/src/resources/extensions/gsd/tools/plan-slice.ts +3 -6
  288. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -3
  289. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +4 -6
  290. package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -3
  291. package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -3
  292. package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -3
  293. package/src/resources/extensions/gsd/tools/validate-milestone.ts +2 -3
  294. package/src/resources/extensions/gsd/triage-resolution.ts +11 -4
  295. package/src/resources/extensions/gsd/types.ts +1 -0
  296. package/src/resources/extensions/gsd/workflow-events.ts +2 -1
  297. package/src/resources/extensions/gsd/workflow-logger.ts +52 -5
  298. package/src/resources/extensions/gsd/workflow-migration.ts +14 -12
  299. package/src/resources/extensions/gsd/workflow-projections.ts +2 -2
  300. package/src/resources/extensions/gsd/workflow-reconcile.ts +2 -2
  301. package/src/resources/extensions/gsd/worktree-manager.ts +16 -14
  302. package/src/resources/extensions/shared/interview-ui.ts +3 -1
  303. package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +144 -0
  304. package/dist/web/standalone/.next/static/chunks/app/page-0c485498795110d6.js +0 -1
  305. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
  306. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
  307. /package/dist/web/standalone/.next/static/{JVkoVYumy0cDhOQISEYdG → 72_sVF0fdrMZX707jm10G}/_buildManifest.js +0 -0
  308. /package/dist/web/standalone/.next/static/{JVkoVYumy0cDhOQISEYdG → 72_sVF0fdrMZX707jm10G}/_ssgManifest.js +0 -0
@@ -82,11 +82,14 @@ export default function AskUserQuestions(pi) {
82
82
  return errorResult(`Error: ask_user_questions requires non-empty options for every question (question "${q.id}" has none)`, params.questions);
83
83
  }
84
84
  }
85
+ // Try remote first if configured (works in both interactive and headless modes).
86
+ // tryRemoteQuestions returns null when no remote channel is configured, so
87
+ // this is a no-op when the user has not set up Slack/Discord/Telegram.
88
+ const { tryRemoteQuestions } = await import("./remote-questions/manager.js");
89
+ const remoteResult = await tryRemoteQuestions(params.questions, signal);
90
+ if (remoteResult)
91
+ return { ...remoteResult, details: remoteResult.details };
85
92
  if (!ctx.hasUI) {
86
- const { tryRemoteQuestions } = await import("./remote-questions/manager.js");
87
- const remoteResult = await tryRemoteQuestions(params.questions, signal);
88
- if (remoteResult)
89
- return { ...remoteResult, details: remoteResult.details };
90
93
  return errorResult("Error: UI not available (non-interactive mode)", params.questions);
91
94
  }
92
95
  // Delegate to shared interview UI
@@ -495,6 +495,8 @@ export async function runGuards(ic, mid) {
495
495
  // ── Stop/Backtrack directive guard (#3487) ──
496
496
  // Check for unexecuted stop or backtrack captures BEFORE dispatching any unit.
497
497
  // This ensures user "halt" directives are honored immediately.
498
+ // IMPORTANT: Fail-closed — any exception during stop handling still breaks the loop
499
+ // to ensure user halt intent is never silently dropped.
498
500
  try {
499
501
  const { loadStopCaptures, markCaptureExecuted } = await import("../captures.js");
500
502
  const stopCaptures = loadStopCaptures(s.basePath);
@@ -506,11 +508,9 @@ export async function runGuards(ic, mid) {
506
508
  : `Stop directive: ${first.text}`;
507
509
  ctx.ui.notify(label, "warning");
508
510
  deps.sendDesktopNotification("GSD", label, "warning", "stop-directive", basename(s.originalBasePath || s.basePath));
509
- // Mark all stop/backtrack captures as executed so they don't re-fire
510
- for (const cap of stopCaptures) {
511
- markCaptureExecuted(s.basePath, cap.id);
512
- }
513
- // For backtrack captures, write the backtrack trigger before pausing
511
+ // Pause first ensures auto-mode stops even if later steps fail
512
+ await deps.pauseAuto(ctx, pi);
513
+ // For backtrack captures, write the backtrack trigger after pausing
514
514
  if (isBacktrack) {
515
515
  try {
516
516
  const { executeBacktrack } = await import("../triage-resolution.js");
@@ -520,13 +520,19 @@ export async function runGuards(ic, mid) {
520
520
  debugLog("guards", { phase: "backtrack-execution-error", error: String(e) });
521
521
  }
522
522
  }
523
- await deps.pauseAuto(ctx, pi);
523
+ // Mark captures as executed only after successful pause/transition
524
+ for (const cap of stopCaptures) {
525
+ markCaptureExecuted(s.basePath, cap.id);
526
+ }
524
527
  debugLog("autoLoop", { phase: "exit", reason: isBacktrack ? "user-backtrack" : "user-stop" });
525
528
  return { action: "break", reason: isBacktrack ? "user-backtrack" : "user-stop" };
526
529
  }
527
530
  }
528
531
  catch (e) {
532
+ // Fail-closed: if anything in the stop guard throws, break the loop
533
+ // rather than silently continuing and dropping user halt intent
529
534
  debugLog("guards", { phase: "stop-guard-error", error: String(e) });
535
+ return { action: "break", reason: "stop-guard-error" };
530
536
  }
531
537
  // Budget ceiling guard
532
538
  const budgetCeiling = prefs?.budget_ceiling;
@@ -894,7 +900,9 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
894
900
  nextSteps: [],
895
901
  });
896
902
  }
897
- catch { /* non-fatal — anchor is advisory */ }
903
+ catch (err) { /* non-fatal — anchor is advisory */
904
+ logWarning("engine", `phase anchor failed: ${err instanceof Error ? err.message : String(err)}`);
905
+ }
898
906
  }
899
907
  deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: ic.nextSeq(), eventType: "unit-end", data: { unitType, unitId, status: unitResult.status, artifactVerified, ...(unitResult.errorContext ? { errorContext: unitResult.errorContext } : {}) }, causedBy: { flowId: ic.flowId, seq: unitStartSeq } });
900
908
  return { action: "next", data: { unitStartedAt: s.currentUnit?.startedAt } };
@@ -20,6 +20,7 @@ import { loadEffectiveGSDPreferences, getGlobalGSDPreferencesPath } from "./pref
20
20
  import { resolveServiceTierIcon, getEffectiveServiceTier } from "./service-tier.js";
21
21
  import { parseUnitId } from "./unit-id.js";
22
22
  import { formatRtkSavingsLabel, getRtkSessionSavings, } from "../shared/rtk-session-stats.js";
23
+ import { logWarning } from "./workflow-logger.js";
23
24
  // ─── UAT Slice Extraction ─────────────────────────────────────────────────────
24
25
  /**
25
26
  * Extract the target slice ID from a run-uat unit ID (e.g. "M001/S01" → "S01").
@@ -220,8 +221,9 @@ export function updateSliceProgressCache(base, mid, activeSid) {
220
221
  }
221
222
  }
222
223
  }
223
- catch {
224
+ catch (err) {
224
225
  // Non-fatal — just omit task count
226
+ logWarning("dashboard", `operation failed: ${err instanceof Error ? err.message : String(err)}`);
225
227
  }
226
228
  }
227
229
  cachedSliceProgress = {
@@ -232,8 +234,9 @@ export function updateSliceProgressCache(base, mid, activeSid) {
232
234
  taskDetails,
233
235
  };
234
236
  }
235
- catch {
237
+ catch (err) {
236
238
  // Non-fatal — widget just won't show progress bar
239
+ logWarning("dashboard", `operation failed: ${err instanceof Error ? err.message : String(err)}`);
237
240
  }
238
241
  }
239
242
  export function getRoadmapSlicesSync() {
@@ -263,8 +266,9 @@ function refreshLastCommit(basePath) {
263
266
  }
264
267
  lastCommitFetchedAt = Date.now();
265
268
  }
266
- catch {
269
+ catch (err) {
267
270
  // Non-fatal — just skip last commit display
271
+ logWarning("dashboard", `operation failed: ${err instanceof Error ? err.message : String(err)}`);
268
272
  }
269
273
  }
270
274
  function getLastCommit(basePath) {
@@ -300,7 +304,9 @@ function ensureWidgetModeLoaded() {
300
304
  widgetMode = saved;
301
305
  }
302
306
  }
303
- catch { /* non-fatal — use default */ }
307
+ catch (err) { /* non-fatal — use default */
308
+ logWarning("dashboard", `operation failed: ${err instanceof Error ? err.message : String(err)}`);
309
+ }
304
310
  }
305
311
  /** Persist widget mode to global preferences YAML. */
306
312
  function persistWidgetMode(mode) {
@@ -320,7 +326,9 @@ function persistWidgetMode(mode) {
320
326
  }
321
327
  writeFileSync(prefsPath, content, "utf-8");
322
328
  }
323
- catch { /* non-fatal — mode still set in memory */ }
329
+ catch (err) { /* non-fatal — mode still set in memory */
330
+ logWarning("dashboard", `file write failed: ${err instanceof Error ? err.message : String(err)}`);
331
+ }
324
332
  }
325
333
  /** Cycle to the next widget mode. Returns the new mode. */
326
334
  export function cycleWidgetMode() {
@@ -360,7 +368,9 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
360
368
  try {
361
369
  cachedBranch = getCurrentBranch(accessors.getBasePath());
362
370
  }
363
- catch { /* not in git repo */ }
371
+ catch (err) { /* not in git repo */
372
+ logWarning("dashboard", `git branch detection failed: ${err instanceof Error ? err.message : String(err)}`);
373
+ }
364
374
  // Cache short pwd (last 2 path segments only) + worktree/branch info
365
375
  let widgetPwd;
366
376
  {
@@ -394,7 +404,8 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
394
404
  const savings = sessionId ? getRtkSessionSavings(accessors.getBasePath(), sessionId) : null;
395
405
  cachedRtkLabel = formatRtkSavingsLabel(savings);
396
406
  }
397
- catch {
407
+ catch (err) {
408
+ logWarning("dashboard", `RTK savings lookup failed: ${err instanceof Error ? err.message : String(err)}`);
398
409
  cachedRtkLabel = null;
399
410
  }
400
411
  };
@@ -416,7 +427,9 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
416
427
  refreshRtkLabel();
417
428
  cachedLines = undefined;
418
429
  }
419
- catch { /* non-fatal */ }
430
+ catch (err) { /* non-fatal */
431
+ logWarning("dashboard", `DB status update failed: ${err instanceof Error ? err.message : String(err)}`);
432
+ }
420
433
  }, 15_000);
421
434
  return {
422
435
  render(width) {
@@ -13,7 +13,7 @@ import { isDbAvailable, getMilestoneSlices, getPendingGates, markAllGatesOmitted
13
13
  import { extractVerdict, isAcceptableUatVerdict } from "./verdict-parser.js";
14
14
  import { gsdRoot, resolveMilestoneFile, resolveMilestonePath, resolveSliceFile, resolveTaskFile, relSliceFile, buildMilestoneFileName, } from "./paths.js";
15
15
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
16
- import { logError } from "./workflow-logger.js";
16
+ import { logWarning, logError } from "./workflow-logger.js";
17
17
  import { join } from "node:path";
18
18
  import { hasImplementationArtifacts } from "./auto-recovery.js";
19
19
  import { buildDiscussMilestonePrompt, buildResearchMilestonePrompt, buildPlanMilestonePrompt, buildResearchSlicePrompt, buildPlanSlicePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt, buildReplanSlicePrompt, buildRunUatPrompt, buildReassessRoadmapPrompt, buildRewriteDocsPrompt, buildReactiveExecutePrompt, buildGateEvaluatePrompt, checkNeedsReassessment, checkNeedsRunUat, } from "./auto-prompts.js";
@@ -564,7 +564,9 @@ export const DISPATCH_RULES = [
564
564
  }
565
565
  }
566
566
  }
567
- catch { /* fall through — don't block on DB errors */ }
567
+ catch (err) { /* fall through — don't block on DB errors */
568
+ logWarning("dispatch", `verification class check failed: ${err instanceof Error ? err.message : String(err)}`);
569
+ }
568
570
  return {
569
571
  action: "dispatch",
570
572
  unitType: "complete-milestone",
@@ -602,8 +604,9 @@ export async function resolveDispatch(ctx) {
602
604
  const registry = getRegistry();
603
605
  return await registry.evaluateDispatch(ctx);
604
606
  }
605
- catch {
607
+ catch (err) {
606
608
  // Registry not initialized — fall back to inline loop
609
+ logWarning("dispatch", `registry dispatch failed, falling back to inline rules: ${err instanceof Error ? err.message : String(err)}`);
607
610
  }
608
611
  for (const rule of DISPATCH_RULES) {
609
612
  const result = await rule.match(ctx);
@@ -4,8 +4,8 @@
4
4
  * and fallback chains.
5
5
  */
6
6
  import { resolveModelWithFallbacksForUnit, resolveDynamicRoutingConfig } from "./preferences.js";
7
- import { classifyUnitComplexity, tierLabel, extractTaskMetadata } from "./complexity-classifier.js";
8
- import { resolveModelForComplexity, escalateTier } from "./model-router.js";
7
+ import { classifyUnitComplexity, tierLabel } from "./complexity-classifier.js";
8
+ import { resolveModelForComplexity, escalateTier, getEligibleModels, loadCapabilityOverrides } from "./model-router.js";
9
9
  import { getLedger, getProjectTotals } from "./metrics.js";
10
10
  import { unitPhaseLabel } from "./auto-dashboard.js";
11
11
  export function resolvePreferredModelConfig(unitType, autoModeStartModel) {
@@ -68,19 +68,68 @@ export async function selectAndApplyModel(ctx, pi, unitType, unitId, basePath, p
68
68
  }
69
69
  }
70
70
  }
71
- // Extract task metadata for capability scoring
72
- const taskMeta = unitType === "execute-task"
73
- ? extractTaskMetadata(unitId, basePath)
74
- : undefined;
75
- const routingResult = resolveModelForComplexity(classification, modelConfig, routingConfig, availableModelIds, unitType, taskMeta);
71
+ // Load user capability overrides from preferences (D-17: deep-merged with built-in profiles)
72
+ const capabilityOverrides = loadCapabilityOverrides(prefs ?? {});
73
+ // Fire before_model_select hook (ADR-004, D-03)
74
+ // Hook can override model selection entirely by returning { modelId }
75
+ let hookOverride;
76
+ if (routingConfig.hooks !== false) {
77
+ const eligible = getEligibleModels(classification.tier, availableModelIds, routingConfig);
78
+ const hookResult = await pi.emitBeforeModelSelect({
79
+ unitType,
80
+ unitId,
81
+ classification: {
82
+ tier: classification.tier,
83
+ reason: classification.reason,
84
+ downgraded: classification.downgraded,
85
+ },
86
+ taskMetadata: classification.taskMetadata,
87
+ eligibleModels: eligible,
88
+ phaseConfig: modelConfig ? {
89
+ primary: modelConfig.primary,
90
+ fallbacks: modelConfig.fallbacks ?? [],
91
+ } : undefined,
92
+ });
93
+ if (hookResult?.modelId) {
94
+ hookOverride = hookResult.modelId;
95
+ }
96
+ }
97
+ let routingResult;
98
+ if (hookOverride) {
99
+ // Hook override bypasses capability scoring entirely
100
+ routingResult = {
101
+ modelId: hookOverride,
102
+ fallbacks: [
103
+ ...(modelConfig?.fallbacks ?? []).filter(f => f !== hookOverride),
104
+ ...(modelConfig?.primary && modelConfig.primary !== hookOverride ? [modelConfig.primary] : []),
105
+ ],
106
+ tier: classification.tier,
107
+ wasDowngraded: hookOverride !== modelConfig?.primary,
108
+ reason: `hook override: ${hookOverride}`,
109
+ selectionMethod: "tier-only",
110
+ };
111
+ }
112
+ else {
113
+ routingResult = resolveModelForComplexity(classification, modelConfig, routingConfig, availableModelIds, unitType, classification.taskMetadata, capabilityOverrides);
114
+ }
76
115
  if (routingResult.wasDowngraded) {
77
116
  effectiveModelConfig = {
78
117
  primary: routingResult.modelId,
79
118
  fallbacks: routingResult.fallbacks,
80
119
  };
81
120
  if (verbose) {
82
- const method = routingResult.selectionMethod === "capability-scored" ? "capability-scored" : "tier-only";
83
- ctx.ui.notify(`Dynamic routing [${tierLabel(classification.tier)}]: ${routingResult.modelId} (${method} ${classification.reason})`, "info");
121
+ if (routingResult.selectionMethod === "capability-scored" && routingResult.capabilityScores) {
122
+ // Verbose scoring breakdown for capability-scored decisions (D-20)
123
+ const tierLbl = tierLabel(classification.tier);
124
+ const scores = Object.entries(routingResult.capabilityScores)
125
+ .sort(([, a], [, b]) => b - a)
126
+ .map(([id, score]) => `${id}: ${score.toFixed(1)}`)
127
+ .join(", ");
128
+ ctx.ui.notify(`Dynamic routing [${tierLbl}]: ${routingResult.modelId} (capability-scored) — ${scores}`, "info");
129
+ }
130
+ else {
131
+ ctx.ui.notify(`Dynamic routing [${tierLabel(classification.tier)}]: ${routingResult.modelId} (${classification.reason})`, "info");
132
+ }
84
133
  }
85
134
  }
86
135
  routingTierLabel = ` [${tierLabel(classification.tier)}]`;
@@ -208,8 +208,9 @@ export async function postUnitPreVerification(pctx, opts) {
208
208
  const { getTaskIssueNumberForCommit } = await import("../github-sync/sync.js");
209
209
  ghIssueNumber = getTaskIssueNumberForCommit(s.basePath, mid, sid, tid) ?? undefined;
210
210
  }
211
- catch {
211
+ catch (err) {
212
212
  // GitHub sync not available — skip
213
+ logWarning("engine", `GitHub issue lookup failed: ${err instanceof Error ? err.message : String(err)}`);
213
214
  }
214
215
  taskContext = {
215
216
  taskId: `${sid}/${tid}`,
@@ -448,7 +449,7 @@ export async function postUnitPostVerification(pctx) {
448
449
  catch (dbErr) {
449
450
  // DB unavailable — fail explicitly rather than silently reverting to markdown mutation.
450
451
  // Use 'gsd recover' to rebuild DB state from disk if needed.
451
- process.stderr.write(`gsd: retry state-reset failed (DB unavailable): ${dbErr.message}. Run 'gsd recover' to reconcile.\n`);
452
+ logError("engine", `retry state-reset failed (DB unavailable): ${dbErr.message}. Run 'gsd recover' to reconcile.`);
452
453
  }
453
454
  }
454
455
  // 2. Delete SUMMARY.md for the task
@@ -18,6 +18,7 @@ import { computeBudgets, resolveExecutorContextWindow, truncateAtSectionBoundary
18
18
  import { getPendingGates } from "./gsd-db.js";
19
19
  import { formatDecisionsCompact, formatRequirementsCompact } from "./structured-data-formatter.js";
20
20
  import { readPhaseAnchor, formatAnchorForPrompt } from "./phase-anchor.js";
21
+ import { logWarning } from "./workflow-logger.js";
21
22
  // ─── Preamble Cap ─────────────────────────────────────────────────────────────
22
23
  const MAX_PREAMBLE_CHARS = 30_000;
23
24
  function capPreamble(preamble) {
@@ -37,7 +38,8 @@ function formatExecutorConstraints() {
37
38
  const prefs = loadEffectiveGSDPreferences();
38
39
  windowTokens = resolveExecutorContextWindow(undefined, prefs?.preferences);
39
40
  }
40
- catch {
41
+ catch (e) {
42
+ logWarning("prompt", `resolveExecutorContextWindow failed: ${e.message}`);
41
43
  windowTokens = 200_000; // safe default
42
44
  }
43
45
  const budgets = computeBudgets(windowTokens);
@@ -161,7 +163,9 @@ export async function inlineDependencySummaries(mid, sid, base, budgetChars) {
161
163
  // If slice not found in DB, fall through to file-based parsing
162
164
  }
163
165
  }
164
- catch { /* fall through */ }
166
+ catch (err) {
167
+ logWarning("prompt", `inlineDependencySummaries DB lookup failed: ${err instanceof Error ? err.message : String(err)}`);
168
+ }
165
169
  // If DB didn't provide depends, fall back to roadmap parsing
166
170
  if (!depends) {
167
171
  const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
@@ -233,8 +237,8 @@ export async function inlineDecisionsFromDb(base, milestoneId, scope, level) {
233
237
  }
234
238
  }
235
239
  }
236
- catch {
237
- // DB not available fall through to filesystem
240
+ catch (err) {
241
+ logWarning("prompt", `inlineDecisionsFromDb failed: ${err instanceof Error ? err.message : String(err)}`);
238
242
  }
239
243
  return inlineGsdRootFile(base, "decisions.md", "Decisions");
240
244
  }
@@ -258,8 +262,8 @@ export async function inlineRequirementsFromDb(base, sliceId, level) {
258
262
  }
259
263
  }
260
264
  }
261
- catch {
262
- // DB not available fall through to filesystem
265
+ catch (err) {
266
+ logWarning("prompt", `inlineRequirementsFromDb failed: ${err instanceof Error ? err.message : String(err)}`);
263
267
  }
264
268
  return inlineGsdRootFile(base, "requirements.md", "Requirements");
265
269
  }
@@ -278,8 +282,8 @@ export async function inlineProjectFromDb(base) {
278
282
  }
279
283
  }
280
284
  }
281
- catch {
282
- // DB not available fall through to filesystem
285
+ catch (err) {
286
+ logWarning("prompt", `inlineProjectFromDb failed: ${err instanceof Error ? err.message : String(err)}`);
283
287
  }
284
288
  return inlineGsdRootFile(base, "project.md", "Project");
285
289
  }
@@ -399,8 +403,8 @@ export function buildSkillActivationBlock(params) {
399
403
  matched.add(normalizeSkillReference(skillName));
400
404
  }
401
405
  }
402
- catch {
403
- // Non-fatal malformed task plan should not break prompt construction
406
+ catch (err) {
407
+ logWarning("prompt", `parseTaskPlanFile failed: ${err instanceof Error ? err.message : String(err)}`);
404
408
  }
405
409
  }
406
410
  const ordered = [...matched]
@@ -619,7 +623,9 @@ export async function checkNeedsReassessment(base, mid, state) {
619
623
  }
620
624
  }
621
625
  }
622
- catch { /* fall through */ }
626
+ catch (err) {
627
+ logWarning("prompt", `checkNeedsReassessment DB lookup failed: ${err instanceof Error ? err.message : String(err)}`);
628
+ }
623
629
  // File-based fallback using roadmap checkboxes
624
630
  const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
625
631
  if (!roadmapPath)
@@ -694,7 +700,9 @@ export async function checkNeedsRunUat(base, mid, state, prefs) {
694
700
  }
695
701
  }
696
702
  }
697
- catch { /* fall through */ }
703
+ catch (err) {
704
+ logWarning("prompt", `checkNeedsRunUat DB lookup failed: ${err instanceof Error ? err.message : String(err)}`);
705
+ }
698
706
  // File-based fallback using roadmap checkboxes
699
707
  if (!prefs?.uat_dispatch)
700
708
  return null;
@@ -1150,7 +1158,9 @@ export async function buildCompleteMilestonePrompt(mid, midTitle, base, level) {
1150
1158
  sliceIds = getMilestoneSlices(mid).map(s => s.id);
1151
1159
  }
1152
1160
  }
1153
- catch { /* fall through */ }
1161
+ catch (err) {
1162
+ logWarning("prompt", `buildCompleteMilestonePrompt DB lookup failed: ${err instanceof Error ? err.message : String(err)}`);
1163
+ }
1154
1164
  // File-based fallback: parse roadmap for slice IDs when DB has no data
1155
1165
  if (sliceIds.length === 0 && roadmapPath) {
1156
1166
  const roadmapContent = await loadFile(roadmapPath);
@@ -1233,7 +1243,9 @@ export async function buildValidateMilestonePrompt(mid, midTitle, base, level) {
1233
1243
  }
1234
1244
  }
1235
1245
  }
1236
- catch { /* fall through */ }
1246
+ catch (err) {
1247
+ logWarning("prompt", `buildValidateMilestonePrompt verification classes lookup failed: ${err instanceof Error ? err.message : String(err)}`);
1248
+ }
1237
1249
  // Inline all slice summaries and UAT results
1238
1250
  let valSliceIds = [];
1239
1251
  try {
@@ -1242,7 +1254,9 @@ export async function buildValidateMilestonePrompt(mid, midTitle, base, level) {
1242
1254
  valSliceIds = getMilestoneSlices(mid).map(s => s.id);
1243
1255
  }
1244
1256
  }
1245
- catch { /* fall through */ }
1257
+ catch (err) {
1258
+ logWarning("prompt", `buildValidateMilestonePrompt slice IDs lookup failed: ${err instanceof Error ? err.message : String(err)}`);
1259
+ }
1246
1260
  // File-based fallback: parse roadmap for slice IDs when DB has no data
1247
1261
  if (valSliceIds.length === 0 && roadmapPath) {
1248
1262
  const roadmapContent = await loadFile(roadmapPath);
@@ -1378,8 +1392,8 @@ export async function buildReplanSlicePrompt(mid, midTitle, sid, sTitle, base) {
1378
1392
  captureContext = replanCaptures.map(c => `- **${c.id}**: "${c.text}" — ${c.rationale ?? "no rationale"}`).join("\n");
1379
1393
  }
1380
1394
  }
1381
- catch {
1382
- // Non-fatal captures module may not be available
1395
+ catch (err) {
1396
+ logWarning("prompt", `loadReplanCaptures failed: ${err instanceof Error ? err.message : String(err)}`);
1383
1397
  }
1384
1398
  return loadPrompt("replan-slice", {
1385
1399
  workingDirectory: base,
@@ -1468,8 +1482,8 @@ export async function buildReassessRoadmapPrompt(mid, midTitle, completedSliceId
1468
1482
  deferredCaptures = deferred.map(c => `- **${c.id}**: "${c.text}" — ${c.rationale ?? "deferred during triage"}`).join("\n");
1469
1483
  }
1470
1484
  }
1471
- catch {
1472
- // Non-fatal captures module may not be available
1485
+ catch (err) {
1486
+ logWarning("prompt", `loadDeferredCaptures failed: ${err instanceof Error ? err.message : String(err)}`);
1473
1487
  }
1474
1488
  const reassessCommitInstruction = "Do not commit — .gsd/ planning docs are managed externally and not tracked in git.";
1475
1489
  return loadPrompt("reassess-roadmap", {
@@ -1646,7 +1660,9 @@ export async function buildRewriteDocsPrompt(mid, midTitle, activeSlice, base, o
1646
1660
  .map(t => ({ id: t.id }));
1647
1661
  }
1648
1662
  }
1649
- catch { /* fall through */ }
1663
+ catch (err) {
1664
+ logWarning("prompt", `buildRewriteDocsPrompt DB task lookup failed: ${err instanceof Error ? err.message : String(err)}`);
1665
+ }
1650
1666
  if (!incompleteTasks) {
1651
1667
  // DB unavailable — no task data to inline
1652
1668
  incompleteTasks = [];
@@ -12,6 +12,7 @@ import { parseRoadmap as parseLegacyRoadmap, parsePlan as parseLegacyPlan } from
12
12
  import { isDbAvailable, getTask, getSlice, getSliceTasks, updateTaskStatus } from "./gsd-db.js";
13
13
  import { isValidationTerminal } from "./state.js";
14
14
  import { getErrorMessage } from "./error-utils.js";
15
+ import { logWarning, logError } from "./workflow-logger.js";
15
16
  import { nativeConflictFiles, nativeCommit, nativeCheckoutTheirs, nativeAddPaths, nativeMergeAbort, nativeResetHard, } from "./native-git-bridge.js";
16
17
  import { resolveSlicePath, resolveSliceFile, resolveTasksDir, resolveTaskFiles, relMilestoneFile, relSliceFile, buildSliceFileName, resolveMilestoneFile, clearPathCache, resolveGsdRootFile, } from "./paths.js";
17
18
  import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, } from "node:fs";
@@ -40,7 +41,8 @@ export function hasImplementationArtifacts(basePath) {
40
41
  encoding: "utf-8",
41
42
  });
42
43
  }
43
- catch {
44
+ catch (e) {
45
+ logWarning("recovery", `git rev-parse check failed: ${e.message}`);
44
46
  return true;
45
47
  }
46
48
  // Strategy: check `git diff --name-only` against the merge-base with the
@@ -59,8 +61,9 @@ export function hasImplementationArtifacts(basePath) {
59
61
  const implFiles = changedFiles.filter(f => !f.startsWith(".gsd/") && !f.startsWith(".gsd\\"));
60
62
  return implFiles.length > 0;
61
63
  }
62
- catch {
64
+ catch (e) {
63
65
  // Non-fatal — if git operations fail, don't block the pipeline
66
+ logWarning("recovery", `implementation artifact check failed: ${e.message}`);
64
67
  return true;
65
68
  }
66
69
  }
@@ -77,8 +80,9 @@ function detectMainBranch(basePath) {
77
80
  if (result.trim())
78
81
  return "main";
79
82
  }
80
- catch {
81
- // main doesn't exist
83
+ catch (_) {
84
+ // Expected — main doesn't exist, try master next
85
+ void _;
82
86
  }
83
87
  try {
84
88
  const result = execFileSync("git", ["rev-parse", "--verify", "master"], {
@@ -89,10 +93,13 @@ function detectMainBranch(basePath) {
89
93
  if (result.trim())
90
94
  return "master";
91
95
  }
92
- catch {
93
- // master doesn't exist either
96
+ catch (_) {
97
+ // Expected — master doesn't exist either
98
+ void _;
94
99
  }
95
- return "main"; // default fallback
100
+ // Neither main nor master found — warn and fall back
101
+ logWarning("recovery", "neither main nor master branch found, defaulting to main");
102
+ return "main";
96
103
  }
97
104
  /**
98
105
  * Get files changed since the branch diverged from the target branch.
@@ -107,15 +114,17 @@ function getChangedFilesSinceBranch(basePath, targetBranch) {
107
114
  return result ? result.split("\n").filter(Boolean) : [];
108
115
  }
109
116
  }
110
- catch {
117
+ catch (err) {
111
118
  // merge-base failed — fall back
119
+ logWarning("recovery", `merge-base detection failed: ${err instanceof Error ? err.message : String(err)}`);
112
120
  }
113
121
  // Fallback: check last 20 commits
114
122
  try {
115
123
  const result = execFileSync("git", ["log", "--name-only", "--pretty=format:", "-20", "HEAD"], { cwd: basePath, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
116
124
  return result ? [...new Set(result.split("\n").filter(Boolean))] : [];
117
125
  }
118
- catch {
126
+ catch (e) {
127
+ logWarning("recovery", `git log fallback failed: ${e.message}`);
119
128
  return [];
120
129
  }
121
130
  }
@@ -198,8 +207,9 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
198
207
  return false;
199
208
  }
200
209
  }
201
- catch {
210
+ catch (err) {
202
211
  // DB unavailable — treat as verified to avoid blocking
212
+ logWarning("recovery", `gate-evaluate DB check failed: ${err instanceof Error ? err.message : String(err)}`);
203
213
  }
204
214
  return true;
205
215
  }
@@ -291,8 +301,9 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
291
301
  }
292
302
  }
293
303
  }
294
- catch {
304
+ catch (err) {
295
305
  // Parse failure — don't block; slice plan may have non-standard format
306
+ logWarning("recovery", `plan-slice task plan verification failed: ${err instanceof Error ? err.message : String(err)}`);
296
307
  }
297
308
  }
298
309
  }
@@ -325,7 +336,8 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
325
336
  if (slice && !slice.done)
326
337
  return false;
327
338
  }
328
- catch {
339
+ catch (e) {
340
+ logWarning("recovery", `roadmap parse failed: ${e.message}`);
329
341
  return false;
330
342
  }
331
343
  }
@@ -374,7 +386,9 @@ export function writeBlockerPlaceholder(unitType, unitId, base, reason) {
374
386
  try {
375
387
  updateTaskStatus(mid, sid, tid, "complete", new Date().toISOString());
376
388
  }
377
- catch { /* non-fatal */ }
389
+ catch (err) { /* non-fatal */
390
+ logError("recovery", `DB status update failed: ${err instanceof Error ? err.message : String(err)}`);
391
+ }
378
392
  }
379
393
  }
380
394
  return diagnoseExpectedArtifact(unitType, unitId, base);
@@ -389,23 +403,26 @@ function abortAndResetMerge(basePath, hasMergeHead, squashMsgPath) {
389
403
  try {
390
404
  nativeMergeAbort(basePath);
391
405
  }
392
- catch {
406
+ catch (err) {
393
407
  /* best-effort */
408
+ logWarning("recovery", `git merge-abort failed: ${err instanceof Error ? err.message : String(err)}`);
394
409
  }
395
410
  }
396
411
  else if (squashMsgPath) {
397
412
  try {
398
413
  unlinkSync(squashMsgPath);
399
414
  }
400
- catch {
415
+ catch (err) {
401
416
  /* best-effort */
417
+ logWarning("recovery", `file unlink failed: ${err instanceof Error ? err.message : String(err)}`);
402
418
  }
403
419
  }
404
420
  try {
405
421
  nativeResetHard(basePath);
406
422
  }
407
- catch {
423
+ catch (err) {
408
424
  /* best-effort */
425
+ logError("recovery", `git reset failed: ${err instanceof Error ? err.message : String(err)}`);
409
426
  }
410
427
  }
411
428
  /**
@@ -452,7 +469,8 @@ export function reconcileMergeState(basePath, ctx) {
452
469
  nativeCheckoutTheirs(basePath, gsdConflicts);
453
470
  nativeAddPaths(basePath, gsdConflicts);
454
471
  }
455
- catch {
472
+ catch (e) {
473
+ logError("recovery", `auto-resolve .gsd/ conflicts failed: ${e.message}`);
456
474
  resolved = false;
457
475
  }
458
476
  if (resolved) {
@@ -460,7 +478,8 @@ export function reconcileMergeState(basePath, ctx) {
460
478
  nativeCommit(basePath, "chore: auto-resolve .gsd/ state file conflicts");
461
479
  ctx.ui.notify(`Auto-resolved ${gsdConflicts.length} .gsd/ state file conflict(s) from prior merge.`, "info");
462
480
  }
463
- catch {
481
+ catch (e) {
482
+ logError("recovery", `auto-commit .gsd/ conflict resolution failed: ${e.message}`);
464
483
  resolved = false;
465
484
  }
466
485
  }