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,9 +19,9 @@ import type {
19
19
  GSDSlice,
20
20
  GSDTask,
21
21
  } from '../migrate/types.ts';
22
- import { describe, test, beforeEach, afterEach } from 'node:test';
23
- import assert from 'node:assert/strict';
22
+ import { createTestContext } from './test-helpers.ts';
24
23
 
24
+ const { assertEq, assertTrue, report } = createTestContext();
25
25
  // ─── Fixture Helpers ───────────────────────────────────────────────────────
26
26
 
27
27
  function emptyProject(overrides: Partial<PlanningProject> = {}): PlanningProject {
@@ -134,7 +134,8 @@ function makeResearch(fileName: string, content: string): PlanningResearch {
134
134
 
135
135
  // ─── Scenario 1: Flat Single-Milestone (3 phases → M001 with S01/S02/S03) ──
136
136
 
137
- test('Scenario 1: Flat single-milestone', () => {
137
+ {
138
+ console.log('Scenario 1: Flat single-milestone');
138
139
 
139
140
  const project = emptyProject({
140
141
  project: '# My Project\nA cool project.',
@@ -158,25 +159,26 @@ test('Scenario 1: Flat single-milestone', () => {
158
159
 
159
160
  const result = transformToGSD(project);
160
161
 
161
- assert.deepStrictEqual(result.milestones.length, 1, 'flat: produces 1 milestone');
162
- assert.ok(result.milestones[0]?.id === 'M001', 'flat: milestone ID is M001');
163
- assert.deepStrictEqual(result.milestones[0]?.slices.length, 3, 'flat: 3 slices');
164
- assert.deepStrictEqual(result.milestones[0]?.slices[0]?.id, 'S01', 'flat: first slice is S01');
165
- assert.deepStrictEqual(result.milestones[0]?.slices[1]?.id, 'S02', 'flat: second slice is S02');
166
- assert.deepStrictEqual(result.milestones[0]?.slices[2]?.id, 'S03', 'flat: third slice is S03');
167
- assert.ok(result.milestones[0]?.slices[0]?.title.length > 0, 'flat: slice title not empty');
168
- assert.deepStrictEqual(result.milestones[0]?.slices[0]?.tasks.length, 1, 'flat: S01 has 1 task');
169
- assert.deepStrictEqual(result.milestones[0]?.slices[1]?.tasks.length, 2, 'flat: S02 has 2 tasks');
170
- assert.deepStrictEqual(result.milestones[0]?.slices[2]?.tasks.length, 1, 'flat: S03 has 1 task');
171
- assert.deepStrictEqual(result.milestones[0]?.slices[0]?.tasks[0]?.id, 'T01', 'flat: first task is T01');
172
- assert.deepStrictEqual(result.milestones[0]?.slices[1]?.tasks[1]?.id, 'T02', 'flat: second task in S02 is T02');
173
- assert.ok(result.projectContent.includes('My Project'), 'flat: projectContent preserved');
174
- assert.deepStrictEqual(result.milestones[0]?.boundaryMap, [], 'flat: boundaryMap defaults to empty');
175
- });
162
+ assertEq(result.milestones.length, 1, 'flat: produces 1 milestone');
163
+ assertTrue(result.milestones[0]?.id === 'M001', 'flat: milestone ID is M001');
164
+ assertEq(result.milestones[0]?.slices.length, 3, 'flat: 3 slices');
165
+ assertEq(result.milestones[0]?.slices[0]?.id, 'S01', 'flat: first slice is S01');
166
+ assertEq(result.milestones[0]?.slices[1]?.id, 'S02', 'flat: second slice is S02');
167
+ assertEq(result.milestones[0]?.slices[2]?.id, 'S03', 'flat: third slice is S03');
168
+ assertTrue(result.milestones[0]?.slices[0]?.title.length > 0, 'flat: slice title not empty');
169
+ assertEq(result.milestones[0]?.slices[0]?.tasks.length, 1, 'flat: S01 has 1 task');
170
+ assertEq(result.milestones[0]?.slices[1]?.tasks.length, 2, 'flat: S02 has 2 tasks');
171
+ assertEq(result.milestones[0]?.slices[2]?.tasks.length, 1, 'flat: S03 has 1 task');
172
+ assertEq(result.milestones[0]?.slices[0]?.tasks[0]?.id, 'T01', 'flat: first task is T01');
173
+ assertEq(result.milestones[0]?.slices[1]?.tasks[1]?.id, 'T02', 'flat: second task in S02 is T02');
174
+ assertTrue(result.projectContent.includes('My Project'), 'flat: projectContent preserved');
175
+ assertEq(result.milestones[0]?.boundaryMap, [], 'flat: boundaryMap defaults to empty');
176
+ }
176
177
 
177
178
  // ─── Scenario 2: Multi-Milestone (2 milestones with independent numbering) ──
178
179
 
179
- test('Scenario 2: Multi-milestone', () => {
180
+ {
181
+ console.log('Scenario 2: Multi-milestone');
180
182
 
181
183
  const project = emptyProject({
182
184
  roadmap: milestoneRoadmap([
@@ -204,22 +206,23 @@ test('Scenario 2: Multi-milestone', () => {
204
206
 
205
207
  const result = transformToGSD(project);
206
208
 
207
- assert.deepStrictEqual(result.milestones.length, 2, 'multi: 2 milestones');
208
- assert.deepStrictEqual(result.milestones[0]?.id, 'M001', 'multi: first milestone M001');
209
- assert.deepStrictEqual(result.milestones[1]?.id, 'M002', 'multi: second milestone M002');
210
- assert.deepStrictEqual(result.milestones[0]?.slices.length, 2, 'multi: M001 has 2 slices');
211
- assert.deepStrictEqual(result.milestones[1]?.slices.length, 3, 'multi: M002 has 3 slices');
209
+ assertEq(result.milestones.length, 2, 'multi: 2 milestones');
210
+ assertEq(result.milestones[0]?.id, 'M001', 'multi: first milestone M001');
211
+ assertEq(result.milestones[1]?.id, 'M002', 'multi: second milestone M002');
212
+ assertEq(result.milestones[0]?.slices.length, 2, 'multi: M001 has 2 slices');
213
+ assertEq(result.milestones[1]?.slices.length, 3, 'multi: M002 has 3 slices');
212
214
  // Independent numbering: both start at S01
213
- assert.deepStrictEqual(result.milestones[0]?.slices[0]?.id, 'S01', 'multi: M001 starts at S01');
214
- assert.deepStrictEqual(result.milestones[1]?.slices[0]?.id, 'S01', 'multi: M002 starts at S01');
215
- assert.deepStrictEqual(result.milestones[1]?.slices[2]?.id, 'S03', 'multi: M002 third slice is S03');
216
- assert.ok(result.milestones[0]?.title.length > 0, 'multi: M001 has title');
217
- assert.ok(result.milestones[1]?.title.length > 0, 'multi: M002 has title');
218
- });
215
+ assertEq(result.milestones[0]?.slices[0]?.id, 'S01', 'multi: M001 starts at S01');
216
+ assertEq(result.milestones[1]?.slices[0]?.id, 'S01', 'multi: M002 starts at S01');
217
+ assertEq(result.milestones[1]?.slices[2]?.id, 'S03', 'multi: M002 third slice is S03');
218
+ assertTrue(result.milestones[0]?.title.length > 0, 'multi: M001 has title');
219
+ assertTrue(result.milestones[1]?.title.length > 0, 'multi: M002 has title');
220
+ }
219
221
 
220
222
  // ─── Scenario 3: Decimal Phase Ordering (1, 2, 2.1, 2.2, 3 → S01–S05) ──
221
223
 
222
- test('Scenario 3: Decimal phase ordering', () => {
224
+ {
225
+ console.log('Scenario 3: Decimal phase ordering');
223
226
 
224
227
  const project = emptyProject({
225
228
  roadmap: flatRoadmap([
@@ -240,26 +243,27 @@ test('Scenario 3: Decimal phase ordering', () => {
240
243
 
241
244
  const result = transformToGSD(project);
242
245
 
243
- assert.deepStrictEqual(result.milestones[0]?.slices.length, 5, 'decimal: 5 slices total');
244
- assert.deepStrictEqual(result.milestones[0]?.slices[0]?.id, 'S01', 'decimal: first is S01');
245
- assert.deepStrictEqual(result.milestones[0]?.slices[1]?.id, 'S02', 'decimal: second is S02');
246
- assert.deepStrictEqual(result.milestones[0]?.slices[2]?.id, 'S03', 'decimal: third is S03');
247
- assert.deepStrictEqual(result.milestones[0]?.slices[3]?.id, 'S04', 'decimal: fourth is S04');
248
- assert.deepStrictEqual(result.milestones[0]?.slices[4]?.id, 'S05', 'decimal: fifth is S05');
246
+ assertEq(result.milestones[0]?.slices.length, 5, 'decimal: 5 slices total');
247
+ assertEq(result.milestones[0]?.slices[0]?.id, 'S01', 'decimal: first is S01');
248
+ assertEq(result.milestones[0]?.slices[1]?.id, 'S02', 'decimal: second is S02');
249
+ assertEq(result.milestones[0]?.slices[2]?.id, 'S03', 'decimal: third is S03');
250
+ assertEq(result.milestones[0]?.slices[3]?.id, 'S04', 'decimal: fourth is S04');
251
+ assertEq(result.milestones[0]?.slices[4]?.id, 'S05', 'decimal: fifth is S05');
249
252
  // Order must be by float value: 1, 2, 2.1, 2.2, 3
250
- assert.ok(
253
+ assertTrue(
251
254
  result.milestones[0]?.slices[0]?.title.toLowerCase().includes('foundation'),
252
255
  'decimal: S01 is foundation (phase 1)',
253
256
  );
254
- assert.ok(
257
+ assertTrue(
255
258
  result.milestones[0]?.slices[4]?.title.toLowerCase().includes('finalize'),
256
259
  'decimal: S05 is finalize (phase 3)',
257
260
  );
258
- });
261
+ }
259
262
 
260
263
  // ─── Scenario 4: Completion State ──────────────────────────────────────────
261
264
 
262
- test('Scenario 4: Completion state mapping', () => {
265
+ {
266
+ console.log('Scenario 4: Completion state mapping');
263
267
 
264
268
  const project = emptyProject({
265
269
  roadmap: flatRoadmap([
@@ -284,25 +288,26 @@ test('Scenario 4: Completion state mapping', () => {
284
288
  const doneSlice = result.milestones[0]?.slices[0];
285
289
  const activeSlice = result.milestones[0]?.slices[1];
286
290
 
287
- assert.ok(doneSlice?.done === true, 'completion: done phase → done slice');
288
- assert.ok(activeSlice?.done === false, 'completion: active phase → not-done slice');
289
- assert.ok(doneSlice?.tasks[0]?.done === true, 'completion: plan with summary → done task');
290
- assert.ok(doneSlice?.tasks[1]?.done === false, 'completion: plan without summary → not-done task');
291
- assert.ok(doneSlice?.tasks[0]?.summary !== null, 'completion: done task has summary data');
292
- assert.ok(doneSlice?.tasks[1]?.summary === null, 'completion: not-done task has null summary');
293
- assert.deepStrictEqual(doneSlice?.tasks[0]?.summary?.completedAt, '2026-01-15', 'completion: summary completedAt from frontmatter');
294
- assert.deepStrictEqual(doneSlice?.tasks[0]?.summary?.duration, '2h', 'completion: summary duration from frontmatter');
295
- assert.deepStrictEqual(doneSlice?.tasks[0]?.summary?.provides, ['feature-01'], 'completion: summary provides from frontmatter');
296
- assert.deepStrictEqual(doneSlice?.tasks[0]?.summary?.keyFiles, ['file-01.ts'], 'completion: summary keyFiles from frontmatter');
297
- assert.ok(doneSlice?.tasks[0]?.summary?.whatHappened?.includes('Summary body') ?? false, 'completion: summary whatHappened from body');
298
- assert.ok(doneSlice?.summary !== null, 'completion: done slice has slice summary');
299
- assert.ok(activeSlice?.summary === null, 'completion: active slice has null summary');
300
- assert.deepStrictEqual(doneSlice?.tasks[0]?.estimate, '2h', 'completion: task estimate from summary duration');
301
- });
291
+ assertTrue(doneSlice?.done === true, 'completion: done phase → done slice');
292
+ assertTrue(activeSlice?.done === false, 'completion: active phase → not-done slice');
293
+ assertTrue(doneSlice?.tasks[0]?.done === true, 'completion: plan with summary → done task');
294
+ assertTrue(doneSlice?.tasks[1]?.done === false, 'completion: plan without summary → not-done task');
295
+ assertTrue(doneSlice?.tasks[0]?.summary !== null, 'completion: done task has summary data');
296
+ assertTrue(doneSlice?.tasks[1]?.summary === null, 'completion: not-done task has null summary');
297
+ assertEq(doneSlice?.tasks[0]?.summary?.completedAt, '2026-01-15', 'completion: summary completedAt from frontmatter');
298
+ assertEq(doneSlice?.tasks[0]?.summary?.duration, '2h', 'completion: summary duration from frontmatter');
299
+ assertEq(doneSlice?.tasks[0]?.summary?.provides, ['feature-01'], 'completion: summary provides from frontmatter');
300
+ assertEq(doneSlice?.tasks[0]?.summary?.keyFiles, ['file-01.ts'], 'completion: summary keyFiles from frontmatter');
301
+ assertTrue(doneSlice?.tasks[0]?.summary?.whatHappened?.includes('Summary body') ?? false, 'completion: summary whatHappened from body');
302
+ assertTrue(doneSlice?.summary !== null, 'completion: done slice has slice summary');
303
+ assertTrue(activeSlice?.summary === null, 'completion: active slice has null summary');
304
+ assertEq(doneSlice?.tasks[0]?.estimate, '2h', 'completion: task estimate from summary duration');
305
+ }
302
306
 
303
307
  // ─── Scenario 5: Research Consolidation ────────────────────────────────────
304
308
 
305
- test('Scenario 5: Research consolidation', () => {
309
+ {
310
+ console.log('Scenario 5: Research consolidation');
306
311
 
307
312
  const project = emptyProject({
308
313
  roadmap: flatRoadmap([roadmapEntry(1, 'researched-phase')]),
@@ -323,27 +328,28 @@ test('Scenario 5: Research consolidation', () => {
323
328
  const result = transformToGSD(project);
324
329
 
325
330
  // Project-level research → milestone research
326
- assert.ok(result.milestones[0]?.research !== null, 'research: milestone has consolidated research');
327
- assert.ok(result.milestones[0]?.research!.includes('Project Summary'), 'research: includes SUMMARY content');
328
- assert.ok(result.milestones[0]?.research!.includes('Architecture'), 'research: includes ARCHITECTURE content');
329
- assert.ok(result.milestones[0]?.research!.includes('Pitfalls'), 'research: includes PITFALLS content');
331
+ assertTrue(result.milestones[0]?.research !== null, 'research: milestone has consolidated research');
332
+ assertTrue(result.milestones[0]?.research!.includes('Project Summary'), 'research: includes SUMMARY content');
333
+ assertTrue(result.milestones[0]?.research!.includes('Architecture'), 'research: includes ARCHITECTURE content');
334
+ assertTrue(result.milestones[0]?.research!.includes('Pitfalls'), 'research: includes PITFALLS content');
330
335
 
331
336
  // Fixed ordering: SUMMARY before ARCHITECTURE before PITFALLS
332
337
  const summaryIdx = result.milestones[0]?.research!.indexOf('Project Summary') ?? -1;
333
338
  const archIdx = result.milestones[0]?.research!.indexOf('Architecture') ?? -1;
334
339
  const pitfallIdx = result.milestones[0]?.research!.indexOf('Pitfalls') ?? -1;
335
- assert.ok(summaryIdx < archIdx, 'research: SUMMARY before ARCHITECTURE in consolidated');
336
- assert.ok(archIdx < pitfallIdx, 'research: ARCHITECTURE before PITFALLS in consolidated');
340
+ assertTrue(summaryIdx < archIdx, 'research: SUMMARY before ARCHITECTURE in consolidated');
341
+ assertTrue(archIdx < pitfallIdx, 'research: ARCHITECTURE before PITFALLS in consolidated');
337
342
 
338
343
  // Phase-level research → slice research
339
344
  const slice = result.milestones[0]?.slices[0];
340
- assert.ok(slice?.research !== null, 'research: slice has phase research');
341
- assert.ok(slice?.research!.includes('Phase Features'), 'research: slice research includes phase content');
342
- });
345
+ assertTrue(slice?.research !== null, 'research: slice has phase research');
346
+ assertTrue(slice?.research!.includes('Phase Features'), 'research: slice research includes phase content');
347
+ }
343
348
 
344
349
  // ─── Scenario 6: Requirements Classification ──────────────────────────────
345
350
 
346
- test('Scenario 6: Requirements classification', () => {
351
+ {
352
+ console.log('Scenario 6: Requirements classification');
347
353
 
348
354
  const project = emptyProject({
349
355
  roadmap: flatRoadmap([roadmapEntry(1, 'req-phase')]),
@@ -359,21 +365,22 @@ test('Scenario 6: Requirements classification', () => {
359
365
 
360
366
  const result = transformToGSD(project);
361
367
 
362
- assert.deepStrictEqual(result.requirements.length, 3, 'requirements: 3 requirements');
363
- assert.deepStrictEqual(result.requirements[0]?.id, 'R001', 'requirements: first is R001');
364
- assert.deepStrictEqual(result.requirements[0]?.status, 'active', 'requirements: R001 status active');
365
- assert.deepStrictEqual(result.requirements[1]?.status, 'validated', 'requirements: R002 status validated');
366
- assert.deepStrictEqual(result.requirements[2]?.status, 'deferred', 'requirements: R003 status deferred');
367
- assert.ok(result.requirements[0]?.title === 'Core Feature', 'requirements: R001 title preserved');
368
- assert.ok(result.requirements[0]?.description.includes('Description for R001'), 'requirements: R001 description preserved');
369
- assert.deepStrictEqual(result.requirements[0]?.class, 'core-capability', 'requirements: default class');
370
- assert.deepStrictEqual(result.requirements[0]?.source, 'inferred', 'requirements: default source');
371
- assert.deepStrictEqual(result.requirements[0]?.primarySlice, 'none yet', 'requirements: default primarySlice');
372
- });
368
+ assertEq(result.requirements.length, 3, 'requirements: 3 requirements');
369
+ assertEq(result.requirements[0]?.id, 'R001', 'requirements: first is R001');
370
+ assertEq(result.requirements[0]?.status, 'active', 'requirements: R001 status active');
371
+ assertEq(result.requirements[1]?.status, 'validated', 'requirements: R002 status validated');
372
+ assertEq(result.requirements[2]?.status, 'deferred', 'requirements: R003 status deferred');
373
+ assertTrue(result.requirements[0]?.title === 'Core Feature', 'requirements: R001 title preserved');
374
+ assertTrue(result.requirements[0]?.description.includes('Description for R001'), 'requirements: R001 description preserved');
375
+ assertEq(result.requirements[0]?.class, 'core-capability', 'requirements: default class');
376
+ assertEq(result.requirements[0]?.source, 'inferred', 'requirements: default source');
377
+ assertEq(result.requirements[0]?.primarySlice, 'none yet', 'requirements: default primarySlice');
378
+ }
373
379
 
374
380
  // ─── Scenario 7: Empty Phase (no plans → slice with 0 tasks) ───────────────
375
381
 
376
- test('Scenario 7: Empty phase', () => {
382
+ {
383
+ console.log('Scenario 7: Empty phase');
377
384
 
378
385
  const project = emptyProject({
379
386
  roadmap: flatRoadmap([
@@ -390,14 +397,15 @@ test('Scenario 7: Empty phase', () => {
390
397
 
391
398
  const result = transformToGSD(project);
392
399
 
393
- assert.deepStrictEqual(result.milestones[0]?.slices[0]?.tasks.length, 0, 'empty: empty phase → 0 tasks');
394
- assert.deepStrictEqual(result.milestones[0]?.slices[1]?.tasks.length, 1, 'empty: non-empty phase → 1 task');
395
- assert.ok(result.milestones[0]?.slices[0]?.id === 'S01', 'empty: empty slice still gets ID');
396
- });
400
+ assertEq(result.milestones[0]?.slices[0]?.tasks.length, 0, 'empty: empty phase → 0 tasks');
401
+ assertEq(result.milestones[0]?.slices[1]?.tasks.length, 1, 'empty: non-empty phase → 1 task');
402
+ assertTrue(result.milestones[0]?.slices[0]?.id === 'S01', 'empty: empty slice still gets ID');
403
+ }
397
404
 
398
405
  // ─── Scenario 8: Demo Derivation from Plan Objective ───────────────────────
399
406
 
400
- test('Scenario 8: Demo derivation', () => {
407
+ {
408
+ console.log('Scenario 8: Demo derivation');
401
409
 
402
410
  const project = emptyProject({
403
411
  roadmap: flatRoadmap([roadmapEntry(1, 'demo-phase')]),
@@ -412,18 +420,19 @@ test('Scenario 8: Demo derivation', () => {
412
420
 
413
421
  const result = transformToGSD(project);
414
422
 
415
- assert.ok(result.milestones[0]?.slices[0]?.demo.length > 0, 'demo: slice demo is not empty');
416
- assert.ok(
423
+ assertTrue(result.milestones[0]?.slices[0]?.demo.length > 0, 'demo: slice demo is not empty');
424
+ assertTrue(
417
425
  result.milestones[0]?.slices[0]?.demo.includes('authentication') ||
418
426
  result.milestones[0]?.slices[0]?.demo.includes('Build'),
419
427
  'demo: slice demo derived from first plan objective',
420
428
  );
421
- assert.ok(result.milestones[0]?.slices[0]?.goal.length > 0, 'demo: slice goal is not empty');
422
- });
429
+ assertTrue(result.milestones[0]?.slices[0]?.goal.length > 0, 'demo: slice goal is not empty');
430
+ }
423
431
 
424
432
  // ─── Scenario 9: Field Defaults and Type Safety ────────────────────────────
425
433
 
426
- test('Scenario 9: Field defaults', () => {
434
+ {
435
+ console.log('Scenario 9: Field defaults');
427
436
 
428
437
  const project = emptyProject({
429
438
  roadmap: flatRoadmap([roadmapEntry(1, 'defaults-phase')]),
@@ -451,19 +460,20 @@ test('Scenario 9: Field defaults', () => {
451
460
  const slice = result.milestones[0]?.slices[0];
452
461
  const task = slice?.tasks[0];
453
462
 
454
- assert.deepStrictEqual(slice?.risk, 'medium', 'defaults: slice risk defaults to medium');
455
- assert.deepStrictEqual(slice?.depends, [], 'defaults: S01 has no depends');
456
- assert.ok(task?.description.length > 0, 'defaults: task description not empty');
457
- assert.deepStrictEqual(task?.files, ['src/auth.ts', 'src/db.ts'], 'defaults: task files from frontmatter');
458
- assert.deepStrictEqual(task?.mustHaves, ['Auth works', 'DB connected'], 'defaults: task mustHaves from frontmatter');
459
- assert.deepStrictEqual(task?.done, false, 'defaults: task without summary is not done');
460
- assert.deepStrictEqual(task?.estimate, '', 'defaults: task without summary has empty estimate');
461
- assert.ok(task?.summary === null, 'defaults: task without summary has null summary');
462
- });
463
+ assertEq(slice?.risk, 'medium', 'defaults: slice risk defaults to medium');
464
+ assertEq(slice?.depends, [], 'defaults: S01 has no depends');
465
+ assertTrue(task?.description.length > 0, 'defaults: task description not empty');
466
+ assertEq(task?.files, ['src/auth.ts', 'src/db.ts'], 'defaults: task files from frontmatter');
467
+ assertEq(task?.mustHaves, ['Auth works', 'DB connected'], 'defaults: task mustHaves from frontmatter');
468
+ assertEq(task?.done, false, 'defaults: task without summary is not done');
469
+ assertEq(task?.estimate, '', 'defaults: task without summary has empty estimate');
470
+ assertTrue(task?.summary === null, 'defaults: task without summary has null summary');
471
+ }
463
472
 
464
473
  // ─── Scenario 10: Sequential Depends ──────────────────────────────────────
465
474
 
466
- test('Scenario 10: Sequential depends', () => {
475
+ {
476
+ console.log('Scenario 10: Sequential depends');
467
477
 
468
478
  const project = emptyProject({
469
479
  roadmap: flatRoadmap([
@@ -481,14 +491,15 @@ test('Scenario 10: Sequential depends', () => {
481
491
  const result = transformToGSD(project);
482
492
  const slices = result.milestones[0]?.slices;
483
493
 
484
- assert.deepStrictEqual(slices?.[0]?.depends, [], 'depends: S01 has empty depends');
485
- assert.deepStrictEqual(slices?.[1]?.depends, ['S01'], 'depends: S02 depends on S01');
486
- assert.deepStrictEqual(slices?.[2]?.depends, ['S02'], 'depends: S03 depends on S02');
487
- });
494
+ assertEq(slices?.[0]?.depends, [], 'depends: S01 has empty depends');
495
+ assertEq(slices?.[1]?.depends, ['S01'], 'depends: S02 depends on S01');
496
+ assertEq(slices?.[2]?.depends, ['S02'], 'depends: S03 depends on S02');
497
+ }
488
498
 
489
499
  // ─── Scenario 11: Requirements with unknown status and missing IDs ─────────
490
500
 
491
- test('Scenario 11: Requirements edge cases', () => {
501
+ {
502
+ console.log('Scenario 11: Requirements edge cases');
492
503
 
493
504
  const project = emptyProject({
494
505
  roadmap: flatRoadmap([roadmapEntry(1, 'req-edge')]),
@@ -505,16 +516,17 @@ test('Scenario 11: Requirements edge cases', () => {
505
516
 
506
517
  const result = transformToGSD(project);
507
518
 
508
- assert.deepStrictEqual(result.requirements[0]?.id, 'R001', 'req-edge: empty id gets R001');
509
- assert.deepStrictEqual(result.requirements[1]?.id, 'R002', 'req-edge: second empty id gets R002');
510
- assert.deepStrictEqual(result.requirements[2]?.id, 'R005', 'req-edge: existing id preserved');
511
- assert.deepStrictEqual(result.requirements[2]?.status, 'active', 'req-edge: unknown status normalized to active');
512
- assert.deepStrictEqual(result.requirements[3]?.status, 'deferred', 'req-edge: uppercase DEFERRED normalized');
513
- });
519
+ assertEq(result.requirements[0]?.id, 'R001', 'req-edge: empty id gets R001');
520
+ assertEq(result.requirements[1]?.id, 'R002', 'req-edge: second empty id gets R002');
521
+ assertEq(result.requirements[2]?.id, 'R005', 'req-edge: existing id preserved');
522
+ assertEq(result.requirements[2]?.status, 'active', 'req-edge: unknown status normalized to active');
523
+ assertEq(result.requirements[3]?.status, 'deferred', 'req-edge: uppercase DEFERRED normalized');
524
+ }
514
525
 
515
526
  // ─── Scenario 12: Vision derivation ────────────────────────────────────────
516
527
 
517
- test('Scenario 12: Vision derivation', () => {
528
+ {
529
+ console.log('Scenario 12: Vision derivation');
518
530
 
519
531
  // Vision from project description
520
532
  const project1 = emptyProject({
@@ -524,7 +536,7 @@ test('Scenario 12: Vision derivation', () => {
524
536
  });
525
537
 
526
538
  const result1 = transformToGSD(project1);
527
- assert.ok(result1.milestones[0]?.vision.includes('revolutionary'), 'vision: derived from project first line');
539
+ assertTrue(result1.milestones[0]?.vision.includes('revolutionary'), 'vision: derived from project first line');
528
540
 
529
541
  // Vision fallback when no project
530
542
  const project2 = emptyProject({
@@ -533,12 +545,13 @@ test('Scenario 12: Vision derivation', () => {
533
545
  });
534
546
 
535
547
  const result2 = transformToGSD(project2);
536
- assert.ok(result2.milestones[0]?.vision.length > 0, 'vision: fallback is non-empty');
537
- });
548
+ assertTrue(result2.milestones[0]?.vision.length > 0, 'vision: fallback is non-empty');
549
+ }
538
550
 
539
551
  // ─── Scenario 13: Decisions content from summaries ─────────────────────────
540
552
 
541
- test('Scenario 13: Decisions content', () => {
553
+ {
554
+ console.log('Scenario 13: Decisions content');
542
555
 
543
556
  const project = emptyProject({
544
557
  roadmap: flatRoadmap([roadmapEntry(1, 'decision-phase', true)]),
@@ -552,12 +565,13 @@ test('Scenario 13: Decisions content', () => {
552
565
 
553
566
  const result = transformToGSD(project);
554
567
 
555
- assert.ok(result.decisionsContent.includes('decision-01'), 'decisions: extracts key-decisions from summaries');
556
- });
568
+ assertTrue(result.decisionsContent.includes('decision-01'), 'decisions: extracts key-decisions from summaries');
569
+ }
557
570
 
558
571
  // ─── Scenario 14: No undefined values in output ───────────────────────────
559
572
 
560
- test('Scenario 14: No undefined values', () => {
573
+ {
574
+ console.log('Scenario 14: No undefined values');
561
575
 
562
576
  const project = emptyProject({
563
577
  project: '# Test\nDescription.',
@@ -582,7 +596,7 @@ test('Scenario 14: No undefined values', () => {
582
596
  // Deep check for undefined values
583
597
  function checkNoUndefined(obj: unknown, path: string): void {
584
598
  if (obj === undefined) {
585
- assert.ok(false, `no-undefined: ${path} is undefined`);
599
+ assertTrue(false, `no-undefined: ${path} is undefined`);
586
600
  return;
587
601
  }
588
602
  if (obj === null) return; // null is allowed (e.g. research, summary)
@@ -598,12 +612,13 @@ test('Scenario 14: No undefined values', () => {
598
612
  }
599
613
 
600
614
  checkNoUndefined(result, 'result');
601
- assert.ok(true, 'no-undefined: deep check completed without finding undefined values');
602
- });
615
+ assertTrue(true, 'no-undefined: deep check completed without finding undefined values');
616
+ }
603
617
 
604
618
  // ─── Scenario 15: Research with no files ───────────────────────────────────
605
619
 
606
- test('Scenario 15: Empty research', () => {
620
+ {
621
+ console.log('Scenario 15: Empty research');
607
622
 
608
623
  const project = emptyProject({
609
624
  roadmap: flatRoadmap([roadmapEntry(1, 'no-research')]),
@@ -611,9 +626,10 @@ test('Scenario 15: Empty research', () => {
611
626
  });
612
627
 
613
628
  const result = transformToGSD(project);
614
- assert.ok(result.milestones[0]?.research === null, 'empty-research: milestone research is null');
615
- assert.ok(result.milestones[0]?.slices[0]?.research === null, 'empty-research: slice research is null');
616
- });
629
+ assertTrue(result.milestones[0]?.research === null, 'empty-research: milestone research is null');
630
+ assertTrue(result.milestones[0]?.slices[0]?.research === null, 'empty-research: slice research is null');
631
+ }
617
632
 
618
633
  // ─── Results ───────────────────────────────────────────────────────────────
619
634
 
635
+ report();