@algosuite/vo-mcp 0.2.0-beta.75 → 0.2.0-beta.76

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.
@@ -1614,6 +1614,67 @@ var init_process_runner = __esm({
1614
1614
  }
1615
1615
  });
1616
1616
 
1617
+ // src/runner/worktree-paths.mjs
1618
+ import { createHash as createHash2 } from "node:crypto";
1619
+ import fs from "node:fs";
1620
+ import path3 from "node:path";
1621
+ function canonicalPathKey(target, { cache: cache2 = null, realpath: realpath2 = fs.realpathSync.native } = {}) {
1622
+ const resolved = path3.resolve(String(target || ""));
1623
+ const tail = [];
1624
+ let cursor = resolved;
1625
+ for (; ; ) {
1626
+ let real = cache2 ? cache2.get(cursor) : void 0;
1627
+ if (real === void 0) {
1628
+ try {
1629
+ real = realpath2(cursor);
1630
+ } catch {
1631
+ real = null;
1632
+ }
1633
+ if (cache2) cache2.set(cursor, real);
1634
+ }
1635
+ if (real) {
1636
+ const unprefixed = String(real).replace(/^\\\\\?\\UNC\\/u, "\\\\").replace(/^\\\\\?\\/u, "");
1637
+ const joined = tail.length ? path3.join(unprefixed, ...[...tail].reverse()) : unprefixed;
1638
+ return process.platform === "win32" ? joined.toLowerCase() : joined;
1639
+ }
1640
+ const parent = path3.dirname(cursor);
1641
+ if (parent === cursor) break;
1642
+ tail.push(path3.basename(cursor));
1643
+ cursor = parent;
1644
+ }
1645
+ return process.platform === "win32" ? resolved.toLowerCase() : resolved;
1646
+ }
1647
+ function samePath2(left, right) {
1648
+ const a = path3.resolve(left);
1649
+ const b = path3.resolve(right);
1650
+ return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
1651
+ }
1652
+ function worktreePoolForRoot(root, { clonesRootDir = process.env.VO_CODE_RUNNER_CLONES_ROOT || "" } = {}) {
1653
+ const canonicalRoot = path3.resolve(root);
1654
+ if (clonesRootDir) {
1655
+ const clonePool = path3.resolve(clonesRootDir);
1656
+ if (samePath2(path3.dirname(canonicalRoot), clonePool)) {
1657
+ return path3.join(clonePool, ".agent-worktrees", path3.basename(canonicalRoot));
1658
+ }
1659
+ }
1660
+ return path3.join(canonicalRoot, ".agent-worktrees");
1661
+ }
1662
+ function worktreeDirForName(root, worktreeName, options = {}) {
1663
+ const leaf = createHash2("sha256").update(String(worktreeName)).digest("hex").slice(0, 16);
1664
+ return path3.join(worktreePoolForRoot(root, options), leaf);
1665
+ }
1666
+ function recoveryLedgerPathForRoot(root, options = {}) {
1667
+ return path3.join(worktreePoolForRoot(root, options), "recovery-ledger.jsonl");
1668
+ }
1669
+ function legacyRecoveryLedgerPathForRoot(root) {
1670
+ return path3.join(path3.resolve(root), ".agent-worktrees", "recovery-ledger.jsonl");
1671
+ }
1672
+ var init_worktree_paths = __esm({
1673
+ "src/runner/worktree-paths.mjs"() {
1674
+ "use strict";
1675
+ }
1676
+ });
1677
+
1617
1678
  // src/runner/worktree-add.mjs
1618
1679
  import fsp2 from "node:fs/promises";
1619
1680
  async function pathExists2(target) {
@@ -1634,8 +1695,9 @@ async function worktreeStillRegistered(root, worktreeDir, runner) {
1634
1695
  `git worktree list --porcelain failed during rollback verification: ${summarizeProcessFailure(listed)}`
1635
1696
  );
1636
1697
  }
1637
- const registered = String(listed.stdout || "").split(/\r?\n/u).filter((line) => line.startsWith("worktree ")).map((line) => line.slice("worktree ".length).trim());
1638
- return registered.includes(worktreeDir);
1698
+ const cache2 = /* @__PURE__ */ new Map();
1699
+ const target = canonicalPathKey(worktreeDir, { cache: cache2 });
1700
+ return String(listed.stdout || "").split(/\r?\n/u).filter((line) => line.startsWith("worktree ")).some((line) => canonicalPathKey(line.slice("worktree ".length).trim(), { cache: cache2 }) === target);
1639
1701
  }
1640
1702
  async function branchStillExists(root, branchName, runner) {
1641
1703
  const listed = await runner("git", ["branch", "--list", "--format=%(refname:short)", branchName], {
@@ -1749,25 +1811,26 @@ var init_worktree_add = __esm({
1749
1811
  "use strict";
1750
1812
  init_pnpm_link_detach();
1751
1813
  init_process_runner();
1814
+ init_worktree_paths();
1752
1815
  DEFAULT_WORKTREE_ADD_TIMEOUT_MS = 10 * 60 * 1e3;
1753
1816
  DEFAULT_WORKTREE_ADD_ATTEMPTS = 2;
1754
1817
  }
1755
1818
  });
1756
1819
 
1757
1820
  // src/runner/pnpm-canonical-health.mjs
1758
- import fs from "node:fs";
1821
+ import fs2 from "node:fs";
1759
1822
  import fsp3 from "node:fs/promises";
1760
- import path3 from "node:path";
1823
+ import path4 from "node:path";
1761
1824
  function readJsonFile(file) {
1762
- if (!fs.existsSync(file)) return null;
1825
+ if (!fs2.existsSync(file)) return null;
1763
1826
  try {
1764
- return JSON.parse(fs.readFileSync(file, "utf8"));
1827
+ return JSON.parse(fs2.readFileSync(file, "utf8"));
1765
1828
  } catch {
1766
1829
  return null;
1767
1830
  }
1768
1831
  }
1769
1832
  function packageJsonAt(root) {
1770
- return readJsonFile(path3.join(root, "package.json"));
1833
+ return readJsonFile(path4.join(root, "package.json"));
1771
1834
  }
1772
1835
  function dependencyNamesForPackage(root) {
1773
1836
  const manifest = packageJsonAt(root);
@@ -1779,7 +1842,7 @@ function dependencyNamesForPackage(root) {
1779
1842
  ])].sort();
1780
1843
  }
