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
@@ -10,9 +10,9 @@ import { parsePlanningDirectory } from '../migrate/parser.ts';
10
10
  import { validatePlanningDirectory } from '../migrate/validator.ts';
11
11
 
12
12
  import type { PlanningProject, ValidationResult } from '../migrate/types.ts';
13
- import { describe, test, beforeEach, afterEach } from 'node:test';
14
- import assert from 'node:assert/strict';
13
+ import { createTestContext } from './test-helpers.ts';
15
14
 
15
+ const { assertEq, assertTrue, report } = createTestContext();
16
16
  // ─── Fixture Helpers ───────────────────────────────────────────────────────
17
17
 
18
18
  function createFixtureBase(): string {
@@ -241,9 +241,11 @@ Fixed the login button by correcting the touch event handler.
241
241
  // Test Groups
242
242
  // ═══════════════════════════════════════════════════════════════════════════
243
243
 
244
- // ─── Test 1: Complete .planning directory ──────────────────────────────
244
+ async function main(): Promise<void> {
245
245
 
246
- test('Complete .planning directory with all file types', async () => {
246
+ // ─── Test 1: Complete .planning directory ──────────────────────────────
247
+ console.log('\n=== Complete .planning directory with all file types ===');
248
+ {
247
249
  const base = createFixtureBase();
248
250
  try {
249
251
  const planning = createPlanningDir(base);
@@ -311,86 +313,86 @@ Dashboard needs auth to be complete first.
311
313
  const project = await parsePlanningDirectory(planning);
312
314
 
313
315
  // Top-level structure
314
- assert.deepStrictEqual(project.path, planning, 'project.path matches');
315
- assert.ok(project.project !== null, 'PROJECT.md parsed');
316
- assert.ok(project.roadmap !== null, 'ROADMAP.md parsed');
317
- assert.ok(project.requirements.length > 0, 'requirements parsed');
318
- assert.ok(project.state !== null, 'STATE.md parsed');
319
- assert.ok(project.config !== null, 'config.json parsed');
316
+ assertEq(project.path, planning, 'project.path matches');
317
+ assertTrue(project.project !== null, 'PROJECT.md parsed');
318
+ assertTrue(project.roadmap !== null, 'ROADMAP.md parsed');
319
+ assertTrue(project.requirements.length > 0, 'requirements parsed');
320
+ assertTrue(project.state !== null, 'STATE.md parsed');
321
+ assertTrue(project.config !== null, 'config.json parsed');
320
322
 
321
323
  // Phases
322
- assert.ok('29-auth-system' in project.phases, 'phase 29 present');
323
- assert.ok('30-dashboard' in project.phases, 'phase 30 present');
324
+ assertTrue('29-auth-system' in project.phases, 'phase 29 present');
325
+ assertTrue('30-dashboard' in project.phases, 'phase 30 present');
324
326
 
325
327
  const phase29 = project.phases['29-auth-system'];
326
- assert.deepStrictEqual(phase29?.number, 29, 'phase 29 number');
327
- assert.deepStrictEqual(phase29?.slug, 'auth-system', 'phase 29 slug');
328
- assert.ok('01' in (phase29?.plans ?? {}), 'phase 29 has plan 01');
329
- assert.ok('01' in (phase29?.summaries ?? {}), 'phase 29 has summary 01');
330
- assert.ok((phase29?.research?.length ?? 0) > 0, 'phase 29 has research');
328
+ assertEq(phase29?.number, 29, 'phase 29 number');
329
+ assertEq(phase29?.slug, 'auth-system', 'phase 29 slug');
330
+ assertTrue('01' in (phase29?.plans ?? {}), 'phase 29 has plan 01');
331
+ assertTrue('01' in (phase29?.summaries ?? {}), 'phase 29 has summary 01');
332
+ assertTrue((phase29?.research?.length ?? 0) > 0, 'phase 29 has research');
331
333
 
332
334
  // Plan content (XML-in-markdown)
333
335
  const plan29 = phase29?.plans?.['01'];
334
- assert.ok(plan29 !== undefined, 'plan 29-01 exists');
335
- assert.ok(plan29?.objective?.includes('authentication') ?? false, 'plan objective extracted');
336
- assert.ok((plan29?.tasks?.length ?? 0) >= 3, 'plan tasks extracted');
337
- assert.ok(plan29?.context?.includes('JWT') ?? false, 'plan context extracted');
338
- assert.ok(plan29?.verification !== '', 'plan verification extracted');
339
- assert.ok(plan29?.successCriteria !== '', 'plan success criteria extracted');
336
+ assertTrue(plan29 !== undefined, 'plan 29-01 exists');
337
+ assertTrue(plan29?.objective?.includes('authentication') ?? false, 'plan objective extracted');
338
+ assertTrue((plan29?.tasks?.length ?? 0) >= 3, 'plan tasks extracted');
339
+ assertTrue(plan29?.context?.includes('JWT') ?? false, 'plan context extracted');
340
+ assertTrue(plan29?.verification !== '', 'plan verification extracted');
341
+ assertTrue(plan29?.successCriteria !== '', 'plan success criteria extracted');
340
342
 
341
343
  // Plan frontmatter
342
- assert.deepStrictEqual(plan29?.frontmatter?.phase, '29-auth-system', 'plan frontmatter phase');
343
- assert.deepStrictEqual(plan29?.frontmatter?.plan, '01', 'plan frontmatter plan');
344
- assert.deepStrictEqual(plan29?.frontmatter?.type, 'implementation', 'plan frontmatter type');
345
- assert.deepStrictEqual(plan29?.frontmatter?.wave, 1, 'plan frontmatter wave');
346
- assert.deepStrictEqual(plan29?.frontmatter?.autonomous, true, 'plan frontmatter autonomous');
344
+ assertEq(plan29?.frontmatter?.phase, '29-auth-system', 'plan frontmatter phase');
345
+ assertEq(plan29?.frontmatter?.plan, '01', 'plan frontmatter plan');
346
+ assertEq(plan29?.frontmatter?.type, 'implementation', 'plan frontmatter type');
347
+ assertEq(plan29?.frontmatter?.wave, 1, 'plan frontmatter wave');
348
+ assertEq(plan29?.frontmatter?.autonomous, true, 'plan frontmatter autonomous');
347
349
 
348
350
  // Summary content
349
351
  const summary29 = phase29?.summaries?.['01'];
350
- assert.ok(summary29 !== undefined, 'summary 29-01 exists');
351
- assert.deepStrictEqual(summary29?.frontmatter?.phase, '29-auth-system', 'summary frontmatter phase');
352
- assert.deepStrictEqual(summary29?.frontmatter?.plan, '01', 'summary frontmatter plan');
353
- assert.deepStrictEqual(summary29?.frontmatter?.subsystem, 'auth', 'summary frontmatter subsystem');
354
- assert.ok((summary29?.frontmatter?.tags?.length ?? 0) >= 2, 'summary frontmatter tags');
355
- assert.ok((summary29?.frontmatter?.provides?.length ?? 0) >= 2, 'summary frontmatter provides');
356
- assert.ok((summary29?.frontmatter?.affects?.length ?? 0) >= 1, 'summary frontmatter affects');
357
- assert.ok((summary29?.frontmatter?.['tech-stack']?.length ?? 0) >= 2, 'summary frontmatter tech-stack');
358
- assert.ok((summary29?.frontmatter?.['key-files']?.length ?? 0) >= 2, 'summary frontmatter key-files');
359
- assert.ok((summary29?.frontmatter?.['key-decisions']?.length ?? 0) >= 2, 'summary frontmatter key-decisions');
360
- assert.ok((summary29?.frontmatter?.['patterns-established']?.length ?? 0) >= 1, 'summary frontmatter patterns-established');
361
- assert.deepStrictEqual(summary29?.frontmatter?.duration, '2h', 'summary frontmatter duration');
362
- assert.deepStrictEqual(summary29?.frontmatter?.completed, '2026-01-15', 'summary frontmatter completed');
352
+ assertTrue(summary29 !== undefined, 'summary 29-01 exists');
353
+ assertEq(summary29?.frontmatter?.phase, '29-auth-system', 'summary frontmatter phase');
354
+ assertEq(summary29?.frontmatter?.plan, '01', 'summary frontmatter plan');
355
+ assertEq(summary29?.frontmatter?.subsystem, 'auth', 'summary frontmatter subsystem');
356
+ assertTrue((summary29?.frontmatter?.tags?.length ?? 0) >= 2, 'summary frontmatter tags');
357
+ assertTrue((summary29?.frontmatter?.provides?.length ?? 0) >= 2, 'summary frontmatter provides');
358
+ assertTrue((summary29?.frontmatter?.affects?.length ?? 0) >= 1, 'summary frontmatter affects');
359
+ assertTrue((summary29?.frontmatter?.['tech-stack']?.length ?? 0) >= 2, 'summary frontmatter tech-stack');
360
+ assertTrue((summary29?.frontmatter?.['key-files']?.length ?? 0) >= 2, 'summary frontmatter key-files');
361
+ assertTrue((summary29?.frontmatter?.['key-decisions']?.length ?? 0) >= 2, 'summary frontmatter key-decisions');
362
+ assertTrue((summary29?.frontmatter?.['patterns-established']?.length ?? 0) >= 1, 'summary frontmatter patterns-established');
363
+ assertEq(summary29?.frontmatter?.duration, '2h', 'summary frontmatter duration');
364
+ assertEq(summary29?.frontmatter?.completed, '2026-01-15', 'summary frontmatter completed');
363
365
 
364
366
  // Quick tasks
365
- assert.ok(project.quickTasks.length >= 1, 'quick tasks parsed');
366
- assert.deepStrictEqual(project.quickTasks[0]?.number, 1, 'quick task number');
367
- assert.ok(project.quickTasks[0]?.plan !== null, 'quick task has plan');
368
- assert.ok(project.quickTasks[0]?.summary !== null, 'quick task has summary');
367
+ assertTrue(project.quickTasks.length >= 1, 'quick tasks parsed');
368
+ assertEq(project.quickTasks[0]?.number, 1, 'quick task number');
369
+ assertTrue(project.quickTasks[0]?.plan !== null, 'quick task has plan');
370
+ assertTrue(project.quickTasks[0]?.summary !== null, 'quick task has summary');
369
371
 
370
372
  // Milestones
371
- assert.ok(project.milestones.length >= 1, 'milestones parsed');
373
+ assertTrue(project.milestones.length >= 1, 'milestones parsed');
372
374
 
373
375
  // Root research
374
- assert.ok(project.research.length >= 1, 'root research parsed');
376
+ assertTrue(project.research.length >= 1, 'root research parsed');
375
377
 
376
378
  // Config
377
- assert.deepStrictEqual(project.config?.projectName, 'test-project', 'config projectName');
379
+ assertEq(project.config?.projectName, 'test-project', 'config projectName');
378
380
 
379
381
  // State
380
- assert.ok(project.state?.currentPhase?.includes('30') ?? false, 'state current phase');
381
- assert.deepStrictEqual(project.state?.status, 'in-progress', 'state status');
382
+ assertTrue(project.state?.currentPhase?.includes('30') ?? false, 'state current phase');
383
+ assertEq(project.state?.status, 'in-progress', 'state status');
382
384
 
383
385
  // Validation
384
- assert.deepStrictEqual(project.validation.valid, true, 'validation passes for complete dir');
385
- assert.deepStrictEqual(project.validation.issues.length, 0, 'no validation issues');
386
+ assertEq(project.validation.valid, true, 'validation passes for complete dir');
387
+ assertEq(project.validation.issues.length, 0, 'no validation issues');
386
388
  } finally {
387
389
  cleanup(base);
388
390
  }
389
- });
391
+ }
390
392
 
391
393
  // ─── Test 2: Minimal .planning directory (only ROADMAP.md) ─────────────
392
-
393
- test('Minimal .planning directory (only ROADMAP.md)', async () => {
394
+ console.log('\n=== Minimal .planning directory (only ROADMAP.md) ===');
395
+ {
394
396
  const base = createFixtureBase();
395
397
  try {
396
398
  const planning = createPlanningDir(base);
@@ -398,42 +400,42 @@ test('Minimal .planning directory (only ROADMAP.md)', async () => {
398
400
 
399
401
  const project = await parsePlanningDirectory(planning);
400
402
 
401
- assert.deepStrictEqual(project.project, null, 'minimal: PROJECT.md is null');
402
- assert.ok(project.roadmap !== null, 'minimal: ROADMAP.md parsed');
403
- assert.deepStrictEqual(project.requirements.length, 0, 'minimal: no requirements');
404
- assert.deepStrictEqual(project.state, null, 'minimal: no state');
405
- assert.deepStrictEqual(project.config, null, 'minimal: no config');
406
- assert.deepStrictEqual(Object.keys(project.phases).length, 0, 'minimal: no phases');
407
- assert.deepStrictEqual(project.quickTasks.length, 0, 'minimal: no quick tasks');
408
- assert.deepStrictEqual(project.milestones.length, 0, 'minimal: no milestones');
409
- assert.deepStrictEqual(project.research.length, 0, 'minimal: no research');
410
- assert.deepStrictEqual(project.validation.valid, true, 'minimal: validation passes');
403
+ assertEq(project.project, null, 'minimal: PROJECT.md is null');
404
+ assertTrue(project.roadmap !== null, 'minimal: ROADMAP.md parsed');
405
+ assertEq(project.requirements.length, 0, 'minimal: no requirements');
406
+ assertEq(project.state, null, 'minimal: no state');
407
+ assertEq(project.config, null, 'minimal: no config');
408
+ assertEq(Object.keys(project.phases).length, 0, 'minimal: no phases');
409
+ assertEq(project.quickTasks.length, 0, 'minimal: no quick tasks');
410
+ assertEq(project.milestones.length, 0, 'minimal: no milestones');
411
+ assertEq(project.research.length, 0, 'minimal: no research');
412
+ assertEq(project.validation.valid, true, 'minimal: validation passes');
411
413
  } finally {
412
414
  cleanup(base);
413
415
  }
414
- });
416
+ }
415
417
 
416
418
  // ─── Test 3: Missing directory → validation fatal error ────────────────
417
-
418
- test('Missing directory → validation returns fatal error', async () => {
419
+ console.log('\n=== Missing directory → validation returns fatal error ===');
420
+ {
419
421
  const base = createFixtureBase();
420
422
  try {
421
423
  const result = await validatePlanningDirectory(join(base, 'nonexistent'));
422
424
 
423
- assert.deepStrictEqual(result.valid, false, 'missing dir: validation fails');
424
- assert.ok(result.issues.length > 0, 'missing dir: has issues');
425
- assert.ok(
425
+ assertEq(result.valid, false, 'missing dir: validation fails');
426
+ assertTrue(result.issues.length > 0, 'missing dir: has issues');
427
+ assertTrue(
426
428
  result.issues.some(i => i.severity === 'fatal'),
427
429
  'missing dir: has fatal issue'
428
430
  );
429
431
  } finally {
430
432
  cleanup(base);
431
433
  }
432
- });
434
+ }
433
435
 
434
436
  // ─── Test 4: Duplicate phase numbers ───────────────────────────────────
435
-
436
- test('Phase directory with duplicate numbers', async () => {
437
+ console.log('\n=== Phase directory with duplicate numbers ===');
438
+ {
437
439
  const base = createFixtureBase();
438
440
  try {
439
441
  const planning = createPlanningDir(base);
@@ -454,18 +456,18 @@ test('Phase directory with duplicate numbers', async () => {
454
456
 
455
457
  const project = await parsePlanningDirectory(planning);
456
458
 
457
- assert.ok('45-core-infrastructure' in project.phases, 'dup nums: core-infrastructure phase present');
458
- assert.ok('45-logging-config' in project.phases, 'dup nums: logging-config phase present');
459
- assert.deepStrictEqual(project.phases['45-core-infrastructure']?.number, 45, 'dup nums: both have number 45 (a)');
460
- assert.deepStrictEqual(project.phases['45-logging-config']?.number, 45, 'dup nums: both have number 45 (b)');
459
+ assertTrue('45-core-infrastructure' in project.phases, 'dup nums: core-infrastructure phase present');
460
+ assertTrue('45-logging-config' in project.phases, 'dup nums: logging-config phase present');
461
+ assertEq(project.phases['45-core-infrastructure']?.number, 45, 'dup nums: both have number 45 (a)');
462
+ assertEq(project.phases['45-logging-config']?.number, 45, 'dup nums: both have number 45 (b)');
461
463
  } finally {
462
464
  cleanup(base);
463
465
  }
464
- });
466
+ }
465
467
 
466
468
  // ─── Test 5: XML-in-markdown plan parsing ──────────────────────────────
467
-
468
- test('Plan file with XML-in-markdown', async () => {
469
+ console.log('\n=== Plan file with XML-in-markdown ===');
470
+ {
469
471
  const base = createFixtureBase();
470
472
  try {
471
473
  const planning = createPlanningDir(base);
@@ -478,21 +480,21 @@ test('Plan file with XML-in-markdown', async () => {
478
480
  const project = await parsePlanningDirectory(planning);
479
481
  const plan = project.phases['29-auth-system']?.plans?.['01'];
480
482
 
481
- assert.ok(plan !== undefined, 'xml plan: plan exists');
482
- assert.ok(plan?.objective?.includes('authentication') ?? false, 'xml plan: objective extracted');
483
- assert.ok((plan?.tasks?.length ?? 0) === 3, 'xml plan: 3 tasks extracted');
484
- assert.ok(plan?.tasks?.[0]?.includes('auth middleware') ?? false, 'xml plan: first task content');
485
- assert.ok(plan?.context?.includes('JWT') ?? false, 'xml plan: context extracted');
486
- assert.ok(plan?.verification?.includes('Login returns') ?? false, 'xml plan: verification extracted');
487
- assert.ok(plan?.successCriteria?.includes('endpoints respond') ?? false, 'xml plan: success criteria extracted');
483
+ assertTrue(plan !== undefined, 'xml plan: plan exists');
484
+ assertTrue(plan?.objective?.includes('authentication') ?? false, 'xml plan: objective extracted');
485
+ assertTrue((plan?.tasks?.length ?? 0) === 3, 'xml plan: 3 tasks extracted');
486
+ assertTrue(plan?.tasks?.[0]?.includes('auth middleware') ?? false, 'xml plan: first task content');
487
+ assertTrue(plan?.context?.includes('JWT') ?? false, 'xml plan: context extracted');
488
+ assertTrue(plan?.verification?.includes('Login returns') ?? false, 'xml plan: verification extracted');
489
+ assertTrue(plan?.successCriteria?.includes('endpoints respond') ?? false, 'xml plan: success criteria extracted');
488
490
  } finally {
489
491
  cleanup(base);
490
492
  }
491
- });
493
+ }
492
494
 
493
495
  // ─── Test 6: Summary file with YAML frontmatter ───────────────────────
494
-
495
- test('Summary file with YAML frontmatter', async () => {
496
+ console.log('\n=== Summary file with YAML frontmatter ===');
497
+ {
496
498
  const base = createFixtureBase();
497
499
  try {
498
500
  const planning = createPlanningDir(base);
@@ -505,27 +507,27 @@ test('Summary file with YAML frontmatter', async () => {
505
507
  const project = await parsePlanningDirectory(planning);
506
508
  const summary = project.phases['29-auth-system']?.summaries?.['01'];
507
509
 
508
- assert.ok(summary !== undefined, 'summary fm: summary exists');
509
- assert.deepStrictEqual(summary?.frontmatter?.phase, '29-auth-system', 'summary fm: phase');
510
- assert.deepStrictEqual(summary?.frontmatter?.plan, '01', 'summary fm: plan');
511
- assert.deepStrictEqual(summary?.frontmatter?.subsystem, 'auth', 'summary fm: subsystem');
512
- assert.deepStrictEqual(summary?.frontmatter?.tags, ['authentication', 'security'], 'summary fm: tags');
513
- assert.deepStrictEqual(summary?.frontmatter?.provides, ['auth-middleware', 'jwt-validation'], 'summary fm: provides');
514
- assert.deepStrictEqual(summary?.frontmatter?.affects, ['api-routes'], 'summary fm: affects');
515
- assert.deepStrictEqual(summary?.frontmatter?.['tech-stack'], ['jsonwebtoken', 'express'], 'summary fm: tech-stack');
516
- assert.deepStrictEqual(summary?.frontmatter?.['key-files'], ['src/auth.ts', 'src/middleware/auth.ts'], 'summary fm: key-files');
517
- assert.deepStrictEqual(summary?.frontmatter?.['key-decisions'], ['Use RS256 for JWT signing', 'Store refresh tokens in DB'], 'summary fm: key-decisions');
518
- assert.deepStrictEqual(summary?.frontmatter?.['patterns-established'], ['Middleware-based auth'], 'summary fm: patterns-established');
519
- assert.deepStrictEqual(summary?.frontmatter?.duration, '2h', 'summary fm: duration');
520
- assert.deepStrictEqual(summary?.frontmatter?.completed, '2026-01-15', 'summary fm: completed');
510
+ assertTrue(summary !== undefined, 'summary fm: summary exists');
511
+ assertEq(summary?.frontmatter?.phase, '29-auth-system', 'summary fm: phase');
512
+ assertEq(summary?.frontmatter?.plan, '01', 'summary fm: plan');
513
+ assertEq(summary?.frontmatter?.subsystem, 'auth', 'summary fm: subsystem');
514
+ assertEq(summary?.frontmatter?.tags, ['authentication', 'security'], 'summary fm: tags');
515
+ assertEq(summary?.frontmatter?.provides, ['auth-middleware', 'jwt-validation'], 'summary fm: provides');
516
+ assertEq(summary?.frontmatter?.affects, ['api-routes'], 'summary fm: affects');
517
+ assertEq(summary?.frontmatter?.['tech-stack'], ['jsonwebtoken', 'express'], 'summary fm: tech-stack');
518
+ assertEq(summary?.frontmatter?.['key-files'], ['src/auth.ts', 'src/middleware/auth.ts'], 'summary fm: key-files');
519
+ assertEq(summary?.frontmatter?.['key-decisions'], ['Use RS256 for JWT signing', 'Store refresh tokens in DB'], 'summary fm: key-decisions');
520
+ assertEq(summary?.frontmatter?.['patterns-established'], ['Middleware-based auth'], 'summary fm: patterns-established');
521
+ assertEq(summary?.frontmatter?.duration, '2h', 'summary fm: duration');
522
+ assertEq(summary?.frontmatter?.completed, '2026-01-15', 'summary fm: completed');
521
523
  } finally {
522
524
  cleanup(base);
523
525
  }
524
- });
526
+ }
525
527
 
526
528
  // ─── Test 7: Orphan summaries (no matching plan) ──────────────────────
527
-
528
- test('Orphan summaries (no matching plan)', async () => {
529
+ console.log('\n=== Orphan summaries (no matching plan) ===');
530
+ {
529
531
  const base = createFixtureBase();
530
532
  try {
531
533
  const planning = createPlanningDir(base);
@@ -559,19 +561,19 @@ Another orphan.
559
561
  const project = await parsePlanningDirectory(planning);
560
562
  const phase = project.phases['45-logging-config'];
561
563
 
562
- assert.ok(phase !== undefined, 'orphan: phase exists');
563
- assert.deepStrictEqual(Object.keys(phase?.plans ?? {}).length, 0, 'orphan: no plans');
564
- assert.ok(Object.keys(phase?.summaries ?? {}).length >= 2, 'orphan: summaries preserved');
565
- assert.ok('04' in (phase?.summaries ?? {}), 'orphan: summary 04 present');
566
- assert.ok('05' in (phase?.summaries ?? {}), 'orphan: summary 05 present');
564
+ assertTrue(phase !== undefined, 'orphan: phase exists');
565
+ assertEq(Object.keys(phase?.plans ?? {}).length, 0, 'orphan: no plans');
566
+ assertTrue(Object.keys(phase?.summaries ?? {}).length >= 2, 'orphan: summaries preserved');
567
+ assertTrue('04' in (phase?.summaries ?? {}), 'orphan: summary 04 present');
568
+ assertTrue('05' in (phase?.summaries ?? {}), 'orphan: summary 05 present');
567
569
  } finally {
568
570
  cleanup(base);
569
571
  }
570
- });
572
+ }
571
573
 
572
574
  // ─── Test 8: .archive/ directory skipped ──────────────────────────────
573
-
574
- test('.archive/ directory → skipped by default', async () => {
575
+ console.log('\n=== .archive/ directory → skipped by default ===');
576
+ {
575
577
  const base = createFixtureBase();
576
578
  try {
577
579
  const planning = createPlanningDir(base);
@@ -589,17 +591,17 @@ test('.archive/ directory → skipped by default', async () => {
589
591
 
590
592
  const project = await parsePlanningDirectory(planning);
591
593
 
592
- assert.ok('29-auth-system' in project.phases, 'archive: normal phase present');
594
+ assertTrue('29-auth-system' in project.phases, 'archive: normal phase present');
593
595
  // Archive phases should not appear in the phases map
594
- assert.ok(!Object.keys(project.phases).some(k => k.includes('old-auth')), 'archive: archived phase not present');
596
+ assertTrue(!Object.keys(project.phases).some(k => k.includes('old-auth')), 'archive: archived phase not present');
595
597
  } finally {
596
598
  cleanup(base);
597
599
  }
598
- });
600
+ }
599
601
 
600
602
  // ─── Test 9: Quick tasks ──────────────────────────────────────────────
601
-
602
- test('Quick tasks parsed', async () => {
603
+ console.log('\n=== Quick tasks parsed ===');
604
+ {
603
605
  const base = createFixtureBase();
604
606
  try {
605
607
  const planning = createPlanningDir(base);
@@ -618,22 +620,22 @@ test('Quick tasks parsed', async () => {
618
620
 
619
621
  const project = await parsePlanningDirectory(planning);
620
622
 
621
- assert.deepStrictEqual(project.quickTasks.length, 2, 'quick: 2 quick tasks');
622
- assert.deepStrictEqual(project.quickTasks[0]?.number, 1, 'quick: first task number');
623
- assert.deepStrictEqual(project.quickTasks[0]?.slug, 'fix-login', 'quick: first task slug');
624
- assert.ok(project.quickTasks[0]?.plan !== null, 'quick: first task has plan');
625
- assert.ok(project.quickTasks[0]?.summary !== null, 'quick: first task has summary');
626
- assert.deepStrictEqual(project.quickTasks[1]?.number, 2, 'quick: second task number');
627
- assert.ok(project.quickTasks[1]?.plan !== null, 'quick: second task has plan');
628
- assert.deepStrictEqual(project.quickTasks[1]?.summary, null, 'quick: second task has no summary');
623
+ assertEq(project.quickTasks.length, 2, 'quick: 2 quick tasks');
624
+ assertEq(project.quickTasks[0]?.number, 1, 'quick: first task number');
625
+ assertEq(project.quickTasks[0]?.slug, 'fix-login', 'quick: first task slug');
626
+ assertTrue(project.quickTasks[0]?.plan !== null, 'quick: first task has plan');
627
+ assertTrue(project.quickTasks[0]?.summary !== null, 'quick: first task has summary');
628
+ assertEq(project.quickTasks[1]?.number, 2, 'quick: second task number');
629
+ assertTrue(project.quickTasks[1]?.plan !== null, 'quick: second task has plan');
630
+ assertEq(project.quickTasks[1]?.summary, null, 'quick: second task has no summary');
629
631
  } finally {
630
632
  cleanup(base);
631
633
  }
632
- });
634
+ }
633
635
 
634
636
  // ─── Test 10: Roadmap with milestone sections and <details> ────────────
635
-
636
- test('Roadmap with milestone sections and <details> blocks', async () => {
637
+ console.log('\n=== Roadmap with milestone sections and <details> blocks ===');
638
+ {
637
639
  const base = createFixtureBase();
638
640
  try {
639
641
  const planning = createPlanningDir(base);
@@ -641,35 +643,35 @@ test('Roadmap with milestone sections and <details> blocks', async () => {
641
643
 
642
644
  const project = await parsePlanningDirectory(planning);
643
645
 
644
- assert.ok(project.roadmap !== null, 'ms roadmap: roadmap parsed');
645
- assert.ok((project.roadmap?.milestones?.length ?? 0) >= 2, 'ms roadmap: has milestone sections');
646
+ assertTrue(project.roadmap !== null, 'ms roadmap: roadmap parsed');
647
+ assertTrue((project.roadmap?.milestones?.length ?? 0) >= 2, 'ms roadmap: has milestone sections');
646
648
 
647
649
  // Check collapsed milestone
648
650
  const v20 = project.roadmap?.milestones?.find(m => m.id.includes('2.0'));
649
- assert.ok(v20 !== undefined, 'ms roadmap: v2.0 milestone found');
650
- assert.deepStrictEqual(v20?.collapsed, true, 'ms roadmap: v2.0 is collapsed');
651
- assert.ok((v20?.phases?.length ?? 0) >= 2, 'ms roadmap: v2.0 has phases');
652
- assert.ok(v20?.phases?.every(p => p.done) ?? false, 'ms roadmap: v2.0 phases all done');
651
+ assertTrue(v20 !== undefined, 'ms roadmap: v2.0 milestone found');
652
+ assertEq(v20?.collapsed, true, 'ms roadmap: v2.0 is collapsed');
653
+ assertTrue((v20?.phases?.length ?? 0) >= 2, 'ms roadmap: v2.0 has phases');
654
+ assertTrue(v20?.phases?.every(p => p.done) ?? false, 'ms roadmap: v2.0 phases all done');
653
655
 
654
656
  // Check active milestone
655
657
  const v25 = project.roadmap?.milestones?.find(m => m.id.includes('2.5'));
656
- assert.ok(v25 !== undefined, 'ms roadmap: v2.5 milestone found');
657
- assert.deepStrictEqual(v25?.collapsed, false, 'ms roadmap: v2.5 is not collapsed');
658
- assert.ok((v25?.phases?.length ?? 0) >= 3, 'ms roadmap: v2.5 has phases');
658
+ assertTrue(v25 !== undefined, 'ms roadmap: v2.5 milestone found');
659
+ assertEq(v25?.collapsed, false, 'ms roadmap: v2.5 is not collapsed');
660
+ assertTrue((v25?.phases?.length ?? 0) >= 3, 'ms roadmap: v2.5 has phases');
659
661
 
660
662
  // Check completion state
661
663
  const phase29 = v25?.phases?.find(p => p.number === 29);
662
- assert.ok(phase29?.done === true, 'ms roadmap: phase 29 is done');
664
+ assertTrue(phase29?.done === true, 'ms roadmap: phase 29 is done');
663
665
  const phase30 = v25?.phases?.find(p => p.number === 30);
664
- assert.ok(phase30?.done === false, 'ms roadmap: phase 30 is not done');
666
+ assertTrue(phase30?.done === false, 'ms roadmap: phase 30 is not done');
665
667
  } finally {
666
668
  cleanup(base);
667
669
  }
668
- });
670
+ }
669
671
 
670
672
  // ─── Test 11: Non-standard phase files → extra files ──────────────────
671
-
672
- test('Non-standard phase files → collected as extra files', async () => {
673
+ console.log('\n=== Non-standard phase files → collected as extra files ===');
674
+ {
673
675
  const base = createFixtureBase();
674
676
  try {
675
677
  const planning = createPlanningDir(base);
@@ -685,28 +687,28 @@ test('Non-standard phase files → collected as extra files', async () => {
685
687
  const project = await parsePlanningDirectory(planning);
686
688
  const phase = project.phases['36-attachment-system'];
687
689
 
688
- assert.ok(phase !== undefined, 'extra: phase exists');
689
- assert.ok((phase?.extraFiles?.length ?? 0) >= 3, 'extra: non-standard files collected');
690
- assert.ok(
690
+ assertTrue(phase !== undefined, 'extra: phase exists');
691
+ assertTrue((phase?.extraFiles?.length ?? 0) >= 3, 'extra: non-standard files collected');
692
+ assertTrue(
691
693
  phase?.extraFiles?.some(f => f.fileName === 'BASELINE.md') ?? false,
692
694
  'extra: BASELINE.md collected'
693
695
  );
694
- assert.ok(
696
+ assertTrue(
695
697
  phase?.extraFiles?.some(f => f.fileName === 'BUNDLE-ANALYSIS.md') ?? false,
696
698
  'extra: BUNDLE-ANALYSIS.md collected'
697
699
  );
698
- assert.ok(
700
+ assertTrue(
699
701
  phase?.extraFiles?.some(f => f.fileName === 'depcheck-results.txt') ?? false,
700
702
  'extra: depcheck-results.txt collected'
701
703
  );
702
704
  } finally {
703
705
  cleanup(base);
704
706
  }
705
- });
707
+ }
706
708
 
707
709
  // ─── Test 12: Validation — missing ROADMAP.md → warning (not fatal) ───
708
-
709
- test('Validation: missing ROADMAP.md → warning (not fatal)', async () => {
710
+ console.log('\n=== Validation: missing ROADMAP.md → warning (not fatal) ===');
711
+ {
710
712
  const base = createFixtureBase();
711
713
  try {
712
714
  const planning = createPlanningDir(base);
@@ -715,19 +717,19 @@ test('Validation: missing ROADMAP.md → warning (not fatal)', async () => {
715
717
 
716
718
  const result = await validatePlanningDirectory(planning);
717
719
 
718
- assert.deepStrictEqual(result.valid, true, 'no roadmap: validation still passes');
719
- assert.ok(
720
+ assertEq(result.valid, true, 'no roadmap: validation still passes');
721
+ assertTrue(
720
722
  result.issues.some(i => i.severity === 'warning' && i.file.includes('ROADMAP')),
721
723
  'no roadmap: warning issue mentions ROADMAP'
722
724
  );
723
725
  } finally {
724
726
  cleanup(base);
725
727
  }
726
- });
728
+ }
727
729
 
728
730
  // ─── Test 13: Validation — missing PROJECT.md → warning ───────────────
729
-
730
- test('Validation: missing PROJECT.md → warning', async () => {
731
+ console.log('\n=== Validation: missing PROJECT.md → warning ===');
732
+ {
731
733
  const base = createFixtureBase();
732
734
  try {
733
735
  const planning = createPlanningDir(base);
@@ -736,13 +738,20 @@ test('Validation: missing PROJECT.md → warning', async () => {
736
738
 
737
739
  const result = await validatePlanningDirectory(planning);
738
740
 
739
- assert.deepStrictEqual(result.valid, true, 'no project: validation passes (warning only)');
740
- assert.ok(
741
+ assertEq(result.valid, true, 'no project: validation passes (warning only)');
742
+ assertTrue(
741
743
  result.issues.some(i => i.severity === 'warning' && i.file.includes('PROJECT')),
742
744
  'no project: warning issue mentions PROJECT'
743
745
  );
744
746
  } finally {
745
747
  cleanup(base);
746
748
  }
747
- });
749
+ }
748
750
 
751
+ report();
752
+ }
753
+
754
+ main().catch((error) => {
755
+ console.error(error);
756
+ process.exit(1);
757
+ });