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
@@ -31,9 +31,9 @@ import type {
31
31
  GSDSliceSummaryData,
32
32
  GSDTaskSummaryData,
33
33
  } from '../migrate/types.ts';
34
- import { describe, test, beforeEach, afterEach } from 'node:test';
35
- import assert from 'node:assert/strict';
34
+ import { createTestContext } from './test-helpers.ts';
36
35
 
36
+ const { assertEq, assertTrue, report } = createTestContext();
37
37
  // ─── Test Data Builders ────────────────────────────────────────────────────
38
38
 
39
39
  function makeTask(overrides: Partial<GSDTask> = {}): GSDTask {
@@ -103,7 +103,11 @@ function makeTaskSummary(overrides: Partial<GSDTaskSummaryData> = {}): GSDTaskSu
103
103
  };
104
104
  }
105
105
 
106
- test('Scenario A: Roadmap round-trip with 2 slices (1 done, 1 not)', () => {
106
+ // ═══════════════════════════════════════════════════════════════════════════
107
+ // Scenario A: Roadmap round-trip with 2 slices (1 done, 1 not)
108
+ // ═══════════════════════════════════════════════════════════════════════════
109
+
110
+ {
107
111
  const milestone = makeMilestone({
108
112
  slices: [
109
113
  makeSlice({
@@ -128,31 +132,35 @@ test('Scenario A: Roadmap round-trip with 2 slices (1 done, 1 not)', () => {
128
132
  const output = formatRoadmap(milestone);
129
133
  const parsed = parseRoadmap(output);
130
134
 
131
- assert.deepStrictEqual(parsed.title, 'M001: Core Platform', 'roadmap: title');
132
- assert.deepStrictEqual(parsed.vision, 'Build the core platform', 'roadmap: vision');
133
- assert.deepStrictEqual(parsed.successCriteria.length, 2, 'roadmap: successCriteria count');
134
- assert.deepStrictEqual(parsed.successCriteria[0], 'All tests pass', 'roadmap: successCriteria[0]');
135
- assert.deepStrictEqual(parsed.successCriteria[1], 'Deploy to staging', 'roadmap: successCriteria[1]');
136
- assert.deepStrictEqual(parsed.slices.length, 2, 'roadmap: slices count');
137
-
138
- assert.deepStrictEqual(parsed.slices[0].id, 'S01', 'roadmap: S01 id');
139
- assert.deepStrictEqual(parsed.slices[0].title, 'Auth System', 'roadmap: S01 title');
140
- assert.deepStrictEqual(parsed.slices[0].done, true, 'roadmap: S01 done');
141
- assert.deepStrictEqual(parsed.slices[0].risk, 'high', 'roadmap: S01 risk');
142
- assert.deepStrictEqual(parsed.slices[0].depends.length, 0, 'roadmap: S01 depends empty');
143
- assert.deepStrictEqual(parsed.slices[0].demo, 'Login flow works', 'roadmap: S01 demo');
144
-
145
- assert.deepStrictEqual(parsed.slices[1].id, 'S02', 'roadmap: S02 id');
146
- assert.deepStrictEqual(parsed.slices[1].title, 'Dashboard', 'roadmap: S02 title');
147
- assert.deepStrictEqual(parsed.slices[1].done, false, 'roadmap: S02 done');
148
- assert.deepStrictEqual(parsed.slices[1].risk, 'low', 'roadmap: S02 risk');
149
- assert.deepStrictEqual(parsed.slices[1].depends, ['S01'], 'roadmap: S02 depends');
150
- assert.deepStrictEqual(parsed.slices[1].demo, 'Dashboard renders data', 'roadmap: S02 demo');
151
-
152
- assert.deepStrictEqual(parsed.boundaryMap.length, 0, 'roadmap: boundaryMap empty');
153
- });
154
-
155
- test('Scenario B: Plan round-trip with 3 tasks (mixed done)', () => {
135
+ assertEq(parsed.title, 'M001: Core Platform', 'roadmap: title');
136
+ assertEq(parsed.vision, 'Build the core platform', 'roadmap: vision');
137
+ assertEq(parsed.successCriteria.length, 2, 'roadmap: successCriteria count');
138
+ assertEq(parsed.successCriteria[0], 'All tests pass', 'roadmap: successCriteria[0]');
139
+ assertEq(parsed.successCriteria[1], 'Deploy to staging', 'roadmap: successCriteria[1]');
140
+ assertEq(parsed.slices.length, 2, 'roadmap: slices count');
141
+
142
+ assertEq(parsed.slices[0].id, 'S01', 'roadmap: S01 id');
143
+ assertEq(parsed.slices[0].title, 'Auth System', 'roadmap: S01 title');
144
+ assertEq(parsed.slices[0].done, true, 'roadmap: S01 done');
145
+ assertEq(parsed.slices[0].risk, 'high', 'roadmap: S01 risk');
146
+ assertEq(parsed.slices[0].depends.length, 0, 'roadmap: S01 depends empty');
147
+ assertEq(parsed.slices[0].demo, 'Login flow works', 'roadmap: S01 demo');
148
+
149
+ assertEq(parsed.slices[1].id, 'S02', 'roadmap: S02 id');
150
+ assertEq(parsed.slices[1].title, 'Dashboard', 'roadmap: S02 title');
151
+ assertEq(parsed.slices[1].done, false, 'roadmap: S02 done');
152
+ assertEq(parsed.slices[1].risk, 'low', 'roadmap: S02 risk');
153
+ assertEq(parsed.slices[1].depends, ['S01'], 'roadmap: S02 depends');
154
+ assertEq(parsed.slices[1].demo, 'Dashboard renders data', 'roadmap: S02 demo');
155
+
156
+ assertEq(parsed.boundaryMap.length, 0, 'roadmap: boundaryMap empty');
157
+ }
158
+
159
+ // ═══════════════════════════════════════════════════════════════════════════
160
+ // Scenario B: Plan round-trip with 3 tasks (mixed done)
161
+ // ═══════════════════════════════════════════════════════════════════════════
162
+
163
+ {
156
164
  const slice = makeSlice({
157
165
  id: 'S01',
158
166
  title: 'Auth System',
@@ -168,27 +176,31 @@ test('Scenario B: Plan round-trip with 3 tasks (mixed done)', () => {
168
176
  const output = formatPlan(slice);
169
177
  const parsed = parsePlan(output);
170
178
 
171
- assert.deepStrictEqual(parsed.id, 'S01', 'plan: id');
172
- assert.deepStrictEqual(parsed.title, 'Auth System', 'plan: title');
173
- assert.deepStrictEqual(parsed.goal, 'Working authentication system', 'plan: goal');
174
- assert.deepStrictEqual(parsed.demo, 'Login works with valid credentials', 'plan: demo');
175
- assert.deepStrictEqual(parsed.tasks.length, 3, 'plan: tasks count');
179
+ assertEq(parsed.id, 'S01', 'plan: id');
180
+ assertEq(parsed.title, 'Auth System', 'plan: title');
181
+ assertEq(parsed.goal, 'Working authentication system', 'plan: goal');
182
+ assertEq(parsed.demo, 'Login works with valid credentials', 'plan: demo');
183
+ assertEq(parsed.tasks.length, 3, 'plan: tasks count');
176
184
 
177
- assert.deepStrictEqual(parsed.tasks[0].id, 'T01', 'plan: T01 id');
178
- assert.deepStrictEqual(parsed.tasks[0].title, 'Setup Models', 'plan: T01 title');
179
- assert.deepStrictEqual(parsed.tasks[0].done, true, 'plan: T01 done');
180
- assert.deepStrictEqual(parsed.tasks[0].estimate, '15m', 'plan: T01 estimate');
185
+ assertEq(parsed.tasks[0].id, 'T01', 'plan: T01 id');
186
+ assertEq(parsed.tasks[0].title, 'Setup Models', 'plan: T01 title');
187
+ assertEq(parsed.tasks[0].done, true, 'plan: T01 done');
188
+ assertEq(parsed.tasks[0].estimate, '15m', 'plan: T01 estimate');
181
189
 
182
- assert.deepStrictEqual(parsed.tasks[1].id, 'T02', 'plan: T02 id');
183
- assert.deepStrictEqual(parsed.tasks[1].done, false, 'plan: T02 done');
184
- assert.deepStrictEqual(parsed.tasks[1].estimate, '30m', 'plan: T02 estimate');
190
+ assertEq(parsed.tasks[1].id, 'T02', 'plan: T02 id');
191
+ assertEq(parsed.tasks[1].done, false, 'plan: T02 done');
192
+ assertEq(parsed.tasks[1].estimate, '30m', 'plan: T02 estimate');
193
+
194
+ assertEq(parsed.tasks[2].id, 'T03', 'plan: T03 id');
195
+ assertEq(parsed.tasks[2].done, true, 'plan: T03 done');
196
+ assertEq(parsed.tasks[2].estimate, '20m', 'plan: T03 estimate');
197
+ }
185
198
 
186
- assert.deepStrictEqual(parsed.tasks[2].id, 'T03', 'plan: T03 id');
187
- assert.deepStrictEqual(parsed.tasks[2].done, true, 'plan: T03 done');
188
- assert.deepStrictEqual(parsed.tasks[2].estimate, '20m', 'plan: T03 estimate');
189
- });
199
+ // ═══════════════════════════════════════════════════════════════════════════
200
+ // Scenario C: Slice summary round-trip with full data
201
+ // ═══════════════════════════════════════════════════════════════════════════
190
202
 
191
- test('Scenario C: Slice summary round-trip with full data', () => {
203
+ {
192
204
  const slice = makeSlice({
193
205
  id: 'S01',
194
206
  title: 'Auth System',
@@ -199,24 +211,28 @@ test('Scenario C: Slice summary round-trip with full data', () => {
199
211
  const output = formatSliceSummary(slice, 'M001');
200
212
  const parsed = parseSummary(output);
201
213
 
202
- assert.deepStrictEqual(parsed.frontmatter.id, 'S01', 'sliceSummary: id');
203
- assert.deepStrictEqual(parsed.frontmatter.parent, 'M001', 'sliceSummary: parent');
204
- assert.deepStrictEqual(parsed.frontmatter.milestone, 'M001', 'sliceSummary: milestone');
205
- assert.deepStrictEqual(parsed.frontmatter.provides, ['auth-flow', 'jwt-tokens'], 'sliceSummary: provides');
206
- assert.deepStrictEqual(parsed.frontmatter.requires.length, 0, 'sliceSummary: requires empty');
207
- assert.deepStrictEqual(parsed.frontmatter.affects.length, 0, 'sliceSummary: affects empty');
208
- assert.deepStrictEqual(parsed.frontmatter.key_files, ['src/auth.ts', 'src/middleware.ts'], 'sliceSummary: key_files');
209
- assert.deepStrictEqual(parsed.frontmatter.key_decisions, ['Use JWT over sessions'], 'sliceSummary: key_decisions');
210
- assert.deepStrictEqual(parsed.frontmatter.patterns_established, ['Middleware pattern'], 'sliceSummary: patterns_established');
211
- assert.deepStrictEqual(parsed.frontmatter.duration, '2h', 'sliceSummary: duration');
212
- assert.deepStrictEqual(parsed.frontmatter.completed_at, '2026-03-10', 'sliceSummary: completed_at');
213
- assert.deepStrictEqual(parsed.frontmatter.verification_result, 'passed', 'sliceSummary: verification_result');
214
- assert.deepStrictEqual(parsed.frontmatter.blocker_discovered, false, 'sliceSummary: blocker_discovered');
215
- assert.ok(parsed.whatHappened.includes('Implemented full auth system'), 'sliceSummary: whatHappened content');
216
- assert.deepStrictEqual(parsed.title, 'S01: Auth System', 'sliceSummary: title');
217
- });
218
-
219
- test('Scenario D: Task summary round-trip', () => {
214
+ assertEq(parsed.frontmatter.id, 'S01', 'sliceSummary: id');
215
+ assertEq(parsed.frontmatter.parent, 'M001', 'sliceSummary: parent');
216
+ assertEq(parsed.frontmatter.milestone, 'M001', 'sliceSummary: milestone');
217
+ assertEq(parsed.frontmatter.provides, ['auth-flow', 'jwt-tokens'], 'sliceSummary: provides');
218
+ assertEq(parsed.frontmatter.requires.length, 0, 'sliceSummary: requires empty');
219
+ assertEq(parsed.frontmatter.affects.length, 0, 'sliceSummary: affects empty');
220
+ assertEq(parsed.frontmatter.key_files, ['src/auth.ts', 'src/middleware.ts'], 'sliceSummary: key_files');
221
+ assertEq(parsed.frontmatter.key_decisions, ['Use JWT over sessions'], 'sliceSummary: key_decisions');
222
+ assertEq(parsed.frontmatter.patterns_established, ['Middleware pattern'], 'sliceSummary: patterns_established');
223
+ assertEq(parsed.frontmatter.duration, '2h', 'sliceSummary: duration');
224
+ assertEq(parsed.frontmatter.completed_at, '2026-03-10', 'sliceSummary: completed_at');
225
+ assertEq(parsed.frontmatter.verification_result, 'passed', 'sliceSummary: verification_result');
226
+ assertEq(parsed.frontmatter.blocker_discovered, false, 'sliceSummary: blocker_discovered');
227
+ assertTrue(parsed.whatHappened.includes('Implemented full auth system'), 'sliceSummary: whatHappened content');
228
+ assertEq(parsed.title, 'S01: Auth System', 'sliceSummary: title');
229
+ }
230
+
231
+ // ═══════════════════════════════════════════════════════════════════════════
232
+ // Scenario D: Task summary round-trip
233
+ // ═══════════════════════════════════════════════════════════════════════════
234
+
235
+ {
220
236
  const task = makeTask({
221
237
  id: 'T01',
222
238
  title: 'Setup Auth',
@@ -227,18 +243,22 @@ test('Scenario D: Task summary round-trip', () => {
227
243
  const output = formatTaskSummary(task, 'S01', 'M001');
228
244
  const parsed = parseSummary(output);
229
245
 
230
- assert.deepStrictEqual(parsed.frontmatter.id, 'T01', 'taskSummary: id');
231
- assert.deepStrictEqual(parsed.frontmatter.parent, 'S01', 'taskSummary: parent');
232
- assert.deepStrictEqual(parsed.frontmatter.milestone, 'M001', 'taskSummary: milestone');
233
- assert.deepStrictEqual(parsed.frontmatter.provides, ['auth-endpoint'], 'taskSummary: provides');
234
- assert.deepStrictEqual(parsed.frontmatter.key_files, ['src/auth.ts'], 'taskSummary: key_files');
235
- assert.deepStrictEqual(parsed.frontmatter.duration, '45m', 'taskSummary: duration');
236
- assert.deepStrictEqual(parsed.frontmatter.completed_at, '2026-03-09', 'taskSummary: completed_at');
237
- assert.ok(parsed.whatHappened.includes('Built the auth endpoint'), 'taskSummary: whatHappened content');
238
- assert.deepStrictEqual(parsed.title, 'T01: Setup Auth', 'taskSummary: title');
239
- });
240
-
241
- test('Scenario E: Requirements round-trip with mixed statuses', () => {
246
+ assertEq(parsed.frontmatter.id, 'T01', 'taskSummary: id');
247
+ assertEq(parsed.frontmatter.parent, 'S01', 'taskSummary: parent');
248
+ assertEq(parsed.frontmatter.milestone, 'M001', 'taskSummary: milestone');
249
+ assertEq(parsed.frontmatter.provides, ['auth-endpoint'], 'taskSummary: provides');
250
+ assertEq(parsed.frontmatter.key_files, ['src/auth.ts'], 'taskSummary: key_files');
251
+ assertEq(parsed.frontmatter.duration, '45m', 'taskSummary: duration');
252
+ assertEq(parsed.frontmatter.completed_at, '2026-03-09', 'taskSummary: completed_at');
253
+ assertTrue(parsed.whatHappened.includes('Built the auth endpoint'), 'taskSummary: whatHappened content');
254
+ assertEq(parsed.title, 'T01: Setup Auth', 'taskSummary: title');
255
+ }
256
+
257
+ // ═══════════════════════════════════════════════════════════════════════════
258
+ // Scenario E: Requirements round-trip with mixed statuses
259
+ // ═══════════════════════════════════════════════════════════════════════════
260
+
261
+ {
242
262
  const requirements: GSDRequirement[] = [
243
263
  { id: 'R001', title: 'Auth Required', class: 'core-capability', status: 'active', description: 'Must have auth', source: 'spec', primarySlice: 'S01' },
244
264
  { id: 'R002', title: 'Logging', class: 'observability', status: 'active', description: 'Must log', source: 'spec', primarySlice: 'S02' },
@@ -250,93 +270,110 @@ test('Scenario E: Requirements round-trip with mixed statuses', () => {
250
270
  const output = formatRequirements(requirements);
251
271
  const counts = parseRequirementCounts(output);
252
272
 
253
- assert.deepStrictEqual(counts.active, 2, 'requirements: active count');
254
- assert.deepStrictEqual(counts.validated, 1, 'requirements: validated count');
255
- assert.deepStrictEqual(counts.deferred, 1, 'requirements: deferred count');
256
- assert.deepStrictEqual(counts.outOfScope, 1, 'requirements: outOfScope count');
257
- assert.deepStrictEqual(counts.total, 5, 'requirements: total count');
258
- });
273
+ assertEq(counts.active, 2, 'requirements: active count');
274
+ assertEq(counts.validated, 1, 'requirements: validated count');
275
+ assertEq(counts.deferred, 1, 'requirements: deferred count');
276
+ assertEq(counts.outOfScope, 1, 'requirements: outOfScope count');
277
+ assertEq(counts.total, 5, 'requirements: total count');
278
+ }
279
+
280
+ // ═══════════════════════════════════════════════════════════════════════════
281
+ // Scenario F: Edge cases
282
+ // ═══════════════════════════════════════════════════════════════════════════
259
283
 
260
- test('F1: Empty vision → fallback text', () => {
284
+ // F1: Empty vision → fallback text
285
+ {
261
286
  const milestone = makeMilestone({ vision: '' });
262
287
  const output = formatRoadmap(milestone);
263
288
  const parsed = parseRoadmap(output);
264
- assert.deepStrictEqual(parsed.vision, '(migrated project)', 'edge: empty vision fallback');
265
- });
289
+ assertEq(parsed.vision, '(migrated project)', 'edge: empty vision fallback');
290
+ }
266
291
 
267
- test('F2: Empty successCriteria → empty array', () => {
292
+ // F2: Empty successCriteria → empty array
293
+ {
268
294
  const milestone = makeMilestone({ successCriteria: [] });
269
295
  const output = formatRoadmap(milestone);
270
296
  const parsed = parseRoadmap(output);
271
- assert.deepStrictEqual(parsed.successCriteria.length, 0, 'edge: empty successCriteria');
272
- });
297
+ assertEq(parsed.successCriteria.length, 0, 'edge: empty successCriteria');
298
+ }
273
299
 
274
- test('F3: Empty tasks → empty array in parsed plan', () => {
300
+ // F3: Empty tasks → empty array in parsed plan
301
+ {
275
302
  const slice = makeSlice({ tasks: [] });
276
303
  const output = formatPlan(slice);
277
304
  const parsed = parsePlan(output);
278
- assert.deepStrictEqual(parsed.tasks.length, 0, 'edge: empty tasks');
279
- });
305
+ assertEq(parsed.tasks.length, 0, 'edge: empty tasks');
306
+ }
280
307
 
281
- test('F4: Null summary → empty string from formatSliceSummary', () => {
308
+ // F4: Null summary → empty string from formatSliceSummary
309
+ {
282
310
  const slice = makeSlice({ summary: null });
283
311
  const output = formatSliceSummary(slice, 'M001');
284
- assert.deepStrictEqual(output, '', 'edge: null summary returns empty string');
285
- });
312
+ assertEq(output, '', 'edge: null summary returns empty string');
313
+ }
286
314
 
287
- test('F5: Done=true checkbox in roadmap', () => {
315
+ // F5: Done=true checkbox in roadmap
316
+ {
288
317
  const milestone = makeMilestone({
289
318
  slices: [makeSlice({ id: 'S01', done: true })],
290
319
  });
291
320
  const output = formatRoadmap(milestone);
292
321
  const parsed = parseRoadmap(output);
293
- assert.deepStrictEqual(parsed.slices[0].done, true, 'edge: done checkbox true');
294
- });
322
+ assertEq(parsed.slices[0].done, true, 'edge: done checkbox true');
323
+ }
295
324
 
296
- test('F6: Done=false checkbox in roadmap', () => {
325
+ // F6: Done=false checkbox in roadmap
326
+ {
297
327
  const milestone = makeMilestone({
298
328
  slices: [makeSlice({ id: 'S01', done: false })],
299
329
  });
300
330
  const output = formatRoadmap(milestone);
301
331
  const parsed = parseRoadmap(output);
302
- assert.deepStrictEqual(parsed.slices[0].done, false, 'edge: done checkbox false');
303
- });
332
+ assertEq(parsed.slices[0].done, false, 'edge: done checkbox false');
333
+ }
304
334
 
305
- test('F7: Null task summary → empty string from formatTaskSummary', () => {
335
+ // F7: Null task summary → empty string from formatTaskSummary
336
+ {
306
337
  const task = makeTask({ summary: null });
307
338
  const output = formatTaskSummary(task, 'S01', 'M001');
308
- assert.deepStrictEqual(output, '', 'edge: null task summary returns empty string');
309
- });
339
+ assertEq(output, '', 'edge: null task summary returns empty string');
340
+ }
310
341
 
311
- test('F8: Empty requirements → all zeros', () => {
342
+ // F8: Empty requirements → all zeros
343
+ {
312
344
  const output = formatRequirements([]);
313
345
  const counts = parseRequirementCounts(output);
314
- assert.deepStrictEqual(counts.total, 0, 'edge: empty requirements total 0');
315
- });
346
+ assertEq(counts.total, 0, 'edge: empty requirements total 0');
347
+ }
316
348
 
317
- test('F9: formatProject with empty content → produces valid stub', () => {
349
+ // F9: formatProject with empty content → produces valid stub
350
+ {
318
351
  const output = formatProject('');
319
- assert.ok(output.includes('# Project'), 'edge: empty project has heading');
320
- assert.ok(output.length > 10, 'edge: empty project not blank');
321
- });
352
+ assertTrue(output.includes('# Project'), 'edge: empty project has heading');
353
+ assertTrue(output.length > 10, 'edge: empty project not blank');
354
+ }
322
355
 
323
- test('F10: formatProject with existing content → passes through', () => {
356
+ // F10: formatProject with existing content → passes through
357
+ {
324
358
  const content = '# My Project\n\nDescription here.\n';
325
359
  const output = formatProject(content);
326
- assert.deepStrictEqual(output, content, 'edge: project passthrough');
327
- });
360
+ assertEq(output, content, 'edge: project passthrough');
361
+ }
328
362
 
329
- test('F11: formatDecisions with empty content → produces valid stub', () => {
363
+ // F11: formatDecisions with empty content → produces valid stub
364
+ {
330
365
  const output = formatDecisions('');
331
- assert.ok(output.includes('# Decisions'), 'edge: empty decisions has heading');
332
- });
366
+ assertTrue(output.includes('# Decisions'), 'edge: empty decisions has heading');
367
+ }
333
368
 
334
- test('F12: formatContext produces valid content', () => {
369
+ // F12: formatContext produces valid content
370
+ {
335
371
  const output = formatContext('M001');
336
- assert.ok(output.includes('M001'), 'edge: context mentions milestone');
337
- });
372
+ assertTrue(output.includes('M001'), 'edge: context mentions milestone');
373
+ }
338
374
 
339
- test('F13: formatState produces valid content', () => {
375
+ // F13: formatState produces valid content
376
+ {
340
377
  const milestones = [makeMilestone({
341
378
  slices: [
342
379
  makeSlice({ done: true }),
@@ -344,18 +381,20 @@ test('F13: formatState produces valid content', () => {
344
381
  ],
345
382
  })];
346
383
  const output = formatState(milestones);
347
- assert.ok(output.includes('1/2'), 'edge: state shows slice progress');
348
- });
384
+ assertTrue(output.includes('1/2'), 'edge: state shows slice progress');
385
+ }
349
386
 
350
- test('F14: Task with no estimate → no est backtick in plan', () => {
387
+ // F14: Task with no estimate → no est backtick in plan
388
+ {
351
389
  const slice = makeSlice({
352
390
  tasks: [makeTask({ id: 'T01', title: 'Quick Fix', estimate: '' })],
353
391
  });
354
392
  const output = formatPlan(slice);
355
393
  const parsed = parsePlan(output);
356
- assert.deepStrictEqual(parsed.tasks[0].id, 'T01', 'edge: task no estimate id');
357
- assert.deepStrictEqual(parsed.tasks[0].estimate, '', 'edge: task no estimate empty');
358
- });
394
+ assertEq(parsed.tasks[0].id, 'T01', 'edge: task no estimate id');
395
+ assertEq(parsed.tasks[0].estimate, '', 'edge: task no estimate empty');
396
+ }
359
397
 
360
398
  // ═══════════════════════════════════════════════════════════════════════════
361
399
 
400
+ report();