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
@@ -43,36 +43,31 @@ function makeNoUICtx(cwd: string) {
43
43
 
44
44
  // ─── Scenario 1: No manifest exists ──────────────────────────────────────────
45
45
 
46
- test('secrets gate: no manifest exists — getManifestStatus returns null', async (t) => {
46
+ test('secrets gate: no manifest exists — getManifestStatus returns null', async () => {
47
47
  const tmp = makeTempDir('gate-no-manifest');
48
- t.after(() => rmSync(tmp, { recursive: true, force: true }));
49
-
50
- // No .gsd directory at all
51
- const result = await getManifestStatus(tmp, 'M001');
52
- assert.strictEqual(result, null, 'should return null when no manifest file exists');
48
+ try {
49
+ // No .gsd directory at all
50
+ const result = await getManifestStatus(tmp, 'M001');
51
+ assert.strictEqual(result, null, 'should return null when no manifest file exists');
52
+ } finally {
53
+ rmSync(tmp, { recursive: true, force: true });
54
+ }
53
55
  });
54
56
 
55
57
  // ─── Scenario 2: Pending keys exist ─────────────────────────────────────────
56
58
 
57
- test('secrets gate: pending keys exist — gate triggers collection, manifest updated on disk', async (t) => {
59
+ test('secrets gate: pending keys exist — gate triggers collection, manifest updated on disk', async () => {
58
60
  const tmp = makeTempDir('gate-pending');
59
61
  const savedA = process.env.GSD_GATE_TEST_EXISTING;
60
- t.after(() => {
61
- delete process.env.GSD_GATE_TEST_EXISTING;
62
- if (savedA !== undefined) process.env.GSD_GATE_TEST_EXISTING = savedA;
62
+ try {
63
+ // Simulate one key already in env
64
+ process.env.GSD_GATE_TEST_EXISTING = 'already-here';
65
+
66
+ // Ensure pending keys are NOT in env
63
67
  delete process.env.GSD_GATE_TEST_PEND_A;
64
68
  delete process.env.GSD_GATE_TEST_PEND_B;
65
- rmSync(tmp, { recursive: true, force: true });
66
- });
67
-
68
- // Simulate one key already in env
69
- process.env.GSD_GATE_TEST_EXISTING = 'already-here';
70
-
71
- // Ensure pending keys are NOT in env
72
- delete process.env.GSD_GATE_TEST_PEND_A;
73
- delete process.env.GSD_GATE_TEST_PEND_B;
74
69
 
75
- writeManifest(tmp, `# Secrets Manifest
70
+ writeManifest(tmp, `# Secrets Manifest
76
71
 
77
72
  **Milestone:** M001
78
73
  **Generated:** 2025-06-20T10:00:00Z
@@ -102,60 +97,62 @@ test('secrets gate: pending keys exist — gate triggers collection, manifest up
102
97
  1. Already in env
103
98
  `);
104
99
 
105
- // (a) Verify getManifestStatus shows pending keys
106
- const status = await getManifestStatus(tmp, 'M001');
107
- assert.notStrictEqual(status, null, 'manifest should exist');
108
- assert.ok(status!.pending.length > 0, 'should have pending keys');
109
- assert.deepStrictEqual(status!.pending, ['GSD_GATE_TEST_PEND_A', 'GSD_GATE_TEST_PEND_B'], 'pending keys');
110
- assert.deepStrictEqual(status!.existing, ['GSD_GATE_TEST_EXISTING'], 'existing keys');
111
-
112
- // (b) Call collectSecretsFromManifest with no-UI context
113
- // With hasUI: false, collectOneSecret returns null → pending keys become "skipped"
114
- const result = await collectSecretsFromManifest(tmp, 'M001', makeNoUICtx(tmp));
115
-
116
- // (c) Verify return shape
117
- assert.deepStrictEqual(result.applied, [], 'no keys applied (no UI to enter values)');
118
- assert.ok(result.skipped.includes('GSD_GATE_TEST_PEND_A'), 'PEND_A should be skipped');
119
- assert.ok(result.skipped.includes('GSD_GATE_TEST_PEND_B'), 'PEND_B should be skipped');
120
- assert.deepStrictEqual(result.existingSkipped, ['GSD_GATE_TEST_EXISTING']);
121
-
122
- // (d) Verify manifest on disk was updated — pending entries that went through
123
- // collection are now "skipped". The existing-in-env entry retains its manifest
124
- // status ("pending") because collectSecretsFromManifest only updates entries
125
- // that flow through collectOneSecret. At runtime, getManifestStatus overrides
126
- // env-present entries to "existing" regardless of manifest status.
127
- const manifestPath = join(tmp, '.gsd', 'milestones', 'M001', 'M001-SECRETS.md');
128
- const updatedContent = readFileSync(manifestPath, 'utf8');
129
- assert.ok(
130
- updatedContent.includes('**Status:** skipped'),
131
- 'formerly-pending entries should now have status "skipped" in the manifest file',
132
- );
133
- // Count: PEND_A → skipped, PEND_B → skipped, EXISTING stays pending on disk
134
- const skippedMatches = updatedContent.match(/\*\*Status:\*\* skipped/g);
135
- assert.strictEqual(skippedMatches?.length, 2, 'two entries should have status "skipped"');
136
- const pendingMatches = updatedContent.match(/\*\*Status:\*\* pending/g);
137
- assert.strictEqual(pendingMatches?.length, 1, 'one entry (existing-in-env) retains pending on disk');
138
-
139
- // (e) Verify getManifestStatus now shows no pending
140
- const statusAfter = await getManifestStatus(tmp, 'M001');
141
- assert.notStrictEqual(statusAfter, null);
142
- assert.deepStrictEqual(statusAfter!.pending, [], 'no pending keys after collection');
100
+ // (a) Verify getManifestStatus shows pending keys
101
+ const status = await getManifestStatus(tmp, 'M001');
102
+ assert.notStrictEqual(status, null, 'manifest should exist');
103
+ assert.ok(status!.pending.length > 0, 'should have pending keys');
104
+ assert.deepStrictEqual(status!.pending, ['GSD_GATE_TEST_PEND_A', 'GSD_GATE_TEST_PEND_B'], 'pending keys');
105
+ assert.deepStrictEqual(status!.existing, ['GSD_GATE_TEST_EXISTING'], 'existing keys');
106
+
107
+ // (b) Call collectSecretsFromManifest with no-UI context
108
+ // With hasUI: false, collectOneSecret returns null → pending keys become "skipped"
109
+ const result = await collectSecretsFromManifest(tmp, 'M001', makeNoUICtx(tmp));
110
+
111
+ // (c) Verify return shape
112
+ assert.deepStrictEqual(result.applied, [], 'no keys applied (no UI to enter values)');
113
+ assert.ok(result.skipped.includes('GSD_GATE_TEST_PEND_A'), 'PEND_A should be skipped');
114
+ assert.ok(result.skipped.includes('GSD_GATE_TEST_PEND_B'), 'PEND_B should be skipped');
115
+ assert.deepStrictEqual(result.existingSkipped, ['GSD_GATE_TEST_EXISTING']);
116
+
117
+ // (d) Verify manifest on disk was updated — pending entries that went through
118
+ // collection are now "skipped". The existing-in-env entry retains its manifest
119
+ // status ("pending") because collectSecretsFromManifest only updates entries
120
+ // that flow through collectOneSecret. At runtime, getManifestStatus overrides
121
+ // env-present entries to "existing" regardless of manifest status.
122
+ const manifestPath = join(tmp, '.gsd', 'milestones', 'M001', 'M001-SECRETS.md');
123
+ const updatedContent = readFileSync(manifestPath, 'utf8');
124
+ assert.ok(
125
+ updatedContent.includes('**Status:** skipped'),
126
+ 'formerly-pending entries should now have status "skipped" in the manifest file',
127
+ );
128
+ // Count: PEND_A → skipped, PEND_B → skipped, EXISTING stays pending on disk
129
+ const skippedMatches = updatedContent.match(/\*\*Status:\*\* skipped/g);
130
+ assert.strictEqual(skippedMatches?.length, 2, 'two entries should have status "skipped"');
131
+ const pendingMatches = updatedContent.match(/\*\*Status:\*\* pending/g);
132
+ assert.strictEqual(pendingMatches?.length, 1, 'one entry (existing-in-env) retains pending on disk');
133
+
134
+ // (e) Verify getManifestStatus now shows no pending
135
+ const statusAfter = await getManifestStatus(tmp, 'M001');
136
+ assert.notStrictEqual(statusAfter, null);
137
+ assert.deepStrictEqual(statusAfter!.pending, [], 'no pending keys after collection');
138
+ } finally {
139
+ delete process.env.GSD_GATE_TEST_EXISTING;
140
+ if (savedA !== undefined) process.env.GSD_GATE_TEST_EXISTING = savedA;
141
+ delete process.env.GSD_GATE_TEST_PEND_A;
142
+ delete process.env.GSD_GATE_TEST_PEND_B;
143
+ rmSync(tmp, { recursive: true, force: true });
144
+ }
143
145
  });
144
146
 
145
147
  // ─── Scenario 3: No pending keys — all collected or in env ──────────────────
146
148
 
147
- test('secrets gate: no pending keys — getManifestStatus shows pending.length === 0', async (t) => {
149
+ test('secrets gate: no pending keys — getManifestStatus shows pending.length === 0', async () => {
148
150
  const tmp = makeTempDir('gate-no-pending');
149
151
  const savedKey = process.env.GSD_GATE_TEST_ENVKEY;
150
- t.after(() => {
151
- delete process.env.GSD_GATE_TEST_ENVKEY;
152
- if (savedKey !== undefined) process.env.GSD_GATE_TEST_ENVKEY = savedKey;
153
- rmSync(tmp, { recursive: true, force: true });
154
- });
155
-
156
- process.env.GSD_GATE_TEST_ENVKEY = 'some-value';
152
+ try {
153
+ process.env.GSD_GATE_TEST_ENVKEY = 'some-value';
157
154
 
158
- writeManifest(tmp, `# Secrets Manifest
155
+ writeManifest(tmp, `# Secrets Manifest
159
156
 
160
157
  **Milestone:** M001
161
158
  **Generated:** 2025-06-20T10:00:00Z
@@ -185,10 +182,15 @@ test('secrets gate: no pending keys — getManifestStatus shows pending.length =
185
182
  1. In env already
186
183
  `);
187
184
 
188
- const result = await getManifestStatus(tmp, 'M001');
189
- assert.notStrictEqual(result, null, 'manifest should exist');
190
- assert.deepStrictEqual(result!.pending, [], 'no pending keys — gate would skip');
191
- assert.deepStrictEqual(result!.collected, ['ALREADY_COLLECTED']);
192
- assert.deepStrictEqual(result!.skipped, ['ALREADY_SKIPPED']);
193
- assert.deepStrictEqual(result!.existing, ['GSD_GATE_TEST_ENVKEY']);
185
+ const result = await getManifestStatus(tmp, 'M001');
186
+ assert.notStrictEqual(result, null, 'manifest should exist');
187
+ assert.deepStrictEqual(result!.pending, [], 'no pending keys — gate would skip');
188
+ assert.deepStrictEqual(result!.collected, ['ALREADY_COLLECTED']);
189
+ assert.deepStrictEqual(result!.skipped, ['ALREADY_SKIPPED']);
190
+ assert.deepStrictEqual(result!.existing, ['GSD_GATE_TEST_ENVKEY']);
191
+ } finally {
192
+ delete process.env.GSD_GATE_TEST_ENVKEY;
193
+ if (savedKey !== undefined) process.env.GSD_GATE_TEST_ENVKEY = savedKey;
194
+ rmSync(tmp, { recursive: true, force: true });
195
+ }
194
196
  });
@@ -22,8 +22,6 @@
22
22
  * - The !hasSurvivorBranch block has a needs-discussion handler
23
23
  */
24
24
 
25
- import { describe, test, afterEach } from "node:test";
26
- import assert from "node:assert/strict";
27
25
  import { mkdtempSync, mkdirSync, rmSync, writeFileSync, readFileSync } from "node:fs";
28
26
  import { join } from "node:path";
29
27
  import { tmpdir } from "node:os";
@@ -32,6 +30,9 @@ import { dirname } from "node:path";
32
30
 
33
31
  import { deriveState } from "../state.ts";
34
32
  import { invalidateAllCaches } from "../cache.ts";
33
+ import { createTestContext } from "./test-helpers.ts";
34
+
35
+ const { assertEq, assertTrue, report } = createTestContext();
35
36
 
36
37
  // ─── Fixture Helpers ─────────────────────────────────────────────────────────
37
38
 
@@ -75,46 +76,52 @@ function readAutoStartSource(): string {
75
76
  // Tests
76
77
  // ═══════════════════════════════════════════════════════════════════════════════
77
78
 
78
- describe("auto-start-needs-discussion (#1726)", () => {
79
+ async function main(): Promise<void> {
79
80
 
80
- test("1. CONTEXT-DRAFT.md only needs-discussion phase", async () => {
81
+ // ─── 1. deriveState returns needs-discussion for CONTEXT-DRAFT only ────────
82
+ console.log("\n=== 1. CONTEXT-DRAFT.md only → needs-discussion phase ===");
83
+ {
81
84
  const base = createBase();
82
85
  try {
83
86
  writeContextDraft(base, "M001", "# Draft\nSeed discussion.");
84
87
  invalidateAllCaches();
85
88
  const state = await deriveState(base);
86
- assert.strictEqual(state.phase, "needs-discussion",
89
+ assertEq(state.phase, "needs-discussion",
87
90
  "milestone with only CONTEXT-DRAFT should be needs-discussion");
88
- assert.ok(!!state.activeMilestone,
91
+ assertTrue(!!state.activeMilestone,
89
92
  "activeMilestone should be set for needs-discussion");
90
- assert.strictEqual(state.activeMilestone?.id, "M001",
93
+ assertEq(state.activeMilestone?.id, "M001",
91
94
  "activeMilestone.id should be M001");
92
95
  } finally {
93
96
  cleanup(base);
94
97
  }
95
- });
98
+ }
96
99
 
97
- test("2. Survivor branch check excludes needs-discussion", () => {
100
+ // ─── 2. Survivor branch filter excludes needs-discussion (#1726 bug 1) ────
101
+ console.log("\n=== 2. Survivor branch check excludes needs-discussion ===");
102
+ {
98
103
  const source = readAutoStartSource();
99
104
 
100
105
  // Find the survivor branch check block (Milestone branch recovery comment)
101
106
  const survivorBlock = source.match(
102
107
  /\/\/ Milestone branch recovery.*?hasSurvivorBranch = nativeBranchExists/s,
103
108
  );
104
- assert.ok(!!survivorBlock,
109
+ assertTrue(!!survivorBlock,
105
110
  "found survivor branch check block in auto-start.ts");
106
111
 
107
112
  if (survivorBlock) {
108
113
  const block = survivorBlock[0];
109
114
  // The condition should only check pre-planning, NOT needs-discussion
110
- assert.ok(!block.includes("needs-discussion"),
115
+ assertTrue(!block.includes("needs-discussion"),
111
116
  "survivor branch filter must NOT include needs-discussion phase");
112
- assert.ok(block.includes("pre-planning"),
117
+ assertTrue(block.includes("pre-planning"),
113
118
  "survivor branch filter should include pre-planning phase");
114
119
  }
115
- });
120
+ }
116
121
 
117
- test("3. needs-discussion handler exists in bootstrap", () => {
122
+ // ─── 3. needs-discussion handler exists in !hasSurvivorBranch block (#1726 bug 2)
123
+ console.log("\n=== 3. needs-discussion handler exists in bootstrap ===");
124
+ {
118
125
  const source = readAutoStartSource();
119
126
 
120
127
  // After the pre-planning handler, there should be a needs-discussion handler
@@ -122,26 +129,30 @@ describe("auto-start-needs-discussion (#1726)", () => {
122
129
  const needsDiscussionHandler = source.match(
123
130
  /if\s*\(state\.phase\s*===\s*"needs-discussion"\)\s*\{[^}]*showSmartEntry/s,
124
131
  );
125
- assert.ok(!!needsDiscussionHandler,
132
+ assertTrue(!!needsDiscussionHandler,
126
133
  "needs-discussion handler calling showSmartEntry must exist in !hasSurvivorBranch block");
127
- });
134
+ }
128
135
 
129
- test("4. needs-discussion handler has abort path", () => {
136
+ // ─── 4. needs-discussion handler aborts if discussion doesn't promote draft
137
+ console.log("\n=== 4. needs-discussion handler has abort path ===");
138
+ {
130
139
  const source = readAutoStartSource();
131
140
 
132
141
  // The handler should check postState.phase !== "needs-discussion" and abort
133
142
  // if discussion didn't promote the draft
134
- assert.ok(
143
+ assertTrue(
135
144
  source.includes('postState.phase !== "needs-discussion"'),
136
145
  "needs-discussion handler must check if phase advanced after showSmartEntry",
137
146
  );
138
- assert.ok(
147
+ assertTrue(
139
148
  source.includes("milestone draft was not promoted"),
140
149
  "needs-discussion handler must have abort message when draft not promoted",
141
150
  );
142
- });
151
+ }
143
152
 
144
- test("5. Full context + roadmap → not needs-discussion", async () => {
153
+ // ─── 5. CONTEXT-DRAFT + CONTEXT + ROADMAP → not needs-discussion ──────────
154
+ console.log("\n=== 5. Full context + roadmap → not needs-discussion ===");
155
+ {
145
156
  const base = createBase();
146
157
  try {
147
158
  writeContextDraft(base, "M001", "# Draft\nSeed discussion.");
@@ -150,14 +161,16 @@ describe("auto-start-needs-discussion (#1726)", () => {
150
161
  "# M001: Test\n\n## Slices\n- [ ] **S01: Test Slice** `risk:low` `depends:[]`\n > After this: works\n");
151
162
  invalidateAllCaches();
152
163
  const state = await deriveState(base);
153
- assert.ok(state.phase !== "needs-discussion",
164
+ assertTrue(state.phase !== "needs-discussion",
154
165
  "milestone with full context + roadmap should NOT be needs-discussion");
155
166
  } finally {
156
167
  cleanup(base);
157
168
  }
158
- });
169
+ }
159
170
 
160
- test("6. No infinite loop: needs-discussion always routes to showSmartEntry", () => {
171
+ // ─── 6. Verify the two bug conditions cannot produce infinite loop ────────
172
+ console.log("\n=== 6. No infinite loop: needs-discussion always routes to showSmartEntry ===");
173
+ {
161
174
  const source = readAutoStartSource();
162
175
 
163
176
  // Verify needs-discussion does NOT appear in auto-dispatch trigger conditions
@@ -167,7 +180,7 @@ describe("auto-start-needs-discussion (#1726)", () => {
167
180
  /\/\/ Milestone branch recovery.*?let hasSurvivorBranch = false;[\s\S]*?if\s*\([^)]*state\.phase[^)]*\)\s*\{/,
168
181
  );
169
182
  if (survivorSection) {
170
- assert.ok(
183
+ assertTrue(
171
184
  !survivorSection[0].includes("needs-discussion"),
172
185
  "survivor branch phase condition must not mention needs-discussion",
173
186
  );
@@ -177,17 +190,19 @@ describe("auto-start-needs-discussion (#1726)", () => {
177
190
  const notSurvivorBlock = source.match(
178
191
  /if\s*\(!hasSurvivorBranch\)\s*\{([\s\S]*?)\/\/ Unreachable safety check/,
179
192
  );
180
- assert.ok(!!notSurvivorBlock,
193
+ assertTrue(!!notSurvivorBlock,
181
194
  "found !hasSurvivorBranch block in auto-start.ts");
182
195
  if (notSurvivorBlock) {
183
- assert.ok(
196
+ assertTrue(
184
197
  notSurvivorBlock[1].includes('"needs-discussion"'),
185
198
  "!hasSurvivorBranch block must handle needs-discussion phase",
186
199
  );
187
200
  }
188
- });
201
+ }
189
202
 
190
- test("7. Survivor branch + needs-discussion routes to showSmartEntry", () => {
203
+ // ─── 7. Survivor branch + needs-discussion routes to showSmartEntry (#1726)
204
+ console.log("\n=== 7. Survivor branch + needs-discussion routes to showSmartEntry ===");
205
+ {
191
206
  const source = readAutoStartSource();
192
207
 
193
208
  // When hasSurvivorBranch is true AND phase is needs-discussion, the code
@@ -195,24 +210,31 @@ describe("auto-start-needs-discussion (#1726)", () => {
195
210
  const survivorNeedsDiscussion = source.match(
196
211
  /if\s*\(hasSurvivorBranch\s*&&\s*state\.phase\s*===\s*"needs-discussion"\)\s*\{[^}]*showSmartEntry/s,
197
212
  );
198
- assert.ok(!!survivorNeedsDiscussion,
213
+ assertTrue(!!survivorNeedsDiscussion,
199
214
  "hasSurvivorBranch && needs-discussion must route to showSmartEntry");
200
215
 
201
216
  // Verify the handler checks if the discussion succeeded
202
217
  const handlerBlock = source.match(
203
218
  /if\s*\(hasSurvivorBranch\s*&&\s*state\.phase\s*===\s*"needs-discussion"\)\s*\{([\s\S]*?)\n \}/,
204
219
  );
205
- assert.ok(!!handlerBlock,
220
+ assertTrue(!!handlerBlock,
206
221
  "found survivor + needs-discussion handler block");
207
222
  if (handlerBlock) {
208
- assert.ok(
223
+ assertTrue(
209
224
  handlerBlock[1].includes('postState.phase !== "needs-discussion"'),
210
225
  "handler must check if phase advanced after discussion",
211
226
  );
212
- assert.ok(
227
+ assertTrue(
213
228
  handlerBlock[1].includes("releaseLockAndReturn"),
214
229
  "handler must abort if discussion didn't promote draft",
215
230
  );
216
231
  }
217
- });
232
+ }
233
+
234
+ report();
235
+ }
236
+
237
+ main().catch((err) => {
238
+ console.error(err);
239
+ process.exit(1);
218
240
  });