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
@@ -63,33 +63,35 @@ steps:
63
63
 
64
64
  // ─── loadDefinition: valid YAML ──────────────────────────────────────────
65
65
 
66
- test("loadDefinition: valid 3-step YAML returns correct structure", (t) => {
66
+ test("loadDefinition: valid 3-step YAML returns correct structure", () => {
67
67
  const dir = writeDefYaml(VALID_3STEP_YAML);
68
- t.after(() => { try { rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch { /* Windows EPERM */ } });
69
-
70
- const def = loadDefinition(dir, "test-workflow");
71
-
72
- assert.equal(def.version, 1);
73
- assert.equal(def.name, "test-workflow");
74
- assert.equal(def.description, "A test workflow");
75
- assert.deepEqual(def.params, { topic: "AI" });
76
- assert.equal(def.steps.length, 3);
77
-
78
- // Step 1: research
79
- assert.equal(def.steps[0].id, "research");
80
- assert.equal(def.steps[0].name, "Research the topic");
81
- assert.equal(def.steps[0].prompt, "Research {{topic}} and write findings to research.md");
82
- assert.deepEqual(def.steps[0].requires, []);
83
- assert.deepEqual(def.steps[0].produces, ["research.md"]);
84
-
85
- // Step 2: outline — depends on research
86
- assert.equal(def.steps[1].id, "outline");
87
- assert.deepEqual(def.steps[1].requires, ["research"]);
88
-
89
- // Step 3: draft — depends on outline
90
- assert.equal(def.steps[2].id, "draft");
91
- assert.deepEqual(def.steps[2].requires, ["outline"]);
92
- assert.deepEqual(def.steps[2].produces, ["draft.md"]);
68
+ try {
69
+ const def = loadDefinition(dir, "test-workflow");
70
+
71
+ assert.equal(def.version, 1);
72
+ assert.equal(def.name, "test-workflow");
73
+ assert.equal(def.description, "A test workflow");
74
+ assert.deepEqual(def.params, { topic: "AI" });
75
+ assert.equal(def.steps.length, 3);
76
+
77
+ // Step 1: research
78
+ assert.equal(def.steps[0].id, "research");
79
+ assert.equal(def.steps[0].name, "Research the topic");
80
+ assert.equal(def.steps[0].prompt, "Research {{topic}} and write findings to research.md");
81
+ assert.deepEqual(def.steps[0].requires, []);
82
+ assert.deepEqual(def.steps[0].produces, ["research.md"]);
83
+
84
+ // Step 2: outline — depends on research
85
+ assert.equal(def.steps[1].id, "outline");
86
+ assert.deepEqual(def.steps[1].requires, ["research"]);
87
+
88
+ // Step 3: draft — depends on outline
89
+ assert.equal(def.steps[2].id, "draft");
90
+ assert.deepEqual(def.steps[2].requires, ["outline"]);
91
+ assert.deepEqual(def.steps[2].produces, ["draft.md"]);
92
+ } finally {
93
+ try { rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch { /* Windows EPERM */ }
94
+ }
93
95
  });
94
96
 
95
97
  // ─── validateDefinition: rejection cases ─────────────────────────────────
@@ -221,21 +223,23 @@ test("validateDefinition: missing step name → error", () => {
221
223
 
222
224
  // ─── loadDefinition: error cases ─────────────────────────────────────────
223
225
 
224
- test("loadDefinition: missing file → descriptive error", (t) => {
226
+ test("loadDefinition: missing file → descriptive error", () => {
225
227
  const dir = makeTmpDir();
226
- t.after(() => { try { rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch { /* Windows EPERM */ } });
227
-
228
- assert.throws(
229
- () => loadDefinition(dir, "nonexistent"),
230
- (err: Error) => {
231
- assert.ok(err.message.includes("not found"));
232
- assert.ok(err.message.includes("nonexistent.yaml"));
233
- return true;
234
- },
235
- );
236
- });
237
-
238
- test("loadDefinition: invalid YAML schema → descriptive error", (t) => {
228
+ try {
229
+ assert.throws(
230
+ () => loadDefinition(dir, "nonexistent"),
231
+ (err: Error) => {
232
+ assert.ok(err.message.includes("not found"));
233
+ assert.ok(err.message.includes("nonexistent.yaml"));
234
+ return true;
235
+ },
236
+ );
237
+ } finally {
238
+ try { rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch { /* Windows EPERM */ }
239
+ }
240
+ });
241
+
242
+ test("loadDefinition: invalid YAML schema → descriptive error", () => {
239
243
  const dir = writeDefYaml(`
240
244
  version: 2
241
245
  name: "bad"
@@ -244,21 +248,23 @@ steps:
244
248
  name: "A"
245
249
  prompt: "do A"
246
250
  `);
247
- t.after(() => { try { rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch { /* Windows EPERM */ } });
248
-
249
- assert.throws(
250
- () => loadDefinition(dir, "test-workflow"),
251
- (err: Error) => {
252
- assert.ok(err.message.includes("Invalid workflow definition"));
253
- assert.ok(err.message.includes("Unsupported version"));
254
- return true;
255
- },
256
- );
251
+ try {
252
+ assert.throws(
253
+ () => loadDefinition(dir, "test-workflow"),
254
+ (err: Error) => {
255
+ assert.ok(err.message.includes("Invalid workflow definition"));
256
+ assert.ok(err.message.includes("Unsupported version"));
257
+ return true;
258
+ },
259
+ );
260
+ } finally {
261
+ try { rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch { /* Windows EPERM */ }
262
+ }
257
263
  });
258
264
 
259
265
  // ─── loadDefinition: snake_case → camelCase conversion ───────────────────
260
266
 
261
- test("loadDefinition: depends_on in YAML maps to requires in TypeScript", (t) => {
267
+ test("loadDefinition: depends_on in YAML maps to requires in TypeScript", () => {
262
268
  const dir = writeDefYaml(`
263
269
  version: 1
264
270
  name: "dep-test"
@@ -271,13 +277,15 @@ steps:
271
277
  prompt: "do second"
272
278
  depends_on: [first]
273
279
  `);
274
- t.after(() => { try { rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch { /* Windows EPERM */ } });
275
-
276
- const def = loadDefinition(dir, "test-workflow");
277
- assert.deepEqual(def.steps[1].requires, ["first"]);
280
+ try {
281
+ const def = loadDefinition(dir, "test-workflow");
282
+ assert.deepEqual(def.steps[1].requires, ["first"]);
283
+ } finally {
284
+ try { rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch { /* Windows EPERM */ }
285
+ }
278
286
  });
279
287
 
280
- test("loadDefinition: context_from in YAML maps to contextFrom in TypeScript", (t) => {
288
+ test("loadDefinition: context_from in YAML maps to contextFrom in TypeScript", () => {
281
289
  const dir = writeDefYaml(`
282
290
  version: 1
283
291
  name: "ctx-test"
@@ -290,10 +298,12 @@ steps:
290
298
  prompt: "do second"
291
299
  context_from: [first]
292
300
  `);
293
- t.after(() => { try { rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch { /* Windows EPERM */ } });
294
-
295
- const def = loadDefinition(dir, "test-workflow");
296
- assert.deepEqual(def.steps[1].contextFrom, ["first"]);
301
+ try {
302
+ const def = loadDefinition(dir, "test-workflow");
303
+ assert.deepEqual(def.steps[1].contextFrom, ["first"]);
304
+ } finally {
305
+ try { rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch { /* Windows EPERM */ }
306
+ }
297
307
  });
298
308
 
299
309
  // ─── validateDefinition: iterate field validation ────────────────────────
@@ -715,7 +725,7 @@ test("validateDefinition: valid minimal step (no requires/produces) → accepted
715
725
  assert.equal(result.errors.length, 0);
716
726
  });
717
727
 
718
- test("loadDefinition: loads without params field → params is undefined", (t) => {
728
+ test("loadDefinition: loads without params field → params is undefined", () => {
719
729
  const dir = writeDefYaml(`
720
730
  version: 1
721
731
  name: "no-params"
@@ -724,13 +734,15 @@ steps:
724
734
  name: "A"
725
735
  prompt: "do A"
726
736
  `);
727
- t.after(() => { try { rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch { /* Windows EPERM */ } });
728
-
729
- const def = loadDefinition(dir, "test-workflow");
730
- assert.equal(def.params, undefined);
737
+ try {
738
+ const def = loadDefinition(dir, "test-workflow");
739
+ assert.equal(def.params, undefined);
740
+ } finally {
741
+ try { rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch { /* Windows EPERM */ }
742
+ }
731
743
  });
732
744
 
733
- test("loadDefinition: loads without description → description is undefined", (t) => {
745
+ test("loadDefinition: loads without description → description is undefined", () => {
734
746
  const dir = writeDefYaml(`
735
747
  version: 1
736
748
  name: "no-desc"
@@ -739,13 +751,15 @@ steps:
739
751
  name: "A"
740
752
  prompt: "do A"
741
753
  `);
742
- t.after(() => { try { rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch { /* Windows EPERM */ } });
743
-
744
- const def = loadDefinition(dir, "test-workflow");
745
- assert.equal(def.description, undefined);
754
+ try {
755
+ const def = loadDefinition(dir, "test-workflow");
756
+ assert.equal(def.description, undefined);
757
+ } finally {
758
+ try { rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch { /* Windows EPERM */ }
759
+ }
746
760
  });
747
761
 
748
- test("loadDefinition: step with no requires/produces defaults to empty arrays", (t) => {
762
+ test("loadDefinition: step with no requires/produces defaults to empty arrays", () => {
749
763
  const dir = writeDefYaml(`
750
764
  version: 1
751
765
  name: "defaults"
@@ -754,9 +768,11 @@ steps:
754
768
  name: "A"
755
769
  prompt: "do A"
756
770
  `);
757
- t.after(() => { try { rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch { /* Windows EPERM */ } });
758
-
759
- const def = loadDefinition(dir, "test-workflow");
760
- assert.deepEqual(def.steps[0].requires, []);
761
- assert.deepEqual(def.steps[0].produces, []);
771
+ try {
772
+ const def = loadDefinition(dir, "test-workflow");
773
+ assert.deepEqual(def.steps[0].requires, []);
774
+ assert.deepEqual(def.steps[0].produces, []);
775
+ } finally {
776
+ try { rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch { /* Windows EPERM */ }
777
+ }
762
778
  });
@@ -1,5 +1,3 @@
1
- import { describe, test } from 'node:test';
2
- import assert from 'node:assert/strict';
3
1
  // derive-state-crossval.test.ts — Cross-validation: deriveStateFromDb() vs _deriveStateImpl()
4
2
  // Proves both paths produce field-identical GSDState across 7 fixture scenarios,
5
3
  // plus an auto-migration round-trip test.
@@ -21,8 +19,11 @@ import {
21
19
  insertTask,
22
20
  } from '../gsd-db.ts';
23
21
  import { migrateHierarchyToDb } from '../md-importer.ts';
22
+ import { createTestContext } from './test-helpers.ts';
24
23
  import type { GSDState } from '../types.ts';
25
24
 
25
+ const { assertEq, assertTrue, report } = createTestContext();
26
+
26
27
  // ─── Fixture Helpers ───────────────────────────────────────────────────────
27
28
 
28
29
  function createFixtureBase(): string {
@@ -47,29 +48,29 @@ function cleanup(base: string): void {
47
48
  */
48
49
  function assertStatesEqual(dbState: GSDState, fileState: GSDState, prefix: string): void {
49
50
  // Phase
50
- assert.deepStrictEqual(dbState.phase, fileState.phase, `${prefix}: phase`);
51
+ assertEq(dbState.phase, fileState.phase, `${prefix}: phase`);
51
52
 
52
53
  // Active refs
53
- assert.deepStrictEqual(dbState.activeMilestone?.id ?? null, fileState.activeMilestone?.id ?? null, `${prefix}: activeMilestone.id`);
54
- assert.deepStrictEqual(dbState.activeMilestone?.title ?? null, fileState.activeMilestone?.title ?? null, `${prefix}: activeMilestone.title`);
55
- assert.deepStrictEqual(dbState.activeSlice?.id ?? null, fileState.activeSlice?.id ?? null, `${prefix}: activeSlice.id`);
56
- assert.deepStrictEqual(dbState.activeSlice?.title ?? null, fileState.activeSlice?.title ?? null, `${prefix}: activeSlice.title`);
57
- assert.deepStrictEqual(dbState.activeTask?.id ?? null, fileState.activeTask?.id ?? null, `${prefix}: activeTask.id`);
58
- assert.deepStrictEqual(dbState.activeTask?.title ?? null, fileState.activeTask?.title ?? null, `${prefix}: activeTask.title`);
54
+ assertEq(dbState.activeMilestone?.id ?? null, fileState.activeMilestone?.id ?? null, `${prefix}: activeMilestone.id`);
55
+ assertEq(dbState.activeMilestone?.title ?? null, fileState.activeMilestone?.title ?? null, `${prefix}: activeMilestone.title`);
56
+ assertEq(dbState.activeSlice?.id ?? null, fileState.activeSlice?.id ?? null, `${prefix}: activeSlice.id`);
57
+ assertEq(dbState.activeSlice?.title ?? null, fileState.activeSlice?.title ?? null, `${prefix}: activeSlice.title`);
58
+ assertEq(dbState.activeTask?.id ?? null, fileState.activeTask?.id ?? null, `${prefix}: activeTask.id`);
59
+ assertEq(dbState.activeTask?.title ?? null, fileState.activeTask?.title ?? null, `${prefix}: activeTask.title`);
59
60
 
60
61
  // Blockers
61
- assert.deepStrictEqual(dbState.blockers.length, fileState.blockers.length, `${prefix}: blockers.length`);
62
+ assertEq(dbState.blockers.length, fileState.blockers.length, `${prefix}: blockers.length`);
62
63
 
63
64
  // Next action (may differ in wording between paths — compare presence)
64
- assert.ok(typeof dbState.nextAction === 'string', `${prefix}: nextAction is string`);
65
+ assertTrue(typeof dbState.nextAction === 'string', `${prefix}: nextAction is string`);
65
66
 
66
67
  // Registry — length and each entry
67
- assert.deepStrictEqual(dbState.registry.length, fileState.registry.length, `${prefix}: registry.length`);
68
+ assertEq(dbState.registry.length, fileState.registry.length, `${prefix}: registry.length`);
68
69
  for (let i = 0; i < fileState.registry.length; i++) {
69
- assert.deepStrictEqual(dbState.registry[i]?.id, fileState.registry[i]?.id, `${prefix}: registry[${i}].id`);
70
- assert.deepStrictEqual(dbState.registry[i]?.status, fileState.registry[i]?.status, `${prefix}: registry[${i}].status`);
70
+ assertEq(dbState.registry[i]?.id, fileState.registry[i]?.id, `${prefix}: registry[${i}].id`);
71
+ assertEq(dbState.registry[i]?.status, fileState.registry[i]?.status, `${prefix}: registry[${i}].status`);
71
72
  // dependsOn may or may not be present
72
- assert.deepStrictEqual(
73
+ assertEq(
73
74
  JSON.stringify(dbState.registry[i]?.dependsOn ?? []),
74
75
  JSON.stringify(fileState.registry[i]?.dependsOn ?? []),
75
76
  `${prefix}: registry[${i}].dependsOn`,
@@ -77,27 +78,28 @@ function assertStatesEqual(dbState: GSDState, fileState: GSDState, prefix: strin
77
78
  }
78
79
 
79
80
  // Requirements
80
- assert.deepStrictEqual(dbState.requirements?.active ?? 0, fileState.requirements?.active ?? 0, `${prefix}: requirements.active`);
81
- assert.deepStrictEqual(dbState.requirements?.validated ?? 0, fileState.requirements?.validated ?? 0, `${prefix}: requirements.validated`);
82
- assert.deepStrictEqual(dbState.requirements?.total ?? 0, fileState.requirements?.total ?? 0, `${prefix}: requirements.total`);
81
+ assertEq(dbState.requirements?.active ?? 0, fileState.requirements?.active ?? 0, `${prefix}: requirements.active`);
82
+ assertEq(dbState.requirements?.validated ?? 0, fileState.requirements?.validated ?? 0, `${prefix}: requirements.validated`);
83
+ assertEq(dbState.requirements?.total ?? 0, fileState.requirements?.total ?? 0, `${prefix}: requirements.total`);
83
84
 
84
85
  // Progress
85
- assert.deepStrictEqual(dbState.progress?.milestones?.done, fileState.progress?.milestones?.done, `${prefix}: progress.milestones.done`);
86
- assert.deepStrictEqual(dbState.progress?.milestones?.total, fileState.progress?.milestones?.total, `${prefix}: progress.milestones.total`);
87
- assert.deepStrictEqual(dbState.progress?.slices?.done ?? 0, fileState.progress?.slices?.done ?? 0, `${prefix}: progress.slices.done`);
88
- assert.deepStrictEqual(dbState.progress?.slices?.total ?? 0, fileState.progress?.slices?.total ?? 0, `${prefix}: progress.slices.total`);
89
- assert.deepStrictEqual(dbState.progress?.tasks?.done ?? 0, fileState.progress?.tasks?.done ?? 0, `${prefix}: progress.tasks.done`);
90
- assert.deepStrictEqual(dbState.progress?.tasks?.total ?? 0, fileState.progress?.tasks?.total ?? 0, `${prefix}: progress.tasks.total`);
86
+ assertEq(dbState.progress?.milestones?.done, fileState.progress?.milestones?.done, `${prefix}: progress.milestones.done`);
87
+ assertEq(dbState.progress?.milestones?.total, fileState.progress?.milestones?.total, `${prefix}: progress.milestones.total`);
88
+ assertEq(dbState.progress?.slices?.done ?? 0, fileState.progress?.slices?.done ?? 0, `${prefix}: progress.slices.done`);
89
+ assertEq(dbState.progress?.slices?.total ?? 0, fileState.progress?.slices?.total ?? 0, `${prefix}: progress.slices.total`);
90
+ assertEq(dbState.progress?.tasks?.done ?? 0, fileState.progress?.tasks?.done ?? 0, `${prefix}: progress.tasks.done`);
91
+ assertEq(dbState.progress?.tasks?.total ?? 0, fileState.progress?.tasks?.total ?? 0, `${prefix}: progress.tasks.total`);
91
92
  }
92
93
 
93
94
  // ═══════════════════════════════════════════════════════════════════════════
94
95
  // Scenario fixtures
95
96
  // ═══════════════════════════════════════════════════════════════════════════
96
97
 
97
- describe('derive-state-crossval', async () => {
98
+ async function main(): Promise<void> {
98
99
 
99
100
  // ─── Scenario A: Pre-planning — milestone with CONTEXT but no roadmap ──
100
- test('crossval A: pre-planning', async () => {
101
+ console.log('\n=== crossval A: pre-planning ===');
102
+ {
101
103
  const base = createFixtureBase();
102
104
  try {
103
105
  writeFile(base, 'milestones/M001/M001-CONTEXT.md', '# M001: New Project\n\nWe are exploring scope.');
@@ -114,17 +116,18 @@ describe('derive-state-crossval', async () => {
114
116
  const dbState = await deriveStateFromDb(base);
115
117
 
116
118
  assertStatesEqual(dbState, fileState, 'A-preplan');
117
- assert.deepStrictEqual(dbState.phase, 'pre-planning', 'A-preplan: phase is pre-planning');
119
+ assertEq(dbState.phase, 'pre-planning', 'A-preplan: phase is pre-planning');
118
120
 
119
121
  closeDatabase();
120
122
  } finally {
121
123
  closeDatabase();
122
124
  cleanup(base);
123
125
  }
124
- });
126
+ }
125
127
 
126
128
  // ─── Scenario B: Executing — 2 slices, first complete, second active ──
127
- test('crossval B: executing', async () => {
129
+ console.log('\n=== crossval B: executing ===');
130
+ {
128
131
  const base = createFixtureBase();
129
132
  try {
130
133
  const roadmap = `# M001: Test Project
@@ -179,19 +182,20 @@ skills_used: []
179
182
  const dbState = await deriveStateFromDb(base);
180
183
 
181
184
  assertStatesEqual(dbState, fileState, 'B-executing');
182
- assert.deepStrictEqual(dbState.phase, 'executing', 'B-executing: phase is executing');
183
- assert.deepStrictEqual(dbState.activeSlice?.id, 'S02', 'B-executing: activeSlice is S02');
184
- assert.deepStrictEqual(dbState.activeTask?.id, 'T02', 'B-executing: activeTask is T02');
185
+ assertEq(dbState.phase, 'executing', 'B-executing: phase is executing');
186
+ assertEq(dbState.activeSlice?.id, 'S02', 'B-executing: activeSlice is S02');
187
+ assertEq(dbState.activeTask?.id, 'T02', 'B-executing: activeTask is T02');
185
188
 
186
189
  closeDatabase();
187
190
  } finally {
188
191
  closeDatabase();
189
192
  cleanup(base);
190
193
  }
191
- });
194
+ }
192
195
 
193
196
  // ─── Scenario C: Summarizing — all tasks done, no slice summary ────────
194
- test('crossval C: summarizing', async () => {
197
+ console.log('\n=== crossval C: summarizing ===');
198
+ {
195
199
  const base = createFixtureBase();
196
200
  try {
197
201
  const roadmap = `# M001: Summarize Test
@@ -241,19 +245,20 @@ skills_used: []
241
245
  const dbState = await deriveStateFromDb(base);
242
246
 
243
247
  assertStatesEqual(dbState, fileState, 'C-summarizing');
244
- assert.deepStrictEqual(dbState.phase, 'summarizing', 'C-summarizing: phase is summarizing');
245
- assert.deepStrictEqual(dbState.activeSlice?.id, 'S01', 'C-summarizing: activeSlice is S01');
246
- assert.deepStrictEqual(dbState.activeTask, null, 'C-summarizing: no activeTask');
248
+ assertEq(dbState.phase, 'summarizing', 'C-summarizing: phase is summarizing');
249
+ assertEq(dbState.activeSlice?.id, 'S01', 'C-summarizing: activeSlice is S01');
250
+ assertEq(dbState.activeTask, null, 'C-summarizing: no activeTask');
247
251
 
248
252
  closeDatabase();
249
253
  } finally {
250
254
  closeDatabase();
251
255
  cleanup(base);
252
256
  }
253
- });
257
+ }
254
258
 
255
259
  // ─── Scenario D: Multi-milestone — M001 complete, M002 active ─────────
256
- test('crossval D: multi-milestone', async () => {
260
+ console.log('\n=== crossval D: multi-milestone ===');
261
+ {
257
262
  const base = createFixtureBase();
258
263
  try {
259
264
  const m1Roadmap = `# M001: First Milestone
@@ -308,23 +313,24 @@ skills_used: []
308
313
  const dbState = await deriveStateFromDb(base);
309
314
 
310
315
  assertStatesEqual(dbState, fileState, 'D-multims');
311
- assert.deepStrictEqual(dbState.activeMilestone?.id, 'M002', 'D-multims: activeMilestone is M002');
312
- assert.deepStrictEqual(dbState.registry.length, 2, 'D-multims: 2 milestones in registry');
316
+ assertEq(dbState.activeMilestone?.id, 'M002', 'D-multims: activeMilestone is M002');
317
+ assertEq(dbState.registry.length, 2, 'D-multims: 2 milestones in registry');
313
318
 
314
319
  const m1 = dbState.registry.find(e => e.id === 'M001');
315
320
  const m2 = dbState.registry.find(e => e.id === 'M002');
316
- assert.deepStrictEqual(m1?.status, 'complete', 'D-multims: M001 complete');
317
- assert.deepStrictEqual(m2?.status, 'active', 'D-multims: M002 active');
321
+ assertEq(m1?.status, 'complete', 'D-multims: M001 complete');
322
+ assertEq(m2?.status, 'active', 'D-multims: M002 active');
318
323
 
319
324
  closeDatabase();
320
325
  } finally {
321
326
  closeDatabase();
322
327
  cleanup(base);
323
328
  }
324
- });
329
+ }
325
330
 
326
331
  // ─── Scenario E: Blocked — circular slice deps ────────────────────────
327
- test('crossval E: blocked', async () => {
332
+ console.log('\n=== crossval E: blocked ===');
333
+ {
328
334
  const base = createFixtureBase();
329
335
  try {
330
336
  const roadmap = `# M001: Blocked Test
@@ -351,18 +357,19 @@ skills_used: []
351
357
  const dbState = await deriveStateFromDb(base);
352
358
 
353
359
  assertStatesEqual(dbState, fileState, 'E-blocked');
354
- assert.deepStrictEqual(dbState.phase, 'blocked', 'E-blocked: phase is blocked');
355
- assert.ok(dbState.blockers.length > 0, 'E-blocked: has blockers');
360
+ assertEq(dbState.phase, 'blocked', 'E-blocked: phase is blocked');
361
+ assertTrue(dbState.blockers.length > 0, 'E-blocked: has blockers');
356
362
 
357
363
  closeDatabase();
358
364
  } finally {
359
365
  closeDatabase();
360
366
  cleanup(base);
361
367
  }
362
- });
368
+ }
363
369
 
364
370
  // ─── Scenario F: Parked — PARKED file on milestone ────────────────────
365
- test('crossval F: parked', async () => {
371
+ console.log('\n=== crossval F: parked ===');
372
+ {
366
373
  const base = createFixtureBase();
367
374
  try {
368
375
  const roadmap = `# M001: Parked Milestone
@@ -389,19 +396,20 @@ skills_used: []
389
396
  const dbState = await deriveStateFromDb(base);
390
397
 
391
398
  assertStatesEqual(dbState, fileState, 'F-parked');
392
- assert.deepStrictEqual(dbState.activeMilestone?.id, 'M002', 'F-parked: activeMilestone is M002');
393
- assert.ok(dbState.registry.some(e => e.id === 'M001' && e.status === 'parked'), 'F-parked: M001 parked');
399
+ assertEq(dbState.activeMilestone?.id, 'M002', 'F-parked: activeMilestone is M002');
400
+ assertTrue(dbState.registry.some(e => e.id === 'M001' && e.status === 'parked'), 'F-parked: M001 parked');
394
401
 
395
402
  closeDatabase();
396
403
  } finally {
397
404
  closeDatabase();
398
405
  cleanup(base);
399
406
  }
400
- });
407
+ }
401
408
 
402
409
  // ─── Scenario G: Auto-migration round-trip ────────────────────────────
403
410
  // Create a markdown-only fixture (no DB). Migrate to DB. Both paths identical.
404
- test('crossval G: auto-migration round-trip', async () => {
411
+ console.log('\n=== crossval G: auto-migration round-trip ===');
412
+ {
405
413
  const base = createFixtureBase();
406
414
  try {
407
415
  const roadmap = `# M001: Migration Test
@@ -481,9 +489,9 @@ skills_used: []
481
489
  const counts = migrateHierarchyToDb(base);
482
490
 
483
491
  // Verify migration populated correctly
484
- assert.ok(counts.milestones >= 1, 'G-roundtrip: migrated milestones');
485
- assert.ok(counts.slices >= 2, 'G-roundtrip: migrated slices');
486
- assert.ok(counts.tasks >= 3, 'G-roundtrip: migrated tasks');
492
+ assertTrue(counts.milestones >= 1, 'G-roundtrip: migrated milestones');
493
+ assertTrue(counts.slices >= 2, 'G-roundtrip: migrated slices');
494
+ assertTrue(counts.tasks >= 3, 'G-roundtrip: migrated tasks');
487
495
 
488
496
  // Step 3: Get DB-backed state
489
497
  invalidateStateCache();
@@ -491,22 +499,29 @@ skills_used: []
491
499
 
492
500
  // Step 4: Deep cross-validation
493
501
  assertStatesEqual(dbState, fileState, 'G-roundtrip');
494
- assert.deepStrictEqual(dbState.phase, 'executing', 'G-roundtrip: phase is executing');
495
- assert.deepStrictEqual(dbState.activeSlice?.id, 'S02', 'G-roundtrip: activeSlice is S02');
496
- assert.deepStrictEqual(dbState.activeTask?.id, 'T02', 'G-roundtrip: activeTask is T02');
497
- assert.deepStrictEqual(dbState.requirements?.active, 1, 'G-roundtrip: requirements.active = 1');
498
- assert.deepStrictEqual(dbState.requirements?.validated, 1, 'G-roundtrip: requirements.validated = 1');
499
- assert.deepStrictEqual(dbState.requirements?.deferred, 1, 'G-roundtrip: requirements.deferred = 1');
500
- assert.deepStrictEqual(dbState.requirements?.total, 3, 'G-roundtrip: requirements.total = 3');
501
- assert.deepStrictEqual(dbState.progress?.slices?.done, 1, 'G-roundtrip: slices.done = 1');
502
- assert.deepStrictEqual(dbState.progress?.slices?.total, 3, 'G-roundtrip: slices.total = 3');
503
- assert.deepStrictEqual(dbState.progress?.tasks?.done, 1, 'G-roundtrip: tasks.done = 1');
504
- assert.deepStrictEqual(dbState.progress?.tasks?.total, 3, 'G-roundtrip: tasks.total = 3');
502
+ assertEq(dbState.phase, 'executing', 'G-roundtrip: phase is executing');
503
+ assertEq(dbState.activeSlice?.id, 'S02', 'G-roundtrip: activeSlice is S02');
504
+ assertEq(dbState.activeTask?.id, 'T02', 'G-roundtrip: activeTask is T02');
505
+ assertEq(dbState.requirements?.active, 1, 'G-roundtrip: requirements.active = 1');
506
+ assertEq(dbState.requirements?.validated, 1, 'G-roundtrip: requirements.validated = 1');
507
+ assertEq(dbState.requirements?.deferred, 1, 'G-roundtrip: requirements.deferred = 1');
508
+ assertEq(dbState.requirements?.total, 3, 'G-roundtrip: requirements.total = 3');
509
+ assertEq(dbState.progress?.slices?.done, 1, 'G-roundtrip: slices.done = 1');
510
+ assertEq(dbState.progress?.slices?.total, 3, 'G-roundtrip: slices.total = 3');
511
+ assertEq(dbState.progress?.tasks?.done, 1, 'G-roundtrip: tasks.done = 1');
512
+ assertEq(dbState.progress?.tasks?.total, 3, 'G-roundtrip: tasks.total = 3');
505
513
 
506
514
  closeDatabase();
507
515
  } finally {
508
516
  closeDatabase();
509
517
  cleanup(base);
510
518
  }
511
- });
519
+ }
520
+
521
+ report();
522
+ }
523
+
524
+ main().catch((error) => {
525
+ console.error(error);
526
+ process.exit(1);
512
527
  });