gsd-pi 2.33.1-dev.ee47f1b → 2.34.0-dev.bbb5216

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 (135) hide show
  1. package/dist/bundled-resource-path.d.ts +8 -0
  2. package/dist/bundled-resource-path.js +14 -0
  3. package/dist/headless-query.js +6 -6
  4. package/dist/resources/extensions/gsd/auto/session.js +27 -32
  5. package/dist/resources/extensions/gsd/auto-dashboard.js +29 -109
  6. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +6 -1
  7. package/dist/resources/extensions/gsd/auto-dispatch.js +52 -81
  8. package/dist/resources/extensions/gsd/auto-loop.js +956 -0
  9. package/dist/resources/extensions/gsd/auto-observability.js +4 -2
  10. package/dist/resources/extensions/gsd/auto-post-unit.js +75 -185
  11. package/dist/resources/extensions/gsd/auto-prompts.js +133 -101
  12. package/dist/resources/extensions/gsd/auto-recovery.js +59 -97
  13. package/dist/resources/extensions/gsd/auto-start.js +330 -309
  14. package/dist/resources/extensions/gsd/auto-supervisor.js +5 -11
  15. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +7 -7
  16. package/dist/resources/extensions/gsd/auto-timers.js +3 -4
  17. package/dist/resources/extensions/gsd/auto-verification.js +35 -73
  18. package/dist/resources/extensions/gsd/auto-worktree-sync.js +167 -0
  19. package/dist/resources/extensions/gsd/auto-worktree.js +291 -126
  20. package/dist/resources/extensions/gsd/auto.js +283 -1013
  21. package/dist/resources/extensions/gsd/captures.js +10 -4
  22. package/dist/resources/extensions/gsd/dispatch-guard.js +7 -8
  23. package/dist/resources/extensions/gsd/docs/preferences-reference.md +25 -18
  24. package/dist/resources/extensions/gsd/doctor-checks.js +3 -4
  25. package/dist/resources/extensions/gsd/git-service.js +1 -1
  26. package/dist/resources/extensions/gsd/gsd-db.js +296 -151
  27. package/dist/resources/extensions/gsd/index.js +92 -228
  28. package/dist/resources/extensions/gsd/post-unit-hooks.js +13 -13
  29. package/dist/resources/extensions/gsd/progress-score.js +61 -156
  30. package/dist/resources/extensions/gsd/quick.js +98 -122
  31. package/dist/resources/extensions/gsd/session-lock.js +13 -0
  32. package/dist/resources/extensions/gsd/templates/preferences.md +1 -0
  33. package/dist/resources/extensions/gsd/undo.js +43 -48
  34. package/dist/resources/extensions/gsd/unit-runtime.js +16 -15
  35. package/dist/resources/extensions/gsd/verification-evidence.js +0 -1
  36. package/dist/resources/extensions/gsd/verification-gate.js +6 -35
  37. package/dist/resources/extensions/gsd/worktree-command.js +30 -24
  38. package/dist/resources/extensions/gsd/worktree-manager.js +2 -3
  39. package/dist/resources/extensions/gsd/worktree-resolver.js +344 -0
  40. package/dist/resources/extensions/gsd/worktree.js +7 -44
  41. package/dist/tool-bootstrap.js +59 -11
  42. package/dist/worktree-cli.js +7 -7
  43. package/package.json +1 -1
  44. package/packages/pi-ai/dist/models.generated.d.ts +3630 -5483
  45. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  46. package/packages/pi-ai/dist/models.generated.js +735 -2588
  47. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  48. package/packages/pi-ai/src/models.generated.ts +1039 -2892
  49. package/packages/pi-coding-agent/package.json +1 -1
  50. package/pkg/package.json +1 -1
  51. package/src/resources/extensions/gsd/auto/session.ts +47 -30
  52. package/src/resources/extensions/gsd/auto-dashboard.ts +28 -131
  53. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +6 -1
  54. package/src/resources/extensions/gsd/auto-dispatch.ts +135 -91
  55. package/src/resources/extensions/gsd/auto-loop.ts +1665 -0
  56. package/src/resources/extensions/gsd/auto-observability.ts +4 -2
  57. package/src/resources/extensions/gsd/auto-post-unit.ts +85 -228
  58. package/src/resources/extensions/gsd/auto-prompts.ts +138 -109
  59. package/src/resources/extensions/gsd/auto-recovery.ts +124 -118
  60. package/src/resources/extensions/gsd/auto-start.ts +440 -354
  61. package/src/resources/extensions/gsd/auto-supervisor.ts +5 -12
  62. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +8 -8
  63. package/src/resources/extensions/gsd/auto-timers.ts +3 -4
  64. package/src/resources/extensions/gsd/auto-verification.ts +76 -90
  65. package/src/resources/extensions/gsd/auto-worktree-sync.ts +204 -0
  66. package/src/resources/extensions/gsd/auto-worktree.ts +389 -141
  67. package/src/resources/extensions/gsd/auto.ts +515 -1199
  68. package/src/resources/extensions/gsd/captures.ts +10 -4
  69. package/src/resources/extensions/gsd/dispatch-guard.ts +13 -9
  70. package/src/resources/extensions/gsd/docs/preferences-reference.md +25 -18
  71. package/src/resources/extensions/gsd/doctor-checks.ts +3 -4
  72. package/src/resources/extensions/gsd/git-service.ts +8 -1
  73. package/src/resources/extensions/gsd/gitignore.ts +4 -2
  74. package/src/resources/extensions/gsd/gsd-db.ts +375 -180
  75. package/src/resources/extensions/gsd/index.ts +104 -263
  76. package/src/resources/extensions/gsd/post-unit-hooks.ts +13 -13
  77. package/src/resources/extensions/gsd/progress-score.ts +65 -200
  78. package/src/resources/extensions/gsd/quick.ts +121 -125
  79. package/src/resources/extensions/gsd/session-lock.ts +11 -0
  80. package/src/resources/extensions/gsd/templates/preferences.md +1 -0
  81. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +32 -59
  82. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +75 -27
  83. package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
  84. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +37 -0
  85. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +1458 -0
  86. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +8 -162
  87. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +2 -108
  88. package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +1 -3
  89. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +0 -3
  90. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +58 -0
  91. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +0 -55
  92. package/src/resources/extensions/gsd/tests/headless-query.test.ts +22 -0
  93. package/src/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +8 -11
  94. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +4 -6
  95. package/src/resources/extensions/gsd/tests/run-uat.test.ts +3 -3
  96. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +64 -0
  97. package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +181 -0
  98. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +0 -3
  99. package/src/resources/extensions/gsd/tests/token-profile.test.ts +6 -6
  100. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +6 -6
  101. package/src/resources/extensions/gsd/tests/undo.test.ts +6 -0
  102. package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +24 -26
  103. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +7 -201
  104. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +205 -0
  105. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +442 -0
  106. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +0 -3
  107. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +705 -0
  108. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +57 -106
  109. package/src/resources/extensions/gsd/tests/worktree.test.ts +5 -1
  110. package/src/resources/extensions/gsd/tests/write-gate.test.ts +43 -132
  111. package/src/resources/extensions/gsd/types.ts +90 -81
  112. package/src/resources/extensions/gsd/undo.ts +42 -46
  113. package/src/resources/extensions/gsd/unit-runtime.ts +14 -18
  114. package/src/resources/extensions/gsd/verification-evidence.ts +1 -3
  115. package/src/resources/extensions/gsd/verification-gate.ts +6 -39
  116. package/src/resources/extensions/gsd/worktree-command.ts +36 -24
  117. package/src/resources/extensions/gsd/worktree-manager.ts +2 -3
  118. package/src/resources/extensions/gsd/worktree-resolver.ts +485 -0
  119. package/src/resources/extensions/gsd/worktree.ts +7 -44
  120. package/dist/resources/extensions/gsd/auto-constants.js +0 -5
  121. package/dist/resources/extensions/gsd/auto-idempotency.js +0 -106
  122. package/dist/resources/extensions/gsd/auto-stuck-detection.js +0 -165
  123. package/dist/resources/extensions/gsd/mechanical-completion.js +0 -351
  124. package/src/resources/extensions/gsd/auto-constants.ts +0 -6
  125. package/src/resources/extensions/gsd/auto-idempotency.ts +0 -151
  126. package/src/resources/extensions/gsd/auto-stuck-detection.ts +0 -221
  127. package/src/resources/extensions/gsd/mechanical-completion.ts +0 -430
  128. package/src/resources/extensions/gsd/tests/auto-dispatch-loop.test.ts +0 -691
  129. package/src/resources/extensions/gsd/tests/auto-reentrancy-guard.test.ts +0 -127
  130. package/src/resources/extensions/gsd/tests/auto-skip-loop.test.ts +0 -123
  131. package/src/resources/extensions/gsd/tests/dispatch-stall-guard.test.ts +0 -126
  132. package/src/resources/extensions/gsd/tests/loop-regression.test.ts +0 -874
  133. package/src/resources/extensions/gsd/tests/mechanical-completion.test.ts +0 -356
  134. package/src/resources/extensions/gsd/tests/progress-score.test.ts +0 -206
  135. package/src/resources/extensions/gsd/tests/session-lock.test.ts +0 -434
