gsd-pi 2.50.0 → 2.51.0-dev.7d435fe

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 (681) hide show
  1. package/README.md +6 -4
  2. package/dist/cli.js +26 -0
  3. package/dist/headless-events.d.ts +18 -0
  4. package/dist/headless-events.js +36 -0
  5. package/dist/headless-types.d.ts +28 -0
  6. package/dist/headless-types.js +7 -0
  7. package/dist/headless.d.ts +8 -3
  8. package/dist/headless.js +47 -16
  9. package/dist/help-text.js +16 -5
  10. package/dist/loader.js +4 -0
  11. package/dist/onboarding.js +5 -4
  12. package/dist/remote-questions-config.js +1 -1
  13. package/dist/resource-loader.d.ts +4 -1
  14. package/dist/resource-loader.js +138 -3
  15. package/dist/resources/extensions/async-jobs/async-bash-tool.js +32 -18
  16. package/dist/resources/extensions/bg-shell/interaction.js +3 -1
  17. package/dist/resources/extensions/bg-shell/process-manager.js +4 -1
  18. package/dist/resources/extensions/claude-code-cli/partial-builder.js +5 -0
  19. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +18 -19
  20. package/dist/resources/extensions/gsd/auto/phases.js +16 -1
  21. package/dist/resources/extensions/gsd/auto/session.js +5 -0
  22. package/dist/resources/extensions/gsd/auto-dashboard.js +22 -3
  23. package/dist/resources/extensions/gsd/auto-dispatch.js +98 -53
  24. package/dist/resources/extensions/gsd/auto-observability.js +54 -0
  25. package/dist/resources/extensions/gsd/auto-post-unit.js +37 -76
  26. package/dist/resources/extensions/gsd/auto-prompts.js +57 -0
  27. package/dist/resources/extensions/gsd/auto-recovery.js +21 -25
  28. package/dist/resources/extensions/gsd/auto-start.js +2 -0
  29. package/dist/resources/extensions/gsd/auto-timers.js +24 -2
  30. package/dist/resources/extensions/gsd/auto-tool-tracking.js +25 -7
  31. package/dist/resources/extensions/gsd/auto-utils.js +20 -0
  32. package/dist/resources/extensions/gsd/auto-worktree.js +21 -0
  33. package/dist/resources/extensions/gsd/auto.js +19 -7
  34. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +95 -69
  35. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +12 -2
  36. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -1
  37. package/dist/resources/extensions/gsd/claude-import.js +60 -9
  38. package/dist/resources/extensions/gsd/commands/handlers/auto.js +69 -6
  39. package/dist/resources/extensions/gsd/commands-config.js +10 -5
  40. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
  41. package/dist/resources/extensions/gsd/crash-recovery.js +6 -2
  42. package/dist/resources/extensions/gsd/custom-execution-policy.js +3 -2
  43. package/dist/resources/extensions/gsd/custom-verification.js +3 -1
  44. package/dist/resources/extensions/gsd/custom-workflow-engine.js +3 -2
  45. package/dist/resources/extensions/gsd/dashboard-overlay.js +4 -0
  46. package/dist/resources/extensions/gsd/detection.js +595 -9
  47. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -1
  48. package/dist/resources/extensions/gsd/docs/preferences-reference.md +18 -3
  49. package/dist/resources/extensions/gsd/error-classifier.js +105 -0
  50. package/dist/resources/extensions/gsd/files.js +5 -1
  51. package/dist/resources/extensions/gsd/gitignore.js +7 -7
  52. package/dist/resources/extensions/gsd/gsd-db.js +298 -45
  53. package/dist/resources/extensions/gsd/guided-flow.js +10 -0
  54. package/dist/resources/extensions/gsd/init-wizard.js +11 -3
  55. package/dist/resources/extensions/gsd/key-manager.js +7 -16
  56. package/dist/resources/extensions/gsd/memory-store.js +28 -13
  57. package/dist/resources/extensions/gsd/milestone-actions.js +19 -0
  58. package/dist/resources/extensions/gsd/model-router.js +25 -0
  59. package/dist/resources/extensions/gsd/notifications.js +23 -0
  60. package/dist/resources/extensions/gsd/observability-validator.js +422 -0
  61. package/dist/resources/extensions/gsd/preferences-models.js +1 -13
  62. package/dist/resources/extensions/gsd/preferences-skills.js +11 -5
  63. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  64. package/dist/resources/extensions/gsd/preferences-validation.js +25 -0
  65. package/dist/resources/extensions/gsd/preferences.js +16 -13
  66. package/dist/resources/extensions/gsd/prompts/forensics.md +11 -7
  67. package/dist/resources/extensions/gsd/prompts/system.md +1 -1
  68. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +6 -1
  69. package/dist/resources/extensions/gsd/provider-error-pause.js +0 -36
  70. package/dist/resources/extensions/gsd/roadmap-mutations.js +110 -0
  71. package/dist/resources/extensions/gsd/rtk-status.js +43 -0
  72. package/dist/resources/extensions/gsd/rule-registry.js +11 -12
  73. package/dist/resources/extensions/gsd/service-tier.js +13 -2
  74. package/dist/resources/extensions/gsd/session-forensics.js +7 -3
  75. package/dist/resources/extensions/gsd/skill-catalog.js +1026 -0
  76. package/dist/resources/extensions/gsd/skill-discovery.js +3 -2
  77. package/dist/resources/extensions/gsd/skill-health.js +2 -2
  78. package/dist/resources/extensions/gsd/skill-telemetry.js +15 -5
  79. package/dist/resources/extensions/gsd/state.js +38 -7
  80. package/dist/resources/extensions/gsd/templates/{preferences.md → PREFERENCES.md} +2 -0
  81. package/dist/resources/extensions/gsd/templates/milestone-validation.md +12 -0
  82. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +28 -9
  83. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -10
  84. package/dist/resources/extensions/gsd/tools/complete-slice.js +3 -17
  85. package/dist/resources/extensions/gsd/tools/complete-task.js +7 -18
  86. package/dist/resources/extensions/gsd/tools/plan-milestone.js +26 -17
  87. package/dist/resources/extensions/gsd/tools/plan-slice.js +25 -14
  88. package/dist/resources/extensions/gsd/tools/plan-task.js +21 -11
  89. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +47 -37
  90. package/dist/resources/extensions/gsd/tools/replan-slice.js +49 -38
  91. package/dist/resources/extensions/gsd/tools/validate-milestone.js +23 -16
  92. package/dist/resources/extensions/gsd/undo.js +8 -7
  93. package/dist/resources/extensions/gsd/unit-runtime.js +2 -1
  94. package/dist/resources/extensions/gsd/verification-gate.js +3 -1
  95. package/dist/resources/extensions/gsd/workflow-logger.js +0 -1
  96. package/dist/resources/extensions/remote-questions/config.js +1 -1
  97. package/dist/resources/extensions/remote-questions/remote-command.js +1 -1
  98. package/dist/resources/extensions/search-the-web/native-search.js +1 -1
  99. package/dist/resources/extensions/search-the-web/provider.js +1 -1
  100. package/dist/resources/extensions/shared/rtk-session-stats.js +189 -0
  101. package/dist/resources/extensions/shared/rtk.js +100 -0
  102. package/dist/rtk.d.ts +52 -0
  103. package/dist/rtk.js +332 -0
  104. package/dist/web/standalone/.next/BUILD_ID +1 -1
  105. package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -17
  106. package/dist/web/standalone/.next/build-manifest.json +4 -4
  107. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  108. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  109. package/dist/web/standalone/.next/required-server-files.json +3 -3
  110. package/dist/web/standalone/.next/routes-manifest.json +6 -0
  111. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  112. package/dist/web/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  115. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  123. package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  128. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  133. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  135. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  138. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  143. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  144. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  150. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js.nft.json +1 -1
  156. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  159. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/experimental/route.js +3 -0
  161. package/dist/web/standalone/.next/server/app/api/experimental/route.js.nft.json +1 -0
  162. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -0
  163. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  165. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  168. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  171. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  174. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  177. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  180. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  183. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  186. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  189. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  192. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/preferences/route.js.nft.json +1 -1
  195. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  198. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  201. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -26
  203. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js.nft.json +1 -1
  204. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  207. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  210. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  212. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  213. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  214. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  215. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  216. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  217. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  218. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  219. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  220. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  221. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  222. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  223. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  224. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  225. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  226. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  227. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  228. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  229. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  230. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  231. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  232. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  233. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js.nft.json +1 -1
  234. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  235. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  236. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js.nft.json +1 -1
  237. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  238. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  239. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  240. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  241. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  242. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  243. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  244. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  245. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js.nft.json +1 -1
  246. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  247. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  248. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  249. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  250. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  251. package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  252. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  253. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  254. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  255. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  256. package/dist/web/standalone/.next/server/app/index.html +1 -1
  257. package/dist/web/standalone/.next/server/app/index.rsc +5 -5
  258. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  259. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
  260. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  261. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  262. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  263. package/dist/web/standalone/.next/server/app/page.js +2 -2
  264. package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
  265. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  266. package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -17
  267. package/dist/web/standalone/.next/server/chunks/2229.js +12 -0
  268. package/dist/web/standalone/.next/server/chunks/2331.js +25 -0
  269. package/dist/web/standalone/.next/server/chunks/{741.js → 4741.js} +1 -1
  270. package/dist/web/standalone/.next/server/chunks/5822.js +2 -0
  271. package/dist/web/standalone/.next/server/chunks/7471.js +13 -0
  272. package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
  273. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  274. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  275. package/dist/web/standalone/.next/server/middleware.js +3 -3
  276. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  277. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  278. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  279. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  280. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  281. package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
  282. package/dist/web/standalone/.next/static/RqOU-jOv9uZ1Q03P6L6nn/_buildManifest.js +1 -0
  283. package/dist/web/standalone/.next/static/chunks/{485.243af25f0cdf50d6.js → 2008.817d0885545aaea9.js} +6 -6
  284. package/dist/web/standalone/.next/static/chunks/4024.21054f459af5cc78.js +9 -0
  285. package/dist/web/standalone/.next/static/chunks/app/_global-error/page-c4cc189e7b117ea2.js +1 -0
  286. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  287. package/dist/web/standalone/.next/static/chunks/app/api/boot/route-c4cc189e7b117ea2.js +1 -0
  288. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-c4cc189e7b117ea2.js +1 -0
  289. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-c4cc189e7b117ea2.js +1 -0
  290. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-c4cc189e7b117ea2.js +1 -0
  291. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-c4cc189e7b117ea2.js +1 -0
  292. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-c4cc189e7b117ea2.js +1 -0
  293. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-c4cc189e7b117ea2.js +1 -0
  294. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-c4cc189e7b117ea2.js +1 -0
  295. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-c4cc189e7b117ea2.js +1 -0
  296. package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-c4cc189e7b117ea2.js +1 -0
  297. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-c4cc189e7b117ea2.js +1 -0
  298. package/dist/web/standalone/.next/static/chunks/app/api/files/route-c4cc189e7b117ea2.js +1 -0
  299. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-c4cc189e7b117ea2.js +1 -0
  300. package/dist/web/standalone/.next/static/chunks/app/api/git/route-c4cc189e7b117ea2.js +1 -0
  301. package/dist/web/standalone/.next/static/chunks/app/api/history/route-c4cc189e7b117ea2.js +1 -0
  302. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-c4cc189e7b117ea2.js +1 -0
  303. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-c4cc189e7b117ea2.js +1 -0
  304. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-c4cc189e7b117ea2.js +1 -0
  305. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-c4cc189e7b117ea2.js +1 -0
  306. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-c4cc189e7b117ea2.js +1 -0
  307. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-c4cc189e7b117ea2.js +1 -0
  308. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-c4cc189e7b117ea2.js +1 -0
  309. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-c4cc189e7b117ea2.js +1 -0
  310. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-c4cc189e7b117ea2.js +1 -0
  311. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-c4cc189e7b117ea2.js +1 -0
  312. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-c4cc189e7b117ea2.js +1 -0
  313. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-c4cc189e7b117ea2.js +1 -0
  314. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-c4cc189e7b117ea2.js +1 -0
  315. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-c4cc189e7b117ea2.js +1 -0
  316. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-c4cc189e7b117ea2.js +1 -0
  317. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-c4cc189e7b117ea2.js +1 -0
  318. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-c4cc189e7b117ea2.js +1 -0
  319. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-c4cc189e7b117ea2.js +1 -0
  320. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-c4cc189e7b117ea2.js +1 -0
  321. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-c4cc189e7b117ea2.js +1 -0
  322. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-c4cc189e7b117ea2.js +1 -0
  323. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-c4cc189e7b117ea2.js +1 -0
  324. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-c4cc189e7b117ea2.js +1 -0
  325. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-c4cc189e7b117ea2.js +1 -0
  326. package/dist/web/standalone/.next/static/chunks/app/api/update/route-c4cc189e7b117ea2.js +1 -0
  327. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-c4cc189e7b117ea2.js +1 -0
  328. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  329. package/dist/web/standalone/.next/static/chunks/app/page-b950e4e384cc62b3.js +1 -0
  330. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  331. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-c4cc189e7b117ea2.js +1 -0
  332. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-c4cc189e7b117ea2.js +1 -0
  333. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  334. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-c4cc189e7b117ea2.js +1 -0
  335. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-c4cc189e7b117ea2.js +1 -0
  336. package/dist/web/standalone/.next/static/chunks/webpack-024d82be84800e52.js +1 -0
  337. package/dist/web/standalone/.next/static/css/a58ef8a151aa0493.css +1 -0
  338. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  339. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  340. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  341. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  342. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  343. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  344. package/dist/web/standalone/server.js +1 -1
  345. package/dist/wizard.js +4 -1
  346. package/package.json +2 -2
  347. package/packages/pi-ai/dist/models.d.ts +14 -3
  348. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  349. package/packages/pi-ai/dist/models.js +53 -10
  350. package/packages/pi-ai/dist/models.js.map +1 -1
  351. package/packages/pi-ai/dist/models.test.js +102 -1
  352. package/packages/pi-ai/dist/models.test.js.map +1 -1
  353. package/packages/pi-ai/dist/types.d.ts +31 -0
  354. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  355. package/packages/pi-ai/dist/types.js.map +1 -1
  356. package/packages/pi-ai/src/models.test.ts +114 -1
  357. package/packages/pi-ai/src/models.ts +70 -13
  358. package/packages/pi-ai/src/types.ts +32 -1
  359. package/packages/pi-coding-agent/dist/cli/args.d.ts +2 -0
  360. package/packages/pi-coding-agent/dist/cli/args.d.ts.map +1 -1
  361. package/packages/pi-coding-agent/dist/cli/args.js +3 -0
  362. package/packages/pi-coding-agent/dist/cli/args.js.map +1 -1
  363. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +1 -0
  364. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  365. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -0
  366. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  367. package/packages/pi-coding-agent/dist/core/bash-executor.d.ts +3 -1
  368. package/packages/pi-coding-agent/dist/core/bash-executor.d.ts.map +1 -1
  369. package/packages/pi-coding-agent/dist/core/bash-executor.js +15 -2
  370. package/packages/pi-coding-agent/dist/core/bash-executor.js.map +1 -1
  371. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  372. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  373. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  374. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +1 -0
  375. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  376. package/packages/pi-coding-agent/dist/core/extensions/runner.js +13 -0
  377. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  378. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +19 -1
  379. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  380. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  381. package/packages/pi-coding-agent/dist/core/extensions/wrapper.d.ts.map +1 -1
  382. package/packages/pi-coding-agent/dist/core/extensions/wrapper.js +8 -0
  383. package/packages/pi-coding-agent/dist/core/extensions/wrapper.js.map +1 -1
  384. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  385. package/packages/pi-coding-agent/dist/core/model-registry.js +9 -4
  386. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  387. package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  388. package/packages/pi-coding-agent/dist/core/package-manager.js +8 -1
  389. package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  390. package/packages/pi-coding-agent/dist/core/skills.d.ts +11 -1
  391. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  392. package/packages/pi-coding-agent/dist/core/skills.js +30 -8
  393. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  394. package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
  395. package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
  396. package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
  397. package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.d.ts +19 -0
  398. package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.d.ts.map +1 -0
  399. package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js +83 -0
  400. package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js.map +1 -0
  401. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  402. package/packages/pi-coding-agent/dist/core/tools/bash.js +5 -1
  403. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  404. package/packages/pi-coding-agent/dist/index.d.ts +3 -3
  405. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  406. package/packages/pi-coding-agent/dist/index.js +1 -1
  407. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  408. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  409. package/packages/pi-coding-agent/dist/main.js +5 -3
  410. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  411. package/packages/pi-coding-agent/dist/modes/index.d.ts +1 -1
  412. package/packages/pi-coding-agent/dist/modes/index.d.ts.map +1 -1
  413. package/packages/pi-coding-agent/dist/modes/index.js.map +1 -1
  414. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  415. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +3 -2
  416. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  417. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  418. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +0 -2
  419. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  420. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  421. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +6 -4
  422. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  423. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts +5 -0
  424. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
  425. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +12 -0
  426. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  427. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  428. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +2 -1
  429. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  430. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts +28 -1
  431. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  432. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js +49 -0
  433. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js.map +1 -1
  434. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts +1 -1
  435. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  436. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +114 -6
  437. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  438. package/packages/pi-coding-agent/dist/modes/rpc/rpc-protocol-v2.test.d.ts +9 -0
  439. package/packages/pi-coding-agent/dist/modes/rpc/rpc-protocol-v2.test.d.ts.map +1 -0
  440. package/packages/pi-coding-agent/dist/modes/rpc/rpc-protocol-v2.test.js +831 -0
  441. package/packages/pi-coding-agent/dist/modes/rpc/rpc-protocol-v2.test.js.map +1 -0
  442. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts +66 -0
  443. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  444. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.js.map +1 -1
  445. package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
  446. package/packages/pi-coding-agent/dist/utils/shell.js +0 -1
  447. package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
  448. package/packages/pi-coding-agent/package.json +1 -1
  449. package/packages/pi-coding-agent/src/cli/args.ts +4 -0
  450. package/packages/pi-coding-agent/src/core/agent-session.ts +2 -1
  451. package/packages/pi-coding-agent/src/core/bash-executor.ts +15 -3
  452. package/packages/pi-coding-agent/src/core/extensions/index.ts +2 -0
  453. package/packages/pi-coding-agent/src/core/extensions/runner.ts +18 -0
  454. package/packages/pi-coding-agent/src/core/extensions/types.ts +21 -0
  455. package/packages/pi-coding-agent/src/core/extensions/wrapper.ts +9 -0
  456. package/packages/pi-coding-agent/src/core/model-registry.ts +10 -3
  457. package/packages/pi-coding-agent/src/core/package-manager.ts +10 -1
  458. package/packages/pi-coding-agent/src/core/skills.ts +35 -10
  459. package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
  460. package/packages/pi-coding-agent/src/core/tools/bash-spawn-windows.test.ts +101 -0
  461. package/packages/pi-coding-agent/src/core/tools/bash.ts +5 -1
  462. package/packages/pi-coding-agent/src/index.ts +7 -0
  463. package/packages/pi-coding-agent/src/main.ts +5 -3
  464. package/packages/pi-coding-agent/src/modes/index.ts +8 -1
  465. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +3 -2
  466. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +0 -2
  467. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +6 -4
  468. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +15 -0
  469. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +2 -1
  470. package/packages/pi-coding-agent/src/modes/rpc/rpc-client.ts +54 -1
  471. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +124 -6
  472. package/packages/pi-coding-agent/src/modes/rpc/rpc-protocol-v2.test.ts +971 -0
  473. package/packages/pi-coding-agent/src/modes/rpc/rpc-types.ts +61 -4
  474. package/packages/pi-coding-agent/src/utils/shell.ts +0 -1
  475. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  476. package/pkg/dist/modes/interactive/theme/themes.js +2 -1
  477. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  478. package/pkg/package.json +1 -1
  479. package/scripts/postinstall.js +163 -6
  480. package/src/resources/extensions/async-jobs/async-bash-tool.ts +25 -12
  481. package/src/resources/extensions/bg-shell/interaction.ts +3 -1
  482. package/src/resources/extensions/bg-shell/process-manager.ts +4 -1
  483. package/src/resources/extensions/claude-code-cli/partial-builder.ts +5 -0
  484. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +19 -20
  485. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +105 -0
  486. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +21 -0
  487. package/src/resources/extensions/gsd/auto/phases.ts +15 -1
  488. package/src/resources/extensions/gsd/auto/session.ts +6 -0
  489. package/src/resources/extensions/gsd/auto-dashboard.ts +31 -3
  490. package/src/resources/extensions/gsd/auto-dispatch.ts +102 -50
  491. package/src/resources/extensions/gsd/auto-observability.ts +72 -0
  492. package/src/resources/extensions/gsd/auto-post-unit.ts +56 -83
  493. package/src/resources/extensions/gsd/auto-prompts.ts +48 -0
  494. package/src/resources/extensions/gsd/auto-recovery.ts +19 -26
  495. package/src/resources/extensions/gsd/auto-start.ts +2 -0
  496. package/src/resources/extensions/gsd/auto-timers.ts +25 -1
  497. package/src/resources/extensions/gsd/auto-tool-tracking.ts +30 -6
  498. package/src/resources/extensions/gsd/auto-utils.ts +25 -0
  499. package/src/resources/extensions/gsd/auto-worktree.ts +21 -0
  500. package/src/resources/extensions/gsd/auto.ts +20 -7
  501. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +115 -72
  502. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +11 -2
  503. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +18 -1
  504. package/src/resources/extensions/gsd/claude-import.ts +58 -9
  505. package/src/resources/extensions/gsd/commands/handlers/auto.ts +73 -6
  506. package/src/resources/extensions/gsd/commands-config.ts +11 -5
  507. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
  508. package/src/resources/extensions/gsd/crash-recovery.ts +6 -2
  509. package/src/resources/extensions/gsd/custom-execution-policy.ts +3 -2
  510. package/src/resources/extensions/gsd/custom-verification.ts +3 -1
  511. package/src/resources/extensions/gsd/custom-workflow-engine.ts +3 -2
  512. package/src/resources/extensions/gsd/dashboard-overlay.ts +7 -0
  513. package/src/resources/extensions/gsd/detection.ts +668 -9
  514. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -1
  515. package/src/resources/extensions/gsd/docs/preferences-reference.md +18 -3
  516. package/src/resources/extensions/gsd/error-classifier.ts +139 -0
  517. package/src/resources/extensions/gsd/files.ts +6 -1
  518. package/src/resources/extensions/gsd/gitignore.ts +7 -7
  519. package/src/resources/extensions/gsd/gsd-db.ts +355 -63
  520. package/src/resources/extensions/gsd/guided-flow.ts +11 -0
  521. package/src/resources/extensions/gsd/init-wizard.ts +11 -3
  522. package/src/resources/extensions/gsd/key-manager.ts +7 -16
  523. package/src/resources/extensions/gsd/memory-store.ts +29 -18
  524. package/src/resources/extensions/gsd/milestone-actions.ts +17 -0
  525. package/src/resources/extensions/gsd/model-router.ts +25 -0
  526. package/src/resources/extensions/gsd/notifications.ts +23 -0
  527. package/src/resources/extensions/gsd/observability-validator.ts +456 -0
  528. package/src/resources/extensions/gsd/preferences-models.ts +1 -13
  529. package/src/resources/extensions/gsd/preferences-skills.ts +11 -5
  530. package/src/resources/extensions/gsd/preferences-types.ts +20 -0
  531. package/src/resources/extensions/gsd/preferences-validation.ts +26 -0
  532. package/src/resources/extensions/gsd/preferences.ts +15 -13
  533. package/src/resources/extensions/gsd/prompts/forensics.md +11 -7
  534. package/src/resources/extensions/gsd/prompts/system.md +1 -1
  535. package/src/resources/extensions/gsd/prompts/validate-milestone.md +6 -1
  536. package/src/resources/extensions/gsd/provider-error-pause.ts +0 -48
  537. package/src/resources/extensions/gsd/roadmap-mutations.ts +134 -0
  538. package/src/resources/extensions/gsd/rtk-status.ts +53 -0
  539. package/src/resources/extensions/gsd/rule-registry.ts +11 -12
  540. package/src/resources/extensions/gsd/service-tier.ts +14 -2
  541. package/src/resources/extensions/gsd/session-forensics.ts +7 -3
  542. package/src/resources/extensions/gsd/skill-catalog.ts +1085 -0
  543. package/src/resources/extensions/gsd/skill-discovery.ts +3 -2
  544. package/src/resources/extensions/gsd/skill-health.ts +2 -2
  545. package/src/resources/extensions/gsd/skill-telemetry.ts +15 -5
  546. package/src/resources/extensions/gsd/state.ts +38 -7
  547. package/src/resources/extensions/gsd/templates/{preferences.md → PREFERENCES.md} +2 -0
  548. package/src/resources/extensions/gsd/templates/milestone-validation.md +12 -0
  549. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +16 -0
  550. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +2 -2
  551. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +68 -0
  552. package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +61 -0
  553. package/src/resources/extensions/gsd/tests/claude-import-marketplace-discovery.test.ts +191 -0
  554. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +1 -1
  555. package/src/resources/extensions/gsd/tests/commands-config.test.ts +24 -0
  556. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +2 -2
  557. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  558. package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +106 -0
  559. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  560. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +5 -3
  561. package/src/resources/extensions/gsd/tests/custom-verification.test.ts +33 -0
  562. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +39 -10
  563. package/src/resources/extensions/gsd/tests/detection.test.ts +839 -1
  564. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +28 -9
  565. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +4 -4
  566. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +1 -1
  567. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +2 -2
  568. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +97 -0
  569. package/src/resources/extensions/gsd/tests/empty-db-reconciliation.test.ts +79 -0
  570. package/src/resources/extensions/gsd/tests/git-service.test.ts +1 -1
  571. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
  572. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +63 -0
  573. package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +125 -0
  574. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +1 -1
  575. package/src/resources/extensions/gsd/tests/interactive-tool-idle-exemption.test.ts +119 -0
  576. package/src/resources/extensions/gsd/tests/key-manager.test.ts +16 -1
  577. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  578. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  579. package/src/resources/extensions/gsd/tests/model-router.test.ts +40 -0
  580. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +7 -7
  581. package/src/resources/extensions/gsd/tests/notifications.test.ts +28 -6
  582. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +85 -0
  583. package/src/resources/extensions/gsd/tests/plan-quality-validator.test.ts +474 -0
  584. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +91 -0
  585. package/src/resources/extensions/gsd/tests/preferences.test.ts +51 -1
  586. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +77 -70
  587. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +40 -0
  588. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +6 -6
  589. package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +110 -0
  590. package/src/resources/extensions/gsd/tests/remote-questions.test.ts +29 -0
  591. package/src/resources/extensions/gsd/tests/retry-diagnostic-reasoning.test.ts +161 -0
  592. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +4 -5
  593. package/src/resources/extensions/gsd/tests/rewrite-count-persist.test.ts +82 -0
  594. package/src/resources/extensions/gsd/tests/run-uat.test.ts +146 -0
  595. package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +12 -12
  596. package/src/resources/extensions/gsd/tests/skill-catalog.test.ts +193 -0
  597. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +56 -21
  598. package/src/resources/extensions/gsd/tests/token-cost-display.test.ts +2 -2
  599. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +2 -2
  600. package/src/resources/extensions/gsd/tests/vacuous-truth-slices.test.ts +115 -0
  601. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +90 -0
  602. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +81 -1
  603. package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +130 -0
  604. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -14
  605. package/src/resources/extensions/gsd/tools/complete-slice.ts +3 -21
  606. package/src/resources/extensions/gsd/tools/complete-task.ts +9 -22
  607. package/src/resources/extensions/gsd/tools/plan-milestone.ts +28 -18
  608. package/src/resources/extensions/gsd/tools/plan-slice.ts +28 -16
  609. package/src/resources/extensions/gsd/tools/plan-task.ts +24 -12
  610. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +54 -42
  611. package/src/resources/extensions/gsd/tools/replan-slice.ts +53 -40
  612. package/src/resources/extensions/gsd/tools/validate-milestone.ts +26 -20
  613. package/src/resources/extensions/gsd/types.ts +2 -0
  614. package/src/resources/extensions/gsd/undo.ts +8 -7
  615. package/src/resources/extensions/gsd/unit-runtime.ts +2 -1
  616. package/src/resources/extensions/gsd/verification-gate.ts +3 -1
  617. package/src/resources/extensions/gsd/workflow-logger.ts +0 -1
  618. package/src/resources/extensions/remote-questions/config.ts +1 -1
  619. package/src/resources/extensions/remote-questions/remote-command.ts +1 -1
  620. package/src/resources/extensions/search-the-web/native-search.ts +1 -1
  621. package/src/resources/extensions/search-the-web/provider.ts +1 -1
  622. package/src/resources/extensions/shared/rtk-session-stats.ts +249 -0
  623. package/src/resources/extensions/shared/rtk.ts +120 -0
  624. package/dist/web/standalone/.next/server/chunks/229.js +0 -12
  625. package/dist/web/standalone/.next/server/chunks/441.js +0 -2
  626. package/dist/web/standalone/.next/server/chunks/471.js +0 -13
  627. package/dist/web/standalone/.next/static/MQOhBnkC_TLtNn_JvZWDj/_buildManifest.js +0 -1
  628. package/dist/web/standalone/.next/static/chunks/4024.7c75ac378de0f2b5.js +0 -9
  629. package/dist/web/standalone/.next/static/chunks/app/_global-error/page-d83ba70a25a85472.js +0 -1
  630. package/dist/web/standalone/.next/static/chunks/app/api/boot/route-d83ba70a25a85472.js +0 -1
  631. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-d83ba70a25a85472.js +0 -1
  632. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-d83ba70a25a85472.js +0 -1
  633. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-d83ba70a25a85472.js +0 -1
  634. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-d83ba70a25a85472.js +0 -1
  635. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-d83ba70a25a85472.js +0 -1
  636. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-d83ba70a25a85472.js +0 -1
  637. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-d83ba70a25a85472.js +0 -1
  638. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-d83ba70a25a85472.js +0 -1
  639. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-d83ba70a25a85472.js +0 -1
  640. package/dist/web/standalone/.next/static/chunks/app/api/files/route-d83ba70a25a85472.js +0 -1
  641. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-d83ba70a25a85472.js +0 -1
  642. package/dist/web/standalone/.next/static/chunks/app/api/git/route-d83ba70a25a85472.js +0 -1
  643. package/dist/web/standalone/.next/static/chunks/app/api/history/route-d83ba70a25a85472.js +0 -1
  644. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-d83ba70a25a85472.js +0 -1
  645. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-d83ba70a25a85472.js +0 -1
  646. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-d83ba70a25a85472.js +0 -1
  647. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-d83ba70a25a85472.js +0 -1
  648. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-d83ba70a25a85472.js +0 -1
  649. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-d83ba70a25a85472.js +0 -1
  650. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-d83ba70a25a85472.js +0 -1
  651. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-d83ba70a25a85472.js +0 -1
  652. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-d83ba70a25a85472.js +0 -1
  653. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-d83ba70a25a85472.js +0 -1
  654. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-d83ba70a25a85472.js +0 -1
  655. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-d83ba70a25a85472.js +0 -1
  656. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-d83ba70a25a85472.js +0 -1
  657. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-d83ba70a25a85472.js +0 -1
  658. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-d83ba70a25a85472.js +0 -1
  659. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-d83ba70a25a85472.js +0 -1
  660. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-d83ba70a25a85472.js +0 -1
  661. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-d83ba70a25a85472.js +0 -1
  662. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-d83ba70a25a85472.js +0 -1
  663. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-d83ba70a25a85472.js +0 -1
  664. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-d83ba70a25a85472.js +0 -1
  665. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-d83ba70a25a85472.js +0 -1
  666. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-d83ba70a25a85472.js +0 -1
  667. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-d83ba70a25a85472.js +0 -1
  668. package/dist/web/standalone/.next/static/chunks/app/api/update/route-d83ba70a25a85472.js +0 -1
  669. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-d83ba70a25a85472.js +0 -1
  670. package/dist/web/standalone/.next/static/chunks/app/page-12dd5ece0df4badc.js +0 -1
  671. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  672. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-d83ba70a25a85472.js +0 -1
  673. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-d83ba70a25a85472.js +0 -1
  674. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  675. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-d83ba70a25a85472.js +0 -1
  676. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d83ba70a25a85472.js +0 -1
  677. package/dist/web/standalone/.next/static/chunks/webpack-2473ce2c3879fff4.js +0 -1
  678. package/dist/web/standalone/.next/static/css/dd4ae3f58ac9b600.css +0 -1
  679. package/packages/pi-ai/pnpm-lock.yaml +0 -2022
  680. package/packages/pi-coding-agent/pnpm-lock.yaml +0 -454
  681. /package/dist/web/standalone/.next/static/{MQOhBnkC_TLtNn_JvZWDj → RqOU-jOv9uZ1Q03P6L6nn}/_ssgManifest.js +0 -0
