gsd-pi 2.44.0-dev.848dd4c β†’ 2.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (298) hide show
  1. package/README.md +12 -30
  2. package/dist/resources/extensions/gsd/auto-start.js +0 -10
  3. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +0 -5
  4. package/dist/web/standalone/.next/BUILD_ID +1 -1
  5. package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
  6. package/dist/web/standalone/.next/build-manifest.json +3 -3
  7. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  8. package/dist/web/standalone/.next/required-server-files.json +3 -3
  9. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  10. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  11. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  12. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  13. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  14. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  15. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  16. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  17. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  18. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  19. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  20. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  21. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  22. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  23. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  24. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  25. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  26. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  30. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  31. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  32. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  33. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  34. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  35. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  36. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  37. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  38. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  39. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  40. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  41. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  42. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  43. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  44. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  45. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  46. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  47. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  48. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  49. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  50. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  51. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  52. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  53. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  54. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  55. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  56. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  57. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  58. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  59. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  60. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  61. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  62. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  63. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  64. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  65. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  66. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  67. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  74. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  80. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  94. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  96. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  98. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  100. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/index.html +1 -1
  110. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  111. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  112. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  113. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  115. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/page.js +2 -2
  117. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  119. package/dist/web/standalone/.next/server/chunks/229.js +1 -1
  120. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  121. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/middleware.js +2 -2
  123. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  125. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  126. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  127. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  128. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js β†’ page-2f24283c162b6ab3.js} +1 -1
  129. package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js β†’ layout-9ecfd95f343793f0.js} +1 -1
  130. package/dist/web/standalone/.next/static/chunks/app/page-7e9530a7122506c5.js +1 -0
  131. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
  132. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
  133. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  134. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  135. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  136. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  137. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  138. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  139. package/dist/web/standalone/server.js +1 -1
  140. package/package.json +1 -1
  141. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +8 -6
  142. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  143. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +26 -24
  144. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  145. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +48 -29
  146. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  147. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +44 -34
  148. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  149. package/packages/pi-coding-agent/dist/core/session-manager.test.js +34 -30
  150. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  151. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +12 -10
  152. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  153. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +47 -43
  154. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  155. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  156. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  157. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +43 -31
  158. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +45 -40
  159. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  160. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  161. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  162. package/src/resources/extensions/gsd/auto-start.ts +0 -14
  163. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +0 -8
  164. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  165. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +16 -14
  166. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +57 -43
  167. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +13 -11
  168. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +523 -465
  169. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +75 -73
  170. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +56 -34
  171. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +656 -533
  172. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +143 -165
  173. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +52 -29
  174. package/src/resources/extensions/gsd/tests/captures.test.ts +176 -148
  175. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +33 -32
  176. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +143 -141
  177. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  178. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  179. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +59 -38
  180. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +263 -228
  181. package/src/resources/extensions/gsd/tests/complete-task.test.ts +302 -250
  182. package/src/resources/extensions/gsd/tests/context-store.test.ts +367 -354
  183. package/src/resources/extensions/gsd/tests/continue-here.test.ts +72 -68
  184. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +106 -92
  185. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +35 -27
  186. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +237 -220
  187. package/src/resources/extensions/gsd/tests/db-writer.test.ts +420 -390
  188. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +92 -76
  189. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +83 -68
  190. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +183 -152
  191. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +101 -78
  192. package/src/resources/extensions/gsd/tests/derive-state.test.ts +227 -192
  193. package/src/resources/extensions/gsd/tests/detection.test.ts +278 -232
  194. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +34 -30
  195. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +180 -164
  196. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +49 -43
  197. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +32 -28
  198. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +29 -27
  199. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +38 -34
  200. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +75 -54
  201. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +32 -21
  202. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +97 -72
  203. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +44 -38
  204. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +145 -104
  205. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +106 -84
  206. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +60 -54
  207. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +93 -72
  208. package/src/resources/extensions/gsd/tests/doctor.test.ts +134 -104
  209. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +131 -123
  210. package/src/resources/extensions/gsd/tests/exit-command.test.ts +24 -20
  211. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +57 -48
  212. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +7 -5
  213. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +42 -30
  214. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +206 -198
  215. package/src/resources/extensions/gsd/tests/git-locale.test.ts +27 -13
  216. package/src/resources/extensions/gsd/tests/git-service.test.ts +388 -285
  217. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +39 -31
  218. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +69 -63
  219. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +264 -255
  220. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +119 -108
  221. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +103 -81
  222. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +262 -229
  223. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  224. package/src/resources/extensions/gsd/tests/health-widget.test.ts +37 -29
  225. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +102 -81
  226. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +18 -16
  227. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +46 -41
  228. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +53 -42
  229. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +91 -75
  230. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
  231. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +194 -150
  232. package/src/resources/extensions/gsd/tests/md-importer.test.ts +125 -101
  233. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +54 -45
  234. package/src/resources/extensions/gsd/tests/memory-store.test.ts +93 -80
  235. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +66 -57
  236. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +93 -83
  237. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +170 -161
  238. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +141 -125
  239. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +131 -107
  240. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +96 -87
  241. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +164 -125
  242. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +94 -81
  243. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +36 -35
  244. package/src/resources/extensions/gsd/tests/overrides.test.ts +106 -99
  245. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +47 -40
  246. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +28 -25
  247. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +83 -66
  248. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +77 -54
  249. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +115 -68
  250. package/src/resources/extensions/gsd/tests/parsers.test.ts +611 -546
  251. package/src/resources/extensions/gsd/tests/paths.test.ts +87 -72
  252. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +117 -77
  253. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  254. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +119 -93
  255. package/src/resources/extensions/gsd/tests/queue-order.test.ts +82 -70
  256. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +55 -42
  257. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +73 -45
  258. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +38 -28
  259. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +80 -73
  260. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +74 -71
  261. package/src/resources/extensions/gsd/tests/requirements.test.ts +75 -70
  262. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +66 -44
  263. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +181 -114
  264. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +65 -63
  265. package/src/resources/extensions/gsd/tests/run-uat.test.ts +128 -66
  266. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +25 -18
  267. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +44 -37
  268. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +26 -19
  269. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +8 -6
  270. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +28 -22
  271. package/src/resources/extensions/gsd/tests/token-savings.test.ts +56 -54
  272. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +25 -23
  273. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +11 -9
  274. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +82 -66
  275. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +47 -46
  276. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +22 -20
  277. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +86 -84
  278. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +43 -41
  279. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +96 -94
  280. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +13 -11
  281. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +29 -27
  282. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +52 -50
  283. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +13 -10
  284. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +18 -14
  285. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +39 -38
  286. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +21 -17
  287. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +30 -25
  288. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +37 -30
  289. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +22 -15
  290. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +66 -59
  291. package/src/resources/extensions/gsd/tests/worktree.test.ts +50 -44
  292. package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +0 -1
  293. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
  294. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
  295. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +0 -100
  296. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +0 -63
  297. /package/dist/web/standalone/.next/static/{-zps1Q9mQmioAKLcQiCr8 β†’ mgkxN0mGP6gSUmGPEzbk_}/_buildManifest.js +0 -0
  298. /package/dist/web/standalone/.next/static/{-zps1Q9mQmioAKLcQiCr8 β†’ mgkxN0mGP6gSUmGPEzbk_}/_ssgManifest.js +0 -0