@@ -45,12 +45,11 @@ const PACKAGE_SCRIPT_KEYS = ["typecheck", "lint", "test"] as const;
45
45
  * 4. None found
46
46
  */
47
47
  export function discoverCommands(options: DiscoverCommandsOptions): DiscoveredCommands {
48
- // 1. Preference commands (still sanitize — may contain prose from misconfiguration)
48
+ // 1. Preference commands
49
49
  if (options.preferenceCommands && options.preferenceCommands.length > 0) {
50
50
  const filtered = options.preferenceCommands
51
51
  .map(c => c.trim())
52
- .filter(Boolean)
53
- .filter(c => isLikelyCommand(c));
52
+ .filter(Boolean);
54
53
  if (filtered.length > 0) {
55
54
  return { commands: filtered, source: "preference" };
56
55
  }
@@ -112,9 +111,7 @@ const MAX_FAILURE_CONTEXT_CHARS = 10_000;
112
111
  * Returns an empty string when all checks pass or the checks array is empty.
113
112
  */
114
113
  export function formatFailureContext(result: VerificationResult): string {
115
- // Only include blocking failures in retry context non-blocking (advisory) failures
116
- // should not be injected into retry prompts to avoid noise pollution.
117
- const failures = result.checks.filter((c) => c.exitCode !== 0 && c.blocking);
114
+ const failures = result.checks.filter((c) => c.exitCode !== 0);
118
115
  if (failures.length === 0) return "";
119
116
 
120
117
  const blocks: string[] = [];
@@ -232,20 +229,13 @@ export interface RunVerificationGateOptions {
232
229
  commandTimeoutMs?: number;
233
230
  }
234
231
 
235
- /** Error codes from spawnSync that indicate infrastructure/OS-level failures
236
- * rather than the command itself failing. These are transient — the agent
237
- * cannot fix them, so they should not trigger auto-fix retries. */
238
- const INFRA_ERROR_CODES = new Set(["ETIMEDOUT", "ENOENT", "ENOMEM", "EMFILE", "ENFILE", "EAGAIN"]);
239
-
240
232
  /**
241
233
  * Run the verification gate: discover commands, execute each via spawnSync,
242
234
  * and return a structured result.
243
235
  *
244
236
  * - All commands run sequentially regardless of individual pass/fail.
245
- * - `passed` is true when every blocking command exits 0 (or no commands are discovered).
237
+ * - `passed` is true when every command exits 0 (or no commands are discovered).
246
238
  * - stdout/stderr per command are truncated to 10 KB.
247
- * - Spawn/infra errors (ETIMEDOUT, ENOENT, etc.) are tagged with `infraError: true`
248
- * so the retry logic can distinguish "the OS couldn't run this" from "the tests failed".
249
239
  */
250
240
  export function runVerificationGate(options: RunVerificationGateOptions): VerificationResult {
251
241
  const timestamp = Date.now();
@@ -265,10 +255,6 @@ export function runVerificationGate(options: RunVerificationGateOptions): Verifi
265
255
  };
266
256
  }
267
257
 
268
- // Commands from preference and task-plan sources are blocking;
269
- // package-json discovered commands are advisory (non-blocking).
270
- const blocking = source === "preference" || source === "task-plan";
271
-
272
258
  const checks: VerificationCheck[] = [];
273
259
 
274
260
  for (const command of commands) {
@@ -286,26 +272,12 @@ export function runVerificationGate(options: RunVerificationGateOptions): Verifi
286
272
  let stderr: string;
287
273
 
288
274
  if (result.error) {
289
- // Spawn infrastructure failure OS-level, not a test failure.
290
- // Tag with infraError so the retry logic can skip auto-fix attempts.
291
- const errCode = (result.error as NodeJS.ErrnoException).code;
292
- const isInfra = !!errCode && INFRA_ERROR_CODES.has(errCode);
275
+ // Command not found or spawn failure
293
276
  exitCode = 127;
294
277
  stderr = truncate(
295
278
  (result.stderr || "") + "\n" + (result.error as Error).message,
296
279
  MAX_OUTPUT_BYTES,
297
280
  );
298
-
299
- checks.push({
300
- command,
301
- exitCode,
302
- stdout: truncate(result.stdout, MAX_OUTPUT_BYTES),
303
- stderr,
304
- durationMs,
305
- blocking,
306
- ...(isInfra ? { infraError: true } : {}),
307
- });
308
- continue;
309
281
  } else {
310
282
  // status is null when killed by signal — treat as failure
311
283
  exitCode = result.status ?? 1;
@@ -318,16 +290,11 @@ export function runVerificationGate(options: RunVerificationGateOptions): Verifi
318
290
  stdout: truncate(result.stdout, MAX_OUTPUT_BYTES),
319
291
  stderr,
320
292
  durationMs,
321
- blocking,
322
293
  });
323
294
  }
324
295
 
325
- // Gate passes if all blocking checks pass (non-blocking failures are advisory)
326
- const blockingChecks = checks.filter(c => c.blocking);
327
- const passed = blockingChecks.length === 0 || blockingChecks.every(c => c.exitCode === 0);
328
-
329
296
  return {
330
- passed,
297
+ passed: checks.every(c => c.exitCode === 0),
331
298
  checks,
332
299
  discoverySource: source,
333
300
  timestamp,
@@ -34,7 +34,6 @@ import type { FileLineStat } from "./worktree-manager.js";
34
34
  import { existsSync, realpathSync, readdirSync, rmSync, unlinkSync } from "node:fs";
35
35
  import { nativeMergeAbort } from "./native-git-bridge.js";
36
36
  import { join, sep } from "node:path";
37
- import { getErrorMessage } from "./error-utils.js";
38
37
 
39
38
  /**
40
39
  * Tracks the original project root so we can switch back.
@@ -42,28 +41,16 @@ import { getErrorMessage } from "./error-utils.js";
42
41
  */
43
42
  let originalCwd: string | null = null;
44
43
 
45
- function ensureWorktreeStateInitialized(): void {
46
- if (originalCwd) return;
47
- const cwd = process.cwd();
48
- const marker = `${sep}.gsd${sep}worktrees${sep}`;
49
- const markerIdx = cwd.indexOf(marker);
50
- if (markerIdx !== -1) {
51
- originalCwd = cwd.slice(0, markerIdx);
52
- }
53
- }
54
-
55
44
  /** Get the original project root if currently in a worktree, or null. */
56
45
  export function getWorktreeOriginalCwd(): string | null {
57
- ensureWorktreeStateInitialized();
58
46
  return originalCwd;
59
47
  }
60
48
 
61
49
  /** Get the name of the active worktree, or null if not in one. */
62
50
  export function getActiveWorktreeName(): string | null {
63
- ensureWorktreeStateInitialized();
64
51
  if (!originalCwd) return null;
65
52
  const cwd = process.cwd();
66
- const wtDir = join(gsdRoot(originalCwd), "worktrees");
53
+ const wtDir = join(originalCwd, ".gsd", "worktrees");
67
54
  if (!cwd.startsWith(wtDir)) return null;
68
55
  const rel = cwd.slice(wtDir.length + 1);
69
56
  const name = rel.split("/")[0] ?? rel.split("\\")[0];
@@ -116,13 +103,12 @@ function worktreeCompletions(prefix: string) {
116
103
  return [];
117
104
  }
118
105
 
119
- export async function handleWorktreeCommand(
106
+ async function worktreeHandler(
120
107
  args: string,
121
108
  ctx: ExtensionCommandContext,
122
109
  pi: ExtensionAPI,
123
110
  alias: string,
124
111
  ): Promise<void> {
125
- ensureWorktreeStateInitialized();
126
112
  const trimmed = (typeof args === "string" ? args : "").trim();
127
113
  const basePath = process.cwd();
128
114
 
@@ -242,11 +228,27 @@ export async function handleWorktreeCommand(
242
228
  }
243
229
  }
244
230
 
231
+ export async function handleWorktreeCommand(
232
+ args: string,
233
+ ctx: ExtensionCommandContext,
234
+ pi: ExtensionAPI,
235
+ alias: string,
236
+ ): Promise<void> {
237
+ await worktreeHandler(args, ctx, pi, alias);
238
+ }
239
+
245
240
  export function registerWorktreeCommand(pi: ExtensionAPI): void {
246
241
  // Restore worktree state after /reload.
247
242
  // The module-level originalCwd resets to null when extensions are re-loaded,
248
243
  // but process.cwd() is still inside the worktree. Detect this and recover.
249
- ensureWorktreeStateInitialized();
244
+ if (!originalCwd) {
245
+ const cwd = process.cwd();
246
+ const marker = `${sep}.gsd${sep}worktrees${sep}`;
247
+ const markerIdx = cwd.indexOf(marker);
248
+ if (markerIdx !== -1) {
249
+ originalCwd = cwd.slice(0, markerIdx);
250
+ }
251
+ }
250
252
 
251
253
  pi.registerCommand("worktree", {
252
254
  description: "Git worktrees (also /wt): /worktree <name> | list | merge | remove",
@@ -377,7 +379,7 @@ async function handleCreate(
377
379
  "info",
378
380
  );
379
381
  } catch (error) {
380
- const msg = getErrorMessage(error);
382
+ const msg = error instanceof Error ? error.message : String(error);
381
383
  ctx.ui.notify(`Failed to create worktree: ${msg}`, "error");
382
384
  }
383
385
  }
@@ -425,7 +427,7 @@ async function handleSwitch(
425
427
  "info",
426
428
  );
427
429
  } catch (error) {
428
- const msg = getErrorMessage(error);
430
+ const msg = error instanceof Error ? error.message : String(error);
429
431
  ctx.ui.notify(`Failed to switch to worktree: ${msg}`, "error");
430
432
  }
431
433
  }
@@ -535,7 +537,7 @@ async function handleList(
535
537
 
536
538
  ctx.ui.notify(lines.join("\n"), "info");
537
539
  } catch (error) {
538
- const msg = getErrorMessage(error);
540
+ const msg = error instanceof Error ? error.message : String(error);
539
541
  ctx.ui.notify(`Failed to list worktrees: ${msg}`, "error");
540
542
  }
541
543
  }
@@ -640,6 +642,16 @@ async function handleMerge(
640
642
  const commitType = inferCommitType(name);
641
643
  const commitMessage = `${commitType}(${name}): merge worktree ${name}`;
642
644
 
645
+ // Reconcile worktree DB into main DB before squash merge
646
+ const wtDbPath = join(worktreePath(basePath, name), ".gsd", "gsd.db");
647
+ const mainDbPath = join(basePath, ".gsd", "gsd.db");
648
+ if (existsSync(wtDbPath) && existsSync(mainDbPath)) {
649
+ try {
650
+ const { reconcileWorktreeDb } = await import("./gsd-db.js");
651
+ reconcileWorktreeDb(mainDbPath, wtDbPath);
652
+ } catch { /* non-fatal */ }
653
+ }
654
+
643
655
  try {
644
656
  mergeWorktreeToMain(basePath, name, commitMessage);
645
657
  ctx.ui.notify(
@@ -653,7 +665,7 @@ async function handleMerge(
653
665
  );
654
666
  return;
655
667
  } catch (mergeErr) {
656
- const mergeMsg = getErrorMessage(mergeErr);
668
+ const mergeMsg = mergeErr instanceof Error ? mergeErr.message : String(mergeErr);
657
669
  const isConflict = /conflict/i.test(mergeMsg);
658
670
 
659
671
  if (isConflict) {
@@ -710,7 +722,7 @@ async function handleMerge(
710
722
  "info",
711
723
  );
712
724
  } catch (error) {
713
- const msg = getErrorMessage(error);
725
+ const msg = error instanceof Error ? error.message : String(error);
714
726
  ctx.ui.notify(`Failed to start merge: ${msg}`, "error");
715
727
  }
716
728
  }
@@ -753,7 +765,7 @@ async function handleRemove(
753
765
 
754
766
  ctx.ui.notify(`${CLR.ok("✓")} Worktree ${CLR.name(name)} removed ${CLR.muted("(branch deleted)")}.`, "info");
755
767
  } catch (error) {
756
- const msg = getErrorMessage(error);
768
+ const msg = error instanceof Error ? error.message : String(error);
757
769
  ctx.ui.notify(`Failed to remove worktree: ${msg}`, "error");
758
770
  }
759
771
  }
@@ -807,7 +819,7 @@ async function handleRemoveAll(
807
819
  if (failed.length > 0) lines.push(`${CLR.warn("✗")} Failed: ${failed.map(n => CLR.name(n)).join(", ")}`);
808
820
  ctx.ui.notify(lines.join("\n"), failed.length > 0 ? "warning" : "info");
809
821
  } catch (error) {
810
- const msg = getErrorMessage(error);
822
+ const msg = error instanceof Error ? error.message : String(error);
811
823
  ctx.ui.notify(`Failed to remove worktrees: ${msg}`, "error");
812
824
  }
813
825
  }
@@ -17,7 +17,6 @@
17
17
 
18
18
  import { existsSync, mkdirSync, readFileSync, realpathSync } from "node:fs";
19
19
  import { join, resolve, sep } from "node:path";
20
- import { gsdRoot } from "./paths.js";
21
20
  import { GSDError, GSD_PARSE_ERROR, GSD_STALE_STATE, GSD_LOCK_HELD, GSD_GIT_ERROR, GSD_MERGE_CONFLICT } from "./errors.js";
22
21
  import {
23
22
  nativeBranchDelete,
@@ -101,7 +100,7 @@ export function resolveGitDir(basePath: string): string {
101
100
  }
102
101
 
103
102
  export function worktreesDir(basePath: string): string {
104
- return join(gsdRoot(basePath), "worktrees");
103
+ return join(basePath, ".gsd", "worktrees");
105
104
  }
106
105
 
107
106
  export function worktreePath(basePath: string, name: string): string {
@@ -194,7 +193,7 @@ export function listWorktrees(basePath: string): WorktreeInfo[] {
194
193
  const seenRoots = new Set<string>();
195
194
  const worktreeRoots = baseVariants
196
195
  .map(baseVariant => {
197
- const path = join(gsdRoot(baseVariant), "worktrees");
196
+ const path = join(baseVariant, ".gsd", "worktrees");
198
197
  return {
199
198
  normalized: normalizePathForComparison(path),
200
199
  };