gdharness 1.3.59 → 1.3.60

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/build/cli.js CHANGED
@@ -1717,6 +1717,7 @@ var init_whole_file = __esm(() => {
1717
1717
  // src/engine-slots.ts
1718
1718
  import {
1719
1719
  closeSync as closeSync2,
1720
+ existsSync as existsSync2,
1720
1721
  mkdirSync as mkdirSync2,
1721
1722
  openSync as openSync2,
1722
1723
  readdirSync,
@@ -1766,6 +1767,83 @@ function keptSlotsOf(count) {
1766
1767
  function reservedSlotOf(count) {
1767
1768
  return count - Math.max(1, count - keptSlotsOf(count)) >= 2 ? count - 1 : null;
1768
1769
  }
1770
+ function slotWaiters(directory) {
1771
+ const marks = join5(directory, WAITING_FOLDER);
1772
+ let names;
1773
+ try {
1774
+ names = readdirSync(marks).filter((name) => name.endsWith(".json"));
1775
+ } catch {
1776
+ return [];
1777
+ }
1778
+ const found = [];
1779
+ for (const mark of names.sort()) {
1780
+ let content;
1781
+ let madeAt;
1782
+ try {
1783
+ content = readWhole(join5(marks, mark));
1784
+ madeAt = statSync3(join5(marks, mark)).mtimeMs;
1785
+ } catch {
1786
+ continue;
1787
+ }
1788
+ const holder = content === null ? null : holderOf(content);
1789
+ if (content === null || holder === null || !alive(holder.pid)) {
1790
+ continue;
1791
+ }
1792
+ const { taker, since } = JSON.parse(content);
1793
+ if (taker === MEMORY_TAKER) {
1794
+ continue;
1795
+ }
1796
+ found.push({
1797
+ mark,
1798
+ taker: taker === "gate" || taker === "timing" || taker === "tier" ? taker : "other",
1799
+ since: Math.floor(typeof since === "number" && Number.isFinite(since) ? since * 1000 : madeAt),
1800
+ game: holder.game === true
1801
+ });
1802
+ }
1803
+ return found;
1804
+ }
1805
+ function slotsClaimed(ahead, open) {
1806
+ const left = new Set(open);
1807
+ const taken = new Map;
1808
+ for (const [at, numbers] of ahead.entries()) {
1809
+ const first = numbers.find((slot) => left.has(slot));
1810
+ if (first !== undefined) {
1811
+ left.delete(first);
1812
+ taken.set(first, at);
1813
+ }
1814
+ }
1815
+ return taken;
1816
+ }
1817
+
1818
+ class SlotLine {
1819
+ since;
1820
+ mark;
1821
+ left = new Map;
1822
+ taker;
1823
+ game;
1824
+ clock;
1825
+ constructor(taker, game = false, clock = Date.now) {
1826
+ this.taker = taker;
1827
+ this.game = game;
1828
+ this.clock = clock;
1829
+ this.since = clock();
1830
+ }
1831
+ marked(holder) {
1832
+ return { ...holder, ...this.game ? { game: true } : {}, taker: this.taker, since: this.since / 1000 };
1833
+ }
1834
+ ahead(waiters) {
1835
+ const own = this.mark ?? "￿";
1836
+ return waiters.filter((one) => one.mark !== this.mark && (one.since < this.since || one.since === this.since && one.mark < own)).sort((a, b) => a.since - b.since || (a.mark < b.mark ? -1 : 1));
1837
+ }
1838
+ admitted(numbers, theirs) {
1839
+ const now = this.clock();
1840
+ this.left = new Map([...theirs].map((slot) => [slot, this.left.get(slot) ?? now]));
1841
+ return numbers.filter((slot) => !theirs.has(slot) || now - (this.left.get(slot) ?? now) >= SLOT_YIELD_MS);
1842
+ }
1843
+ leaves() {
1844
+ return [...this.left.keys()].sort((a, b) => a - b);
1845
+ }
1846
+ }
1769
1847
  function gamesKeptOf(kept) {
1770
1848
  return Math.max(0, Math.min(Math.floor(kept / 2), kept - GATE_KEPT - 1));
1771
1849
  }
@@ -1905,6 +1983,7 @@ class EngineSlots {
1905
1983
  starts = new Map;
1906
1984
  held = new Set;
1907
1985
  marks = new Set;
1986
+ passedOver = new Map;
1908
1987
  inherited = null;
1909
1988
  drawn = { numbers: [] };
1910
1989
  saidAt = Number.NEGATIVE_INFINITY;
@@ -1923,19 +2002,20 @@ class EngineSlots {
1923
2002
  }
1924
2003
  async take(signal, waiting, blocked, game = false) {
1925
2004
  mkdirSync2(this.directory, { recursive: true });
1926
- const began = Date.now();
2005
+ const line = new SlotLine(this.taker(), game);
2006
+ const began = line.since;
1927
2007
  let said = Number.NEGATIVE_INFINITY;
1928
2008
  let mark;
1929
2009
  let changes;
1930
2010
  try {
1931
2011
  for (;; ) {
1932
2012
  signal?.throwIfAborted();
1933
- const lock = await this.takeFree(game, Date.now() - began);
2013
+ const lock = await this.takeFree(game, Date.now() - began, line);
1934
2014
  if (lock !== null) {
1935
2015
  return lock;
1936
2016
  }
1937
2017
  if (mark === undefined) {
1938
- mark = this.waitMarked();
2018
+ mark = this.waitMarked(line);
1939
2019
  blocked?.();
1940
2020
  }
1941
2021
  const now = Date.now();
@@ -1962,7 +2042,7 @@ class EngineSlots {
1962
2042
  }
1963
2043
  }
1964
2044
  }
1965
- async takeFree(game = false, waitedMs = 0) {
2045
+ async takeFree(game = false, waitedMs = 0, line) {
1966
2046
  mkdirSync2(this.directory, { recursive: true });
1967
2047
  await this.sweep();
1968
2048
  const inherited = this.inherited === null ? await this.inheritedLock() : null;
@@ -1972,7 +2052,9 @@ class EngineSlots {
1972
2052
  }
1973
2053
  const taker = this.taker();
1974
2054
  const aged = taker === "other" && !game && waitedMs >= ONE_OFF_AGED_MS;
1975
- this.drawn = slotsDrawnOn(this.count, taker, taker === "gate" || taker === "timing" || aged ? "none" : await this.gateQueue());
2055
+ let queue;
2056
+ const queued = async () => queue ??= await this.gateQueue();
2057
+ this.drawn = slotsDrawnOn(this.count, taker, taker === "gate" || taker === "timing" || aged ? "none" : await queued());
1976
2058
  if (game && this.drawn.limit === "kept") {
1977
2059
  const reserve = reservedSlotOf(this.count);
1978
2060
  this.drawn = { ...this.drawn, numbers: this.drawn.numbers.filter((slot) => slot !== reserve) };
@@ -1983,8 +2065,31 @@ class EngineSlots {
1983
2065
  return null;
1984
2066
  }
1985
2067
  }
2068
+ let tried = this.drawn.numbers;
2069
+ if (taker !== "timing") {
2070
+ const placed = line ?? new SlotLine(taker, game);
2071
+ const now = Date.now();
2072
+ const waiting = slotWaiters(this.directory);
2073
+ for (const mark of this.passedOver.keys()) {
2074
+ if (!waiting.some((one) => one.mark === mark)) {
2075
+ this.passedOver.delete(mark);
2076
+ }
2077
+ }
2078
+ const ahead = placed.ahead(waiting).filter((one) => now - (this.passedOver.get(one.mark) ?? now) < SLOT_YIELD_MS);
2079
+ const claims = await this.claimedAhead(ahead, queued);
2080
+ for (const mark of claims.values()) {
2081
+ if (!this.passedOver.has(mark)) {
2082
+ this.passedOver.set(mark, now);
2083
+ }
2084
+ }
2085
+ tried = placed.admitted(tried, new Set(claims.keys()));
2086
+ const left = placed.leaves().filter((slot) => this.drawn.numbers.includes(slot) && !tried.includes(slot));
2087
+ if (left.length > 0) {
2088
+ this.drawn = { ...this.drawn, left };
2089
+ }
2090
+ }
1986
2091
  const holder = game ? { ...this.holder, game: true } : this.holder;
1987
- for (const slot of this.drawn.numbers) {
2092
+ for (const slot of tried) {
1988
2093
  const lock = join5(this.directory, `${String(slot)}.lock`);
1989
2094
  if (this.made(lock, holder) || await this.takenOver(lock, holder)) {
1990
2095
  this.held.add(lock);
@@ -1993,6 +2098,30 @@ class EngineSlots {
1993
2098
  }
1994
2099
  return null;
1995
2100
  }
2101
+ async claimedAhead(ahead, queued) {
2102
+ if (ahead.length === 0) {
2103
+ return new Map;
2104
+ }
2105
+ const open = [];
2106
+ for (let slot = 0;slot < this.count; slot += 1) {
2107
+ const lock = join5(this.directory, `${String(slot)}.lock`);
2108
+ if (!existsSync2(lock) || await this.free(lock)) {
2109
+ open.push(slot);
2110
+ }
2111
+ }
2112
+ if (open.length === 0) {
2113
+ return new Map;
2114
+ }
2115
+ const now = Date.now();
2116
+ const reserve = reservedSlotOf(this.count);
2117
+ const drawn = [];
2118
+ for (const one of ahead) {
2119
+ const aged = one.taker === "other" && !one.game && now - one.since >= ONE_OFF_AGED_MS;
2120
+ const theirs = slotsDrawnOn(this.count, one.taker, one.taker === "gate" || one.taker === "timing" || aged ? "none" : await queued());
2121
+ drawn.push(one.game && theirs.limit === "kept" ? theirs.numbers.filter((slot) => slot !== reserve) : theirs.numbers);
2122
+ }
2123
+ return new Map([...slotsClaimed(drawn, open)].map(([slot, at]) => [slot, ahead[at]?.mark ?? ""]));
2124
+ }
1996
2125
  async inheritedLock() {
1997
2126
  const lock = nonEmpty(process4.env[HELD_VARIABLE]);
1998
2127
  const content = lock === undefined ? null : readWhole(lock);
@@ -2006,14 +2135,14 @@ class EngineSlots {
2006
2135
  return tree !== undefined && inheritsSlot(tree, process4.pid, holder, basename3(process4.execPath), engineStarted) ? lock : null;
2007
2136
  }
2008
2137
  markWaiting() {
2009
- const mark = this.waitMarked();
2138
+ const mark = this.waitMarked({ ...this.holder, taker: MEMORY_TAKER });
2010
2139
  return () => {
2011
2140
  if (mark !== undefined && this.marks.delete(mark)) {
2012
2141
  removeWhole(mark);
2013
2142
  }
2014
2143
  };
2015
2144
  }
2016
- waitMarked() {
2145
+ waitMarked(line) {
2017
2146
  const marks = join5(this.directory, WAITING_FOLDER);
2018
2147
  waitsMarked += 1;
2019
2148
  const mark = join5(marks, `${String(this.holder.pid)}-${String(waitsMarked)}.json`);
@@ -2022,9 +2151,12 @@ class EngineSlots {
2022
2151
  } catch {
2023
2152
  return;
2024
2153
  }
2025
- if (!this.made(mark)) {
2154
+ if (!this.made(mark, line instanceof SlotLine ? line.marked(this.holder) : line)) {
2026
2155
  return;
2027
2156
  }
2157
+ if (line instanceof SlotLine) {
2158
+ line.mark = basename3(mark);
2159
+ }
2028
2160
  this.marks.add(mark);
2029
2161
  return mark;
2030
2162
  }
@@ -2283,13 +2415,16 @@ function slotWaitSaid(waitedMs, count, directory, holders = [], drawn = { number
2283
2415
  const waiting = `${so}: ${slots}`;
2284
2416
  const back = `the engine starts when ${taking === 1 ? "it" : "one"} is given back`;
2285
2417
  const starts = drawn.limit === "kept" || drawn.limit === "tier" || drawn.limit === "games" ? `${back} or no gate is queued` : back;
2286
- if (named.length === 0) {
2287
- return `${waiting}, by a gate or another tool, and ${starts}.`;
2288
- }
2289
- if (taking === 1) {
2290
- return `${waiting}, by ${named.join(", ")}, and ${starts}.`;
2418
+ const said = named.length === 0 ? `${waiting}, by a gate or another tool, and ${starts}.` : taking === 1 ? `${waiting}, by ${named.join(", ")}, and ${starts}.` : `${waiting}: ${listed(named)}. ${starts.charAt(0).toUpperCase()}${starts.slice(1)}.`;
2419
+ return `${said}${leftSaid(drawn)}`;
2420
+ }
2421
+ function leftSaid(drawn, past = false) {
2422
+ const left = drawn.left ?? [];
2423
+ if (left.length === 0) {
2424
+ return "";
2291
2425
  }
2292
- return `${waiting}: ${listed(named)}. ${starts.charAt(0).toUpperCase()}${starts.slice(1)}.`;
2426
+ const slots = left.length === 1 ? `slot ${String(left[0])}` : `slots ${listed(left.map(String))}`;
2427
+ return past ? ` It left free ${slots} to takers that had begun waiting before it, which go first.` : ` It leaves free ${slots} to takers that began waiting before it, which go first.`;
2293
2428
  }
2294
2429
  function slotsSaid(taking, count, directory, limit) {
2295
2430
  const where = `on this machine (${directory})`;
@@ -2312,10 +2447,8 @@ function slotWaitedSaid(waitedMs, count, directory, holders, drawn = { numbers:
2312
2447
  const taking = drawn.limit === undefined ? count : drawn.numbers.length;
2313
2448
  const slots = `${slotsSaid(taking, count, directory, drawn.limit)} ${taking === 1 ? "was" : "were"} in use`;
2314
2449
  const named = holdersNamed(taking, holders);
2315
- if (named.length === 0) {
2316
- return `${waited} When it first waited, ${slots}, by a gate or another tool.`;
2317
- }
2318
- return taking === 1 ? `${waited} When it first waited, ${slots}, by ${named.join(", ")}.` : `${waited} When it first waited, ${slots}: ${listed(named)}.`;
2450
+ const said = named.length === 0 ? `${waited} When it first waited, ${slots}, by a gate or another tool.` : taking === 1 ? `${waited} When it first waited, ${slots}, by ${named.join(", ")}.` : `${waited} When it first waited, ${slots}: ${listed(named)}.`;
2451
+ return `${said}${leftSaid(drawn, true)}`;
2319
2452
  }
2320
2453
  function holdersNamed(count, holders) {
2321
2454
  const held = new Map;
@@ -2370,7 +2503,7 @@ async function inASlot(body) {
2370
2503
  held.release();
2371
2504
  }
2372
2505
  }
2373
- var HELD_VARIABLE = "GODOT_ENGINE_HELD", SLOTS_VARIABLE = "GODOT_ENGINE_SLOTS", SLOT_COUNT_VARIABLE = "GODOT_ENGINE_SLOT_COUNT", PROCESSORS_A_SLOT = 2, START_TOLERANCE_MS = 2000, UNWRITTEN_MS = 1e4, SLOT_LOOK_MS = 1000, SLOT_SETTLE_MS = 50, WAIT_SAID_MS = 20000, COMMAND_WAIT_SAID_MS = 2000, START_READ_MS = 1e4, WAITING_FOLDER = "waiting", QUEUED_FOLDER = "queued", SHARE_VARIABLE = "GODOT_ENGINE_SHARE", SHARE_COUNT_VARIABLE = "GODOT_ENGINE_SHARE_COUNT", GATE_KEPT = 1, ONE_OFF_AGED_MS = 120000, TIMED_VARIABLE = "GODOT_ENGINE_TIMED", TIER_VARIABLE = "GODOT_ENGINE_TIER", SEATED_SUFFIX = ".seated", waitsMarked = 0, ENGINE_PID_LOOK_MS = 100, ours, saidTo, takenBy;
2506
+ var HELD_VARIABLE = "GODOT_ENGINE_HELD", SLOTS_VARIABLE = "GODOT_ENGINE_SLOTS", SLOT_COUNT_VARIABLE = "GODOT_ENGINE_SLOT_COUNT", PROCESSORS_A_SLOT = 2, START_TOLERANCE_MS = 2000, UNWRITTEN_MS = 1e4, SLOT_LOOK_MS = 1000, SLOT_SETTLE_MS = 50, WAIT_SAID_MS = 20000, COMMAND_WAIT_SAID_MS = 2000, START_READ_MS = 1e4, WAITING_FOLDER = "waiting", QUEUED_FOLDER = "queued", SHARE_VARIABLE = "GODOT_ENGINE_SHARE", SHARE_COUNT_VARIABLE = "GODOT_ENGINE_SHARE_COUNT", GATE_KEPT = 1, ONE_OFF_AGED_MS = 120000, SLOT_YIELD_MS = 5000, MEMORY_TAKER = "memory", TIMED_VARIABLE = "GODOT_ENGINE_TIMED", TIER_VARIABLE = "GODOT_ENGINE_TIER", SEATED_SUFFIX = ".seated", waitsMarked = 0, ENGINE_PID_LOOK_MS = 100, ours, saidTo, takenBy;
2374
2507
  var init_engine_slots = __esm(() => {
2375
2508
  init_alive();
2376
2509
  init_cache_home();
@@ -9645,7 +9778,7 @@ var init_config_formats = __esm(() => {
9645
9778
  });
9646
9779
 
9647
9780
  // src/runner.ts
9648
- import { existsSync as existsSync2, realpathSync as realpathSync2 } from "node:fs";
9781
+ import { existsSync as existsSync3, realpathSync as realpathSync2 } from "node:fs";
9649
9782
  import { delimiter, dirname as dirname3, extname, join as join6, resolve as resolve3 } from "node:path";
9650
9783
  import process5 from "node:process";
9651
9784
  function currentRunner() {
@@ -9689,12 +9822,12 @@ function realPath(path) {
9689
9822
  }
9690
9823
  function alongside(execPath, name) {
9691
9824
  const runner = join6(dirname3(execPath), process5.platform === "win32" ? `${name}.cmd` : name);
9692
- return existsSync2(runner) ? runner : undefined;
9825
+ return existsSync3(runner) ? runner : undefined;
9693
9826
  }
9694
9827
  var init_runner = () => {};
9695
9828
 
9696
9829
  // src/harnesses.ts
9697
- import { existsSync as existsSync3, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync8, rmSync as rmSync5, statSync as statSync4, writeFileSync as writeFileSync5 } from "node:fs";
9830
+ import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync8, rmSync as rmSync5, statSync as statSync4, writeFileSync as writeFileSync5 } from "node:fs";
9698
9831
  import { homedir as homedir3 } from "node:os";
9699
9832
  import { basename as basename4, dirname as dirname4, isAbsolute as isAbsolute2, join as join7, relative as relative2, resolve as resolve4 } from "node:path";
9700
9833
  import process6 from "node:process";
@@ -9785,15 +9918,15 @@ function harnessById(id) {
9785
9918
  }
9786
9919
  function present(harness, projectPath) {
9787
9920
  const path = configPath(harness, projectPath);
9788
- if (existsSync3(path)) {
9921
+ if (existsSync4(path)) {
9789
9922
  return true;
9790
9923
  }
9791
9924
  const root = harness.scope === "project" ? projectPath : homedir3();
9792
9925
  const own = dirname4(path);
9793
- if (own !== root && existsSync3(own)) {
9926
+ if (own !== root && existsSync4(own)) {
9794
9927
  return true;
9795
9928
  }
9796
- return harness.marker !== undefined && existsSync3(join7(root, harness.marker));
9929
+ return harness.marker !== undefined && existsSync4(join7(root, harness.marker));
9797
9930
  }
9798
9931
  function candidates(projectPath) {
9799
9932
  const found = [];
@@ -9806,7 +9939,7 @@ function candidates(projectPath) {
9806
9939
  }
9807
9940
  if (present(harness, projectPath)) {
9808
9941
  found.push({ harness, reason: "configured" });
9809
- } else if (harness.home !== undefined && existsSync3(join7(homedir3(), harness.home))) {
9942
+ } else if (harness.home !== undefined && existsSync4(join7(homedir3(), harness.home))) {
9810
9943
  found.push({ harness, reason: "installed" });
9811
9944
  }
9812
9945
  }
@@ -9828,7 +9961,7 @@ function groupByFile(harnesses, projectPath) {
9828
9961
  }
9829
9962
  function registered(harness, projectPath) {
9830
9963
  const path = configPath(harness, projectPath);
9831
- if (harness.snippet !== undefined || !existsSync3(path)) {
9964
+ if (harness.snippet !== undefined || !existsSync4(path)) {
9832
9965
  return false;
9833
9966
  }
9834
9967
  const text = readFileSync8(path, "utf8");
@@ -9857,7 +9990,7 @@ function recordedEnginePath(projectPath) {
9857
9990
  }
9858
9991
  const named = reach(entryEnvironment(harness, projectPath), "GODOT_PATH");
9859
9992
  const path = typeof named !== "string" || named === "" ? null : isAbsolute2(named) ? named : resolve4(projectPath, named);
9860
- if (path !== null && existsSync3(path)) {
9993
+ if (path !== null && existsSync4(path)) {
9861
9994
  return path;
9862
9995
  }
9863
9996
  }
@@ -9865,7 +9998,7 @@ function recordedEnginePath(projectPath) {
9865
9998
  }
9866
9999
  function mainCheckoutOf(projectPath) {
9867
10000
  let top = resolve4(projectPath);
9868
- while (!existsSync3(join7(top, ".git"))) {
10001
+ while (!existsSync4(join7(top, ".git"))) {
9869
10002
  const up = dirname4(top);
9870
10003
  if (up === top) {
9871
10004
  return null;
@@ -9882,7 +10015,7 @@ function mainCheckoutOf(projectPath) {
9882
10015
  }
9883
10016
  const entry = resolve4(top, pointer);
9884
10017
  const commonFile = join7(entry, "commondir");
9885
- if (!existsSync3(commonFile)) {
10018
+ if (!existsSync4(commonFile)) {
9886
10019
  return null;
9887
10020
  }
9888
10021
  const common = resolve4(entry, readFileSync8(commonFile, "utf8").trim());
@@ -9890,11 +10023,11 @@ function mainCheckoutOf(projectPath) {
9890
10023
  return null;
9891
10024
  }
9892
10025
  const main = join7(dirname4(common), relative2(top, resolve4(projectPath)));
9893
- return isSameDirectory(main, projectPath) || !existsSync3(join7(main, "project.godot")) ? null : main;
10026
+ return isSameDirectory(main, projectPath) || !existsSync4(join7(main, "project.godot")) ? null : main;
9894
10027
  }
9895
10028
  function worktreeCheckoutsOf(projectPath) {
9896
10029
  let top = resolve4(projectPath);
9897
- while (!existsSync3(join7(top, ".git"))) {
10030
+ while (!existsSync4(join7(top, ".git"))) {
9898
10031
  const up = dirname4(top);
9899
10032
  if (up === top) {
9900
10033
  return [];
@@ -9902,18 +10035,18 @@ function worktreeCheckoutsOf(projectPath) {
9902
10035
  top = up;
9903
10036
  }
9904
10037
  const listed = join7(top, ".git", "worktrees");
9905
- if (!statSync4(join7(top, ".git")).isDirectory() || !existsSync3(listed)) {
10038
+ if (!statSync4(join7(top, ".git")).isDirectory() || !existsSync4(listed)) {
9906
10039
  return [];
9907
10040
  }
9908
10041
  const below = relative2(top, resolve4(projectPath));
9909
10042
  return readdirSync2(listed).flatMap((name) => {
9910
10043
  const pointer = join7(listed, name, "gitdir");
9911
- if (!existsSync3(pointer)) {
10044
+ if (!existsSync4(pointer)) {
9912
10045
  return [];
9913
10046
  }
9914
10047
  const checkout = dirname4(resolve4(listed, name, readFileSync8(pointer, "utf8").trim()));
9915
10048
  const project = join7(checkout, below);
9916
- return existsSync3(join7(project, "project.godot")) ? [project] : [];
10049
+ return existsSync4(join7(project, "project.godot")) ? [project] : [];
9917
10050
  });
9918
10051
  }
9919
10052
  function entryEnvironment(harness, projectPath) {
@@ -9921,7 +10054,7 @@ function entryEnvironment(harness, projectPath) {
9921
10054
  return;
9922
10055
  }
9923
10056
  const path = configPath(harness, projectPath);
9924
- if (!existsSync3(path)) {
10057
+ if (!existsSync4(path)) {
9925
10058
  return;
9926
10059
  }
9927
10060
  let parsed;
@@ -9942,7 +10075,7 @@ function reach(held, key) {
9942
10075
  }
9943
10076
  function disconnect(harness, projectPath) {
9944
10077
  const path = configPath(harness, projectPath);
9945
- if (!existsSync3(path)) {
10078
+ if (!existsSync4(path)) {
9946
10079
  return { harness, path, action: "absent" };
9947
10080
  }
9948
10081
  if (harness.snippet !== undefined) {
@@ -10029,7 +10162,7 @@ function connect(harness, projectPath, launch) {
10029
10162
  if (harness.snippet !== undefined) {
10030
10163
  return { harness, path, action: "snippet", snippet: harness.snippet(launch) };
10031
10164
  }
10032
- const held = existsSync3(path) ? readFileSync8(path, "utf8") : "";
10165
+ const held = existsSync4(path) ? readFileSync8(path, "utf8") : "";
10033
10166
  if (harness.toml !== undefined) {
10034
10167
  const already = held.includes(harness.toml.identity ?? harness.toml.header);
10035
10168
  return put(harness, path, writeToml(held, harness.toml, launch), already);
@@ -11195,7 +11328,7 @@ var init_gdscript_source = __esm(() => {
11195
11328
  });
11196
11329
 
11197
11330
  // src/class-cache.ts
11198
- import { existsSync as existsSync4, readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync5 } from "node:fs";
11331
+ import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync5 } from "node:fs";
11199
11332
  import { join as join8, posix } from "node:path";
11200
11333
  function isToolScript(source) {
11201
11334
  return TOOL.test(codeOf(source));
@@ -11259,7 +11392,7 @@ function declaredClassOf(source) {
11259
11392
  }
11260
11393
  function eachScript(projectPath, each) {
11261
11394
  const visit = (directory, prefix) => {
11262
- if (existsSync4(join8(directory, ".gdignore"))) {
11395
+ if (existsSync5(join8(directory, ".gdignore"))) {
11263
11396
  return;
11264
11397
  }
11265
11398
  for (const entry of readdirSync3(directory, { withFileTypes: true })) {
@@ -11655,7 +11788,7 @@ function uncachedForTheEngineNote(projectPath, types) {
11655
11788
  }
11656
11789
  const one = types.length === 1;
11657
11790
  const named = types.map((type) => `${type.type} (${type.declaredIn})`).join(", ");
11658
- const cacheExists = existsSync4(join8(projectPath, ".godot", "global_script_class_cache.cfg"));
11791
+ const cacheExists = existsSync5(join8(projectPath, ".godot", "global_script_class_cache.cfg"));
11659
11792
  const state = cacheExists ? `missing from .godot/global_script_class_cache.cfg, which is where the engine that compiled these scripts resolves a class name from, so the error is the cache being behind the files rather than the script.` : `the engine that compiled these scripts resolves a class name from .godot/global_script_class_cache.cfg, which has not been written yet, as in a project no editor has opened, so the error is the missing cache rather than the script.`;
11660
11793
  return `${named} ${one ? "is" : "are"} declared in this project${cacheExists ? " and" : ", but"} ${state} ` + "project_import refresh_classes writes the cache from the declarations on disk; editor_run start " + "writes it before a game, and an editor opening the project writes it when it scans.";
11661
11794
  }
@@ -11681,7 +11814,7 @@ function declaredSince(projectPath, paths, names, since) {
11681
11814
  });
11682
11815
  }
11683
11816
  function cachedAtMissingPaths(cached, projectPath) {
11684
- return [...cached].filter(([, path]) => path.startsWith("res://") && !existsSync4(join8(projectPath, path.slice("res://".length)))).map(([name]) => name).sort();
11817
+ return [...cached].filter(([, path]) => path.startsWith("res://") && !existsSync5(join8(projectPath, path.slice("res://".length)))).map(([name]) => name).sort();
11685
11818
  }
11686
11819
  function staleAgainst(cached, projectPath) {
11687
11820
  return [...declaredClasses(projectPath)].filter(([name, path]) => cached.get(name) !== path).map(([name]) => name);
@@ -13015,7 +13148,7 @@ var init_suite_judge = __esm(() => {
13015
13148
  // src/engine-launch.ts
13016
13149
  import {
13017
13150
  closeSync as closeSync4,
13018
- existsSync as existsSync5,
13151
+ existsSync as existsSync6,
13019
13152
  fstatSync as fstatSync2,
13020
13153
  openSync as openSync4,
13021
13154
  readdirSync as readdirSync4,
@@ -13055,7 +13188,7 @@ function godotNamed(value, cwd) {
13055
13188
  return null;
13056
13189
  }
13057
13190
  const path = resolve5(cwd, value);
13058
- if (!existsSync5(path) || statSync6(path).isDirectory()) {
13191
+ if (!existsSync6(path) || statSync6(path).isDirectory()) {
13059
13192
  throw new EngineUsageError(`--godot names ${path}, which is not an engine executable.`);
13060
13193
  }
13061
13194
  return path;
@@ -13086,7 +13219,7 @@ function resPathOf(entry, projectPath, cwd) {
13086
13219
  const file = caseAt?.[1] ?? entry;
13087
13220
  const fromProject = resolve5(projectPath, file);
13088
13221
  const fromHere = resolve5(cwd, file);
13089
- const absolute = isAbsolute3(file) || !existsSync5(fromProject) && existsSync5(fromHere) ? fromHere : fromProject;
13222
+ const absolute = isAbsolute3(file) || !existsSync6(fromProject) && existsSync6(fromHere) ? fromHere : fromProject;
13090
13223
  const inside = relative3(projectPath, absolute);
13091
13224
  if (inside.startsWith("..") || isAbsolute3(inside)) {
13092
13225
  throw new EngineUsageError(`${entry} is not inside the project at ${projectPath}.`);
@@ -13098,7 +13231,7 @@ function homeOf(projectPath) {
13098
13231
  return mainCheckoutOf(projectPath) ?? projectPath;
13099
13232
  }
13100
13233
  function sweepRunDirectories(runs, kept = KEPT_RUN_DIRECTORIES) {
13101
- if (!existsSync5(runs)) {
13234
+ if (!existsSync6(runs)) {
13102
13235
  return;
13103
13236
  }
13104
13237
  const ended = [];
@@ -13339,7 +13472,7 @@ async function watchedEngine(launch, lock, args, directory, log, silenceSeconds,
13339
13472
  continue;
13340
13473
  }
13341
13474
  const { stoppedIn } = readRun(readLog(log));
13342
- const unstarted = helper !== null && !existsSync5(helper.pid) ? `, and it never started ${helper.how}: ${helperStep(helper.step)}` : "";
13475
+ const unstarted = helper !== null && !existsSync6(helper.pid) ? `, and it never started ${helper.how}: ${helperStep(helper.step)}` : "";
13343
13476
  ended = `the engine printed nothing for ${String(allowed.seconds)} s${countedBy(quiet, silent, at)}${stoppedIn === null ? "" : ` while running ${stoppedIn}`}, so it was ended${unstarted}`;
13344
13477
  stop();
13345
13478
  }
@@ -13425,7 +13558,7 @@ var init_engine_launch = __esm(() => {
13425
13558
  });
13426
13559
 
13427
13560
  // src/detection.ts
13428
- import { existsSync as existsSync6, readdirSync as readdirSync5, statSync as statSync7 } from "node:fs";
13561
+ import { existsSync as existsSync7, readdirSync as readdirSync5, statSync as statSync7 } from "node:fs";
13429
13562
  import { homedir as homedir4 } from "node:os";
13430
13563
  import { join as join10 } from "node:path";
13431
13564
  function resolveHomeDirectory() {
@@ -13436,7 +13569,7 @@ function resolveHomeDirectory() {
13436
13569
  }
13437
13570
  }
13438
13571
  function scanDirectoryForGodotBinaries(directory, platform) {
13439
- if (!directory || !existsSync6(directory)) {
13572
+ if (!directory || !existsSync7(directory)) {
13440
13573
  return [];
13441
13574
  }
13442
13575
  let entries;
@@ -13704,7 +13837,7 @@ var init_launch = __esm(() => {
13704
13837
  });
13705
13838
 
13706
13839
  // src/godot-path.ts
13707
- import { existsSync as existsSync7 } from "node:fs";
13840
+ import { existsSync as existsSync8 } from "node:fs";
13708
13841
  import { isAbsolute as isAbsolute4, normalize, resolve as resolve6 } from "node:path";
13709
13842
  function versionStartOf(error) {
13710
13843
  const failed = error ?? {};
@@ -13782,7 +13915,7 @@ class GodotLocator {
13782
13915
  if (known !== undefined) {
13783
13916
  return known;
13784
13917
  }
13785
- if (path !== "godot" && !existsSync7(path)) {
13918
+ if (path !== "godot" && !existsSync8(path)) {
13786
13919
  this.answered.set(path, "does not exist");
13787
13920
  return "does not exist";
13788
13921
  }
@@ -14167,7 +14300,7 @@ var init_engine_run = __esm(() => {
14167
14300
  });
14168
14301
 
14169
14302
  // src/doc-cache.ts
14170
- import { existsSync as existsSync8, readdirSync as readdirSync6, statSync as statSync8 } from "node:fs";
14303
+ import { existsSync as existsSync9, readdirSync as readdirSync6, statSync as statSync8 } from "node:fs";
14171
14304
  import { homedir as homedir5 } from "node:os";
14172
14305
  import { basename as basename5, dirname as dirname5, isAbsolute as isAbsolute5, join as join11 } from "node:path";
14173
14306
  import process9 from "node:process";
@@ -14175,7 +14308,7 @@ function editorCacheDirectory(godotPath, platform = process9.platform, env = pro
14175
14308
  const beside = dirname5(godotPath);
14176
14309
  const bundle = platform === "darwin" && basename5(beside) === "MacOS" && basename5(dirname5(beside)) === "Contents" ? dirname5(dirname5(dirname5(beside))) : null;
14177
14310
  for (const folder of bundle === null ? [beside] : [beside, bundle]) {
14178
- if (existsSync8(join11(folder, "._sc_")) || existsSync8(join11(folder, "_sc_"))) {
14311
+ if (existsSync9(join11(folder, "._sc_")) || existsSync9(join11(folder, "_sc_"))) {
14179
14312
  return join11(folder, "editor_data", "cache");
14180
14313
  }
14181
14314
  }
@@ -14223,7 +14356,7 @@ var init_doc_cache = __esm(() => {
14223
14356
  });
14224
14357
 
14225
14358
  // src/project-scan.ts
14226
- import { existsSync as existsSync9, readdirSync as readdirSync7, readFileSync as readFileSync12, statSync as statSync9 } from "node:fs";
14359
+ import { existsSync as existsSync10, readdirSync as readdirSync7, readFileSync as readFileSync12, statSync as statSync9 } from "node:fs";
14227
14360
  import { basename as basename6, extname as extname2, join as join12, relative as relative4, sep as sep3 } from "node:path";
14228
14361
  function skipped(name) {
14229
14362
  return name.startsWith(".") || SKIPPED.has(name);
@@ -14232,10 +14365,10 @@ function steppedOver(directory) {
14232
14365
  return gdignored(directory) || installedByUs(directory);
14233
14366
  }
14234
14367
  function gdignored(directory) {
14235
- return existsSync9(join12(directory, ".gdignore"));
14368
+ return existsSync10(join12(directory, ".gdignore"));
14236
14369
  }
14237
14370
  function installedByUs(directory) {
14238
- return existsSync9(join12(directory, VERSION_MARKER));
14371
+ return existsSync10(join12(directory, VERSION_MARKER));
14239
14372
  }
14240
14373
  function projectStructure(projectPath) {
14241
14374
  const structure = { scenes: 0, scripts: 0, assets: 0, other: 0 };
@@ -14348,7 +14481,7 @@ function scriptsWithoutUid(projectPath) {
14348
14481
  continue;
14349
14482
  }
14350
14483
  const extension = entry.name.split(".").pop()?.toLowerCase() ?? "";
14351
- if (CARRIES_A_UID.has(extension) && !existsSync9(join12(directory, `${entry.name}.uid`))) {
14484
+ if (CARRIES_A_UID.has(extension) && !existsSync10(join12(directory, `${entry.name}.uid`))) {
14352
14485
  found.push(spelled);
14353
14486
  }
14354
14487
  }
@@ -14615,7 +14748,7 @@ var init_project_scan = __esm(() => {
14615
14748
 
14616
14749
  // src/import-freshness.ts
14617
14750
  import { createHash as createHash2 } from "node:crypto";
14618
- import { existsSync as existsSync10, readdirSync as readdirSync8, readFileSync as readFileSync13, statSync as statSync10 } from "node:fs";
14751
+ import { existsSync as existsSync11, readdirSync as readdirSync8, readFileSync as readFileSync13, statSync as statSync10 } from "node:fs";
14619
14752
  import { join as join13 } from "node:path";
14620
14753
  function md5Of(file) {
14621
14754
  let stats;
@@ -14741,7 +14874,7 @@ function behind(projectPath, resPath, sidecarFile, sidecar, importedFrom) {
14741
14874
  return "its import file names no imported output, as one written before the engine imports from it does";
14742
14875
  }
14743
14876
  }
14744
- if (outputs.some((output) => !existsSync10(onDisk(projectPath, output)))) {
14877
+ if (outputs.some((output) => !existsSync11(onDisk(projectPath, output)))) {
14745
14878
  return "its imported output is not on disk";
14746
14879
  }
14747
14880
  const source = unquoted(deps.get("source_file"));
@@ -14766,7 +14899,7 @@ function staleImports(projectPath) {
14766
14899
  const stale = [];
14767
14900
  const importedFrom = importedSidecarMd5s(projectPath);
14768
14901
  const visit = (directory, resDirectory) => {
14769
- if (existsSync10(join13(directory, ".gdignore")) || existsSync10(join13(directory, VERSION_MARKER))) {
14902
+ if (existsSync11(join13(directory, ".gdignore")) || existsSync11(join13(directory, VERSION_MARKER))) {
14770
14903
  return;
14771
14904
  }
14772
14905
  let entries;
@@ -14857,7 +14990,7 @@ var init_import_freshness = __esm(() => {
14857
14990
 
14858
14991
  // src/library-copies.ts
14859
14992
  import {
14860
- existsSync as existsSync11,
14993
+ existsSync as existsSync12,
14861
14994
  mkdirSync as mkdirSync4,
14862
14995
  readdirSync as readdirSync9,
14863
14996
  readFileSync as readFileSync14,
@@ -14875,7 +15008,7 @@ function freeLibraryCopies(projectPath, platform = process.platform) {
14875
15008
  for (const library of windowsLibraries(projectPath)) {
14876
15009
  const folder = dirname6(library);
14877
15010
  const copy = `~${basename7(library)}`;
14878
- if (existsSync11(join14(folder, copy))) {
15011
+ if (existsSync12(join14(folder, copy))) {
14879
15012
  const aside = join14(folder, `${copy}.aside-${process.pid}-${Date.now()}`);
14880
15013
  try {
14881
15014
  renameSync3(join14(folder, copy), aside);
@@ -14901,7 +15034,7 @@ function freeLibraryCopies(projectPath, platform = process.platform) {
14901
15034
  }
14902
15035
  function seedExtensionList(projectPath) {
14903
15036
  const list = join14(projectPath, ".godot", "extension_list.cfg");
14904
- if (existsSync11(list)) {
15037
+ if (existsSync12(list)) {
14905
15038
  return null;
14906
15039
  }
14907
15040
  const found = unlistedExtensions(projectPath);
@@ -14915,12 +15048,12 @@ function seedExtensionList(projectPath) {
14915
15048
  return found;
14916
15049
  }
14917
15050
  function unlistedExtensions(projectPath) {
14918
- if (existsSync11(join14(projectPath, ".godot", "extension_list.cfg"))) {
15051
+ if (existsSync12(join14(projectPath, ".godot", "extension_list.cfg"))) {
14919
15052
  return [];
14920
15053
  }
14921
15054
  const found = [];
14922
15055
  const visit = (directory, resDirectory) => {
14923
- if (existsSync11(join14(directory, ".gdignore"))) {
15056
+ if (existsSync12(join14(directory, ".gdignore"))) {
14924
15057
  return;
14925
15058
  }
14926
15059
  let entries;
@@ -14991,12 +15124,12 @@ var init_library_copies = () => {};
14991
15124
 
14992
15125
  // src/reimport.ts
14993
15126
  import { createHash as createHash3 } from "node:crypto";
14994
- import { existsSync as existsSync12, readFileSync as readFileSync15, rmSync as rmSync8, statSync as statSync11, utimesSync, writeFileSync as writeFileSync8 } from "node:fs";
15127
+ import { existsSync as existsSync13, readFileSync as readFileSync15, rmSync as rmSync8, statSync as statSync11, utimesSync, writeFileSync as writeFileSync8 } from "node:fs";
14995
15128
  import { basename as basename8, join as join15 } from "node:path";
14996
15129
  function forceNextImport(projectPath, resourcePath) {
14997
15130
  const relative = resourcePath.replace(/^res:\/\//, "");
14998
15131
  const sidecar = join15(projectPath, `${relative}.import`);
14999
- if (!existsSync12(sidecar)) {
15132
+ if (!existsSync13(sidecar)) {
15000
15133
  return;
15001
15134
  }
15002
15135
  const { atime, mtimeMs } = statSync11(sidecar);
@@ -15011,7 +15144,7 @@ function importRecord(projectPath, resourcePath) {
15011
15144
  var init_reimport = () => {};
15012
15145
 
15013
15146
  // src/scratch.ts
15014
- import { existsSync as existsSync13, mkdtempSync as mkdtempSync2, readdirSync as readdirSync10, rmSync as rmSync9 } from "node:fs";
15147
+ import { existsSync as existsSync14, mkdtempSync as mkdtempSync2, readdirSync as readdirSync10, rmSync as rmSync9 } from "node:fs";
15015
15148
  import { tmpdir as tmpdir5 } from "node:os";
15016
15149
  import { join as join16 } from "node:path";
15017
15150
  import process10 from "node:process";
@@ -15070,7 +15203,7 @@ function tryAgain(path, attempt) {
15070
15203
  lastTryOnExit();
15071
15204
  }
15072
15205
  const after = AGAIN_AFTER_MS[attempt];
15073
- if (after === undefined || !existsSync13(path)) {
15206
+ if (after === undefined || !existsSync14(path)) {
15074
15207
  waiting.delete(path);
15075
15208
  if (after === undefined) {
15076
15209
  atExit.add(path);
@@ -15226,7 +15359,7 @@ var init_script_origins = __esm(() => {
15226
15359
  });
15227
15360
 
15228
15361
  // src/headless.ts
15229
- import { existsSync as existsSync14, readFileSync as readFileSync16, writeFileSync as writeFileSync9 } from "node:fs";
15362
+ import { existsSync as existsSync15, readFileSync as readFileSync16, writeFileSync as writeFileSync9 } from "node:fs";
15230
15363
  import { dirname as dirname7, join as join18 } from "node:path";
15231
15364
  function snakeCased(params) {
15232
15365
  const result = emptyRecord();
@@ -15515,7 +15648,7 @@ async function operationOutcome(engine, operation, params, projectPath) {
15515
15648
  };
15516
15649
  }
15517
15650
  function answerIn(file) {
15518
- if (!existsSync14(file)) {
15651
+ if (!existsSync15(file)) {
15519
15652
  return { kind: "none" };
15520
15653
  }
15521
15654
  const text = readFileSync16(file, "utf8");
@@ -15544,7 +15677,7 @@ var init_headless = __esm(() => {
15544
15677
  });
15545
15678
 
15546
15679
  // src/update-check.ts
15547
- import { existsSync as existsSync15, mkdirSync as mkdirSync5, readFileSync as readFileSync17, writeFileSync as writeFileSync10 } from "node:fs";
15680
+ import { existsSync as existsSync16, mkdirSync as mkdirSync5, readFileSync as readFileSync17, writeFileSync as writeFileSync10 } from "node:fs";
15548
15681
  import { homedir as homedir6, tmpdir as tmpdir6 } from "node:os";
15549
15682
  import { join as join19 } from "node:path";
15550
15683
  function packageUrl(root) {
@@ -15586,7 +15719,7 @@ function cacheFile(environment = process.env) {
15586
15719
  }
15587
15720
  function readCache(path) {
15588
15721
  try {
15589
- if (!existsSync15(path)) {
15722
+ if (!existsSync16(path)) {
15590
15723
  return null;
15591
15724
  }
15592
15725
  const parsed = JSON.parse(readFileSync17(path, "utf8"));
@@ -16066,7 +16199,7 @@ var init_ports = __esm(() => {
16066
16199
  });
16067
16200
 
16068
16201
  // src/lsp_client.ts
16069
- import { existsSync as existsSync16, realpathSync as realpathSync3 } from "node:fs";
16202
+ import { existsSync as existsSync17, realpathSync as realpathSync3 } from "node:fs";
16070
16203
  import { readFile, realpath } from "node:fs/promises";
16071
16204
  import { createConnection } from "node:net";
16072
16205
  import { dirname as dirname8, extname as extname3, join as join20, resolve as resolve7 } from "node:path";
@@ -16747,7 +16880,7 @@ async function resolveLSPPaths(projectPathValue, scriptPathValue) {
16747
16880
  } catch {
16748
16881
  throw new ArgumentRefusal(`Project path does not exist: ${requestedProjectPath}`);
16749
16882
  }
16750
- if (!existsSync16(join20(projectPath, "project.godot"))) {
16883
+ if (!existsSync17(join20(projectPath, "project.godot"))) {
16751
16884
  throw new ArgumentRefusal(`Not a Godot project: ${projectPath}. Point projectPath at the directory holding project.godot.`);
16752
16885
  }
16753
16886
  const contained = resolveWithinProject(projectPath, scriptPathValue);
@@ -17261,7 +17394,7 @@ function readParams(params, key) {
17261
17394
  import { createHash as createHash5 } from "node:crypto";
17262
17395
  import {
17263
17396
  cpSync,
17264
- existsSync as existsSync18,
17397
+ existsSync as existsSync19,
17265
17398
  mkdirSync as mkdirSync6,
17266
17399
  readdirSync as readdirSync12,
17267
17400
  readFileSync as readFileSync21,
@@ -17344,7 +17477,7 @@ function installedRuntimeDigest(projectPath) {
17344
17477
  }
17345
17478
  function digestMarker(projectPath, addon) {
17346
17479
  const marker = join22(projectPath, "addons", addon, DIGEST_MARKER);
17347
- if (!existsSync18(marker)) {
17480
+ if (!existsSync19(marker)) {
17348
17481
  return null;
17349
17482
  }
17350
17483
  const said = readFileSync21(marker, "utf8").trim();
@@ -17361,7 +17494,7 @@ function shippedLoader() {
17361
17494
  }
17362
17495
  function loaderState(projectPath) {
17363
17496
  const copy = join22(projectPath, ...RUNTIME_AUTOLOAD.path.split("/"));
17364
- if (!existsSync18(copy)) {
17497
+ if (!existsSync19(copy)) {
17365
17498
  return "missing";
17366
17499
  }
17367
17500
  const lines = (path) => readFileSync21(path, "utf8").replaceAll(`\r
@@ -17380,7 +17513,7 @@ function writeLoader(projectPath) {
17380
17513
  }
17381
17514
  function removeLoader(projectPath) {
17382
17515
  const copy = join22(projectPath, ...RUNTIME_AUTOLOAD.path.split("/"));
17383
- if (!existsSync18(copy)) {
17516
+ if (!existsSync19(copy)) {
17384
17517
  return false;
17385
17518
  }
17386
17519
  rmSync10(copy);
@@ -17396,10 +17529,10 @@ function shippedListedRunner() {
17396
17529
  }
17397
17530
  function gdUnit4Unusable(projectPath) {
17398
17531
  const marker = "addons/gdUnit4/plugin.cfg";
17399
- if (!existsSync18(join22(projectPath, ...marker.split("/")))) {
17532
+ if (!existsSync19(join22(projectPath, ...marker.split("/")))) {
17400
17533
  return { missing: true, reason: `gdUnit4 is not installed in this project: no ${marker}` };
17401
17534
  }
17402
- if (!existsSync18(join22(projectPath, ...GDUNIT4_CI_RUNNER.split("/")))) {
17535
+ if (!existsSync19(join22(projectPath, ...GDUNIT4_CI_RUNNER.split("/")))) {
17403
17536
  return {
17404
17537
  missing: false,
17405
17538
  reason: `gdUnit4 in this project is older than 6.0, which the shipped runner needs: no ${GDUNIT4_CI_RUNNER}`
@@ -17411,11 +17544,11 @@ function installAddons(projectPath, from = shippedAddonsDirectory()) {
17411
17544
  const installed = [];
17412
17545
  for (const name of ADDONS) {
17413
17546
  const source = join22(from, name);
17414
- if (!existsSync18(join22(source, addonMarking(name)))) {
17547
+ if (!existsSync19(join22(source, addonMarking(name)))) {
17415
17548
  throw new Error(`The package holds no ${name} addon at ${source}.`);
17416
17549
  }
17417
17550
  const target = join22(projectPath, "addons", name);
17418
- const replaced = existsSync18(target);
17551
+ const replaced = existsSync19(target);
17419
17552
  rmSync10(target, { recursive: true, force: true });
17420
17553
  mkdirSync6(dirname9(target), { recursive: true });
17421
17554
  cpSync(source, target, { recursive: true });
@@ -17431,7 +17564,7 @@ function installAddons(projectPath, from = shippedAddonsDirectory()) {
17431
17564
  }
17432
17565
  function installedAddonVersion(projectPath) {
17433
17566
  const marker = join22(projectPath, "addons", ADDONS[0], VERSION_MARKER);
17434
- if (!existsSync18(marker)) {
17567
+ if (!existsSync19(marker)) {
17435
17568
  return null;
17436
17569
  }
17437
17570
  const said = readFileSync21(marker, "utf8").trim();
@@ -17441,13 +17574,13 @@ function removeAddons(projectPath) {
17441
17574
  const removed = [];
17442
17575
  for (const name of ADDONS) {
17443
17576
  const target = join22(projectPath, "addons", name);
17444
- if (existsSync18(target)) {
17577
+ if (existsSync19(target)) {
17445
17578
  rmSync10(target, { recursive: true, force: true });
17446
17579
  removed.push(target);
17447
17580
  }
17448
17581
  }
17449
17582
  const addons = join22(projectPath, "addons");
17450
- if (removed.length > 0 && existsSync18(addons) && readdirSync12(addons).length === 0) {
17583
+ if (removed.length > 0 && existsSync19(addons) && readdirSync12(addons).length === 0) {
17451
17584
  rmdirSync(addons);
17452
17585
  removed.push(addons);
17453
17586
  }
@@ -17547,8 +17680,8 @@ function inspectProject(projectPath) {
17547
17680
  const addons = ADDONS.map((name) => {
17548
17681
  const directory = join22(projectPath, "addons", name);
17549
17682
  const marker = join22(directory, VERSION_MARKER);
17550
- const installed = existsSync18(directory);
17551
- const version = existsSync18(marker) ? readFileSync21(marker, "utf8").trim() : null;
17683
+ const installed = existsSync19(directory);
17684
+ const version = existsSync19(marker) ? readFileSync21(marker, "utf8").trim() : null;
17552
17685
  const current = version === SERVER_VERSION;
17553
17686
  if (!installed) {
17554
17687
  problems.push(`addons/${name} is not installed; run gdharness setup`);
@@ -17581,7 +17714,7 @@ function inspectProject(projectPath) {
17581
17714
  const ignoredAutoloads = [];
17582
17715
  const addonMissing = (path) => addons.some((addon) => !addon.installed && path.startsWith(`addons/${addon.name}/`));
17583
17716
  for (const [name, path] of named) {
17584
- if (!existsSync18(join22(projectPath, path))) {
17717
+ if (!existsSync19(join22(projectPath, path))) {
17585
17718
  if (!addonMissing(path)) {
17586
17719
  problems.push(`the ${name} autoload names res://${path}, which is not in this project, so it boots with a missing script; restore that file, or point the autoload at one that is here`);
17587
17720
  }
@@ -20152,7 +20285,7 @@ var init_tool_reference = __esm(() => {
20152
20285
  });
20153
20286
 
20154
20287
  // src/suite-plan.ts
20155
- import { existsSync as existsSync22, mkdirSync as mkdirSync9, readFileSync as readFileSync24 } from "node:fs";
20288
+ import { existsSync as existsSync23, mkdirSync as mkdirSync9, readFileSync as readFileSync24 } from "node:fs";
20156
20289
  import { dirname as dirname11, join as join26, posix as posix3 } from "node:path";
20157
20290
  function within(path, folder) {
20158
20291
  return path === folder || path.startsWith(`${folder}/`);
@@ -20564,7 +20697,7 @@ function windowNeedsOf(scripts, paths) {
20564
20697
  }
20565
20698
  function capsFrames(projectPath) {
20566
20699
  const file = `${projectPath}/project.godot`;
20567
- if (!existsSync22(file)) {
20700
+ if (!existsSync23(file)) {
20568
20701
  return false;
20569
20702
  }
20570
20703
  const cap = parseProjectGodot(readFileSync24(file, "utf8"))["application"]?.["run/max_fps"];
@@ -20572,14 +20705,14 @@ function capsFrames(projectPath) {
20572
20705
  }
20573
20706
  function gdUnitFailsOnPushErrors(projectPath) {
20574
20707
  const file = `${projectPath}/project.godot`;
20575
- if (!existsSync22(file)) {
20708
+ if (!existsSync23(file)) {
20576
20709
  return false;
20577
20710
  }
20578
20711
  return parseProjectGodot(readFileSync24(file, "utf8"))["gdunit4"]?.["report/godot/push_error"] === true;
20579
20712
  }
20580
20713
  function viewportOf(projectPath) {
20581
20714
  const file = `${projectPath}/project.godot`;
20582
- if (!existsSync22(file)) {
20715
+ if (!existsSync23(file)) {
20583
20716
  return null;
20584
20717
  }
20585
20718
  const text = readFileSync24(file, "utf8");
@@ -42201,7 +42334,7 @@ var init_stdio = __esm(() => {
42201
42334
  });
42202
42335
 
42203
42336
  // src/autoload-failure.ts
42204
- import { existsSync as existsSync24, readFileSync as readFileSync27 } from "node:fs";
42337
+ import { existsSync as existsSync25, readFileSync as readFileSync27 } from "node:fs";
42205
42338
  import { join as join29 } from "node:path";
42206
42339
  function scriptsAutoloaded(projectPath) {
42207
42340
  const scripts = new Map;
@@ -42217,7 +42350,7 @@ function scriptsAutoloaded(projectPath) {
42217
42350
  continue;
42218
42351
  }
42219
42352
  const scene = join29(projectPath, path);
42220
- if (!existsSync24(scene)) {
42353
+ if (!existsSync25(scene)) {
42221
42354
  continue;
42222
42355
  }
42223
42356
  try {
@@ -42240,7 +42373,7 @@ var init_autoload_failure = __esm(() => {
42240
42373
  });
42241
42374
 
42242
42375
  // src/runtime-client.ts
42243
- import { existsSync as existsSync25, readdirSync as readdirSync16, readFileSync as readFileSync28, statSync as statSync15, unlinkSync as unlinkSync3 } from "node:fs";
42376
+ import { existsSync as existsSync26, readdirSync as readdirSync16, readFileSync as readFileSync28, statSync as statSync15, unlinkSync as unlinkSync3 } from "node:fs";
42244
42377
  import { createConnection as createConnection2 } from "node:net";
42245
42378
  import { tmpdir as tmpdir7 } from "node:os";
42246
42379
  import { dirname as dirname14, join as join30, resolve as resolve12 } from "node:path";
@@ -42264,7 +42397,7 @@ function runtimeDirectories(variables = process.env) {
42264
42397
  function errorReportOf(pid, directories = runtimeDirectories()) {
42265
42398
  for (const directory of directories) {
42266
42399
  const path = join30(directory, `runtime-${pid}.log`);
42267
- if (existsSync25(path)) {
42400
+ if (existsSync26(path)) {
42268
42401
  return path;
42269
42402
  }
42270
42403
  }
@@ -42410,7 +42543,7 @@ function strangersAmong(candidates, now, startTimes = startTimesOf) {
42410
42543
  }).map((one) => one.file));
42411
42544
  }
42412
42545
  function announcedIn(directory) {
42413
- if (!existsSync25(directory)) {
42546
+ if (!existsSync26(directory)) {
42414
42547
  return [];
42415
42548
  }
42416
42549
  const found = [];
@@ -42463,7 +42596,7 @@ function announcedIn(directory) {
42463
42596
  return found;
42464
42597
  }
42465
42598
  async function announcementEnded(pid, directories = runtimeDirectories()) {
42466
- const files = directories.map((directory) => join30(directory, `runtime-${pid}.json`)).filter((file) => existsSync25(file));
42599
+ const files = directories.map((directory) => join30(directory, `runtime-${pid}.json`)).filter((file) => existsSync26(file));
42467
42600
  const first = files[0];
42468
42601
  if (first === undefined) {
42469
42602
  return;
@@ -43042,11 +43175,11 @@ var init_class_note = __esm(() => {
43042
43175
  });
43043
43176
 
43044
43177
  // src/config-pin.ts
43045
- import { existsSync as existsSync26, readFileSync as readFileSync32 } from "node:fs";
43178
+ import { existsSync as existsSync27, readFileSync as readFileSync32 } from "node:fs";
43046
43179
  import { join as join34 } from "node:path";
43047
43180
  function versionsNamedInConfig(projectPath) {
43048
43181
  const config = join34(projectPath, ".mcp.json");
43049
- if (!existsSync26(config)) {
43182
+ if (!existsSync27(config)) {
43050
43183
  return [];
43051
43184
  }
43052
43185
  let text;
@@ -43072,7 +43205,7 @@ var init_config_pin = __esm(() => {
43072
43205
  });
43073
43206
 
43074
43207
  // src/cut-test-run.ts
43075
- import { existsSync as existsSync27, mkdirSync as mkdirSync14, readFileSync as readFileSync33, rmSync as rmSync15, writeFileSync as writeFileSync16 } from "node:fs";
43208
+ import { existsSync as existsSync28, mkdirSync as mkdirSync14, readFileSync as readFileSync33, rmSync as rmSync15, writeFileSync as writeFileSync16 } from "node:fs";
43076
43209
  import { dirname as dirname18, join as join35 } from "node:path";
43077
43210
  function keptAt(projectPath) {
43078
43211
  return join35(projectPath, ".godot", "gdharness-reports", "cut-run.json");
@@ -43087,7 +43220,7 @@ function keepCutTestRun(projectPath, run) {
43087
43220
  }
43088
43221
  function takeCutTestRun(projectPath) {
43089
43222
  const path = keptAt(projectPath);
43090
- if (!existsSync27(path)) {
43223
+ if (!existsSync28(path)) {
43091
43224
  return null;
43092
43225
  }
43093
43226
  try {
@@ -43855,7 +43988,7 @@ var init_dap_client = __esm(() => {
43855
43988
  // src/editor-log.ts
43856
43989
  import {
43857
43990
  closeSync as closeSync5,
43858
- existsSync as existsSync28,
43991
+ existsSync as existsSync29,
43859
43992
  mkdirSync as mkdirSync15,
43860
43993
  openSync as openSync5,
43861
43994
  readFileSync as readFileSync34,
@@ -43919,7 +44052,7 @@ function editorConsole(projectPath, editorPid, openedByAServer) {
43919
44052
  return { kind: "another editor", notedPid: noted?.pid ?? null };
43920
44053
  }
43921
44054
  const path = editorLogPath(projectPath);
43922
- if (!existsSync28(path)) {
44055
+ if (!existsSync29(path)) {
43923
44056
  return { kind: "not written" };
43924
44057
  }
43925
44058
  const log = new GameLog;
@@ -44138,7 +44271,7 @@ var init_editor_log = __esm(() => {
44138
44271
  });
44139
44272
 
44140
44273
  // src/rename.ts
44141
- import { existsSync as existsSync29, mkdirSync as mkdirSync16, readFileSync as readFileSync35, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync18 } from "node:fs";
44274
+ import { existsSync as existsSync30, mkdirSync as mkdirSync16, readFileSync as readFileSync35, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync18 } from "node:fs";
44142
44275
  import { dirname as dirname20, posix as posix4 } from "node:path";
44143
44276
 
44144
44277
  class Script {
@@ -44863,7 +44996,7 @@ function applyRewrites(rewrites) {
44863
44996
  if (now !== rewrite.before) {
44864
44997
  throw new Error(`${rewrite.path} changed on disk while the rename was being worked out; nothing was written`);
44865
44998
  }
44866
- if (rewrite.writeTo !== rewrite.absolute && existsSync29(rewrite.writeTo)) {
44999
+ if (rewrite.writeTo !== rewrite.absolute && existsSync30(rewrite.writeTo)) {
44867
45000
  throw new Error(`${rewrite.writeTo} already exists; nothing was written`);
44868
45001
  }
44869
45002
  }
@@ -44877,7 +45010,7 @@ function applyRewrites(rewrites) {
44877
45010
  let movedUid = false;
44878
45011
  if (rewrite.writeTo !== rewrite.absolute) {
44879
45012
  unlinkSync4(rewrite.absolute);
44880
- if (existsSync29(`${rewrite.absolute}.uid`)) {
45013
+ if (existsSync30(`${rewrite.absolute}.uid`)) {
44881
45014
  renameSync4(`${rewrite.absolute}.uid`, `${rewrite.writeTo}.uid`);
44882
45015
  movedUid = true;
44883
45016
  }
@@ -44923,7 +45056,7 @@ var init_rename = __esm(() => {
44923
45056
  });
44924
45057
 
44925
45058
  // src/rename-symbol.ts
44926
- import { existsSync as existsSync30, mkdirSync as mkdirSync17, readdirSync as readdirSync17, realpathSync as realpathSync5, rmSync as rmSync17, writeFileSync as writeFileSync19 } from "node:fs";
45059
+ import { existsSync as existsSync31, mkdirSync as mkdirSync17, readdirSync as readdirSync17, realpathSync as realpathSync6, rmSync as rmSync17, writeFileSync as writeFileSync19 } from "node:fs";
44927
45060
  import { basename as basename10, dirname as dirname21, join as join37, relative as relative7, resolve as resolve13 } from "node:path";
44928
45061
  function resourcePathOf(projectPath, absolute) {
44929
45062
  const inside = relative7(onDiskSpelling(projectPath), onDiskSpelling(absolute));
@@ -44937,7 +45070,7 @@ function onDiskSpelling(path) {
44937
45070
  let at = resolve13(path);
44938
45071
  for (;; ) {
44939
45072
  try {
44940
- return join37(realpathSync5.native(at), ...missing.reverse());
45073
+ return join37(realpathSync6.native(at), ...missing.reverse());
44941
45074
  } catch {
44942
45075
  const parent = dirname21(at);
44943
45076
  if (parent === at) {
@@ -44991,7 +45124,7 @@ async function renameSymbol(request, services) {
44991
45124
  reason: `newScriptPath must be a .gd path inside the project, and ${request.newScriptPath} is not.`
44992
45125
  };
44993
45126
  }
44994
- if (existsSync30(request.newScriptPath)) {
45127
+ if (existsSync31(request.newScriptPath)) {
44995
45128
  return { ok: false, reason: `${moveTo} already exists, so the script cannot be moved there.` };
44996
45129
  }
44997
45130
  }
@@ -45168,7 +45301,7 @@ async function renameSymbol(request, services) {
45168
45301
  scripts,
45169
45302
  moves: new Map([[declaringPath, moveTo]]),
45170
45303
  named: [declaringPath],
45171
- exists: (path) => existsSync30(`${projectPath}/${path.slice("res://".length)}`)
45304
+ exists: (path) => existsSync31(`${projectPath}/${path.slice("res://".length)}`)
45172
45305
  }, plan);
45173
45306
  }
45174
45307
  plan = mentionIgnored(plan, ignoredTexts(projectPath), symbol, moveTo === null ? [] : [declaringPath]);
@@ -45443,7 +45576,7 @@ var init_rename_symbol = __esm(() => {
45443
45576
 
45444
45577
  // src/file-move.ts
45445
45578
  import {
45446
- existsSync as existsSync31,
45579
+ existsSync as existsSync32,
45447
45580
  mkdirSync as mkdirSync18,
45448
45581
  readdirSync as readdirSync18,
45449
45582
  readFileSync as readFileSync36,
@@ -45476,7 +45609,7 @@ function unseenByTheEngine(projectPath, path) {
45476
45609
  }
45477
45610
  if (at < steps.length - 1) {
45478
45611
  directory = join38(directory, step);
45479
- if (existsSync31(join38(directory, ".gdignore"))) {
45612
+ if (existsSync32(join38(directory, ".gdignore"))) {
45480
45613
  return `${path} is under a directory holding a .gdignore, which the engine does not load`;
45481
45614
  }
45482
45615
  }
@@ -45488,12 +45621,12 @@ function installedAddonOf(projectPath, path) {
45488
45621
  if (steps[0] !== "addons" || steps[1] === undefined) {
45489
45622
  return null;
45490
45623
  }
45491
- return existsSync31(join38(projectPath, "addons", steps[1], VERSION_MARKER)) ? `res://addons/${steps[1]}` : null;
45624
+ return existsSync32(join38(projectPath, "addons", steps[1], VERSION_MARKER)) ? `res://addons/${steps[1]}` : null;
45492
45625
  }
45493
45626
  function binaryResources(projectPath) {
45494
45627
  const found = [];
45495
45628
  const visit = (directory, prefix) => {
45496
- if (existsSync31(join38(directory, ".gdignore"))) {
45629
+ if (existsSync32(join38(directory, ".gdignore"))) {
45497
45630
  return;
45498
45631
  }
45499
45632
  for (const entry of readdirSync18(directory, { withFileTypes: true })) {
@@ -45530,7 +45663,7 @@ function planFileMove(projectPath, absoluteFrom, absoluteTo) {
45530
45663
  if (to === null) {
45531
45664
  return { ok: false, reason: `newPath must be a path inside the project, and ${absoluteTo} is not.` };
45532
45665
  }
45533
- if (!existsSync31(absoluteFrom)) {
45666
+ if (!existsSync32(absoluteFrom)) {
45534
45667
  return { ok: false, reason: `There is nothing at ${from} to move.` };
45535
45668
  }
45536
45669
  if (from === to) {
@@ -45559,7 +45692,7 @@ function planFileMove(projectPath, absoluteFrom, absoluteTo) {
45559
45692
  if (isDirectory && to.startsWith(`${from}/`)) {
45560
45693
  return { ok: false, reason: `${from} cannot be moved into itself.` };
45561
45694
  }
45562
- if (existsSync31(absoluteTo) && !sameFile(absoluteFrom, absoluteTo)) {
45695
+ if (existsSync32(absoluteTo) && !sameFile(absoluteFrom, absoluteTo)) {
45563
45696
  return { ok: false, reason: `${to} already exists, so nothing was moved there.` };
45564
45697
  }
45565
45698
  const unseen = unseenByTheEngine(projectPath, to);
@@ -45567,7 +45700,7 @@ function planFileMove(projectPath, absoluteFrom, absoluteTo) {
45567
45700
  return { ok: false, reason: `${unseen}, so nothing there could load what was moved.` };
45568
45701
  }
45569
45702
  if (!isDirectory) {
45570
- const owner = SIDECARS.map((sidecar) => from.endsWith(sidecar) ? from.slice(0, -sidecar.length) : null).find((path) => path !== null && existsSync31(join38(projectPath, path.slice("res://".length))));
45703
+ const owner = SIDECARS.map((sidecar) => from.endsWith(sidecar) ? from.slice(0, -sidecar.length) : null).find((path) => path !== null && existsSync32(join38(projectPath, path.slice("res://".length))));
45571
45704
  if (owner !== undefined && owner !== null) {
45572
45705
  return { ok: false, reason: `${from} belongs to ${owner} and moves with it: move ${owner} instead.` };
45573
45706
  }
@@ -45589,7 +45722,7 @@ function planFileMove(projectPath, absoluteFrom, absoluteTo) {
45589
45722
  } else {
45590
45723
  moves.set(from, to);
45591
45724
  for (const sidecar of SIDECARS) {
45592
- if (existsSync31(`${absoluteFrom}${sidecar}`)) {
45725
+ if (existsSync32(`${absoluteFrom}${sidecar}`)) {
45593
45726
  moves.set(`${from}${sidecar}`, `${to}${sidecar}`);
45594
45727
  }
45595
45728
  }
@@ -45601,7 +45734,7 @@ function planFileMove(projectPath, absoluteFrom, absoluteTo) {
45601
45734
  scripts,
45602
45735
  moves,
45603
45736
  named: [from],
45604
- exists: (path) => existsSync31(join38(projectPath, path.slice("res://".length)))
45737
+ exists: (path) => existsSync32(join38(projectPath, path.slice("res://".length)))
45605
45738
  }, { edits: [], mentions: [] });
45606
45739
  plan = mentionIgnored(plan, ignoredTexts(projectPath), null, [from]);
45607
45740
  const binaries = [];
@@ -45672,13 +45805,13 @@ function applyFileMove(outcome) {
45672
45805
  }
45673
45806
  }
45674
45807
  for (const file of outcome.moved) {
45675
- if (!existsSync31(file.absoluteFrom)) {
45808
+ if (!existsSync32(file.absoluteFrom)) {
45676
45809
  throw new Error(`${file.from} is gone from disk; nothing was written`);
45677
45810
  }
45678
45811
  if (file.text !== null && readFileSync36(file.absoluteFrom, "utf8") !== file.text.before) {
45679
45812
  throw new Error(`${file.from} changed on disk while the move was being worked out; nothing was written`);
45680
45813
  }
45681
- if (existsSync31(file.absoluteTo) && !sameFile(file.absoluteFrom, file.absoluteTo)) {
45814
+ if (existsSync32(file.absoluteTo) && !sameFile(file.absoluteFrom, file.absoluteTo)) {
45682
45815
  throw new Error(`${file.to} already exists; nothing was written`);
45683
45816
  }
45684
45817
  }
@@ -50404,10 +50537,10 @@ var init_server_instructions = __esm(() => {
50404
50537
  });
50405
50538
 
50406
50539
  // src/suites-scene.ts
50407
- import { existsSync as existsSync32, mkdirSync as mkdirSync22, writeFileSync as writeFileSync22 } from "node:fs";
50540
+ import { existsSync as existsSync33, mkdirSync as mkdirSync22, writeFileSync as writeFileSync22 } from "node:fs";
50408
50541
  import { join as join42, relative as relative9, sep as sep5 } from "node:path";
50409
50542
  function hasSuitesScene(projectPath) {
50410
- return existsSync32(join42(projectPath, SUITES_SCENE));
50543
+ return existsSync33(join42(projectPath, SUITES_SCENE));
50411
50544
  }
50412
50545
  function suitesSceneArgs(projectPath, suites) {
50413
50546
  const runs = join42(projectPath, ".godot", "gdharness", "suite-scenes");
@@ -50442,7 +50575,7 @@ var init_suites_scene = __esm(() => {
50442
50575
  });
50443
50576
 
50444
50577
  // src/test-selection.ts
50445
- import { existsSync as existsSync33 } from "node:fs";
50578
+ import { existsSync as existsSync34 } from "node:fs";
50446
50579
  import { basename as basename13, join as join43 } from "node:path";
50447
50580
  function casesOutOfPath(projectPath, given, tests) {
50448
50581
  const entries = Array.isArray(given) ? given : [given];
@@ -50487,12 +50620,12 @@ function casesIn(scripts, suite) {
50487
50620
  }
50488
50621
  function scriptsWithoutCases(projectPath, asked) {
50489
50622
  const scripts = new ProjectScripts(projectPath);
50490
- return asked.filter((path) => path.endsWith(".gd") && existsSync33(join43(projectPath, path.slice("res://".length))) && casesIn(scripts, path).length === 0);
50623
+ return asked.filter((path) => path.endsWith(".gd") && existsSync34(join43(projectPath, path.slice("res://".length))) && casesIn(scripts, path).length === 0);
50491
50624
  }
50492
50625
  function suitesUnder(projectPath, asked) {
50493
50626
  const scripts = projectFiles(projectPath, [".gd"]).map((path) => `res://${path}`);
50494
50627
  return [
50495
- ...new Set(asked.flatMap((path) => path.endsWith(".gd") ? existsSync33(join43(projectPath, path.slice("res://".length))) ? [path] : [] : scripts.filter((script) => script.startsWith(`${path}/`))))
50628
+ ...new Set(asked.flatMap((path) => path.endsWith(".gd") ? existsSync34(join43(projectPath, path.slice("res://".length))) ? [path] : [] : scripts.filter((script) => script.startsWith(`${path}/`))))
50496
50629
  ];
50497
50630
  }
50498
50631
  function selectTests(projectPath, asked, given) {
@@ -50558,14 +50691,14 @@ import {
50558
50691
  closeSync as closeSync6,
50559
50692
  constants,
50560
50693
  copyFileSync as copyFileSync2,
50561
- existsSync as existsSync34,
50694
+ existsSync as existsSync35,
50562
50695
  fstatSync as fstatSync3,
50563
50696
  mkdirSync as mkdirSync23,
50564
50697
  openSync as openSync7,
50565
50698
  readdirSync as readdirSync20,
50566
50699
  readFileSync as readFileSync40,
50567
50700
  readSync as readSync4,
50568
- realpathSync as realpathSync6,
50701
+ realpathSync as realpathSync7,
50569
50702
  rmdirSync as rmdirSync2,
50570
50703
  statSync as statSync20,
50571
50704
  writeFileSync as writeFileSync23
@@ -50586,7 +50719,7 @@ function greetingWaitMs() {
50586
50719
  function pictureToSend(pngPath, jpegPath) {
50587
50720
  const png = readFileSync40(pngPath);
50588
50721
  const beside = pngPath.replace(/\.png$/, ".jpg");
50589
- const jpeg = jpegPath !== undefined && normalize2(jpegPath) === normalize2(beside) && existsSync34(beside) ? readFileSync40(beside) : null;
50722
+ const jpeg = jpegPath !== undefined && normalize2(jpegPath) === normalize2(beside) && existsSync35(beside) ? readFileSync40(beside) : null;
50590
50723
  const sent = jpeg !== null && jpeg.length < png.length ? jpeg : png;
50591
50724
  return {
50592
50725
  data: sent.toString("base64"),
@@ -50626,7 +50759,7 @@ function writtenFileRefusal(path, rule) {
50626
50759
  return `${named} ${path} does not end in ${rule.extensions.join(" or ")}, which is what ${what} is.`;
50627
50760
  }
50628
50761
  const directory = realAsFarAsItExists(dirname25(path));
50629
- if (!existsSync34(directory)) {
50762
+ if (!existsSync35(directory)) {
50630
50763
  return `${named}'s directory ${dirname25(path)} does not exist; ${what} creates no directories.`;
50631
50764
  }
50632
50765
  const where = join44(directory, basename14(path));
@@ -50634,7 +50767,7 @@ function writtenFileRefusal(path, rule) {
50634
50767
  if (inside !== undefined) {
50635
50768
  return `${named} ${path} is inside the project at ${inside}; ${what} is saved outside it, so it never becomes part of the game.`;
50636
50769
  }
50637
- const taken = rule.writes(where).find((file) => existsSync34(file));
50770
+ const taken = rule.writes(where).find((file) => existsSync35(file));
50638
50771
  if (taken !== undefined) {
50639
50772
  return taken === where ? `${named} ${path} already exists; ${what} is not written over a file. Name a new one.` : `${named} ${path} would write ${taken}, which already exists; ${what} is not written over a file. Name a new one.`;
50640
50773
  }
@@ -51420,7 +51553,7 @@ function unsavedInEditorNote(scripts) {
51420
51553
  return `${named} ${one ? "is" : "are"} open in the editor's script ${one ? "tab" : "tabs"} with unsaved edits, and saving ${one ? "that tab" : "them"} there writes ${one ? "its" : "their"} text over what was written here: close ${one ? "it" : "them"} without saving, or save first and edit again.`;
51421
51554
  }
51422
51555
  function editorAddonMissing(projectPath) {
51423
- if (!existsSync34(join44(projectPath, "project.godot"))) {
51556
+ if (!existsSync35(join44(projectPath, "project.godot"))) {
51424
51557
  return null;
51425
51558
  }
51426
51559
  const report = inspectProject(projectPath);
@@ -51964,7 +52097,7 @@ function uncaughtNote(uncaught) {
51964
52097
  }
51965
52098
  function elsewhereIn(projectPath, asked) {
51966
52099
  const wanted = asked.replace(/^res:\/\//, "").replace(/\/+$/, "");
51967
- if (wanted === "" || existsSync34(join44(projectPath, wanted))) {
52100
+ if (wanted === "" || existsSync35(join44(projectPath, wanted))) {
51968
52101
  return "";
51969
52102
  }
51970
52103
  const root = (wanted.split("/")[0] ?? "").toLowerCase();
@@ -51987,7 +52120,7 @@ function windowNoteFor(needing, sharing) {
51987
52120
  return `${named(needing)} ${one ? "needs" : "need"} a window, as gdharness test reads ${one ? "it" : "them"}, so the run had one: the engine ran without --headless, at the size project.godot gives its viewport, with no sound${process.platform === "win32" ? ", on a desktop of its own, where its window neither shows nor takes the keyboard" : ""}. ${why}${shared}`;
51988
52121
  }
51989
52122
  function testPathsIn(projectPath, given, named = "path") {
51990
- const defaults = TEST_DIRECTORIES.filter((directory) => existsSync34(join44(projectPath, directory)));
52123
+ const defaults = TEST_DIRECTORIES.filter((directory) => existsSync35(join44(projectPath, directory)));
51991
52124
  const entries = given === undefined || given === null || given === "" ? defaults.length > 0 ? defaults : TEST_DIRECTORIES : given;
51992
52125
  const listed = Array.isArray(entries) ? entries : [entries];
51993
52126
  if (listed.length === 0) {
@@ -52412,7 +52545,7 @@ class GodotServer {
52412
52545
  argv: process.argv.slice(1),
52413
52546
  cwd,
52414
52547
  project: this.ownProject,
52415
- mcpJson: existsSync34(mcpJson) ? mcpJson : null
52548
+ mcpJson: existsSync35(mcpJson) ? mcpJson : null
52416
52549
  });
52417
52550
  if (predecessor !== null) {
52418
52551
  writeLifecycle("replaced", { project: this.ownProject, predecessor });
@@ -52554,7 +52687,7 @@ class GodotServer {
52554
52687
  return checked.response;
52555
52688
  }
52556
52689
  const named = args["projectPath"];
52557
- if (typeof named === "string" && existsSync34(join44(named, "project.godot"))) {
52690
+ if (typeof named === "string" && existsSync35(join44(named, "project.godot"))) {
52558
52691
  this.lastProjectPath = named;
52559
52692
  }
52560
52693
  this.updates.refresh();
@@ -53190,7 +53323,7 @@ class GodotServer {
53190
53323
  return this.createErrorResponse("line is required: the one-based line to stop on.");
53191
53324
  }
53192
53325
  if (op === "set") {
53193
- if (!existsSync34(located.absolutePath)) {
53326
+ if (!existsSync35(located.absolutePath)) {
53194
53327
  return this.missingScript(project.value.path, located.relativePath);
53195
53328
  }
53196
53329
  const nothing = lineNothingStopsOn(located.absolutePath, located.relativePath, line);
@@ -53295,7 +53428,7 @@ class GodotServer {
53295
53428
  return { ok: false, response: this.createErrorResponse("projectPath is required.") };
53296
53429
  }
53297
53430
  const file = join44(path, "project.godot");
53298
- if (!existsSync34(file)) {
53431
+ if (!existsSync35(file)) {
53299
53432
  return {
53300
53433
  ok: false,
53301
53434
  response: this.createErrorResponse(`Not a Godot project: ${path}`, [
@@ -54121,11 +54254,11 @@ class GodotServer {
54121
54254
  if (place !== null && !place.ok) {
54122
54255
  return this.createErrorResponse(place.reason);
54123
54256
  }
54124
- if (place !== null && !existsSync34(place.absolutePath)) {
54257
+ if (place !== null && !existsSync35(place.absolutePath)) {
54125
54258
  const folders = readdirSync20(project.value.path, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name).sort();
54126
54259
  return this.createErrorResponse(`There is nothing at res://${place.relativePath} to search.${folders.length === 0 ? "" : ` The project's folders are ${folders.join(", ")}.`}`);
54127
54260
  }
54128
- if (place !== null && !isWithinRoot(realpathSync6.native(project.value.path), realpathSync6.native(place.absolutePath))) {
54261
+ if (place !== null && !isWithinRoot(realpathSync7.native(project.value.path), realpathSync7.native(place.absolutePath))) {
54129
54262
  return this.createErrorResponse(`res://${place.relativePath} leads outside the project through a link, so it is not searched.`);
54130
54263
  }
54131
54264
  try {
@@ -54312,7 +54445,7 @@ ${platform}`;
54312
54445
  output.absolutePath
54313
54446
  ];
54314
54447
  this.logDebug(`Exporting: ${engine.value} ${exportArgs.join(" ")}`);
54315
- const writtenAt = () => existsSync34(output.absolutePath) ? statSync20(output.absolutePath).mtimeMs : null;
54448
+ const writtenAt = () => existsSync35(output.absolutePath) ? statSync20(output.absolutePath).mtimeMs : null;
54316
54449
  const caches = editorCacheDirectory(engine.value);
54317
54450
  const exportOnce = async () => {
54318
54451
  const before = writtenAt();
@@ -54342,7 +54475,7 @@ ${platform}`;
54342
54475
  return this.createErrorResponse(`Export could not be run: ${ending.failure ?? "the engine gave no exit status"}`);
54343
54476
  }
54344
54477
  const beside = writtenBeside(listedBefore, filesIn(folder), basename14(output.absolutePath), dirname25(output.relativePath).replaceAll("\\", "/"));
54345
- return exportAnswer(ending, { preset, outputPath: output.relativePath, debug, ...pack ? { pack } : {} }, before, writtenAt(), beside, docCacheNote, existsSync34(output.absolutePath) ? statSync20(output.absolutePath).size : null, importedFirstAnswer(imported));
54478
+ return exportAnswer(ending, { preset, outputPath: output.relativePath, debug, ...pack ? { pack } : {} }, before, writtenAt(), beside, docCacheNote, existsSync35(output.absolutePath) ? statSync20(output.absolutePath).size : null, importedFirstAnswer(imported));
54346
54479
  }
54347
54480
  reportTestProgress(log) {
54348
54481
  const progress = callProgress();
@@ -54403,7 +54536,7 @@ ${platform}`;
54403
54536
  if (movie !== null) {
54404
54537
  return this.createErrorResponse(movie);
54405
54538
  }
54406
- const missing = paths.value.filter((path) => !existsSync34(join44(project.value.path, path.slice("res://".length))));
54539
+ const missing = paths.value.filter((path) => !existsSync35(join44(project.value.path, path.slice("res://".length))));
54407
54540
  const projectScripts = new ProjectScripts(project.value.path);
54408
54541
  const present = paths.value.filter((path) => !missing.includes(path));
54409
54542
  const asked = projectScripts.searchedAsTold(present);
@@ -54595,7 +54728,7 @@ ${platform}`;
54595
54728
  await untilGone([run.process.pid]);
54596
54729
  }
54597
54730
  await run.settled;
54598
- const helperFailed = onDesktop ? helperFailure(helperFiles.error) ?? (existsSync34(helperFiles.pid) ? null : `it never started, and ${helperStep(helperFiles.step)}`) : null;
54731
+ const helperFailed = onDesktop ? helperFailure(helperFiles.error) ?? (existsSync35(helperFiles.pid) ? null : `it never started, and ${helperStep(helperFiles.step)}`) : null;
54599
54732
  if (helperFailed !== null) {
54600
54733
  discard(join44(project.value.path, ".godot", ...ours.split("/")), userData);
54601
54734
  return this.createErrorResponse(`No tests ran: ${named(needing)} ${needing.length === 1 ? "needs" : "need"} a window, and the engine could not be started on a desktop of its own: ${helperFailed}`);
@@ -54611,10 +54744,10 @@ ${platform}`;
54611
54744
  const reportsDir = join44(project.value.path, ".godot", ...ours.split("/"));
54612
54745
  let report = null;
54613
54746
  let reportProblem = null;
54614
- const casePrinted = withNestedErrors(readRun(existsSync34(engineLog) ? readFileSync40(engineLog, "utf8") : ""), run.log.all);
54747
+ const casePrinted = withNestedErrors(readRun(existsSync35(engineLog) ? readFileSync40(engineLog, "utf8") : ""), run.log.all);
54615
54748
  const declaredErrors = readExpected(expectedFile);
54616
54749
  try {
54617
- const written = existsSync34(reportsDir) && notCompiled === null ? readdirSync20(reportsDir).filter((name) => name.startsWith("report_")).sort((a, b) => Number(a.slice("report_".length)) - Number(b.slice("report_".length))) : [];
54750
+ const written = existsSync35(reportsDir) && notCompiled === null ? readdirSync20(reportsDir).filter((name) => name.startsWith("report_")).sort((a, b) => Number(a.slice("report_".length)) - Number(b.slice("report_".length))) : [];
54618
54751
  const newest = written.at(-1);
54619
54752
  if (newest !== undefined) {
54620
54753
  report = parseJUnit(readFileSync40(join44(reportsDir, newest, "results.xml"), "utf8"));
@@ -54941,7 +55074,7 @@ ${error.text}`;
54941
55074
  if (!location.ok) {
54942
55075
  return this.createErrorResponse(location.reason, PATH_SOLUTIONS);
54943
55076
  }
54944
- if (!existsSync34(location.absolutePath)) {
55077
+ if (!existsSync35(location.absolutePath)) {
54945
55078
  return this.missingScript(project.value.path, location.relativePath);
54946
55079
  }
54947
55080
  ignored = scriptsUnderGdignore(project.value.path, [location.relativePath]);
@@ -55031,7 +55164,7 @@ ${error.text}`;
55031
55164
  const wanted = `res://${relativePath}`;
55032
55165
  const folder = dirname25(relativePath.replaceAll("\\", "/"));
55033
55166
  const inFolder = join44(projectPath, folder);
55034
- const beside = existsSync34(inFolder) ? readdirSync20(inFolder, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => `res://${folder === "." ? "" : `${folder}/`}${entry.name}`) : [];
55167
+ const beside = existsSync35(inFolder) ? readdirSync20(inFolder, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => `res://${folder === "." ? "" : `${folder}/`}${entry.name}`) : [];
55035
55168
  return this.createErrorResponse(withNearestFiles(`Script file does not exist: ${wanted}`, wanted, scripts, beside));
55036
55169
  }
55037
55170
  async compileScripts(projectPath, paths) {
@@ -55159,7 +55292,7 @@ ${error.text}`;
55159
55292
  const cached = cachedClasses(projectPath);
55160
55293
  const sourceOf = (resourcePath) => {
55161
55294
  const contained = resolveWithinProject(projectPath, resourcePath);
55162
- if (!contained.ok || !existsSync34(contained.absolutePath)) {
55295
+ if (!contained.ok || !existsSync35(contained.absolutePath)) {
55163
55296
  return null;
55164
55297
  }
55165
55298
  try {
@@ -55253,7 +55386,7 @@ ${error.text}`;
55253
55386
  }
55254
55387
  sourceOfClass(projectPath, resourcePath) {
55255
55388
  const contained = resolveWithinProject(projectPath, resourcePath);
55256
- if (!contained.ok || !existsSync34(contained.absolutePath)) {
55389
+ if (!contained.ok || !existsSync35(contained.absolutePath)) {
55257
55390
  return null;
55258
55391
  }
55259
55392
  try {
@@ -56121,7 +56254,7 @@ ${error.text}`;
56121
56254
  if (!paths.ok) {
56122
56255
  return refused(paths.reason, PATH_SOLUTIONS);
56123
56256
  }
56124
- const missing = paths.value.filter((path) => !existsSync34(join44(projectPath, path.slice("res://".length))));
56257
+ const missing = paths.value.filter((path) => !existsSync35(join44(projectPath, path.slice("res://".length))));
56125
56258
  if (missing.length > 0) {
56126
56259
  return refused(`Nothing at ${missing.join(" and ")} in the project at ${projectPath}.`, PATH_SOLUTIONS);
56127
56260
  }
@@ -56166,7 +56299,7 @@ ${error.text}`;
56166
56299
  return this.createErrorResponse(sceneToRun.reason, PATH_SOLUTIONS);
56167
56300
  }
56168
56301
  const build = readNonEmptyString(args, "executable");
56169
- if (build === undefined && sceneToRun?.ok && !existsSync34(sceneToRun.absolutePath)) {
56302
+ if (build === undefined && sceneToRun?.ok && !existsSync35(sceneToRun.absolutePath)) {
56170
56303
  return this.createErrorResponse(`No scene at res://${sceneToRun.relativePath} in the project at ${project.value.path}.`, PATH_SOLUTIONS);
56171
56304
  }
56172
56305
  const exported = build === undefined ? null : exportedBuild(project.value.path, build);
@@ -56294,7 +56427,7 @@ ${error.text}`;
56294
56427
  }
56295
56428
  async runtimeUp(projectPath, before, budget, withArgs) {
56296
56429
  const budgetMs = budget.ms;
56297
- if (!existsSync34(join44(projectPath, RUNTIME_SCRIPT))) {
56430
+ if (!existsSync35(join44(projectPath, RUNTIME_SCRIPT))) {
56298
56431
  return runtimeVerdict(null, {
56299
56432
  addon: false,
56300
56433
  budgetMs,
@@ -57370,7 +57503,7 @@ ${error.text}`;
57370
57503
  };
57371
57504
  const going = await this.runStillGoing(run);
57372
57505
  const projectPath = run.projectPath;
57373
- const projectGone = projectPath !== null && !existsSync34(join44(projectPath, "project.godot"));
57506
+ const projectGone = projectPath !== null && !existsSync35(join44(projectPath, "project.godot"));
57374
57507
  if (projectGone && callersName !== undefined) {
57375
57508
  return this.createErrorResponse(`callersOf reads the project's scripts, and the run's project at ${projectPath} has no project.godot any more.`, ["editor_run profile without callersOf answers with the profile itself"]);
57376
57509
  }
@@ -57777,7 +57910,7 @@ ${error.text}`;
57777
57910
  notes.push(endedWithoutACode({
57778
57911
  throughEditor: run.throughEditor,
57779
57912
  announced: announced !== undefined || run.announcedPid !== undefined,
57780
- couldAnnounce: run.projectPath !== null && existsSync34(join44(run.projectPath, RUNTIME_SCRIPT)),
57913
+ couldAnnounce: run.projectPath !== null && existsSync35(join44(run.projectPath, RUNTIME_SCRIPT)),
57781
57914
  endedHere: typeof run.endedHere === "string",
57782
57915
  pickedUp: run.pickedUp === true
57783
57916
  }));
@@ -58573,11 +58706,18 @@ ${error.text}`;
58573
58706
  return this.answer(created);
58574
58707
  }
58575
58708
  const rebuilt = await this.rebuildClassCache(project.value.path);
58576
- const registered = cachedClasses(project.value.path)?.get(declared) === readString(created.payload, "full_path");
58709
+ const fullPath = readString(created.payload, "full_path");
58710
+ const registered = cachedClasses(project.value.path)?.get(declared) === fullPath;
58711
+ const recompiled = registered && created.payload["parses"] === false && fullPath !== undefined ? await this.compileScripts(project.value.path, [fullPath]) : null;
58712
+ const parsesOnTheList = recompiled?.ok === true && recompiled.payload.failed.length === 0;
58577
58713
  const answered = this.answer({
58578
58714
  ...created,
58579
58715
  payload: {
58580
58716
  ...created.payload,
58717
+ ...parsesOnTheList ? {
58718
+ parses: true,
58719
+ parsesNote: `The engine that wrote it compiled it against the class list from before, which did not hold ${declared}, so the errors it printed naming ${declared} are its own and not the script's. An engine started on the rebuilt list compiles it.`
58720
+ } : {},
58581
58721
  registered,
58582
58722
  ...registered ? {} : {
58583
58723
  registrationNote: rebuilt.ok ? `The class list was rebuilt and does not hold ${declared} at this script, so nothing started next resolves it by name. project_import refresh_classes says what the list holds and why.` : `The class list could not be rebuilt, so nothing started next resolves ${declared} by name: ${rebuilt.message}`
@@ -58659,7 +58799,7 @@ ${error.text}`;
58659
58799
  if (!scriptPath.ok) {
58660
58800
  return this.createErrorResponse(scriptPath.reason);
58661
58801
  }
58662
- if (!existsSync34(scriptPath.absolutePath)) {
58802
+ if (!existsSync35(scriptPath.absolutePath)) {
58663
58803
  return this.missingScript(projectPath, scriptPath.relativePath);
58664
58804
  }
58665
58805
  const asked = readNonEmptyString(args, "newScriptPath");
@@ -59303,7 +59443,7 @@ ${error.text}`;
59303
59443
  async ownRunOnItsWay(projectPath, budgetMs) {
59304
59444
  const run = await this.currentRun();
59305
59445
  const project = projectPath ?? run?.projectPath ?? null;
59306
- if (run === null || project === null || run.announcedPid !== undefined || run.projectPath !== null && !isSameDirectory(run.projectPath, project) || !existsSync34(join44(project, RUNTIME_SCRIPT)) || !await this.runStillGoing(run)) {
59446
+ if (run === null || project === null || run.announcedPid !== undefined || run.projectPath !== null && !isSameDirectory(run.projectPath, project) || !existsSync35(join44(project, RUNTIME_SCRIPT)) || !await this.runStillGoing(run)) {
59307
59447
  return null;
59308
59448
  }
59309
59449
  const already = runtimesAnnounced().running;
@@ -59756,7 +59896,7 @@ var init_server = __esm(() => {
59756
59896
  init_bridge_announce();
59757
59897
  init_engine_launch();
59758
59898
  init_engine_slots();
59759
- import { existsSync as existsSync35 } from "node:fs";
59899
+ import { existsSync as existsSync36 } from "node:fs";
59760
59900
  import { dirname as dirname26, join as join45, resolve as resolve15 } from "node:path";
59761
59901
 
59762
59902
  // src/error-mode.ts
@@ -59795,7 +59935,7 @@ init_alive();
59795
59935
  init_engine_launch();
59796
59936
  init_lsp_client();
59797
59937
  init_process_children();
59798
- import { existsSync as existsSync17, readdirSync as readdirSync11, readFileSync as readFileSync19, unlinkSync as unlinkSync2 } from "node:fs";
59938
+ import { existsSync as existsSync18, readdirSync as readdirSync11, readFileSync as readFileSync19, unlinkSync as unlinkSync2 } from "node:fs";
59799
59939
  import { connect as connect2 } from "node:net";
59800
59940
  import { join as join21, resolve as resolve8 } from "node:path";
59801
59941
  var EDITOR_RECORD_PROTOCOL = 1;
@@ -59907,7 +60047,7 @@ function lspOptionsOf(args, cwd) {
59907
60047
  }
59908
60048
  }
59909
60049
  const projectPath = resolve8(cwd, named ?? ".");
59910
- if (!existsSync17(join21(projectPath, "project.godot"))) {
60050
+ if (!existsSync18(join21(projectPath, "project.godot"))) {
59911
60051
  throw new EngineUsageError(`Not a Godot project: ${projectPath} holds no project.godot.`);
59912
60052
  }
59913
60053
  return { projectPath, port, waitSeconds };
@@ -60014,7 +60154,7 @@ init_setup();
60014
60154
  init_setup();
60015
60155
  init_tool_definitions();
60016
60156
  init_tool_reference();
60017
- import { existsSync as existsSync19, mkdirSync as mkdirSync7, readdirSync as readdirSync13, rmSync as rmSync11, writeFileSync as writeFileSync12 } from "node:fs";
60157
+ import { existsSync as existsSync20, mkdirSync as mkdirSync7, readdirSync as readdirSync13, rmSync as rmSync11, writeFileSync as writeFileSync12 } from "node:fs";
60018
60158
  import { basename as basename9, dirname as dirname10, join as join23 } from "node:path";
60019
60159
  var SKILL_NAME = "gdharness";
60020
60160
  var SHARED_SKILLS = join23(".agents", "skills");
@@ -60286,7 +60426,7 @@ function everySkillDirectory(projectPath, harnesses) {
60286
60426
  function removeSkill(directories, projectPath) {
60287
60427
  const removed = [];
60288
60428
  for (const directory of directories) {
60289
- if (existsSync19(directory)) {
60429
+ if (existsSync20(directory)) {
60290
60430
  rmSync11(directory, { recursive: true, force: true });
60291
60431
  pruneEmpty(dirname10(directory), projectPath);
60292
60432
  removed.push(directory);
@@ -60308,7 +60448,7 @@ function pruneEmpty(directory, projectPath) {
60308
60448
  function writeSkill(directories, version) {
60309
60449
  const files = skillFiles(version);
60310
60450
  return directories.map((directory) => {
60311
- const replaced = existsSync19(directory);
60451
+ const replaced = existsSync20(directory);
60312
60452
  rmSync11(directory, { recursive: true, force: true });
60313
60453
  for (const [name, contents] of files) {
60314
60454
  const path = join23(directory, name);
@@ -60325,7 +60465,7 @@ init_engine_slots();
60325
60465
  init_log_read();
60326
60466
  init_setup();
60327
60467
  init_suite_judge();
60328
- import { existsSync as existsSync20, mkdirSync as mkdirSync8, readFileSync as readFileSync22, rmSync as rmSync12 } from "node:fs";
60468
+ import { existsSync as existsSync21, mkdirSync as mkdirSync8, readFileSync as readFileSync22, rmSync as rmSync12 } from "node:fs";
60329
60469
  import { availableParallelism as availableParallelism4 } from "node:os";
60330
60470
  import { join as join24, resolve as resolve10 } from "node:path";
60331
60471
  import process13 from "node:process";
@@ -60367,9 +60507,9 @@ function spreadOptionsOf(args, cwd) {
60367
60507
  }
60368
60508
  const first = positional[0];
60369
60509
  const named = first === undefined ? null : resolve10(cwd, first);
60370
- const projectNamed = named !== null && existsSync20(join24(named, "project.godot"));
60510
+ const projectNamed = named !== null && existsSync21(join24(named, "project.godot"));
60371
60511
  const projectPath = projectNamed ? named : resolve10(cwd);
60372
- if (!existsSync20(join24(projectPath, "project.godot"))) {
60512
+ if (!existsSync21(join24(projectPath, "project.godot"))) {
60373
60513
  throw new EngineUsageError(`Not a Godot project: ${projectPath} holds no project.godot.`);
60374
60514
  }
60375
60515
  const scenes = positional.slice(projectNamed ? 1 : 0);
@@ -60377,7 +60517,7 @@ function spreadOptionsOf(args, cwd) {
60377
60517
  throw new EngineUsageError(scenes.length === 0 ? "gdharness spread needs the scene of the bench to play." : `gdharness spread plays one scene, and was given ${String(scenes.length)}: ${scenes.join(", ")}.`);
60378
60518
  }
60379
60519
  const scene = resPathOf(scenes[0] ?? "", projectPath, cwd);
60380
- if (!existsSync20(join24(projectPath, scene.slice("res://".length)))) {
60520
+ if (!existsSync21(join24(projectPath, scene.slice("res://".length)))) {
60381
60521
  throw new EngineUsageError(`Nothing at ${scene} in the project at ${projectPath}.`);
60382
60522
  }
60383
60523
  const benchArguments = dashes === -1 ? [] : args.slice(dashes + 1);
@@ -60448,7 +60588,7 @@ function shareFaults(played) {
60448
60588
  return faults;
60449
60589
  }
60450
60590
  async function runSpreadCommand(options, godotPath) {
60451
- if (!existsSync20(join24(options.projectPath, SHARE_SCRIPT))) {
60591
+ if (!existsSync21(join24(options.projectPath, SHARE_SCRIPT))) {
60452
60592
  throw new EngineUsageError(`res://${SHARE_SCRIPT} is not in the project, so its bench cannot ask GdhShare for outcomes. Run gdharness setup.`);
60453
60593
  }
60454
60594
  const startedAt = Date.now();
@@ -60513,7 +60653,7 @@ async function runSpreadCommand(options, godotPath) {
60513
60653
  const faults = left.flatMap((worker) => engineFaults(worker, options.godotVersion));
60514
60654
  const arms = left.map((_, index) => {
60515
60655
  const file = join24(shareDirectory, `worker-${String(index)}.arms`);
60516
- return existsSync20(file) ? armsPlayed(readFileSync22(file, "utf8")) : [];
60656
+ return existsSync21(file) ? armsPlayed(readFileSync22(file, "utf8")) : [];
60517
60657
  });
60518
60658
  faults.push(...shareFaults(arms));
60519
60659
  if (faults.length > 0) {
@@ -60523,7 +60663,7 @@ async function runSpreadCommand(options, godotPath) {
60523
60663
  console.log(readLog(gather.log).replace(CONTROL_SEQUENCE, "").trimEnd());
60524
60664
  const gatherFaults = engineFaults(gather, options.godotVersion);
60525
60665
  const gatheredFile = join24(shareDirectory, "gathered.arms");
60526
- const gathered = new Set((existsSync20(gatheredFile) ? armsPlayed(readFileSync22(gatheredFile, "utf8")) ?? [] : []).map((arm) => arm.arm));
60666
+ const gathered = new Set((existsSync21(gatheredFile) ? armsPlayed(readFileSync22(gatheredFile, "utf8")) ?? [] : []).map((arm) => arm.arm));
60527
60667
  const ungathered = (arms[0] ?? []).filter((arm) => !gathered.has(arm.arm)).map((arm) => arm.arm);
60528
60668
  if (ungathered.length > 0) {
60529
60669
  gatherFaults.push(`the gathering run never asked for ${ungathered.join(", ")}, which the workers played: it went another way through the arms than they did`);
@@ -60574,7 +60714,7 @@ function engineFaults(engine, godotVersion) {
60574
60714
  const said = code === null ? "without an exit code" : code >>> 0 >= WINDOWS_EXCEPTION2 ? exitNamed(code) : String(code);
60575
60715
  faults.push(`${engine.name}: the engine exited ${said}`);
60576
60716
  }
60577
- if (!existsSync20(engine.log)) {
60717
+ if (!existsSync21(engine.log)) {
60578
60718
  return faults;
60579
60719
  }
60580
60720
  const printed = readRun(readLog(engine.log));
@@ -60590,7 +60730,7 @@ function engineFaults(engine, godotVersion) {
60590
60730
  }
60591
60731
  function progressOf(logs) {
60592
60732
  const each = logs.map((log, index) => {
60593
- const text = existsSync20(log) ? readLog(log) : "";
60733
+ const text = existsSync21(log) ? readLog(log) : "";
60594
60734
  const last = [...text.matchAll(PROGRESS)].at(-1);
60595
60735
  return last === undefined ? `worker ${String(index)} has played no arm yet` : `worker ${String(index)} at ${last[1] ?? ""} ${last[2] ?? ""} of ${last[3] ?? ""}`;
60596
60736
  });
@@ -60622,10 +60762,11 @@ init_reimport();
60622
60762
  init_setup();
60623
60763
  import {
60624
60764
  copyFileSync,
60625
- existsSync as existsSync23,
60765
+ existsSync as existsSync24,
60626
60766
  mkdirSync as mkdirSync10,
60627
60767
  readdirSync as readdirSync15,
60628
60768
  readFileSync as readFileSync26,
60769
+ realpathSync as realpathSync5,
60629
60770
  rmSync as rmSync13,
60630
60771
  statSync as statSync14,
60631
60772
  writeFileSync as writeFileSync13
@@ -60639,7 +60780,7 @@ import { setTimeout as delay5 } from "node:timers/promises";
60639
60780
  init_class_cache();
60640
60781
  init_gdscript_source();
60641
60782
  import { createHash as createHash6 } from "node:crypto";
60642
- import { existsSync as existsSync21, readdirSync as readdirSync14, readFileSync as readFileSync23, statSync as statSync13 } from "node:fs";
60783
+ import { existsSync as existsSync22, readdirSync as readdirSync14, readFileSync as readFileSync23, statSync as statSync13 } from "node:fs";
60643
60784
  import { join as join25, posix as posix2 } from "node:path";
60644
60785
  var EVERY_FILE = "res://";
60645
60786
  var CACHE_HELD = "cache:";
@@ -60657,7 +60798,7 @@ var ADDON = /^res:\/\/addons\/[^/]+\//;
60657
60798
  var TEXT_RESOURCE = /\.(?:tscn|tres|gdextension)$/;
60658
60799
  function reachedBySuite(file) {
60659
60800
  const bySuite = new Map;
60660
- if (!existsSync21(file)) {
60801
+ if (!existsSync22(file)) {
60661
60802
  return bySuite;
60662
60803
  }
60663
60804
  const paths = (value) => Array.isArray(value) ? value.filter((path) => typeof path === "string") : [];
@@ -60767,7 +60908,7 @@ ${this.read(path).digest}
60767
60908
  const hash = createHash6("sha256");
60768
60909
  let modified = 0;
60769
60910
  const directory = join25(this.scripts.projectPath, root.slice("res://".length));
60770
- if (existsSync21(directory)) {
60911
+ if (existsSync22(directory)) {
60771
60912
  walkSeen(directory, (file, under, stat) => {
60772
60913
  hash.update(`${under}
60773
60914
  `).update(readFileSync23(file));
@@ -60778,7 +60919,7 @@ ${this.read(path).digest}
60778
60919
  }
60779
60920
  readAnew(path) {
60780
60921
  const file = join25(this.scripts.projectPath, path.slice("res://".length));
60781
- if (!existsSync21(file)) {
60922
+ if (!existsSync22(file)) {
60782
60923
  return { digest: "missing", follows: [], also: [], modified: 0 };
60783
60924
  }
60784
60925
  const stat = statSync13(file);
@@ -60789,12 +60930,12 @@ ${this.read(path).digest}
60789
60930
  }
60790
60931
  const bytes = readFileSync23(file);
60791
60932
  const digest = createHash6("sha256").update(bytes).digest("hex");
60792
- const also = [`${path}.import`, `${path}.uid`].filter((beside) => existsSync21(join25(this.scripts.projectPath, beside.slice("res://".length))));
60933
+ const also = [`${path}.import`, `${path}.uid`].filter((beside) => existsSync22(join25(this.scripts.projectPath, beside.slice("res://".length))));
60793
60934
  const follows = [];
60794
60935
  if (TEXT_RESOURCE.test(path)) {
60795
60936
  for (const [named] of bytes.toString("latin1").matchAll(RES_LITERAL)) {
60796
60937
  const target = join25(this.scripts.projectPath, named.slice("res://".length));
60797
- (existsSync21(target) && statSync13(target).isDirectory() ? also : follows).push(named);
60938
+ (existsSync22(target) && statSync13(target).isDirectory() ? also : follows).push(named);
60798
60939
  }
60799
60940
  } else if (path.endsWith(".gd")) {
60800
60941
  const reaches = this.scriptReaches(path);
@@ -60981,7 +61122,7 @@ function joinedString(expression, named) {
60981
61122
  }
60982
61123
  function walkSeen(root, seen) {
60983
61124
  const walk = (directory, under) => {
60984
- if (existsSync21(join25(directory, ".gdignore"))) {
61125
+ if (existsSync22(join25(directory, ".gdignore"))) {
60985
61126
  return;
60986
61127
  }
60987
61128
  for (const entry of readdirSync14(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
@@ -60999,7 +61140,7 @@ function walkSeen(root, seen) {
60999
61140
  }
61000
61141
  function extensionsOf(projectPath) {
61001
61142
  const list = join25(projectPath, ".godot", "extension_list.cfg");
61002
- return existsSync21(list) ? readFileSync23(list, "utf8").split(`
61143
+ return existsSync22(list) ? readFileSync23(list, "utf8").split(`
61003
61144
  `).map((line) => line.trim()).filter((line) => line.startsWith("res://")) : [];
61004
61145
  }
61005
61146
 
@@ -61088,9 +61229,9 @@ function testOptionsOf(args, cwd) {
61088
61229
  }
61089
61230
  const first = positional[0];
61090
61231
  const named = first === undefined ? null : resolve11(cwd, first);
61091
- const projectNamed = named !== null && existsSync23(join28(named, "project.godot"));
61232
+ const projectNamed = named !== null && existsSync24(join28(named, "project.godot"));
61092
61233
  const projectPath = projectNamed ? named : resolve11(cwd);
61093
- if (!existsSync23(join28(projectPath, "project.godot"))) {
61234
+ if (!existsSync24(join28(projectPath, "project.godot"))) {
61094
61235
  throw new EngineUsageError(`Not a Godot project: ${projectPath} holds no project.godot.`);
61095
61236
  }
61096
61237
  const last = (flag) => valued.get(flag)?.at(-1);
@@ -61125,12 +61266,12 @@ function seedOf(value) {
61125
61266
  return seed;
61126
61267
  }
61127
61268
  function rootsOf(options) {
61128
- return options.roots.length > 0 ? options.roots : TEST_DIRECTORIES.filter((root) => existsSync23(join28(options.projectPath, root))).map((root) => `res://${root}`);
61269
+ return options.roots.length > 0 ? options.roots : TEST_DIRECTORIES.filter((root) => existsSync24(join28(options.projectPath, root))).map((root) => `res://${root}`);
61129
61270
  }
61130
61271
  function searchedRoots(options) {
61131
61272
  return options.selected.length === 0 ? rootsOf(options) : options.selected.filter((entry) => {
61132
61273
  const directory = join28(options.projectPath, entry.slice("res://".length));
61133
- return existsSync23(directory) && statSync14(directory).isDirectory();
61274
+ return existsSync24(directory) && statSync14(directory).isDirectory();
61134
61275
  });
61135
61276
  }
61136
61277
  function selectedSuites(scripts, options) {
@@ -61147,9 +61288,9 @@ function selectedSuites(scripts, options) {
61147
61288
  const caseAt = /^(res:\/\/.*\.gd):(\w+)$/.exec(entry);
61148
61289
  const path = caseAt?.[1] ?? entry;
61149
61290
  const directory = join28(options.projectPath, path.slice(6));
61150
- const suites = existsSync23(directory) && statSync14(directory).isDirectory() ? scripts.suitesUnder([path.replace(/\/$/, "")]) : [scripts.suite(path)].filter((suite) => suite !== null);
61291
+ const suites = existsSync24(directory) && statSync14(directory).isDirectory() ? scripts.suitesUnder([path.replace(/\/$/, "")]) : [scripts.suite(path)].filter((suite) => suite !== null);
61151
61292
  if (suites.length === 0) {
61152
- throw new EngineUsageError(existsSync23(directory) ? `${path} holds no gdUnit4 suite: nothing there extends GdUnitTestSuite and declares a test_ function.` : `Nothing at ${path} in the project at ${options.projectPath}.`);
61293
+ throw new EngineUsageError(existsSync24(directory) ? `${path} holds no gdUnit4 suite: nothing there extends GdUnitTestSuite and declares a test_ function.` : `Nothing at ${path} in the project at ${options.projectPath}.`);
61153
61294
  }
61154
61295
  for (const suite of suites) {
61155
61296
  const picked = chosen.get(suite.path) ?? { suite, cases: new Set };
@@ -61291,8 +61432,7 @@ async function runTestCommand(options, godotPath) {
61291
61432
  getLocalVersion(),
61292
61433
  readFileSync26(shippedListedRunner(), "utf8"),
61293
61434
  engineSaid(godotPath),
61294
- ...options.reachAlso.map((path) => `${path}
61295
- ${existsSync23(path) ? readFileSync26(path, "latin1") : "missing"}`)
61435
+ ...reachedAlsoSaid(options.projectPath, options.reachAlso)
61296
61436
  ];
61297
61437
  const everySuite = suites;
61298
61438
  const compileKept = options.changedOnly ? { file: join28(state, COMPILED_FILE), scripts, always } : null;
@@ -61498,7 +61638,7 @@ function readPassed(file) {
61498
61638
  function recordPassed(file, projectPath, ran, failedAcross, inputs, began) {
61499
61639
  const passed = readPassed(file);
61500
61640
  for (const path of Object.keys(passed)) {
61501
- if (!existsSync23(join28(projectPath, path.slice("res://".length)))) {
61641
+ if (!existsSync24(join28(projectPath, path.slice("res://".length)))) {
61502
61642
  delete passed[path];
61503
61643
  }
61504
61644
  }
@@ -61532,11 +61672,16 @@ function recordPassed(file, projectPath, ran, failedAcross, inputs, began) {
61532
61672
  writeJson(file, passed);
61533
61673
  }
61534
61674
  function engineSaid(godotPath) {
61535
- const stat = statSync14(godotPath);
61536
- return `${resolve11(godotPath)}
61675
+ const engine = realpathSync5.native(godotPath);
61676
+ const stat = statSync14(engine);
61677
+ return `${engine}
61537
61678
  ${String(stat.size)}
61538
61679
  ${String(stat.mtimeMs)}`;
61539
61680
  }
61681
+ function reachedAlsoSaid(projectPath, paths) {
61682
+ return paths.map((path) => `${relative5(projectPath, path).split(sep4).join("/")}
61683
+ ${existsSync24(path) ? readFileSync26(path, "latin1") : "missing"}`);
61684
+ }
61540
61685
  var COMPILE_CHECK = "compiling every script together";
61541
61686
 
61542
61687
  class HandedSlot {
@@ -61860,7 +62005,7 @@ async function runEngine2(launch, plan, index, times, again = "", slot = null) {
61860
62005
  }
61861
62006
  var REPORT_FILES_NAMED = 3;
61862
62007
  function reportsFault(reports) {
61863
- const files = existsSync23(reports) ? readdirSync15(reports, { recursive: true, encoding: "utf8" }).filter((file) => statSync14(join28(reports, file)).isFile()).sort() : [];
62008
+ const files = existsSync24(reports) ? readdirSync15(reports, { recursive: true, encoding: "utf8" }).filter((file) => statSync14(join28(reports, file)).isFile()).sort() : [];
61864
62009
  if (files.length === 0) {
61865
62010
  return null;
61866
62011
  }
@@ -61873,7 +62018,7 @@ function report(ran, compiled, across, uncollected, startedAt, logs, printOutput
61873
62018
  for (const engine of ran) {
61874
62019
  console.log("");
61875
62020
  console.log(`--- what engine ${String(engine.index)} printed, running ${named(engine.plan.suites.map((suite) => suite.path))}:`);
61876
- console.log(existsSync23(engine.log) ? readLog(engine.log).replace(CONTROL_SEQUENCE, "").trimEnd() : "(no log was written)");
62021
+ console.log(existsSync24(engine.log) ? readLog(engine.log).replace(CONTROL_SEQUENCE, "").trimEnd() : "(no log was written)");
61877
62022
  }
61878
62023
  }
61879
62024
  const failed = ran.filter((engine) => !engine.verdict.passed);
@@ -61884,7 +62029,7 @@ function report(ran, compiled, across, uncollected, startedAt, logs, printOutput
61884
62029
  for (const fault of engine.verdict.faults) {
61885
62030
  console.log(` ${fault}`);
61886
62031
  }
61887
- if (existsSync23(engine.log)) {
62032
+ if (existsSync24(engine.log)) {
61888
62033
  const verdict = [
61889
62034
  `gdharness: ${heading.slice(4)}`,
61890
62035
  ...engine.verdict.faults.map((fault) => ` ${fault}`)
@@ -62023,7 +62168,7 @@ class UsageError extends Refusal {
62023
62168
  function projectArgument(at) {
62024
62169
  const named = args.slice(at).find((value) => !value.startsWith("--"));
62025
62170
  const projectPath = resolve15(named ?? ".");
62026
- if (!existsSync35(join45(projectPath, "project.godot"))) {
62171
+ if (!existsSync36(join45(projectPath, "project.godot"))) {
62027
62172
  throw new UsageError(`Not a Godot project: ${projectPath} holds no project.godot.`);
62028
62173
  }
62029
62174
  return projectPath;
@@ -62087,7 +62232,7 @@ async function registerRuntime(godot, projectPath) {
62087
62232
  }
62088
62233
  const path = (named ?? "").replace(/^res:\/\//, "");
62089
62234
  console.log(`${RUNTIME_AUTOLOAD.name} autoload left at ${named}, which this project registers itself`);
62090
- if (!existsSync35(join45(projectPath, path))) {
62235
+ if (!existsSync36(join45(projectPath, path))) {
62091
62236
  console.log(" that file is not in this project, so it boots with a missing script");
62092
62237
  }
62093
62238
  console.log(` ${useTheShippedLoader(RUNTIME_AUTOLOAD.name, path)}`);
@@ -62220,7 +62365,7 @@ async function setup() {
62220
62365
  console.log("no harness configured; name one yourself, and gdharness harnesses lists them all");
62221
62366
  }
62222
62367
  if (!args.includes("--no-skill")) {
62223
- const directories = skillDirectories(chosen.harnesses, projectPath, existsSync35);
62368
+ const directories = skillDirectories(chosen.harnesses, projectPath, existsSync36);
62224
62369
  for (const written of writeSkill(directories, getLocalVersion())) {
62225
62370
  console.log(`skill: ${written.replaced ? "replaced" : "written"} ${written.path}`);
62226
62371
  }
@@ -62340,7 +62485,7 @@ async function upgrade() {
62340
62485
  moved.push(took.from);
62341
62486
  }
62342
62487
  }
62343
- for (const written of writeSkill(skillDirectories(already, projectPath, existsSync35), version)) {
62488
+ for (const written of writeSkill(skillDirectories(already, projectPath, existsSync36), version)) {
62344
62489
  console.log(`skill: ${written.replaced ? "replaced" : "written"} ${written.path}`);
62345
62490
  }
62346
62491
  console.log(`