gsd-pi 2.44.0-dev.62b5d6c → 2.44.0-dev.73f2fd5

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 (326) hide show
  1. package/README.md +30 -12
  2. package/dist/resources/extensions/gsd/auto/infra-errors.js +3 -0
  3. package/dist/resources/extensions/gsd/auto/phases.js +36 -36
  4. package/dist/resources/extensions/gsd/auto-prompts.js +24 -1
  5. package/dist/resources/extensions/gsd/auto-start.js +10 -0
  6. package/dist/resources/extensions/gsd/auto-timers.js +57 -3
  7. package/dist/resources/extensions/gsd/auto-worktree-sync.js +4 -0
  8. package/dist/resources/extensions/gsd/auto-worktree.js +9 -6
  9. package/dist/resources/extensions/gsd/auto.js +30 -3
  10. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +156 -0
  11. package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -12
  12. package/dist/resources/extensions/gsd/commands/catalog.js +6 -1
  13. package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -0
  14. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  15. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
  16. package/dist/resources/extensions/gsd/commands-mcp-status.js +187 -0
  17. package/dist/resources/extensions/gsd/db-writer.js +34 -16
  18. package/dist/resources/extensions/gsd/doctor.js +8 -0
  19. package/dist/resources/extensions/gsd/git-service.js +8 -3
  20. package/dist/resources/extensions/gsd/gsd-db.js +12 -1
  21. package/dist/resources/extensions/gsd/markdown-renderer.js +1 -1
  22. package/dist/resources/extensions/gsd/preferences.js +9 -1
  23. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
  24. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  25. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  26. package/dist/resources/extensions/gsd/prompts/replan-slice.md +3 -14
  27. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
  28. package/dist/resources/extensions/gsd/provider-error-pause.js +7 -0
  29. package/dist/resources/extensions/gsd/state.js +19 -2
  30. package/dist/resources/extensions/gsd/tools/plan-slice.js +1 -0
  31. package/dist/resources/extensions/gsd/tools/plan-task.js +1 -0
  32. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -0
  33. package/dist/resources/extensions/gsd/tools/validate-milestone.js +88 -0
  34. package/dist/resources/extensions/gsd/worktree-resolver.js +6 -0
  35. package/dist/resources/extensions/mcp-client/index.js +14 -0
  36. package/dist/web/standalone/.next/BUILD_ID +1 -1
  37. package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
  38. package/dist/web/standalone/.next/build-manifest.json +2 -2
  39. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  40. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  41. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  43. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  44. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  45. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  46. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  47. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  48. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  49. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  52. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  55. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  56. package/dist/web/standalone/.next/server/app/index.html +1 -1
  57. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  58. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app-paths-manifest.json +17 -17
  64. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  65. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  66. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  67. package/package.json +1 -1
  68. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +3 -1
  69. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  70. package/packages/pi-coding-agent/dist/core/auth-storage.js +15 -1
  71. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  72. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
  73. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  74. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
  75. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  76. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
  77. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  78. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts +15 -0
  79. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts.map +1 -0
  80. package/packages/pi-coding-agent/dist/core/local-model-check.js +41 -0
  81. package/packages/pi-coding-agent/dist/core/local-model-check.js.map +1 -0
  82. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +11 -0
  83. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  84. package/packages/pi-coding-agent/dist/core/model-registry.js +20 -1
  85. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  86. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
  87. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  88. package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
  89. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  90. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  91. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  92. package/packages/pi-coding-agent/dist/core/settings-manager.js +6 -0
  93. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  94. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
  95. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  96. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  97. package/packages/pi-coding-agent/dist/main.js +17 -0
  98. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  99. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts +2 -0
  100. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts.map +1 -0
  101. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js +32 -0
  102. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js.map +1 -0
  103. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +3 -1
  104. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  105. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +8 -1
  106. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  107. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  108. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  109. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +12 -0
  110. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  111. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts +15 -0
  112. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts.map +1 -0
  113. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js +40 -0
  114. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js.map +1 -0
  115. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  116. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +4 -1
  117. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  118. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +5 -2
  119. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  120. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +13 -2
  121. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  122. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  123. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +17 -8
  124. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  125. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  126. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +7 -3
  127. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  128. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
  129. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  130. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  131. package/packages/pi-coding-agent/src/core/auth-storage.ts +15 -1
  132. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  133. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
  134. package/packages/pi-coding-agent/src/core/local-model-check.ts +45 -0
  135. package/packages/pi-coding-agent/src/core/model-registry.ts +21 -1
  136. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
  137. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  138. package/packages/pi-coding-agent/src/core/settings-manager.ts +9 -0
  139. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  140. package/packages/pi-coding-agent/src/main.ts +19 -0
  141. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/timestamp.test.ts +38 -0
  142. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +10 -0
  143. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  144. package/packages/pi-coding-agent/src/modes/interactive/components/timestamp.ts +48 -0
  145. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +3 -1
  146. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +18 -3
  147. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +16 -7
  148. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +8 -1
  149. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  150. package/src/resources/extensions/gsd/auto/infra-errors.ts +3 -0
  151. package/src/resources/extensions/gsd/auto/phases.ts +45 -48
  152. package/src/resources/extensions/gsd/auto-prompts.ts +24 -1
  153. package/src/resources/extensions/gsd/auto-start.ts +14 -0
  154. package/src/resources/extensions/gsd/auto-timers.ts +64 -3
  155. package/src/resources/extensions/gsd/auto-worktree-sync.ts +5 -0
  156. package/src/resources/extensions/gsd/auto-worktree.ts +9 -6
  157. package/src/resources/extensions/gsd/auto.ts +37 -3
  158. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +148 -0
  159. package/src/resources/extensions/gsd/bootstrap/system-context.ts +48 -11
  160. package/src/resources/extensions/gsd/commands/catalog.ts +6 -1
  161. package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -0
  162. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  163. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
  164. package/src/resources/extensions/gsd/commands-mcp-status.ts +247 -0
  165. package/src/resources/extensions/gsd/db-writer.ts +39 -17
  166. package/src/resources/extensions/gsd/doctor.ts +7 -1
  167. package/src/resources/extensions/gsd/git-service.ts +6 -2
  168. package/src/resources/extensions/gsd/gsd-db.ts +16 -1
  169. package/src/resources/extensions/gsd/markdown-renderer.ts +1 -1
  170. package/src/resources/extensions/gsd/preferences.ts +11 -1
  171. package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
  172. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  173. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  174. package/src/resources/extensions/gsd/prompts/replan-slice.md +3 -14
  175. package/src/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
  176. package/src/resources/extensions/gsd/provider-error-pause.ts +9 -0
  177. package/src/resources/extensions/gsd/state.ts +19 -1
  178. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  179. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
  180. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
  181. package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +88 -0
  182. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
  183. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
  184. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
  185. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
  186. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
  187. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
  188. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
  189. package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
  190. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
  191. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
  192. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  193. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  194. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +38 -59
  195. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +228 -263
  196. package/src/resources/extensions/gsd/tests/complete-task.test.ts +250 -302
  197. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +114 -0
  198. package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
  199. package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
  200. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
  201. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
  202. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
  203. package/src/resources/extensions/gsd/tests/db-writer.test.ts +465 -416
  204. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
  205. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
  206. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +210 -181
  207. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
  208. package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
  209. package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
  210. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
  211. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
  212. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
  213. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
  214. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
  215. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
  216. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
  217. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
  218. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
  219. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
  220. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
  221. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
  222. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
  223. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
  224. package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
  225. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
  226. package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +120 -0
  227. package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
  228. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
  229. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
  230. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
  231. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
  232. package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
  233. package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
  234. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
  235. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
  236. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
  237. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
  238. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
  239. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
  240. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  241. package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
  242. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -102
  243. package/src/resources/extensions/gsd/tests/infra-error.test.ts +20 -2
  244. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
  245. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
  246. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
  247. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
  248. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
  249. package/src/resources/extensions/gsd/tests/knowledge.test.ts +89 -0
  250. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
  251. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +103 -0
  252. package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
  253. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
  254. package/src/resources/extensions/gsd/tests/memory-store.test.ts +80 -93
  255. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +66 -0
  256. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
  257. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
  258. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
  259. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
  260. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
  261. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
  262. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
  263. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
  264. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
  265. package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
  266. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
  267. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
  268. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
  269. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
  270. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
  271. package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
  272. package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
  273. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
  274. package/src/resources/extensions/gsd/tests/preferences.test.ts +27 -0
  275. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +11 -7
  276. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  277. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
  278. package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
  279. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
  280. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
  281. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
  282. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
  283. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
  284. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
  285. package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
  286. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
  287. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
  288. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
  289. package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
  290. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
  291. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
  292. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
  293. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
  294. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
  295. package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +67 -0
  296. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
  297. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +49 -0
  298. package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
  299. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
  300. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +10 -11
  301. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
  302. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
  303. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
  304. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
  305. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
  306. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
  307. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
  308. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
  309. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
  310. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
  311. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
  312. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
  313. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
  314. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
  315. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
  316. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
  317. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
  318. package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
  319. package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -0
  320. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -0
  321. package/src/resources/extensions/gsd/tools/replan-slice.ts +3 -0
  322. package/src/resources/extensions/gsd/tools/validate-milestone.ts +127 -0
  323. package/src/resources/extensions/gsd/worktree-resolver.ts +7 -0
  324. package/src/resources/extensions/mcp-client/index.ts +20 -0
  325. /package/dist/web/standalone/.next/static/{fOnWQBjWXMKUs4bqTg530 → kxxAA66bah_yhPYqLBHE2}/_buildManifest.js +0 -0
  326. /package/dist/web/standalone/.next/static/{fOnWQBjWXMKUs4bqTg530 → kxxAA66bah_yhPYqLBHE2}/_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 () => {
165
+ it("AutoUnitRuntimeRecord includes continueHereFired with default false", async (t) => {
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,87 +171,83 @@ 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
- 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
- }
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");
202
200
  });
