gsd-pi 2.44.0-dev.62b5d6c → 2.44.0-dev.a5271fc

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 (198) hide show
  1. package/README.md +30 -12
  2. package/dist/resources/extensions/gsd/auto-start.js +10 -0
  3. package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -12
  4. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
  5. package/dist/resources/extensions/gsd/preferences.js +9 -1
  6. package/dist/resources/extensions/gsd/state.js +19 -2
  7. package/dist/web/standalone/.next/BUILD_ID +1 -1
  8. package/dist/web/standalone/.next/app-path-routes-manifest.json +19 -19
  9. package/dist/web/standalone/.next/build-manifest.json +2 -2
  10. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  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.html +1 -1
  20. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  21. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  22. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  23. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  24. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  25. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/index.html +1 -1
  28. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  30. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  31. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  32. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  33. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  34. package/dist/web/standalone/.next/server/app-paths-manifest.json +19 -19
  35. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  36. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  37. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  38. package/package.json +1 -1
  39. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
  40. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  41. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
  42. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  43. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
  44. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  45. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
  46. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  47. package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
  48. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  49. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
  50. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  51. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
  52. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  53. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  54. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  55. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
  56. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
  57. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  58. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  59. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  60. package/src/resources/extensions/gsd/auto-start.ts +14 -0
  61. package/src/resources/extensions/gsd/bootstrap/system-context.ts +48 -11
  62. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
  63. package/src/resources/extensions/gsd/preferences.ts +11 -1
  64. package/src/resources/extensions/gsd/state.ts +19 -1
  65. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  66. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
  67. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
  68. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
  69. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
  70. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
  71. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
  72. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
  73. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
  74. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
  75. package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
  76. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
  77. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
  78. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  79. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  80. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +38 -59
  81. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +228 -263
  82. package/src/resources/extensions/gsd/tests/complete-task.test.ts +250 -302
  83. package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
  84. package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
  85. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
  86. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
  87. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
  88. package/src/resources/extensions/gsd/tests/db-writer.test.ts +390 -420
  89. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
  90. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
  91. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +183 -181
  92. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
  93. package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
  94. package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
  95. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
  96. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
  97. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
  98. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
  99. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
  100. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
  101. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
  102. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
  103. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
  104. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
  105. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
  106. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
  107. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
  108. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
  109. package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
  110. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
  111. package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
  112. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
  113. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
  114. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
  115. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
  116. package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
  117. package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
  118. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
  119. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
  120. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
  121. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
  122. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
  123. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
  124. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  125. package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
  126. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -102
  127. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
  128. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
  129. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
  130. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
  131. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
  132. package/src/resources/extensions/gsd/tests/knowledge.test.ts +89 -0
  133. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
  134. package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
  135. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
  136. package/src/resources/extensions/gsd/tests/memory-store.test.ts +80 -93
  137. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
  138. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
  139. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
  140. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
  141. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
  142. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
  143. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
  144. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
  145. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
  146. package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
  147. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
  148. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
  149. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
  150. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
  151. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
  152. package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
  153. package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
  154. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
  155. package/src/resources/extensions/gsd/tests/preferences.test.ts +27 -0
  156. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  157. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
  158. package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
  159. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
  160. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
  161. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
  162. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
  163. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
  164. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
  165. package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
  166. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
  167. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
  168. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
  169. package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
  170. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
  171. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
  172. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
  173. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
  174. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
  175. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
  176. package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
  177. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
  178. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +9 -11
  179. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
  180. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
  181. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
  182. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
  183. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
  184. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
  185. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
  186. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
  187. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
  188. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
  189. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
  190. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
  191. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
  192. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
  193. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
  194. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
  195. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
  196. package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
  197. /package/dist/web/standalone/.next/static/{fOnWQBjWXMKUs4bqTg530 → JyimLR2pZuvKEzv26gI3w}/_buildManifest.js +0 -0
  198. /package/dist/web/standalone/.next/static/{fOnWQBjWXMKUs4bqTg530 → JyimLR2pZuvKEzv26gI3w}/_ssgManifest.js +0 -0