1781
1844
  function packageEntryPath(nodeModulesDir, packageName) {
1782
- return path3.join(nodeModulesDir, ...String(packageName || "").split("/"));
1845
+ return path4.join(nodeModulesDir, ...String(packageName || "").split("/"));
1783
1846
  }
1784
1847
  function rootFsApi() {
1785
1848
  return {
@@ -1808,7 +1871,7 @@ async function inspectDependencyEntry(nodeModulesDir, packageName, fsApi) {
1808
1871
  } catch {
1809
1872
  return { issue: `missing or dangling dependency link: ${entry}` };
1810
1873
  }
1811
- const packageJsonPath = path3.join(resolved, "package.json");
1874
+ const packageJsonPath = path4.join(resolved, "package.json");
1812
1875
  if (!await pathExists3(packageJsonPath, fsApi)) {
1813
1876
  return { issue: `dependency target is missing package.json: ${entry} -> ${resolved}` };
1814
1877
  }
@@ -1820,11 +1883,11 @@ async function inspectDependencyEntry(nodeModulesDir, packageName, fsApi) {
1820
1883
  return { issue: null };
1821
1884
  }
1822
1885
  function representativePackages(root, linkedWorkspaceDirs, sampleLimit) {
1823
- const packages = [{ nodeModulesDir: path3.join(root, "node_modules"), packageRoot: root }];
1886
+ const packages = [{ nodeModulesDir: path4.join(root, "node_modules"), packageRoot: root }];
1824
1887
  for (const relativeDir of linkedWorkspaceDirs) {
1825
1888
  packages.push({
1826
- nodeModulesDir: path3.join(root, relativeDir, "node_modules"),
1827
- packageRoot: path3.join(root, relativeDir)
1889
+ nodeModulesDir: path4.join(root, relativeDir, "node_modules"),
1890
+ packageRoot: path4.join(root, relativeDir)
1828
1891
  });
1829
1892
  }
1830
1893
  const representatives = [];
@@ -1836,7 +1899,7 @@ function representativePackages(root, linkedWorkspaceDirs, sampleLimit) {
1836
1899
  return representatives;
1837
1900
  }
1838
1901
  function canonicalNodeModulesQuarantineRoot(root) {
1839
- return path3.join(root, ".agent-worktrees", QUARANTINE_DIRNAME);
1902
+ return path4.join(root, ".agent-worktrees", QUARANTINE_DIRNAME);
1840
1903
  }
1841
1904
  async function inspectCanonicalNodeModulesHealth({
1842
1905
  root,
@@ -1847,8 +1910,8 @@ async function inspectCanonicalNodeModulesHealth({
1847
1910
  sampleLimit = DEFAULT_SAMPLE_LIMIT
1848
1911
  }) {
1849
1912
  const issues = [];
1850
- const nodeModulesDir = path3.join(root, "node_modules");
1851
- const markerPath = path3.join(nodeModulesDir, ".vo-deps-state.json");
1913
+ const nodeModulesDir = path4.join(root, "node_modules");
1914
+ const markerPath = path4.join(nodeModulesDir, ".vo-deps-state.json");
1852
1915
  if (!await pathExists3(nodeModulesDir, fsApi)) {
1853
1916
  issues.push(`missing root node_modules: ${nodeModulesDir}`);
1854
1917
  } else {
@@ -1857,8 +1920,8 @@ async function inspectCanonicalNodeModulesHealth({
1857
1920
  issues.push(`root node_modules must be a real directory: ${nodeModulesDir}`);
1858
1921
  }
1859
1922
  }
1860
- if (!await pathExists3(path3.join(nodeModulesDir, ".pnpm"), fsApi)) {
1861
- issues.push(`missing root .pnpm store view: ${path3.join(nodeModulesDir, ".pnpm")}`);
1923
+ if (!await pathExists3(path4.join(nodeModulesDir, ".pnpm"), fsApi)) {
1924
+ issues.push(`missing root .pnpm store view: ${path4.join(nodeModulesDir, ".pnpm")}`);
1862
1925
  }
1863
1926
  if (requireMarker) {
1864
1927
  try {
@@ -1871,7 +1934,7 @@ async function inspectCanonicalNodeModulesHealth({
1871
1934
  }
1872
1935
  }
1873
1936
  for (const relativeDir of linkedWorkspaceDirs) {
1874
- const workspaceNodeModules = path3.join(root, relativeDir, "node_modules");
1937
+ const workspaceNodeModules = path4.join(root, relativeDir, "node_modules");
1875
1938
  if (!await pathExists3(workspaceNodeModules, fsApi)) {
1876
1939
  issues.push(`missing workspace node_modules: ${workspaceNodeModules}`);
1877
1940
  continue;
@@ -1894,17 +1957,17 @@ async function inspectCanonicalNodeModulesHealth({
1894
1957
  async function quarantineCanonicalNodeModules(root, issues, options = {}) {
1895
1958
  const fsApi = options.fsApi || rootFsApi();
1896
1959
  const logger = options.logger || console.error;
1897
- const nodeModulesDir = path3.join(root, "node_modules");
1960
+ const nodeModulesDir = path4.join(root, "node_modules");
1898
1961
  const quarantineRoot = canonicalNodeModulesQuarantineRoot(root);
1899
1962
  if (!await pathExists3(nodeModulesDir, fsApi)) return null;
1900
1963
  await fsApi.mkdir(quarantineRoot, { recursive: true });
1901
1964
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
1902
1965
  let attempt = 0;
1903
1966
  for (; ; ) {
1904
- const quarantinePath = path3.join(quarantineRoot, `node_modules-${stamp}-${process.pid}-${attempt}`);
1967
+ const quarantinePath = path4.join(quarantineRoot, `node_modules-${stamp}-${process.pid}-${attempt}`);
1905
1968
  try {
1906
1969
  await fsApi.rename(nodeModulesDir, quarantinePath);
1907
- const metadataPath = path3.join(quarantinePath, ".vo-runner-quarantine.json");
1970
+ const metadataPath = path4.join(quarantinePath, ".vo-runner-quarantine.json");
1908
1971
  await fsApi.writeFile(metadataPath, `${JSON.stringify({
1909
1972
  issues,
1910
1973
  originalPath: nodeModulesDir,
@@ -1929,27 +1992,27 @@ var init_pnpm_canonical_health = __esm({
1929
1992
  });
1930
1993
 
1931
1994
  // src/runner/pnpm-command.mjs
1932
- import fs2 from "node:fs";
1995
+ import fs3 from "node:fs";
1933
1996
  import os from "node:os";
1934
- import path4 from "node:path";
1997
+ import path5 from "node:path";
1935
1998
  function isWindowsDriveOrUnc(value) {
1936
1999
  return WINDOWS_DRIVE_OR_UNC_RE.test(String(value || ""));
1937
2000
  }
1938
2001
  function portableDirname(value) {
1939
- if (isWindowsDriveOrUnc(value)) return path4.win32.dirname(value);
1940
- if (path4.posix.isAbsolute(value)) return path4.posix.dirname(value);
1941
- return path4.dirname(value);
2002
+ if (isWindowsDriveOrUnc(value)) return path5.win32.dirname(value);
2003
+ if (path5.posix.isAbsolute(value)) return path5.posix.dirname(value);
2004
+ return path5.dirname(value);
1942
2005
  }
1943
2006
  function portableJoin(root, ...segments) {
1944
- if (isWindowsDriveOrUnc(root)) return path4.win32.join(root, ...segments);
1945
- if (path4.posix.isAbsolute(root)) return path4.posix.join(root, ...segments);
1946
- return path4.join(root, ...segments);
2007
+ if (isWindowsDriveOrUnc(root)) return path5.win32.join(root, ...segments);
2008
+ if (path5.posix.isAbsolute(root)) return path5.posix.join(root, ...segments);
2009
+ return path5.join(root, ...segments);
1947
2010
  }
1948
2011
  function readPackageManager(root) {
1949
- const packagePath = path4.join(root, "package.json");
1950
- if (!fs2.existsSync(packagePath)) return "";
2012
+ const packagePath = path5.join(root, "package.json");
2013
+ if (!fs3.existsSync(packagePath)) return "";
1951
2014
  try {
1952
- return String(JSON.parse(fs2.readFileSync(packagePath, "utf8"))?.packageManager || "").trim();
2015
+ return String(JSON.parse(fs3.readFileSync(packagePath, "utf8"))?.packageManager || "").trim();
1953
2016
  } catch {
1954
2017
  return "";
1955
2018
  }
@@ -1966,13 +2029,13 @@ function pnpmSelector(root) {
1966
2029
  const packageManager = readPackageManager(root);
1967
2030
  const version = validatedPnpmVersionToken(root);
1968
2031
  if (packageManager && !version) {
1969
- throw new Error(`[vo-mcp runner] invalid pnpm packageManager token in ${path4.join(root, "package.json")}`);
2032
+ throw new Error(`[vo-mcp runner] invalid pnpm packageManager token in ${path5.join(root, "package.json")}`);
1970
2033
  }
1971
2034
  return version ? `pnpm@${version}` : "pnpm";
1972
2035
  }
1973
2036
  function whereResults(result) {
1974
2037
  if (result?.status !== 0) return [];
1975
- return String(result.stdout || "").split(/\r?\n/u).map((line) => line.trim()).filter((line) => path4.win32.isAbsolute(line));
2038
+ return String(result.stdout || "").split(/\r?\n/u).map((line) => line.trim()).filter((line) => path5.win32.isAbsolute(line));
1976
2039
  }
1977
2040
  async function resolveWindowsNativeCommand(command, runner) {
1978
2041
  const result = await runner("where", [command], { timeoutMs: 1e4 });
@@ -1984,29 +2047,29 @@ function trustedCorepackCandidates(options) {
1984
2047
  const roots = [portableDirname(execPath)];
1985
2048
  for (const key of ["ProgramW6432", "ProgramFiles", "ProgramFiles(x86)"]) {
1986
2049
  const programFiles = String(env2[key] || "").trim();
1987
- if (isWindowsDriveOrUnc(programFiles) || path4.posix.isAbsolute(programFiles)) {
2050
+ if (isWindowsDriveOrUnc(programFiles) || path5.posix.isAbsolute(programFiles)) {
1988
2051
  roots.push(portableJoin(programFiles, "nodejs"));
1989
2052
  }
1990
2053
  }
1991
2054
  return [...new Set(roots)].map((root) => portableJoin(root, "node_modules", "corepack", "dist", "corepack.js"));
1992
2055
  }
1993
2056
  function resolveTrustedCorepackJs(options) {
1994
- const existsSync13 = options.existsSync || fs2.existsSync;
2057
+ const existsSync13 = options.existsSync || fs3.existsSync;
1995
2058
  return trustedCorepackCandidates(options).find((candidate) => existsSync13(candidate)) || "";
1996
2059
  }
1997
2060
  function defaultPnpmShimRoot() {
1998
- return path4.join(os.homedir(), ".vo", "pnpm-shim");
2061
+ return path5.join(os.homedir(), ".vo", "pnpm-shim");
1999
2062
  }
2000
2063
  function materializePnpmShimDir(corepackJs, execPath, options = {}) {
2001
- const mkdirSync10 = options.mkdirSync || fs2.mkdirSync;
2002
- const writeFileSync6 = options.writeFileSync || fs2.writeFileSync;
2003
- const chmodSync3 = options.chmodSync || fs2.chmodSync;
2064
+ const mkdirSync10 = options.mkdirSync || fs3.mkdirSync;
2065
+ const writeFileSync6 = options.writeFileSync || fs3.writeFileSync;
2066
+ const chmodSync3 = options.chmodSync || fs3.chmodSync;
2004
2067
  const dir = options.shimRoot || defaultPnpmShimRoot();
2005
2068
  mkdirSync10(dir, { recursive: true });
2006
- writeFileSync6(path4.join(dir, PNPM_SHIM_CMD_NAME), `@echo off\r
2069
+ writeFileSync6(path5.join(dir, PNPM_SHIM_CMD_NAME), `@echo off\r
2007
2070
  "${execPath}" "${corepackJs}" pnpm %*\r
2008
2071
  `);
2009
- const shPath = path4.join(dir, PNPM_SHIM_SH_NAME);
2072
+ const shPath = path5.join(dir, PNPM_SHIM_SH_NAME);
2010
2073
  writeFileSync6(shPath, `#!/bin/sh
2011
2074
  exec "${execPath}" "${corepackJs}" pnpm "$@"
2012
2075
  `);
@@ -2018,8 +2081,8 @@ exec "${execPath}" "${corepackJs}" pnpm "$@"
2018
2081
  }
2019
2082
  function commandDirectory(command) {
2020
2083
  if (!command) return "";
2021
- if (isWindowsDriveOrUnc(command)) return path4.win32.dirname(command);
2022
- if (path4.posix.isAbsolute(command)) return path4.posix.dirname(command);
2084
+ if (isWindowsDriveOrUnc(command)) return path5.win32.dirname(command);
2085
+ if (path5.posix.isAbsolute(command)) return path5.posix.dirname(command);
2023
2086
  return "";
2024
2087
  }
2025
2088
  function agentPathDirs(command, execPath) {
@@ -2108,7 +2171,7 @@ var init_pnpm_command = __esm({
2108
2171
 
2109
2172
  // src/runner/pnpm-materialize.mjs
2110
2173
  import fsp4 from "node:fs/promises";
2111
- import path5 from "node:path";
2174
+ import path6 from "node:path";
2112
2175
  function linkType() {
2113
2176
  return process.platform === "win32" ? "junction" : "dir";
2114
2177
  }
@@ -2119,14 +2182,16 @@ async function realpathOrThrow(target, fsApi) {
2119
2182
  throw new Error(`[vo-mcp runner] dependency path is missing: ${target}`);
2120
2183
  }
2121
2184
  }
2122
- function shouldMapToWorktree(resolvedTarget, canonicalRoot) {
2123
- const relative = path5.relative(canonicalRoot, resolvedTarget).replace(/\\/g, "/");
2124
- return Boolean(relative && !relative.startsWith("..") && !relative.split("/").includes("node_modules"));
2185
+ function shouldMapToWorktree(resolvedTarget, canonicalRoot, pathApi = path6) {
2186
+ const relative = pathApi.relative(canonicalRoot, resolvedTarget);
2187
+ if (!relative || pathApi.isAbsolute(relative)) return false;
2188
+ const normalized = relative.replace(/\\/g, "/");
2189
+ return !normalized.startsWith("..") && !normalized.split("/").includes("node_modules");
2125
2190
  }
2126
2191
  async function resolveEntryTarget(sourceEntry, canonicalRoot, worktreeRoot, fsApi) {
2127
2192
  const resolved = await realpathOrThrow(sourceEntry, fsApi);
2128
2193
  if (!shouldMapToWorktree(resolved, canonicalRoot)) return resolved;
2129
- const mapped = path5.join(worktreeRoot, path5.relative(canonicalRoot, resolved));
2194
+ const mapped = path6.join(worktreeRoot, path6.relative(canonicalRoot, resolved));
2130
2195
  if (!await fsApi.pathExists(mapped)) {
2131
2196
  throw new Error(`[vo-mcp runner] task-local workspace target is missing for dependency link: ${mapped}`);
2132
2197
  }
@@ -2137,7 +2202,7 @@ async function ensureLinkedDirectory(source, target, fsApi) {
2137
2202
  if (await fsApi.realpath(target) === await fsApi.realpath(source)) return;
2138
2203
  throw new Error(`[vo-mcp runner] refusing to overwrite existing dependency path: ${target}`);
2139
2204
  }
2140
- await fsApi.mkdir(path5.dirname(target), { recursive: true });
2205
+ await fsApi.mkdir(path6.dirname(target), { recursive: true });
2141
2206
  await fsApi.symlink(source, target, linkType());
2142
2207
  if (await fsApi.realpath(target) !== await fsApi.realpath(source)) {
2143
2208
  throw new Error(`[vo-mcp runner] dependency link validation failed for ${target}`);
@@ -2151,8 +2216,8 @@ async function maybeYield2(state) {
2151
2216
  async function copyDirRecursive(sourceDir, targetDir, fsApi, yieldState) {
2152
2217
  await fsApi.mkdir(targetDir, { recursive: true });
2153
2218
  for (const entry of await fsApi.readdir(sourceDir, { withFileTypes: true })) {
2154
- const source = path5.join(sourceDir, entry.name);
2155
- const target = path5.join(targetDir, entry.name);
2219
+ const source = path6.join(sourceDir, entry.name);
2220
+ const target = path6.join(targetDir, entry.name);
2156
2221
  await maybeYield2(yieldState);
2157
2222
  if (entry.isDirectory()) {
2158
2223
  await copyDirRecursive(source, target, fsApi, yieldState);
@@ -2164,17 +2229,17 @@ async function copyDirRecursive(sourceDir, targetDir, fsApi, yieldState) {
2164
2229
  async function materializeEntry(sourceEntry, targetEntry, canonicalRoot, worktreeRoot, options) {
2165
2230
  await options.beforeEntry?.(sourceEntry, targetEntry);
2166
2231
  const stat3 = await options.fsApi.lstat(sourceEntry);
2167
- if (stat3.isDirectory() && !stat3.isSymbolicLink() && path5.basename(sourceEntry) === ".bin") {
2232
+ if (stat3.isDirectory() && !stat3.isSymbolicLink() && path6.basename(sourceEntry) === ".bin") {
2168
2233
  await copyDirRecursive(sourceEntry, targetEntry, options.fsApi, options.yieldState);
2169
2234
  return;
2170
2235
  }
2171
- if (stat3.isDirectory() && !stat3.isSymbolicLink() && path5.basename(sourceEntry).startsWith("@")) {
2236
+ if (stat3.isDirectory() && !stat3.isSymbolicLink() && path6.basename(sourceEntry).startsWith("@")) {
2172
2237
  await options.fsApi.mkdir(targetEntry, { recursive: true });
2173
2238
  for (const nested of await options.fsApi.readdir(sourceEntry, { withFileTypes: true })) {
2174
2239
  await maybeYield2(options.yieldState);
2175
2240
  await materializeEntry(
2176
- path5.join(sourceEntry, nested.name),
2177
- path5.join(targetEntry, nested.name),
2241
+ path6.join(sourceEntry, nested.name),
2242
+ path6.join(targetEntry, nested.name),
2178
2243
  canonicalRoot,
2179
2244
  worktreeRoot,
2180
2245
  options
@@ -2187,7 +2252,7 @@ async function materializeEntry(sourceEntry, targetEntry, canonicalRoot, worktre
2187
2252
  await ensureLinkedDirectory(resolvedTarget, targetEntry, options.fsApi);
2188
2253
  return;
2189
2254
  }
2190
- await options.fsApi.mkdir(path5.dirname(targetEntry), { recursive: true });
2255
+ await options.fsApi.mkdir(path6.dirname(targetEntry), { recursive: true });
2191
2256
  await options.fsApi.copyFile(sourceEntry, targetEntry);
2192
2257
  }
2193
2258
  function createPnpmFsApi(pathExists6) {
@@ -2207,13 +2272,14 @@ function createPnpmFsApi(pathExists6) {
2207
2272
  };
2208
2273
  }
2209
2274
  async function materializeNodeModulesForest(sourceNodeModules, targetNodeModules, canonicalRoot, worktreeRoot, options) {
2275
+ const realCanonicalRoot = await realpathOrThrow(canonicalRoot, options.fsApi);
2210
2276
  await options.fsApi.mkdir(targetNodeModules, { recursive: true });
2211
2277
  for (const entry of await options.fsApi.readdir(sourceNodeModules, { withFileTypes: true })) {
2212
2278
  await maybeYield2(options.yieldState);
2213
2279
  await materializeEntry(
2214
- path5.join(sourceNodeModules, entry.name),
2215
- path5.join(targetNodeModules, entry.name),
2216
- canonicalRoot,
2280
+ path6.join(sourceNodeModules, entry.name),
2281
+ path6.join(targetNodeModules, entry.name),
2282
+ realCanonicalRoot,
2217
2283
  worktreeRoot,
2218
2284
  options
2219
2285
  );
@@ -2226,21 +2292,21 @@ var init_pnpm_materialize = __esm({
2226
2292
  });
2227
2293
 
2228
2294
  // src/runner/pnpm-hydration.mjs
2229
- import { createHash as createHash2 } from "node:crypto";
2230
- import fs3 from "node:fs";
2295
+ import { createHash as createHash3 } from "node:crypto";
2296
+ import fs4 from "node:fs";
2231
2297
  import fsp5 from "node:fs/promises";
2232
- import path6 from "node:path";
2298
+ import path7 from "node:path";
2233
2299
  function hashText(text) {
2234
- return createHash2("sha256").update(String(text)).digest("hex");
2300
+ return createHash3("sha256").update(String(text)).digest("hex");
2235
2301
  }
2236
2302
  function statePath(root) {
2237
- return path6.join(root, ".agent-worktrees", "runner-pnpm-hydration.json");
2303
+ return path7.join(root, ".agent-worktrees", "runner-pnpm-hydration.json");
2238
2304
  }
2239
2305
  function packageJson(root) {
2240
- const packagePath = path6.join(root, "package.json");
2241
- if (!fs3.existsSync(packagePath)) return null;
2306
+ const packagePath = path7.join(root, "package.json");
2307
+ if (!fs4.existsSync(packagePath)) return null;
2242
2308
  try {
2243
- return JSON.parse(fs3.readFileSync(packagePath, "utf8"));
2309
+ return JSON.parse(fs4.readFileSync(packagePath, "utf8"));
2244
2310
  } catch {
2245
2311
  return null;
2246
2312
  }
@@ -2254,23 +2320,23 @@ async function pathExists4(target) {
2254
2320
  }
2255
2321
  }
2256
2322
  function lockfileHash(root) {
2257
- const lockPath = path6.join(root, "pnpm-lock.yaml");
2258
- if (!fs3.existsSync(lockPath)) return "";
2259
- return hashText(fs3.readFileSync(lockPath, "utf8"));
2323
+ const lockPath = path7.join(root, "pnpm-lock.yaml");
2324
+ if (!fs4.existsSync(lockPath)) return "";
2325
+ return hashText(fs4.readFileSync(lockPath, "utf8"));
2260
2326
  }
2261
2327
  function readHydrationState(root) {
2262
2328
  const file = statePath(root);
2263
- if (!fs3.existsSync(file)) return null;
2329
+ if (!fs4.existsSync(file)) return null;
2264
2330
  try {
2265
- return JSON.parse(fs3.readFileSync(file, "utf8"));
2331
+ return JSON.parse(fs4.readFileSync(file, "utf8"));
2266
2332
  } catch {
2267
2333
  return null;
2268
2334
  }
2269
2335
  }
2270
2336
  function writeHydrationState(root, state) {
2271
2337
  const file = statePath(root);
2272
- fs3.mkdirSync(path6.dirname(file), { recursive: true });
2273
- fs3.writeFileSync(file, `${JSON.stringify({
2338
+ fs4.mkdirSync(path7.dirname(file), { recursive: true });
2339
+ fs4.writeFileSync(file, `${JSON.stringify({
2274
2340
  ...state,
2275
2341
  stateVersion: 2,
2276
2342
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -2278,7 +2344,7 @@ function writeHydrationState(root, state) {
2278
2344
  `, "utf8");
2279
2345
  }
2280
2346
  function voDepsStatePath(root) {
2281
- return path6.join(root, "node_modules", ".vo-deps-state.json");
2347
+ return path7.join(root, "node_modules", ".vo-deps-state.json");
2282
2348
  }
2283
2349
  async function ensureVoDepsState(root, expectedHash, fsApi = fsp5) {
2284
2350
  const marker = voDepsStatePath(root);
@@ -2288,7 +2354,7 @@ async function ensureVoDepsState(root, expectedHash, fsApi = fsp5) {
2288
2354
  } catch {
2289
2355
  }
2290
2356
  const temp = `${marker}.tmp-${process.pid}-${Date.now()}`;
2291
- await fsApi.mkdir(path6.dirname(marker), { recursive: true });
2357
+ await fsApi.mkdir(path7.dirname(marker), { recursive: true });
2292
2358
  await fsApi.writeFile(temp, `${JSON.stringify({ lockfileHash: expectedHash, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)}
2293
2359
  `, "utf8");
2294
2360
  await fsApi.rename(temp, marker);
@@ -2315,9 +2381,9 @@ function workspacePatternsFromPackageJson(root) {
2315
2381
  return [];
2316
2382
  }
2317
2383
  function workspacePatternsFromPnpmWorkspace(root) {
2318
- const workspacePath = path6.join(root, "pnpm-workspace.yaml");
2319
- if (!fs3.existsSync(workspacePath)) return [];
2320
- const lines = fs3.readFileSync(workspacePath, "utf8").split(/\r?\n/u);
2384
+ const workspacePath = path7.join(root, "pnpm-workspace.yaml");
2385
+ if (!fs4.existsSync(workspacePath)) return [];
2386
+ const lines = fs4.readFileSync(workspacePath, "utf8").split(/\r?\n/u);
2321
2387
  const patterns = [];
2322
2388
  let inPackages = false;
2323
2389
  for (const rawLine of lines) {
@@ -2374,16 +2440,16 @@ function collectPackageDirs(root, options = {}) {
2374
2440
  while (stack.length > 0) {
2375
2441
  const current = stack.pop();
2376
2442
  if (!current) continue;
2377
- const relativeDir = path6.relative(root, current.dir).replace(/\\/g, "/");
2378
- if (relativeDir && fs3.existsSync(path6.join(current.dir, "package.json"))) {
2443
+ const relativeDir = path7.relative(root, current.dir).replace(/\\/g, "/");
2444
+ if (relativeDir && fs4.existsSync(path7.join(current.dir, "package.json"))) {
2379
2445
  found.push(relativeDir);
2380
2446
  if (found.length >= maxDirs) break;
2381
2447
  }
2382
2448
  if (current.depth >= maxDepth) continue;
2383
- for (const entry of fs3.readdirSync(current.dir, { withFileTypes: true })) {
2449
+ for (const entry of fs4.readdirSync(current.dir, { withFileTypes: true })) {
2384
2450
  if (!entry.isDirectory()) continue;
2385
2451
  if (IGNORED_SCAN_DIRS.has(entry.name)) continue;
2386
- stack.push({ dir: path6.join(current.dir, entry.name), depth: current.depth + 1 });
2452
+ stack.push({ dir: path7.join(current.dir, entry.name), depth: current.depth + 1 });
2387
2453
  }
2388
2454
  }
2389
2455
  return found.sort();
@@ -2407,8 +2473,8 @@ async function runInstall(root, options = {}) {
2407
2473
  }
2408
2474
  }
2409
2475
  async function hasReadyNodeModules(root) {
2410
- const nodeModules = path6.join(root, "node_modules");
2411
- return await pathExists4(path6.join(nodeModules, ".modules.yaml")) || await pathExists4(path6.join(nodeModules, ".pnpm"));
2476
+ const nodeModules = path7.join(root, "node_modules");
2477
+ return await pathExists4(path7.join(nodeModules, ".modules.yaml")) || await pathExists4(path7.join(nodeModules, ".pnpm"));
2412
2478
  }
2413
2479
  function hydrationFsApi(overrides = {}) {
2414
2480
  return { ...createPnpmFsApi(pathExists4), ...overrides };
@@ -2445,7 +2511,7 @@ async function ensurePnpmHydration(root, options = {}) {
2445
2511
  expectedHash: hash,
2446
2512
  requireMarker: false
2447
2513
  });
2448
- if (!health.healthy && await fsApi.pathExists(path6.join(root, "node_modules"))) {
2514
+ if (!health.healthy && await fsApi.pathExists(path7.join(root, "node_modules"))) {
2449
2515
  quarantine = await quarantineCanonicalNodeModules(root, health.issues, {
2450
2516
  fsApi,
2451
2517
  logger: options.logger
@@ -2457,7 +2523,7 @@ async function ensurePnpmHydration(root, options = {}) {
2457
2523
  }
2458
2524
  const linkedWorkspaceDirs = [];
2459
2525
  for (const relativeDir of workspaceDirs) {
2460
- if (await pathExists4(path6.join(root, relativeDir, "node_modules"))) {
2526
+ if (await pathExists4(path7.join(root, relativeDir, "node_modules"))) {
2461
2527
  linkedWorkspaceDirs.push(relativeDir);
2462
2528
  }
2463
2529
  }
@@ -2493,18 +2559,18 @@ async function linkHydratedNodeModules({ root, worktreeDir, hydration, options =
2493
2559
  yieldEvery: Math.max(1, options.yieldEvery ?? DEFAULT_YIELD_EVERY2)
2494
2560
  }
2495
2561
  };
2496
- recordOwnedNodeModulesRoot(dependencyOwnership, path6.join(worktreeDir, "node_modules"));
2562
+ recordOwnedNodeModulesRoot(dependencyOwnership, path7.join(worktreeDir, "node_modules"));
2497
2563
  await materializeNodeModulesForest(
2498
- path6.join(root, "node_modules"),
2499
- path6.join(worktreeDir, "node_modules"),
2564
+ path7.join(root, "node_modules"),
2565
+ path7.join(worktreeDir, "node_modules"),
2500
2566
  root,
2501
2567
  worktreeDir,
2502
2568
  materializeOptions
2503
2569
  );
2504
2570
  for (const relativeDir of hydration.linkedWorkspaceDirs) {
2505
- const sourceNodeModules = path6.join(root, relativeDir, "node_modules");
2506
- const targetNodeModules = path6.join(worktreeDir, relativeDir, "node_modules");
2507
- if (!await fsApi.pathExists(path6.join(worktreeDir, relativeDir))) continue;
2571
+ const sourceNodeModules = path7.join(root, relativeDir, "node_modules");
2572
+ const targetNodeModules = path7.join(worktreeDir, relativeDir, "node_modules");
2573
+ if (!await fsApi.pathExists(path7.join(worktreeDir, relativeDir))) continue;
2508
2574
  recordOwnedNodeModulesRoot(dependencyOwnership, targetNodeModules);
2509
2575
  await materializeNodeModulesForest(sourceNodeModules, targetNodeModules, root, worktreeDir, materializeOptions);
2510
2576
  }
@@ -2540,67 +2606,6 @@ var init_pnpm_hydration = __esm({
2540
2606
  }
2541
2607
  });
2542
2608
 
2543
- // src/runner/worktree-paths.mjs
2544
- import { createHash as createHash3 } from "node:crypto";
2545
- import fs4 from "node:fs";
2546
- import path7 from "node:path";
2547
- function canonicalPathKey(target, { cache: cache2 = null, realpath: realpath2 = fs4.realpathSync.native } = {}) {
2548
- const resolved = path7.resolve(String(target || ""));
2549
- const tail = [];
2550
- let cursor = resolved;
2551
- for (; ; ) {
2552
- let real = cache2 ? cache2.get(cursor) : void 0;
2553
- if (real === void 0) {
2554
- try {
2555
- real = realpath2(cursor);
2556
- } catch {
2557
- real = null;
2558
- }
2559
- if (cache2) cache2.set(cursor, real);
2560
- }
2561
- if (real) {
2562
- const unprefixed = String(real).replace(/^\\\\\?\\UNC\\/u, "\\\\").replace(/^\\\\\?\\/u, "");
2563
- const joined = tail.length ? path7.join(unprefixed, ...[...tail].reverse()) : unprefixed;
2564
- return process.platform === "win32" ? joined.toLowerCase() : joined;
2565
- }
2566
- const parent = path7.dirname(cursor);
2567
- if (parent === cursor) break;
2568
- tail.push(path7.basename(cursor));
2569
- cursor = parent;
2570
- }
2571
- return process.platform === "win32" ? resolved.toLowerCase() : resolved;
2572
- }
2573
- function samePath2(left, right) {
2574
- const a = path7.resolve(left);
2575
- const b = path7.resolve(right);
2576
- return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
2577
- }
2578
- function worktreePoolForRoot(root, { clonesRootDir = process.env.VO_CODE_RUNNER_CLONES_ROOT || "" } = {}) {
2579
- const canonicalRoot = path7.resolve(root);
2580
- if (clonesRootDir) {
2581
- const clonePool = path7.resolve(clonesRootDir);
2582
- if (samePath2(path7.dirname(canonicalRoot), clonePool)) {
2583
- return path7.join(clonePool, ".agent-worktrees", path7.basename(canonicalRoot));
2584
- }
2585
- }
2586
- return path7.join(canonicalRoot, ".agent-worktrees");
2587
- }
2588
- function worktreeDirForName(root, worktreeName, options = {}) {
2589
- const leaf = createHash3("sha256").update(String(worktreeName)).digest("hex").slice(0, 16);
2590
- return path7.join(worktreePoolForRoot(root, options), leaf);
2591
- }
2592
- function recoveryLedgerPathForRoot(root, options = {}) {
2593
- return path7.join(worktreePoolForRoot(root, options), "recovery-ledger.jsonl");
2594
- }
2595
- function legacyRecoveryLedgerPathForRoot(root) {
2596
- return path7.join(path7.resolve(root), ".agent-worktrees", "recovery-ledger.jsonl");
2597
- }
2598
- var init_worktree_paths = __esm({
2599
- "src/runner/worktree-paths.mjs"() {
2600
- "use strict";
2601
- }
2602
- });
2603
-
2604
2609
  // src/runner/worktree-cleanup.mjs
2605
2610
  import fs5 from "node:fs";
2606
2611
  import fsp6 from "node:fs/promises";
@@ -3057,27 +3062,29 @@ async function fetchExactTaskBase(root, baseSha, options = {}) {
3057
3062
  function shouldIgnoreManagedEntry(entryName) {
3058
3063
  return IGNORED_MANAGED_ENTRIES.has(entryName) || entryName.endsWith(".lock") || entryName.startsWith("runner-");
3059
3064
  }
3060
- async function registeredWorktreeDirs(root, options = {}) {
3065
+ async function registeredWorktreeKeys(root, cache2, options = {}) {
3061
3066
  const listed = await git(root, ["worktree", "list", "--porcelain"], options);
3062
3067
  if (listed.status !== 0) {
3063
3068
  throw new Error(`git worktree list --porcelain failed while checking managed residue: ${summarizeProcessFailure(listed)}`);
3064
3069
  }
3065
3070
  return new Set(
3066
- String(listed.stdout || "").split(/\r?\n/u).filter((line) => line.startsWith("worktree ")).map((line) => path9.resolve(line.slice("worktree ".length).trim()))
3071
+ String(listed.stdout || "").split(/\r?\n/u).filter((line) => line.startsWith("worktree ")).map((line) => canonicalPathKey(line.slice("worktree ".length).trim(), { cache: cache2 }))
3067
3072
  );
3068
3073
  }
3069
3074
  async function reportLegacyResiduals(root, options = {}) {
3070
3075
  const managedRoot = path9.join(root, ".agent-worktrees");
3071
3076
  if (!fs6.existsSync(managedRoot)) return [];
3072
- const registered = await registeredWorktreeDirs(root, options);
3073
- const pending = pendingCleanupDirs();
3077
+ const cache2 = /* @__PURE__ */ new Map();
3078
+ const registered = await registeredWorktreeKeys(root, cache2, options);
3079
+ const pending = new Set([...pendingCleanupDirs()].map((dir) => canonicalPathKey(dir, { cache: cache2 })));
3074
3080
  const found = [];
3075
3081
  for (const entry of fs6.readdirSync(managedRoot, { withFileTypes: true })) {
3076
3082
  if (!entry.isDirectory()) continue;
3077
3083
  if (shouldIgnoreManagedEntry(entry.name)) continue;
3078
3084
  const absolute = path9.resolve(path9.join(managedRoot, entry.name));
3079
- if (registered.has(absolute)) continue;
3080
- if (pending.has(absolute)) continue;
3085
+ const key = canonicalPathKey(absolute, { cache: cache2 });
3086
+ if (registered.has(key)) continue;
3087
+ if (pending.has(key)) continue;
3081
3088
  found.push(absolute);
3082
3089
  }
3083
3090
  if (found.length === 0) return [];
@@ -3114,6 +3121,7 @@ var init_task_root_prepare = __esm({
3114
3121
  init_pnpm_command();
3115
3122
  init_process_runner();
3116
3123
  init_worktree_cleanup();
3124
+ init_worktree_paths();
3117
3125
  PREP_LOCK_WAIT_MS = 20 * 60 * 1e3;
3118
3126
  PREP_LOCK_STALE_MS = 45 * 60 * 1e3;
3119
3127
  REPORTED_RESIDUAL_SNAPSHOTS = /* @__PURE__ */ new Set();