gsd-pi 2.59.0 → 2.60.0-dev.2580e65

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 (354) hide show
  1. package/dist/resources/extensions/ask-user-questions.js +7 -4
  2. package/dist/resources/extensions/gsd/auto/phases.js +62 -1
  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 +57 -3
  6. package/dist/resources/extensions/gsd/auto-post-unit.js +43 -3
  7. package/dist/resources/extensions/gsd/auto-prompts.js +49 -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 +72 -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 +58 -5
  20. package/dist/resources/extensions/gsd/bootstrap/system-context.js +11 -10
  21. package/dist/resources/extensions/gsd/captures.js +54 -1
  22. package/dist/resources/extensions/gsd/commands/catalog.js +2 -0
  23. package/dist/resources/extensions/gsd/commands-codebase.js +48 -21
  24. package/dist/resources/extensions/gsd/commands-inspect.js +2 -1
  25. package/dist/resources/extensions/gsd/commands-maintenance.js +32 -19
  26. package/dist/resources/extensions/gsd/complexity-classifier.js +9 -5
  27. package/dist/resources/extensions/gsd/context-masker.js +68 -0
  28. package/dist/resources/extensions/gsd/custom-verification.js +3 -2
  29. package/dist/resources/extensions/gsd/docs/preferences-reference.md +7 -0
  30. package/dist/resources/extensions/gsd/gsd-db.js +35 -15
  31. package/dist/resources/extensions/gsd/guided-flow.js +19 -9
  32. package/dist/resources/extensions/gsd/init-wizard.js +12 -0
  33. package/dist/resources/extensions/gsd/markdown-renderer.js +11 -9
  34. package/dist/resources/extensions/gsd/md-importer.js +5 -4
  35. package/dist/resources/extensions/gsd/milestone-actions.js +3 -2
  36. package/dist/resources/extensions/gsd/milestone-ids.js +2 -1
  37. package/dist/resources/extensions/gsd/model-router.js +199 -45
  38. package/dist/resources/extensions/gsd/parallel-merge.js +5 -3
  39. package/dist/resources/extensions/gsd/parallel-orchestrator.js +26 -14
  40. package/dist/resources/extensions/gsd/phase-anchor.js +56 -0
  41. package/dist/resources/extensions/gsd/preferences-types.js +2 -0
  42. package/dist/resources/extensions/gsd/preferences-validation.js +91 -0
  43. package/dist/resources/extensions/gsd/preferences.js +15 -3
  44. package/dist/resources/extensions/gsd/prompt-loader.js +3 -2
  45. package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -0
  46. package/dist/resources/extensions/gsd/prompts/rethink.md +7 -0
  47. package/dist/resources/extensions/gsd/prompts/triage-captures.md +6 -1
  48. package/dist/resources/extensions/gsd/rethink.js +5 -2
  49. package/dist/resources/extensions/gsd/rule-registry.js +7 -6
  50. package/dist/resources/extensions/gsd/safe-fs.js +6 -8
  51. package/dist/resources/extensions/gsd/state.js +1 -1
  52. package/dist/resources/extensions/gsd/status-guards.js +4 -3
  53. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
  54. package/dist/resources/extensions/gsd/tools/complete-slice.js +3 -2
  55. package/dist/resources/extensions/gsd/tools/complete-task.js +3 -2
  56. package/dist/resources/extensions/gsd/tools/plan-milestone.js +3 -2
  57. package/dist/resources/extensions/gsd/tools/plan-slice.js +3 -2
  58. package/dist/resources/extensions/gsd/tools/plan-task.js +2 -1
  59. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +4 -4
  60. package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -1
  61. package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -1
  62. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -1
  63. package/dist/resources/extensions/gsd/tools/validate-milestone.js +2 -1
  64. package/dist/resources/extensions/gsd/triage-resolution.js +135 -1
  65. package/dist/resources/extensions/gsd/triage-ui.js +12 -3
  66. package/dist/resources/extensions/gsd/workflow-events.js +2 -1
  67. package/dist/resources/extensions/gsd/workflow-logger.js +37 -4
  68. package/dist/resources/extensions/gsd/workflow-migration.js +14 -12
  69. package/dist/resources/extensions/gsd/workflow-projections.js +2 -2
  70. package/dist/resources/extensions/gsd/workflow-reconcile.js +2 -2
  71. package/dist/resources/extensions/gsd/worktree-manager.js +26 -14
  72. package/dist/resources/extensions/shared/interview-ui.js +3 -1
  73. package/dist/resources/skills/btw/SKILL.md +42 -0
  74. package/dist/web/standalone/.next/BUILD_ID +1 -1
  75. package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
  76. package/dist/web/standalone/.next/build-manifest.json +3 -3
  77. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  78. package/dist/web/standalone/.next/required-server-files.json +3 -3
  79. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  80. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  81. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  82. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  90. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  92. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  93. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  94. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  96. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  106. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  118. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  146. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  152. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  166. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  168. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  170. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  172. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/index.html +1 -1
  182. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  183. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  184. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  185. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  186. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  187. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  188. package/dist/web/standalone/.next/server/app/page.js +2 -2
  189. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app-paths-manifest.json +17 -17
  191. package/dist/web/standalone/.next/server/chunks/2229.js +1 -1
  192. package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
  193. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/middleware.js +2 -2
  195. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  196. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  197. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  198. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  199. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  200. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  201. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  202. package/dist/web/standalone/.next/static/chunks/app/page-0c485498795110d6.js +1 -0
  203. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  204. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  205. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  206. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  207. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  208. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  209. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  210. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  211. package/dist/web/standalone/server.js +1 -1
  212. package/package.json +1 -1
  213. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  214. package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -0
  215. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  216. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -1
  217. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  218. package/packages/pi-coding-agent/dist/core/extensions/runner.js +16 -0
  219. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  220. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +26 -0
  221. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  222. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  223. package/packages/pi-coding-agent/dist/core/lsp/config.d.ts.map +1 -1
  224. package/packages/pi-coding-agent/dist/core/lsp/config.js +6 -1
  225. package/packages/pi-coding-agent/dist/core/lsp/config.js.map +1 -1
  226. package/packages/pi-coding-agent/dist/core/lsp/defaults.json +2 -2
  227. package/packages/pi-coding-agent/dist/core/lsp/lsp-legacy-alias.test.d.ts +2 -0
  228. package/packages/pi-coding-agent/dist/core/lsp/lsp-legacy-alias.test.d.ts.map +1 -0
  229. package/packages/pi-coding-agent/dist/core/lsp/lsp-legacy-alias.test.js +47 -0
  230. package/packages/pi-coding-agent/dist/core/lsp/lsp-legacy-alias.test.js.map +1 -0
  231. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts +1 -0
  232. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  233. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +6 -0
  234. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  235. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.d.ts +2 -0
  236. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.d.ts.map +1 -0
  237. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +122 -0
  238. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -0
  239. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +1 -0
  240. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  241. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +30 -0
  242. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  243. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
  244. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +1 -7
  245. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  246. package/packages/pi-coding-agent/package.json +1 -1
  247. package/packages/pi-coding-agent/src/core/extensions/loader.ts +6 -0
  248. package/packages/pi-coding-agent/src/core/extensions/runner.ts +19 -0
  249. package/packages/pi-coding-agent/src/core/extensions/types.ts +26 -0
  250. package/packages/pi-coding-agent/src/core/lsp/config.ts +7 -1
  251. package/packages/pi-coding-agent/src/core/lsp/defaults.json +2 -2
  252. package/packages/pi-coding-agent/src/core/lsp/lsp-legacy-alias.test.ts +70 -0
  253. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +156 -0
  254. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +7 -0
  255. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +38 -0
  256. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +1 -8
  257. package/pkg/package.json +1 -1
  258. package/src/resources/extensions/ask-user-questions.ts +7 -3
  259. package/src/resources/extensions/gsd/auto/phases.ts +70 -1
  260. package/src/resources/extensions/gsd/auto-dashboard.ts +22 -8
  261. package/src/resources/extensions/gsd/auto-dispatch.ts +7 -3
  262. package/src/resources/extensions/gsd/auto-model-selection.ts +77 -6
  263. package/src/resources/extensions/gsd/auto-post-unit.ts +52 -5
  264. package/src/resources/extensions/gsd/auto-prompts.ts +54 -20
  265. package/src/resources/extensions/gsd/auto-recovery.ts +38 -18
  266. package/src/resources/extensions/gsd/auto-start.ts +10 -9
  267. package/src/resources/extensions/gsd/auto-timers.ts +12 -5
  268. package/src/resources/extensions/gsd/auto-unit-closeout.ts +6 -2
  269. package/src/resources/extensions/gsd/auto-verification.ts +3 -6
  270. package/src/resources/extensions/gsd/auto-worktree.ts +121 -55
  271. package/src/resources/extensions/gsd/auto.ts +40 -17
  272. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +4 -3
  273. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +80 -2
  274. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +4 -16
  275. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +2 -1
  276. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +61 -4
  277. package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -10
  278. package/src/resources/extensions/gsd/captures.ts +71 -2
  279. package/src/resources/extensions/gsd/commands/catalog.ts +2 -0
  280. package/src/resources/extensions/gsd/commands-codebase.ts +52 -20
  281. package/src/resources/extensions/gsd/commands-inspect.ts +2 -1
  282. package/src/resources/extensions/gsd/commands-maintenance.ts +28 -19
  283. package/src/resources/extensions/gsd/complexity-classifier.ts +10 -5
  284. package/src/resources/extensions/gsd/context-masker.ts +74 -0
  285. package/src/resources/extensions/gsd/custom-verification.ts +3 -2
  286. package/src/resources/extensions/gsd/docs/preferences-reference.md +7 -0
  287. package/src/resources/extensions/gsd/gsd-db.ts +14 -16
  288. package/src/resources/extensions/gsd/guided-flow.ts +9 -8
  289. package/src/resources/extensions/gsd/init-wizard.ts +12 -0
  290. package/src/resources/extensions/gsd/markdown-renderer.ts +11 -17
  291. package/src/resources/extensions/gsd/md-importer.ts +5 -4
  292. package/src/resources/extensions/gsd/milestone-actions.ts +3 -2
  293. package/src/resources/extensions/gsd/milestone-ids.ts +2 -1
  294. package/src/resources/extensions/gsd/model-router.ts +245 -56
  295. package/src/resources/extensions/gsd/parallel-merge.ts +5 -3
  296. package/src/resources/extensions/gsd/parallel-orchestrator.ts +18 -14
  297. package/src/resources/extensions/gsd/phase-anchor.ts +71 -0
  298. package/src/resources/extensions/gsd/preferences-types.ts +22 -0
  299. package/src/resources/extensions/gsd/preferences-validation.ts +83 -0
  300. package/src/resources/extensions/gsd/preferences.ts +16 -3
  301. package/src/resources/extensions/gsd/prompt-loader.ts +3 -2
  302. package/src/resources/extensions/gsd/prompts/execute-task.md +2 -0
  303. package/src/resources/extensions/gsd/prompts/rethink.md +7 -0
  304. package/src/resources/extensions/gsd/prompts/triage-captures.md +6 -1
  305. package/src/resources/extensions/gsd/rethink.ts +5 -2
  306. package/src/resources/extensions/gsd/rule-registry.ts +7 -6
  307. package/src/resources/extensions/gsd/safe-fs.ts +6 -5
  308. package/src/resources/extensions/gsd/state.ts +1 -1
  309. package/src/resources/extensions/gsd/status-guards.ts +4 -3
  310. package/src/resources/extensions/gsd/tests/capability-router.test.ts +347 -0
  311. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +63 -0
  312. package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +27 -2
  313. package/src/resources/extensions/gsd/tests/context-masker.test.ts +122 -0
  314. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +4 -4
  315. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +1188 -0
  316. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +841 -0
  317. package/src/resources/extensions/gsd/tests/model-router.test.ts +488 -2
  318. package/src/resources/extensions/gsd/tests/phase-anchor.test.ts +83 -0
  319. package/src/resources/extensions/gsd/tests/preferences.test.ts +62 -0
  320. package/src/resources/extensions/gsd/tests/remote-questions.test.ts +21 -0
  321. package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +284 -0
  322. package/src/resources/extensions/gsd/tests/status-guards.test.ts +4 -0
  323. package/src/resources/extensions/gsd/tests/stop-backtrack.test.ts +216 -0
  324. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +1 -1
  325. package/src/resources/extensions/gsd/tests/workflow-logger-audit.test.ts +120 -0
  326. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +6 -6
  327. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -6
  328. package/src/resources/extensions/gsd/tools/complete-slice.ts +3 -6
  329. package/src/resources/extensions/gsd/tools/complete-task.ts +3 -6
  330. package/src/resources/extensions/gsd/tools/plan-milestone.ts +3 -6
  331. package/src/resources/extensions/gsd/tools/plan-slice.ts +3 -6
  332. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -3
  333. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +4 -6
  334. package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -3
  335. package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -3
  336. package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -3
  337. package/src/resources/extensions/gsd/tools/validate-milestone.ts +2 -3
  338. package/src/resources/extensions/gsd/triage-resolution.ts +151 -1
  339. package/src/resources/extensions/gsd/triage-ui.ts +12 -3
  340. package/src/resources/extensions/gsd/types.ts +1 -0
  341. package/src/resources/extensions/gsd/workflow-events.ts +2 -1
  342. package/src/resources/extensions/gsd/workflow-logger.ts +52 -5
  343. package/src/resources/extensions/gsd/workflow-migration.ts +14 -12
  344. package/src/resources/extensions/gsd/workflow-projections.ts +2 -2
  345. package/src/resources/extensions/gsd/workflow-reconcile.ts +2 -2
  346. package/src/resources/extensions/gsd/worktree-manager.ts +16 -14
  347. package/src/resources/extensions/shared/interview-ui.ts +3 -1
  348. package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +144 -0
  349. package/src/resources/skills/btw/SKILL.md +42 -0
  350. package/dist/web/standalone/.next/static/chunks/app/page-62be3b5fa91e4c8f.js +0 -1
  351. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  352. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  353. /package/dist/web/standalone/.next/static/{DGvT_c5Vb7Wu3X-fEOVUU → ogyMN7M-3bGGuRY08L5HR}/_buildManifest.js +0 -0
  354. /package/dist/web/standalone/.next/static/{DGvT_c5Vb7Wu3X-fEOVUU → ogyMN7M-3bGGuRY08L5HR}/_ssgManifest.js +0 -0
