gsd-pi 2.44.0-dev.62b5d6c → 2.44.0-dev.848dd4c

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 (190) 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/commands/handlers/workflow.js +5 -0
  4. package/dist/web/standalone/.next/BUILD_ID +1 -1
  5. package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -18
  6. package/dist/web/standalone/.next/build-manifest.json +2 -2
  7. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  8. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  9. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  10. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  11. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  12. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  13. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  14. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  15. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  16. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  17. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  18. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  19. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  20. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  21. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  22. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  23. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  24. package/dist/web/standalone/.next/server/app/index.html +1 -1
  25. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  30. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  31. package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -18
  32. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  33. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  34. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  35. package/package.json +1 -1
  36. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
  37. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  38. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
  39. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  40. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
  41. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  42. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
  43. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  44. package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
  45. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  46. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
  47. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  48. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
  49. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  50. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  51. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  52. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
  53. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
  54. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  55. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  56. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  57. package/src/resources/extensions/gsd/auto-start.ts +14 -0
  58. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
  59. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  60. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
  61. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
  62. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
  63. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
  64. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
  65. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
  66. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
  67. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
  68. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
  69. package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
  70. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
  71. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
  72. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  73. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  74. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +38 -59
  75. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +228 -263
  76. package/src/resources/extensions/gsd/tests/complete-task.test.ts +250 -302
  77. package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
  78. package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
  79. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
  80. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
  81. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
  82. package/src/resources/extensions/gsd/tests/db-writer.test.ts +390 -420
  83. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
  84. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
  85. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +152 -183
  86. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
  87. package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
  88. package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
  89. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
  90. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
  91. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
  92. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
  93. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
  94. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
  95. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
  96. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
  97. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
  98. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
  99. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
  100. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
  101. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
  102. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
  103. package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
  104. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
  105. package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
  106. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
  107. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
  108. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
  109. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
  110. package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
  111. package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
  112. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
  113. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
  114. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
  115. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
  116. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
  117. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
  118. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  119. package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
  120. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -102
  121. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
  122. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
  123. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
  124. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
  125. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
  126. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
  127. package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
  128. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
  129. package/src/resources/extensions/gsd/tests/memory-store.test.ts +80 -93
  130. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
  131. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
  132. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
  133. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
  134. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
  135. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
  136. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
  137. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
  138. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
  139. package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
  140. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
  141. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
  142. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
  143. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
  144. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
  145. package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
  146. package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
  147. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
  148. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  149. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
  150. package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
  151. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
  152. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
  153. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
  154. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
  155. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
  156. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
  157. package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
  158. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
  159. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
  160. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
  161. package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
  162. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
  163. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
  164. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
  165. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
  166. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
  167. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
  168. package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
  169. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
  170. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +9 -11
  171. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
  172. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
  173. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
  174. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
  175. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
  176. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
  177. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
  178. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
  179. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
  180. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
  181. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
  182. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
  183. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
  184. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
  185. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
  186. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
  187. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
  188. package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
  189. /package/dist/web/standalone/.next/static/{fOnWQBjWXMKUs4bqTg530 → -zps1Q9mQmioAKLcQiCr8}/_buildManifest.js +0 -0
  190. /package/dist/web/standalone/.next/static/{fOnWQBjWXMKUs4bqTg530 → -zps1Q9mQmioAKLcQiCr8}/_ssgManifest.js +0 -0
