@staff0rd/assist 0.433.0 → 0.433.1

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.
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import { Command } from "commander";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "@staff0rd/assist",
9
- version: "0.433.0",
9
+ version: "0.433.1",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -8070,17 +8070,18 @@ function delay(ms) {
8070
8070
 
8071
8071
  // src/shared/createBundleHandler.ts
8072
8072
  import { createHash } from "crypto";
8073
- import { readFileSync as readFileSync18 } from "fs";
8073
+ import { readFileSync as readFileSync18, statSync as statSync2 } from "fs";
8074
8074
  import { dirname as dirname19, join as join22 } from "path";
8075
8075
  import { fileURLToPath as fileURLToPath4 } from "url";
8076
8076
  function createBundleHandler(importMetaUrl, bundlePath, contentType = "application/javascript") {
8077
- const dir = dirname19(fileURLToPath4(importMetaUrl));
8077
+ const file = join22(dirname19(fileURLToPath4(importMetaUrl)), bundlePath);
8078
8078
  let cache2;
8079
8079
  return (req, res) => {
8080
- if (!cache2) {
8081
- const body = readFileSync18(join22(dir, bundlePath), "utf8");
8080
+ const mtimeMs = statSync2(file).mtimeMs;
8081
+ if (cache2?.mtimeMs !== mtimeMs) {
8082
+ const body = readFileSync18(file, "utf8");
8082
8083
  const etag = `"${createHash("sha256").update(body).digest("hex").slice(0, 16)}"`;
8083
- cache2 = { body, etag };
8084
+ cache2 = { body, etag, mtimeMs };
8084
8085
  }
8085
8086
  const headers = {
8086
8087
  ETag: cache2.etag,
@@ -8700,14 +8701,14 @@ import { basename as basename6, join as join25 } from "path";
8700
8701
  import { promisify as promisify3 } from "util";
8701
8702
 
8702
8703
  // src/commands/sessions/web/findSynthesisForBranch.ts
8703
- import { existsSync as existsSync26, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
8704
+ import { existsSync as existsSync26, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
8704
8705
  import { basename as basename5, dirname as dirname20, join as join24 } from "path";
8705
8706
  function findSynthesisForBranch(repoReviewsDir, branch2) {
8706
8707
  const branchKeyPath = join24(repoReviewsDir, `${branch2}-`);
8707
8708
  const parent = dirname20(branchKeyPath);
8708
8709
  const branchPrefix = basename5(branchKeyPath);
8709
8710
  if (!existsSync26(parent)) return null;
8710
- const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join24(parent, name, "synthesis.md")).filter((path71) => existsSync26(path71)).map((path71) => ({ path: path71, mtime: statSync2(path71).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
8711
+ const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join24(parent, name, "synthesis.md")).filter((path71) => existsSync26(path71)).map((path71) => ({ path: path71, mtime: statSync3(path71).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
8711
8712
  return synthesisFiles[0]?.path ?? null;
8712
8713
  }
8713
8714
 
@@ -13295,7 +13296,7 @@ function getPinStatePath(pin) {
13295
13296
  }
13296
13297
 
13297
13298
  // src/commands/codeComment/sweepRestrictedDir.ts
13298
- import { readdirSync as readdirSync3, statSync as statSync3, unlinkSync as unlinkSync7 } from "fs";
13299
+ import { readdirSync as readdirSync3, statSync as statSync4, unlinkSync as unlinkSync7 } from "fs";
13299
13300
  import { join as join34 } from "path";
13300
13301
  var STALE_AFTER_MS = 30 * 60 * 1e3;
13301
13302
  function sweepRestrictedDir(dir = getRestrictedDir()) {
@@ -13309,7 +13310,7 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
13309
13310
  for (const entry of entries) {
13310
13311
  const path71 = join34(dir, entry);
13311
13312
  try {
13312
- if (statSync3(path71).mtimeMs < cutoff) unlinkSync7(path71);
13313
+ if (statSync4(path71).mtimeMs < cutoff) unlinkSync7(path71);
13313
13314
  } catch {
13314
13315
  continue;
13315
13316
  }
@@ -15282,7 +15283,7 @@ function collectAllDeps(node) {
15282
15283
  }
15283
15284
 
15284
15285
  // src/commands/dotnet/findContainingSolutions.ts
15285
- import { readdirSync as readdirSync6, readFileSync as readFileSync33, statSync as statSync4 } from "fs";
15286
+ import { readdirSync as readdirSync6, readFileSync as readFileSync33, statSync as statSync5 } from "fs";
15286
15287
  import path32 from "path";
15287
15288
  function findSlnFiles(dir, maxDepth, depth = 0) {
15288
15289
  if (depth > maxDepth) return [];
@@ -15298,7 +15299,7 @@ function findSlnFiles(dir, maxDepth, depth = 0) {
15298
15299
  continue;
15299
15300
  const full = path32.join(dir, entry);
15300
15301
  try {
15301
- const stat2 = statSync4(full);
15302
+ const stat2 = statSync5(full);
15302
15303
  if (stat2.isFile() && entry.endsWith(".sln")) {
15303
15304
  results.push(full);
15304
15305
  } else if (stat2.isDirectory()) {
@@ -16269,7 +16270,7 @@ import {
16269
16270
  readdirSync as readdirSync8,
16270
16271
  readFileSync as readFileSync35,
16271
16272
  rmSync as rmSync3,
16272
- statSync as statSync5
16273
+ statSync as statSync6
16273
16274
  } from "fs";
16274
16275
  import { basename as basename10, join as join45 } from "path";
16275
16276
 
@@ -16342,13 +16343,13 @@ async function migrateFile(orm, origin, file, createdAt) {
16342
16343
  async function migrateDiskHandovers(orm, origin, cwd = process.cwd()) {
16343
16344
  let migrated = 0;
16344
16345
  for (const file of collectMarkdown(getHandoversDir(cwd))) {
16345
- const createdAt = parseArchiveTimestamp(basename10(file)) ?? statSync5(file).mtime;
16346
+ const createdAt = parseArchiveTimestamp(basename10(file)) ?? statSync6(file).mtime;
16346
16347
  await migrateFile(orm, origin, file, createdAt);
16347
16348
  migrated++;
16348
16349
  }
16349
16350
  const handoverPath = getHandoverPath(cwd);
16350
16351
  if (existsSync42(handoverPath)) {
16351
- await migrateFile(orm, origin, handoverPath, statSync5(handoverPath).mtime);
16352
+ await migrateFile(orm, origin, handoverPath, statSync6(handoverPath).mtime);
16352
16353
  migrated++;
16353
16354
  }
16354
16355
  return migrated;
@@ -21808,11 +21809,11 @@ async function runBacklogSession(synthesisPath) {
21808
21809
  }
21809
21810
 
21810
21811
  // src/commands/review/cachedReviewerResult.ts
21811
- import { statSync as statSync6 } from "fs";
21812
+ import { statSync as statSync7 } from "fs";
21812
21813
  function cachedReviewerResult(name, outputPath) {
21813
21814
  let size;
21814
21815
  try {
21815
- size = statSync6(outputPath).size;
21816
+ size = statSync7(outputPath).size;
21816
21817
  } catch {
21817
21818
  return null;
21818
21819
  }
@@ -23523,14 +23524,14 @@ async function configure() {
23523
23524
  }
23524
23525
 
23525
23526
  // src/commands/transcript/list.ts
23526
- import { existsSync as existsSync48, readdirSync as readdirSync10, statSync as statSync7 } from "fs";
23527
+ import { existsSync as existsSync48, readdirSync as readdirSync10, statSync as statSync8 } from "fs";
23527
23528
  import { join as join56 } from "path";
23528
23529
  function list4() {
23529
23530
  const { vttDir } = getTranscriptConfig();
23530
23531
  if (!existsSync48(vttDir)) return;
23531
23532
  for (const entry of readdirSync10(vttDir)) {
23532
23533
  if (!entry.endsWith(".vtt")) continue;
23533
- if (statSync7(join56(vttDir, entry)).isDirectory()) continue;
23534
+ if (statSync8(join56(vttDir, entry)).isDirectory()) continue;
23534
23535
  console.log(entry);
23535
23536
  }
23536
23537
  }
@@ -24366,7 +24367,7 @@ async function auth() {
24366
24367
 
24367
24368
  // src/commands/roam/postRoamActivity.ts
24368
24369
  import { execFileSync as execFileSync9 } from "child_process";
24369
- import { readdirSync as readdirSync11, readFileSync as readFileSync46, statSync as statSync8 } from "fs";
24370
+ import { readdirSync as readdirSync11, readFileSync as readFileSync46, statSync as statSync9 } from "fs";
24370
24371
  import { join as join63 } from "path";
24371
24372
  function findPortFile(roamDir) {
24372
24373
  let entries;
@@ -24378,7 +24379,7 @@ function findPortFile(roamDir) {
24378
24379
  const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
24379
24380
  const path71 = join63(roamDir, name);
24380
24381
  try {
24381
- return { path: path71, mtimeMs: statSync8(path71).mtimeMs };
24382
+ return { path: path71, mtimeMs: statSync9(path71).mtimeMs };
24382
24383
  } catch {
24383
24384
  return void 0;
24384
24385
  }
@@ -25572,7 +25573,7 @@ function readDesignSystemPrompt() {
25572
25573
  import * as pty from "node-pty";
25573
25574
 
25574
25575
  // src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
25575
- import { chmodSync, existsSync as existsSync57, statSync as statSync9 } from "fs";
25576
+ import { chmodSync, existsSync as existsSync57, statSync as statSync10 } from "fs";
25576
25577
  import { createRequire as createRequire3 } from "module";
25577
25578
  import path59 from "path";
25578
25579
  var require4 = createRequire3(import.meta.url);
@@ -25588,7 +25589,7 @@ function ensureSpawnHelperExecutable() {
25588
25589
  "spawn-helper"
25589
25590
  );
25590
25591
  if (!existsSync57(helper)) return;
25591
- const mode = statSync9(helper).mode;
25592
+ const mode = statSync10(helper).mode;
25592
25593
  if ((mode & 73) === 0) chmodSync(helper, mode | 493);
25593
25594
  }
25594
25595
 
@@ -25648,7 +25649,13 @@ function spawnRun(opts) {
25648
25649
  return spawnPty(["assist", "run", opts.name, ...opts.args ?? []], opts.cwd);
25649
25650
  }
25650
25651
 
25651
- // src/commands/sessions/daemon/createSession.ts
25652
+ // src/commands/sessions/daemon/startOrHoldPty.ts
25653
+ function startOrHoldPty(start3, hold) {
25654
+ if (hold) return { pty: null, pendingStart: start3 };
25655
+ return { pty: start3() };
25656
+ }
25657
+
25658
+ // src/commands/sessions/daemon/sessionBase.ts
25652
25659
  function sessionBase(id, status3) {
25653
25660
  const startedAt = Date.now();
25654
25661
  return {
@@ -25662,27 +25669,32 @@ function sessionBase(id, status3) {
25662
25669
  scrollback: ""
25663
25670
  };
25664
25671
  }
25665
- function createSession(id, prompt, cwd, design, harness) {
25666
- if (harness === "pi") return createPiSession(id, prompt, cwd);
25672
+
25673
+ // src/commands/sessions/daemon/createSession.ts
25674
+ function createSession(id, prompt, cwd, design, harness, holdPty) {
25675
+ if (harness === "pi") return createPiSession(id, prompt, cwd, holdPty);
25667
25676
  const claudeSessionId = randomUUID5();
25668
25677
  return {
25669
25678
  ...sessionBase(id, prompt ? "running" : "waiting"),
25670
25679
  name: prompt?.slice(0, 40) || `Session ${id}`,
25671
25680
  commandType: "claude",
25672
- pty: spawnClaude2({ prompt, cwd, sessionId: id, claudeSessionId, design }),
25681
+ ...startOrHoldPty(
25682
+ () => spawnClaude2({ prompt, cwd, sessionId: id, claudeSessionId, design }),
25683
+ holdPty
25684
+ ),
25673
25685
  cwd,
25674
25686
  claudeSessionId,
25675
25687
  initialPrompt: prompt,
25676
25688
  design
25677
25689
  };
25678
25690
  }
25679
- function createPiSession(id, prompt, cwd) {
25691
+ function createPiSession(id, prompt, cwd, holdPty) {
25680
25692
  return {
25681
25693
  ...sessionBase(id, prompt ? "running" : "waiting"),
25682
25694
  name: prompt?.slice(0, 40) || `Session ${id}`,
25683
25695
  commandType: "claude",
25684
25696
  harness: "pi",
25685
- pty: spawnPi2({ prompt, cwd, sessionId: id }),
25697
+ ...startOrHoldPty(() => spawnPi2({ prompt, cwd, sessionId: id }), holdPty),
25686
25698
  cwd,
25687
25699
  initialPrompt: prompt
25688
25700
  };
@@ -26373,12 +26385,12 @@ function shouldAutoDismiss(session, exitCode) {
26373
26385
  }
26374
26386
 
26375
26387
  // src/commands/sessions/daemon/shouldAutoRun.ts
26376
- function shouldAutoRun(session) {
26388
+ function shouldAutoRun(session, status3 = session.status) {
26377
26389
  if (!session.autoRun) return { run: false, reason: null };
26378
- if (session.status !== "done")
26390
+ if (status3 !== "done")
26379
26391
  return {
26380
26392
  run: false,
26381
- reason: `session status is "${session.status}", not "done"`
26393
+ reason: `session status is "${status3}", not "done"`
26382
26394
  };
26383
26395
  if (session.commandType !== "assist")
26384
26396
  return {
@@ -26404,7 +26416,8 @@ function shouldAutoRun(session) {
26404
26416
  function applyStatusChange(session, status3, exitCode, dismiss, notify2, reuseForRun) {
26405
26417
  if (session.status === status3) return;
26406
26418
  const deps2 = { dismiss, notify: notify2, reuseForRun };
26407
- if (status3 === "done" && session.worktree) {
26419
+ const chainsToNextRun = shouldAutoRun(session, status3).run;
26420
+ if (status3 === "done" && session.worktree && !chainsToNextRun) {
26408
26421
  void resolveDoneDurability(
26409
26422
  session,
26410
26423
  () => finishStatusChange(session, "done", exitCode, deps2),
@@ -26439,6 +26452,25 @@ function makeStatusChangeHandler(dismiss, notify2, reuseForRun) {
26439
26452
  return (s, status3, exitCode) => applyStatusChange(s, status3, exitCode, dismiss, notify2, reuseForRun);
26440
26453
  }
26441
26454
 
26455
+ // src/commands/sessions/daemon/emitSessionOutput.ts
26456
+ var MAX_SCROLLBACK = 256 * 1024;
26457
+ function emitSessionOutput(session, clients, data) {
26458
+ session.scrollback += data;
26459
+ if (session.scrollback.length > MAX_SCROLLBACK) {
26460
+ session.scrollback = session.scrollback.slice(-MAX_SCROLLBACK);
26461
+ }
26462
+ broadcast(clients, { type: "output", sessionId: session.id, data });
26463
+ }
26464
+
26465
+ // src/commands/sessions/daemon/exitReason.ts
26466
+ import { existsSync as existsSync60 } from "fs";
26467
+ function exitReason(session, exitCode) {
26468
+ const base = `process exited with code ${exitCode}`;
26469
+ if (session.cwd && !existsSync60(session.cwd))
26470
+ return `${base}: working directory ${session.cwd} no longer exists`;
26471
+ return base;
26472
+ }
26473
+
26442
26474
  // src/commands/sessions/daemon/handleFailedResume.ts
26443
26475
  function handleFailedResume(session, exitCode, onStatusChange) {
26444
26476
  const failed2 = session.restored === true && exitCode !== 0 && session.scrollback.length === 0;
@@ -26452,7 +26484,7 @@ function handleFailedResume(session, exitCode, onStatusChange) {
26452
26484
  }
26453
26485
 
26454
26486
  // src/commands/sessions/daemon/watchActivity.ts
26455
- import { existsSync as existsSync60, mkdirSync as mkdirSync25, watch as watch2 } from "fs";
26487
+ import { existsSync as existsSync61, mkdirSync as mkdirSync25, watch as watch2 } from "fs";
26456
26488
  import { dirname as dirname29 } from "path";
26457
26489
 
26458
26490
  // src/commands/sessions/daemon/applyReviewPause.ts
@@ -26533,7 +26565,7 @@ function watchActivity(session, notify2, onClaudeSessionId) {
26533
26565
  if (timer) clearTimeout(timer);
26534
26566
  timer = setTimeout(read, DEBOUNCE_MS2);
26535
26567
  });
26536
- if (existsSync60(path71)) read();
26568
+ if (existsSync61(path71)) read();
26537
26569
  }
26538
26570
  function refreshActivity(session) {
26539
26571
  if (session.commandType !== "assist" || !session.cwd) return;
@@ -26582,7 +26614,7 @@ function handlePtyExit(session, exitCode, onStatusChange) {
26582
26614
  if (handleFailedResume(session, exitCode, onStatusChange)) return;
26583
26615
  const priorStatus = session.status;
26584
26616
  if (exitCode !== 0) {
26585
- session.error = `process exited with code ${exitCode}`;
26617
+ session.error = exitReason(session, exitCode);
26586
26618
  daemonLog(
26587
26619
  `session ${session.id} ("${session.name}") pty exited with code ${exitCode} from status "${priorStatus}" \u2014 unexpected exit, marking error`
26588
26620
  );
@@ -26597,21 +26629,23 @@ function handlePtyExit(session, exitCode, onStatusChange) {
26597
26629
  }
26598
26630
 
26599
26631
  // src/commands/sessions/daemon/wirePtyEvents.ts
26600
- var MAX_SCROLLBACK = 256 * 1024;
26601
- function appendScrollback(session, data) {
26602
- session.scrollback += data;
26603
- if (session.scrollback.length > MAX_SCROLLBACK) {
26604
- session.scrollback = session.scrollback.slice(-MAX_SCROLLBACK);
26605
- }
26606
- }
26607
26632
  function wirePtyEvents(session, clients, onStatusChange) {
26608
26633
  if (!session.pty) return;
26609
- session.pty.onData((data) => {
26610
- appendScrollback(session, data);
26611
- broadcast(clients, { type: "output", sessionId: session.id, data });
26634
+ session.pty.onData((data) => emitSessionOutput(session, clients, data));
26635
+ session.pty.onExit(({ exitCode }) => {
26636
+ handlePtyExit(session, exitCode, onStatusChange);
26637
+ reportSilentFailure(session, clients);
26612
26638
  });
26613
- session.pty.onExit(
26614
- ({ exitCode }) => handlePtyExit(session, exitCode, onStatusChange)
26639
+ }
26640
+ function reportSilentFailure(session, clients) {
26641
+ if (session.status !== "error" || !session.error) return;
26642
+ if (session.scrollback.length > 0) return;
26643
+ emitSessionOutput(
26644
+ session,
26645
+ clients,
26646
+ `\r
26647
+ \x1B[31m${session.error}\x1B[0m\r
26648
+ `
26615
26649
  );
26616
26650
  }
26617
26651
 
@@ -27164,6 +27198,207 @@ function restoreAll(spawn12, sessions) {
27164
27198
  });
27165
27199
  }
27166
27200
 
27201
+ // src/commands/sessions/daemon/worktree/rearmStoppedSessions.ts
27202
+ function rearmStoppedSessions(sessions, notify2) {
27203
+ for (const s of sessions.values()) {
27204
+ if (s.status !== "stopped" || !s.worktree) continue;
27205
+ void resolveDoneDurability(
27206
+ s,
27207
+ () => {
27208
+ if (dismissSession(sessions, s.id)) notify2();
27209
+ },
27210
+ notify2
27211
+ );
27212
+ }
27213
+ }
27214
+
27215
+ // src/commands/sessions/daemon/worktree/reconcileWorktreesOnRestore.ts
27216
+ import { existsSync as existsSync65 } from "fs";
27217
+ import { basename as basename14 } from "path";
27218
+
27219
+ // src/commands/sessions/daemon/worktree/worktreeConfigFor.ts
27220
+ var DISABLED = {
27221
+ enabled: false,
27222
+ install: true,
27223
+ copy: [".env", "settings.local.json", ".claude/settings.local.json"]
27224
+ };
27225
+ function worktreeConfigFor(cwd) {
27226
+ try {
27227
+ return loadConfigFrom(cwd).worktree ?? DISABLED;
27228
+ } catch {
27229
+ return DISABLED;
27230
+ }
27231
+ }
27232
+
27233
+ // src/commands/sessions/daemon/worktree/detectExistingWorktree.ts
27234
+ function detectExistingWorktree(cwd) {
27235
+ const repoRoot = findRepoRoot(cwd) ?? cwd;
27236
+ if (!worktreeConfigFor(repoRoot).enabled) return void 0;
27237
+ const clone = mainWorktree(repoRoot);
27238
+ if (clone && clone !== repoRoot) return { path: repoRoot, clone };
27239
+ return void 0;
27240
+ }
27241
+
27242
+ // src/commands/sessions/daemon/worktree/seedWorktree.ts
27243
+ import { execFile as execFile8 } from "child_process";
27244
+ import { copyFileSync, existsSync as existsSync64, mkdirSync as mkdirSync26 } from "fs";
27245
+ import { dirname as dirname30, join as join71 } from "path";
27246
+
27247
+ // src/commands/sessions/daemon/worktree/resolveInstallCommand.ts
27248
+ import { existsSync as existsSync63 } from "fs";
27249
+ import { join as join70 } from "path";
27250
+ function detectInstallCommand(repoRoot) {
27251
+ if (!existsSync63(join70(repoRoot, "package.json"))) return null;
27252
+ if (existsSync63(join70(repoRoot, "pnpm-lock.yaml"))) return "pnpm install";
27253
+ if (existsSync63(join70(repoRoot, "yarn.lock"))) return "yarn install";
27254
+ if (existsSync63(join70(repoRoot, "bun.lockb"))) return "bun install";
27255
+ return "npm install";
27256
+ }
27257
+ function resolveInstallCommand(repoRoot, install) {
27258
+ if (install === false) return null;
27259
+ if (typeof install === "string") return install;
27260
+ return detectInstallCommand(repoRoot);
27261
+ }
27262
+
27263
+ // src/commands/sessions/daemon/worktree/seedWorktree.ts
27264
+ function seedWorktree(worktreePath, clone, onSeeded = () => {
27265
+ }) {
27266
+ const cfg = worktreeConfigFor(clone);
27267
+ copyConfigFiles(worktreePath, clone, cfg.copy);
27268
+ runInstall(worktreePath, clone, cfg.install, onSeeded);
27269
+ }
27270
+ function copyConfigFiles(worktreePath, clone, copy) {
27271
+ for (const rel of copy) {
27272
+ const src = join71(clone, rel);
27273
+ if (!existsSync64(src)) continue;
27274
+ const dest = join71(worktreePath, rel);
27275
+ try {
27276
+ mkdirSync26(dirname30(dest), { recursive: true });
27277
+ copyFileSync(src, dest);
27278
+ daemonLog(`worktree ${worktreePath} seeded ${rel}`);
27279
+ } catch (error) {
27280
+ daemonLog(
27281
+ `worktree ${worktreePath} failed to seed ${rel}: ${message(error)}`
27282
+ );
27283
+ }
27284
+ }
27285
+ }
27286
+ function runInstall(worktreePath, clone, install, onSeeded) {
27287
+ const command = resolveInstallCommand(clone, install);
27288
+ if (!command) {
27289
+ onSeeded();
27290
+ return;
27291
+ }
27292
+ const windows = /^[A-Za-z]:[\\/]/.test(worktreePath);
27293
+ const shell = windows ? "cmd.exe" : process.env.SHELL ?? "bash";
27294
+ const shellArgs = windows ? ["/c", command] : ["-l", "-c", command];
27295
+ daemonLog(`worktree ${worktreePath} installing deps: ${command}`);
27296
+ execFile8(shell, shellArgs, { cwd: worktreePath }, (error) => {
27297
+ daemonLog(
27298
+ error ? `worktree ${worktreePath} install failed: ${error.message}` : `worktree ${worktreePath} install complete`
27299
+ );
27300
+ onSeeded();
27301
+ });
27302
+ }
27303
+ function message(error) {
27304
+ return error instanceof Error ? error.message : String(error);
27305
+ }
27306
+
27307
+ // src/commands/sessions/daemon/worktree/bindNewWorktree.ts
27308
+ function boundTreeRoots(sessions) {
27309
+ const roots = /* @__PURE__ */ new Set();
27310
+ for (const session of sessions.values())
27311
+ if (session.cwd) roots.add(findRepoRoot(session.cwd) ?? session.cwd);
27312
+ return roots;
27313
+ }
27314
+ function bindNewWorktree(session, alloc, notify2, startHeld = () => {
27315
+ }) {
27316
+ if (alloc.kind !== "worktree" || !alloc.cwd || !alloc.clone || !session)
27317
+ return;
27318
+ session.worktree = { path: alloc.cwd, clone: alloc.clone };
27319
+ if (alloc.created)
27320
+ seedWorktree(alloc.cwd, alloc.clone, () => startHeld(session));
27321
+ notify2();
27322
+ }
27323
+ function bindRestoredWorktrees(sessions) {
27324
+ for (const session of sessions.values()) {
27325
+ if (session.worktree || !session.cwd) continue;
27326
+ const worktree = detectExistingWorktree(session.cwd);
27327
+ if (worktree) session.worktree = worktree;
27328
+ }
27329
+ }
27330
+ function bindResumedWorktree(session, cwd, notify2) {
27331
+ if (!session) return;
27332
+ const worktree = detectExistingWorktree(cwd);
27333
+ if (!worktree) return;
27334
+ session.worktree = worktree;
27335
+ notify2();
27336
+ }
27337
+
27338
+ // src/commands/sessions/daemon/worktree/readWorktreeRegistry.ts
27339
+ var REGISTRY_FILE = "worktrees.json";
27340
+ function readWorktreeRegistry() {
27341
+ const data = loadJson(REGISTRY_FILE);
27342
+ return Object.entries(data).map(([path71, record]) => ({ path: path71, ...record }));
27343
+ }
27344
+ function recordWorktree(path71, clone, origin) {
27345
+ const data = loadJson(REGISTRY_FILE);
27346
+ data[path71] = { clone, origin };
27347
+ saveJson(REGISTRY_FILE, data);
27348
+ }
27349
+
27350
+ // src/commands/sessions/daemon/worktree/reconcileWorktreesOnRestore.ts
27351
+ function reconcileWorktreesOnRestore(sessions) {
27352
+ bindRestoredWorktrees(sessions);
27353
+ void pruneWorktrees([...sessions.values()].map((s) => s.cwd));
27354
+ }
27355
+ async function pruneWorktrees(liveCwds) {
27356
+ const accounted = /* @__PURE__ */ new Set();
27357
+ for (const cwd of liveCwds) if (cwd) accounted.add(cwd);
27358
+ for (const s of loadPersistedSessions()) accounted.add(s.cwd);
27359
+ const clonesToPrune = /* @__PURE__ */ new Set();
27360
+ const orphanBranches = [];
27361
+ for (const { path: path71, clone } of readWorktreeRegistry()) {
27362
+ if (accounted.has(path71)) continue;
27363
+ if (!existsSync65(path71)) {
27364
+ clonesToPrune.add(clone);
27365
+ orphanBranches.push({ clone, branch: basename14(path71) });
27366
+ continue;
27367
+ }
27368
+ daemonLog(`worktree ${path71} orphaned across restart; reconciling`);
27369
+ await reapWorktree(path71);
27370
+ }
27371
+ for (const clone of clonesToPrune) {
27372
+ if (!existsSync65(clone)) continue;
27373
+ try {
27374
+ await git3(clone, ["worktree", "prune"]);
27375
+ daemonLog(`worktree bookkeeping pruned for clone ${clone}`);
27376
+ } catch {
27377
+ }
27378
+ }
27379
+ for (const { clone, branch: branch2 } of orphanBranches)
27380
+ if (existsSync65(clone)) await pruneStaleWorktreeBranch(clone, branch2);
27381
+ }
27382
+ async function pruneStaleWorktreeBranch(clone, branch2) {
27383
+ if (!listLocalBranches(clone).includes(branch2)) return;
27384
+ try {
27385
+ await git3(clone, ["branch", "-d", branch2]);
27386
+ daemonLog(`stale worktree branch ${branch2} pruned from clone ${clone}`);
27387
+ } catch {
27388
+ daemonLog(
27389
+ `stale worktree branch ${branch2} retained (unmerged; surfaced not destroyed) in clone ${clone}`
27390
+ );
27391
+ }
27392
+ }
27393
+
27394
+ // src/commands/sessions/daemon/restoreAllSessions.ts
27395
+ function restoreAllSessions(spawnWith, sessions, notify2) {
27396
+ const names = restoreAll(spawnWith, sessions);
27397
+ reconcileWorktreesOnRestore(sessions);
27398
+ rearmStoppedSessions(sessions, notify2);
27399
+ return names;
27400
+ }
27401
+
27167
27402
  // src/commands/sessions/daemon/retrySession.ts
27168
27403
  function retrySession(session, clients, onStatusChange) {
27169
27404
  const respawn = respawnThunk(session);
@@ -27270,8 +27505,44 @@ function shutdownSessions(sessions) {
27270
27505
  }
27271
27506
  }
27272
27507
 
27508
+ // src/commands/sessions/daemon/startHeldSession.ts
27509
+ function startHeldSession(session, sessions, clients, onStatusChange, notify2) {
27510
+ const start3 = session.pendingStart;
27511
+ if (!start3) return;
27512
+ session.pendingStart = void 0;
27513
+ if (sessions.get(session.id) !== session) {
27514
+ daemonLog(
27515
+ `session ${session.id} not started after seeding: card is gone (${session.worktree?.path ?? "no worktree"})`
27516
+ );
27517
+ return;
27518
+ }
27519
+ session.startedAt = Date.now();
27520
+ if (session.status === "running") session.runningSince = session.startedAt;
27521
+ session.pty = start3();
27522
+ if (session.cols && session.rows)
27523
+ try {
27524
+ session.pty?.resize(session.cols, session.rows);
27525
+ } catch {
27526
+ }
27527
+ wirePtyEvents(session, clients, onStatusChange);
27528
+ daemonLog(
27529
+ `session ${session.id} started once worktree ${session.worktree?.path ?? session.cwd} finished seeding`
27530
+ );
27531
+ notify2();
27532
+ }
27533
+
27534
+ // src/commands/sessions/daemon/treeSpawnContext.ts
27535
+ function treeSpawnContext(sessions, spawnWith, notify2, clients, onStatusChange) {
27536
+ return {
27537
+ sessions,
27538
+ spawnWith,
27539
+ notify: notify2,
27540
+ startHeld: (session) => startHeldSession(session, sessions, clients, onStatusChange, notify2)
27541
+ };
27542
+ }
27543
+
27273
27544
  // src/commands/sessions/daemon/watchTranscript.ts
27274
- import { existsSync as existsSync62, watch as watch3 } from "fs";
27545
+ import { existsSync as existsSync66, watch as watch3 } from "fs";
27275
27546
 
27276
27547
  // src/commands/sessions/daemon/reconcileTranscriptStatus.ts
27277
27548
  async function resolveTranscriptPath(session) {
@@ -27306,7 +27577,7 @@ function watchTranscript(session, onStatusChange) {
27306
27577
  if (!session.cwd || !session.claudeSessionId) return;
27307
27578
  if (session.watchedTranscriptId === session.claudeSessionId) return;
27308
27579
  const dir = projectDirForCwd(session.cwd);
27309
- if (!existsSync62(dir)) return;
27580
+ if (!existsSync66(dir)) return;
27310
27581
  if (session.transcriptWatcher) {
27311
27582
  session.transcriptWatcher.close();
27312
27583
  session.transcriptWatcher = void 0;
@@ -27457,13 +27728,13 @@ async function defaultConnect() {
27457
27728
  }
27458
27729
 
27459
27730
  // src/commands/sessions/daemon/hasPersistedWindowsSessions.ts
27460
- import { existsSync as existsSync63, readFileSync as readFileSync49 } from "fs";
27731
+ import { existsSync as existsSync67, readFileSync as readFileSync49 } from "fs";
27461
27732
  import { posix } from "path";
27462
27733
  function hasPersistedWindowsSessions() {
27463
27734
  const sessionsFile = windowsSessionsFileFromWsl();
27464
27735
  if (!sessionsFile) return false;
27465
27736
  try {
27466
- if (!existsSync63(sessionsFile)) return false;
27737
+ if (!existsSync67(sessionsFile)) return false;
27467
27738
  const data = JSON.parse(readFileSync49(sessionsFile, "utf8"));
27468
27739
  return Array.isArray(data) && data.length > 0;
27469
27740
  } catch (error) {
@@ -27590,7 +27861,7 @@ function replayScrollback2(state, client) {
27590
27861
  data: stripReplayQueries(data)
27591
27862
  });
27592
27863
  }
27593
- function appendScrollback2(state, sessionId, data) {
27864
+ function appendScrollback(state, sessionId, data) {
27594
27865
  const next3 = (state.scrollback.get(sessionId) ?? "") + data;
27595
27866
  state.scrollback.set(
27596
27867
  sessionId,
@@ -27690,7 +27961,7 @@ function handleCreated(state, msg) {
27690
27961
  function handleOutput(state, msg) {
27691
27962
  const sessionId = nsId(msg);
27692
27963
  const data = msg.data;
27693
- appendScrollback2(state, sessionId, data);
27964
+ appendScrollback(state, sessionId, data);
27694
27965
  state.broadcast({ type: "output", sessionId, data });
27695
27966
  }
27696
27967
  function relayWithSessionId(state, msg) {
@@ -28006,194 +28277,8 @@ var WindowsProxy = class {
28006
28277
  }
28007
28278
  };
28008
28279
 
28009
- // src/commands/sessions/daemon/worktree/reconcileWorktreesOnRestore.ts
28010
- import { existsSync as existsSync66 } from "fs";
28011
- import { basename as basename14 } from "path";
28012
-
28013
- // src/commands/sessions/daemon/worktree/worktreeConfigFor.ts
28014
- var DISABLED = {
28015
- enabled: false,
28016
- install: true,
28017
- copy: [".env", "settings.local.json", ".claude/settings.local.json"]
28018
- };
28019
- function worktreeConfigFor(cwd) {
28020
- try {
28021
- return loadConfigFrom(cwd).worktree ?? DISABLED;
28022
- } catch {
28023
- return DISABLED;
28024
- }
28025
- }
28026
-
28027
- // src/commands/sessions/daemon/worktree/detectExistingWorktree.ts
28028
- function detectExistingWorktree(cwd) {
28029
- const repoRoot = findRepoRoot(cwd) ?? cwd;
28030
- if (!worktreeConfigFor(repoRoot).enabled) return void 0;
28031
- const clone = mainWorktree(repoRoot);
28032
- if (clone && clone !== repoRoot) return { path: repoRoot, clone };
28033
- return void 0;
28034
- }
28035
-
28036
- // src/commands/sessions/daemon/worktree/seedWorktree.ts
28037
- import { execFile as execFile8 } from "child_process";
28038
- import { copyFileSync, existsSync as existsSync65, mkdirSync as mkdirSync26 } from "fs";
28039
- import { dirname as dirname30, join as join71 } from "path";
28040
-
28041
- // src/commands/sessions/daemon/worktree/resolveInstallCommand.ts
28042
- import { existsSync as existsSync64 } from "fs";
28043
- import { join as join70 } from "path";
28044
- function detectInstallCommand(repoRoot) {
28045
- if (!existsSync64(join70(repoRoot, "package.json"))) return null;
28046
- if (existsSync64(join70(repoRoot, "pnpm-lock.yaml"))) return "pnpm install";
28047
- if (existsSync64(join70(repoRoot, "yarn.lock"))) return "yarn install";
28048
- if (existsSync64(join70(repoRoot, "bun.lockb"))) return "bun install";
28049
- return "npm install";
28050
- }
28051
- function resolveInstallCommand(repoRoot, install) {
28052
- if (install === false) return null;
28053
- if (typeof install === "string") return install;
28054
- return detectInstallCommand(repoRoot);
28055
- }
28056
-
28057
- // src/commands/sessions/daemon/worktree/seedWorktree.ts
28058
- function seedWorktree(worktreePath, clone) {
28059
- const cfg = worktreeConfigFor(clone);
28060
- copyConfigFiles(worktreePath, clone, cfg.copy);
28061
- runInstall(worktreePath, clone, cfg.install);
28062
- }
28063
- function copyConfigFiles(worktreePath, clone, copy) {
28064
- for (const rel of copy) {
28065
- const src = join71(clone, rel);
28066
- if (!existsSync65(src)) continue;
28067
- const dest = join71(worktreePath, rel);
28068
- try {
28069
- mkdirSync26(dirname30(dest), { recursive: true });
28070
- copyFileSync(src, dest);
28071
- daemonLog(`worktree ${worktreePath} seeded ${rel}`);
28072
- } catch (error) {
28073
- daemonLog(
28074
- `worktree ${worktreePath} failed to seed ${rel}: ${message(error)}`
28075
- );
28076
- }
28077
- }
28078
- }
28079
- function runInstall(worktreePath, clone, install) {
28080
- const command = resolveInstallCommand(clone, install);
28081
- if (!command) return;
28082
- const windows = /^[A-Za-z]:[\\/]/.test(worktreePath);
28083
- const shell = windows ? "cmd.exe" : process.env.SHELL ?? "bash";
28084
- const shellArgs = windows ? ["/c", command] : ["-l", "-c", command];
28085
- daemonLog(`worktree ${worktreePath} installing deps: ${command}`);
28086
- execFile8(shell, shellArgs, { cwd: worktreePath }, (error) => {
28087
- daemonLog(
28088
- error ? `worktree ${worktreePath} install failed: ${error.message}` : `worktree ${worktreePath} install complete`
28089
- );
28090
- });
28091
- }
28092
- function message(error) {
28093
- return error instanceof Error ? error.message : String(error);
28094
- }
28095
-
28096
- // src/commands/sessions/daemon/worktree/bindNewWorktree.ts
28097
- function boundTreeRoots(sessions) {
28098
- const roots = /* @__PURE__ */ new Set();
28099
- for (const session of sessions.values())
28100
- if (session.cwd) roots.add(findRepoRoot(session.cwd) ?? session.cwd);
28101
- return roots;
28102
- }
28103
- function bindNewWorktree(session, alloc, notify2) {
28104
- if (alloc.kind !== "worktree" || !alloc.cwd || !alloc.clone || !session)
28105
- return;
28106
- session.worktree = { path: alloc.cwd, clone: alloc.clone };
28107
- if (alloc.created) seedWorktree(alloc.cwd, alloc.clone);
28108
- notify2();
28109
- }
28110
- function bindRestoredWorktrees(sessions) {
28111
- for (const session of sessions.values()) {
28112
- if (session.worktree || !session.cwd) continue;
28113
- const worktree = detectExistingWorktree(session.cwd);
28114
- if (worktree) session.worktree = worktree;
28115
- }
28116
- }
28117
- function bindResumedWorktree(session, cwd, notify2) {
28118
- if (!session) return;
28119
- const worktree = detectExistingWorktree(cwd);
28120
- if (!worktree) return;
28121
- session.worktree = worktree;
28122
- notify2();
28123
- }
28124
-
28125
- // src/commands/sessions/daemon/worktree/readWorktreeRegistry.ts
28126
- var REGISTRY_FILE = "worktrees.json";
28127
- function readWorktreeRegistry() {
28128
- const data = loadJson(REGISTRY_FILE);
28129
- return Object.entries(data).map(([path71, record]) => ({ path: path71, ...record }));
28130
- }
28131
- function recordWorktree(path71, clone, origin) {
28132
- const data = loadJson(REGISTRY_FILE);
28133
- data[path71] = { clone, origin };
28134
- saveJson(REGISTRY_FILE, data);
28135
- }
28136
-
28137
- // src/commands/sessions/daemon/worktree/reconcileWorktreesOnRestore.ts
28138
- function reconcileWorktreesOnRestore(sessions) {
28139
- bindRestoredWorktrees(sessions);
28140
- void pruneWorktrees([...sessions.values()].map((s) => s.cwd));
28141
- }
28142
- async function pruneWorktrees(liveCwds) {
28143
- const accounted = /* @__PURE__ */ new Set();
28144
- for (const cwd of liveCwds) if (cwd) accounted.add(cwd);
28145
- for (const s of loadPersistedSessions()) accounted.add(s.cwd);
28146
- const clonesToPrune = /* @__PURE__ */ new Set();
28147
- const orphanBranches = [];
28148
- for (const { path: path71, clone } of readWorktreeRegistry()) {
28149
- if (accounted.has(path71)) continue;
28150
- if (!existsSync66(path71)) {
28151
- clonesToPrune.add(clone);
28152
- orphanBranches.push({ clone, branch: basename14(path71) });
28153
- continue;
28154
- }
28155
- daemonLog(`worktree ${path71} orphaned across restart; reconciling`);
28156
- await reapWorktree(path71);
28157
- }
28158
- for (const clone of clonesToPrune) {
28159
- if (!existsSync66(clone)) continue;
28160
- try {
28161
- await git3(clone, ["worktree", "prune"]);
28162
- daemonLog(`worktree bookkeeping pruned for clone ${clone}`);
28163
- } catch {
28164
- }
28165
- }
28166
- for (const { clone, branch: branch2 } of orphanBranches)
28167
- if (existsSync66(clone)) await pruneStaleWorktreeBranch(clone, branch2);
28168
- }
28169
- async function pruneStaleWorktreeBranch(clone, branch2) {
28170
- if (!listLocalBranches(clone).includes(branch2)) return;
28171
- try {
28172
- await git3(clone, ["branch", "-d", branch2]);
28173
- daemonLog(`stale worktree branch ${branch2} pruned from clone ${clone}`);
28174
- } catch {
28175
- daemonLog(
28176
- `stale worktree branch ${branch2} retained (unmerged; surfaced not destroyed) in clone ${clone}`
28177
- );
28178
- }
28179
- }
28180
-
28181
- // src/commands/sessions/daemon/worktree/rearmStoppedSessions.ts
28182
- function rearmStoppedSessions(sessions, notify2) {
28183
- for (const s of sessions.values()) {
28184
- if (s.status !== "stopped" || !s.worktree) continue;
28185
- void resolveDoneDurability(
28186
- s,
28187
- () => {
28188
- if (dismissSession(sessions, s.id)) notify2();
28189
- },
28190
- notify2
28191
- );
28192
- }
28193
- }
28194
-
28195
28280
  // src/commands/sessions/daemon/createAssistSession.ts
28196
- function createAssistSession(id, assistArgs, cwd, meta) {
28281
+ function createAssistSession(id, assistArgs, cwd, meta, holdPty) {
28197
28282
  const startedAt = Date.now();
28198
28283
  return {
28199
28284
  id,
@@ -28205,7 +28290,10 @@ function createAssistSession(id, assistArgs, cwd, meta) {
28205
28290
  startedAt,
28206
28291
  runningMs: 0,
28207
28292
  runningSince: startedAt,
28208
- pty: spawnPty(["assist", ...assistArgs], cwd, id),
28293
+ ...startOrHoldPty(
28294
+ () => spawnPty(["assist", ...assistArgs], cwd, id),
28295
+ holdPty
28296
+ ),
28209
28297
  scrollback: "",
28210
28298
  assistArgs,
28211
28299
  cwd
@@ -28234,7 +28322,7 @@ function resumeSession(id, sessionId, cwd, name) {
28234
28322
  }
28235
28323
 
28236
28324
  // src/commands/sessions/daemon/worktree/createWorktree.ts
28237
- import { existsSync as existsSync67 } from "fs";
28325
+ import { existsSync as existsSync68 } from "fs";
28238
28326
  import { basename as basename16, dirname as dirname31 } from "path";
28239
28327
 
28240
28328
  // src/commands/sessions/daemon/worktree/planAllocation.ts
@@ -28259,7 +28347,7 @@ function createWorktree(clone, root, boundTreeRoots2) {
28259
28347
  const path71 = nextWorktreePath(
28260
28348
  clone,
28261
28349
  base,
28262
- (candidate) => registered.has(candidate) || existsSync67(candidate) || boundTreeRoots2.has(candidate) || branches.has(basename16(candidate))
28350
+ (candidate) => registered.has(candidate) || existsSync68(candidate) || boundTreeRoots2.has(candidate) || branches.has(basename16(candidate))
28263
28351
  );
28264
28352
  const trunk = cloneTrunkBranch(clone);
28265
28353
  gitSync(clone, ["config", "push.default", "upstream"]);
@@ -28311,22 +28399,23 @@ function allocateTree(requestedCwd, boundTreeRoots2) {
28311
28399
  // src/commands/sessions/daemon/worktree/spawnInTree.ts
28312
28400
  function allocateAndBind(ctx, cwd, create) {
28313
28401
  const alloc = allocateTree(cwd, boundTreeRoots(ctx.sessions));
28314
- const id = ctx.spawnWith((sid) => create(sid, alloc.cwd));
28315
- bindNewWorktree(ctx.sessions.get(id), alloc, ctx.notify);
28402
+ const needsSeeding = alloc.kind === "worktree" && alloc.created === true;
28403
+ const id = ctx.spawnWith((sid) => create(sid, alloc.cwd, needsSeeding));
28404
+ bindNewWorktree(ctx.sessions.get(id), alloc, ctx.notify, ctx.startHeld);
28316
28405
  return id;
28317
28406
  }
28318
28407
  function spawnInTree(ctx, prompt, cwd, design, harness) {
28319
28408
  return allocateAndBind(
28320
28409
  ctx,
28321
28410
  cwd,
28322
- (sid, resolvedCwd) => createSession(sid, prompt, resolvedCwd, design, harness)
28411
+ (sid, resolvedCwd, holdUntilSeeded) => createSession(sid, prompt, resolvedCwd, design, harness, holdUntilSeeded)
28323
28412
  );
28324
28413
  }
28325
28414
  function spawnAssistInTree(ctx, assistArgs, cwd, meta) {
28326
28415
  return allocateAndBind(
28327
28416
  ctx,
28328
28417
  cwd,
28329
- (sid, resolvedCwd) => createAssistSession(sid, assistArgs, resolvedCwd, meta)
28418
+ (sid, resolvedCwd, holdUntilSeeded) => createAssistSession(sid, assistArgs, resolvedCwd, meta, holdUntilSeeded)
28330
28419
  );
28331
28420
  }
28332
28421
  function resumeInTree(ctx, sessionId, cwd, name) {
@@ -28434,10 +28523,7 @@ var SessionManager = class {
28434
28523
  );
28435
28524
  }
28436
28525
  restore() {
28437
- const names = restoreAll(this.spawnWith, this.sessions);
28438
- reconcileWorktreesOnRestore(this.sessions);
28439
- rearmStoppedSessions(this.sessions, this.notify);
28440
- return names;
28526
+ return restoreAllSessions(this.spawnWith, this.sessions, this.notify);
28441
28527
  }
28442
28528
  drain = () => drainSessions(this.sessions, this.notify);
28443
28529
  add(session) {
@@ -28448,11 +28534,13 @@ var SessionManager = class {
28448
28534
  }
28449
28535
  spawnWith = (create) => this.add(create(sessionLimits.nextId(this.sessions.size, this.idCounter)));
28450
28536
  treeCtx() {
28451
- return {
28452
- sessions: this.sessions,
28453
- spawnWith: this.spawnWith,
28454
- notify: this.notify
28455
- };
28537
+ return treeSpawnContext(
28538
+ this.sessions,
28539
+ this.spawnWith,
28540
+ this.notify,
28541
+ this.clients,
28542
+ this.onStatusChange
28543
+ );
28456
28544
  }
28457
28545
  spawn(prompt, cwd, design, harness) {
28458
28546
  return spawnInTree(this.treeCtx(), prompt, cwd, design, harness);
@@ -29264,13 +29352,13 @@ function buildLimitsSegment(rateLimits) {
29264
29352
  }
29265
29353
 
29266
29354
  // src/commands/readGitBranch.ts
29267
- import { readFileSync as readFileSync52, statSync as statSync11 } from "fs";
29355
+ import { readFileSync as readFileSync52, statSync as statSync12 } from "fs";
29268
29356
  import { isAbsolute as isAbsolute2, join as join73, resolve as resolve17 } from "path";
29269
29357
  function resolveGitDir(cwd) {
29270
29358
  const dotGit = join73(cwd, ".git");
29271
29359
  let stat2;
29272
29360
  try {
29273
- stat2 = statSync11(dotGit);
29361
+ stat2 = statSync12(dotGit);
29274
29362
  } catch {
29275
29363
  return null;
29276
29364
  }