@@ -53,43 +53,37 @@ function cleanup(dir: string): void {
53
53
 
54
54
  // ─── hasGitTrackedGsdFiles ───────────────────────────────────────────
55
55
 
56
- test("hasGitTrackedGsdFiles returns false when .gsd/ does not exist", () => {
56
+ test("hasGitTrackedGsdFiles returns false when .gsd/ does not exist", (t) => {
57
57
  const dir = makeTempRepo();
58
- try {
59
- assert.equal(hasGitTrackedGsdFiles(dir), false);
60
- } finally {
61
- cleanup(dir);
62
- }
58
+ t.after(() => { cleanup(dir); });
59
+
60
+ assert.equal(hasGitTrackedGsdFiles(dir), false);
63
61
  });
64
62
 
65
- test("hasGitTrackedGsdFiles returns true when .gsd/ has tracked files", () => {
63
+ test("hasGitTrackedGsdFiles returns true when .gsd/ has tracked files", (t) => {
66
64
  const dir = makeTempRepo();
67
- try {
68
- mkdirSync(join(dir, ".gsd", "milestones"), { recursive: true });
69
- writeFileSync(join(dir, ".gsd", "PROJECT.md"), "# Test Project\n");
70
- git(dir, "add", ".gsd/PROJECT.md");
71
- git(dir, "commit", "-m", "add gsd");
72
- assert.equal(hasGitTrackedGsdFiles(dir), true);
73
- } finally {
74
- cleanup(dir);
75
- }
65
+ t.after(() => { cleanup(dir); });
66
+
67
+ mkdirSync(join(dir, ".gsd", "milestones"), { recursive: true });
68
+ writeFileSync(join(dir, ".gsd", "PROJECT.md"), "# Test Project\n");
69
+ git(dir, "add", ".gsd/PROJECT.md");
70
+ git(dir, "commit", "-m", "add gsd");
71
+ assert.equal(hasGitTrackedGsdFiles(dir), true);
76
72
  });
77
73
 
78
- test("hasGitTrackedGsdFiles returns false when .gsd/ exists but is untracked", () => {
74
+ test("hasGitTrackedGsdFiles returns false when .gsd/ exists but is untracked", (t) => {
79
75
  const dir = makeTempRepo();
80
- try {
81
- mkdirSync(join(dir, ".gsd"), { recursive: true });
82
- writeFileSync(join(dir, ".gsd", "STATE.md"), "state\n");
83
- // Not git-added — should return false
84
- assert.equal(hasGitTrackedGsdFiles(dir), false);
85
- } finally {
86
- cleanup(dir);
87
- }
76
+ t.after(() => { cleanup(dir); });
77
+
78
+ mkdirSync(join(dir, ".gsd"), { recursive: true });
79
+ writeFileSync(join(dir, ".gsd", "STATE.md"), "state\n");
80
+ // Not git-added — should return false
81
+ assert.equal(hasGitTrackedGsdFiles(dir), false);
88
82
  });
89
83
 
90
84
  // ─── ensureGitignore — tracked .gsd/ protection ─────────────────────
91
85
 
92
- test("ensureGitignore does NOT add .gsd when .gsd/ has tracked files (#1364)", () => {
86
+ test("ensureGitignore does NOT add .gsd when .gsd/ has tracked files (#1364)", (t) => {
93
87
  const dir = makeTempRepo();
94
88
  try {
95
89
  // Set up .gsd/ with tracked files
@@ -118,7 +112,7 @@ test("ensureGitignore does NOT add .gsd when .gsd/ has tracked files (#1364)", (
118
112
  }
119
113
  });
120
114
 
121
- test("ensureGitignore adds .gsd when .gsd/ has NO tracked files", () => {
115
+ test("ensureGitignore adds .gsd when .gsd/ has NO tracked files", (t) => {
122
116
  const dir = makeTempRepo();
123
117
  try {
124
118
  // Run ensureGitignore (no .gsd/ at all)
@@ -136,20 +130,18 @@ test("ensureGitignore adds .gsd when .gsd/ has NO tracked files", () => {
136
130
  }
137
131
  });
138
132
 
139
- test("ensureGitignore respects manageGitignore: false", () => {
133
+ test("ensureGitignore respects manageGitignore: false", (t) => {
140
134
  const dir = makeTempRepo();
141
- try {
142
- const result = ensureGitignore(dir, { manageGitignore: false });
143
- assert.equal(result, false);
144
- assert.ok(!existsSync(join(dir, ".gitignore")), "Should not create .gitignore");
145
- } finally {
146
- cleanup(dir);
147
- }
135
+ t.after(() => { cleanup(dir); });
136
+
137
+ const result = ensureGitignore(dir, { manageGitignore: false });
138
+ assert.equal(result, false);
139
+ assert.ok(!existsSync(join(dir, ".gitignore")), "Should not create .gitignore");
148
140
  });
149
141
 
150
142
  // ─── ensureGitignore — verify no tracked files become invisible ─────
151
143
 
152
- test("ensureGitignore with tracked .gsd/ does not cause git to see files as deleted", () => {
144
+ test("ensureGitignore with tracked .gsd/ does not cause git to see files as deleted", (t) => {
153
145
  const dir = makeTempRepo();
154
146
  try {
155
147
  // Create tracked .gsd/ files
@@ -183,7 +175,7 @@ test("ensureGitignore with tracked .gsd/ does not cause git to see files as dele
183
175
  }
184
176
  });
185
177
 
186
- test("hasGitTrackedGsdFiles returns true (fail-safe) when git is not available", () => {
178
+ test("hasGitTrackedGsdFiles returns true (fail-safe) when git is not available", (t) => {
187
179
  const dir = makeTempRepo();
188
180
  try {
189
181
  // Create and track .gsd/ files
@@ -207,7 +199,7 @@ test("hasGitTrackedGsdFiles returns true (fail-safe) when git is not available",
207
199
 
208
200
  // ─── migrateToExternalState — tracked .gsd/ protection ──────────────
209
201
 
210
- test("migrateToExternalState aborts when .gsd/ has tracked files (#1364)", () => {
202
+ test("migrateToExternalState aborts when .gsd/ has tracked files (#1364)", (t) => {
211
203
  const dir = makeTempRepo();
212
204
  try {
213
205
  // Create tracked .gsd/ files
@@ -235,7 +227,7 @@ test("migrateToExternalState aborts when .gsd/ has tracked files (#1364)", () =>
235
227
  }
236
228
  });
237
229
 
238
- test("migrateToExternalState cleans git index so tracked files don't show as deleted (#1364 path 2)", () => {
230
+ test("migrateToExternalState cleans git index so tracked files don't show as deleted (#1364 path 2)", (t) => {
239
231
  const dir = makeTempRepo();
240
232
  try {
241
233
  // Track .gsd/ files, then untrack them so migration proceeds
@@ -56,7 +56,7 @@ function makeStep(overrides: Partial<GraphStep> & { id: string }): GraphStep {
56
56
  // ─── writeGraph + readGraph round-trip ───────────────────────────────────
57
57
 
58
58
  describe("writeGraph + readGraph round-trip", () => {
59
- it("preserves all fields including parentStepId and dependsOn", () => {
59
+ it("preserves all fields including parentStepId and dependsOn", (t) => {
60
60
  const dir = makeTmpDir();
61
61
  try {
62
62
  const graph = makeGraph([
@@ -89,7 +89,7 @@ describe("writeGraph + readGraph round-trip", () => {
89
89
  }
90
90
  });
91
91
 
92
- it("preserves startedAt and finishedAt fields", () => {
92
+ it("preserves startedAt and finishedAt fields", (t) => {
93
93
  const dir = makeTmpDir();
94
94
  try {
95
95
  const graph = makeGraph([
@@ -110,7 +110,7 @@ describe("writeGraph + readGraph round-trip", () => {
110
110
  }
111
111
  });
112
112
 
113
- it("creates directory if it does not exist", () => {
113
+ it("creates directory if it does not exist", (t) => {
114
114
  const base = makeTmpDir();
115
115
  const nested = join(base, "sub", "dir");
116
116
  try {
@@ -129,59 +129,53 @@ describe("writeGraph + readGraph round-trip", () => {
129
129
  // ─── readGraph error paths ───────────────────────────────────────────────
130
130
 
131
131
  describe("readGraph error paths", () => {
132
- it("throws with descriptive error when file is missing", () => {
132
+ it("throws with descriptive error when file is missing", (t) => {
133
133
  const dir = makeTmpDir();
134
- try {
135
- assert.throws(
136
- () => readGraph(dir),
137
- (err: Error) => {
138
- assert.ok(err.message.includes("GRAPH.yaml not found"));
139
- assert.ok(err.message.includes(dir));
140
- return true;
141
- },
142
- );
143
- } finally {
144
- cleanupDir(dir);
145
- }
134
+ t.after(() => { cleanupDir(dir); });
135
+
136
+ assert.throws(
137
+ () => readGraph(dir),
138
+ (err: Error) => {
139
+ assert.ok(err.message.includes("GRAPH.yaml not found"));
140
+ assert.ok(err.message.includes(dir));
141
+ return true;
142
+ },
143
+ );
146
144
  });
147
145
 
148
- it("throws with descriptive error when YAML is malformed (missing steps)", () => {
146
+ it("throws with descriptive error when YAML is malformed (missing steps)", (t) => {
149
147
  const dir = makeTmpDir();
150
- try {
151
- writeFileSync(join(dir, "GRAPH.yaml"), "metadata:\n name: bad\n", "utf-8");
152
- assert.throws(
153
- () => readGraph(dir),
154
- (err: Error) => {
155
- assert.ok(err.message.includes("missing or invalid 'steps' array"));
156
- return true;
157
- },
158
- );
159
- } finally {
160
- cleanupDir(dir);
161
- }
148
+ t.after(() => { cleanupDir(dir); });
149
+
150
+ writeFileSync(join(dir, "GRAPH.yaml"), "metadata:\n name: bad\n", "utf-8");
151
+ assert.throws(
152
+ () => readGraph(dir),
153
+ (err: Error) => {
154
+ assert.ok(err.message.includes("missing or invalid 'steps' array"));
155
+ return true;
156
+ },
157
+ );
162
158
  });
163
159
 
164
- it("throws when steps is not an array", () => {
160
+ it("throws when steps is not an array", (t) => {
165
161
  const dir = makeTmpDir();
166
- try {
167
- writeFileSync(join(dir, "GRAPH.yaml"), "steps: not-an-array\nmetadata:\n name: bad\n", "utf-8");
168
- assert.throws(
169
- () => readGraph(dir),
170
- (err: Error) => {
171
- assert.ok(err.message.includes("missing or invalid 'steps' array"));
172
- return true;
173
- },
174
- );
175
- } finally {
176
- cleanupDir(dir);
177
- }
162
+ t.after(() => { cleanupDir(dir); });
163
+
164
+ writeFileSync(join(dir, "GRAPH.yaml"), "steps: not-an-array\nmetadata:\n name: bad\n", "utf-8");
165
+ assert.throws(
166
+ () => readGraph(dir),
167
+ (err: Error) => {
168
+ assert.ok(err.message.includes("missing or invalid 'steps' array"));
169
+ return true;
170
+ },
171
+ );
178
172
  });
179
173
  });
180
174
 
181
175
  // ─── getNextPendingStep ──────────────────────────────────────────────────
182
176
 
183
177
  describe("getNextPendingStep", () => {
184
- it("returns first step with all deps complete", () => {
178
+ it("returns first step with all deps complete", (t) => {
185
179
  const graph = makeGraph([
186
180
  makeStep({ id: "a", status: "complete" }),
187
181
  makeStep({ id: "b", dependsOn: ["a"] }),
@@ -192,7 +186,7 @@ describe("getNextPendingStep", () => {
192
186
  assert.equal(next?.id, "b");
193
187
  });
194
188
 
195
- it("skips steps with incomplete deps", () => {
189
+ it("skips steps with incomplete deps", (t) => {
196
190
  const graph = makeGraph([
197
191
  makeStep({ id: "a" }),
198
192
  makeStep({ id: "b", dependsOn: ["a"] }),
@@ -203,7 +197,7 @@ describe("getNextPendingStep", () => {
203
197
  assert.equal(next?.id, "a");
204
198
  });
205
199
 
206
- it("returns null when all steps are complete", () => {
200
+ it("returns null when all steps are complete", (t) => {
207
201
  const graph = makeGraph([
208
202
  makeStep({ id: "a", status: "complete" }),
209
203
  makeStep({ id: "b", status: "complete" }),
@@ -212,7 +206,7 @@ describe("getNextPendingStep", () => {
212
206
  assert.equal(getNextPendingStep(graph), null);
213
207
  });
214
208
 
215
- it("returns null when all pending steps are blocked", () => {
209
+ it("returns null when all pending steps are blocked", (t) => {
216
210
  const graph = makeGraph([
217
211
  makeStep({ id: "a", status: "active" }), // not complete
218
212
  makeStep({ id: "b", dependsOn: ["a"] }), // blocked
@@ -221,7 +215,7 @@ describe("getNextPendingStep", () => {
221
215
  assert.equal(getNextPendingStep(graph), null);
222
216
  });
223
217
 
224
- it("returns first pending step with no deps when root steps exist", () => {
218
+ it("returns first pending step with no deps when root steps exist", (t) => {
225
219
  const graph = makeGraph([
226
220
  makeStep({ id: "a" }),
227
221
  makeStep({ id: "b" }),
@@ -231,7 +225,7 @@ describe("getNextPendingStep", () => {
231
225
  assert.equal(next?.id, "a");
232
226
  });
233
227
 
234
- it("skips expanded steps", () => {
228
+ it("skips expanded steps", (t) => {
235
229
  const graph = makeGraph([
236
230
  makeStep({ id: "a", status: "expanded" }),
237
231
  makeStep({ id: "b" }),
@@ -245,7 +239,7 @@ describe("getNextPendingStep", () => {
245
239
  // ─── markStepComplete ────────────────────────────────────────────────────
246
240
 
247
241
  describe("markStepComplete", () => {
248
- it("returns new graph with step status 'complete' (original unchanged)", () => {
242
+ it("returns new graph with step status 'complete' (original unchanged)", (t) => {
249
243
  const original = makeGraph([
250
244
  makeStep({ id: "a" }),
251
245
  makeStep({ id: "b" }),
@@ -264,7 +258,7 @@ describe("markStepComplete", () => {
264
258
  assert.equal(updated.steps[1].status, "pending");
265
259
  });
266
260
 
267
- it("sets finishedAt timestamp", () => {
261
+ it("sets finishedAt timestamp", (t) => {
268
262
  const graph = makeGraph([makeStep({ id: "a" })]);
269
263
  const updated = markStepComplete(graph, "a");
270
264
  assert.ok(updated.steps[0].finishedAt);
@@ -272,7 +266,7 @@ describe("markStepComplete", () => {
272
266
  assert.ok(!isNaN(Date.parse(updated.steps[0].finishedAt!)));
273
267
  });
274
268
 
275
- it("throws for unknown step ID", () => {
269
+ it("throws for unknown step ID", (t) => {
276
270
  const graph = makeGraph([makeStep({ id: "a" })]);
277
271
  assert.throws(
278
272
  () => markStepComplete(graph, "nonexistent"),
@@ -284,7 +278,7 @@ describe("markStepComplete", () => {
284
278
  );
285
279
  });
286
280
 
287
- it("preserves metadata in returned graph", () => {
281
+ it("preserves metadata in returned graph", (t) => {
288
282
  const graph = makeGraph([makeStep({ id: "a" })], "my-workflow");
289
283
  const updated = markStepComplete(graph, "a");
290
284
  assert.equal(updated.metadata.name, "my-workflow");
@@ -295,7 +289,7 @@ describe("markStepComplete", () => {
295
289
  // ─── expandIteration ─────────────────────────────────────────────────────
296
290
 
297
291
  describe("expandIteration", () => {
298
- it("creates instance steps with correct IDs (stepId--001, stepId--002)", () => {
292
+ it("creates instance steps with correct IDs (stepId--001, stepId--002)", (t) => {
299
293
  const graph = makeGraph([
300
294
  makeStep({ id: "iter-step", title: "Process items" }),
301
295
  makeStep({ id: "final", dependsOn: ["iter-step"] }),
@@ -317,7 +311,7 @@ describe("expandIteration", () => {
317
311
  assert.equal(expanded.steps[3].id, "iter-step--003");
318
312
  });
319
313
 
320
- it("marks parent step as 'expanded'", () => {
314
+ it("marks parent step as 'expanded'", (t) => {
321
315
  const graph = makeGraph([
322
316
  makeStep({ id: "iter", title: "Iterate" }),
323
317
  ]);
@@ -326,7 +320,7 @@ describe("expandIteration", () => {
326
320
  assert.equal(expanded.steps[0].status, "expanded");
327
321
  });
328
322
 
329
- it("instance steps have correct titles, prompts, parentStepId, and deps", () => {
323
+ it("instance steps have correct titles, prompts, parentStepId, and deps", (t) => {
330
324
  const graph = makeGraph([
331
325
  makeStep({ id: "pre", status: "complete" }),
332
326
  makeStep({ id: "iter", title: "Process", dependsOn: ["pre"] }),
@@ -352,7 +346,7 @@ describe("expandIteration", () => {
352
346
  assert.equal(inst2.parentStepId, "iter");
353
347
  });
354
348
 
355
- it("rewrites downstream deps from parent ID to all instance IDs", () => {
349
+ it("rewrites downstream deps from parent ID to all instance IDs", (t) => {
356
350
  const graph = makeGraph([
357
351
  makeStep({ id: "iter", title: "Iterate" }),
358
352
  makeStep({ id: "after", dependsOn: ["iter"] }),
@@ -370,7 +364,7 @@ describe("expandIteration", () => {
370
364
  assert.deepStrictEqual(afterStep.dependsOn, ["iter--001", "iter--002"]);
371
365
  });
372
366
 
373
- it("preserves steps that don't depend on the parent", () => {
367
+ it("preserves steps that don't depend on the parent", (t) => {
374
368
  const graph = makeGraph([
375
369
  makeStep({ id: "unrelated" }),
376
370
  makeStep({ id: "iter", title: "Iterate" }),
@@ -382,7 +376,7 @@ describe("expandIteration", () => {
382
376
  assert.deepStrictEqual(unrelated.dependsOn, []);
383
377
  });
384
378
 
385
- it("throws for non-pending parent step", () => {
379
+ it("throws for non-pending parent step", (t) => {
386
380
  const graph = makeGraph([
387
381
  makeStep({ id: "iter", status: "complete" }),
388
382
  ]);
@@ -397,7 +391,7 @@ describe("expandIteration", () => {
397
391
  );
398
392
  });
399
393
 
400
- it("throws for unknown step ID", () => {
394
+ it("throws for unknown step ID", (t) => {
401
395
  const graph = makeGraph([makeStep({ id: "a" })]);
402
396
  assert.throws(
403
397
  () => expandIteration(graph, "nonexistent", ["a"], "{{item}}"),
@@ -409,7 +403,7 @@ describe("expandIteration", () => {
409
403
  );
410
404
  });
411
405
 
412
- it("does not mutate the input graph", () => {
406
+ it("does not mutate the input graph", (t) => {
413
407
  const graph = makeGraph([
414
408
  makeStep({ id: "iter", title: "Iterate" }),
415
409
  makeStep({ id: "after", dependsOn: ["iter"] }),
@@ -430,7 +424,7 @@ describe("expandIteration", () => {
430
424
  // ─── initializeGraph ─────────────────────────────────────────────────────
431
425
 
432
426
  describe("initializeGraph", () => {
433
- it("converts a valid 3-step definition to graph with all pending steps", () => {
427
+ it("converts a valid 3-step definition to graph with all pending steps", (t) => {
434
428
  const def: WorkflowDefinition = {
435
429
  version: 1,
436
430
  name: "test-workflow",
@@ -465,7 +459,7 @@ describe("initializeGraph", () => {
465
459
  assert.deepStrictEqual(graph.steps[2].dependsOn, ["s1", "s2"]);
466
460
  });
467
461
 
468
- it("is also exported as graphFromDefinition (backward compat)", () => {
462
+ it("is also exported as graphFromDefinition (backward compat)", (t) => {
469
463
  assert.equal(graphFromDefinition, initializeGraph);
470
464
  });
471
465
  });
@@ -473,7 +467,7 @@ describe("initializeGraph", () => {
473
467
  // ─── Atomic write safety ─────────────────────────────────────────────────
474
468
 
475
469
  describe("atomic write safety", () => {
476
- it("final file exists and .tmp file does not exist after write", () => {
470
+ it("final file exists and .tmp file does not exist after write", (t) => {
477
471
  const dir = makeTmpDir();
478
472
  try {
479
473
  const graph = makeGraph([makeStep({ id: "s1" })]);
@@ -486,7 +480,7 @@ describe("atomic write safety", () => {
486
480
  }
487
481
  });
488
482
 
489
- it("YAML content is valid and parseable", () => {
483
+ it("YAML content is valid and parseable", (t) => {
490
484
  const dir = makeTmpDir();
491
485
  try {
492
486
  const graph = makeGraph([makeStep({ id: "s1" })]);
@@ -507,7 +501,7 @@ describe("atomic write safety", () => {
507
501
  // ─── YAML snake_case / camelCase boundary ────────────────────────────────
508
502
 
509
503
  describe("YAML snake_case / camelCase boundary", () => {
510
- it("writes snake_case to disk and reads back as camelCase", () => {
504
+ it("writes snake_case to disk and reads back as camelCase", (t) => {
511
505
  const dir = makeTmpDir();
512
506
  try {
513
507
  const graph = makeGraph([
@@ -541,7 +535,7 @@ describe("YAML snake_case / camelCase boundary", () => {
541
535
  }
542
536
  });
543
537
 
544
- it("omits optional fields from YAML when undefined", () => {
538
+ it("omits optional fields from YAML when undefined", (t) => {
545
539
  const dir = makeTmpDir();
546
540
  try {
547
541
  const graph = makeGraph([
@@ -565,7 +559,7 @@ describe("YAML snake_case / camelCase boundary", () => {
565
559
  // ─── Edge cases ──────────────────────────────────────────────────────────
566
560
 
567
561
  describe("edge cases", () => {
568
- it("handles empty items array in expandIteration", () => {
562
+ it("handles empty items array in expandIteration", (t) => {
569
563
  const graph = makeGraph([
570
564
  makeStep({ id: "iter" }),
571
565
  ]);
@@ -576,7 +570,7 @@ describe("edge cases", () => {
576
570
  assert.equal(expanded.steps[0].status, "expanded");
577
571
  });
578
572
 
579
- it("handles graph with single step", () => {
573
+ it("handles graph with single step", (t) => {
580
574
  const graph = makeGraph([makeStep({ id: "only" })]);
581
575
  const next = getNextPendingStep(graph);
582
576
  assert.equal(next?.id, "only");
@@ -585,7 +579,7 @@ describe("edge cases", () => {
585
579
  assert.equal(getNextPendingStep(completed), null);
586
580
  });
587
581
 
588
- it("initializeGraph handles steps with empty requires", () => {
582
+ it("initializeGraph handles steps with empty requires", (t) => {
589
583
  const def: WorkflowDefinition = {
590
584
  version: 1,
591
585
  name: "empty-requires",