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
@@ -162,7 +162,7 @@ describe("continue-here", () => {
162
162
  });
163
163
 
164
164
  describe("continueHereFired runtime record field", () => {
165
- it("AutoUnitRuntimeRecord includes continueHereFired with default false", async (t) => {
165
+ it("AutoUnitRuntimeRecord includes continueHereFired with default false", async () => {
166
166
  // Import writeUnitRuntimeRecord to verify the field is present and defaults
167
167
  const { writeUnitRuntimeRecord, readUnitRuntimeRecord, clearUnitRuntimeRecord } = await import("../unit-runtime.js");
168
168
  const fs = await import("node:fs");
@@ -171,83 +171,87 @@ describe("continue-here", () => {
171
171
 
172
172
  // Use a temp directory as basePath
173
173
  const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "continue-here-test-"));
174
- t.after(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
175
-
176
- const record = writeUnitRuntimeRecord(tmpDir, "execute-task", "M007/S02/T02", Date.now(), {
177
- phase: "dispatched",
178
- wrapupWarningSent: false,
179
- });
180
-
181
- assert.equal(record.continueHereFired, false, "default continueHereFired should be false");
182
-
183
- // Verify it persists to disk
184
- const read = readUnitRuntimeRecord(tmpDir, "execute-task", "M007/S02/T02");
185
- assert.ok(read, "record should be readable");
186
- assert.equal(read!.continueHereFired, false);
187
-
188
- // Update to true
189
- const updated = writeUnitRuntimeRecord(tmpDir, "execute-task", "M007/S02/T02", Date.now(), {
190
- continueHereFired: true,
191
- });
192
- assert.equal(updated.continueHereFired, true, "updated continueHereFired should be true");
193
-
194
- // Verify persistence
195
- const readUpdated = readUnitRuntimeRecord(tmpDir, "execute-task", "M007/S02/T02");
196
- assert.equal(readUpdated!.continueHereFired, true, "persisted continueHereFired should be true");
197
-
198
- // Clean up
199
- clearUnitRuntimeRecord(tmpDir, "execute-task", "M007/S02/T02");
174
+ try {
175
+ const record = writeUnitRuntimeRecord(tmpDir, "execute-task", "M007/S02/T02", Date.now(), {
176
+ phase: "dispatched",
177
+ wrapupWarningSent: false,
178
+ });
179
+
180
+ assert.equal(record.continueHereFired, false, "default continueHereFired should be false");
181
+
182
+ // Verify it persists to disk
183
+ const read = readUnitRuntimeRecord(tmpDir, "execute-task", "M007/S02/T02");
184
+ assert.ok(read, "record should be readable");
185
+ assert.equal(read!.continueHereFired, false);
186
+
187
+ // Update to true
188
+ const updated = writeUnitRuntimeRecord(tmpDir, "execute-task", "M007/S02/T02", Date.now(), {
189
+ continueHereFired: true,
190
+ });
191
+ assert.equal(updated.continueHereFired, true, "updated continueHereFired should be true");
192
+
193
+ // Verify persistence
194
+ const readUpdated = readUnitRuntimeRecord(tmpDir, "execute-task", "M007/S02/T02");
195
+ assert.equal(readUpdated!.continueHereFired, true, "persisted continueHereFired should be true");
196
+
197
+ // Clean up
198
+ clearUnitRuntimeRecord(tmpDir, "execute-task", "M007/S02/T02");
199
+ } finally {
200
+ fs.rmSync(tmpDir, { recursive: true, force: true });
201
+ }
200
202
  });
201
203
  });
202
204
 
203
205
  describe("context-pressure monitor integration", () => {
204
- it("should fire wrap-up when context >= threshold and mark continueHereFired", async (t) => {
206
+ it("should fire wrap-up when context >= threshold and mark continueHereFired", async () => {
205
207
  const { writeUnitRuntimeRecord, readUnitRuntimeRecord, clearUnitRuntimeRecord } = await import("../unit-runtime.js");
206
208
  const fs = await import("node:fs");
207
209
  const path = await import("node:path");
208
210
  const os = await import("node:os");
209
211
 
210
212
  const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "continue-here-monitor-"));
211
- t.after(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
212
-
213
- // Simulate the monitor's one-shot logic:
214
- // 1. Write initial runtime record (continueHereFired=false)
215
- const startedAt = Date.now();
216
- writeUnitRuntimeRecord(tmpDir, "execute-task", "M001/S01/T01", startedAt, {
217
- phase: "dispatched",
218
- wrapupWarningSent: false,
219
- });
220
-
221
- const budget = computeBudgets(128_000);
222
- const threshold = budget.continueThresholdPercent;
223
-
224
- // Simulate the monitor poll: context at 75% (above threshold)
225
- const contextPercent = 75;
226
- const runtime = readUnitRuntimeRecord(tmpDir, "execute-task", "M001/S01/T01");
227
- assert.ok(runtime, "runtime record should exist");
228
- assert.equal(runtime!.continueHereFired, false, "initially false");
229
-
230
- // Check: should fire
231
- const shouldFire = !runtime!.continueHereFired
232
- && contextPercent >= threshold;
233
- assert.ok(shouldFire, "should fire when context >= threshold and not yet fired");
234
-
235
- // Mark as fired (what the monitor does)
236
- writeUnitRuntimeRecord(tmpDir, "execute-task", "M001/S01/T01", startedAt, {
237
- continueHereFired: true,
238
- });
239
-
240
- // Verify one-shot: second poll should NOT fire
241
- const runtime2 = readUnitRuntimeRecord(tmpDir, "execute-task", "M001/S01/T01");
242
- assert.ok(runtime2, "runtime record should still exist");
243
- assert.equal(runtime2!.continueHereFired, true, "should be marked as fired");
244
-
245
- const shouldFireAgain = !runtime2!.continueHereFired
246
- && contextPercent >= threshold;
247
- assert.equal(shouldFireAgain, false, "must not fire again — one-shot guard");
248
-
249
- // Clean up
250
- clearUnitRuntimeRecord(tmpDir, "execute-task", "M001/S01/T01");
213
+ try {
214
+ // Simulate the monitor's one-shot logic:
215
+ // 1. Write initial runtime record (continueHereFired=false)
216
+ const startedAt = Date.now();
217
+ writeUnitRuntimeRecord(tmpDir, "execute-task", "M001/S01/T01", startedAt, {
218
+ phase: "dispatched",
219
+ wrapupWarningSent: false,
220
+ });
221
+
222
+ const budget = computeBudgets(128_000);
223
+ const threshold = budget.continueThresholdPercent;
224
+
225
+ // Simulate the monitor poll: context at 75% (above threshold)
226
+ const contextPercent = 75;
227
+ const runtime = readUnitRuntimeRecord(tmpDir, "execute-task", "M001/S01/T01");
228
+ assert.ok(runtime, "runtime record should exist");
229
+ assert.equal(runtime!.continueHereFired, false, "initially false");
230
+
231
+ // Check: should fire
232
+ const shouldFire = !runtime!.continueHereFired
233
+ && contextPercent >= threshold;
234
+ assert.ok(shouldFire, "should fire when context >= threshold and not yet fired");
235
+
236
+ // Mark as fired (what the monitor does)
237
+ writeUnitRuntimeRecord(tmpDir, "execute-task", "M001/S01/T01", startedAt, {
238
+ continueHereFired: true,
239
+ });
240
+
241
+ // Verify one-shot: second poll should NOT fire
242
+ const runtime2 = readUnitRuntimeRecord(tmpDir, "execute-task", "M001/S01/T01");
243
+ assert.ok(runtime2, "runtime record should still exist");
244
+ assert.equal(runtime2!.continueHereFired, true, "should be marked as fired");
245
+
246
+ const shouldFireAgain = !runtime2!.continueHereFired
247
+ && contextPercent >= threshold;
248
+ assert.equal(shouldFireAgain, false, "must not fire again — one-shot guard");
249
+
250
+ // Clean up
251
+ clearUnitRuntimeRecord(tmpDir, "execute-task", "M001/S01/T01");
252
+ } finally {
253
+ fs.rmSync(tmpDir, { recursive: true, force: true });
254
+ }
251
255
  });
252
256
 
253
257
  it("should not fire when context is below threshold", () => {
@@ -7,12 +7,11 @@
7
7
  * That failure confirms the test runs against real code. (T01 state)
8
8
  */
9
9
 
10
- import { describe, test } from "node:test";
11
- import assert from "node:assert/strict";
12
10
  import {
13
11
  type SliceAggregate,
14
12
  formatCostProjection,
15
13
  } from "../metrics.js";
14
+ import { createTestContext } from './test-helpers.ts';
16
15
 
17
16
  // ─── Test helpers ─────────────────────────────────────────────────────────────
18
17
 
@@ -26,95 +25,110 @@ function makeSliceAggregate(sliceId: string, cost: number): SliceAggregate {
26
25
  };
27
26
  }
28
27
 
28
+ const { assertEq, assertTrue, report } = createTestContext();
29
29
  // ─── formatCostProjection ─────────────────────────────────────────────────────
30
30
 
31
- describe("formatCostProjection", () => {
32
-
33
- test("zero completed slices → empty result", () => {
34
- const result = formatCostProjection([], 3);
35
- assert.strictEqual(result.length, 0, "zero slices → empty array");
36
- });
37
-
38
- test("one slice → suppressed (need ≥2 to project reliably)", () => {
39
- const result = formatCostProjection([makeSliceAggregate("M001/S01", 0.10)], 3);
40
- assert.strictEqual(result.length, 0, "one slice → suppressed (no projection shown)");
41
- });
42
-
43
- test("two slices → projection shown", () => {
44
- const slices = [
45
- makeSliceAggregate("M001/S01", 0.10),
46
- makeSliceAggregate("M001/S02", 0.10),
47
- ];
48
- const result = formatCostProjection(slices, 5);
49
- assert.ok(result.length > 0, "two slices → projection shown");
50
- });
51
-
52
- test("two-slice result contains $ (cost is formatted)", () => {
53
- const slices = [
54
- makeSliceAggregate("M001/S01", 0.10),
55
- makeSliceAggregate("M001/S02", 0.10),
56
- ];
57
- const result = formatCostProjection(slices, 5);
58
- assert.ok(result.length > 0 && result[0].includes("$"), "projection line contains \"$\"");
59
- });
60
-
61
- test("budget ceiling hit: total >= ceiling → line contains ceiling", () => {
62
- const slices = [
63
- makeSliceAggregate("M001/S01", 0.10),
64
- makeSliceAggregate("M001/S02", 0.10),
65
- ];
66
- const result = formatCostProjection(slices, 5, 0.05);
67
- const hasCeilingLine = result.some(
68
- line => line.toLowerCase().includes("ceiling")
69
- );
70
- assert.ok(hasCeilingLine, "ceiling warning appears when total ($0.20) >= ceiling ($0.05)");
71
- });
72
-
73
- test("budget ceiling not hit: total < ceiling → no ceiling line", () => {
74
- const slices = [
75
- makeSliceAggregate("M001/S01", 0.10),
76
- makeSliceAggregate("M001/S02", 0.10),
77
- ];
78
- const result = formatCostProjection(slices, 5, 100.00);
79
- const hasCeilingLine = result.some(
80
- line => line.toLowerCase().includes("ceiling")
81
- );
82
- assert.ok(!hasCeilingLine, "no ceiling warning when total ($0.20) < ceiling ($100.00)");
83
- });
84
-
85
- test("no ceiling arg → no ceiling line", () => {
86
- const slices = [
87
- makeSliceAggregate("M001/S01", 0.10),
88
- makeSliceAggregate("M001/S02", 0.10),
89
- ];
90
- const result = formatCostProjection(slices, 5);
91
- const hasCeilingLine = result.some(
92
- line => line.toLowerCase().includes("ceiling")
93
- );
94
- assert.ok(!hasCeilingLine, "no ceiling warning when no ceiling is set");
95
- });
96
-
97
- test("rounding: avg $0.10 × 5 remaining = $0.50", () => {
98
- const slices = [
99
- makeSliceAggregate("M001/S01", 0.10),
100
- makeSliceAggregate("M001/S02", 0.10),
101
- ];
102
- const result = formatCostProjection(slices, 5);
103
- const hasRoundedCost = result.some(line => line.includes("$0.50"));
104
- assert.ok(hasRoundedCost, "projected cost $0.50 (avg $0.10 × 5 remaining) appears in output");
105
- });
106
-
107
- test("bare milestone entries excluded from average", () => {
108
- const slices = [
109
- makeSliceAggregate("M001", 5.00), // bare milestone — must be excluded
110
- makeSliceAggregate("M001/S01", 0.10),
111
- makeSliceAggregate("M001/S02", 0.10),
112
- ];
113
- const result = formatCostProjection(slices, 3);
114
- const hasCorrectProjection = result.some(line => line.includes("$0.30"));
115
- assert.ok(
116
- hasCorrectProjection,
117
- "bare milestone entry excluded from avg: projection shows $0.30 (avg $0.10 × 3), not $1.83 (including $5.00 entry)"
118
- );
119
- });
120
- });
31
+ console.log("\n=== formatCostProjection ===");
32
+
33
+ // 1. Zero completed slices → empty result
34
+ {
35
+ const result = formatCostProjection([], 3);
36
+ assertEq(result.length, 0, "zero slices → empty array");
37
+ }
38
+
39
+ // 2. One slice → suppressed (need ≥2 to project reliably)
40
+ {
41
+ const result = formatCostProjection([makeSliceAggregate("M001/S01", 0.10)], 3);
42
+ assertEq(result.length, 0, "one slice → suppressed (no projection shown)");
43
+ }
44
+
45
+ // 3. Two slices → projection shown (result.length > 0)
46
+ {
47
+ const slices = [
48
+ makeSliceAggregate("M001/S01", 0.10),
49
+ makeSliceAggregate("M001/S02", 0.10),
50
+ ];
51
+ const result = formatCostProjection(slices, 5);
52
+ assertTrue(result.length > 0, "two slices projection shown");
53
+ }
54
+
55
+ // 4. Two-slice result: result[0] contains "$" (cost is formatted)
56
+ {
57
+ const slices = [
58
+ makeSliceAggregate("M001/S01", 0.10),
59
+ makeSliceAggregate("M001/S02", 0.10),
60
+ ];
61
+ const result = formatCostProjection(slices, 5);
62
+ assertTrue(result.length > 0 && result[0].includes("$"), "projection line contains \"$\"");
63
+ }
64
+
65
+ // 5. Budget ceiling hit: total $0.20 >= ceiling $0.05 → line contains "ceiling"
66
+ {
67
+ const slices = [
68
+ makeSliceAggregate("M001/S01", 0.10),
69
+ makeSliceAggregate("M001/S02", 0.10),
70
+ ];
71
+ const result = formatCostProjection(slices, 5, 0.05);
72
+ const hasCeilingLine = result.some(
73
+ line => line.toLowerCase().includes("ceiling")
74
+ );
75
+ assertTrue(hasCeilingLine, "ceiling warning appears when total ($0.20) >= ceiling ($0.05)");
76
+ }
77
+
78
+ // 6. Budget ceiling not hit: total $0.20 < ceiling $100.00 → no ceiling line
79
+ {
80
+ const slices = [
81
+ makeSliceAggregate("M001/S01", 0.10),
82
+ makeSliceAggregate("M001/S02", 0.10),
83
+ ];
84
+ const result = formatCostProjection(slices, 5, 100.00);
85
+ const hasCeilingLine = result.some(
86
+ line => line.toLowerCase().includes("ceiling")
87
+ );
88
+ assertTrue(!hasCeilingLine, "no ceiling warning when total ($0.20) < ceiling ($100.00)");
89
+ }
90
+
91
+ // 7. No ceiling arg → no ceiling line
92
+ {
93
+ const slices = [
94
+ makeSliceAggregate("M001/S01", 0.10),
95
+ makeSliceAggregate("M001/S02", 0.10),
96
+ ];
97
+ const result = formatCostProjection(slices, 5);
98
+ const hasCeilingLine = result.some(
99
+ line => line.toLowerCase().includes("ceiling")
100
+ );
101
+ assertTrue(!hasCeilingLine, "no ceiling warning when no ceiling is set");
102
+ }
103
+
104
+ // 8. Rounding: avg $0.10 × 5 remaining = $0.50 → result[0] contains "$0.50"
105
+ {
106
+ const slices = [
107
+ makeSliceAggregate("M001/S01", 0.10),
108
+ makeSliceAggregate("M001/S02", 0.10),
109
+ ];
110
+ const result = formatCostProjection(slices, 5);
111
+ const hasRoundedCost = result.some(line => line.includes("$0.50"));
112
+ assertTrue(hasRoundedCost, "projected cost $0.50 (avg $0.10 × 5 remaining) appears in output");
113
+ }
114
+
115
+ // 9. Bare milestone entries excluded from average:
116
+ // makeSliceAggregate('M001', 5.00) has no "/" in sliceId → excluded from avg calc.
117
+ // Only M001/S01 ($0.10) and M001/S02 ($0.10) count → avg $0.10 × 3 remaining = $0.30
118
+ {
119
+ const slices = [
120
+ makeSliceAggregate("M001", 5.00), // bare milestone — must be excluded
121
+ makeSliceAggregate("M001/S01", 0.10),
122
+ makeSliceAggregate("M001/S02", 0.10),
123
+ ];
124
+ const result = formatCostProjection(slices, 3);
125
+ const hasCorrectProjection = result.some(line => line.includes("$0.30"));
126
+ assertTrue(
127
+ hasCorrectProjection,
128
+ "bare milestone entry excluded from avg: projection shows $0.30 (avg $0.10 × 3), not $1.83 (including $5.00 entry)"
129
+ );
130
+ }
131
+
132
+ // ─── Summary ──────────────────────────────────────────────────────────────────
133
+
134
+ report();
@@ -26,45 +26,53 @@ function cleanup(base: string): void {
26
26
 
27
27
  // ─── writeLock / readCrashLock ────────────────────────────────────────────
28
28
 
29
- test("writeLock creates lock file and readCrashLock reads it", (t) => {
29
+ test("writeLock creates lock file and readCrashLock reads it", () => {
30
30
  const base = makeTmpBase();
31
- t.after(() => cleanup(base));
32
-
33
- writeLock(base, "execute-task", "M001/S01/T01", 3, "/tmp/session.jsonl");
34
- const lock = readCrashLock(base);
35
- assert.ok(lock, "lock should exist");
36
- assert.equal(lock!.unitType, "execute-task");
37
- assert.equal(lock!.unitId, "M001/S01/T01");
38
- assert.equal(lock!.completedUnits, 3);
39
- assert.equal(lock!.sessionFile, "/tmp/session.jsonl");
40
- assert.equal(lock!.pid, process.pid);
31
+ try {
32
+ writeLock(base, "execute-task", "M001/S01/T01", 3, "/tmp/session.jsonl");
33
+ const lock = readCrashLock(base);
34
+ assert.ok(lock, "lock should exist");
35
+ assert.equal(lock!.unitType, "execute-task");
36
+ assert.equal(lock!.unitId, "M001/S01/T01");
37
+ assert.equal(lock!.completedUnits, 3);
38
+ assert.equal(lock!.sessionFile, "/tmp/session.jsonl");
39
+ assert.equal(lock!.pid, process.pid);
40
+ } finally {
41
+ cleanup(base);
42
+ }
41
43
  });
42
44
 
43
- test("readCrashLock returns null when no lock exists", (t) => {
45
+ test("readCrashLock returns null when no lock exists", () => {
44
46
  const base = makeTmpBase();
45
- t.after(() => cleanup(base));
46
-
47
- const lock = readCrashLock(base);
48
- assert.equal(lock, null);
47
+ try {
48
+ const lock = readCrashLock(base);
49
+ assert.equal(lock, null);
50
+ } finally {
51
+ cleanup(base);
52
+ }
49
53
  });
50
54
 
51
55
  // ─── clearLock ────────────────────────────────────────────────────────────
52
56
 
53
- test("clearLock removes existing lock file", (t) => {
57
+ test("clearLock removes existing lock file", () => {
54
58
  const base = makeTmpBase();
55
- t.after(() => cleanup(base));
56
-
57
- writeLock(base, "plan-slice", "M001/S01", 0);
58
- assert.ok(readCrashLock(base), "lock should exist before clear");
59
- clearLock(base);
60
- assert.equal(readCrashLock(base), null, "lock should be gone after clear");
59
+ try {
60
+ writeLock(base, "plan-slice", "M001/S01", 0);
61
+ assert.ok(readCrashLock(base), "lock should exist before clear");
62
+ clearLock(base);
63
+ assert.equal(readCrashLock(base), null, "lock should be gone after clear");
64
+ } finally {
65
+ cleanup(base);
66
+ }
61
67
  });
62
68
 
63
- test("clearLock is safe when no lock exists", (t) => {
69
+ test("clearLock is safe when no lock exists", () => {
64
70
  const base = makeTmpBase();
65
- t.after(() => cleanup(base));
66
-
67
- assert.doesNotThrow(() => clearLock(base));
71
+ try {
72
+ assert.doesNotThrow(() => clearLock(base));
73
+ } finally {
74
+ cleanup(base);
75
+ }
68
76
  });
69
77
 
70
78
  // ─── isLockProcessAlive ──────────────────────────────────────────────────