@@ -36,176 +36,156 @@ function makeTempDir(prefix: string): string {
36
36
 
37
37
  // ─── appendCapture ────────────────────────────────────────────────────────────
38
38
 
39
- test("captures: appendCapture creates CAPTURES.md on first call", () => {
39
+ test("captures: appendCapture creates CAPTURES.md on first call", (t) => {
40
40
  const tmp = makeTempDir("cap-create");
41
- try {
42
- const id = appendCapture(tmp, "first thought");
43
- assert.ok(id.startsWith("CAP-"), "ID should start with CAP-");
44
- assert.ok(
45
- existsSync(join(tmp, ".gsd", "CAPTURES.md")),
46
- "CAPTURES.md should exist",
47
- );
48
- const content = readFileSync(join(tmp, ".gsd", "CAPTURES.md"), "utf-8");
49
- assert.ok(content.includes("# Captures"), "should have header");
50
- assert.ok(content.includes(`### ${id}`), "should have entry heading");
51
- assert.ok(
52
- content.includes("**Text:** first thought"),
53
- "should have text field",
54
- );
55
- assert.ok(
56
- content.includes("**Status:** pending"),
57
- "should have pending status",
58
- );
59
- } finally {
60
- rmSync(tmp, { recursive: true, force: true });
61
- }
41
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
42
+
43
+ const id = appendCapture(tmp, "first thought");
44
+ assert.ok(id.startsWith("CAP-"), "ID should start with CAP-");
45
+ assert.ok(
46
+ existsSync(join(tmp, ".gsd", "CAPTURES.md")),
47
+ "CAPTURES.md should exist",
48
+ );
49
+ const content = readFileSync(join(tmp, ".gsd", "CAPTURES.md"), "utf-8");
50
+ assert.ok(content.includes("# Captures"), "should have header");
51
+ assert.ok(content.includes(`### ${id}`), "should have entry heading");
52
+ assert.ok(
53
+ content.includes("**Text:** first thought"),
54
+ "should have text field",
55
+ );
56
+ assert.ok(
57
+ content.includes("**Status:** pending"),
58
+ "should have pending status",
59
+ );
62
60
  });
63
61
 
64
- test("captures: appendCapture appends to existing file", () => {
62
+ test("captures: appendCapture appends to existing file", (t) => {
65
63
  const tmp = makeTempDir("cap-append");
66
- try {
67
- const id1 = appendCapture(tmp, "thought one");
68
- const id2 = appendCapture(tmp, "thought two");
69
- assert.notStrictEqual(id1, id2, "IDs should be unique");
70
-
71
- const content = readFileSync(join(tmp, ".gsd", "CAPTURES.md"), "utf-8");
72
- assert.ok(content.includes(`### ${id1}`), "should have first entry");
73
- assert.ok(content.includes(`### ${id2}`), "should have second entry");
74
- assert.ok(
75
- content.includes("**Text:** thought one"),
76
- "should have first text",
77
- );
78
- assert.ok(
79
- content.includes("**Text:** thought two"),
80
- "should have second text",
81
- );
82
- } finally {
83
- rmSync(tmp, { recursive: true, force: true });
84
- }
64
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
65
+
66
+ const id1 = appendCapture(tmp, "thought one");
67
+ const id2 = appendCapture(tmp, "thought two");
68
+ assert.notStrictEqual(id1, id2, "IDs should be unique");
69
+
70
+ const content = readFileSync(join(tmp, ".gsd", "CAPTURES.md"), "utf-8");
71
+ assert.ok(content.includes(`### ${id1}`), "should have first entry");
72
+ assert.ok(content.includes(`### ${id2}`), "should have second entry");
73
+ assert.ok(
74
+ content.includes("**Text:** thought one"),
75
+ "should have first text",
76
+ );
77
+ assert.ok(
78
+ content.includes("**Text:** thought two"),
79
+ "should have second text",
80
+ );
85
81
  });
86
82
 
87
83
  // ─── loadAllCaptures / loadPendingCaptures ────────────────────────────────────
88
84
 
89
- test("captures: loadAllCaptures parses entries correctly", () => {
85
+ test("captures: loadAllCaptures parses entries correctly", (t) => {
90
86
  const tmp = makeTempDir("cap-load");
91
- try {
92
- appendCapture(tmp, "alpha");
93
- appendCapture(tmp, "beta");
94
-
95
- const all = loadAllCaptures(tmp);
96
- assert.strictEqual(all.length, 2, "should have 2 entries");
97
- assert.strictEqual(all[0].text, "alpha");
98
- assert.strictEqual(all[1].text, "beta");
99
- assert.strictEqual(all[0].status, "pending");
100
- assert.strictEqual(all[1].status, "pending");
101
- } finally {
102
- rmSync(tmp, { recursive: true, force: true });
103
- }
87
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
88
+
89
+ appendCapture(tmp, "alpha");
90
+ appendCapture(tmp, "beta");
91
+
92
+ const all = loadAllCaptures(tmp);
93
+ assert.strictEqual(all.length, 2, "should have 2 entries");
94
+ assert.strictEqual(all[0].text, "alpha");
95
+ assert.strictEqual(all[1].text, "beta");
96
+ assert.strictEqual(all[0].status, "pending");
97
+ assert.strictEqual(all[1].status, "pending");
104
98
  });
105
99
 
106
- test("captures: loadAllCaptures returns empty array when no file", () => {
100
+ test("captures: loadAllCaptures returns empty array when no file", (t) => {
107
101
  const tmp = makeTempDir("cap-nofile");
108
- try {
109
- const all = loadAllCaptures(tmp);
110
- assert.strictEqual(all.length, 0);
111
- } finally {
112
- rmSync(tmp, { recursive: true, force: true });
113
- }
102
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
103
+
104
+ const all = loadAllCaptures(tmp);
105
+ assert.strictEqual(all.length, 0);
114
106
  });
115
107
 
116
- test("captures: loadPendingCaptures filters resolved entries", () => {
108
+ test("captures: loadPendingCaptures filters resolved entries", (t) => {
117
109
  const tmp = makeTempDir("cap-pending");
118
- try {
119
- const id1 = appendCapture(tmp, "pending one");
120
- appendCapture(tmp, "pending two");
110
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
121
111
 
122
- markCaptureResolved(tmp, id1, "note", "acknowledged", "just a note");
112
+ const id1 = appendCapture(tmp, "pending one");
113
+ appendCapture(tmp, "pending two");
123
114
 
124
- const pending = loadPendingCaptures(tmp);
125
- assert.strictEqual(pending.length, 1, "should have 1 pending");
126
- assert.strictEqual(pending[0].text, "pending two");
127
- } finally {
128
- rmSync(tmp, { recursive: true, force: true });
129
- }
115
+ markCaptureResolved(tmp, id1, "note", "acknowledged", "just a note");
116
+
117
+ const pending = loadPendingCaptures(tmp);
118
+ assert.strictEqual(pending.length, 1, "should have 1 pending");
119
+ assert.strictEqual(pending[0].text, "pending two");
130
120
  });
131
121
 
132
- test("captures: loadAllCaptures preserves resolved entries", () => {
122
+ test("captures: loadAllCaptures preserves resolved entries", (t) => {
133
123
  const tmp = makeTempDir("cap-all-resolved");
134
- try {
135
- const id1 = appendCapture(tmp, "pending one");
136
- appendCapture(tmp, "pending two");
137
-
138
- markCaptureResolved(tmp, id1, "note", "acknowledged", "just a note");
139
-
140
- const all = loadAllCaptures(tmp);
141
- assert.strictEqual(all.length, 2, "all should still have 2");
142
- assert.strictEqual(all[0].status, "resolved");
143
- assert.strictEqual(all[1].status, "pending");
144
- } finally {
145
- rmSync(tmp, { recursive: true, force: true });
146
- }
124
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
125
+
126
+ const id1 = appendCapture(tmp, "pending one");
127
+ appendCapture(tmp, "pending two");
128
+
129
+ markCaptureResolved(tmp, id1, "note", "acknowledged", "just a note");
130
+
131
+ const all = loadAllCaptures(tmp);
132
+ assert.strictEqual(all.length, 2, "all should still have 2");
133
+ assert.strictEqual(all[0].status, "resolved");
134
+ assert.strictEqual(all[1].status, "pending");
147
135
  });
148
136
 
149
137
  // ─── hasPendingCaptures ───────────────────────────────────────────────────────
150
138
 
151
- test("captures: hasPendingCaptures returns false when no file", () => {
139
+ test("captures: hasPendingCaptures returns false when no file", (t) => {
152
140
  const tmp = makeTempDir("cap-has-nofile");
153
- try {
154
- assert.strictEqual(hasPendingCaptures(tmp), false);
155
- } finally {
156
- rmSync(tmp, { recursive: true, force: true });
157
- }
141
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
142
+
143
+ assert.strictEqual(hasPendingCaptures(tmp), false);
158
144
  });
159
145
 
160
- test("captures: hasPendingCaptures returns true with pending entries", () => {
146
+ test("captures: hasPendingCaptures returns true with pending entries", (t) => {
161
147
  const tmp = makeTempDir("cap-has-true");
162
- try {
163
- appendCapture(tmp, "something");
164
- assert.strictEqual(hasPendingCaptures(tmp), true);
165
- } finally {
166
- rmSync(tmp, { recursive: true, force: true });
167
- }
148
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
149
+
150
+ appendCapture(tmp, "something");
151
+ assert.strictEqual(hasPendingCaptures(tmp), true);
168
152
  });
169
153
 
170
- test("captures: hasPendingCaptures returns false when all resolved", () => {
154
+ test("captures: hasPendingCaptures returns false when all resolved", (t) => {
171
155
  const tmp = makeTempDir("cap-has-false");
172
- try {
173
- const id = appendCapture(tmp, "will resolve");
174
- markCaptureResolved(tmp, id, "note", "done", "resolved it");
175
- assert.strictEqual(hasPendingCaptures(tmp), false);
176
- } finally {
177
- rmSync(tmp, { recursive: true, force: true });
178
- }
156
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
157
+
158
+ const id = appendCapture(tmp, "will resolve");
159
+ markCaptureResolved(tmp, id, "note", "done", "resolved it");
160
+ assert.strictEqual(hasPendingCaptures(tmp), false);
179
161
  });
180
162
 
181
163
  // ─── markCaptureResolved ──────────────────────────────────────────────────────
182
164
 
183
- test("captures: markCaptureResolved updates entry in place", () => {
165
+ test("captures: markCaptureResolved updates entry in place", (t) => {
184
166
  const tmp = makeTempDir("cap-resolve");
185
- try {
186
- const id1 = appendCapture(tmp, "keep pending");
187
- const id2 = appendCapture(tmp, "will resolve");
188
- appendCapture(tmp, "also pending");
189
-
190
- markCaptureResolved(tmp, id2, "quick-task", "executed inline", "small fix");
191
-
192
- const all = loadAllCaptures(tmp);
193
- assert.strictEqual(all.length, 3, "should still have 3 entries");
194
-
195
- const resolved = all.find((c) => c.id === id2)!;
196
- assert.strictEqual(resolved.status, "resolved");
197
- assert.strictEqual(resolved.classification, "quick-task");
198
- assert.strictEqual(resolved.resolution, "executed inline");
199
- assert.strictEqual(resolved.rationale, "small fix");
200
- assert.ok(resolved.resolvedAt, "should have resolved timestamp");
201
-
202
- // Others should be unaffected
203
- const kept = all.find((c) => c.id === id1)!;
204
- assert.strictEqual(kept.status, "pending");
205
- assert.strictEqual(kept.classification, undefined);
206
- } finally {
207
- rmSync(tmp, { recursive: true, force: true });
208
- }
167
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
168
+
169
+ const id1 = appendCapture(tmp, "keep pending");
170
+ const id2 = appendCapture(tmp, "will resolve");
171
+ appendCapture(tmp, "also pending");
172
+
173
+ markCaptureResolved(tmp, id2, "quick-task", "executed inline", "small fix");
174
+
175
+ const all = loadAllCaptures(tmp);
176
+ assert.strictEqual(all.length, 3, "should still have 3 entries");
177
+
178
+ const resolved = all.find((c) => c.id === id2)!;
179
+ assert.strictEqual(resolved.status, "resolved");
180
+ assert.strictEqual(resolved.classification, "quick-task");
181
+ assert.strictEqual(resolved.resolution, "executed inline");
182
+ assert.strictEqual(resolved.rationale, "small fix");
183
+ assert.ok(resolved.resolvedAt, "should have resolved timestamp");
184
+
185
+ // Others should be unaffected
186
+ const kept = all.find((c) => c.id === id1)!;
187
+ assert.strictEqual(kept.status, "pending");
188
+ assert.strictEqual(kept.classification, undefined);
209
189
  });
210
190
 
211
191
  // ─── resolveCapturesPath ──────────────────────────────────────────────────────
@@ -371,58 +351,50 @@ test("triage: parseTriageOutput handles all five classification types", () => {
371
351
 
372
352
  // ─── Edge Cases ───────────────────────────────────────────────────────────────
373
353
 
374
- test("captures: appendCapture handles special characters in text", () => {
354
+ test("captures: appendCapture handles special characters in text", (t) => {
375
355
  const tmp = makeTempDir("cap-special");
376
- try {
377
- const id = appendCapture(tmp, 'text with "quotes" and **bold** and `code`');
378
- const all = loadAllCaptures(tmp);
379
- assert.strictEqual(all.length, 1);
380
- assert.ok(all[0].text.includes('"quotes"'), "should preserve quotes");
381
- assert.ok(all[0].text.includes("**bold**"), "should preserve bold");
382
- } finally {
383
- rmSync(tmp, { recursive: true, force: true });
384
- }
356
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
357
+
358
+ const id = appendCapture(tmp, 'text with "quotes" and **bold** and `code`');
359
+ const all = loadAllCaptures(tmp);
360
+ assert.strictEqual(all.length, 1);
361
+ assert.ok(all[0].text.includes('"quotes"'), "should preserve quotes");
362
+ assert.ok(all[0].text.includes("**bold**"), "should preserve bold");
385
363
  });
386
364
 
387
- test("captures: markCaptureResolved is no-op for non-existent ID", () => {
365
+ test("captures: markCaptureResolved is no-op for non-existent ID", (t) => {
388
366
  const tmp = makeTempDir("cap-noop");
389
- try {
390
- appendCapture(tmp, "real capture");
391
- // Should not throw
392
- markCaptureResolved(tmp, "CAP-nonexistent", "note", "test", "test");
393
- const all = loadAllCaptures(tmp);
394
- assert.strictEqual(all.length, 1);
395
- assert.strictEqual(all[0].status, "pending", "original should be unchanged");
396
- } finally {
397
- rmSync(tmp, { recursive: true, force: true });
398
- }
367
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
368
+
369
+ appendCapture(tmp, "real capture");
370
+ // Should not throw
371
+ markCaptureResolved(tmp, "CAP-nonexistent", "note", "test", "test");
372
+ const all = loadAllCaptures(tmp);
373
+ assert.strictEqual(all.length, 1);
374
+ assert.strictEqual(all[0].status, "pending", "original should be unchanged");
399
375
  });
400
376
 
401
- test("captures: markCaptureResolved is no-op when no file exists", () => {
377
+ test("captures: markCaptureResolved is no-op when no file exists", (t) => {
402
378
  const tmp = makeTempDir("cap-nofile-resolve");
403
- try {
404
- // Should not throw
405
- markCaptureResolved(tmp, "CAP-abc", "note", "test", "test");
406
- } finally {
407
- rmSync(tmp, { recursive: true, force: true });
408
- }
379
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
380
+
381
+ // Should not throw
382
+ markCaptureResolved(tmp, "CAP-abc", "note", "test", "test");
409
383
  });
410
384
 
411
- test("captures: re-resolving a capture overwrites previous resolution", () => {
385
+ test("captures: re-resolving a capture overwrites previous resolution", (t) => {
412
386
  const tmp = makeTempDir("cap-reresolve");
413
- try {
414
- const id = appendCapture(tmp, "will re-resolve");
415
- markCaptureResolved(tmp, id, "note", "first resolution", "first rationale");
416
- markCaptureResolved(tmp, id, "inject", "second resolution", "second rationale");
417
-
418
- const all = loadAllCaptures(tmp);
419
- assert.strictEqual(all.length, 1);
420
- assert.strictEqual(all[0].classification, "inject", "should have updated classification");
421
- assert.strictEqual(all[0].resolution, "second resolution");
422
- assert.strictEqual(all[0].rationale, "second rationale");
423
- } finally {
424
- rmSync(tmp, { recursive: true, force: true });
425
- }
387
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
388
+
389
+ const id = appendCapture(tmp, "will re-resolve");
390
+ markCaptureResolved(tmp, id, "note", "first resolution", "first rationale");
391
+ markCaptureResolved(tmp, id, "inject", "second resolution", "second rationale");
392
+
393
+ const all = loadAllCaptures(tmp);
394
+ assert.strictEqual(all.length, 1);
395
+ assert.strictEqual(all[0].classification, "inject", "should have updated classification");
396
+ assert.strictEqual(all[0].resolution, "second resolution");
397
+ assert.strictEqual(all[0].rationale, "second rationale");
426
398
  });
427
399
 
428
400
  test("triage: parseTriageOutput preserves affectedFiles and targetSlice", () => {
@@ -8,7 +8,6 @@
8
8
  * `/plugin marketplace add ...` source model.
9
9
  */
10
10
 
11
-
12
11
  import { describe, it, before, after, mock } from 'node:test';
13
12
  import assert from 'node:assert';
14
13
  import { existsSync, mkdtempSync, rmSync, writeFileSync, readFileSync, mkdirSync } from 'node:fs';
@@ -306,45 +305,45 @@ describe(
306
305
  });
307
306
  });
308
307
 
309
- it('should not persist marketplace agent directories into package sources', async () => {
308
+ it('should not persist marketplace agent directories into package sources', async (t) => {
310
309
  const isolatedAgentDir = join(tempDir, '.gsd', 'agent');
311
310
  const settingsPath = join(isolatedAgentDir, 'settings.json');
312
311
  rmSync(isolatedAgentDir, { recursive: true, force: true });
313
312
  process.env.GSD_CODING_AGENT_DIR = isolatedAgentDir;
314
313
 
315
- try {
316
- mkdirSync(isolatedAgentDir, { recursive: true });
317
- const tempSettings: Record<string, unknown> = { packages: [] };
318
- writeFileSync(settingsPath, JSON.stringify(tempSettings, null, 2));
319
-
320
- const { ctx } = createMockContext([
321
- 'Plugins only',
322
- 'Yes - discover plugins and select components',
323
- 'Import all components',
324
- 'Yes, continue',
325
- ]);
326
-
327
- const readPrefs = () => ({ ...prefs });
328
- const writePrefs = async (p: Record<string, unknown>) => {
329
- Object.assign(prefs, p);
330
- };
331
-
332
- await runClaudeImportFlow(ctx, 'global', readPrefs, writePrefs);
333
-
334
- const settings = JSON.parse(readFileSync(settingsPath, 'utf8')) as { packages?: unknown[] };
335
- const packageEntries = Array.isArray(settings.packages) ? settings.packages : [];
336
- const hasAgentsDirPackage = packageEntries.some((entry) => {
337
- const source = typeof entry === 'string'
338
- ? entry
339
- : (entry && typeof entry === 'object' ? (entry as { source?: unknown }).source : undefined);
340
- return typeof source === 'string' && source.endsWith('/agents');
341
- });
342
-
343
- assert.strictEqual(hasAgentsDirPackage, false, 'Marketplace agent directories should not be persisted as package sources');
344
- } finally {
314
+ t.after(() => {
345
315
  delete process.env.GSD_CODING_AGENT_DIR;
346
316
  rmSync(isolatedAgentDir, { recursive: true, force: true });
347
- }
317
+ });
318
+
319
+ mkdirSync(isolatedAgentDir, { recursive: true });
320
+ const tempSettings: Record<string, unknown> = { packages: [] };
321
+ writeFileSync(settingsPath, JSON.stringify(tempSettings, null, 2));
322
+
323
+ const { ctx } = createMockContext([
324
+ 'Plugins only',
325
+ 'Yes - discover plugins and select components',
326
+ 'Import all components',
327
+ 'Yes, continue',
328
+ ]);
329
+
330
+ const readPrefs = () => ({ ...prefs });
331
+ const writePrefs = async (p: Record<string, unknown>) => {
332
+ Object.assign(prefs, p);
333
+ };
334
+
335
+ await runClaudeImportFlow(ctx, 'global', readPrefs, writePrefs);
336
+
337
+ const settings = JSON.parse(readFileSync(settingsPath, 'utf8')) as { packages?: unknown[] };
338
+ const packageEntries = Array.isArray(settings.packages) ? settings.packages : [];
339
+ const hasAgentsDirPackage = packageEntries.some((entry) => {
340
+ const source = typeof entry === 'string'
341
+ ? entry
342
+ : (entry && typeof entry === 'object' ? (entry as { source?: unknown }).source : undefined);
343
+ return typeof source === 'string' && source.endsWith('/agents');
344
+ });
345
+
346
+ assert.strictEqual(hasAgentsDirPackage, false, 'Marketplace agent directories should not be persisted as package sources');
348
347
  });
349
348
  });
350
349
  }