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
@@ -19,8 +19,9 @@ import {
19
19
  formatDecisionsForPrompt,
20
20
  formatRequirementsForPrompt,
21
21
  } from '../context-store.ts';
22
- import { describe, test, beforeEach, afterEach } from 'node:test';
23
- import assert from 'node:assert/strict';
22
+ import { createTestContext } from './test-helpers.ts';
23
+
24
+ const { assertEq, assertTrue, report } = createTestContext();
24
25
 
25
26
  // ─── Fixture Helper ────────────────────────────────────────────────────────
26
27
 
@@ -47,7 +48,8 @@ function generateDecisionsMarkdown(count: number): string {
47
48
  // Edge Case 1: Empty Project
48
49
  // ═══════════════════════════════════════════════════════════════════════════
49
50
 
50
- test('integration-edge: empty project', () => {
51
+ console.log('\n=== integration-edge: empty project ===');
52
+ {
51
53
  const base = mkdtempSync(join(tmpdir(), 'gsd-int-edge-empty-'));
52
54
  const gsdDir = join(base, '.gsd');
53
55
  mkdirSync(gsdDir, { recursive: true });
@@ -57,54 +59,55 @@ test('integration-edge: empty project', () => {
57
59
  try {
58
60
  // Open DB first so migrateFromMarkdown doesn't auto-create at default path
59
61
  openDatabase(dbPath);
60
- assert.ok(isDbAvailable(), 'empty: DB available after open');
62
+ assertTrue(isDbAvailable(), 'empty: DB available after open');
61
63
 
62
64
  // Migrate with no markdown files on disk
63
65
  const result = migrateFromMarkdown(base);
64
66
 
65
- assert.deepStrictEqual(result.decisions, 0, 'empty: 0 decisions imported');
66
- assert.deepStrictEqual(result.requirements, 0, 'empty: 0 requirements imported');
67
- assert.deepStrictEqual(result.artifacts, 0, 'empty: 0 artifacts imported');
67
+ assertEq(result.decisions, 0, 'empty: 0 decisions imported');
68
+ assertEq(result.requirements, 0, 'empty: 0 requirements imported');
69
+ assertEq(result.artifacts, 0, 'empty: 0 artifacts imported');
68
70
 
69
71
  // Query decisions → empty array
70
72
  const decisions = queryDecisions();
71
- assert.deepStrictEqual(decisions.length, 0, 'empty: queryDecisions returns empty array');
73
+ assertEq(decisions.length, 0, 'empty: queryDecisions returns empty array');
72
74
 
73
75
  // Query requirements → empty array
74
76
  const requirements = queryRequirements();
75
- assert.deepStrictEqual(requirements.length, 0, 'empty: queryRequirements returns empty array');
77
+ assertEq(requirements.length, 0, 'empty: queryRequirements returns empty array');
76
78
 
77
79
  // Query with scope filters → still empty, no crash
78
80
  const scopedDecisions = queryDecisions({ milestoneId: 'M001' });
79
- assert.deepStrictEqual(scopedDecisions.length, 0, 'empty: scoped queryDecisions returns empty');
81
+ assertEq(scopedDecisions.length, 0, 'empty: scoped queryDecisions returns empty');
80
82
 
81
83
  const scopedRequirements = queryRequirements({ sliceId: 'S01' });
82
- assert.deepStrictEqual(scopedRequirements.length, 0, 'empty: scoped queryRequirements returns empty');
84
+ assertEq(scopedRequirements.length, 0, 'empty: scoped queryRequirements returns empty');
83
85
 
84
86
  // Format empty results → empty strings
85
87
  const formattedD = formatDecisionsForPrompt([]);
86
88
  const formattedR = formatRequirementsForPrompt([]);
87
- assert.deepStrictEqual(formattedD, '', 'empty: formatDecisionsForPrompt returns empty string');
88
- assert.deepStrictEqual(formattedR, '', 'empty: formatRequirementsForPrompt returns empty string');
89
+ assertEq(formattedD, '', 'empty: formatDecisionsForPrompt returns empty string');
90
+ assertEq(formattedR, '', 'empty: formatRequirementsForPrompt returns empty string');
89
91
 
90
92
  // Format with actual empty query results
91
93
  const formattedD2 = formatDecisionsForPrompt(decisions);
92
94
  const formattedR2 = formatRequirementsForPrompt(requirements);
93
- assert.deepStrictEqual(formattedD2, '', 'empty: format of empty query decisions is empty string');
94
- assert.deepStrictEqual(formattedR2, '', 'empty: format of empty query requirements is empty string');
95
+ assertEq(formattedD2, '', 'empty: format of empty query decisions is empty string');
96
+ assertEq(formattedR2, '', 'empty: format of empty query requirements is empty string');
95
97
 
96
98
  closeDatabase();
97
99
  } finally {
98
100
  closeDatabase();
99
101
  rmSync(base, { recursive: true, force: true });
100
102
  }
101
- });
103
+ }
102
104
 
103
105
  // ═══════════════════════════════════════════════════════════════════════════
104
106
  // Edge Case 2: Partial Migration (decisions only, no requirements)
105
107
  // ═══════════════════════════════════════════════════════════════════════════
106
108
 
107
- test('integration-edge: partial migration', () => {
109
+ console.log('\n=== integration-edge: partial migration ===');
110
+ {
108
111
  const base = mkdtempSync(join(tmpdir(), 'gsd-int-edge-partial-'));
109
112
  const gsdDir = join(base, '.gsd');
110
113
  mkdirSync(gsdDir, { recursive: true });
@@ -117,48 +120,49 @@ test('integration-edge: partial migration', () => {
117
120
 
118
121
  try {
119
122
  openDatabase(dbPath);
120
- assert.ok(isDbAvailable(), 'partial: DB available after open');
123
+ assertTrue(isDbAvailable(), 'partial: DB available after open');
121
124
 
122
125
  const result = migrateFromMarkdown(base);
123
126
 
124
127
  // Decisions imported, requirements skipped gracefully
125
- assert.ok(result.decisions === 6, `partial: imported ${result.decisions} decisions, expected 6`);
126
- assert.deepStrictEqual(result.requirements, 0, 'partial: 0 requirements imported (no file)');
128
+ assertTrue(result.decisions === 6, `partial: imported ${result.decisions} decisions, expected 6`);
129
+ assertEq(result.requirements, 0, 'partial: 0 requirements imported (no file)');
127
130
 
128
131
  // Decisions queryable
129
132
  const decisions = queryDecisions();
130
- assert.ok(decisions.length === 6, `partial: queryDecisions returns 6 (got ${decisions.length})`);
133
+ assertTrue(decisions.length === 6, `partial: queryDecisions returns 6 (got ${decisions.length})`);
131
134
 
132
135
  const m001Decisions = queryDecisions({ milestoneId: 'M001' });
133
- assert.ok(m001Decisions.length > 0, 'partial: M001 decisions non-empty');
134
- assert.ok(m001Decisions.length < decisions.length, 'partial: M001 scope filters correctly');
136
+ assertTrue(m001Decisions.length > 0, 'partial: M001 decisions non-empty');
137
+ assertTrue(m001Decisions.length < decisions.length, 'partial: M001 scope filters correctly');
135
138
 
136
139
  // Requirements return empty — no crash
137
140
  const requirements = queryRequirements();
138
- assert.deepStrictEqual(requirements.length, 0, 'partial: queryRequirements returns empty');
141
+ assertEq(requirements.length, 0, 'partial: queryRequirements returns empty');
139
142
 
140
143
  const scopedReqs = queryRequirements({ sliceId: 'S01' });
141
- assert.deepStrictEqual(scopedReqs.length, 0, 'partial: scoped queryRequirements returns empty');
144
+ assertEq(scopedReqs.length, 0, 'partial: scoped queryRequirements returns empty');
142
145
 
143
146
  // Format works on partial data
144
147
  const formattedD = formatDecisionsForPrompt(m001Decisions);
145
- assert.ok(formattedD.length > 0, 'partial: formatted decisions non-empty');
148
+ assertTrue(formattedD.length > 0, 'partial: formatted decisions non-empty');
146
149
 
147
150
  const formattedR = formatRequirementsForPrompt(requirements);
148
- assert.deepStrictEqual(formattedR, '', 'partial: formatted empty requirements is empty string');
151
+ assertEq(formattedR, '', 'partial: formatted empty requirements is empty string');
149
152
 
150
153
  closeDatabase();
151
154
  } finally {
152
155
  closeDatabase();
153
156
  rmSync(base, { recursive: true, force: true });
154
157
  }
155
- });
158
+ }
156
159
 
157
160
  // ═══════════════════════════════════════════════════════════════════════════
158
161
  // Edge Case 3: Fallback Mode (_resetProvider)
159
162
  // ═══════════════════════════════════════════════════════════════════════════
160
163
 
161
- test('integration-edge: fallback mode', () => {
164
+ console.log('\n=== integration-edge: fallback mode ===');
165
+ {
162
166
  const base = mkdtempSync(join(tmpdir(), 'gsd-int-edge-fallback-'));
163
167
  const gsdDir = join(base, '.gsd');
164
168
  mkdirSync(gsdDir, { recursive: true });
@@ -171,53 +175,54 @@ test('integration-edge: fallback mode', () => {
171
175
  try {
172
176
  // Step 1: Open DB normally and verify it works
173
177
  openDatabase(dbPath);
174
- assert.ok(isDbAvailable(), 'fallback: DB available after open');
178
+ assertTrue(isDbAvailable(), 'fallback: DB available after open');
175
179
 
176
180
  migrateFromMarkdown(base);
177
181
  const before = queryDecisions();
178
- assert.ok(before.length === 4, `fallback: 4 decisions before reset (got ${before.length})`);
182
+ assertTrue(before.length === 4, `fallback: 4 decisions before reset (got ${before.length})`);
179
183
 
180
184
  // Step 2: Close and reset provider → DB unavailable
181
185
  closeDatabase();
182
186
  _resetProvider();
183
- assert.ok(!isDbAvailable(), 'fallback: DB unavailable after _resetProvider');
187
+ assertTrue(!isDbAvailable(), 'fallback: DB unavailable after _resetProvider');
184
188
 
185
189
  // Step 3: Queries degrade gracefully (return empty, don't throw)
186
190
  const degradedDecisions = queryDecisions();
187
- assert.deepStrictEqual(degradedDecisions.length, 0, 'fallback: queryDecisions returns empty when unavailable');
191
+ assertEq(degradedDecisions.length, 0, 'fallback: queryDecisions returns empty when unavailable');
188
192
 
189
193
  const degradedRequirements = queryRequirements();
190
- assert.deepStrictEqual(degradedRequirements.length, 0, 'fallback: queryRequirements returns empty when unavailable');
194
+ assertEq(degradedRequirements.length, 0, 'fallback: queryRequirements returns empty when unavailable');
191
195
 
192
196
  const degradedScopedD = queryDecisions({ milestoneId: 'M001' });
193
- assert.deepStrictEqual(degradedScopedD.length, 0, 'fallback: scoped queryDecisions returns empty when unavailable');
197
+ assertEq(degradedScopedD.length, 0, 'fallback: scoped queryDecisions returns empty when unavailable');
194
198
 
195
199
  const degradedScopedR = queryRequirements({ sliceId: 'S01' });
196
- assert.deepStrictEqual(degradedScopedR.length, 0, 'fallback: scoped queryRequirements returns empty when unavailable');
200
+ assertEq(degradedScopedR.length, 0, 'fallback: scoped queryRequirements returns empty when unavailable');
197
201
 
198
202
  // Format functions work on empty arrays (no crash)
199
203
  const formattedD = formatDecisionsForPrompt(degradedDecisions);
200
- assert.deepStrictEqual(formattedD, '', 'fallback: format degraded decisions is empty');
204
+ assertEq(formattedD, '', 'fallback: format degraded decisions is empty');
201
205
 
202
206
  const formattedR = formatRequirementsForPrompt(degradedRequirements);
203
- assert.deepStrictEqual(formattedR, '', 'fallback: format degraded requirements is empty');
207
+ assertEq(formattedR, '', 'fallback: format degraded requirements is empty');
204
208
 
205
209
  // Step 4: Re-open DB → restores availability
206
210
  openDatabase(dbPath);
207
- assert.ok(isDbAvailable(), 'fallback: DB available after re-open');
211
+ assertTrue(isDbAvailable(), 'fallback: DB available after re-open');
208
212
 
209
213
  // Data should be there from the file-backed DB (persisted by first open)
210
214
  // But rows may need re-import since the DB was freshly opened from the file
211
215
  migrateFromMarkdown(base);
212
216
  const restored = queryDecisions();
213
- assert.ok(restored.length === 4, `fallback: 4 decisions after re-open (got ${restored.length})`);
217
+ assertTrue(restored.length === 4, `fallback: 4 decisions after re-open (got ${restored.length})`);
214
218
 
215
219
  closeDatabase();
216
220
  } finally {
217
221
  closeDatabase();
218
222
  rmSync(base, { recursive: true, force: true });
219
223
  }
220
- });
224
+ }
221
225
 
222
226
  // ─── Report ────────────────────────────────────────────────────────────────
223
227
 
228
+ report();
@@ -21,8 +21,9 @@ import {
21
21
  formatRequirementsForPrompt,
22
22
  } from '../context-store.ts';
23
23
  import { saveDecisionToDb, generateDecisionsMd } from '../db-writer.ts';
24
- import { describe, test, beforeEach, afterEach } from 'node:test';
25
- import assert from 'node:assert/strict';
24
+ import { createTestContext } from './test-helpers.ts';
25
+
26
+ const { assertEq, assertTrue, assertMatch, report } = createTestContext();
26
27
 
27
28
  // ─── Fixture Generators (duplicated from token-savings.test.ts — file-scoped) ──
28
29
 
@@ -118,7 +119,10 @@ const ROADMAP_CONTENT = `# M001: Test Milestone\n\n**Vision:** Integration test
118
119
  // Full Lifecycle Integration Test
119
120
  // ═══════════════════════════════════════════════════════════════════════════
120
121
 
121
- test('integration-lifecycle: full pipeline', async () => {
122
+ async function main(): Promise<void> {
123
+
124
+ console.log('\n=== integration-lifecycle: full pipeline ===');
125
+ {
122
126
  // ── Step 1: Set up temp dir with realistic .gsd/ structure ──────────
123
127
  const base = mkdtempSync(join(tmpdir(), 'gsd-int-lifecycle-'));
124
128
  const gsdDir = join(base, '.gsd');
@@ -138,37 +142,37 @@ test('integration-lifecycle: full pipeline', async () => {
138
142
  try {
139
143
  // ── Step 2: Open file-backed DB + migrateFromMarkdown ──────────────
140
144
  openDatabase(dbPath);
141
- assert.ok(isDbAvailable(), 'lifecycle: DB is available after open');
145
+ assertTrue(isDbAvailable(), 'lifecycle: DB is available after open');
142
146
 
143
147
  const result = migrateFromMarkdown(base);
144
148
 
145
- assert.ok(result.decisions === DECISIONS_COUNT, `lifecycle: imported ${result.decisions} decisions, expected ${DECISIONS_COUNT}`);
146
- assert.ok(result.requirements === REQUIREMENTS_COUNT, `lifecycle: imported ${result.requirements} requirements, expected ${REQUIREMENTS_COUNT}`);
147
- assert.ok(result.artifacts >= 1, `lifecycle: imported at least 1 artifact (got ${result.artifacts})`);
149
+ assertTrue(result.decisions === DECISIONS_COUNT, `lifecycle: imported ${result.decisions} decisions, expected ${DECISIONS_COUNT}`);
150
+ assertTrue(result.requirements === REQUIREMENTS_COUNT, `lifecycle: imported ${result.requirements} requirements, expected ${REQUIREMENTS_COUNT}`);
151
+ assertTrue(result.artifacts >= 1, `lifecycle: imported at least 1 artifact (got ${result.artifacts})`);
148
152
 
149
153
  // Verify file-backed DB uses WAL
150
154
  const adapter = _getAdapter()!;
151
155
  const mode = adapter.prepare('PRAGMA journal_mode').get();
152
- assert.deepStrictEqual(mode?.['journal_mode'], 'wal', 'lifecycle: file-backed DB uses WAL mode');
156
+ assertEq(mode?.['journal_mode'], 'wal', 'lifecycle: file-backed DB uses WAL mode');
153
157
 
154
158
  // ── Step 3: Scoped queries — decisions by milestone ────────────────
155
159
  const allDecisions = queryDecisions();
156
160
  const m001Decisions = queryDecisions({ milestoneId: 'M001' });
157
161
  const m002Decisions = queryDecisions({ milestoneId: 'M002' });
158
162
 
159
- assert.ok(allDecisions.length === DECISIONS_COUNT, `lifecycle: all decisions count = ${DECISIONS_COUNT} (got ${allDecisions.length})`);
160
- assert.ok(m001Decisions.length > 0, 'lifecycle: M001 decisions non-empty');
161
- assert.ok(m002Decisions.length > 0, 'lifecycle: M002 decisions non-empty');
162
- assert.ok(m001Decisions.length < allDecisions.length, 'lifecycle: M001 filtered count < total count');
163
- assert.ok(m002Decisions.length < allDecisions.length, 'lifecycle: M002 filtered count < total count');
164
- assert.deepStrictEqual(m001Decisions.length + m002Decisions.length, allDecisions.length, 'lifecycle: M001 + M002 = total decisions');
163
+ assertTrue(allDecisions.length === DECISIONS_COUNT, `lifecycle: all decisions count = ${DECISIONS_COUNT} (got ${allDecisions.length})`);
164
+ assertTrue(m001Decisions.length > 0, 'lifecycle: M001 decisions non-empty');
165
+ assertTrue(m002Decisions.length > 0, 'lifecycle: M002 decisions non-empty');
166
+ assertTrue(m001Decisions.length < allDecisions.length, 'lifecycle: M001 filtered count < total count');
167
+ assertTrue(m002Decisions.length < allDecisions.length, 'lifecycle: M002 filtered count < total count');
168
+ assertEq(m001Decisions.length + m002Decisions.length, allDecisions.length, 'lifecycle: M001 + M002 = total decisions');
165
169
 
166
170
  // Verify scoping correctness
167
171
  for (const d of m001Decisions) {
168
- assert.ok(d.when_context.includes('M001'), `lifecycle: M001 decision ${d.id} has M001 in when_context`);
172
+ assertTrue(d.when_context.includes('M001'), `lifecycle: M001 decision ${d.id} has M001 in when_context`);
169
173
  }
170
174
  for (const d of m002Decisions) {
171
- assert.ok(d.when_context.includes('M002'), `lifecycle: M002 decision ${d.id} has M002 in when_context`);
175
+ assertTrue(d.when_context.includes('M002'), `lifecycle: M002 decision ${d.id} has M002 in when_context`);
172
176
  }
173
177
 
174
178
  // ── Step 4: Scoped queries — requirements by slice ─────────────────
@@ -176,19 +180,19 @@ test('integration-lifecycle: full pipeline', async () => {
176
180
  const s01Requirements = queryRequirements({ sliceId: 'S01' });
177
181
  const s04Requirements = queryRequirements({ sliceId: 'S04' });
178
182
 
179
- assert.ok(allRequirements.length === REQUIREMENTS_COUNT, `lifecycle: all requirements count = ${REQUIREMENTS_COUNT} (got ${allRequirements.length})`);
180
- assert.ok(s01Requirements.length > 0, 'lifecycle: S01 requirements non-empty');
181
- assert.ok(s04Requirements.length > 0, 'lifecycle: S04 requirements non-empty');
182
- assert.ok(s01Requirements.length < allRequirements.length, 'lifecycle: S01 filtered count < total count');
183
+ assertTrue(allRequirements.length === REQUIREMENTS_COUNT, `lifecycle: all requirements count = ${REQUIREMENTS_COUNT} (got ${allRequirements.length})`);
184
+ assertTrue(s01Requirements.length > 0, 'lifecycle: S01 requirements non-empty');
185
+ assertTrue(s04Requirements.length > 0, 'lifecycle: S04 requirements non-empty');
186
+ assertTrue(s01Requirements.length < allRequirements.length, 'lifecycle: S01 filtered count < total count');
183
187
 
184
188
  // ── Step 5: Format + token savings validation ──────────────────────
185
189
  const formattedDecisions = formatDecisionsForPrompt(m001Decisions);
186
190
  const formattedRequirements = formatRequirementsForPrompt(s01Requirements);
187
191
 
188
- assert.ok(formattedDecisions.length > 0, 'lifecycle: formatted M001 decisions non-empty');
189
- assert.ok(formattedRequirements.length > 0, 'lifecycle: formatted S01 requirements non-empty');
190
- assert.match(formattedDecisions, /\| D/, 'lifecycle: formatted decisions contains decision rows');
191
- assert.match(formattedRequirements, /### R\d+/, 'lifecycle: formatted requirements has headings');
192
+ assertTrue(formattedDecisions.length > 0, 'lifecycle: formatted M001 decisions non-empty');
193
+ assertTrue(formattedRequirements.length > 0, 'lifecycle: formatted S01 requirements non-empty');
194
+ assertMatch(formattedDecisions, /\| D/, 'lifecycle: formatted decisions contains decision rows');
195
+ assertMatch(formattedRequirements, /### R\d+/, 'lifecycle: formatted requirements has headings');
192
196
 
193
197
  // Token savings: scoped output vs full file content
194
198
  const fullDecisionsContent = readFileSync(join(gsdDir, 'DECISIONS.md'), 'utf-8');
@@ -199,24 +203,24 @@ test('integration-lifecycle: full pipeline', async () => {
199
203
 
200
204
  console.log(` Token savings: ${savingsPercent.toFixed(1)}% (scoped: ${dbScopedTotal}, full: ${fullTotal})`);
201
205
 
202
- assert.ok(dbScopedTotal > 0, 'lifecycle: scoped content non-empty');
203
- assert.ok(dbScopedTotal < fullTotal, 'lifecycle: scoped content smaller than full content');
204
- assert.ok(savingsPercent >= 30, `lifecycle: savings ≥30% (actual: ${savingsPercent.toFixed(1)}%)`);
206
+ assertTrue(dbScopedTotal > 0, 'lifecycle: scoped content non-empty');
207
+ assertTrue(dbScopedTotal < fullTotal, 'lifecycle: scoped content smaller than full content');
208
+ assertTrue(savingsPercent >= 30, `lifecycle: savings ≥30% (actual: ${savingsPercent.toFixed(1)}%)`);
205
209
 
206
210
  // ── Step 6: Simulate content change → re-import ────────────────────
207
211
  const newDecisionRow = `| D${DECISIONS_COUNT + 1} | M001/S01 | testing | new decision added after initial import | choice X | rationale Y | yes |`;
208
212
  appendFileSync(join(gsdDir, 'DECISIONS.md'), '\n' + newDecisionRow + '\n');
209
213
 
210
214
  const result2 = migrateFromMarkdown(base);
211
- assert.ok(result2.decisions === DECISIONS_COUNT + 1, `lifecycle: re-import got ${result2.decisions} decisions, expected ${DECISIONS_COUNT + 1}`);
215
+ assertTrue(result2.decisions === DECISIONS_COUNT + 1, `lifecycle: re-import got ${result2.decisions} decisions, expected ${DECISIONS_COUNT + 1}`);
212
216
 
213
217
  const afterReimport = queryDecisions();
214
- assert.ok(afterReimport.length === DECISIONS_COUNT + 1, `lifecycle: DB has ${DECISIONS_COUNT + 1} decisions after re-import (got ${afterReimport.length})`);
218
+ assertTrue(afterReimport.length === DECISIONS_COUNT + 1, `lifecycle: DB has ${DECISIONS_COUNT + 1} decisions after re-import (got ${afterReimport.length})`);
215
219
 
216
220
  // Verify the new decision is queryable
217
221
  const newM001 = queryDecisions({ milestoneId: 'M001' });
218
222
  const foundNew = newM001.some(d => d.id === `D${DECISIONS_COUNT + 1}`);
219
- assert.ok(foundNew, `lifecycle: newly imported D${DECISIONS_COUNT + 1} found in M001 scope`);
223
+ assertTrue(foundNew, `lifecycle: newly imported D${DECISIONS_COUNT + 1} found in M001 scope`);
220
224
 
221
225
  // ── Step 7: saveDecisionToDb write-back + round-trip ───────────────
222
226
  const saved = await saveDecisionToDb(
@@ -230,37 +234,44 @@ test('integration-lifecycle: full pipeline', async () => {
230
234
  base,
231
235
  );
232
236
 
233
- assert.ok(typeof saved.id === 'string', 'lifecycle: saveDecisionToDb returned an id');
234
- assert.match(saved.id, /^D\d+$/, 'lifecycle: saved ID matches D### pattern');
237
+ assertTrue(typeof saved.id === 'string', 'lifecycle: saveDecisionToDb returned an id');
238
+ assertMatch(saved.id, /^D\d+$/, 'lifecycle: saved ID matches D### pattern');
235
239
 
236
240
  // Query back from DB
237
241
  const allAfterSave = queryDecisions();
238
242
  const savedDecision = allAfterSave.find(d => d.id === saved.id);
239
- assert.ok(savedDecision !== null && savedDecision !== undefined, `lifecycle: saved decision ${saved.id} found in DB`);
240
- assert.deepStrictEqual(savedDecision?.decision, 'integration test write-back decision', 'lifecycle: saved decision text matches');
241
- assert.deepStrictEqual(savedDecision?.choice, 'option Z', 'lifecycle: saved choice matches');
243
+ assertTrue(savedDecision !== null && savedDecision !== undefined, `lifecycle: saved decision ${saved.id} found in DB`);
244
+ assertEq(savedDecision?.decision, 'integration test write-back decision', 'lifecycle: saved decision text matches');
245
+ assertEq(savedDecision?.choice, 'option Z', 'lifecycle: saved choice matches');
242
246
 
243
247
  // Verify DECISIONS.md was regenerated with the new decision
244
248
  const regeneratedMd = readFileSync(join(gsdDir, 'DECISIONS.md'), 'utf-8');
245
- assert.ok(regeneratedMd.includes(saved.id), `lifecycle: regenerated DECISIONS.md contains ${saved.id}`);
246
- assert.ok(regeneratedMd.includes('integration test write-back decision'), 'lifecycle: regenerated md contains write-back text');
249
+ assertTrue(regeneratedMd.includes(saved.id), `lifecycle: regenerated DECISIONS.md contains ${saved.id}`);
250
+ assertTrue(regeneratedMd.includes('integration test write-back decision'), 'lifecycle: regenerated md contains write-back text');
247
251
 
248
252
  // Round-trip: parse regenerated markdown back → verify field fidelity
249
253
  const reparsed = parseDecisionsTable(regeneratedMd);
250
254
  const reparsedSaved = reparsed.find(d => d.id === saved.id);
251
- assert.ok(reparsedSaved !== undefined, `lifecycle: reparsed markdown contains ${saved.id}`);
252
- assert.deepStrictEqual(reparsedSaved?.choice, 'option Z', 'lifecycle: round-trip choice preserved');
253
- assert.deepStrictEqual(reparsedSaved?.rationale, 'proves round-trip fidelity', 'lifecycle: round-trip rationale preserved');
255
+ assertTrue(reparsedSaved !== undefined, `lifecycle: reparsed markdown contains ${saved.id}`);
256
+ assertEq(reparsedSaved?.choice, 'option Z', 'lifecycle: round-trip choice preserved');
257
+ assertEq(reparsedSaved?.rationale, 'proves round-trip fidelity', 'lifecycle: round-trip rationale preserved');
254
258
 
255
259
  // ── Step 8: DB consistency — total count sanity ─────────────────────
256
260
  const finalCount = queryDecisions().length;
257
261
  // Original 14 + 1 re-import + 1 saveDecisionToDb = 16
258
- assert.ok(finalCount === DECISIONS_COUNT + 2, `lifecycle: final DB count = ${DECISIONS_COUNT + 2} (got ${finalCount})`);
262
+ assertTrue(finalCount === DECISIONS_COUNT + 2, `lifecycle: final DB count = ${DECISIONS_COUNT + 2} (got ${finalCount})`);
259
263
 
260
264
  closeDatabase();
261
265
  } finally {
262
266
  closeDatabase();
263
267
  rmSync(base, { recursive: true, force: true });
264
268
  }
265
- });
269
+ }
266
270
 
271
+ report();
272
+ }
273
+
274
+ main().catch((error) => {
275
+ console.error(error);
276
+ process.exit(1);
277
+ });