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
@@ -5,6 +5,7 @@
5
5
  // and encapsulates mutable hook state as instance fields.
6
6
  //
7
7
  // A module-level singleton accessor allows existing code to migrate incrementally.
8
+ import { logWarning } from "./workflow-logger.js";
8
9
  import { resolvePostUnitHooks, resolvePreDispatchHooks } from "./preferences.js";
9
10
  import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
10
11
  import { join } from "node:path";
@@ -310,8 +311,8 @@ export class RuleRegistry {
310
311
  mkdirSync(dir, { recursive: true });
311
312
  writeFileSync(this._hookStatePath(basePath), JSON.stringify(state, null, 2), "utf-8");
312
313
  }
313
- catch {
314
- // Non-fatal state is recreatable from artifacts
314
+ catch (e) {
315
+ logWarning("registry", `failed to persist hook state: ${e.message}`);
315
316
  }
316
317
  }
317
318
  /** Restore hook cycle counts from disk after a crash/restart. */
@@ -331,8 +332,8 @@ export class RuleRegistry {
331
332
  }
332
333
  }
333
334
  }
334
- catch {
335
- // Non-fatal fresh state is fine
335
+ catch (e) {
336
+ logWarning("registry", `failed to restore hook state: ${e.message}`);
336
337
  }
337
338
  }
338
339
  /** Clear persisted hook state file from disk. */
@@ -343,8 +344,8 @@ export class RuleRegistry {
343
344
  writeFileSync(filePath, JSON.stringify({ cycleCounts: {}, savedAt: new Date().toISOString() }, null, 2), "utf-8");
344
345
  }
345
346
  }
346
- catch {
347
- // Non-fatal
347
+ catch (e) {
348
+ logWarning("registry", `failed to clear hook state: ${e.message}`);
348
349
  }
349
350
  }
350
351
  // ── Hook status reporting ───────────────────────────────────────────
@@ -1,8 +1,9 @@
1
1
  import { existsSync, mkdirSync, cpSync } from "node:fs";
2
2
  import { dirname } from "node:path";
3
+ import { logWarning } from "./workflow-logger.js";
3
4
  /**
4
5
  * Safely creates a directory. Returns true if successful, false on error.
5
- * Logs to stderr when GSD_DEBUG is set.
6
+ * Logs warnings via workflow-logger on failure.
6
7
  */
7
8
  export function safeMkdir(dirPath) {
8
9
  try {
@@ -10,14 +11,13 @@ export function safeMkdir(dirPath) {
10
11
  return true;
11
12
  }
12
13
  catch (err) {
13
- if (process.env.GSD_DEBUG)
14
- console.error(`[gsd] mkdir failed: ${dirPath}`, err);
14
+ logWarning("fs", `mkdir failed: ${dirPath}: ${err.message}`);
15
15
  return false;
16
16
  }
17
17
  }
18
18
  /**
19
19
  * Safely copies src to dst. Returns true if successful, false if src doesn't exist or copy fails.
20
- * Logs to stderr when GSD_DEBUG is set.
20
+ * Logs warnings via workflow-logger on failure.
21
21
  */
22
22
  export function safeCopy(src, dst, opts) {
23
23
  if (!existsSync(src))
@@ -27,8 +27,7 @@ export function safeCopy(src, dst, opts) {
27
27
  return true;
28
28
  }
29
29
  catch (err) {
30
- if (process.env.GSD_DEBUG)
31
- console.error(`[gsd] copy failed: ${src} → ${dst}`, err);
30
+ logWarning("fs", `copy failed: ${src} → ${dst}: ${err.message}`);
32
31
  return false;
33
32
  }
34
33
  }
@@ -45,8 +44,7 @@ export function safeCopyRecursive(src, dst, opts) {
45
44
  return true;
46
45
  }
47
46
  catch (err) {
48
- if (process.env.GSD_DEBUG)
49
- console.error(`[gsd] recursive copy failed: ${src} → ${dst}`, err);
47
+ logWarning("fs", `recursive copy failed: ${src} → ${dst}: ${err.message}`);
50
48
  return false;
51
49
  }
52
50
  }
@@ -15,6 +15,7 @@ import { invalidateStateCache } from "../state.js";
15
15
  import { renderAllProjections } from "../workflow-projections.js";