203
201
  });
204
202
 
205
203
  describe("context-pressure monitor integration", () => {
206
- it("should fire wrap-up when context >= threshold and mark continueHereFired", async () => {
204
+ it("should fire wrap-up when context >= threshold and mark continueHereFired", async (t) => {
207
205
  const { writeUnitRuntimeRecord, readUnitRuntimeRecord, clearUnitRuntimeRecord } = await import("../unit-runtime.js");
208
206
  const fs = await import("node:fs");
209
207
  const path = await import("node:path");
210
208
  const os = await import("node:os");
211
209
 
212
210
  const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "continue-here-monitor-"));
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
- }
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");
255
251
  });
256
252
 
257
253
  it("should not fire when context is below threshold", () => {
@@ -7,11 +7,12 @@
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";
10
12
  import {
11
13
  type SliceAggregate,
12
14
  formatCostProjection,
13
15
  } from "../metrics.js";
14
- import { createTestContext } from './test-helpers.ts';
15
16
 
16
17
  // ─── Test helpers ─────────────────────────────────────────────────────────────
17
18
 
@@ -25,110 +26,95 @@ function makeSliceAggregate(sliceId: string, cost: number): SliceAggregate {
25
26
  };
26
27
  }
27
28
 
28
- const { assertEq, assertTrue, report } = createTestContext();
29
29
  // ─── formatCostProjection ─────────────────────────────────────────────────────
30
30
 
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();
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
+ });
@@ -26,53 +26,45 @@ function cleanup(base: string): void {
26
26
 
27
27
  // ─── writeLock / readCrashLock ────────────────────────────────────────────
28
28
 
29
- test("writeLock creates lock file and readCrashLock reads it", () => {
29
+ test("writeLock creates lock file and readCrashLock reads it", (t) => {
30
30
  const base = makeTmpBase();
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
- }
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);
43
41
  });
44
42
 
45
- test("readCrashLock returns null when no lock exists", () => {
43
+ test("readCrashLock returns null when no lock exists", (t) => {
46
44
  const base = makeTmpBase();
47
- try {
48
- const lock = readCrashLock(base);
49
- assert.equal(lock, null);
50
- } finally {
51
- cleanup(base);
52
- }
45
+ t.after(() => cleanup(base));
46
+
47
+ const lock = readCrashLock(base);
48
+ assert.equal(lock, null);
53
49
  });
54
50
 
55
51
  // ─── clearLock ────────────────────────────────────────────────────────────
56
52
 
57
- test("clearLock removes existing lock file", () => {
53
+ test("clearLock removes existing lock file", (t) => {
58
54
  const base = makeTmpBase();
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
- }
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");
67
61
  });
68
62
 
69
- test("clearLock is safe when no lock exists", () => {
63
+ test("clearLock is safe when no lock exists", (t) => {
70
64
  const base = makeTmpBase();
71
- try {
72
- assert.doesNotThrow(() => clearLock(base));
73
- } finally {
74
- cleanup(base);
75
- }
65
+ t.after(() => cleanup(base));
66
+
67
+ assert.doesNotThrow(() => clearLock(base));
76
68
  });
77
69
 
78
70
  // ─── isLockProcessAlive ──────────────────────────────────────────────────