@@ -1,3 +1,4 @@
1
+ import { createTestContext } from './test-helpers.ts';
1
2
  import * as path from 'node:path';
2
3
  import * as os from 'node:os';
3
4
  import * as fs from 'node:fs';
@@ -37,8 +38,8 @@ import {
37
38
  } from '../files.ts';
38
39
  import { clearPathCache, _clearGsdRootCache } from '../paths.ts';
39
40
  import { invalidateStateCache } from '../state.ts';
40
- import { describe, test, beforeEach, afterEach } from 'node:test';
41
- import assert from 'node:assert/strict';
41
+
42
+ const { assertEq, assertTrue, assertMatch, report } = createTestContext();
42
43
 
43
44
  // ═══════════════════════════════════════════════════════════════════════════
44
45
  // Helpers
@@ -173,27 +174,29 @@ function makeTaskSummaryContent(taskId: string): string {
173
174
  // DB Accessor Tests
174
175
  // ═══════════════════════════════════════════════════════════════════════════
175
176
 
176
- test('── markdown-renderer: DB accessor basics ──', () => {
177
+ console.log('\n── markdown-renderer: DB accessor basics ──');
178
+
179
+ {
177
180
  openDatabase(':memory:');
178
181
 
179
182
  // getAllMilestones β€” empty
180
183
  const empty = getAllMilestones();
181
- assert.deepStrictEqual(empty.length, 0, 'getAllMilestones returns empty when no milestones');
184
+ assertEq(empty.length, 0, 'getAllMilestones returns empty when no milestones');
182
185
 
183
186
  // Insert and retrieve
184
187
  insertMilestone({ id: 'M001', title: 'Test MS', status: 'active' });
185
188
  insertMilestone({ id: 'M002', title: 'Second MS', status: 'active' });
186
189
 
187
190
  const all = getAllMilestones();
188
- assert.deepStrictEqual(all.length, 2, 'getAllMilestones returns 2 milestones');
189
- assert.deepStrictEqual(all[0].id, 'M001', 'first milestone is M001');
190
- assert.deepStrictEqual(all[1].id, 'M002', 'second milestone is M002');
191
- assert.deepStrictEqual(all[0].title, 'Test MS', 'milestone title correct');
192
- assert.deepStrictEqual(all[0].status, 'active', 'milestone status correct');
191
+ assertEq(all.length, 2, 'getAllMilestones returns 2 milestones');
192
+ assertEq(all[0].id, 'M001', 'first milestone is M001');
193
+ assertEq(all[1].id, 'M002', 'second milestone is M002');
194
+ assertEq(all[0].title, 'Test MS', 'milestone title correct');
195
+ assertEq(all[0].status, 'active', 'milestone status correct');
193
196
 
194
197
  // getMilestoneSlices β€” empty
195
198
  const noSlices = getMilestoneSlices('M001');
196
- assert.deepStrictEqual(noSlices.length, 0, 'getMilestoneSlices returns empty when no slices');
199
+ assertEq(noSlices.length, 0, 'getMilestoneSlices returns empty when no slices');
197
200
 
198
201
  // Insert slices and retrieve
199
202
  insertSlice({ id: 'S01', milestoneId: 'M001', title: 'Slice 1', status: 'complete' });
@@ -201,24 +204,26 @@ test('── markdown-renderer: DB accessor basics ──', () => {
201
204
  insertSlice({ id: 'S01', milestoneId: 'M002', title: 'M2 Slice', status: 'pending' });
202
205
 
203
206
  const m1Slices = getMilestoneSlices('M001');
204
- assert.deepStrictEqual(m1Slices.length, 2, 'M001 has 2 slices');
205
- assert.deepStrictEqual(m1Slices[0].id, 'S01', 'first slice is S01');
206
- assert.deepStrictEqual(m1Slices[0].status, 'complete', 'S01 status is complete');
207
- assert.deepStrictEqual(m1Slices[1].id, 'S02', 'second slice is S02');
208
- assert.deepStrictEqual(m1Slices[1].status, 'pending', 'S02 status is pending');
207
+ assertEq(m1Slices.length, 2, 'M001 has 2 slices');
208
+ assertEq(m1Slices[0].id, 'S01', 'first slice is S01');
209
+ assertEq(m1Slices[0].status, 'complete', 'S01 status is complete');
210
+ assertEq(m1Slices[1].id, 'S02', 'second slice is S02');
211
+ assertEq(m1Slices[1].status, 'pending', 'S02 status is pending');
209
212
 
210
213
  const m2Slices = getMilestoneSlices('M002');
211
- assert.deepStrictEqual(m2Slices.length, 1, 'M002 has 1 slice');
214
+ assertEq(m2Slices.length, 1, 'M002 has 1 slice');
212
215
 
213
216
  closeDatabase();
214
- });
217
+ }
215
218
 
216
- test('── markdown-renderer: getArtifact accessor ──', () => {
219
+ console.log('\n── markdown-renderer: getArtifact accessor ──');
220
+
221
+ {
217
222
  openDatabase(':memory:');
218
223
 
219
224
  // Not found
220
225
  const missing = getArtifact('nonexistent/path');
221
- assert.deepStrictEqual(missing, null, 'getArtifact returns null for missing path');
226
+ assertEq(missing, null, 'getArtifact returns null for missing path');
222
227
 
223
228
  // Insert and retrieve
224
229
  insertArtifact({
@@ -231,19 +236,21 @@ test('── markdown-renderer: getArtifact accessor ──', () => {
231
236
  });
232
237
 
233
238
  const found = getArtifact('milestones/M001/M001-ROADMAP.md');
234
- assert.ok(found !== null, 'getArtifact returns non-null for existing path');
235
- assert.deepStrictEqual(found!.artifact_type, 'ROADMAP', 'artifact type correct');
236
- assert.deepStrictEqual(found!.milestone_id, 'M001', 'milestone_id correct');
237
- assert.deepStrictEqual(found!.full_content, '# Roadmap content', 'content correct');
239
+ assertTrue(found !== null, 'getArtifact returns non-null for existing path');
240
+ assertEq(found!.artifact_type, 'ROADMAP', 'artifact type correct');
241
+ assertEq(found!.milestone_id, 'M001', 'milestone_id correct');
242
+ assertEq(found!.full_content, '# Roadmap content', 'content correct');
238
243
 
239
244
  closeDatabase();
240
- });
245
+ }
241
246
 
242
247
  // ═══════════════════════════════════════════════════════════════════════════
243
248
  // Roadmap Checkbox Round-Trip
244
249
  // ═══════════════════════════════════════════════════════════════════════════
245
250
 
246
- test('── markdown-renderer: renderRoadmapCheckboxes round-trip ──', async () => {
251
+ console.log('\n── markdown-renderer: renderRoadmapCheckboxes round-trip ──');
252
+
253
+ {
247
254
  const tmpDir = makeTmpDir();
248
255
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
249
256
  openDatabase(dbPath);
@@ -268,34 +275,36 @@ test('── markdown-renderer: renderRoadmapCheckboxes round-trip ──', asyn
268
275
 
269
276
  // Render β€” should set S01 [x] and leave S02 [ ]
270
277
  const ok = await renderRoadmapCheckboxes(tmpDir, 'M001');
271
- assert.ok(ok, 'renderRoadmapCheckboxes returns true');
278
+ assertTrue(ok, 'renderRoadmapCheckboxes returns true');
272
279
 
273
280
  // Read rendered file and parse
274
281
  const rendered = fs.readFileSync(roadmapPath, 'utf-8');
275
282
  clearAllCaches();
276
283
  const parsed = parseRoadmap(rendered);
277
284
 
278
- assert.deepStrictEqual(parsed.slices.length, 2, 'roadmap has 2 slices after render');
285
+ assertEq(parsed.slices.length, 2, 'roadmap has 2 slices after render');
279
286
 
280
287
  const s01 = parsed.slices.find(s => s.id === 'S01');
281
288
  const s02 = parsed.slices.find(s => s.id === 'S02');
282
- assert.ok(!!s01, 'S01 found in parsed roadmap');
283
- assert.ok(!!s02, 'S02 found in parsed roadmap');
284
- assert.ok(s01!.done, 'S01 is checked (done) after render');
285
- assert.ok(!s02!.done, 'S02 is unchecked (pending) after render');
289
+ assertTrue(!!s01, 'S01 found in parsed roadmap');
290
+ assertTrue(!!s02, 'S02 found in parsed roadmap');
291
+ assertTrue(s01!.done, 'S01 is checked (done) after render');
292
+ assertTrue(!s02!.done, 'S02 is unchecked (pending) after render');
286
293
 
287
294
  // Verify artifact stored in DB
288
295
  const artifact = getArtifact('milestones/M001/M001-ROADMAP.md');
289
- assert.ok(artifact !== null, 'roadmap artifact stored in DB after render');
290
- assert.ok(artifact!.full_content.includes('[x] **S01:'), 'DB artifact has S01 checked');
291
- assert.ok(artifact!.full_content.includes('[ ] **S02:'), 'DB artifact has S02 unchecked');
296
+ assertTrue(artifact !== null, 'roadmap artifact stored in DB after render');
297
+ assertTrue(artifact!.full_content.includes('[x] **S01:'), 'DB artifact has S01 checked');
298
+ assertTrue(artifact!.full_content.includes('[ ] **S02:'), 'DB artifact has S02 unchecked');
292
299
  } finally {
293
300
  closeDatabase();
294
301
  cleanupDir(tmpDir);
295
302
  }
296
- });
303
+ }
304
+
305
+ console.log('\n── markdown-renderer: renderRoadmapCheckboxes bidirectional ──');
297
306
 
298
- test('── markdown-renderer: renderRoadmapCheckboxes bidirectional ──', async () => {
307
+ {
299
308
  const tmpDir = makeTmpDir();
300
309
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
301
310
  openDatabase(dbPath);
@@ -319,7 +328,7 @@ test('── markdown-renderer: renderRoadmapCheckboxes bidirectional ──', a
319
328
  clearAllCaches();
320
329
 
321
330
  const ok = await renderRoadmapCheckboxes(tmpDir, 'M001');
322
- assert.ok(ok, 'bidirectional render returns true');
331
+ assertTrue(ok, 'bidirectional render returns true');
323
332
 
324
333
  const rendered = fs.readFileSync(roadmapPath, 'utf-8');
325
334
  clearAllCaches();
@@ -327,19 +336,21 @@ test('── markdown-renderer: renderRoadmapCheckboxes bidirectional ──', a
327
336
 
328
337
  const s01 = parsed.slices.find(s => s.id === 'S01');
329
338
  const s02 = parsed.slices.find(s => s.id === 'S02');
330
- assert.ok(!s01!.done, 'S01 unchecked (DB says pending, was checked on disk)');
331
- assert.ok(s02!.done, 'S02 checked (DB says complete, was unchecked on disk)');
339
+ assertTrue(!s01!.done, 'S01 unchecked (DB says pending, was checked on disk)');
340
+ assertTrue(s02!.done, 'S02 checked (DB says complete, was unchecked on disk)');
332
341
  } finally {
333
342
  closeDatabase();
334
343
  cleanupDir(tmpDir);
335
344
  }
336
- });
345
+ }
337
346
 
338
347
  // ═══════════════════════════════════════════════════════════════════════════
339
348
  // Plan Checkbox Round-Trip
340
349
  // ═══════════════════════════════════════════════════════════════════════════
341
350
 
342
- test('── markdown-renderer: renderPlanCheckboxes round-trip ──', async () => {
351
+ console.log('\n── markdown-renderer: renderPlanCheckboxes round-trip ──');
352
+
353
+ {
343
354
  const tmpDir = makeTmpDir();
344
355
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
345
356
  openDatabase(dbPath);
@@ -365,27 +376,29 @@ test('── markdown-renderer: renderPlanCheckboxes round-trip ──', async (
365
376
  clearAllCaches();
366
377
 
367
378
  const ok = await renderPlanCheckboxes(tmpDir, 'M001', 'S01');
368
- assert.ok(ok, 'renderPlanCheckboxes returns true');
379
+ assertTrue(ok, 'renderPlanCheckboxes returns true');
369
380
 
370
381
  const rendered = fs.readFileSync(planPath, 'utf-8');
371
382
  clearAllCaches();
372
383
  const parsed = parsePlan(rendered);
373
384
 
374
- assert.deepStrictEqual(parsed.tasks.length, 3, 'plan has 3 tasks after render');
385
+ assertEq(parsed.tasks.length, 3, 'plan has 3 tasks after render');
375
386
 
376
387
  const t01 = parsed.tasks.find(t => t.id === 'T01');
377
388
  const t02 = parsed.tasks.find(t => t.id === 'T02');
378
389
  const t03 = parsed.tasks.find(t => t.id === 'T03');
379
- assert.ok(t01!.done, 'T01 checked (done in DB)');
380
- assert.ok(t02!.done, 'T02 checked (done in DB)');
381
- assert.ok(!t03!.done, 'T03 unchecked (pending in DB)');
390
+ assertTrue(t01!.done, 'T01 checked (done in DB)');
391
+ assertTrue(t02!.done, 'T02 checked (done in DB)');
392
+ assertTrue(!t03!.done, 'T03 unchecked (pending in DB)');
382
393
  } finally {
383
394
  closeDatabase();
384
395
  cleanupDir(tmpDir);
385
396
  }
386
- });
397
+ }
387
398
 
388
- test('── markdown-renderer: renderPlanCheckboxes bidirectional ──', async () => {
399
+ console.log('\n── markdown-renderer: renderPlanCheckboxes bidirectional ──');
400
+
401
+ {
389
402
  const tmpDir = makeTmpDir();
390
403
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
391
404
  openDatabase(dbPath);
@@ -409,7 +422,7 @@ test('── markdown-renderer: renderPlanCheckboxes bidirectional ──', asyn
409
422
  clearAllCaches();
410
423
 
411
424
  const ok = await renderPlanCheckboxes(tmpDir, 'M001', 'S01');
412
- assert.ok(ok, 'bidirectional plan render returns true');
425
+ assertTrue(ok, 'bidirectional plan render returns true');
413
426
 
414
427
  const rendered = fs.readFileSync(planPath, 'utf-8');
415
428
  clearAllCaches();
@@ -417,15 +430,17 @@ test('── markdown-renderer: renderPlanCheckboxes bidirectional ──', asyn
417
430
 
418
431
  const t01 = parsed.tasks.find(t => t.id === 'T01');
419
432
  const t02 = parsed.tasks.find(t => t.id === 'T02');
420
- assert.ok(!t01!.done, 'T01 unchecked (DB says pending, was checked)');
421
- assert.ok(t02!.done, 'T02 checked (DB says done, was unchecked)');
433
+ assertTrue(!t01!.done, 'T01 unchecked (DB says pending, was checked)');
434
+ assertTrue(t02!.done, 'T02 checked (DB says done, was unchecked)');
422
435
  } finally {
423
436
  closeDatabase();
424
437
  cleanupDir(tmpDir);
425
438
  }
426
- });
439
+ }
440
+
441
+ console.log('\n── markdown-renderer: renderPlanFromDb creates parse-compatible slice plan + task plan files ──');
427
442
 
428
- test('── markdown-renderer: renderPlanFromDb creates parse-compatible slice plan + task plan files ──', async () => {
443
+ {
429
444
  const tmpDir = makeTmpDir();
430
445
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
431
446
  openDatabase(dbPath);
@@ -483,48 +498,50 @@ test('── markdown-renderer: renderPlanFromDb creates parse-compatible slice
483
498
  });
484
499
 
485
500
  const rendered = await renderPlanFromDb(tmpDir, 'M001', 'S02');
486
- assert.ok(fs.existsSync(rendered.planPath), 'slice plan written to disk');
487
- assert.strictEqual(rendered.taskPlanPaths.length, 2, 'task plan paths returned for each task');
488
- assert.ok(rendered.taskPlanPaths.every((p) => fs.existsSync(p)), 'all task plan files written to disk');
501
+ assertTrue(fs.existsSync(rendered.planPath), 'slice plan written to disk');
502
+ assertEq(rendered.taskPlanPaths.length, 2, 'task plan paths returned for each task');
503
+ assertTrue(rendered.taskPlanPaths.every((p) => fs.existsSync(p)), 'all task plan files written to disk');
489
504
 
490
505
  const planContent = fs.readFileSync(rendered.planPath, 'utf-8');
491
506
  clearAllCaches();
492
507
  const parsedPlan = parsePlan(planContent);
493
- assert.strictEqual(parsedPlan.id, 'S02', 'rendered slice plan parses with correct slice id');
494
- assert.strictEqual(parsedPlan.goal, 'Render slice plans from DB state.', 'rendered slice plan preserves goal');
495
- assert.strictEqual(parsedPlan.demo, 'Rendered plans exist on disk.', 'rendered slice plan preserves demo');
496
- assert.strictEqual(parsedPlan.mustHaves.length, 2, 'rendered slice plan exposes must-haves');
497
- assert.strictEqual(parsedPlan.tasks.length, 2, 'rendered slice plan exposes all tasks');
498
- assert.strictEqual(parsedPlan.tasks[0].id, 'T01', 'first task parses correctly');
499
- assert.ok(parsedPlan.tasks[0].description.includes('DB-backed slice plan renderer'), 'task description preserved in slice plan');
500
- assert.strictEqual(parsedPlan.tasks[0].files?.[0], 'src/resources/extensions/gsd/markdown-renderer.ts', 'files list preserved in slice plan');
501
- assert.strictEqual(parsedPlan.tasks[0].verify, 'node --test markdown-renderer.test.ts', 'verify line preserved in slice plan');
508
+ assertEq(parsedPlan.id, 'S02', 'rendered slice plan parses with correct slice id');
509
+ assertEq(parsedPlan.goal, 'Render slice plans from DB state.', 'rendered slice plan preserves goal');
510
+ assertEq(parsedPlan.demo, 'Rendered plans exist on disk.', 'rendered slice plan preserves demo');
511
+ assertEq(parsedPlan.mustHaves.length, 2, 'rendered slice plan exposes must-haves');
512
+ assertEq(parsedPlan.tasks.length, 2, 'rendered slice plan exposes all tasks');
513
+ assertEq(parsedPlan.tasks[0].id, 'T01', 'first task parses correctly');
514
+ assertTrue(parsedPlan.tasks[0].description.includes('DB-backed slice plan renderer'), 'task description preserved in slice plan');
515
+ assertEq(parsedPlan.tasks[0].files?.[0], 'src/resources/extensions/gsd/markdown-renderer.ts', 'files list preserved in slice plan');
516
+ assertEq(parsedPlan.tasks[0].verify, 'node --test markdown-renderer.test.ts', 'verify line preserved in slice plan');
502
517
 
503
518
  const planArtifact = getArtifact('milestones/M001/slices/S02/S02-PLAN.md');
504
- assert.ok(planArtifact !== null, 'slice plan artifact stored in DB');
505
- assert.ok(planArtifact!.full_content.includes('## Tasks'), 'stored plan artifact contains task section');
519
+ assertTrue(planArtifact !== null, 'slice plan artifact stored in DB');
520
+ assertTrue(planArtifact!.full_content.includes('## Tasks'), 'stored plan artifact contains task section');
506
521
 
507
522
  const taskPlanPath = path.join(tmpDir, '.gsd', 'milestones', 'M001', 'slices', 'S02', 'tasks', 'T01-PLAN.md');
508
523
  const taskPlanContent = fs.readFileSync(taskPlanPath, 'utf-8');
509
524
  const taskPlanFile = parseTaskPlanFile(taskPlanContent);
510
- assert.strictEqual(taskPlanFile.frontmatter.estimated_steps, 1, 'task plan frontmatter exposes estimated_steps');
511
- assert.strictEqual(taskPlanFile.frontmatter.estimated_files, 1, 'task plan frontmatter exposes estimated_files');
512
- assert.strictEqual(taskPlanFile.frontmatter.skills_used.length, 0, 'task plan frontmatter uses conservative empty skills list');
513
- assert.match(taskPlanContent, /^# T01: Render slice plan/m, 'task plan renders task heading');
514
- assert.match(taskPlanContent, /^## Inputs$/m, 'task plan renders Inputs section');
515
- assert.match(taskPlanContent, /^## Expected Output$/m, 'task plan renders Expected Output section');
516
- assert.match(taskPlanContent, /^## Verification$/m, 'task plan renders Verification section');
525
+ assertEq(taskPlanFile.frontmatter.estimated_steps, 1, 'task plan frontmatter exposes estimated_steps');
526
+ assertEq(taskPlanFile.frontmatter.estimated_files, 1, 'task plan frontmatter exposes estimated_files');
527
+ assertEq(taskPlanFile.frontmatter.skills_used.length, 0, 'task plan frontmatter uses conservative empty skills list');
528
+ assertMatch(taskPlanContent, /^# T01: Render slice plan/m, 'task plan renders task heading');
529
+ assertMatch(taskPlanContent, /^## Inputs$/m, 'task plan renders Inputs section');
530
+ assertMatch(taskPlanContent, /^## Expected Output$/m, 'task plan renders Expected Output section');
531
+ assertMatch(taskPlanContent, /^## Verification$/m, 'task plan renders Verification section');
517
532
 
518
533
  const taskArtifact = getArtifact('milestones/M001/slices/S02/tasks/T01-PLAN.md');
519
- assert.ok(taskArtifact !== null, 'task plan artifact stored in DB');
520
- assert.ok(taskArtifact!.full_content.includes('skills_used: []'), 'stored task plan artifact preserves conservative skills_used');
534
+ assertTrue(taskArtifact !== null, 'task plan artifact stored in DB');
535
+ assertTrue(taskArtifact!.full_content.includes('skills_used: []'), 'stored task plan artifact preserves conservative skills_used');
521
536
  } finally {
522
537
  closeDatabase();
523
538
  cleanupDir(tmpDir);
524
539
  }
525
- });
540
+ }
541
+
542
+ console.log('\n── markdown-renderer: renderTaskPlanFromDb throws for missing task ──');
526
543
 
527
- test('── markdown-renderer: renderTaskPlanFromDb throws for missing task ──', async () => {
544
+ {
528
545
  const tmpDir = makeTmpDir();
529
546
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
530
547
  openDatabase(dbPath);
@@ -540,21 +557,23 @@ test('── markdown-renderer: renderTaskPlanFromDb throws for missing task ─
540
557
  await renderTaskPlanFromDb(tmpDir, 'M001', 'S02', 'T99');
541
558
  } catch (error) {
542
559
  threw = true;
543
- assert.match(String((error as Error).message), /task M001\/S02\/T99 not found/, 'renderTaskPlanFromDb should fail clearly when task row is missing');
560
+ assertMatch(String((error as Error).message), /task M001\/S02\/T99 not found/, 'renderTaskPlanFromDb should fail clearly when task row is missing');
544
561
  }
545
- assert.ok(threw, 'renderTaskPlanFromDb throws when the task row is missing');
562
+ assertTrue(threw, 'renderTaskPlanFromDb throws when the task row is missing');
546
563
  } finally {
547
564
  closeDatabase();
548
565
  cleanupDir(tmpDir);
549
566
  }
550
- });
567
+ }
551
568
 
552
569
 
553
570
  // ═══════════════════════════════════════════════════════════════════════════
554
571
  // Task Summary Rendering
555
572
  // ═══════════════════════════════════════════════════════════════════════════
556
573
 
557
- test('── markdown-renderer: renderTaskSummary round-trip ──', async () => {
574
+ console.log('\n── markdown-renderer: renderTaskSummary round-trip ──');
575
+
576
+ {
558
577
  const tmpDir = makeTmpDir();
559
578
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
560
579
  openDatabase(dbPath);
@@ -577,31 +596,33 @@ test('── markdown-renderer: renderTaskSummary round-trip ──', async () =
577
596
  });
578
597
 
579
598
  const ok = await renderTaskSummary(tmpDir, 'M001', 'S01', 'T01');
580
- assert.ok(ok, 'renderTaskSummary returns true');
599
+ assertTrue(ok, 'renderTaskSummary returns true');
581
600
 
582
601
  // Verify file exists on disk
583
602
  const summaryPath = path.join(
584
603
  tmpDir, '.gsd', 'milestones', 'M001', 'slices', 'S01', 'tasks', 'T01-SUMMARY.md',
585
604
  );
586
- assert.ok(fs.existsSync(summaryPath), 'T01-SUMMARY.md written to disk');
605
+ assertTrue(fs.existsSync(summaryPath), 'T01-SUMMARY.md written to disk');
587
606
 
588
607
  // Parse and verify
589
608
  const rendered = fs.readFileSync(summaryPath, 'utf-8');
590
609
  clearAllCaches();
591
610
  const parsed = parseSummary(rendered);
592
- assert.deepStrictEqual(parsed.frontmatter.id, 'T01', 'parsed summary has correct id');
593
- assert.deepStrictEqual(parsed.frontmatter.parent, 'S01', 'parsed summary has correct parent');
594
- assert.deepStrictEqual(parsed.frontmatter.milestone, 'M001', 'parsed summary has correct milestone');
595
- assert.deepStrictEqual(parsed.frontmatter.duration, '45m', 'parsed summary has correct duration');
596
- assert.ok(parsed.title.includes('T01'), 'parsed summary title contains task ID');
597
- assert.ok(parsed.whatHappened.includes('Built the test feature'), 'whatHappened content preserved');
611
+ assertEq(parsed.frontmatter.id, 'T01', 'parsed summary has correct id');
612
+ assertEq(parsed.frontmatter.parent, 'S01', 'parsed summary has correct parent');
613
+ assertEq(parsed.frontmatter.milestone, 'M001', 'parsed summary has correct milestone');
614
+ assertEq(parsed.frontmatter.duration, '45m', 'parsed summary has correct duration');
615
+ assertTrue(parsed.title.includes('T01'), 'parsed summary title contains task ID');
616
+ assertTrue(parsed.whatHappened.includes('Built the test feature'), 'whatHappened content preserved');
598
617
  } finally {
599
618
  closeDatabase();
600
619
  cleanupDir(tmpDir);
601
620
  }
602
- });
621
+ }
622
+
623
+ console.log('\n── markdown-renderer: renderTaskSummary skips empty ──');
603
624
 
604
- test('── markdown-renderer: renderTaskSummary skips empty ──', async () => {
625
+ {
605
626
  const tmpDir = makeTmpDir();
606
627
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
607
628
  openDatabase(dbPath);
@@ -622,18 +643,20 @@ test('── markdown-renderer: renderTaskSummary skips empty ──', async ()
622
643
  });
623
644
 
624
645
  const ok = await renderTaskSummary(tmpDir, 'M001', 'S01', 'T01');
625
- assert.ok(!ok, 'renderTaskSummary returns false for empty summary');
646
+ assertTrue(!ok, 'renderTaskSummary returns false for empty summary');
626
647
  } finally {
627
648
  closeDatabase();
628
649
  cleanupDir(tmpDir);
629
650
  }
630
- });
651
+ }
631
652
 
632
653
  // ═══════════════════════════════════════════════════════════════════════════
633
654
  // Slice Summary Rendering
634
655
  // ═══════════════════════════════════════════════════════════════════════════
635
656
 
636
- test('── markdown-renderer: renderSliceSummary round-trip ──', async () => {
657
+ console.log('\n── markdown-renderer: renderSliceSummary round-trip ──');
658
+
659
+ {
637
660
  const tmpDir = makeTmpDir();
638
661
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
639
662
  openDatabase(dbPath);
@@ -657,36 +680,38 @@ test('── markdown-renderer: renderSliceSummary round-trip ──', async ()
657
680
  });
658
681
 
659
682
  const ok = await renderSliceSummary(tmpDir, 'M001', 'S01');
660
- assert.ok(ok, 'renderSliceSummary returns true');
683
+ assertTrue(ok, 'renderSliceSummary returns true');
661
684
 
662
685
  // Verify SUMMARY file
663
686
  const summaryPath = path.join(
664
687
  tmpDir, '.gsd', 'milestones', 'M001', 'slices', 'S01', 'S01-SUMMARY.md',
665
688
  );
666
- assert.ok(fs.existsSync(summaryPath), 'S01-SUMMARY.md written to disk');
689
+ assertTrue(fs.existsSync(summaryPath), 'S01-SUMMARY.md written to disk');
667
690
 
668
691
  const summaryContent = fs.readFileSync(summaryPath, 'utf-8');
669
- assert.ok(summaryContent.includes('Test Slice Summary'), 'summary content correct');
692
+ assertTrue(summaryContent.includes('Test Slice Summary'), 'summary content correct');
670
693
 
671
694
  // Verify UAT file
672
695
  const uatPath = path.join(
673
696
  tmpDir, '.gsd', 'milestones', 'M001', 'slices', 'S01', 'S01-UAT.md',
674
697
  );
675
- assert.ok(fs.existsSync(uatPath), 'S01-UAT.md written to disk');
698
+ assertTrue(fs.existsSync(uatPath), 'S01-UAT.md written to disk');
676
699
 
677
700
  const uatContent = fs.readFileSync(uatPath, 'utf-8');
678
- assert.ok(uatContent.includes('artifact-driven'), 'UAT content correct');
701
+ assertTrue(uatContent.includes('artifact-driven'), 'UAT content correct');
679
702
  } finally {
680
703
  closeDatabase();
681
704
  cleanupDir(tmpDir);
682
705
  }
683
- });
706
+ }
684
707
 
685
708
  // ═══════════════════════════════════════════════════════════════════════════
686
709
  // renderAllFromDb
687
710
  // ═══════════════════════════════════════════════════════════════════════════
688
711
 
689
- test('── markdown-renderer: renderAllFromDb produces all files ──', async () => {
712
+ console.log('\n── markdown-renderer: renderAllFromDb produces all files ──');
713
+
714
+ {
690
715
  const tmpDir = makeTmpDir();
691
716
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
692
717
  openDatabase(dbPath);
@@ -754,8 +779,8 @@ test('── markdown-renderer: renderAllFromDb produces all files ──', asyn
754
779
 
755
780
  const result = await renderAllFromDb(tmpDir);
756
781
 
757
- assert.ok(result.rendered > 0, 'renderAllFromDb rendered some files');
758
- assert.deepStrictEqual(result.errors.length, 0, 'renderAllFromDb had no errors');
782
+ assertTrue(result.rendered > 0, 'renderAllFromDb rendered some files');
783
+ assertEq(result.errors.length, 0, 'renderAllFromDb had no errors');
759
784
 
760
785
  // Verify M001 roadmap has S01 checked
761
786
  const m1Roadmap = fs.readFileSync(
@@ -764,7 +789,7 @@ test('── markdown-renderer: renderAllFromDb produces all files ──', asyn
764
789
  clearAllCaches();
765
790
  const parsed1 = parseRoadmap(m1Roadmap);
766
791
  const s01 = parsed1.slices.find(s => s.id === 'S01');
767
- assert.ok(s01!.done, 'M001 S01 checked after renderAll');
792
+ assertTrue(s01!.done, 'M001 S01 checked after renderAll');
768
793
 
769
794
  // Verify M001/S01 plan has T01 checked
770
795
  const m1s1Plan = fs.readFileSync(
@@ -772,24 +797,26 @@ test('── markdown-renderer: renderAllFromDb produces all files ──', asyn
772
797
  );
773
798
  clearAllCaches();
774
799
  const parsedPlan = parsePlan(m1s1Plan);
775
- assert.ok(parsedPlan.tasks[0].done, 'M001/S01 T01 checked after renderAll');
800
+ assertTrue(parsedPlan.tasks[0].done, 'M001/S01 T01 checked after renderAll');
776
801
 
777
802
  // Verify task summary written
778
803
  const taskSummaryPath = path.join(
779
804
  tmpDir, '.gsd', 'milestones', 'M001', 'slices', 'S01', 'tasks', 'T01-SUMMARY.md',
780
805
  );
781
- assert.ok(fs.existsSync(taskSummaryPath), 'T01 summary written by renderAll');
806
+ assertTrue(fs.existsSync(taskSummaryPath), 'T01 summary written by renderAll');
782
807
  } finally {
783
808
  closeDatabase();
784
809
  cleanupDir(tmpDir);
785
810
  }
786
- });
811
+ }
787
812
 
788
813
  // ═══════════════════════════════════════════════════════════════════════════
789
814
  // Graceful Degradation (Disk Fallback)
790
815
  // ═══════════════════════════════════════════════════════════════════════════
791
816
 
792
- test('── markdown-renderer: graceful fallback reads from disk when artifact not in DB ──', async () => {
817
+ console.log('\n── markdown-renderer: graceful fallback reads from disk when artifact not in DB ──');
818
+
819
+ {
793
820
  const tmpDir = makeTmpDir();
794
821
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
795
822
  openDatabase(dbPath);
@@ -811,27 +838,29 @@ test('── markdown-renderer: graceful fallback reads from disk when artifact
811
838
 
812
839
  // Verify no artifact in DB
813
840
  const before = getArtifact('milestones/M001/M001-ROADMAP.md');
814
- assert.deepStrictEqual(before, null, 'artifact not in DB before render');
841
+ assertEq(before, null, 'artifact not in DB before render');
815
842
 
816
843
  // Render β€” should read from disk, store in DB
817
844
  const ok = await renderRoadmapCheckboxes(tmpDir, 'M001');
818
- assert.ok(ok, 'render succeeds with disk fallback');
845
+ assertTrue(ok, 'render succeeds with disk fallback');
819
846
 
820
847
  // Verify artifact now in DB (stored after reading from disk)
821
848
  const after = getArtifact('milestones/M001/M001-ROADMAP.md');
822
- assert.ok(after !== null, 'artifact stored in DB after disk fallback render');
823
- assert.ok(after!.full_content.includes('[x] **S01:'), 'DB artifact reflects rendered state');
849
+ assertTrue(after !== null, 'artifact stored in DB after disk fallback render');
850
+ assertTrue(after!.full_content.includes('[x] **S01:'), 'DB artifact reflects rendered state');
824
851
  } finally {
825
852
  closeDatabase();
826
853
  cleanupDir(tmpDir);
827
854
  }
828
- });
855
+ }
829
856
 
830
857
  // ═══════════════════════════════════════════════════════════════════════════
831
858
  // stderr warnings (graceful degradation diagnostics)
832
859
  // ═══════════════════════════════════════════════════════════════════════════
833
860
 
834
- test('── markdown-renderer: stderr warning on missing content ──', async () => {
861
+ console.log('\n── markdown-renderer: stderr warning on missing content ──');
862
+
863
+ {
835
864
  openDatabase(':memory:');
836
865
 
837
866
  // No milestone/slices in DB, no files on disk β€” should return false and emit stderr
@@ -839,16 +868,18 @@ test('── markdown-renderer: stderr warning on missing content ──', async
839
868
  // No slices inserted β€” should warn about no slices
840
869
 
841
870
  const ok = await renderRoadmapCheckboxes('/nonexistent/path', 'M001');
842
- assert.ok(!ok, 'returns false when no slices in DB');
871
+ assertTrue(!ok, 'returns false when no slices in DB');
843
872
 
844
873
  closeDatabase();
845
- });
874
+ }
846
875
 
847
876
  // ═══════════════════════════════════════════════════════════════════════════
848
877
  // Stale Detection β€” Plan Checkbox Mismatch
849
878
  // ═══════════════════════════════════════════════════════════════════════════
850
879
 
851
- test('── markdown-renderer: detectStaleRenders finds plan checkbox mismatch ──', () => {
880
+ console.log('\n── markdown-renderer: detectStaleRenders finds plan checkbox mismatch ──');
881
+
882
+ {
852
883
  const tmpDir = makeTmpDir();
853
884
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
854
885
  openDatabase(dbPath);
@@ -879,25 +910,27 @@ test('── markdown-renderer: detectStaleRenders finds plan checkbox mismatch
879
910
  // The stale detection should find T02 as stale.
880
911
  const stale = detectStaleRenders(tmpDir);
881
912
 
882
- assert.ok(stale.length > 0, 'detectStaleRenders should find stale entries');
913
+ assertTrue(stale.length > 0, 'detectStaleRenders should find stale entries');
883
914
  const t02Stale = stale.find(s => s.reason.includes('T02'));
884
- assert.ok(!!t02Stale, 'should detect T02 as stale (done in DB, unchecked in plan)');
885
- assert.ok(t02Stale!.reason.includes('done in DB but unchecked'), 'reason should explain the mismatch');
915
+ assertTrue(!!t02Stale, 'should detect T02 as stale (done in DB, unchecked in plan)');
916
+ assertTrue(t02Stale!.reason.includes('done in DB but unchecked'), 'reason should explain the mismatch');
886
917
 
887
918
  // T01 should NOT be stale β€” it's checked and done
888
919
  const t01Stale = stale.find(s => s.reason.includes('T01'));
889
- assert.deepStrictEqual(t01Stale, undefined, 'T01 should not be stale (done and checked)');
920
+ assertEq(t01Stale, undefined, 'T01 should not be stale (done and checked)');
890
921
  } finally {
891
922
  closeDatabase();
892
923
  cleanupDir(tmpDir);
893
924
  }
894
- });
925
+ }
895
926
 
896
927
  // ═══════════════════════════════════════════════════════════════════════════
897
928
  // Stale Repair β€” Plan Checkbox
898
929
  // ═══════════════════════════════════════════════════════════════════════════
899
930
 
900
- test('── markdown-renderer: repairStaleRenders fixes plan and second detect returns empty ──', async () => {
931
+ console.log('\n── markdown-renderer: repairStaleRenders fixes plan and second detect returns empty ──');
932
+
933
+ {
901
934
  const tmpDir = makeTmpDir();
902
935
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
903
936
  openDatabase(dbPath);
@@ -923,32 +956,34 @@ test('── markdown-renderer: repairStaleRenders fixes plan and second detect
923
956
 
924
957
  // Verify stale before repair
925
958
  const staleBefore = detectStaleRenders(tmpDir);
926
- assert.ok(staleBefore.length > 0, 'should have stale entries before repair');
959
+ assertTrue(staleBefore.length > 0, 'should have stale entries before repair');
927
960
 
928
961
  // Repair
929
962
  const repaired = await repairStaleRenders(tmpDir);
930
- assert.ok(repaired > 0, 'repairStaleRenders should repair at least 1 file');
963
+ assertTrue(repaired > 0, 'repairStaleRenders should repair at least 1 file');
931
964
 
932
965
  // After repair, detect again β€” should be empty
933
966
  clearAllCaches();
934
967
  const staleAfter = detectStaleRenders(tmpDir);
935
- assert.deepStrictEqual(staleAfter.length, 0, 'detectStaleRenders should return empty after repair');
968
+ assertEq(staleAfter.length, 0, 'detectStaleRenders should return empty after repair');
936
969
 
937
970
  // Verify the plan file was actually updated
938
971
  const repairedContent = fs.readFileSync(planPath, 'utf-8');
939
- assert.ok(repairedContent.includes('[x] **T01:'), 'T01 should be checked after repair');
940
- assert.ok(repairedContent.includes('[x] **T02:'), 'T02 should be checked after repair');
972
+ assertTrue(repairedContent.includes('[x] **T01:'), 'T01 should be checked after repair');
973
+ assertTrue(repairedContent.includes('[x] **T02:'), 'T02 should be checked after repair');
941
974
  } finally {
942
975
  closeDatabase();
943
976
  cleanupDir(tmpDir);
944
977
  }
945
- });
978
+ }
946
979
 
947
980
  // ═══════════════════════════════════════════════════════════════════════════
948
981
  // Stale Detection β€” Roadmap Checkbox Mismatch
949
982
  // ═══════════════════════════════════════════════════════════════════════════
950
983
 
951
- test('── markdown-renderer: detectStaleRenders finds roadmap checkbox mismatch ──', () => {
984
+ console.log('\n── markdown-renderer: detectStaleRenders finds roadmap checkbox mismatch ──');
985
+
986
+ {
952
987
  const tmpDir = makeTmpDir();
953
988
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
954
989
  openDatabase(dbPath);
@@ -972,21 +1007,23 @@ test('── markdown-renderer: detectStaleRenders finds roadmap checkbox mismat
972
1007
 
973
1008
  const stale = detectStaleRenders(tmpDir);
974
1009
  const s01Stale = stale.find(s => s.reason.includes('S01'));
975
- assert.ok(!!s01Stale, 'should detect S01 as stale (complete in DB, unchecked in roadmap)');
1010
+ assertTrue(!!s01Stale, 'should detect S01 as stale (complete in DB, unchecked in roadmap)');
976
1011
 
977
1012
  const s02Stale = stale.find(s => s.reason.includes('S02'));
978
- assert.deepStrictEqual(s02Stale, undefined, 'S02 should not be stale (pending and unchecked β€” matches)');
1013
+ assertEq(s02Stale, undefined, 'S02 should not be stale (pending and unchecked β€” matches)');
979
1014
  } finally {
980
1015
  closeDatabase();
981
1016
  cleanupDir(tmpDir);
982
1017
  }
983
- });
1018
+ }
984
1019
 
985
1020
  // ═══════════════════════════════════════════════════════════════════════════
986
1021
  // Stale Detection β€” Missing Task Summary
987
1022
  // ═══════════════════════════════════════════════════════════════════════════
988
1023
 
989
- test('── markdown-renderer: detectStaleRenders finds missing task summary ──', () => {
1024
+ console.log('\n── markdown-renderer: detectStaleRenders finds missing task summary ──');
1025
+
1026
+ {
990
1027
  const tmpDir = makeTmpDir();
991
1028
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
992
1029
  openDatabase(dbPath);
@@ -1021,19 +1058,21 @@ test('── markdown-renderer: detectStaleRenders finds missing task summary
1021
1058
 
1022
1059
  const stale = detectStaleRenders(tmpDir);
1023
1060
  const summaryStale = stale.find(s => s.reason.includes('SUMMARY.md missing'));
1024
- assert.ok(!!summaryStale, 'should detect missing T01-SUMMARY.md');
1025
- assert.ok(summaryStale!.reason.includes('T01'), 'reason should mention T01');
1061
+ assertTrue(!!summaryStale, 'should detect missing T01-SUMMARY.md');
1062
+ assertTrue(summaryStale!.reason.includes('T01'), 'reason should mention T01');
1026
1063
  } finally {
1027
1064
  closeDatabase();
1028
1065
  cleanupDir(tmpDir);
1029
1066
  }
1030
- });
1067
+ }
1031
1068
 
1032
1069
  // ═══════════════════════════════════════════════════════════════════════════
1033
1070
  // Stale Repair β€” Missing Task Summary
1034
1071
  // ═══════════════════════════════════════════════════════════════════════════
1035
1072
 
1036
- test('── markdown-renderer: repairStaleRenders writes missing task summary ──', async () => {
1073
+ console.log('\n── markdown-renderer: repairStaleRenders writes missing task summary ──');
1074
+
1075
+ {
1037
1076
  const tmpDir = makeTmpDir();
1038
1077
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
1039
1078
  openDatabase(dbPath);
@@ -1065,30 +1104,32 @@ test('── markdown-renderer: repairStaleRenders writes missing task summary
1065
1104
 
1066
1105
  // Repair
1067
1106
  const repaired = await repairStaleRenders(tmpDir);
1068
- assert.ok(repaired > 0, 'should repair missing summary');
1107
+ assertTrue(repaired > 0, 'should repair missing summary');
1069
1108
 
1070
1109
  // Verify file written
1071
1110
  const summaryPath = path.join(
1072
1111
  tmpDir, '.gsd', 'milestones', 'M001', 'slices', 'S01', 'tasks', 'T01-SUMMARY.md',
1073
1112
  );
1074
- assert.ok(fs.existsSync(summaryPath), 'T01-SUMMARY.md should exist after repair');
1113
+ assertTrue(fs.existsSync(summaryPath), 'T01-SUMMARY.md should exist after repair');
1075
1114
 
1076
1115
  // Second detect should be empty
1077
1116
  clearAllCaches();
1078
1117
  const staleAfter = detectStaleRenders(tmpDir);
1079
1118
  const summaryStale = staleAfter.find(s => s.reason.includes('SUMMARY.md missing') && s.reason.includes('T01'));
1080
- assert.deepStrictEqual(summaryStale, undefined, 'missing summary should be fixed after repair');
1119
+ assertEq(summaryStale, undefined, 'missing summary should be fixed after repair');
1081
1120
  } finally {
1082
1121
  closeDatabase();
1083
1122
  cleanupDir(tmpDir);
1084
1123
  }
1085
- });
1124
+ }
1086
1125
 
1087
1126
  // ═══════════════════════════════════════════════════════════════════════════
1088
1127
  // Stale Repair β€” Idempotency
1089
1128
  // ═══════════════════════════════════════════════════════════════════════════
1090
1129
 
1091
- test('── markdown-renderer: repairStaleRenders idempotency β€” fully synced returns 0 ──', async () => {
1130
+ console.log('\n── markdown-renderer: repairStaleRenders idempotency β€” fully synced returns 0 ──');
1131
+
1132
+ {
1092
1133
  const tmpDir = makeTmpDir();
1093
1134
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
1094
1135
  openDatabase(dbPath);
@@ -1111,18 +1152,20 @@ test('── markdown-renderer: repairStaleRenders idempotency β€” fully synced
1111
1152
 
1112
1153
  // No stale entries when everything is in sync (no summary to check since no fullSummaryMd)
1113
1154
  const repaired = await repairStaleRenders(tmpDir);
1114
- assert.deepStrictEqual(repaired, 0, 'repairStaleRenders should return 0 on fully synced project');
1155
+ assertEq(repaired, 0, 'repairStaleRenders should return 0 on fully synced project');
1115
1156
  } finally {
1116
1157
  closeDatabase();
1117
1158
  cleanupDir(tmpDir);
1118
1159
  }
1119
- });
1160
+ }
1120
1161
 
1121
1162
  // ═══════════════════════════════════════════════════════════════════════════
1122
1163
  // Stale Detection β€” Missing Slice Summary + UAT
1123
1164
  // ═══════════════════════════════════════════════════════════════════════════
1124
1165
 
1125
- test('── markdown-renderer: detectStaleRenders finds missing slice summary and UAT ──', () => {
1166
+ console.log('\n── markdown-renderer: detectStaleRenders finds missing slice summary and UAT ──');
1167
+
1168
+ {
1126
1169
  const tmpDir = makeTmpDir();
1127
1170
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
1128
1171
  openDatabase(dbPath);
@@ -1149,13 +1192,14 @@ test('── markdown-renderer: detectStaleRenders finds missing slice summary a
1149
1192
  const summaryStale = stale.find(s => s.reason.includes('SUMMARY.md missing') && s.reason.includes('S01'));
1150
1193
  const uatStale = stale.find(s => s.reason.includes('UAT.md missing') && s.reason.includes('S01'));
1151
1194
 
1152
- assert.ok(!!summaryStale, 'should detect missing S01-SUMMARY.md');
1153
- assert.ok(!!uatStale, 'should detect missing S01-UAT.md');
1195
+ assertTrue(!!summaryStale, 'should detect missing S01-SUMMARY.md');
1196
+ assertTrue(!!uatStale, 'should detect missing S01-UAT.md');
1154
1197
  } finally {
1155
1198
  closeDatabase();
1156
1199
  cleanupDir(tmpDir);
1157
1200
  }
1158
- });
1201
+ }
1159
1202
 
1160
1203
  // ═══════════════════════════════════════════════════════════════════════════
1161
1204
 
1205
+ report();