@@ -9,8 +9,9 @@
9
9
  */
10
10
  import { existsSync, readdirSync, readFileSync } from "node:fs";
11
11
  import { join } from "node:path";
12
- import { getAgentDir } from "@gsd/pi-coding-agent";
13
- const SKILLS_DIR = join(getAgentDir(), "skills");
12
+ import { homedir } from "node:os";
13
+ /** Industry-standard skills.sh global skills directory */
14
+ const SKILLS_DIR = join(homedir(), ".agents", "skills");
14
15
  /** Snapshot of skill names at auto-mode start */
15
16
  let baselineSkills = null;
16
17
  /**
@@ -14,7 +14,7 @@
14
14
  */
15
15
  import { existsSync } from "node:fs";
16
16
  import { join } from "node:path";
17
- import { getAgentDir } from "@gsd/pi-coding-agent";
17
+ import { homedir } from "node:os";
18
18
  import { formatCost, formatTokenCount, loadLedgerFromDisk } from "./metrics.js";
19
19
  import { detectStaleSkills } from "./skill-telemetry.js";
20
20
  // ─── Constants ────────────────────────────────────────────────────────────────
@@ -141,7 +141,7 @@ export function formatSkillDetail(basePath, skillName) {
141
141
  lines.push(` ${date} ${u.id.padEnd(20)} ${formatTokenCount(u.tokens.total).padStart(8)} tokens ${formatCost(u.cost)}`);
142
142
  }
