gsd-pi 2.43.0 → 2.44.0-dev.0b97ffd

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 (693) hide show
  1. package/README.md +30 -12
  2. package/dist/cli.js +13 -1
  3. package/dist/help-text.js +24 -0
  4. package/dist/resources/extensions/bg-shell/overlay.js +3 -0
  5. package/dist/resources/extensions/github-sync/sync.js +2 -1
  6. package/dist/resources/extensions/gsd/auto/loop.js +0 -2
  7. package/dist/resources/extensions/gsd/auto/phases.js +7 -12
  8. package/dist/resources/extensions/gsd/auto-dashboard.js +19 -18
  9. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +34 -19
  10. package/dist/resources/extensions/gsd/auto-dispatch.js +36 -21
  11. package/dist/resources/extensions/gsd/auto-post-unit.js +128 -14
  12. package/dist/resources/extensions/gsd/auto-prompts.js +202 -92
  13. package/dist/resources/extensions/gsd/auto-recovery.js +83 -135
  14. package/dist/resources/extensions/gsd/auto-start.js +10 -0
  15. package/dist/resources/extensions/gsd/auto-supervisor.js +14 -0
  16. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +4 -7
  17. package/dist/resources/extensions/gsd/auto-verification.js +5 -10
  18. package/dist/resources/extensions/gsd/auto-worktree.js +123 -30
  19. package/dist/resources/extensions/gsd/auto.js +1 -4
  20. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +611 -0
  21. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +28 -3
  22. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -0
  23. package/dist/resources/extensions/gsd/commands/catalog.js +3 -1
  24. package/dist/resources/extensions/gsd/commands/handlers/ops.js +15 -1
  25. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
  26. package/dist/resources/extensions/gsd/commands-handlers.js +1 -1
  27. package/dist/resources/extensions/gsd/commands-maintenance.js +78 -3
  28. package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -31
  29. package/dist/resources/extensions/gsd/db-writer.js +95 -4
  30. package/dist/resources/extensions/gsd/dispatch-guard.js +35 -30
  31. package/dist/resources/extensions/gsd/doctor-checks.js +28 -11
  32. package/dist/resources/extensions/gsd/doctor-environment.js +28 -0
  33. package/dist/resources/extensions/gsd/doctor-types.js +0 -15
  34. package/dist/resources/extensions/gsd/doctor.js +46 -282
  35. package/dist/resources/extensions/gsd/file-watcher.js +5 -1
  36. package/dist/resources/extensions/gsd/files.js +14 -198
  37. package/dist/resources/extensions/gsd/git-service.js +4 -0
  38. package/dist/resources/extensions/gsd/gitignore.js +4 -0
  39. package/dist/resources/extensions/gsd/gsd-db.js +819 -197
  40. package/dist/resources/extensions/gsd/guided-flow.js +18 -8
  41. package/dist/resources/extensions/gsd/markdown-renderer.js +862 -0
  42. package/dist/resources/extensions/gsd/md-importer.js +182 -4
  43. package/dist/resources/extensions/gsd/native-git-bridge.js +10 -1
  44. package/dist/resources/extensions/gsd/parallel-eligibility.js +14 -19
  45. package/dist/resources/extensions/gsd/parallel-orchestrator.js +38 -0
  46. package/dist/resources/extensions/gsd/parsers-legacy.js +239 -0
  47. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  48. package/dist/resources/extensions/gsd/preferences-validation.js +9 -0
  49. package/dist/resources/extensions/gsd/preferences.js +1 -0
  50. package/dist/resources/extensions/gsd/prompts/complete-slice.md +22 -9
  51. package/dist/resources/extensions/gsd/prompts/discuss.md +2 -2
  52. package/dist/resources/extensions/gsd/prompts/execute-task.md +15 -5
  53. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  54. package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  55. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  56. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +6 -10
  57. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -7
  58. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -3
  59. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -7
  60. package/dist/resources/extensions/gsd/prompts/replan-slice.md +6 -6
  61. package/dist/resources/extensions/gsd/reactive-graph.js +33 -3
  62. package/dist/resources/extensions/gsd/skill-health.js +3 -1
  63. package/dist/resources/extensions/gsd/state.js +484 -30
  64. package/dist/resources/extensions/gsd/tools/complete-milestone.js +128 -0
  65. package/dist/resources/extensions/gsd/tools/complete-slice.js +244 -0
  66. package/dist/resources/extensions/gsd/tools/complete-task.js +204 -0
  67. package/dist/resources/extensions/gsd/tools/plan-milestone.js +205 -0
  68. package/dist/resources/extensions/gsd/tools/plan-slice.js +155 -0
  69. package/dist/resources/extensions/gsd/tools/plan-task.js +94 -0
  70. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +152 -0
  71. package/dist/resources/extensions/gsd/tools/replan-slice.js +146 -0
  72. package/dist/resources/extensions/gsd/triage-resolution.js +17 -1
  73. package/dist/resources/extensions/gsd/undo.js +197 -3
  74. package/dist/resources/extensions/gsd/visualizer-data.js +53 -16
  75. package/dist/resources/extensions/gsd/workspace-index.js +63 -39
  76. package/dist/web/standalone/.next/BUILD_ID +1 -1
  77. package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -17
  78. package/dist/web/standalone/.next/build-manifest.json +4 -4
  79. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  80. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  81. package/dist/web/standalone/.next/required-server-files.json +4 -4
  82. package/dist/web/standalone/.next/routes-manifest.json +6 -0
  83. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  84. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  86. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  94. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  96. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
  97. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  98. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  100. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  103. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  110. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  148. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  154. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -0
  166. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -0
  167. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -0
  168. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  171. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  173. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  175. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/index.html +1 -1
  185. package/dist/web/standalone/.next/server/app/index.rsc +5 -5
  186. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  187. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
  188. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  189. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  190. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  191. package/dist/web/standalone/.next/server/app/page.js +2 -2
  192. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -17
  194. package/dist/web/standalone/.next/server/chunks/229.js +3 -3
  195. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  196. package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
  197. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/middleware.js +2 -2
  200. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  202. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  203. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  204. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  205. package/dist/web/standalone/.next/static/alS4hoANx0TK4UVZY27da/_buildManifest.js +1 -0
  206. package/dist/web/standalone/.next/static/chunks/{4024.c195dc1fdd2adbea.js → 4024.0de81b543b28b9fe.js} +2 -2
  207. package/dist/web/standalone/.next/static/chunks/app/_global-error/{page-d07a2c023f1aef1e.js → page-d83ba70a25a85472.js} +1 -1
  208. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
  209. package/dist/web/standalone/.next/static/chunks/app/api/boot/{route-d07a2c023f1aef1e.js → route-d83ba70a25a85472.js} +1 -1
  210. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/{route-d07a2c023f1aef1e.js → route-d83ba70a25a85472.js} +1 -1
  211. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/{route-d07a2c023f1aef1e.js → route-d83ba70a25a85472.js} +1 -1
  212. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-d83ba70a25a85472.js +1 -0
  213. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-d83ba70a25a85472.js +1 -0
  214. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-d83ba70a25a85472.js +1 -0
  215. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-d83ba70a25a85472.js +1 -0
  216. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-d83ba70a25a85472.js +1 -0
  217. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-d83ba70a25a85472.js +1 -0
  218. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-d83ba70a25a85472.js +1 -0
  219. package/dist/web/standalone/.next/static/chunks/app/api/files/route-d83ba70a25a85472.js +1 -0
  220. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-d83ba70a25a85472.js +1 -0
  221. package/dist/web/standalone/.next/static/chunks/app/api/git/route-d83ba70a25a85472.js +1 -0
  222. package/dist/web/standalone/.next/static/chunks/app/api/history/route-d83ba70a25a85472.js +1 -0
  223. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-d83ba70a25a85472.js +1 -0
  224. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-d83ba70a25a85472.js +1 -0
  225. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-d83ba70a25a85472.js +1 -0
  226. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-d83ba70a25a85472.js +1 -0
  227. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-d83ba70a25a85472.js +1 -0
  228. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-d83ba70a25a85472.js +1 -0
  229. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-d83ba70a25a85472.js +1 -0
  230. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-d83ba70a25a85472.js +1 -0
  231. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-d83ba70a25a85472.js +1 -0
  232. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-d83ba70a25a85472.js +1 -0
  233. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-d83ba70a25a85472.js +1 -0
  234. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-d83ba70a25a85472.js +1 -0
  235. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-d83ba70a25a85472.js +1 -0
  236. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-d83ba70a25a85472.js +1 -0
  237. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-d83ba70a25a85472.js +1 -0
  238. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-d83ba70a25a85472.js +1 -0
  239. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-d83ba70a25a85472.js +1 -0
  240. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-d83ba70a25a85472.js +1 -0
  241. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-d83ba70a25a85472.js +1 -0
  242. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-d83ba70a25a85472.js +1 -0
  243. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-d83ba70a25a85472.js +1 -0
  244. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-d83ba70a25a85472.js +1 -0
  245. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-d83ba70a25a85472.js +1 -0
  246. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-d83ba70a25a85472.js +1 -0
  247. package/dist/web/standalone/.next/static/chunks/app/api/update/route-d83ba70a25a85472.js +1 -0
  248. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-d83ba70a25a85472.js +1 -0
  249. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
  250. package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
  251. package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
  252. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-d83ba70a25a85472.js +1 -0
  253. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-d83ba70a25a85472.js +1 -0
  254. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  255. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-d83ba70a25a85472.js +1 -0
  256. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d83ba70a25a85472.js +1 -0
  257. package/dist/web/standalone/.next/static/chunks/{webpack-fa307370fcf9fb2c.js → webpack-9014b5adb127a98a.js} +1 -1
  258. package/dist/web/standalone/.next/static/css/8a727f372cf53002.css +1 -0
  259. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  260. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  261. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  262. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  263. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  264. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  265. package/dist/web/standalone/server.js +1 -1
  266. package/package.json +4 -4
  267. package/packages/pi-ai/dist/models.custom.d.ts +173 -0
  268. package/packages/pi-ai/dist/models.custom.d.ts.map +1 -0
  269. package/packages/pi-ai/dist/models.custom.js +170 -0
  270. package/packages/pi-ai/dist/models.custom.js.map +1 -0
  271. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  272. package/packages/pi-ai/dist/models.js +16 -1
  273. package/packages/pi-ai/dist/models.js.map +1 -1
  274. package/packages/pi-ai/dist/models.test.d.ts +2 -0
  275. package/packages/pi-ai/dist/models.test.d.ts.map +1 -0
  276. package/packages/pi-ai/dist/models.test.js +67 -0
  277. package/packages/pi-ai/dist/models.test.js.map +1 -0
  278. package/packages/pi-ai/src/models.custom.ts +172 -0
  279. package/packages/pi-ai/src/models.test.ts +85 -0
  280. package/packages/pi-ai/src/models.ts +17 -1
  281. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +10 -3
  282. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/agent-session.js +21 -34
  284. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
  286. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts +2 -2
  288. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js.map +1 -1
  290. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +2 -2
  291. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  292. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +4 -4
  294. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  296. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  297. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  298. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +6 -0
  299. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  300. package/packages/pi-coding-agent/dist/core/extensions/loader.js +80 -0
  301. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  302. package/packages/pi-coding-agent/dist/core/extensions/loader.test.js +63 -0
  303. package/packages/pi-coding-agent/dist/core/extensions/loader.test.js.map +1 -1
  304. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
  305. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  306. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +37 -0
  307. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  308. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  309. package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts.map +1 -1
  310. package/packages/pi-coding-agent/dist/core/fallback-resolver.js +2 -3
  311. package/packages/pi-coding-agent/dist/core/fallback-resolver.js.map +1 -1
  312. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js +12 -2
  313. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js.map +1 -1
  314. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
  315. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  316. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +38 -0
  317. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -0
  318. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +192 -0
  319. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -0
  320. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts +5 -0
  321. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
  322. package/packages/pi-coding-agent/dist/core/lsp/client.js +69 -21
  323. package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
  324. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts +2 -0
  325. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts.map +1 -0
  326. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +255 -0
  327. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -0
  328. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +15 -0
  329. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  330. package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
  331. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  332. package/packages/pi-coding-agent/dist/core/package-commands.d.ts +25 -0
  333. package/packages/pi-coding-agent/dist/core/package-commands.d.ts.map +1 -0
  334. package/packages/pi-coding-agent/dist/core/package-commands.js +253 -0
  335. package/packages/pi-coding-agent/dist/core/package-commands.js.map +1 -0
  336. package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts +2 -0
  337. package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts.map +1 -0
  338. package/packages/pi-coding-agent/dist/core/package-commands.test.js +225 -0
  339. package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -0
  340. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
  341. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  342. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  343. package/packages/pi-coding-agent/dist/core/sdk.js +4 -0
  344. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  345. package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
  346. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  347. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
  348. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  349. package/packages/pi-coding-agent/dist/index.d.ts +3 -1
  350. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  351. package/packages/pi-coding-agent/dist/index.js +1 -0
  352. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  353. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  354. package/packages/pi-coding-agent/dist/main.js +11 -199
  355. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  356. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts +6 -0
  357. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  358. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +21 -0
  359. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  360. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
  361. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  362. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +8 -15
  363. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  364. package/packages/pi-coding-agent/dist/modes/print-mode.d.ts.map +1 -1
  365. package/packages/pi-coding-agent/dist/modes/print-mode.js +45 -34
  366. package/packages/pi-coding-agent/dist/modes/print-mode.js.map +1 -1
  367. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts +1 -0
  368. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  369. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js +7 -2
  370. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js.map +1 -1
  371. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  372. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +2 -1
  373. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  374. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
  375. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  376. package/packages/pi-coding-agent/package.json +1 -1
  377. package/packages/pi-coding-agent/src/core/agent-session.ts +26 -37
  378. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  379. package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +2 -2
  380. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +3 -3
  381. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +4 -4
  382. package/packages/pi-coding-agent/src/core/extensions/index.ts +5 -0
  383. package/packages/pi-coding-agent/src/core/extensions/loader.test.ts +96 -0
  384. package/packages/pi-coding-agent/src/core/extensions/loader.ts +89 -0
  385. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  386. package/packages/pi-coding-agent/src/core/extensions/types.ts +44 -0
  387. package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +15 -2
  388. package/packages/pi-coding-agent/src/core/fallback-resolver.ts +2 -3
  389. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
  390. package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +274 -0
  391. package/packages/pi-coding-agent/src/core/lsp/client.ts +83 -21
  392. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +288 -0
  393. package/packages/pi-coding-agent/src/core/model-registry.ts +39 -3
  394. package/packages/pi-coding-agent/src/core/package-commands.test.ts +240 -0
  395. package/packages/pi-coding-agent/src/core/package-commands.ts +310 -0
  396. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
  397. package/packages/pi-coding-agent/src/core/sdk.ts +4 -0
  398. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  399. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  400. package/packages/pi-coding-agent/src/index.ts +7 -0
  401. package/packages/pi-coding-agent/src/main.ts +11 -232
  402. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +20 -0
  403. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +9 -16
  404. package/packages/pi-coding-agent/src/modes/print-mode.ts +42 -32
  405. package/packages/pi-coding-agent/src/modes/rpc/rpc-client.ts +8 -2
  406. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +2 -1
  407. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  408. package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
  409. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  410. package/pkg/dist/modes/interactive/theme/theme.js +8 -15
  411. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  412. package/pkg/package.json +1 -1
  413. package/src/resources/extensions/bg-shell/overlay.ts +4 -0
  414. package/src/resources/extensions/github-sync/sync.ts +2 -1
  415. package/src/resources/extensions/gsd/auto/loop-deps.ts +0 -8
  416. package/src/resources/extensions/gsd/auto/loop.ts +0 -2
  417. package/src/resources/extensions/gsd/auto/phases.ts +7 -20
  418. package/src/resources/extensions/gsd/auto/types.ts +0 -1
  419. package/src/resources/extensions/gsd/auto-dashboard.ts +20 -16
  420. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +34 -19
  421. package/src/resources/extensions/gsd/auto-dispatch.ts +38 -21
  422. package/src/resources/extensions/gsd/auto-post-unit.ts +150 -15
  423. package/src/resources/extensions/gsd/auto-prompts.ts +186 -103
  424. package/src/resources/extensions/gsd/auto-recovery.ts +77 -142
  425. package/src/resources/extensions/gsd/auto-start.ts +14 -0
  426. package/src/resources/extensions/gsd/auto-supervisor.ts +14 -0
  427. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +6 -7
  428. package/src/resources/extensions/gsd/auto-verification.ts +4 -9
  429. package/src/resources/extensions/gsd/auto-worktree.ts +126 -30
  430. package/src/resources/extensions/gsd/auto.ts +0 -9
  431. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +675 -4
  432. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +31 -3
  433. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -0
  434. package/src/resources/extensions/gsd/commands/catalog.ts +3 -1
  435. package/src/resources/extensions/gsd/commands/handlers/ops.ts +15 -1
  436. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
  437. package/src/resources/extensions/gsd/commands-handlers.ts +1 -1
  438. package/src/resources/extensions/gsd/commands-maintenance.ts +86 -3
  439. package/src/resources/extensions/gsd/dashboard-overlay.ts +17 -13
  440. package/src/resources/extensions/gsd/db-writer.ts +105 -4
  441. package/src/resources/extensions/gsd/dispatch-guard.ts +32 -30
  442. package/src/resources/extensions/gsd/doctor-checks.ts +25 -11
  443. package/src/resources/extensions/gsd/doctor-environment.ts +31 -0
  444. package/src/resources/extensions/gsd/doctor-types.ts +0 -23
  445. package/src/resources/extensions/gsd/doctor.ts +45 -295
  446. package/src/resources/extensions/gsd/file-watcher.ts +4 -1
  447. package/src/resources/extensions/gsd/files.ts +16 -220
  448. package/src/resources/extensions/gsd/git-service.ts +4 -0
  449. package/src/resources/extensions/gsd/gitignore.ts +4 -0
  450. package/src/resources/extensions/gsd/gsd-db.ts +1157 -370
  451. package/src/resources/extensions/gsd/guided-flow.ts +20 -8
  452. package/src/resources/extensions/gsd/markdown-renderer.ts +1098 -0
  453. package/src/resources/extensions/gsd/md-importer.ts +211 -2
  454. package/src/resources/extensions/gsd/native-git-bridge.ts +12 -1
  455. package/src/resources/extensions/gsd/parallel-eligibility.ts +14 -18
  456. package/src/resources/extensions/gsd/parallel-orchestrator.ts +43 -0
  457. package/src/resources/extensions/gsd/parsers-legacy.ts +271 -0
  458. package/src/resources/extensions/gsd/preferences-types.ts +3 -0
  459. package/src/resources/extensions/gsd/preferences-validation.ts +9 -0
  460. package/src/resources/extensions/gsd/preferences.ts +1 -0
  461. package/src/resources/extensions/gsd/prompts/complete-slice.md +22 -9
  462. package/src/resources/extensions/gsd/prompts/discuss.md +2 -2
  463. package/src/resources/extensions/gsd/prompts/execute-task.md +15 -5
  464. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  465. package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  466. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  467. package/src/resources/extensions/gsd/prompts/plan-milestone.md +6 -10
  468. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -7
  469. package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -3
  470. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -7
  471. package/src/resources/extensions/gsd/prompts/replan-slice.md +6 -6
  472. package/src/resources/extensions/gsd/reactive-graph.ts +33 -3
  473. package/src/resources/extensions/gsd/skill-health.ts +2 -1
  474. package/src/resources/extensions/gsd/state.ts +547 -29
  475. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  476. package/src/resources/extensions/gsd/tests/atomic-task-closeout.test.ts +8 -120
  477. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
  478. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +20 -11
  479. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
  480. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
  481. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +600 -513
  482. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
  483. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
  484. package/src/resources/extensions/gsd/tests/auto-stash-merge.test.ts +121 -0
  485. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +540 -668
  486. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
  487. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
  488. package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
  489. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
  490. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
  491. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  492. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  493. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +39 -60
  494. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +375 -0
  495. package/src/resources/extensions/gsd/tests/complete-task.test.ts +387 -0
  496. package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
  497. package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
  498. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
  499. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
  500. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +0 -2
  501. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
  502. package/src/resources/extensions/gsd/tests/db-writer.test.ts +390 -420
  503. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
  504. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +512 -0
  505. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +644 -84
  506. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
  507. package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
  508. package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
  509. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
  510. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +192 -161
  511. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
  512. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
  513. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +30 -90
  514. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
  515. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +57 -80
  516. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +164 -0
  517. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
  518. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +55 -153
  519. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
  520. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
  521. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +53 -97
  522. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
  523. package/src/resources/extensions/gsd/tests/doctor.test.ts +109 -149
  524. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
  525. package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
  526. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
  527. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
  528. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +278 -0
  529. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +232 -0
  530. package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
  531. package/src/resources/extensions/gsd/tests/git-service.test.ts +291 -390
  532. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
  533. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
  534. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
  535. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
  536. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +440 -0
  537. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
  538. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  539. package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
  540. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -270
  541. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
  542. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
  543. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
  544. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
  545. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +643 -0
  546. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -3
  547. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1161 -0
  548. package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
  549. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
  550. package/src/resources/extensions/gsd/tests/memory-store.test.ts +81 -94
  551. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
  552. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +429 -0
  553. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
  554. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
  555. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
  556. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +89 -97
  557. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +127 -164
  558. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
  559. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
  560. package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
  561. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
  562. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
  563. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
  564. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
  565. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
  566. package/src/resources/extensions/gsd/tests/parsers.test.ts +548 -612
  567. package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
  568. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +176 -113
  569. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +7 -0
  570. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +179 -0
  571. package/src/resources/extensions/gsd/tests/plan-task.test.ts +145 -0
  572. package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +305 -0
  573. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
  574. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +139 -0
  575. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  576. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
  577. package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
  578. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
  579. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
  580. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
  581. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +325 -0
  582. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
  583. package/src/resources/extensions/gsd/tests/replan-handler.test.ts +410 -0
  584. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
  585. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
  586. package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
  587. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
  588. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
  589. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +1 -1
  590. package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +296 -0
  591. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
  592. package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
  593. package/src/resources/extensions/gsd/tests/schema-v9-sequence.test.ts +176 -0
  594. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
  595. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
  596. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +209 -0
  597. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
  598. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
  599. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
  600. package/src/resources/extensions/gsd/tests/token-cost-display.test.ts +118 -0
  601. package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
  602. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
  603. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +19 -13
  604. package/src/resources/extensions/gsd/tests/undo.test.ts +321 -1
  605. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
  606. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
  607. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +1 -1
  608. package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +0 -142
  609. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
  610. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
  611. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
  612. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
  613. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
  614. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
  615. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
  616. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
  617. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
  618. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
  619. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
  620. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +12 -5
  621. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
  622. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
  623. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
  624. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
  625. package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
  626. package/src/resources/extensions/gsd/tools/complete-milestone.ts +176 -0
  627. package/src/resources/extensions/gsd/tools/complete-slice.ts +300 -0
  628. package/src/resources/extensions/gsd/tools/complete-task.ts +245 -0
  629. package/src/resources/extensions/gsd/tools/plan-milestone.ts +249 -0
  630. package/src/resources/extensions/gsd/tools/plan-slice.ts +194 -0
  631. package/src/resources/extensions/gsd/tools/plan-task.ts +116 -0
  632. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +203 -0
  633. package/src/resources/extensions/gsd/tools/replan-slice.ts +192 -0
  634. package/src/resources/extensions/gsd/triage-resolution.ts +20 -1
  635. package/src/resources/extensions/gsd/types.ts +50 -0
  636. package/src/resources/extensions/gsd/undo.ts +247 -3
  637. package/src/resources/extensions/gsd/visualizer-data.ts +54 -17
  638. package/src/resources/extensions/gsd/workspace-index.ts +64 -46
  639. package/dist/resources/extensions/gsd/auto-observability.js +0 -56
  640. package/dist/resources/extensions/gsd/observability-validator.js +0 -422
  641. package/dist/resources/extensions/gsd/roadmap-mutations.js +0 -110
  642. package/dist/web/standalone/.next/static/VvclDCW6TAWjEyLU-EYL1/_buildManifest.js +0 -1
  643. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
  644. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-d07a2c023f1aef1e.js +0 -1
  645. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-d07a2c023f1aef1e.js +0 -1
  646. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-d07a2c023f1aef1e.js +0 -1
  647. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-d07a2c023f1aef1e.js +0 -1
  648. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-d07a2c023f1aef1e.js +0 -1
  649. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-d07a2c023f1aef1e.js +0 -1
  650. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-d07a2c023f1aef1e.js +0 -1
  651. package/dist/web/standalone/.next/static/chunks/app/api/files/route-d07a2c023f1aef1e.js +0 -1
  652. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-d07a2c023f1aef1e.js +0 -1
  653. package/dist/web/standalone/.next/static/chunks/app/api/git/route-d07a2c023f1aef1e.js +0 -1
  654. package/dist/web/standalone/.next/static/chunks/app/api/history/route-d07a2c023f1aef1e.js +0 -1
  655. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-d07a2c023f1aef1e.js +0 -1
  656. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-d07a2c023f1aef1e.js +0 -1
  657. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-d07a2c023f1aef1e.js +0 -1
  658. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-d07a2c023f1aef1e.js +0 -1
  659. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-d07a2c023f1aef1e.js +0 -1
  660. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-d07a2c023f1aef1e.js +0 -1
  661. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-d07a2c023f1aef1e.js +0 -1
  662. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-d07a2c023f1aef1e.js +0 -1
  663. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-d07a2c023f1aef1e.js +0 -1
  664. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-d07a2c023f1aef1e.js +0 -1
  665. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-d07a2c023f1aef1e.js +0 -1
  666. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-d07a2c023f1aef1e.js +0 -1
  667. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-d07a2c023f1aef1e.js +0 -1
  668. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-d07a2c023f1aef1e.js +0 -1
  669. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-d07a2c023f1aef1e.js +0 -1
  670. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-d07a2c023f1aef1e.js +0 -1
  671. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-d07a2c023f1aef1e.js +0 -1
  672. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-d07a2c023f1aef1e.js +0 -1
  673. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-d07a2c023f1aef1e.js +0 -1
  674. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-d07a2c023f1aef1e.js +0 -1
  675. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-d07a2c023f1aef1e.js +0 -1
  676. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-d07a2c023f1aef1e.js +0 -1
  677. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-d07a2c023f1aef1e.js +0 -1
  678. package/dist/web/standalone/.next/static/chunks/app/api/update/route-d07a2c023f1aef1e.js +0 -1
  679. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-d07a2c023f1aef1e.js +0 -1
  680. package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
  681. package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
  682. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-d07a2c023f1aef1e.js +0 -1
  683. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-d07a2c023f1aef1e.js +0 -1
  684. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
  685. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-d07a2c023f1aef1e.js +0 -1
  686. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d07a2c023f1aef1e.js +0 -1
  687. package/dist/web/standalone/.next/static/css/123c0bb039697968.css +0 -1
  688. package/src/resources/extensions/gsd/auto-observability.ts +0 -74
  689. package/src/resources/extensions/gsd/observability-validator.ts +0 -456
  690. package/src/resources/extensions/gsd/roadmap-mutations.ts +0 -134
  691. package/src/resources/extensions/gsd/tests/doctor-task-done-missing-summary-slice-loop.test.ts +0 -174
  692. package/src/resources/extensions/gsd/tests/plan-quality-validator.test.ts +0 -474
  693. /package/dist/web/standalone/.next/static/{VvclDCW6TAWjEyLU-EYL1 → alS4hoANx0TK4UVZY27da}/_ssgManifest.js +0 -0