16
16
  import { writeManifest } from "../workflow-manifest.js";
17
17
  import { appendEvent } from "../workflow-events.js";
18
+ import { logWarning } from "../workflow-logger.js";
18
19
  function renderMilestoneSummaryMarkdown(params) {
19
20
  const now = new Date().toISOString();
20
21
  const keyDecisionsYaml = params.keyDecisions.length > 0
@@ -140,7 +141,7 @@ export async function handleCompleteMilestone(params, basePath) {
140
141
  }
141
142
  catch (renderErr) {
142
143
  // Disk render failed — roll back DB status so state stays consistent
143
- process.stderr.write(`gsd-db: complete_milestone — disk render failed, rolling back DB status: ${renderErr.message}\n`);
144
+ logWarning("tool", `complete_milestone — disk render failed, rolling back DB status: ${renderErr.message}`);
144
145
  updateMilestoneStatus(params.milestoneId, 'active', null);
145
146
  invalidateStateCache();
146
147
  return { error: `disk render failed: ${renderErr.message}` };
@@ -163,7 +164,7 @@ export async function handleCompleteMilestone(params, basePath) {
163
164
  });
164
165
  }
165
166
  catch (hookErr) {
166
- process.stderr.write(`gsd: complete-milestone post-mutation hook warning: ${hookErr.message}\n`);
167
+ logWarning("tool", `complete-milestone post-mutation hook warning: ${hookErr.message}`);
167
168
  }