143
143
  // Check for SKILL.md existence
144
- const skillPath = join(getAgentDir(), "skills", skillName, "SKILL.md");
144
+ const skillPath = join(homedir(), ".agents", "skills", skillName, "SKILL.md");
145
145
  if (existsSync(skillPath)) {
146
146
  const stat = require("node:fs").statSync(skillPath);
147
147
  lines.push("");
@@ -12,7 +12,7 @@
12
12
  */
13
13
  import { existsSync, readdirSync } from "node:fs";
14
14
  import { join } from "node:path";
15
- import { getAgentDir } from "@gsd/pi-coding-agent";
15
+ import { homedir } from "node:os";
16
16
  // ─── In-memory state ──────────────────────────────────────────────────────────
17
17
  /** Skills available in the system prompt for the current unit */
18
18
  let availableSkills = [];
@@ -24,8 +24,14 @@ const activelyLoadedSkills = new Set();
24
24
  * Called before each unit starts.
25
25
  */
26
26
  export function captureAvailableSkills() {
27
- const skillsDir = join(getAgentDir(), "skills");
28
- availableSkills = listSkillNames(skillsDir);
27
+ const skillsDir = join(homedir(), ".agents", "skills");
28
+ const legacyDir = join(homedir(), ".gsd", "agent", "skills");
29
+ const names = listSkillNames(skillsDir);
30
+ // Include skills still in the legacy directory only if migration hasn't completed
31
+ const legacyMigrated = existsSync(join(legacyDir, ".migrated-to-agents"));
32
+ const legacyNames = legacyMigrated ? [] : listSkillNames(legacyDir);
33
+ const all = new Set([...names, ...legacyNames]);
34
+ availableSkills = [...all];
29
35
  activelyLoadedSkills.clear();
30
36
  }
31
37
  /**
@@ -85,8 +91,12 @@ export function detectStaleSkills(units, thresholdDays) {
85
91
  const cutoff = Date.now() - (thresholdDays * 24 * 60 * 60 * 1000);
86
92
  const stale = [];
87
93
  // Check all installed skills, not just those with usage data
88
- const skillsDir = join(getAgentDir(), "skills");
89
- const installed = listSkillNames(skillsDir);
94
+ const skillsDir = join(homedir(), ".agents", "skills");
95
+ const legacyDir = join(homedir(), ".gsd", "agent", "skills");
96
+ const legacyMigrated = existsSync(join(legacyDir, ".migrated-to-agents"));
97
+ const legacyNames = legacyMigrated ? [] : listSkillNames(legacyDir);
98
+ const installedSet = new Set([...listSkillNames(skillsDir), ...legacyNames]);
99
+ const installed = [...installedSet];
90
100
  for (const skill of installed) {
91
101
  const lastTs = lastUsed.get(skill);
92
102
  if (lastTs === undefined || lastTs < cutoff) {
@@ -4,7 +4,8 @@
4
4
  import { parseRoadmap, parsePlan, } from './parsers-legacy.js';
5
5
  import { parseSummary, loadFile, parseRequirementCounts, parseContextDependsOn, } from './files.js';
6
6
  import { resolveMilestoneFile, resolveSlicePath, resolveSliceFile, resolveTaskFile, resolveTasksDir, resolveGsdRootFile, gsdRoot, } from './paths.js';
7
- import { milestoneIdSort, findMilestoneIds } from './milestone-ids.js';
7
+ import { findMilestoneIds } from './milestone-ids.js';
8
+ import { loadQueueOrder, sortByQueueOrder } from './queue-order.js';
8
9
  import { nativeBatchParseGsdFiles } from './native-parser-bridge.js';
9
10
  import { join, resolve } from 'path';
10
11
  import { existsSync, readdirSync } from 'node:fs';
@@ -84,8 +85,14 @@ export async function getActiveMilestoneId(basePath) {
84
85
  if (isDbAvailable()) {
85
86
  const allMilestones = getAllMilestones();
86
87
  if (allMilestones.length > 0) {
87
- const sorted = [...allMilestones].sort((a, b) => a.id.localeCompare(b.id));
88
- for (const m of sorted) {
88
+ // Respect queue-order.json so /gsd queue reordering is honored (#2556).
89
+ // Without this, the DB path uses lexicographic sort while the dispatch
90
+ // guard uses queue order — causing a deadlock.
91
+ const customOrder = loadQueueOrder(basePath);
92
+ const sortedIds = sortByQueueOrder(allMilestones.map(m => m.id), customOrder);
93
+ const byId = new Map(allMilestones.map(m => [m.id, m]));
94
+ for (const id of sortedIds) {
95
+ const m = byId.get(id);
89
96
  if (m.status === "complete" || m.status === "done" || m.status === "parked")
90
97
  continue;
91
98
  return m.id;
@@ -137,7 +144,23 @@ export async function deriveState(basePath) {
137
144
  let result;
138
145
  // Dual-path: try DB-backed derivation first when hierarchy tables are populated
139
146
  if (isDbAvailable()) {
140
- const dbMilestones = getAllMilestones();
147
+ let dbMilestones = getAllMilestones();
148
+ // Disk→DB reconciliation (#2631): when the milestones table is empty
149
+ // (e.g. failed initial migration per #2529), the reconciliation code
150
+ // inside deriveStateFromDb is unreachable. Populate from disk here so
151
+ // the DB path activates correctly.
152
+ if (dbMilestones.length === 0) {
153
+ const diskIds = findMilestoneIds(basePath);
154
+ let synced = false;
155
+ for (const diskId of diskIds) {
156
+ if (!isGhostMilestone(basePath, diskId)) {
157
+ insertMilestone({ id: diskId, status: 'active' });
158
+ synced = true;
159
+ }
160
+ }
161
+ if (synced)
162
+ dbMilestones = getAllMilestones();
163
+ }
141
164
  if (dbMilestones.length > 0) {
142
165
  const stopDbTimer = debugTime("derive-state-db");
143
166
  result = await deriveStateFromDb(basePath);
@@ -233,8 +256,13 @@ export async function deriveStateFromDb(basePath) {
233
256
  });
234
257
  }
235
258
  }
236
- // Re-sort so milestones are in canonical order after injection
237
- allMilestones.sort((a, b) => milestoneIdSort(a.id, b.id));
259
+ // Re-sort so milestones follow queue order (same as dispatch guard) (#2556)
260
+ const customOrder = loadQueueOrder(basePath);
261
+ const sortedIds = sortByQueueOrder(allMilestones.map(m => m.id), customOrder);
262
+ const byId = new Map(allMilestones.map(m => [m.id, m]));
263
+ allMilestones.length = 0;
264
+ for (const id of sortedIds)
265
+ allMilestones.push(byId.get(id));
238
266
  // Parallel worker isolation: when locked, filter to just the locked milestone
239
267
  const milestoneLock = process.env.GSD_MILESTONE_LOCK;
240
268
  const milestones = milestoneLock
@@ -453,7 +481,10 @@ export async function deriveStateFromDb(basePath) {
453
481
  };
454
482
  }
455
483
  // ── All slices done → validating/completing ─────────────────────────
456
- const allSlicesDone = activeMilestoneSlices.every(s => isStatusDone(s.status));
484
+ // Guard: [].every() === true (vacuous truth). Without the length check,
485
+ // an empty slice array causes a premature phase transition to
486
+ // validating-milestone. See: https://github.com/gsd-build/gsd-2/issues/2667
487
+ const allSlicesDone = activeMilestoneSlices.length > 0 && activeMilestoneSlices.every(s => isStatusDone(s.status));
457
488
  if (allSlicesDone) {
458
489
  const validationFile = resolveMilestoneFile(basePath, activeMilestone.id, "VALIDATION");
459
490
  const validationContent = validationFile ? await loadFile(validationFile) : null;
@@ -71,6 +71,8 @@ remote_questions:
71
71
  uat_dispatch:
72
72
  post_unit_hooks: []
73
73
  pre_dispatch_hooks: []
74
+ # experimental:
75
+ # rtk: false
74
76
  ---
75
77
 
76
78
  # GSD Skill Preferences
@@ -35,6 +35,18 @@ validated_at: {{date}}
35
35
 
36
36
  - **{{requirementId}}**: {{status}} — {{disposition: covered by remediation slice / acceptable gap / needs attention}}
37
37
 
38
+ ## Verification Class Compliance
39
+
40
+ <!-- If verification classes were defined during planning, document whether each
41
+ was addressed. Use N/A for classes that were empty or "none" in planning. -->
42
+
43
+ | Class | Planned | Evidence | Status |
44
+ |-------|---------|----------|--------|
45
+ | Contract | {{planned_or_none}} | {{evidence_or_none}} | {{MET / NOT MET / N/A}} |
46
+ | Integration | {{planned_or_none}} | {{evidence_or_none}} | {{MET / NOT MET / N/A}} |
47
+ | Operational | {{planned_or_none}} | {{evidence_or_none}} | {{MET / NOT MET / N/A}} |
48
+ | UAT | {{planned_or_none}} | {{evidence_or_none}} | {{MET / NOT MET / N/A}} |
49
+
38
50
  ## Remediation Slices
39
51
 
40
52
  <!-- New slices appended to the roadmap to address auto-remediable gaps.
@@ -7,17 +7,28 @@ const require = createRequire(import.meta.url);
7
7
  const ROOT = new URL("../../../../../", import.meta.url);
8
8
 
9
9
  export function resolve(specifier, context, nextResolve) {
10
- // 1. Direct redirects to dist/ for specific packages
10
+ // 1. Redirect all workspace package bare imports to source.
11
+ // CI portability runs don't build any packages/ dist artifacts, so every
12
+ // @gsd/* specifier (including transitive ones pulled in by pi-coding-agent
13
+ // source itself) must resolve to the TypeScript source entrypoint.
11
14
  if (specifier === "../../packages/pi-coding-agent/src/index.js") {
12
- specifier = new URL("packages/pi-coding-agent/dist/index.js", ROOT).href;
15
+ specifier = new URL("packages/pi-coding-agent/src/index.ts", ROOT).href;
16
+ } else if (specifier === "@gsd/pi-coding-agent") {
17
+ specifier = new URL("packages/pi-coding-agent/src/index.ts", ROOT).href;
13
18
  } else if (specifier === "@gsd/pi-ai/oauth") {
14
- specifier = new URL("packages/pi-ai/dist/utils/oauth/index.js", ROOT).href;
19
+ specifier = new URL("packages/pi-ai/src/utils/oauth/index.ts", ROOT).href;
15
20
  } else if (specifier === "@gsd/pi-ai") {
16
- specifier = new URL("packages/pi-ai/dist/index.js", ROOT).href;
21
+ specifier = new URL("packages/pi-ai/src/index.ts", ROOT).href;
17
22
  } else if (specifier === "@gsd/pi-agent-core") {
18
- specifier = new URL("packages/pi-agent-core/dist/index.js", ROOT).href;
23
+ specifier = new URL("packages/pi-agent-core/src/index.ts", ROOT).href;
19
24
  } else if (specifier === "@gsd/pi-tui") {
20
- specifier = new URL("packages/pi-tui/dist/index.js", ROOT).href;
25
+ specifier = new URL("packages/pi-tui/src/index.ts", ROOT).href;
26
+ } else if (specifier === "@gsd/native") {
27
+ specifier = new URL("packages/native/src/index.ts", ROOT).href;
28
+ } else if (specifier.startsWith("@gsd/native/")) {
29
+ // Sub-path imports like @gsd/native/fd, @gsd/native/text, etc.
30
+ const subpath = specifier.slice("@gsd/native/".length);
31
+ specifier = new URL(`packages/native/src/${subpath}/index.ts`, ROOT).href;
21
32
  }
22
33
  // 2. Redirect packages/*/dist/ → packages/*/src/ with .js→.ts for strip-types
23
34
  // Also handles local imports — skip rewrite for dist/ paths that are real compiled artifacts.
@@ -54,9 +65,15 @@ export function resolve(specifier, context, nextResolve) {
54
65
  }
55
66
 
56
67
  export function load(url, context, nextLoad) {
57
- // Node's --experimental-strip-types handles .ts but not .tsx (which may contain JSX).
58
- // Use TypeScript to transpile .tsx JS with react-jsx transform, then serve as module.
59
- if (url.endsWith('.tsx')) {
68
+ // Node's --experimental-strip-types handles plain .ts but not .tsx and not
69
+ // all TypeScript syntax used by workspace packages (parameter properties,
70
+ // decorators, etc.). Transpile all workspace package source files and .tsx
71
+ // files through TypeScript's transpileModule to avoid those crashes.
72
+ const shouldTranspileWithTypeScript =
73
+ url.endsWith('.tsx') ||
74
+ (url.endsWith('.ts') && url.includes('/packages/') && url.includes('/src/'));
75
+
76
+ if (shouldTranspileWithTypeScript) {
60
77
  const ts = require('typescript');
61
78
  const source = readFileSync(fileURLToPath(url), 'utf-8');
62
79
  const { outputText } = ts.transpileModule(source, {
@@ -66,6 +83,8 @@ export function load(url, context, nextLoad) {
66
83
  module: ts.ModuleKind.ESNext,
67
84
  target: ts.ScriptTarget.ESNext,
68
85
  esModuleInterop: true,
86
+ experimentalDecorators: true,
87
+ emitDecoratorMetadata: true,
69
88
  },
70
89
  });
71
90
  return { format: 'module', source: outputText, shortCircuit: true };
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { join } from "node:path";
9
9
  import { mkdirSync } from "node:fs";
10
- import { transaction, getMilestone, getMilestoneSlices, getSliceTasks, _getAdapter, } from "../gsd-db.js";
10
+ import { transaction, getMilestone, getMilestoneSlices, getSliceTasks, updateMilestoneStatus, } from "../gsd-db.js";
11
11
  import { resolveMilestonePath, clearPathCache } from "../paths.js";
12
12
  import { saveFile, clearParseCache } from "../files.js";
13
13
  import { invalidateStateCache } from "../state.js";
@@ -116,11 +116,7 @@ export async function handleCompleteMilestone(params, basePath) {
116
116
  }
117
117
  }
118
118
  // All guards passed — perform write
119
- const adapter = _getAdapter();
120
- adapter.prepare(`UPDATE milestones SET status = 'complete', completed_at = :completed_at WHERE id = :mid`).run({
121
- ":completed_at": completedAt,
122
- ":mid": params.milestoneId,
123
- });
119
+ updateMilestoneStatus(params.milestoneId, 'complete', completedAt);
124
120
  });
125
121
  if (guardError) {
126
122
  return { error: guardError };
@@ -144,10 +140,7 @@ export async function handleCompleteMilestone(params, basePath) {
144
140
  catch (renderErr) {
145
141
  // Disk render failed — roll back DB status so state stays consistent
146
142
  process.stderr.write(`gsd-db: complete_milestone — disk render failed, rolling back DB status: ${renderErr.message}\n`);
147
- const rollbackAdapter = _getAdapter();
148
- if (rollbackAdapter) {
149
- rollbackAdapter.prepare(`UPDATE milestones SET status = 'active', completed_at = NULL WHERE id = :mid`).run({ ":mid": params.milestoneId });
150
- }
143
+ updateMilestoneStatus(params.milestoneId, 'active', null);
151
144
  invalidateStateCache();
152
145
  return { error: `disk render failed: ${renderErr.message}` };
153
146
  }
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import { join } from "node:path";
10
10
  import { mkdirSync } from "node:fs";
11
- import { transaction, insertMilestone, insertSlice, getSlice, getSliceTasks, getMilestone, updateSliceStatus, _getAdapter, } from "../gsd-db.js";
11
+ import { transaction, insertMilestone, insertSlice, getSlice, getSliceTasks, getMilestone, updateSliceStatus, setSliceSummaryMd, } from "../gsd-db.js";
12
12
  import { resolveSlicePath, clearPathCache } from "../paths.js";
13
13
  import { checkOwnership, sliceUnitKey } from "../unit-ownership.js";
14
14
  import { saveFile, clearParseCache } from "../files.js";
@@ -240,26 +240,12 @@ export async function handleCompleteSlice(params, basePath) {
240
240
  catch (renderErr) {
241
241
  // Disk render failed — roll back DB status so state stays consistent
242
242
  process.stderr.write(`gsd-db: complete_slice — disk render failed, rolling back DB status: ${renderErr.message}\n`);
243
- const rollbackAdapter = _getAdapter();
244
- if (rollbackAdapter) {
245
- rollbackAdapter.prepare(`UPDATE slices SET status = 'pending' WHERE milestone_id = :mid AND id = :sid`).run({
246
- ":mid": params.milestoneId,
247
- ":sid": params.sliceId,
248
- });
249
- }
243
+ updateSliceStatus(params.milestoneId, params.sliceId, 'pending');
250
244
  invalidateStateCache();
251
245
  return { error: `disk render failed: ${renderErr.message}` };
252
246
  }
253
247
  // Store rendered markdown in DB for D004 recovery
254
- const adapter = _getAdapter();
255
- if (adapter) {
256
- adapter.prepare(`UPDATE slices SET full_summary_md = :summary_md, full_uat_md = :uat_md WHERE milestone_id = :mid AND id = :sid`).run({
257
- ":summary_md": summaryMd,
258
- ":uat_md": uatMd,
259
- ":mid": params.milestoneId,
260
- ":sid": params.sliceId,
261
- });
262
- }
248
+ setSliceSummaryMd(params.milestoneId, params.sliceId, summaryMd, uatMd);
263
249
  // Invalidate all caches
264
250
  invalidateStateCache();
265
251
  clearPathCache();
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import { join } from "node:path";
10
10
  import { mkdirSync } from "node:fs";
11
- import { transaction, insertMilestone, insertSlice, insertTask, insertVerificationEvidence, getMilestone, getSlice, getTask, _getAdapter, } from "../gsd-db.js";
11
+ import { transaction, insertMilestone, insertSlice, insertTask, insertVerificationEvidence, getMilestone, getSlice, getTask, updateTaskStatus, setTaskSummaryMd, deleteVerificationEvidence, } from "../gsd-db.js";
12
12
  import { resolveSliceFile, resolveTasksDir, clearPathCache } from "../paths.js";
13
13
  import { checkOwnership, taskUnitKey } from "../unit-ownership.js";
14
14
  import { saveFile, clearParseCache } from "../files.js";
@@ -202,27 +202,16 @@ export async function handleCompleteTask(params, basePath) {
202
202
  catch (renderErr) {
203
203
  // Disk render failed — roll back DB status so state stays consistent
204
204
  process.stderr.write(`gsd-db: complete_task — disk render failed, rolling back DB status: ${renderErr.message}\n`);
205
- const rollbackAdapter = _getAdapter();
206
- if (rollbackAdapter) {
207
- rollbackAdapter.prepare(`UPDATE tasks SET status = 'pending' WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid`).run({
208
- ":mid": params.milestoneId,
209
- ":sid": params.sliceId,
210
- ":tid": params.taskId,
211
- });
212
- }
205
+ // Delete orphaned verification_evidence rows first (FK constraint
206
+ // references tasks, so evidence must go before status change).
207
+ // Without this, retries accumulate duplicate evidence rows (#2724).
208
+ deleteVerificationEvidence(params.milestoneId, params.sliceId, params.taskId);
209
+ updateTaskStatus(params.milestoneId, params.sliceId, params.taskId, 'pending');
213
210
  invalidateStateCache();
214
211
  return { error: `disk render failed: ${renderErr.message}` };
215
212
  }
216
213
  // Store rendered markdown in DB for D004 recovery
217
- const adapter = _getAdapter();
218
- if (adapter) {
219
- adapter.prepare(`UPDATE tasks SET full_summary_md = :md WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid`).run({
220
- ":md": summaryMd,
221
- ":mid": params.milestoneId,
222
- ":sid": params.sliceId,
223
- ":tid": params.taskId,
224
- });
225
- }
214
+ setTaskSummaryMd(params.milestoneId, params.sliceId, params.taskId, summaryMd);
226
215
  // Invalidate all caches
227
216
  invalidateStateCache();
228
217
  clearPathCache();
@@ -145,25 +145,31 @@ export async function handlePlanMilestone(rawParams, basePath) {
145
145
  catch (err) {
146
146
  return { error: `validation failed: ${err.message}` };
147
147
  }
148
- // ── State machine preconditions ─────────────────────────────────────────
149
- const existingMilestone = getMilestone(params.milestoneId);
150
- if (existingMilestone && (existingMilestone.status === "complete" || existingMilestone.status === "done")) {
151
- return { error: `cannot re-plan milestone ${params.milestoneId}: it is already complete` };
152
- }
153
- // Validate depends_on: all dependencies must exist and be complete
154
- if (params.dependsOn && params.dependsOn.length > 0) {
155
- for (const depId of params.dependsOn) {
156
- const dep = getMilestone(depId);
157
- if (!dep) {
158
- return { error: `depends_on references unknown milestone: ${depId}` };
159
- }
160
- if (dep.status !== "complete" && dep.status !== "done") {
161
- return { error: `depends_on milestone ${depId} is not yet complete (status: ${dep.status})` };
162
- }
163
- }
164
- }
148
+ // ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
149
+ // Guards must be inside the transaction so the state they check cannot
150
+ // change between the read and the write (#2723).
151
+ let guardError = null;
165
152
  try {
166
153
  transaction(() => {
154
+ const existingMilestone = getMilestone(params.milestoneId);
155
+ if (existingMilestone && (existingMilestone.status === "complete" || existingMilestone.status === "done")) {
156
+ guardError = `cannot re-plan milestone ${params.milestoneId}: it is already complete`;
157
+ return;
158
+ }
159
+ // Validate depends_on: all dependencies must exist and be complete
160
+ if (params.dependsOn && params.dependsOn.length > 0) {
161
+ for (const depId of params.dependsOn) {
162
+ const dep = getMilestone(depId);
163
+ if (!dep) {
164
+ guardError = `depends_on references unknown milestone: ${depId}`;
165
+ return;
166
+ }
167
+ if (dep.status !== "complete" && dep.status !== "done") {
168
+ guardError = `depends_on milestone ${depId} is not yet complete (status: ${dep.status})`;
169
+ return;
170
+ }
171
+ }
172
+ }
167
173
  insertMilestone({
168
174
  id: params.milestoneId,
169
175
  title: params.title,
@@ -206,6 +212,9 @@ export async function handlePlanMilestone(rawParams, basePath) {
206
212
  catch (err) {
207
213
  return { error: `db write failed: ${err.message}` };
208
214
  }
215
+ if (guardError) {
216
+ return { error: guardError };
217
+ }
209
218
  let roadmapPath;
210
219
  try {
211
220
  const renderResult = await renderRoadmapFromDb(basePath, params.milestoneId);
@@ -102,22 +102,30 @@ export async function handlePlanSlice(rawParams, basePath) {
102
102
  catch (err) {
103
103
  return { error: `validation failed: ${err.message}` };
104
104
  }
105
- const parentMilestone = getMilestone(params.milestoneId);
106
- if (!parentMilestone) {
107
- return { error: `milestone not found: ${params.milestoneId}` };
108
- }
109
- if (parentMilestone.status === "complete" || parentMilestone.status === "done") {
110
- return { error: `cannot plan slice in a closed milestone: ${params.milestoneId} (status: ${parentMilestone.status})` };
111
- }
112
- const parentSlice = getSlice(params.milestoneId, params.sliceId);
113
- if (!parentSlice) {
114
- return { error: `missing parent slice: ${params.milestoneId}/${params.sliceId}` };
115
- }
116
- if (parentSlice.status === "complete" || parentSlice.status === "done") {
117
- return { error: `cannot re-plan slice ${params.sliceId}: it is already complete — use gsd_slice_reopen first` };
118
- }
105
+ // ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
106
+ // Guards must be inside the transaction so the state they check cannot
107
+ // change between the read and the write (#2723).
108
+ let guardError = null;
119
109
  try {
120
110
  transaction(() => {
111
+ const parentMilestone = getMilestone(params.milestoneId);
112
+ if (!parentMilestone) {
113
+ guardError = `milestone not found: ${params.milestoneId}`;
114
+ return;
115
+ }
116
+ if (parentMilestone.status === "complete" || parentMilestone.status === "done") {
117
+ guardError = `cannot plan slice in a closed milestone: ${params.milestoneId} (status: ${parentMilestone.status})`;
118
+ return;
119
+ }
120
+ const parentSlice = getSlice(params.milestoneId, params.sliceId);
121
+ if (!parentSlice) {
122
+ guardError = `missing parent slice: ${params.milestoneId}/${params.sliceId}`;
123
+ return;
124
+ }
125
+ if (parentSlice.status === "complete" || parentSlice.status === "done") {
126
+ guardError = `cannot re-plan slice ${params.sliceId}: it is already complete — use gsd_slice_reopen first`;
127
+ return;
128
+ }
121
129
  upsertSlicePlanning(params.milestoneId, params.sliceId, {
122
130
  goal: params.goal,
123
131
  successCriteria: params.successCriteria,
@@ -163,6 +171,9 @@ export async function handlePlanSlice(rawParams, basePath) {
163
171
  catch (err) {
164
172
  return { error: `db write failed: ${err.message}` };
165
173
  }
174
+ if (guardError) {
175
+ return { error: guardError };
176
+ }
166
177
  try {
167
178
  const renderResult = await renderPlanFromDb(basePath, params.milestoneId, params.sliceId);
168
179
  invalidateStateCache();
@@ -50,19 +50,26 @@ export async function handlePlanTask(rawParams, basePath) {
50
50
  catch (err) {
51
51
  return { error: `validation failed: ${err.message}` };
52
52
  }
53
- const parentSlice = getSlice(params.milestoneId, params.sliceId);
54
- if (!parentSlice) {
55
- return { error: `missing parent slice: ${params.milestoneId}/${params.sliceId}` };
56
- }
57
- if (parentSlice.status === "complete" || parentSlice.status === "done") {
58
- return { error: `cannot plan task in a closed slice: ${params.sliceId} (status: ${parentSlice.status})` };
59
- }
60
- const existingTask = getTask(params.milestoneId, params.sliceId, params.taskId);
61
- if (existingTask && (existingTask.status === "complete" || existingTask.status === "done")) {
62
- return { error: `cannot re-plan task ${params.taskId}: it is already complete — use gsd_task_reopen first` };
63
- }
53
+ // ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
54
+ // Guards must be inside the transaction so the state they check cannot
55
+ // change between the read and the write (#2723).
56
+ let guardError = null;
64
57
  try {
65
58
  transaction(() => {
59
+ const parentSlice = getSlice(params.milestoneId, params.sliceId);
60
+ if (!parentSlice) {
61
+ guardError = `missing parent slice: ${params.milestoneId}/${params.sliceId}`;
62
+ return;
63
+ }
64
+ if (parentSlice.status === "complete" || parentSlice.status === "done") {
65
+ guardError = `cannot plan task in a closed slice: ${params.sliceId} (status: ${parentSlice.status})`;
66
+ return;
67
+ }
68
+ const existingTask = getTask(params.milestoneId, params.sliceId, params.taskId);
69
+ if (existingTask && (existingTask.status === "complete" || existingTask.status === "done")) {
70
+ guardError = `cannot re-plan task ${params.taskId}: it is already complete — use gsd_task_reopen first`;
71
+ return;
72
+ }
66
73
  if (!existingTask) {
67
74
  insertTask({
68
75
  id: params.taskId,
@@ -88,6 +95,9 @@ export async function handlePlanTask(rawParams, basePath) {
88
95
  catch (err) {
89
96
  return { error: `db write failed: ${err.message}` };
90
97
  }
98
+ if (guardError) {
99
+ return { error: guardError };
100
+ }
91
101
  try {
92
102
  const renderResult = await renderTaskPlanFromDb(basePath, params.milestoneId, params.sliceId, params.taskId);
93
103
  invalidateStateCache();
@@ -61,48 +61,55 @@ export async function handleReassessRoadmap(rawParams, basePath) {
61
61
  catch (err) {
62
62
  return { error: `validation failed: ${err.message}` };
63
63
  }
64
- // ── Verify milestone exists and is active ────────────────────────
65
- const milestone = getMilestone(params.milestoneId);
66
- if (!milestone) {
67
- return { error: `milestone not found: ${params.milestoneId}` };
68
- }
69
- if (milestone.status === "complete" || milestone.status === "done") {
70
- return { error: `cannot reassess a closed milestone: ${params.milestoneId} (status: ${milestone.status})` };
71
- }
72
- // ── Verify completedSliceId is actually complete ──────────────────
73
- const completedSlice = getSlice(params.milestoneId, params.completedSliceId);
74
- if (!completedSlice) {
75
- return { error: `completedSliceId not found: ${params.milestoneId}/${params.completedSliceId}` };
76
- }
77
- if (completedSlice.status !== "complete" && completedSlice.status !== "done") {
78
- return { error: `completedSliceId ${params.completedSliceId} is not complete (status: ${completedSlice.status}) — reassess can only be called after a slice finishes` };
79
- }
80
- // ── Structural enforcement ────────────────────────────────────────
81
- const existingSlices = getMilestoneSlices(params.milestoneId);
82
- const completedSliceIds = new Set();
83
- for (const slice of existingSlices) {
84
- if (slice.status === "complete" || slice.status === "done") {
85
- completedSliceIds.add(slice.id);
86
- }
87
- }
88
- // Reject modifications to completed slices
89
- for (const modifiedSlice of params.sliceChanges.modified) {
90
- if (completedSliceIds.has(modifiedSlice.sliceId)) {
91
- return { error: `cannot modify completed slice ${modifiedSlice.sliceId}` };
92
- }
93
- }
94
- // Reject removal of completed slices
95
- for (const removedId of params.sliceChanges.removed) {
96
- if (completedSliceIds.has(removedId)) {
97
- return { error: `cannot remove completed slice ${removedId}` };
98
- }
99
- }
100
64
  // ── Compute assessment artifact path ──────────────────────────────
101
65
  // Assessment lives in the completed slice's directory
102
66
  const assessmentRelPath = join(".gsd", "milestones", params.milestoneId, "slices", params.completedSliceId, `${params.completedSliceId}-ASSESSMENT.md`);
103
- // ── Transaction: DB mutations ─────────────────────────────────────
67
+ // ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
68
+ // Guards must be inside the transaction so the state they check cannot
69
+ // change between the read and the write (#2723).
70
+ let guardError = null;
104
71
  try {
105
72
  transaction(() => {
73
+ // Verify milestone exists and is active
74
+ const milestone = getMilestone(params.milestoneId);
75
+ if (!milestone) {
76
+ guardError = `milestone not found: ${params.milestoneId}`;
77
+ return;
78
+ }
79
+ if (milestone.status === "complete" || milestone.status === "done") {
80
+ guardError = `cannot reassess a closed milestone: ${params.milestoneId} (status: ${milestone.status})`;
81
+ return;
82
+ }
83
+ // Verify completedSliceId is actually complete
84
+ const completedSlice = getSlice(params.milestoneId, params.completedSliceId);
85
+ if (!completedSlice) {
86
+ guardError = `completedSliceId not found: ${params.milestoneId}/${params.completedSliceId}`;
87
+ return;
88
+ }
89
+ if (completedSlice.status !== "complete" && completedSlice.status !== "done") {
90
+ guardError = `completedSliceId ${params.completedSliceId} is not complete (status: ${completedSlice.status}) — reassess can only be called after a slice finishes`;
91
+ return;
92
+ }
93
+ // Structural enforcement — reject modifications/removal of completed slices
94
+ const existingSlices = getMilestoneSlices(params.milestoneId);
95
+ const completedSliceIds = new Set();
96
+ for (const slice of existingSlices) {
97
+ if (slice.status === "complete" || slice.status === "done") {
98
+ completedSliceIds.add(slice.id);
99
+ }
100
+ }
101
+ for (const modifiedSlice of params.sliceChanges.modified) {
102
+ if (completedSliceIds.has(modifiedSlice.sliceId)) {
103
+ guardError = `cannot modify completed slice ${modifiedSlice.sliceId}`;
104
+ return;
105
+ }
106
+ }
107
+ for (const removedId of params.sliceChanges.removed) {
108
+ if (completedSliceIds.has(removedId)) {
109
+ guardError = `cannot remove completed slice ${removedId}`;
110
+ return;
111
+ }
112
+ }
106
113
  // Record assessment
107
114
  insertAssessment({
108
115
  path: assessmentRelPath,
@@ -142,6 +149,9 @@ export async function handleReassessRoadmap(rawParams, basePath) {
142
149
  catch (err) {
143
150
  return { error: `db write failed: ${err.message}` };
144
151
  }
152
+ if (guardError) {
153
+ return { error: guardError };
154
+ }
145
155
  // ── Render artifacts ──────────────────────────────────────────────
146
156
  try {
147
157
  const roadmapResult = await renderRoadmapFromDb(basePath, params.milestoneId);