@@ -0,0 +1,1098 @@
1
+ // GSD Markdown Renderer — DB → Markdown file generation
2
+ //
3
+ // Transforms DB state into correct markdown files on disk.
4
+ // Each render function reads from DB (with disk fallback),
5
+ // patches content to match DB status, writes atomically to disk,
6
+ // stores updated content in the artifacts table, and invalidates caches.
7
+ //
8
+ // Critical invariant: rendered markdown must round-trip through
9
+ // parseRoadmap(), parsePlan(), parseSummary() in files.ts.
10
+
11
+ import { readFileSync, existsSync, mkdirSync } from "node:fs";
12
+ import { join, relative } from "node:path";
13
+ import { createRequire } from "node:module";
14
+ import {
15
+ getAllMilestones,
16
+ getMilestone,
17
+ getMilestoneSlices,
18
+ getSliceTasks,
19
+ getTask,
20
+ getSlice,
21
+ getArtifact,
22
+ insertArtifact,
23
+ } from "./gsd-db.js";
24
+ import type { MilestoneRow, SliceRow, TaskRow, ArtifactRow } from "./gsd-db.js";
25
+ import {
26
+ resolveMilestoneFile,
27
+ resolveSliceFile,
28
+ resolveSlicePath,
29
+ resolveTasksDir,
30
+ gsdRoot,
31
+ buildTaskFileName,
32
+ buildSliceFileName,
33
+ } from "./paths.js";
34
+ import { saveFile, clearParseCache } from "./files.js";
35
+ import { invalidateStateCache } from "./state.js";
36
+ import { clearPathCache } from "./paths.js";
37
+
38
+ // ─── Helpers ──────────────────────────────────────────────────────────────
39
+
40
+ /**
41
+ * Convert an absolute file path to a .gsd-relative artifact path.
42
+ * E.g. "/project/.gsd/milestones/M001/M001-ROADMAP.md" → "milestones/M001/M001-ROADMAP.md"
43
+ */
44
+ function toArtifactPath(absPath: string, basePath: string): string {
45
+ const root = gsdRoot(basePath);
46
+ const rel = relative(root, absPath);
47
+ // Normalize to forward slashes for consistent DB keys
48
+ return rel.replace(/\\/g, "/");
49
+ }
50
+
51
+ /**
52
+ * Invalidate all caches after a disk write.
53
+ */
54
+ function invalidateCaches(): void {
55
+ invalidateStateCache();
56
+ clearPathCache();
57
+ clearParseCache();
58
+ }
59
+
60
+ /**
61
+ * Load artifact content from DB first, falling back to reading from disk.
62
+ * On disk fallback, stores the content in the artifacts table for future use.
63
+ * Returns null if content is unavailable from both sources.
64
+ */
65
+ function loadArtifactContent(
66
+ artifactPath: string,
67
+ absPath: string | null,
68
+ opts: {
69
+ artifact_type: string;
70
+ milestone_id: string;
71
+ slice_id?: string;
72
+ task_id?: string;
73
+ },
74
+ ): string | null {
75
+ // Try DB first
76
+ const artifact = getArtifact(artifactPath);
77
+ if (artifact && artifact.full_content) {
78
+ return artifact.full_content;
79
+ }
80
+
81
+ // Fall back to disk
82
+ if (!absPath) {
83
+ process.stderr.write(
84
+ `markdown-renderer: artifact not found in DB or on disk: ${artifactPath}\n`,
85
+ );
86
+ return null;
87
+ }
88
+
89
+ let content: string;
90
+ try {
91
+ content = readFileSync(absPath, "utf-8");
92
+ } catch {
93
+ process.stderr.write(
94
+ `markdown-renderer: cannot read file from disk: ${absPath}\n`,
95
+ );
96
+ return null;
97
+ }
98
+
99
+ // Store in DB for future use (graceful degradation path)
100
+ try {
101
+ insertArtifact({
102
+ path: artifactPath,
103
+ artifact_type: opts.artifact_type,
104
+ milestone_id: opts.milestone_id,
105
+ slice_id: opts.slice_id ?? null,
106
+ task_id: opts.task_id ?? null,
107
+ full_content: content,
108
+ });
109
+ } catch {
110
+ // Non-fatal: we have the content, DB storage is best-effort
111
+ process.stderr.write(
112
+ `markdown-renderer: warning — failed to store disk fallback in DB: ${artifactPath}\n`,
113
+ );
114
+ }
115
+
116
+ return content;
117
+ }
118
+
119
+ /**
120
+ * Write rendered content to disk and update the artifacts table.
121
+ */
122
+ async function writeAndStore(
123
+ absPath: string,
124
+ artifactPath: string,
125
+ content: string,
126
+ opts: {
127
+ artifact_type: string;
128
+ milestone_id: string;
129
+ slice_id?: string;
130
+ task_id?: string;
131
+ },
132
+ ): Promise<void> {
133
+ await saveFile(absPath, content);
134
+
135
+ try {
136
+ insertArtifact({
137
+ path: artifactPath,
138
+ artifact_type: opts.artifact_type,
139
+ milestone_id: opts.milestone_id,
140
+ slice_id: opts.slice_id ?? null,
141
+ task_id: opts.task_id ?? null,
142
+ full_content: content,
143
+ });
144
+ } catch {
145
+ // Non-fatal: file is on disk, DB is best-effort
146
+ process.stderr.write(
147
+ `markdown-renderer: warning — failed to update artifact in DB: ${artifactPath}\n`,
148
+ );
149
+ }
150
+
151
+ invalidateCaches();
152
+ }
153
+
154
+ function renderRoadmapMarkdown(milestone: MilestoneRow, slices: SliceRow[]): string {
155
+ const lines: string[] = [];
156
+
157
+ lines.push(`# ${milestone.id}: ${milestone.title || milestone.id}`);
158
+ lines.push("");
159
+ lines.push(`**Vision:** ${milestone.vision}`);
160
+ lines.push("");
161
+
162
+ if (milestone.success_criteria.length > 0) {
163
+ lines.push("## Success Criteria");
164
+ lines.push("");
165
+ for (const criterion of milestone.success_criteria) {
166
+ lines.push(`- ${criterion}`);
167
+ }
168
+ lines.push("");
169
+ }
170
+
171
+ lines.push("## Slices");
172
+ lines.push("");
173
+ for (const slice of slices) {
174
+ const done = slice.status === "complete" ? "x" : " ";
175
+ const depends = `[${(slice.depends ?? []).join(",")}]`;
176
+ lines.push(`- [${done}] **${slice.id}: ${slice.title}** \`risk:${slice.risk}\` \`depends:${depends}\``);
177
+ lines.push(` > After this: ${slice.demo}`);
178
+ lines.push("");
179
+ }
180
+
181
+ if (milestone.boundary_map_markdown.trim()) {
182
+ lines.push("## Boundary Map");
183
+ lines.push("");
184
+ lines.push(milestone.boundary_map_markdown.trim());
185
+ lines.push("");
186
+ }
187
+
188
+ return `${lines.join("\n").trimEnd()}\n`;
189
+ }
190
+
191
+ function renderTaskPlanMarkdown(task: TaskRow): string {
192
+ const estimatedSteps = Math.max(1, task.description.trim().split(/\n+/).filter(Boolean).length || 1);
193
+ const estimatedFiles = task.files.length > 0
194
+ ? task.files.length
195
+ : task.expected_output.length > 0
196
+ ? task.expected_output.length
197
+ : task.inputs.length > 0
198
+ ? task.inputs.length
199
+ : 1;
200
+
201
+ const lines: string[] = [];
202
+ lines.push("---");
203
+ lines.push(`estimated_steps: ${estimatedSteps}`);
204
+ lines.push(`estimated_files: ${estimatedFiles}`);
205
+ lines.push("skills_used: []");
206
+ lines.push("---");
207
+ lines.push("");
208
+ lines.push(`# ${task.id}: ${task.title || task.id}`);
209
+ lines.push("");
210
+
211
+ if (task.description.trim()) {
212
+ lines.push(task.description.trim());
213
+ lines.push("");
214
+ }
215
+
216
+ lines.push("## Inputs");
217
+ lines.push("");
218
+ if (task.inputs.length > 0) {
219
+ for (const input of task.inputs) {
220
+ lines.push(`- \`${input}\``);
221
+ }
222
+ } else {
223
+ lines.push("- None specified.");
224
+ }
225
+ lines.push("");
226
+
227
+ lines.push("## Expected Output");
228
+ lines.push("");
229
+ if (task.expected_output.length > 0) {
230
+ for (const output of task.expected_output) {
231
+ lines.push(`- \`${output}\``);
232
+ }
233
+ } else if (task.files.length > 0) {
234
+ for (const file of task.files) {
235
+ lines.push(`- \`${file}\``);
236
+ }
237
+ } else {
238
+ lines.push("- Update the implementation and proof artifacts needed for this task.");
239
+ }
240
+ lines.push("");
241
+
242
+ lines.push("## Verification");
243
+ lines.push("");
244
+ lines.push(task.verify.trim() || "- Verify the task outcome with the slice-level checks.");
245
+ lines.push("");
246
+
247
+ if (task.observability_impact.trim()) {
248
+ lines.push("## Observability Impact");
249
+ lines.push("");
250
+ lines.push(task.observability_impact.trim());
251
+ lines.push("");
252
+ }
253
+
254
+ return `${lines.join("\n").trimEnd()}\n`;
255
+ }
256
+
257
+ function renderSlicePlanMarkdown(slice: SliceRow, tasks: TaskRow[]): string {
258
+ const lines: string[] = [];
259
+
260
+ lines.push(`# ${slice.id}: ${slice.title || slice.id}`);
261
+ lines.push("");
262
+ lines.push(`**Goal:** ${slice.goal}`);
263
+ lines.push(`**Demo:** ${slice.demo}`);
264
+ lines.push("");
265
+
266
+ lines.push("## Must-Haves");
267
+ lines.push("");
268
+ if (slice.success_criteria.trim()) {
269
+ for (const line of slice.success_criteria.split(/\n+/).map((entry) => entry.trim()).filter(Boolean)) {
270
+ lines.push(line.startsWith("-") ? line : `- ${line}`);
271
+ }
272
+ } else {
273
+ lines.push("- Complete the planned slice outcomes.");
274
+ }
275
+ lines.push("");
276
+
277
+ if (slice.proof_level.trim()) {
278
+ lines.push("## Proof Level");
279
+ lines.push("");
280
+ lines.push(`- This slice proves: ${slice.proof_level.trim()}`);
281
+ lines.push("");
282
+ }
283
+
284
+ if (slice.integration_closure.trim()) {
285
+ lines.push("## Integration Closure");
286
+ lines.push("");
287
+ lines.push(slice.integration_closure.trim());
288
+ lines.push("");
289
+ }
290
+
291
+ lines.push("## Verification");
292
+ lines.push("");
293
+ if (slice.observability_impact.trim()) {
294
+ const verificationLines = slice.observability_impact
295
+ .split(/\n+/)
296
+ .map((entry) => entry.trim())
297
+ .filter(Boolean);
298
+ for (const line of verificationLines) {
299
+ lines.push(line.startsWith("-") ? line : `- ${line}`);
300
+ }
301
+ } else {
302
+ lines.push("- Run the task and slice verification checks for this slice.");
303
+ }
304
+ lines.push("");
305
+
306
+ lines.push("## Tasks");
307
+ lines.push("");
308
+ for (const task of tasks) {
309
+ const done = task.status === "done" || task.status === "complete" ? "x" : " ";
310
+ const estimate = task.estimate.trim() ? ` \`est:${task.estimate.trim()}\`` : "";
311
+ lines.push(`- [${done}] **${task.id}: ${task.title || task.id}**${estimate}`);
312
+ if (task.description.trim()) {
313
+ lines.push(` ${task.description.trim()}`);
314
+ }
315
+ if (task.files.length > 0) {
316
+ lines.push(` - Files: ${task.files.map((file) => `\`${file}\``).join(", ")}`);
317
+ }
318
+ if (task.verify.trim()) {
319
+ lines.push(` - Verify: ${task.verify.trim()}`);
320
+ }
321
+ lines.push("");
322
+ }
323
+
324
+ const filesLikelyTouched = Array.from(new Set(tasks.flatMap((task) => task.files)));
325
+ if (filesLikelyTouched.length > 0) {
326
+ lines.push("## Files Likely Touched");
327
+ lines.push("");
328
+ for (const file of filesLikelyTouched) {
329
+ lines.push(`- ${file}`);
330
+ }
331
+ lines.push("");
332
+ }
333
+
334
+ return `${lines.join("\n").trimEnd()}\n`;
335
+ }
336
+
337
+ export async function renderPlanFromDb(
338
+ basePath: string,
339
+ milestoneId: string,
340
+ sliceId: string,
341
+ ): Promise<{ planPath: string; taskPlanPaths: string[]; content: string }> {
342
+ const slice = getSlice(milestoneId, sliceId);
343
+ if (!slice) {
344
+ throw new Error(`slice ${milestoneId}/${sliceId} not found`);
345
+ }
346
+
347
+ const tasks = getSliceTasks(milestoneId, sliceId);
348
+ if (tasks.length === 0) {
349
+ throw new Error(`no tasks found for ${milestoneId}/${sliceId}`);
350
+ }
351
+
352
+ const slicePath = resolveSlicePath(basePath, milestoneId, sliceId)
353
+ ?? join(gsdRoot(basePath), "milestones", milestoneId, "slices", sliceId);
354
+ const absPath = resolveSliceFile(basePath, milestoneId, sliceId, "PLAN")
355
+ ?? join(slicePath, `${sliceId}-PLAN.md`);
356
+ const artifactPath = toArtifactPath(absPath, basePath);
357
+ const content = renderSlicePlanMarkdown(slice, tasks);
358
+
359
+ await writeAndStore(absPath, artifactPath, content, {
360
+ artifact_type: "PLAN",
361
+ milestone_id: milestoneId,
362
+ slice_id: sliceId,
363
+ });
364
+
365
+ const taskPlanPaths: string[] = [];
366
+ for (const task of tasks) {
367
+ const rendered = await renderTaskPlanFromDb(basePath, milestoneId, sliceId, task.id);
368
+ taskPlanPaths.push(rendered.taskPlanPath);
369
+ }
370
+
371
+ return { planPath: absPath, taskPlanPaths, content };
372
+ }
373
+
374
+ export async function renderTaskPlanFromDb(
375
+ basePath: string,
376
+ milestoneId: string,
377
+ sliceId: string,
378
+ taskId: string,
379
+ ): Promise<{ taskPlanPath: string; content: string }> {
380
+ const task = getTask(milestoneId, sliceId, taskId);
381
+ if (!task) {
382
+ throw new Error(`task ${milestoneId}/${sliceId}/${taskId} not found`);
383
+ }
384
+
385
+ const tasksDir = resolveTasksDir(basePath, milestoneId, sliceId)
386
+ ?? join(gsdRoot(basePath), "milestones", milestoneId, "slices", sliceId, "tasks");
387
+ mkdirSync(tasksDir, { recursive: true });
388
+ const absPath = join(tasksDir, buildTaskFileName(taskId, "PLAN"));
389
+ const artifactPath = toArtifactPath(absPath, basePath);
390
+ const content = renderTaskPlanMarkdown(task);
391
+
392
+ await writeAndStore(absPath, artifactPath, content, {
393
+ artifact_type: "PLAN",
394
+ milestone_id: milestoneId,
395
+ slice_id: sliceId,
396
+ task_id: taskId,
397
+ });
398
+
399
+ return { taskPlanPath: absPath, content };
400
+ }
401
+
402
+ export async function renderRoadmapFromDb(
403
+ basePath: string,
404
+ milestoneId: string,
405
+ ): Promise<{ roadmapPath: string; content: string }> {
406
+ const milestone = getMilestone(milestoneId);
407
+ if (!milestone) {
408
+ throw new Error(`milestone ${milestoneId} not found`);
409
+ }
410
+
411
+ const slices = getMilestoneSlices(milestoneId);
412
+ const absPath = resolveMilestoneFile(basePath, milestoneId, "ROADMAP") ??
413
+ join(gsdRoot(basePath), "milestones", milestoneId, `${milestoneId}-ROADMAP.md`);
414
+ const artifactPath = toArtifactPath(absPath, basePath);
415
+ const content = renderRoadmapMarkdown(milestone, slices);
416
+
417
+ await writeAndStore(absPath, artifactPath, content, {
418
+ artifact_type: "ROADMAP",
419
+ milestone_id: milestoneId,
420
+ });
421
+
422
+ return { roadmapPath: absPath, content };
423
+ }
424
+
425
+ // ─── Roadmap Checkbox Rendering ───────────────────────────────────────────
426
+
427
+ /**
428
+ * Render roadmap checkbox states from DB.
429
+ *
430
+ * For each slice in the milestone, sets [x] if status === 'complete',
431
+ * [ ] otherwise. Handles bidirectional updates (can uncheck previously
432
+ * checked slices if DB says pending).
433
+ *
434
+ * @returns true if the roadmap was written, false on skip/error
435
+ */
436
+ export async function renderRoadmapCheckboxes(
437
+ basePath: string,
438
+ milestoneId: string,
439
+ ): Promise<boolean> {
440
+ const slices = getMilestoneSlices(milestoneId);
441
+ if (slices.length === 0) {
442
+ process.stderr.write(
443
+ `markdown-renderer: no slices found for milestone ${milestoneId}\n`,
444
+ );
445
+ return false;
446
+ }
447
+
448
+ const absPath = resolveMilestoneFile(basePath, milestoneId, "ROADMAP");
449
+ const artifactPath = absPath ? toArtifactPath(absPath, basePath) : null;
450
+
451
+ // Load content from DB (with disk fallback)
452
+ let content: string | null = null;
453
+ if (artifactPath) {
454
+ content = loadArtifactContent(artifactPath, absPath, {
455
+ artifact_type: "ROADMAP",
456
+ milestone_id: milestoneId,
457
+ });
458
+ }
459
+
460
+ if (!content) {
461
+ process.stderr.write(
462
+ `markdown-renderer: no roadmap content available for ${milestoneId}\n`,
463
+ );
464
+ return false;
465
+ }
466
+
467
+ // Apply checkbox patches for each slice
468
+ let updated = content;
469
+ for (const slice of slices) {
470
+ const isDone = slice.status === "complete";
471
+ const sid = slice.id;
472
+
473
+ if (isDone) {
474
+ // Set [x]: replace "- [ ] **S01:" with "- [x] **S01:"
475
+ updated = updated.replace(
476
+ new RegExp(`^(\\s*-\\s+)\\[ \\]\\s+\\*\\*${sid}:`, "m"),
477
+ `$1[x] **${sid}:`,
478
+ );
479
+ } else {
480
+ // Set [ ]: replace "- [x] **S01:" with "- [ ] **S01:"
481
+ updated = updated.replace(
482
+ new RegExp(`^(\\s*-\\s+)\\[x\\]\\s+\\*\\*${sid}:`, "mi"),
483
+ `$1[ ] **${sid}:`,
484
+ );
485
+ }
486
+ }
487
+
488
+ if (!absPath) return false;
489
+
490
+ await writeAndStore(absPath, artifactPath!, updated, {
491
+ artifact_type: "ROADMAP",
492
+ milestone_id: milestoneId,
493
+ });
494
+
495
+ return true;
496
+ }
497
+
498
+ // ─── Plan Checkbox Rendering ──────────────────────────────────────────────
499
+
500
+ /**
501
+ * Render plan checkbox states from DB.
502
+ *
503
+ * For each task in the slice, sets [x] if status === 'done',
504
+ * [ ] otherwise. Bidirectional.
505
+ *
506
+ * @returns true if the plan was written, false on skip/error
507
+ */
508
+ export async function renderPlanCheckboxes(
509
+ basePath: string,
510
+ milestoneId: string,
511
+ sliceId: string,
512
+ ): Promise<boolean> {
513
+ const tasks = getSliceTasks(milestoneId, sliceId);
514
+ if (tasks.length === 0) {
515
+ process.stderr.write(
516
+ `markdown-renderer: no tasks found for ${milestoneId}/${sliceId}\n`,
517
+ );
518
+ return false;
519
+ }
520
+
521
+ const absPath = resolveSliceFile(basePath, milestoneId, sliceId, "PLAN");
522
+ const artifactPath = absPath ? toArtifactPath(absPath, basePath) : null;
523
+
524
+ let content: string | null = null;
525
+ if (artifactPath) {
526
+ content = loadArtifactContent(artifactPath, absPath, {
527
+ artifact_type: "PLAN",
528
+ milestone_id: milestoneId,
529
+ slice_id: sliceId,
530
+ });
531
+ }
532
+
533
+ if (!content) {
534
+ process.stderr.write(
535
+ `markdown-renderer: no plan content available for ${milestoneId}/${sliceId}\n`,
536
+ );
537
+ return false;
538
+ }
539
+
540
+ // Apply checkbox patches for each task
541
+ let updated = content;
542
+ for (const task of tasks) {
543
+ const isDone = task.status === "done" || task.status === "complete";
544
+ const tid = task.id;
545
+
546
+ if (isDone) {
547
+ // Set [x]
548
+ updated = updated.replace(
549
+ new RegExp(`^(\\s*-\\s+)\\[ \\]\\s+\\*\\*${tid}:`, "m"),
550
+ `$1[x] **${tid}:`,
551
+ );
552
+ } else {
553
+ // Set [ ]
554
+ updated = updated.replace(
555
+ new RegExp(`^(\\s*-\\s+)\\[x\\]\\s+\\*\\*${tid}:`, "mi"),
556
+ `$1[ ] **${tid}:`,
557
+ );
558
+ }
559
+ }
560
+
561
+ if (!absPath) return false;
562
+
563
+ await writeAndStore(absPath, artifactPath!, updated, {
564
+ artifact_type: "PLAN",
565
+ milestone_id: milestoneId,
566
+ slice_id: sliceId,
567
+ });
568
+
569
+ return true;
570
+ }
571
+
572
+ // ─── Task Summary Rendering ───────────────────────────────────────────────
573
+
574
+ /**
575
+ * Render a task summary from DB to disk.
576
+ * Reads full_summary_md from the tasks table and writes it to the appropriate file.
577
+ *
578
+ * @returns true if the summary was written, false on skip/error
579
+ */
580
+ export async function renderTaskSummary(
581
+ basePath: string,
582
+ milestoneId: string,
583
+ sliceId: string,
584
+ taskId: string,
585
+ ): Promise<boolean> {
586
+ const task = getTask(milestoneId, sliceId, taskId);
587
+ if (!task || !task.full_summary_md) {
588
+ return false; // No summary to render — skip silently
589
+ }
590
+
591
+ // Resolve the tasks directory, creating path if needed
592
+ const slicePath = resolveSlicePath(basePath, milestoneId, sliceId);
593
+ if (!slicePath) {
594
+ process.stderr.write(
595
+ `markdown-renderer: cannot resolve slice path for ${milestoneId}/${sliceId}\n`,
596
+ );
597
+ return false;
598
+ }
599
+
600
+ const tasksDir = join(slicePath, "tasks");
601
+ const fileName = buildTaskFileName(taskId, "SUMMARY");
602
+ const absPath = join(tasksDir, fileName);
603
+ const artifactPath = toArtifactPath(absPath, basePath);
604
+
605
+ await writeAndStore(absPath, artifactPath, task.full_summary_md, {
606
+ artifact_type: "SUMMARY",
607
+ milestone_id: milestoneId,
608
+ slice_id: sliceId,
609
+ task_id: taskId,
610
+ });
611
+
612
+ return true;
613
+ }
614
+
615
+ // ─── Slice Summary Rendering ──────────────────────────────────────────────
616
+
617
+ /**
618
+ * Render slice summary and UAT files from DB to disk.
619
+ * Reads full_summary_md and full_uat_md from the slices table.
620
+ *
621
+ * @returns true if at least one file was written, false on skip/error
622
+ */
623
+ export async function renderSliceSummary(
624
+ basePath: string,
625
+ milestoneId: string,
626
+ sliceId: string,
627
+ ): Promise<boolean> {
628
+ const slice = getSlice(milestoneId, sliceId);
629
+ if (!slice) {
630
+ return false; // No slice data — skip silently
631
+ }
632
+
633
+ const slicePath = resolveSlicePath(basePath, milestoneId, sliceId);
634
+ if (!slicePath) {
635
+ process.stderr.write(
636
+ `markdown-renderer: cannot resolve slice path for ${milestoneId}/${sliceId}\n`,
637
+ );
638
+ return false;
639
+ }
640
+
641
+ let wrote = false;
642
+
643
+ // Write SUMMARY
644
+ if (slice.full_summary_md) {
645
+ const summaryName = buildSliceFileName(sliceId, "SUMMARY");
646
+ const summaryAbs = join(slicePath, summaryName);
647
+ const summaryArtifact = toArtifactPath(summaryAbs, basePath);
648
+
649
+ await writeAndStore(summaryAbs, summaryArtifact, slice.full_summary_md, {
650
+ artifact_type: "SUMMARY",
651
+ milestone_id: milestoneId,
652
+ slice_id: sliceId,
653
+ });
654
+ wrote = true;
655
+ }
656
+
657
+ // Write UAT
658
+ if (slice.full_uat_md) {
659
+ const uatName = buildSliceFileName(sliceId, "UAT");
660
+ const uatAbs = join(slicePath, uatName);
661
+ const uatArtifact = toArtifactPath(uatAbs, basePath);
662
+
663
+ await writeAndStore(uatAbs, uatArtifact, slice.full_uat_md, {
664
+ artifact_type: "UAT",
665
+ milestone_id: milestoneId,
666
+ slice_id: sliceId,
667
+ });
668
+ wrote = true;
669
+ }
670
+
671
+ return wrote;
672
+ }
673
+
674
+ // ─── Render All From DB ───────────────────────────────────────────────────
675
+
676
+ export interface RenderAllResult {
677
+ rendered: number;
678
+ skipped: number;
679
+ errors: string[];
680
+ }
681
+
682
+ /**
683
+ * Iterate all milestones, slices, and tasks in the DB and render each artifact to disk.
684
+ * Returns structured result for inspection.
685
+ */
686
+ export async function renderAllFromDb(basePath: string): Promise<RenderAllResult> {
687
+ const result: RenderAllResult = { rendered: 0, skipped: 0, errors: [] };
688
+ const milestones = getAllMilestones();
689
+
690
+ for (const milestone of milestones) {
691
+ // Render roadmap checkboxes
692
+ try {
693
+ const ok = await renderRoadmapCheckboxes(basePath, milestone.id);
694
+ if (ok) result.rendered++;
695
+ else result.skipped++;
696
+ } catch (err) {
697
+ result.errors.push(`roadmap ${milestone.id}: ${(err as Error).message}`);
698
+ }
699
+
700
+ // Iterate slices
701
+ const slices = getMilestoneSlices(milestone.id);
702
+ for (const slice of slices) {
703
+ // Render plan checkboxes
704
+ try {
705
+ const ok = await renderPlanCheckboxes(basePath, milestone.id, slice.id);
706
+ if (ok) result.rendered++;
707
+ else result.skipped++;
708
+ } catch (err) {
709
+ result.errors.push(
710
+ `plan ${milestone.id}/${slice.id}: ${(err as Error).message}`,
711
+ );
712
+ }
713
+
714
+ // Render slice summary
715
+ try {
716
+ const ok = await renderSliceSummary(basePath, milestone.id, slice.id);
717
+ if (ok) result.rendered++;
718
+ else result.skipped++;
719
+ } catch (err) {
720
+ result.errors.push(
721
+ `slice summary ${milestone.id}/${slice.id}: ${(err as Error).message}`,
722
+ );
723
+ }
724
+
725
+ // Iterate tasks
726
+ const tasks = getSliceTasks(milestone.id, slice.id);
727
+ for (const task of tasks) {
728
+ try {
729
+ const ok = await renderTaskSummary(
730
+ basePath,
731
+ milestone.id,
732
+ slice.id,
733
+ task.id,
734
+ );
735
+ if (ok) result.rendered++;
736
+ else result.skipped++;
737
+ } catch (err) {
738
+ result.errors.push(
739
+ `task summary ${milestone.id}/${slice.id}/${task.id}: ${(err as Error).message}`,
740
+ );
741
+ }
742
+ }
743
+ }
744
+ }
745
+
746
+ return result;
747
+ }
748
+
749
+ // ─── Stale Detection ──────────────────────────────────────────────────────
750
+
751
+ export interface StaleEntry {
752
+ path: string;
753
+ reason: string;
754
+ }
755
+
756
+ /**
757
+ * Detect stale renders by comparing DB state against file content.
758
+ *
759
+ * Checks:
760
+ * 1. Roadmap checkbox states vs DB slice statuses
761
+ * 2. Plan checkbox states vs DB task statuses
762
+ * 3. Missing SUMMARY.md files for complete tasks with full_summary_md
763
+ * 4. Missing SUMMARY.md/UAT.md files for complete slices with content
764
+ *
765
+ * Returns a list of stale entries with file path and reason.
766
+ * Logs to stderr when stale files are detected.
767
+ */
768
+ export function detectStaleRenders(basePath: string): StaleEntry[] {
769
+ // Lazy-load parsers — intentional disk-vs-DB comparison requires parsers
770
+ const _require = createRequire(import.meta.url);
771
+ let parseRoadmap: Function, parsePlan: Function;
772
+ try {
773
+ const m = _require("./parsers-legacy.ts");
774
+ parseRoadmap = m.parseRoadmap; parsePlan = m.parsePlan;
775
+ } catch {
776
+ const m = _require("./parsers-legacy.js");
777
+ parseRoadmap = m.parseRoadmap; parsePlan = m.parsePlan;
778
+ }
779
+
780
+ const stale: StaleEntry[] = [];
781
+ const milestones = getAllMilestones();
782
+
783
+ for (const milestone of milestones) {
784
+ const slices = getMilestoneSlices(milestone.id);
785
+
786
+ // ── Check roadmap checkbox state ──────────────────────────────────
787
+ const roadmapPath = resolveMilestoneFile(basePath, milestone.id, "ROADMAP");
788
+ if (roadmapPath && existsSync(roadmapPath)) {
789
+ try {
790
+ const content = readFileSync(roadmapPath, "utf-8");
791
+ const parsed = parseRoadmap(content);
792
+
793
+ for (const slice of slices) {
794
+ const isCompleteInDb = slice.status === "complete";
795
+ const roadmapSlice = parsed.slices.find((s: { id: string }) => s.id === slice.id);
796
+ if (!roadmapSlice) continue;
797
+
798
+ if (isCompleteInDb && !roadmapSlice.done) {
799
+ stale.push({
800
+ path: roadmapPath,
801
+ reason: `${slice.id} is complete in DB but unchecked in roadmap`,
802
+ });
803
+ } else if (!isCompleteInDb && roadmapSlice.done) {
804
+ stale.push({
805
+ path: roadmapPath,
806
+ reason: `${slice.id} is not complete in DB but checked in roadmap`,
807
+ });
808
+ }
809
+ }
810
+ } catch {
811
+ // Can't parse roadmap — skip silently
812
+ }
813
+ }
814
+
815
+ // ── Check plan checkbox state and summaries for each slice ────────
816
+ for (const slice of slices) {
817
+ const tasks = getSliceTasks(milestone.id, slice.id);
818
+
819
+ // Check plan checkboxes
820
+ const planPath = resolveSliceFile(basePath, milestone.id, slice.id, "PLAN");
821
+ if (planPath && existsSync(planPath)) {
822
+ try {
823
+ const content = readFileSync(planPath, "utf-8");
824
+ const parsed = parsePlan(content);
825
+
826
+ for (const task of tasks) {
827
+ const isDoneInDb = task.status === "done" || task.status === "complete";
828
+ const planTask = parsed.tasks.find((t: { id: string }) => t.id === task.id);
829
+ if (!planTask) continue;
830
+
831
+ if (isDoneInDb && !planTask.done) {
832
+ stale.push({
833
+ path: planPath,
834
+ reason: `${task.id} is done in DB but unchecked in plan`,
835
+ });
836
+ } else if (!isDoneInDb && planTask.done) {
837
+ stale.push({
838
+ path: planPath,
839
+ reason: `${task.id} is not done in DB but checked in plan`,
840
+ });
841
+ }
842
+ }
843
+ } catch {
844
+ // Can't parse plan — skip silently
845
+ }
846
+ }
847
+
848
+ // Check missing task summary files
849
+ for (const task of tasks) {
850
+ if ((task.status === "done" || task.status === "complete") && task.full_summary_md) {
851
+ const slicePath = resolveSlicePath(basePath, milestone.id, slice.id);
852
+ if (slicePath) {
853
+ const tasksDir = join(slicePath, "tasks");
854
+ const fileName = buildTaskFileName(task.id, "SUMMARY");
855
+ const summaryAbsPath = join(tasksDir, fileName);
856
+
857
+ if (!existsSync(summaryAbsPath)) {
858
+ stale.push({
859
+ path: summaryAbsPath,
860
+ reason: `${task.id} is complete with summary in DB but SUMMARY.md missing on disk`,
861
+ });
862
+ }
863
+ }
864
+ }
865
+ }
866
+
867
+ // Check missing slice summary/UAT files
868
+ const sliceRow = getSlice(milestone.id, slice.id);
869
+ if (sliceRow && sliceRow.status === "complete") {
870
+ const slicePath = resolveSlicePath(basePath, milestone.id, slice.id);
871
+ if (slicePath) {
872
+ if (sliceRow.full_summary_md) {
873
+ const summaryName = buildSliceFileName(slice.id, "SUMMARY");
874
+ const summaryAbsPath = join(slicePath, summaryName);
875
+ if (!existsSync(summaryAbsPath)) {
876
+ stale.push({
877
+ path: summaryAbsPath,
878
+ reason: `${slice.id} is complete with summary in DB but SUMMARY.md missing on disk`,
879
+ });
880
+ }
881
+ }
882
+
883
+ if (sliceRow.full_uat_md) {
884
+ const uatName = buildSliceFileName(slice.id, "UAT");
885
+ const uatAbsPath = join(slicePath, uatName);
886
+ if (!existsSync(uatAbsPath)) {
887
+ stale.push({
888
+ path: uatAbsPath,
889
+ reason: `${slice.id} is complete with UAT in DB but UAT.md missing on disk`,
890
+ });
891
+ }
892
+ }
893
+ }
894
+ }
895
+ }
896
+ }
897
+
898
+ if (stale.length > 0) {
899
+ process.stderr.write(
900
+ `markdown-renderer: detected ${stale.length} stale render(s):\n`,
901
+ );
902
+ for (const entry of stale) {
903
+ process.stderr.write(` - ${entry.path}: ${entry.reason}\n`);
904
+ }
905
+ }
906
+
907
+ return stale;
908
+ }
909
+
910
+ // ─── Stale Repair ─────────────────────────────────────────────────────────
911
+
912
+ /**
913
+ * Repair all stale renders detected by `detectStaleRenders()`.
914
+ *
915
+ * For each stale entry, calls the appropriate render function:
916
+ * - Roadmap checkbox mismatches → renderRoadmapCheckboxes()
917
+ * - Plan checkbox mismatches → renderPlanCheckboxes()
918
+ * - Missing task summaries → renderTaskSummary()
919
+ * - Missing slice summaries/UATs → renderSliceSummary()
920
+ *
921
+ * Idempotent: calling twice with no DB changes produces zero repairs on the second call.
922
+ *
923
+ * @returns the number of files repaired
924
+ */
925
+ export async function repairStaleRenders(basePath: string): Promise<number> {
926
+ const staleEntries = detectStaleRenders(basePath);
927
+ if (staleEntries.length === 0) return 0;
928
+
929
+ // Deduplicate: a single roadmap/plan file might appear multiple times
930
+ // (once per mismatched checkbox). We only need to re-render it once.
931
+ const repairedPaths = new Set<string>();
932
+ let repairCount = 0;
933
+
934
+ for (const entry of staleEntries) {
935
+ if (repairedPaths.has(entry.path)) continue;
936
+ // Normalize path separators for cross-platform regex matching
937
+ const normPath = entry.path.replace(/\\/g, "/");
938
+
939
+ try {
940
+ // Determine repair action from the reason
941
+ if (entry.reason.includes("in roadmap")) {
942
+ // Roadmap checkbox mismatch — extract milestone ID from path
943
+ const milestoneMatch = normPath.match(/milestones\/([^/]+)\//);
944
+ if (milestoneMatch) {
945
+ const ok = await renderRoadmapCheckboxes(basePath, milestoneMatch[1]);
946
+ if (ok) {
947
+ repairedPaths.add(entry.path);
948
+ repairCount++;
949
+ }
950
+ }
951
+ } else if (entry.reason.includes("in plan")) {
952
+ // Plan checkbox mismatch — extract milestone + slice IDs from path
953
+ const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
954
+ if (pathMatch) {
955
+ const ok = await renderPlanCheckboxes(basePath, pathMatch[1], pathMatch[2]);
956
+ if (ok) {
957
+ repairedPaths.add(entry.path);
958
+ repairCount++;
959
+ }
960
+ }
961
+ } else if (entry.reason.includes("SUMMARY.md missing") && entry.reason.match(/^T\d+/)) {
962
+ // Missing task summary — extract IDs from path
963
+ const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\/tasks\//);
964
+ const taskMatch = entry.reason.match(/^(T\d+)/);
965
+ if (pathMatch && taskMatch) {
966
+ const ok = await renderTaskSummary(basePath, pathMatch[1], pathMatch[2], taskMatch[1]);
967
+ if (ok) {
968
+ repairedPaths.add(entry.path);
969
+ repairCount++;
970
+ }
971
+ }
972
+ } else if (entry.reason.includes("SUMMARY.md missing") && entry.reason.match(/^S\d+/)) {
973
+ // Missing slice summary — extract IDs from path
974
+ const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
975
+ if (pathMatch) {
976
+ const ok = await renderSliceSummary(basePath, pathMatch[1], pathMatch[2]);
977
+ if (ok) {
978
+ repairedPaths.add(entry.path);
979
+ repairCount++;
980
+ }
981
+ }
982
+ } else if (entry.reason.includes("UAT.md missing")) {
983
+ // Missing slice UAT — renderSliceSummary handles both SUMMARY + UAT
984
+ const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
985
+ if (pathMatch) {
986
+ const ok = await renderSliceSummary(basePath, pathMatch[1], pathMatch[2]);
987
+ if (ok) {
988
+ repairedPaths.add(entry.path);
989
+ repairCount++;
990
+ }
991
+ }
992
+ }
993
+ } catch (err) {
994
+ process.stderr.write(
995
+ `markdown-renderer: repair failed for ${entry.path}: ${(err as Error).message}\n`,
996
+ );
997
+ }
998
+ }
999
+
1000
+ if (repairCount > 0) {
1001
+ process.stderr.write(
1002
+ `markdown-renderer: repaired ${repairCount} stale render(s)\n`,
1003
+ );
1004
+ }
1005
+
1006
+ return repairCount;
1007
+ }
1008
+
1009
+ // ─── Replan & Assessment Renderers ────────────────────────────────────────
1010
+
1011
+ export interface ReplanData {
1012
+ blockerTaskId: string;
1013
+ blockerDescription: string;
1014
+ whatChanged: string;
1015
+ }
1016
+
1017
+ export interface AssessmentData {
1018
+ verdict: string;
1019
+ assessment: string;
1020
+ completedSliceId?: string;
1021
+ }
1022
+
1023
+ export async function renderReplanFromDb(
1024
+ basePath: string,
1025
+ milestoneId: string,
1026
+ sliceId: string,
1027
+ replanData: ReplanData,
1028
+ ): Promise<{ replanPath: string; content: string }> {
1029
+ const slicePath = resolveSlicePath(basePath, milestoneId, sliceId)
1030
+ ?? join(gsdRoot(basePath), "milestones", milestoneId, "slices", sliceId);
1031
+ const absPath = join(slicePath, `${sliceId}-REPLAN.md`);
1032
+ const artifactPath = toArtifactPath(absPath, basePath);
1033
+
1034
+ const lines: string[] = [];
1035
+ lines.push(`# ${sliceId} Replan`);
1036
+ lines.push("");
1037
+ lines.push(`**Milestone:** ${milestoneId}`);
1038
+ lines.push(`**Slice:** ${sliceId}`);
1039
+ lines.push(`**Blocker Task:** ${replanData.blockerTaskId}`);
1040
+ lines.push(`**Created:** ${new Date().toISOString()}`);
1041
+ lines.push("");
1042
+ lines.push("## Blocker Description");
1043
+ lines.push("");
1044
+ lines.push(replanData.blockerDescription);
1045
+ lines.push("");
1046
+ lines.push("## What Changed");
1047
+ lines.push("");
1048
+ lines.push(replanData.whatChanged);
1049
+ lines.push("");
1050
+
1051
+ const content = `${lines.join("\n").trimEnd()}\n`;
1052
+
1053
+ await writeAndStore(absPath, artifactPath, content, {
1054
+ artifact_type: "REPLAN",
1055
+ milestone_id: milestoneId,
1056
+ slice_id: sliceId,
1057
+ });
1058
+
1059
+ return { replanPath: absPath, content };
1060
+ }
1061
+
1062
+ export async function renderAssessmentFromDb(
1063
+ basePath: string,
1064
+ milestoneId: string,
1065
+ sliceId: string,
1066
+ assessmentData: AssessmentData,
1067
+ ): Promise<{ assessmentPath: string; content: string }> {
1068
+ const slicePath = resolveSlicePath(basePath, milestoneId, sliceId)
1069
+ ?? join(gsdRoot(basePath), "milestones", milestoneId, "slices", sliceId);
1070
+ const absPath = join(slicePath, `${sliceId}-ASSESSMENT.md`);
1071
+ const artifactPath = toArtifactPath(absPath, basePath);
1072
+
1073
+ const lines: string[] = [];
1074
+ lines.push(`# ${sliceId} Assessment`);
1075
+ lines.push("");
1076
+ lines.push(`**Milestone:** ${milestoneId}`);
1077
+ lines.push(`**Slice:** ${sliceId}`);
1078
+ if (assessmentData.completedSliceId) {
1079
+ lines.push(`**Completed Slice:** ${assessmentData.completedSliceId}`);
1080
+ }
1081
+ lines.push(`**Verdict:** ${assessmentData.verdict}`);
1082
+ lines.push(`**Created:** ${new Date().toISOString()}`);
1083
+ lines.push("");
1084
+ lines.push("## Assessment");
1085
+ lines.push("");
1086
+ lines.push(assessmentData.assessment);
1087
+ lines.push("");
1088
+
1089
+ const content = `${lines.join("\n").trimEnd()}\n`;
1090
+
1091
+ await writeAndStore(absPath, artifactPath, content, {
1092
+ artifact_type: "ASSESSMENT",
1093
+ milestone_id: milestoneId,
1094
+ slice_id: sliceId,
1095
+ });
1096
+
1097
+ return { assessmentPath: absPath, content };
1098
+ }