168
169
  return {
169
170
  milestoneId: params.milestoneId,
@@ -18,6 +18,7 @@ import { renderRoadmapCheckboxes } from "../markdown-renderer.js";
18
18
  import { renderAllProjections } from "../workflow-projections.js";
19
19
  import { writeManifest } from "../workflow-manifest.js";
20
20
  import { appendEvent } from "../workflow-events.js";
21
+ import { logWarning } from "../workflow-logger.js";
21
22
  /**
22
23
  * Render slice summary markdown matching the template format.
23
24
  * YAML frontmatter uses snake_case keys for parseSummary() compatibility.
@@ -240,7 +241,7 @@ export async function handleCompleteSlice(params, basePath) {
240
241
  }
241
242
  catch (renderErr) {
242
243
  // Disk render failed — roll back DB status so state stays consistent
243
- process.stderr.write(`gsd-db: complete_slice — disk render failed, rolling back DB status: ${renderErr.message}\n`);
244
+ logWarning("tool", `complete_slice — disk render failed, rolling back DB status: ${renderErr.message}`);
244
245
  updateSliceStatus(params.milestoneId, params.sliceId, 'pending');
245
246
  invalidateStateCache();
246
247
  return { error: `disk render failed: ${renderErr.message}` };
@@ -265,7 +266,7 @@ export async function handleCompleteSlice(params, basePath) {
265
266
  });
266
267
  }
267
268
  catch (hookErr) {
268
- process.stderr.write(`gsd: complete-slice post-mutation hook warning: ${hookErr.message}\n`);
269
+ logWarning("tool", `complete-slice post-mutation hook warning: ${hookErr.message}`);
269
270
  }
270
271
  return {
271
272
  sliceId: params.sliceId,
@@ -18,6 +18,7 @@ import { renderPlanCheckboxes } from "../markdown-renderer.js";
18
18
  import { renderAllProjections, renderSummaryContent } from "../workflow-projections.js";
19
19
  import { writeManifest } from "../workflow-manifest.js";
20
20
  import { appendEvent } from "../workflow-events.js";
21
+ import { logWarning } from "../workflow-logger.js";
21
22
  /**
22
23
  * Build a TaskRow-shaped object from CompleteTaskParams so the unified
23
24
  * renderSummaryContent() can be used at completion time (#2720).
@@ -165,7 +166,7 @@ export async function handleCompleteTask(params, basePath) {
165
166
  }
166
167
  catch (renderErr) {
167
168
  // Disk render failed — roll back DB status so state stays consistent
168
- process.stderr.write(`gsd-db: complete_task — disk render failed, rolling back DB status: ${renderErr.message}\n`);
169
+ logWarning("tool", `complete_task — disk render failed, rolling back DB status: ${renderErr.message}`);
169
170
  // Delete orphaned verification_evidence rows first (FK constraint
170
171
  // references tasks, so evidence must go before status change).
171
172
  // Without this, retries accumulate duplicate evidence rows (#2724).
@@ -194,7 +195,7 @@ export async function handleCompleteTask(params, basePath) {
194
195
  });
195
196
  }
196
197
  catch (hookErr) {
197
- process.stderr.write(`gsd: complete-task post-mutation hook warning: ${hookErr.message}\n`);
198
+ logWarning("tool", `complete-task post-mutation hook warning: ${hookErr.message}`);
198
199
  }
199
200
  return {
200
201
  taskId: params.taskId,
@@ -7,6 +7,7 @@ import { renderRoadmapFromDb } from "../markdown-renderer.js";
7
7
  import { renderAllProjections } from "../workflow-projections.js";
8
8
  import { writeManifest } from "../workflow-manifest.js";
9
9
  import { appendEvent } from "../workflow-events.js";
10
+ import { logWarning } from "../workflow-logger.js";
10
11
  function validateRiskEntries(value) {
11
12
  if (!Array.isArray(value)) {
12
13
  throw new Error("keyRisks must be an array");
@@ -221,7 +222,7 @@ export async function handlePlanMilestone(rawParams, basePath) {
221
222
  roadmapPath = renderResult.roadmapPath;
222
223
  }
223
224
  catch (renderErr) {
224
- process.stderr.write(`gsd-db: plan_milestone — render failed (DB rows preserved for debugging): ${renderErr.message}\n`);
225
+ logWarning("tool", `plan_milestone — render failed (DB rows preserved for debugging): ${renderErr.message}`);
225
226
  invalidateStateCache();
226
227
  return { error: `render failed: ${renderErr.message}` };
227
228
  }
@@ -241,7 +242,7 @@ export async function handlePlanMilestone(rawParams, basePath) {
241
242
  });
242
243
  }
243
244
  catch (hookErr) {
244
- process.stderr.write(`gsd: plan-milestone post-mutation hook warning: ${hookErr.message}\n`);
245
+ logWarning("tool", `plan-milestone post-mutation hook warning: ${hookErr.message}`);
245
246
  }
246
247
  return {
247
248
  milestoneId: params.milestoneId,
@@ -7,6 +7,7 @@ import { renderPlanFromDb } from "../markdown-renderer.js";
7
7
  import { renderAllProjections } from "../workflow-projections.js";
8
8
  import { writeManifest } from "../workflow-manifest.js";
9
9
  import { appendEvent } from "../workflow-events.js";
10
+ import { logWarning } from "../workflow-logger.js";
10
11
  function validateTasks(value) {
11
12
  if (!Array.isArray(value) || value.length === 0) {
12
13
  throw new Error("tasks must be a non-empty array");
@@ -182,7 +183,7 @@ export async function handlePlanSlice(rawParams, basePath) {
182
183
  });
183
184
  }
184
185
  catch (hookErr) {
185
- process.stderr.write(`gsd: plan-slice post-mutation hook warning: ${hookErr.message}\n`);
186
+ logWarning("tool", `plan-slice post-mutation hook warning: ${hookErr.message}`);
186
187
  }
187
188
  return {
188
189
  milestoneId: params.milestoneId,
@@ -192,7 +193,7 @@ export async function handlePlanSlice(rawParams, basePath) {
192
193
  };
193
194
  }
194
195
  catch (renderErr) {
195
- process.stderr.write(`gsd-db: plan_slice — render failed (DB rows preserved for debugging): ${renderErr.message}\n`);
196
+ logWarning("tool", `plan_slice — render failed (DB rows preserved for debugging): ${renderErr.message}`);
196
197
  invalidateStateCache();
197
198
  return { error: `render failed: ${renderErr.message}` };
198
199
  }
@@ -7,6 +7,7 @@ import { renderTaskPlanFromDb } from "../markdown-renderer.js";
7
7
  import { renderAllProjections } from "../workflow-projections.js";
8
8
  import { writeManifest } from "../workflow-manifest.js";
9
9
  import { appendEvent } from "../workflow-events.js";
10
+ import { logWarning } from "../workflow-logger.js";
10
11
  function validateParams(params) {
11
12
  if (!isNonEmptyString(params?.milestoneId))
12
13
  throw new Error("milestoneId is required");
@@ -106,7 +107,7 @@ export async function handlePlanTask(rawParams, basePath) {
106
107
  });
107
108
  }
108
109
  catch (hookErr) {
109
- process.stderr.write(`gsd: plan-task post-mutation hook warning: ${hookErr.message}\n`);
110
+ logWarning("tool", `plan-task post-mutation hook warning: ${hookErr.message}`);
110
111
  }
111
112
  return {
112
113
  milestoneId: params.milestoneId,
@@ -9,6 +9,7 @@ import { renderRoadmapFromDb, renderAssessmentFromDb } from "../markdown-rendere
9
9
  import { renderAllProjections } from "../workflow-projections.js";
10
10
  import { writeManifest } from "../workflow-manifest.js";
11
11
  import { appendEvent } from "../workflow-events.js";
12
+ import { logWarning } from "../workflow-logger.js";
12
13
  function validateParams(params) {
13
14
  if (!isNonEmptyString(params?.milestoneId))
14
15
  throw new Error("milestoneId is required");
@@ -182,9 +183,8 @@ export async function handleReassessRoadmap(rawParams, basePath) {
182
183
  if (existsSync(validationFile))
183
184
  unlinkSync(validationFile);
184
185
  }
185
- catch {
186
- // Best-effort: DB row is already deleted, so state derivation
187
- // will not see the file-based verdict as authoritative.
186
+ catch (e) {
187
+ logWarning("tool", `validation file cleanup failed: ${e.message}`);
188
188
  }
189
189
  }
190
190
  // ── Invalidate caches ─────────────────────────────────────────
@@ -204,7 +204,7 @@ export async function handleReassessRoadmap(rawParams, basePath) {
204
204
  });
205
205
  }
206
206
  catch (hookErr) {
207
- process.stderr.write(`gsd: reassess-roadmap post-mutation hook warning: ${hookErr.message}\n`);
207
+ logWarning("tool", `reassess-roadmap post-mutation hook warning: ${hookErr.message}`);
208
208
  }
209
209
  return {
210
210
  milestoneId: params.milestoneId,
@@ -15,6 +15,7 @@ import { isClosedStatus } from "../status-guards.js";
15
15
  import { renderAllProjections } from "../workflow-projections.js";
16
16
  import { writeManifest } from "../workflow-manifest.js";
17
17
  import { appendEvent } from "../workflow-events.js";
18
+ import { logWarning } from "../workflow-logger.js";
18
19
  export async function handleReopenSlice(params, basePath) {
19
20
  // ── Validate required fields ────────────────────────────────────────────
20
21
  if (!params.sliceId || typeof params.sliceId !== "string" || params.sliceId.trim() === "") {
@@ -77,7 +78,7 @@ export async function handleReopenSlice(params, basePath) {
77
78
  });
78
79
  }
79
80
  catch (hookErr) {
80
- process.stderr.write(`gsd: reopen-slice post-mutation hook warning: ${hookErr.message}\n`);
81
+ logWarning("tool", `reopen-slice post-mutation hook warning: ${hookErr.message}`);
81
82
  }
82
83
  return {
83
84
  milestoneId: params.milestoneId,
@@ -14,6 +14,7 @@ import { isClosedStatus } from "../status-guards.js";
14
14
  import { renderAllProjections } from "../workflow-projections.js";
15
15
  import { writeManifest } from "../workflow-manifest.js";
16
16
  import { appendEvent } from "../workflow-events.js";
17
+ import { logWarning } from "../workflow-logger.js";
17
18
  export async function handleReopenTask(params, basePath) {
18
19
  // ── Validate required fields ────────────────────────────────────────────
19
20
  if (!params.taskId || typeof params.taskId !== "string" || params.taskId.trim() === "") {
@@ -81,7 +82,7 @@ export async function handleReopenTask(params, basePath) {
81
82
  });
82
83
  }
83
84
  catch (hookErr) {
84
- process.stderr.write(`gsd: reopen-task post-mutation hook warning: ${hookErr.message}\n`);
85
+ logWarning("tool", `reopen-task post-mutation hook warning: ${hookErr.message}`);
85
86
  }
86
87
  return {
87
88
  milestoneId: params.milestoneId,
@@ -7,6 +7,7 @@ import { renderPlanFromDb, renderReplanFromDb } from "../markdown-renderer.js";
7
7
  import { renderAllProjections } from "../workflow-projections.js";
8
8
  import { writeManifest } from "../workflow-manifest.js";
9
9
  import { appendEvent } from "../workflow-events.js";
10
+ import { logWarning } from "../workflow-logger.js";
10
11
  function validateParams(params) {
11
12
  if (!isNonEmptyString(params?.milestoneId))
12
13
  throw new Error("milestoneId is required");
@@ -173,7 +174,7 @@ export async function handleReplanSlice(rawParams, basePath) {
173
174
  });
174
175
  }
175
176
  catch (hookErr) {
176
- process.stderr.write(`gsd: replan-slice post-mutation hook warning: ${hookErr.message}\n`);
177
+ logWarning("tool", `replan-slice post-mutation hook warning: ${hookErr.message}`);
177
178
  }
178
179
  return {
179
180
  milestoneId: params.milestoneId,
@@ -15,6 +15,7 @@ import { saveFile, clearParseCache } from "../files.js";
15
15
  import { invalidateStateCache } from "../state.js";
16
16
  import { VALIDATION_VERDICTS, isValidMilestoneVerdict } from "../verdict-parser.js";
17
17
  import { insertMilestoneValidationGates } from "../milestone-validation-gates.js";
18
+ import { logWarning } from "../workflow-logger.js";
18
19
  function renderValidationMarkdown(params) {
19
20
  let md = `---
20
21
  verdict: ${params.verdict}
@@ -95,7 +96,7 @@ export async function handleValidateMilestone(params, basePath) {
95
96
  await saveFile(validationPath, validationMd);
96
97
  }
97
98
  catch (renderErr) {
98
- process.stderr.write(`gsd-db: validate_milestone — disk render failed, rolling back DB row: ${renderErr.message}\n`);
99
+ logWarning("tool", `validate_milestone — disk render failed, rolling back DB row: ${renderErr.message}`);
99
100
  deleteAssessmentByScope(params.milestoneId, 'milestone-validation');
100
101
  return { error: `disk render failed: ${renderErr.message}` };
101
102
  }
@@ -113,10 +113,17 @@ export function executeReplan(basePath, mid, sid, capture) {
113
113
  */
114
114
  export function executeBacktrack(basePath, currentMilestoneId, capture) {
115
115
  try {
116
- // Extract target milestone from capture text or resolution
117
- const targetMatch = (capture.resolution ?? capture.text)
118
- .match(/\b(M\d{3}(?:-[a-z0-9]{6})?)\b/);
119
- const targetMilestoneId = targetMatch?.[1] ?? null;
116
+ // Extract target milestone from capture text or resolution.
117
+ // Filter out the current milestone ID to avoid picking it as the backtrack target
118
+ // when the text mentions both current and target milestones (e.g. "backtrack from M004 to M003").
119
+ const sourceText = capture.resolution ?? capture.text;
120
+ const allMatches = [...sourceText.matchAll(/\b(M\d{3}(?:-[a-z0-9]{6})?)\b/g)]
121
+ .map(m => m[1])
122
+ .filter(id => id !== currentMilestoneId);
123
+ // Reject ambiguous multi-target strings — if more than one distinct target remains,
124
+ // don't guess; let the user clarify.
125
+ const uniqueTargets = [...new Set(allMatches)];
126
+ const targetMilestoneId = uniqueTargets.length === 1 ? uniqueTargets[0] : null;
120
127
  const ts = new Date().toISOString();
121
128
  const triggerPath = join(gsdRoot(basePath), "BACKTRACK-TRIGGER.md");
122
129
  const content = [
@@ -2,6 +2,7 @@ import { createHash, randomUUID } from "node:crypto";
2
2
  import { appendFileSync, readFileSync, existsSync, mkdirSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  import { atomicWriteSync } from "./atomic-write.js";
5
+ import { logWarning } from "./workflow-logger.js";
5
6
  // ─── Session ID ───────────────────────────────────────────────────────────
6
7
  /**
7
8
  * Engine-generated session ID — stable for the lifetime of this process.
@@ -49,7 +50,7 @@ export function readEvents(logPath) {
49
50
  events.push(JSON.parse(line));
50
51
  }
51
52
  catch {
52
- process.stderr.write(`workflow-events: skipping corrupted event line: ${line.slice(0, 80)}\n`);
53
+ logWarning("event-log", `skipping corrupted event line (${line.length} bytes)`);
53
54
  }
54
55
  }
55
56
  return events;
@@ -2,7 +2,9 @@
2
2
  // Centralized warning/error accumulator for the workflow engine pipeline.
3
3
  // Captures structured entries that the auto-loop can drain after each unit
4
4
  // to surface root causes for stuck loops, silent degradation, and blocked writes.
5
- // All entries are also persisted to .gsd/audit-log.jsonl for post-mortem analysis.
5
+ // Error-severity entries are persisted to .gsd/audit-log.jsonl (sanitized) for
6
+ // post-mortem analysis. Warnings are ephemeral (stderr + buffer only) to avoid
7
+ // log amplification from expected-control-flow catch paths.
6
8
  //
7
9
  // Stderr policy: every logWarning/logError call writes immediately to stderr
8
10
  // for terminal visibility. This is intentional — unlike debug-logger (which is
@@ -177,12 +179,15 @@ function _push(severity, component, message, context) {
177
179
  if (_buffer.length > MAX_BUFFER) {
178
180
  _buffer.shift();
179
181
  }
180
- // Persist to .gsd/audit-log.jsonl so entries survive context resets
181
- if (_auditBasePath) {
182
+ // Persist errors to .gsd/audit-log.jsonl so they survive context resets.
183
+ // Only error-severity entries are persisted — warnings are ephemeral (stderr + buffer)
184
+ // to avoid log amplification from expected-control-flow catch paths.
185
+ if (_auditBasePath && severity === "error") {
182
186
  try {
183
187
  const auditDir = join(_auditBasePath, ".gsd");
184
188
  mkdirSync(auditDir, { recursive: true });
185
- appendFileSync(join(auditDir, "audit-log.jsonl"), JSON.stringify(entry) + "\n", "utf-8");
189
+ const sanitized = _sanitizeForAudit(entry);
190
+ appendFileSync(join(auditDir, "audit-log.jsonl"), JSON.stringify(sanitized) + "\n", "utf-8");
186
191
  }
187
192
  catch (auditErr) {
188
193
  // Best-effort — never let audit write failures bubble up
@@ -190,3 +195,31 @@ function _push(severity, component, message, context) {
190
195
  }
191
196
  }
192
197
  }
198
+ /**
199
+ * Sanitize a log entry before persisting to the audit JSONL file.
200
+ * Strips potentially sensitive context (raw paths, cwd, full error text)
201
+ * to avoid leaking local environment details into durable telemetry.
202
+ */
203
+ function _sanitizeForAudit(entry) {
204
+ const sanitized = {
205
+ ts: entry.ts,
206
+ severity: entry.severity,
207
+ component: entry.component,
208
+ // Truncate message to avoid persisting oversized raw error dumps
209
+ message: entry.message.length > 200 ? entry.message.slice(0, 200) + "…[truncated]" : entry.message,
210
+ };
211
+ if (entry.context) {
212
+ // Allowlist: only persist known-safe structured keys
213
+ const SAFE_KEYS = new Set(["fn", "tool", "mid", "sid", "tid", "worktree"]);
214
+ const filtered = {};
215
+ for (const [k, v] of Object.entries(entry.context)) {
216
+ if (SAFE_KEYS.has(k)) {
217
+ filtered[k] = v;
218
+ }
219
+ }
220
+ if (Object.keys(filtered).length > 0) {
221
+ sanitized.context = filtered;
222
+ }
223
+ }
224
+ return sanitized;
225
+ }
@@ -6,6 +6,7 @@ import { existsSync, readdirSync, readFileSync } from "node:fs";
6
6
  import { join } from "node:path";
7
7
  import { _getAdapter, transaction } from "./gsd-db.js";
8
8
  import { parseRoadmap, parsePlan } from "./parsers-legacy.js";
9
+ import { logWarning } from "./workflow-logger.js";
9
10
  // ─── needsAutoMigration ───────────────────────────────────────────────────
10
11
  /**
11
12
  * Returns true when engine tables are empty AND a .gsd/milestones/ directory
@@ -22,8 +23,8 @@ export function needsAutoMigration(basePath) {
22
23
  if (row && row["cnt"] > 0)
23
24
  return false;
24
25
  }
25
- catch {
26
- // Table might not exist yet — that's fine, we can still migrate
26
+ catch (e) {
27
+ logWarning("migration", `DB probe failed: ${e.message}`);
27
28
  return false;
28
29
  }
29
30
  // Check if .gsd/milestones/ directory exists
@@ -66,7 +67,7 @@ export function migrateFromMarkdown(basePath) {
66
67
  .map(e => e.name);
67
68
  }
68
69
  catch {
69
- process.stderr.write("workflow-migration: failed to read milestones directory\n");
70
+ logWarning("migration", "failed to read milestones directory");
70
71
  return;
71
72
  }
72
73
  if (milestoneDirs.length === 0) {
@@ -102,7 +103,7 @@ export function migrateFromMarkdown(basePath) {
102
103
  }));
103
104
  }
104
105
  catch (err) {
105
- process.stderr.write(`workflow-migration: failed to parse ROADMAP.md for ${mId}: ${err.message}\n`);
106
+ logWarning("migration", `failed to parse ROADMAP.md for ${mId}: ${err.message}`);
106
107
  // Still add milestone with ID as title
107
108
  milestoneInserts.push({ id: mId, title: mId, status: milestoneStatus });
108
109
  }
@@ -148,7 +149,7 @@ export function migrateFromMarkdown(basePath) {
148
149
  }
149
150
  }
150
151
  catch (err) {
151
- process.stderr.write(`workflow-migration: failed to parse ${slice.id}-PLAN.md for ${mId}: ${err.message}\n`);
152
+ logWarning("migration", `failed to parse ${slice.id}-PLAN.md for ${mId}: ${err.message}`);
152
153
  }
153
154
  }
154
155
  }
@@ -163,8 +164,8 @@ export function migrateFromMarkdown(basePath) {
163
164
  }
164
165
  }
165
166
  }
166
- catch {
167
- // Non-fatal
167
+ catch (e) {
168
+ logWarning("migration", `Orphaned summary check failed for ${mId}: ${e.message}`);
168
169
  }
169
170
  }
170
171
  // Execute all inserts atomically
@@ -245,19 +246,20 @@ export function validateMigration(basePath) {
245
246
  const plan = parsePlan(planContent);
246
247
  mdTaskCount += plan.tasks.length;
247
248
  }
248
- catch {
249
- // Skip unreadable plan
249
+ catch (e) {
250
+ logWarning("migration", `Failed to read plan ${slice.id}-PLAN.md: ${e.message}`);
250
251
  }
251
252
  }
252
253
  }
253
254
  }
254
- catch {
255
- // Skip unreadable roadmap
255
+ catch (e) {
256
+ logWarning("migration", `Failed to read roadmap for ${mId}: ${e.message}`);
256
257
  }
257
258
  }
258
259
  }
259
260
  }
260
- catch {
261
+ catch (e) {
262
+ logWarning("migration", `Validation failed to read markdown: ${e.message}`);
261
263
  return { discrepancies: ["Failed to read markdown for validation"] };
262
264
  }
263
265
  // Compare counts
@@ -371,7 +371,7 @@ export function regenerateIfMissing(basePath, milestoneId, sliceId, fileType) {
371
371
  regenerated++;
372
372
  }
373
373
  catch (err) {
374
- console.error(`[projections] regenerateIfMissing SUMMARY failed for ${task.id}:`, err);
374
+ logWarning("projection", `regenerateIfMissing SUMMARY failed for ${task.id}: ${err.message}`);
375
375
  }
376
376
  }
377
377
  }
@@ -399,7 +399,7 @@ export function regenerateIfMissing(basePath, milestoneId, sliceId, fileType) {
399
399
  return true;
400
400
  }
401
401
  catch (err) {
402
- console.error(`[projections] regenerateIfMissing ${fileType} failed:`, err);
402
+ logWarning("projection", `regenerateIfMissing ${fileType} failed: ${err.message}`);
403
403
  return false;
404
404
  }
405
405
  }
@@ -375,8 +375,8 @@ function parseEventBlock(block) {
375
375
  try {
376
376
  params = JSON.parse(paramsMatch[1]);
377
377
  }
378
- catch {
379
- // Keep empty params on parse error
378
+ catch (e) {
379
+ logWarning("reconcile", `tool call params parse failed: ${e.message}`);
380
380
  }
381
381
  i++; // consume params line
382
382
  }