@@ -34,7 +34,7 @@ import { clearSkillSnapshot } from "./skill-discovery.js";
34
34
  import { captureAvailableSkills, resetSkillTelemetry, } from "./skill-telemetry.js";
35
35
  import { getRtkSessionSavings } from "../shared/rtk-session-stats.js";
36
36
  import { initMetrics, resetMetrics, getLedger, getProjectTotals, formatCost, formatTokenCount, } from "./metrics.js";
37
- import { setLogBasePath } from "./workflow-logger.js";
37
+ import { setLogBasePath, logWarning } from "./workflow-logger.js";
38
38
  import { join } from "node:path";
39
39
  import { readFileSync, existsSync, mkdirSync, writeFileSync, unlinkSync } from "node:fs";
40
40
  import { atomicWriteSync } from "./atomic-write.js";
@@ -137,8 +137,9 @@ export function getAutoDashboardData() {
137
137
  pendingCaptureCount = countPendingCaptures(s.basePath);
138
138
  }
139
139
  }
140
- catch {
140
+ catch (err) {
141
141
  // Non-fatal — captures module may not be loaded
142
+ logWarning("engine", `capture count failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
142
143
  }
143
144
  return {
144
145
  active: s.active,
@@ -340,8 +341,9 @@ function cleanupAfterLoopExit(ctx) {
340
341
  if (lockBase())
341
342
  releaseSessionLock(lockBase());
342
343
  }
343
- catch {
344
+ catch (err) {
344
345
  /* best-effort — mirror stopAuto cleanup */
346
+ logWarning("session", `lock cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
345
347
  }
346
348
  ctx.ui.setStatus("gsd-auto", undefined);
347
349
  ctx.ui.setWidget("gsd-progress", undefined);
@@ -352,8 +354,9 @@ function cleanupAfterLoopExit(ctx) {
352
354
  try {
353
355
  process.chdir(s.basePath);
354
356
  }
355
- catch {
357
+ catch (err) {
356
358
  /* best-effort */
359
+ logWarning("engine", `chdir failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
357
360
  }
358
361
  }
359
362
  }
@@ -415,8 +418,9 @@ export async function stopAuto(ctx, pi, reason) {
415
418
  milestoneComplete = true;
416
419
  }
417
420
  }
418
- catch {
421
+ catch (err) {
419
422
  // Non-fatal — fall through to preserveBranch path
423
+ logWarning("engine", `milestone summary check failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
420
424
  }
421
425
  if (milestoneComplete) {
422
426
  // Milestone is complete — merge worktree branch back to main
@@ -452,8 +456,9 @@ export async function stopAuto(ctx, pi, reason) {
452
456
  try {
453
457
  process.chdir(s.basePath);
454
458
  }
455
- catch {
459
+ catch (err) {
456
460
  /* best-effort */
461
+ logWarning("engine", `chdir failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
457
462
  }
458
463
  }
459
464
  }
@@ -522,7 +527,9 @@ export async function stopAuto(ctx, pi, reason) {
522
527
  if (existsSync(pausedPath))
523
528
  unlinkSync(pausedPath);
524
529
  }
525
- catch { /* non-fatal */ }
530
+ catch (err) { /* non-fatal */
531
+ logWarning("engine", `file unlink failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
532
+ }
526
533
  // ── Step 13: Restore original model (before reset clears IDs) ──
527
534
  try {
528
535
  if (pi && ctx && s.originalModelId && s.originalModelProvider) {
@@ -556,7 +563,9 @@ export async function stopAuto(ctx, pi, reason) {
556
563
  await closeBrowser();
557
564
  }
558
565
  }
559
- catch { /* non-fatal: browser-tools may not be loaded */ }
566
+ catch (err) { /* non-fatal: browser-tools may not be loaded */
567
+ logWarning("engine", `browser teardown failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
568
+ }
560
569
  // External cleanup (not covered by session reset)
561
570
  clearInFlightTools();
562
571
  clearSliceProgressCache();
@@ -602,16 +611,18 @@ export async function pauseAuto(ctx, _pi, _errorContext) {
602
611
  mkdirSync(runtimeDir, { recursive: true });
603
612
  writeFileSync(join(runtimeDir, "paused-session.json"), JSON.stringify(pausedMeta, null, 2), "utf-8");
604
613
  }
605
- catch {
614
+ catch (err) {
606
615
  // Non-fatal — resume will still work via full bootstrap, just without worktree context
616
+ logWarning("engine", `paused-session file write failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
607
617
  }
608
618
  // Close out the current unit so its runtime record doesn't stay at "dispatched"
609
619
  if (s.currentUnit && ctx) {
610
620
  try {
611
621
  await closeoutUnit(ctx, s.basePath, s.currentUnit.type, s.currentUnit.id, s.currentUnit.startedAt);
612
622
  }
613
- catch {
623
+ catch (err) {
614
624
  // Non-fatal — best-effort closeout on pause
625
+ logWarning("engine", `unit closeout on pause failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
615
626
  }
616
627
  s.currentUnit = null;
617
628
  }
@@ -798,7 +809,9 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
798
809
  try {
799
810
  unlinkSync(pausedPath);
800
811
  }
801
- catch { /* non-fatal */ }
812
+ catch (err) { /* non-fatal */
813
+ logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
814
+ }
802
815
  ctx.ui.notify(`Resuming paused custom workflow${meta.activeRunDir ? ` (${meta.activeRunDir})` : ""}.`, "info");
803
816
  }
804
817
  else if (meta.milestoneId) {
@@ -810,7 +823,9 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
810
823
  try {
811
824
  unlinkSync(pausedPath);
812
825
  }
813
- catch { /* non-fatal */ }
826
+ catch (err) { /* non-fatal */
827
+ logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
828
+ }
814
829
  ctx.ui.notify(`Paused milestone ${meta.milestoneId} is ${!mDir ? "missing" : "already complete"}. Starting fresh.`, "info");
815
830
  }
816
831
  else {
@@ -822,14 +837,17 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
822
837
  try {
823
838
  unlinkSync(pausedPath);
824
839
  }
825
- catch { /* non-fatal */ }
840
+ catch (err) { /* non-fatal */
841
+ logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
842
+ }
826
843
  ctx.ui.notify(`Resuming paused session for ${meta.milestoneId}${meta.worktreePath ? ` (worktree)` : ""}.`, "info");
827
844
  }
828
845
  }
829
846
  }
830
847
  }
831
- catch {
848
+ catch (err) {
832
849
  // Malformed or missing — proceed with fresh bootstrap
850
+ logWarning("session", `paused-session restore failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
833
851
  }
834
852
  }
835
853
  if (s.paused) {
@@ -917,8 +935,9 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
917
935
  try {
918
936
  syncCmuxSidebar(loadEffectiveGSDPreferences()?.preferences, await deriveState(s.basePath));
919
937
  }
920
- catch {
938
+ catch (err) {
921
939
  // Best-effort only — sidebar sync must never block auto-mode startup
940
+ logWarning("engine", `cmux sync failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
922
941
  }
923
942
  logCmuxEvent(loadEffectiveGSDPreferences()?.preferences, requestedStepMode ? "Step-mode started." : "Auto-mode started.", "progress");
924
943
  // Dispatch the first unit
@@ -1043,8 +1062,9 @@ export async function dispatchHookUnit(ctx, pi, hookName, triggerUnitType, trigg
1043
1062
  try {
1044
1063
  await pi.setModel(match);
1045
1064
  }
1046
- catch {
1065
+ catch (err) {
1047
1066
  /* non-fatal */
1067
+ logWarning("dispatch", `hook model set failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
1048
1068
  }
1049
1069
  }
1050
1070
  else {
@@ -1072,7 +1092,9 @@ export async function dispatchHookUnit(ctx, pi, hookName, triggerUnitType, trigg
1072
1092
  if (process.cwd() !== s.basePath)
1073
1093
  process.chdir(s.basePath);
1074
1094
  }
1075
- catch { }
1095
+ catch (err) {
1096
+ logWarning("engine", `chdir failed before hook dispatch: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
1097
+ }
1076
1098
  debugLog("dispatchHookUnit", {
1077
1099
  phase: "send-message",
1078
1100
  promptLength: hookPrompt.length,
@@ -1,3 +1,4 @@
1
+ import { logWarning } from "../workflow-logger.js";
1
2
  import { checkAutoStartAfterDiscuss } from "../guided-flow.js";
2
3
  import { getAutoDashboardData, getAutoModeStartModel, isAutoActive, pauseAuto } from "../auto.js";
3
4
  import { getNextFallbackModel, resolveModelWithFallbacksForUnit } from "../preferences.js";
@@ -68,7 +69,9 @@ export async function handleAgentEnd(pi, event, ctx) {
68
69
  try {
69
70
  await pauseAuto(ctx, pi);
70
71
  }
71
- catch { /* best-effort */ }
72
+ catch (e) {
73
+ logWarning("bootstrap", `pauseAuto failed after empty-content abort: ${e.message}`);
74
+ }
72
75
  }
73
76
  return;
74
77
  }
@@ -184,8 +187,8 @@ export async function handleAgentEnd(pi, event, ctx) {
184
187
  try {
185
188
  await pauseAuto(ctx, pi);
186
189
  }
187
- catch {
188
- // best-effort
190
+ catch (e) {
191
+ logWarning("bootstrap", `pauseAuto failed in agent_end handler: ${e.message}`);
189
192
  }
190
193
  }
191
194
  }
@@ -403,8 +403,8 @@ export function registerDbTools(pi) {
403
403
  const { insertMilestone } = await import("../gsd-db.js");
404
404
  insertMilestone({ id: milestoneId, status: "queued" });
405
405
  }
406
- catch {
407
- // Non-fatal the safety-net in deriveStateFromDb will catch this
406
+ catch (e) {
407
+ logError("tool", `insertMilestone failed for ${milestoneId}: ${e.message}`);
408
408
  }
409
409
  }
410
410
  const milestoneGenerateIdTool = {
@@ -832,6 +832,76 @@ export function registerDbTools(pi) {
832
832
  };
833
833
  pi.registerTool(sliceCompleteTool);
834
834
  registerAlias(pi, sliceCompleteTool, "gsd_complete_slice", "gsd_slice_complete");
835
+ // ─── gsd_skip_slice (#3477 / #3487) ───────────────────────────────────
836
+ const skipSliceExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
837
+ const dbAvailable = await ensureDbOpen();
838
+ if (!dbAvailable) {
839
+ return {
840
+ content: [{ type: "text", text: "Error: GSD database is not available. Cannot skip slice." }],
841
+ details: { operation: "skip_slice", error: "db_unavailable" },
842
+ };
843
+ }
844
+ try {
845
+ const { getSlice, updateSliceStatus } = await import("../gsd-db.js");
846
+ const { invalidateStateCache } = await import("../state.js");
847
+ const slice = getSlice(params.milestoneId, params.sliceId);
848
+ if (!slice) {
849
+ return {
850
+ content: [{ type: "text", text: `Error: Slice ${params.sliceId} not found in milestone ${params.milestoneId}` }],
851
+ details: { operation: "skip_slice", error: "slice_not_found" },
852
+ };
853
+ }
854
+ if (slice.status === "complete" || slice.status === "done") {
855
+ return {
856
+ content: [{ type: "text", text: `Error: Slice ${params.sliceId} is already complete — cannot skip.` }],
857
+ details: { operation: "skip_slice", error: "already_complete" },
858
+ };
859
+ }
860
+ if (slice.status === "skipped") {
861
+ return {
862
+ content: [{ type: "text", text: `Slice ${params.sliceId} is already skipped.` }],
863
+ details: { operation: "skip_slice", sliceId: params.sliceId, milestoneId: params.milestoneId },
864
+ };
865
+ }
866
+ updateSliceStatus(params.milestoneId, params.sliceId, "skipped");
867
+ invalidateStateCache();
868
+ return {
869
+ content: [{ type: "text", text: `Skipped slice ${params.sliceId} (${params.milestoneId}). Reason: ${params.reason ?? "User-directed skip"}. Auto-mode will advance past this slice.` }],
870
+ details: {
871
+ operation: "skip_slice",
872
+ sliceId: params.sliceId,
873
+ milestoneId: params.milestoneId,
874
+ reason: params.reason,
875
+ },
876
+ };
877
+ }
878
+ catch (err) {
879
+ const msg = err instanceof Error ? err.message : String(err);
880
+ logError("tool", `skip_slice tool failed: ${msg}`, { tool: "gsd_skip_slice", error: String(err) });
881
+ return {
882
+ content: [{ type: "text", text: `Error skipping slice: ${msg}` }],
883
+ details: { operation: "skip_slice", error: msg },
884
+ };
885
+ }
886
+ };
887
+ pi.registerTool({
888
+ name: "gsd_skip_slice",
889
+ label: "Skip Slice",
890
+ description: "Mark a slice as skipped so auto-mode advances past it without executing. " +
891
+ "The slice data is preserved for reference. The state machine treats skipped slices like completed ones for dependency satisfaction.",
892
+ promptSnippet: "Skip a GSD slice (mark as skipped, auto-mode will advance past it)",
893
+ promptGuidelines: [
894
+ "Use gsd_skip_slice when a slice should be bypassed — descoped, superseded, or no longer relevant.",
895
+ "Cannot skip a slice that is already complete.",
896
+ "Skipped slices satisfy downstream dependencies just like completed slices.",
897
+ ],
898
+ parameters: Type.Object({
899
+ sliceId: Type.String({ description: "Slice ID (e.g. S02)" }),
900
+ milestoneId: Type.String({ description: "Milestone ID (e.g. M003)" }),
901
+ reason: Type.Optional(Type.String({ description: "Reason for skipping this slice" })),
902
+ }),
903
+ execute: skipSliceExecute,
904
+ });
835
905
  // ─── gsd_complete_milestone ────────────────────────────────────────────
836
906
  const milestoneCompleteExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
837
907
  const dbAvailable = await ensureDbOpen();
@@ -2,7 +2,7 @@ import { existsSync } from "node:fs";
2
2
  import { join, sep } from "node:path";
3
3
  import { createBashTool, createEditTool, createReadTool, createWriteTool } from "@gsd/pi-coding-agent";
4
4
  import { DEFAULT_BASH_TIMEOUT_SECS } from "../constants.js";
5
- import { setLogBasePath } from "../workflow-logger.js";
5
+ import { setLogBasePath, logWarning } from "../workflow-logger.js";
6
6
  /**
7
7
  * Resolve the correct DB path for the current working directory.
8
8
  * If `basePath` is inside a `.gsd/worktrees/<MID>/` directory, returns
@@ -82,7 +82,7 @@ export async function ensureDbOpen() {
82
82
  migrateFromMarkdown(basePath);
83
83
  }
84
84
  catch (err) {
85
- process.stderr.write(`gsd-db: ensureDbOpen auto-migration failed: ${err.message}\n`);
85
+ logWarning("bootstrap", `ensureDbOpen auto-migration failed: ${err.message}`);
86
86
  }
87
87
  }
88
88
  return opened;
@@ -93,17 +93,11 @@ export async function ensureDbOpen() {
93
93
  setLogBasePath(projectRoot);
94
94
  return opened;
95
95
  }
96
- process.stderr.write(`gsd-db: ensureDbOpen failed — no .gsd directory found (resolvedPath=${resolveProjectRootDbPath(basePath)}, cwd=${basePath})\n`);
96
+ logWarning("bootstrap", "ensureDbOpen failed — no .gsd directory found");
97
97
  return false;
98
98
  }
99
99
  catch (err) {
100
- const basePath = process.cwd();
101
- const diagnostic = {
102
- resolvedPath: resolveProjectRootDbPath(basePath),
103
- cwd: basePath,
104
- error: err.message ?? String(err),
105
- };
106
- process.stderr.write(`gsd-db: ensureDbOpen failed — ${JSON.stringify(diagnostic)}\n`);
100
+ logWarning("bootstrap", `ensureDbOpen failed: ${err.message ?? String(err)}`);
107
101
  return false;
108
102
  }
109
103
  }
@@ -1,5 +1,6 @@
1
1
  import { Type } from "@sinclair/typebox";
2
2
  import { queryJournal } from "../journal.js";
3
+ import { logWarning } from "../workflow-logger.js";
3
4
  export function registerJournalTools(pi) {
4
5
  pi.registerTool({
5
6
  name: "gsd_journal_query",
@@ -51,7 +52,7 @@ export function registerJournalTools(pi) {
51
52
  }
52
53
  catch (err) {
53
54
  const msg = err instanceof Error ? err.message : String(err);
54
- process.stderr.write(`gsd-journal: gsd_journal_query tool failed: ${msg}\n`);
55
+ logWarning("tool", `gsd_journal_query tool failed: ${msg}`);
55
56
  return {
56
57
  content: [{ type: "text", text: `Error querying journal: ${msg}` }],
57
58
  details: { operation: "journal_query", error: msg },
@@ -244,17 +244,70 @@ export function registerHooks(pi) {
244
244
  await syncServiceTierStatus(ctx);
245
245
  });
246
246
  pi.on("before_provider_request", async (event) => {
247
+ const payload = event.payload;
248
+ if (!payload || typeof payload !== "object")
249
+ return;
250
+ // ── Observation Masking ─────────────────────────────────────────────
251
+ // Replace old tool results with placeholders to reduce context bloat.
252
+ // Only active during auto-mode when context_management.observation_masking is enabled.
253
+ if (isAutoActive()) {
254
+ try {
255
+ const { loadEffectiveGSDPreferences } = await import("../preferences.js");
256
+ const prefs = loadEffectiveGSDPreferences();
257
+ const cmConfig = prefs?.preferences.context_management;
258
+ // Observation masking: replace old tool results with placeholders
259
+ if (cmConfig?.observation_masking !== false) {
260
+ const keepTurns = cmConfig?.observation_mask_turns ?? 8;
261
+ const { createObservationMask } = await import("../context-masker.js");
262
+ const mask = createObservationMask(keepTurns);
263
+ const messages = payload.messages;
264
+ if (Array.isArray(messages)) {
265
+ payload.messages = mask(messages);
266
+ }
267
+ }
268
+ // Tool result truncation: cap individual tool result content length.
269
+ // In pi-ai format, toolResult messages have role: "toolResult" and content: TextContent[].
270
+ // Creates new objects to avoid mutating shared conversation state.
271
+ const maxChars = cmConfig?.tool_result_max_chars ?? 800;
272
+ const msgs = payload.messages;
273
+ if (Array.isArray(msgs)) {
274
+ payload.messages = msgs.map((msg) => {
275
+ // Match toolResult messages (role: "toolResult", content is array of content blocks)
276
+ if (msg?.role === "toolResult" && Array.isArray(msg.content)) {
277
+ const blocks = msg.content;
278
+ const totalLen = blocks.reduce((sum, b) => sum + (typeof b.text === "string" ? b.text.length : 0), 0);
279
+ if (totalLen > maxChars) {
280
+ const truncated = blocks.map(b => {
281
+ if (typeof b.text === "string" && b.text.length > maxChars) {
282
+ return { ...b, text: b.text.slice(0, maxChars) + "\n…[truncated]" };
283
+ }
284
+ return b;
285
+ });
286
+ return { ...msg, content: truncated };
287
+ }
288
+ }
289
+ return msg;
290
+ });
291
+ }
292
+ }
293
+ catch { /* non-fatal */ }
294
+ }
295
+ // ── Service Tier ────────────────────────────────────────────────────
247
296
  const modelId = event.model?.id;
248
297
  if (!modelId)
249
- return;
298
+ return payload;
250
299
  const { getEffectiveServiceTier, supportsServiceTier } = await import("../service-tier.js");
251
300
  const tier = getEffectiveServiceTier();
252
301
  if (!tier || !supportsServiceTier(modelId))
253
- return;
254
- const payload = event.payload;
255
- if (!payload || typeof payload !== "object")
256
- return;
302
+ return payload;
257
303
  payload.service_tier = tier;
258
304
  return payload;
259
305
  });
306
+ // Capability-aware model routing hook (ADR-004)
307
+ // Extensions can override model selection by returning { modelId: "..." }
308
+ // Return undefined to let the built-in capability scoring proceed.
309
+ pi.on("before_model_select", async (_event) => {
310
+ // Default: no override — let capability scoring handle selection
311
+ return undefined;
312
+ });
260
313
  }
@@ -1,6 +1,7 @@
1
1
  import { existsSync, readFileSync, unlinkSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import { join } from "node:path";
4
+ import { logWarning } from "../workflow-logger.js";
4
5
  import { debugTime } from "../debug-logger.js";
5
6
  import { loadPrompt } from "../prompt-loader.js";
6
7
  import { readForensicsMarker } from "../forensics.js";
@@ -61,8 +62,8 @@ export async function buildBeforeAgentStartResult(event, ctx) {
61
62
  }
62
63
  }
63
64
  }
64
- catch {
65
- // non-fatal
65
+ catch (e) {
66
+ logWarning("bootstrap", `memory block fetch failed: ${e.message}`);
66
67
  }
67
68
  let newSkillsBlock = "";
68
69
  if (hasSkillSnapshot()) {
@@ -88,8 +89,8 @@ export async function buildBeforeAgentStartResult(event, ctx) {
88
89
  codebaseBlock = `\n\n[PROJECT CODEBASE — File structure and descriptions (generated ${generatedAt}, may be stale — run /gsd codebase update to refresh)]\n\n${content}`;
89
90
  }
90
91
  }
91
- catch {
92
- // skip
92
+ catch (e) {
93
+ logWarning("bootstrap", `CODEBASE file read failed: ${e.message}`);
93
94
  }
94
95
  }
95
96
  warnDeprecatedAgentInstructions();
@@ -128,8 +129,8 @@ export function loadKnowledgeBlock(gsdHomeDir, cwd) {
128
129
  globalKnowledge = content;
129
130
  }
130
131
  }
131
- catch {
132
- // skip
132
+ catch (e) {
133
+ logWarning("bootstrap", `global knowledge file read failed: ${e.message}`);
133
134
  }
134
135
  }
135
136
  // 2. Project knowledge (.gsd/KNOWLEDGE.md) — project-specific
@@ -141,8 +142,8 @@ export function loadKnowledgeBlock(gsdHomeDir, cwd) {
141
142
  if (content)
142
143
  projectKnowledge = content;
143
144
  }
144
- catch {
145
- // skip
145
+ catch (e) {
146
+ logWarning("bootstrap", `project knowledge file read failed: ${e.message}`);
146
147
  }
147
148
  }
148
149
  if (!globalKnowledge && !projectKnowledge) {
@@ -381,8 +382,8 @@ export function clearForensicsMarker(basePath) {
381
382
  try {
382
383
  unlinkSync(markerPath);
383
384
  }
384
- catch {
385
- // non-fatal
385
+ catch (e) {
386
+ logWarning("bootstrap", `unlinkSync forensics marker failed: ${e.message}`);
386
387
  }
387
388
  }
388
389
  }
@@ -14,7 +14,7 @@ import { gsdRoot } from "./paths.js";
14
14
  // ─── Constants ────────────────────────────────────────────────────────────────
15
15
  const CAPTURES_FILENAME = "CAPTURES.md";
16
16
  const VALID_CLASSIFICATIONS = [
17
- "quick-task", "inject", "defer", "replan", "note",
17
+ "quick-task", "inject", "defer", "replan", "note", "stop", "backtrack",
18
18
  ];
19
19
  // ─── Path Resolution ──────────────────────────────────────────────────────────
20
20
  /**
@@ -216,6 +216,59 @@ export function loadActionableCaptures(basePath, currentMilestoneId) {
216
216
  !c.resolvedInMilestone ||
217
217
  c.resolvedInMilestone === currentMilestoneId));
218
218
  }
219
+ /**
220
+ * Load unexecuted stop captures — user directives to halt auto-mode.
221
+ * These are checked in the pre-dispatch guard pipeline (runGuards) to
222
+ * pause auto-mode before the next unit is dispatched.
223
+ */
224
+ export function loadStopCaptures(basePath) {
225
+ return loadAllCaptures(basePath).filter(c => c.status === "resolved" && !c.executed &&
226
+ (c.classification === "stop" || c.classification === "backtrack"));
227
+ }
228
+ /**
229
+ * Load unexecuted backtrack captures specifically — captures directing
230
+ * auto-mode to abandon current milestone and return to a previous one.
231
+ */
232
+ export function loadBacktrackCaptures(basePath) {
233
+ return loadAllCaptures(basePath).filter(c => c.status === "resolved" && !c.executed && c.classification === "backtrack");
234
+ }
235
+ /**
236
+ * Revert captures that were silenced by non-triage agents.
237
+ *
238
+ * When an execute-task or other non-triage agent writes `**Status:** resolved`
239
+ * to CAPTURES.md, it bypasses the triage pipeline entirely. This function
240
+ * detects such captures (resolved but missing the Classification field that
241
+ * triage always writes) and reverts them to pending so the triage sidecar
242
+ * picks them up properly.
243
+ *
244
+ * Returns the number of captures reverted.
245
+ */
246
+ export function revertExecutorResolvedCaptures(basePath) {
247
+ const filePath = resolveCapturesPath(basePath);
248
+ if (!existsSync(filePath))
249
+ return 0;
250
+ let content = readFileSync(filePath, "utf-8");
251
+ let reverted = 0;
252
+ const all = loadAllCaptures(basePath);
253
+ for (const capture of all) {
254
+ // A properly triaged capture has both resolved status AND a classification.
255
+ // An executor-silenced capture has resolved status but NO classification.
256
+ if (capture.status === "resolved" && !capture.classification) {
257
+ const sectionRegex = new RegExp(`(### ${escapeRegex(capture.id)}\\n(?:(?!### ).)*?)(?=### |$)`, "s");
258
+ const match = sectionRegex.exec(content);
259
+ if (match) {
260
+ let section = match[1];
261
+ section = section.replace(/\*\*Status:\*\*\s*resolved/i, "**Status:** pending");
262
+ content = content.replace(sectionRegex, section);
263
+ reverted++;
264
+ }
265
+ }
266
+ }
267
+ if (reverted > 0) {
268
+ writeFileSync(filePath, content, "utf-8");
269
+ }
270
+ return reverted;
271
+ }
219
272
  /**
220
273
  * Retroactively stamp a capture with a milestone ID.
221
274
  *
@@ -216,8 +216,10 @@ const NESTED_COMPLETIONS = {
216
216
  codebase: [
217
217
  { cmd: "generate", desc: "Generate or regenerate CODEBASE.md" },
218
218
  { cmd: "generate --max-files", desc: "Generate with custom file limit (default: 500)" },
219
+ { cmd: "generate --collapse-threshold", desc: "Generate with custom collapse threshold (default: 20)" },
219
220
  { cmd: "update", desc: "Incremental update (preserves descriptions)" },
220
221
  { cmd: "update --max-files", desc: "Update with custom file limit" },
222
+ { cmd: "update --collapse-threshold", desc: "Update with custom collapse threshold" },
221
223
  { cmd: "stats", desc: "Show file count, description coverage, and generation time" },
222
224
  { cmd: "help", desc: "Show usage and available subcommands" },
223
225
  ],