gdharness 1.3.55 → 1.3.56

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,7 +1717,6 @@ var init_whole_file = __esm(() => {
1717
1717
  // src/engine-slots.ts
1718
1718
  import {
1719
1719
  closeSync as closeSync2,
1720
- existsSync as existsSync2,
1721
1720
  mkdirSync as mkdirSync2,
1722
1721
  openSync as openSync2,
1723
1722
  readdirSync,
@@ -1761,8 +1760,14 @@ function machineSlots(asked = {
1761
1760
  function nonEmpty(value) {
1762
1761
  return value === undefined || value === "" ? undefined : value;
1763
1762
  }
1763
+ function keptSlotsOf(count) {
1764
+ return Math.max(2, Math.floor(count / 4));
1765
+ }
1766
+ function gamesKeptOf(kept) {
1767
+ return Math.max(0, Math.min(Math.floor(kept / 2), kept - GATE_KEPT - 1));
1768
+ }
1764
1769
  function slotsDrawnOn(count, taker, queue) {
1765
- const gated = Math.max(1, count - KEPT_SLOTS);
1770
+ const gated = Math.max(1, count - keptSlotsOf(count));
1766
1771
  if (taker === "gate") {
1767
1772
  return { numbers: Array.from({ length: gated }, (_, slot) => slot), limit: "gate" };
1768
1773
  }
@@ -1774,10 +1779,7 @@ function slotsDrawnOn(count, taker, queue) {
1774
1779
  if (taker === "tier") {
1775
1780
  return { numbers: [...kept].reverse(), limit: "tier" };
1776
1781
  }
1777
- if (queue === "waiting") {
1778
- return { numbers: [], limit: "held" };
1779
- }
1780
- return { numbers: kept.slice(0, 1), limit: "kept" };
1782
+ return { numbers: kept.slice(0, Math.max(1, kept.length - GATE_KEPT)), limit: "kept" };
1781
1783
  }
1782
1784
  function inAGate(env = process4.env) {
1783
1785
  return nonEmpty(env[SHARE_VARIABLE]) !== undefined && nonEmpty(env[SHARE_COUNT_VARIABLE]) !== undefined;
@@ -1852,11 +1854,16 @@ function holderOf(content) {
1852
1854
  if (typeof parsed !== "object" || parsed === null) {
1853
1855
  return null;
1854
1856
  }
1855
- const { pid, started, by } = parsed;
1857
+ const { pid, started, by, game } = parsed;
1856
1858
  if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || typeof started !== "number") {
1857
1859
  return null;
1858
1860
  }
1859
- return typeof by === "string" && by !== "" ? { pid, started, by } : { pid, started };
1861
+ return {
1862
+ pid,
1863
+ started,
1864
+ ...typeof by === "string" && by !== "" ? { by } : {},
1865
+ ...game === true ? { game } : {}
1866
+ };
1860
1867
  } catch {
1861
1868
  return null;
1862
1869
  }
@@ -1897,7 +1904,7 @@ class EngineSlots {
1897
1904
  this.taker = taker;
1898
1905
  this.drawn = slotsDrawnOn(count, taker(), "none");
1899
1906
  }
1900
- async take(signal, waiting, blocked) {
1907
+ async take(signal, waiting, blocked, game = false) {
1901
1908
  mkdirSync2(this.directory, { recursive: true });
1902
1909
  const began = Date.now();
1903
1910
  let said = Number.NEGATIVE_INFINITY;
@@ -1906,7 +1913,7 @@ class EngineSlots {
1906
1913
  try {
1907
1914
  for (;; ) {
1908
1915
  signal?.throwIfAborted();
1909
- const lock = await this.takeFree();
1916
+ const lock = await this.takeFree(game);
1910
1917
  if (lock !== null) {
1911
1918
  return lock;
1912
1919
  }
@@ -1938,7 +1945,7 @@ class EngineSlots {
1938
1945
  }
1939
1946
  }
1940
1947
  }
1941
- async takeFree() {
1948
+ async takeFree(game = false) {
1942
1949
  mkdirSync2(this.directory, { recursive: true });
1943
1950
  await this.sweep();
1944
1951
  const inherited = this.inherited === null ? await this.inheritedLock() : null;
@@ -1948,9 +1955,18 @@ class EngineSlots {
1948
1955
  }
1949
1956
  const taker = this.taker();
1950
1957
  this.drawn = slotsDrawnOn(this.count, taker, taker === "gate" || taker === "timing" ? "none" : await this.gateQueue());
1958
+ if (game && this.drawn.limit === "kept") {
1959
+ const share = slotsDrawnOn(this.count, "tier", "queued").numbers;
1960
+ const games = await this.heldByGames(share);
1961
+ if (games.length >= gamesKeptOf(share.length)) {
1962
+ this.drawn = { numbers: games, limit: "games" };
1963
+ return null;
1964
+ }
1965
+ }
1966
+ const holder = game ? { ...this.holder, game: true } : this.holder;
1951
1967
  for (const slot of this.drawn.numbers) {
1952
1968
  const lock = join5(this.directory, `${String(slot)}.lock`);
1953
- if (this.made(lock) || await this.takenOver(lock)) {
1969
+ if (this.made(lock, holder) || await this.takenOver(lock, holder)) {
1954
1970
  this.held.add(lock);
1955
1971
  return lock;
1956
1972
  }
@@ -1967,6 +1983,14 @@ class EngineSlots {
1967
1983
  const tree = await processTree();
1968
1984
  return tree !== undefined && inheritsSlot(tree, process4.pid, holder.pid, basename3(process4.execPath)) ? lock : null;
1969
1985
  }
1986
+ markWaiting() {
1987
+ const mark = this.waitMarked();
1988
+ return () => {
1989
+ if (mark !== undefined && this.marks.delete(mark)) {
1990
+ removeWhole(mark);
1991
+ }
1992
+ };
1993
+ }
1970
1994
  waitMarked() {
1971
1995
  const marks = join5(this.directory, WAITING_FOLDER);
1972
1996
  waitsMarked += 1;
@@ -1982,6 +2006,17 @@ class EngineSlots {
1982
2006
  this.marks.add(mark);
1983
2007
  return mark;
1984
2008
  }
2009
+ async heldByGames(numbers) {
2010
+ const games = [];
2011
+ for (const slot of numbers) {
2012
+ const lock = join5(this.directory, `${String(slot)}.lock`);
2013
+ const content = readWhole(lock);
2014
+ if (content !== null && holderOf(content)?.game === true && !await this.free(lock)) {
2015
+ games.push(slot);
2016
+ }
2017
+ }
2018
+ return games;
2019
+ }
1985
2020
  async gateQueue() {
1986
2021
  const marks = join5(this.directory, QUEUED_FOLDER);
1987
2022
  let names;
@@ -2000,10 +2035,8 @@ class EngineSlots {
2000
2035
  if (await this.free(mark)) {
2001
2036
  removeWhole(mark);
2002
2037
  removeWhole(`${mark}${SEATED_SUFFIX}`);
2003
- } else if (!existsSync2(`${mark}${SEATED_SUFFIX}`)) {
2004
- live = "waiting";
2005
- } else if (live === "none") {
2006
- live = "seated";
2038
+ } else {
2039
+ live = "queued";
2007
2040
  }
2008
2041
  }
2009
2042
  return live;
@@ -2047,7 +2080,7 @@ class EngineSlots {
2047
2080
  }
2048
2081
  return handed;
2049
2082
  }
2050
- made(path) {
2083
+ made(path, holder = this.holder) {
2051
2084
  let made;
2052
2085
  try {
2053
2086
  made = openSync2(path, "wx");
@@ -2055,7 +2088,7 @@ class EngineSlots {
2055
2088
  return false;
2056
2089
  }
2057
2090
  try {
2058
- writeSync2(made, JSON.stringify(this.holder));
2091
+ writeSync2(made, JSON.stringify(holder));
2059
2092
  } finally {
2060
2093
  closeSync2(made);
2061
2094
  }
@@ -2075,10 +2108,10 @@ class EngineSlots {
2075
2108
  }
2076
2109
  }
2077
2110
  }
2078
- takenOver(lock) {
2079
- return this.cleared(lock, true);
2111
+ takenOver(lock, holder) {
2112
+ return this.cleared(lock, true, holder);
2080
2113
  }
2081
- async cleared(lock, retake) {
2114
+ async cleared(lock, retake, holder = this.holder) {
2082
2115
  if (!await this.free(lock)) {
2083
2116
  return false;
2084
2117
  }
@@ -2100,7 +2133,7 @@ class EngineSlots {
2100
2133
  } catch {
2101
2134
  return false;
2102
2135
  }
2103
- return retake ? this.made(lock) : true;
2136
+ return retake ? this.made(lock, holder) : true;
2104
2137
  } finally {
2105
2138
  rmSync4(steal, { force: true });
2106
2139
  }
@@ -2136,7 +2169,8 @@ function handSlot(lock, from, to) {
2136
2169
  } catch {
2137
2170
  return false;
2138
2171
  }
2139
- return content !== null && holderOf(content)?.pid === from && writeWhole(lock, JSON.stringify(to));
2172
+ const holder = content === null ? null : holderOf(content);
2173
+ return holder?.pid === from && writeWhole(lock, JSON.stringify(holder.game === true ? { ...to, game: true } : to));
2140
2174
  }
2141
2175
  function giveBackSlot(lock, pid) {
2142
2176
  try {
@@ -2163,15 +2197,12 @@ function nameSlotTaker(by) {
2163
2197
  }
2164
2198
  function slotWaitSaid(waitedMs, count, directory, holders = [], drawn = { numbers: [] }) {
2165
2199
  const so = `Waiting${waitedMs >= 1000 ? ` ${String(Math.round(waitedMs / 1000))} s so far` : ""} for an engine`;
2166
- if (drawn.limit === "held") {
2167
- return `${so}: ${GATE_UNSEATED} (${directory}), and the engine starts once every queued gate has its seat.`;
2168
- }
2169
2200
  const taking = drawn.limit === undefined ? count : drawn.numbers.length;
2170
2201
  const slots = `${slotsSaid(taking, count, directory, drawn.limit)} ${taking === 1 ? "is" : "are"} in use`;
2171
2202
  const named = holdersNamed(taking, holders);
2172
2203
  const waiting = `${so}: ${slots}`;
2173
2204
  const back = `the engine starts when ${taking === 1 ? "it" : "one"} is given back`;
2174
- const starts = drawn.limit === "kept" || drawn.limit === "tier" ? `${back} or no gate is queued` : back;
2205
+ const starts = drawn.limit === "kept" || drawn.limit === "tier" || drawn.limit === "games" ? `${back} or no gate is queued` : back;
2175
2206
  if (named.length === 0) {
2176
2207
  return `${waiting}, by a gate or another tool, and ${starts}.`;
2177
2208
  }
@@ -2191,13 +2222,13 @@ function slotsSaid(taking, count, directory, limit) {
2191
2222
  if (limit === "tier") {
2192
2223
  return `${taking === 1 ? "the one engine slot" : `the ${String(taking)} engine slots`} of the ${String(count)} ${where} a gate's own steps take while a gate is queued`;
2193
2224
  }
2225
+ if (limit === "games") {
2226
+ return `${taking === 1 ? "the one engine slot" : `the ${String(taking)} engine slots`} of the ${String(count)} ${where} that games editor_run started may hold while a gate is queued, the rest kept for short calls,`;
2227
+ }
2194
2228
  return count === 1 ? `the one engine slot ${where}` : `all ${String(count)} engine slots ${where}`;
2195
2229
  }
2196
2230
  function slotWaitedSaid(waitedMs, count, directory, holders, drawn = { numbers: [] }) {
2197
2231
  const waited = `This call waited ${String(Math.round(waitedMs / 1000))} s for an engine slot in all.`;
2198
- if (drawn.limit === "held") {
2199
- return `${waited} When it first waited, ${GATE_UNSEATED} (${directory}), and engines outside a gate wait until every queued gate has its seat.`;
2200
- }
2201
2232
  const taking = drawn.limit === undefined ? count : drawn.numbers.length;
2202
2233
  const slots = `${slotsSaid(taking, count, directory, drawn.limit)} ${taking === 1 ? "was" : "were"} in use`;
2203
2234
  const named = holdersNamed(taking, holders);
@@ -2220,7 +2251,7 @@ function holdersNamed(count, holders) {
2220
2251
  function listed(named) {
2221
2252
  return named.length === 1 ? named.join("") : `${named.slice(0, -1).join(", ")} and ${named.at(-1) ?? ""}`;
2222
2253
  }
2223
- async function slotForCall() {
2254
+ async function slotForCall(game = false) {
2224
2255
  const slots = await processSlots();
2225
2256
  const progress = callProgress();
2226
2257
  const waits = callSlotWaits();
@@ -2232,7 +2263,7 @@ async function slotForCall() {
2232
2263
  }, () => {
2233
2264
  blockedBy = slots.holders();
2234
2265
  blockedOn = slots.drawn;
2235
- });
2266
+ }, game);
2236
2267
  if (waits !== undefined && blockedBy !== undefined) {
2237
2268
  waits.ms += Date.now() - began;
2238
2269
  const heldBy = blockedBy;
@@ -2259,7 +2290,7 @@ async function inASlot(body) {
2259
2290
  held.release();
2260
2291
  }
2261
2292
  }
2262
- 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", KEPT_SLOTS = 2, TIMED_VARIABLE = "GODOT_ENGINE_TIMED", TIER_VARIABLE = "GODOT_ENGINE_TIER", SEATED_SUFFIX = ".seated", GATE_UNSEATED = "a gate in this machine's queue is waiting for its seat", waitsMarked = 0, ours, saidTo, takenBy;
2293
+ 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, TIMED_VARIABLE = "GODOT_ENGINE_TIMED", TIER_VARIABLE = "GODOT_ENGINE_TIER", SEATED_SUFFIX = ".seated", waitsMarked = 0, ours, saidTo, takenBy;
2263
2294
  var init_engine_slots = __esm(() => {
2264
2295
  init_alive();
2265
2296
  init_cache_home();
@@ -9534,7 +9565,7 @@ var init_config_formats = __esm(() => {
9534
9565
  });
9535
9566
 
9536
9567
  // src/runner.ts
9537
- import { existsSync as existsSync3, realpathSync as realpathSync2 } from "node:fs";
9568
+ import { existsSync as existsSync2, realpathSync as realpathSync2 } from "node:fs";
9538
9569
  import { delimiter, dirname as dirname3, extname, join as join6, resolve as resolve3 } from "node:path";
9539
9570
  import process5 from "node:process";
9540
9571
  function currentRunner() {
@@ -9578,12 +9609,12 @@ function realPath(path) {
9578
9609
  }
9579
9610
  function alongside(execPath, name) {
9580
9611
  const runner = join6(dirname3(execPath), process5.platform === "win32" ? `${name}.cmd` : name);
9581
- return existsSync3(runner) ? runner : undefined;
9612
+ return existsSync2(runner) ? runner : undefined;
9582
9613
  }
9583
9614
  var init_runner = () => {};
9584
9615
 
9585
9616
  // src/harnesses.ts
9586
- 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";
9617
+ 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";
9587
9618
  import { homedir as homedir3 } from "node:os";
9588
9619
  import { basename as basename4, dirname as dirname4, isAbsolute as isAbsolute2, join as join7, relative as relative2, resolve as resolve4 } from "node:path";
9589
9620
  import process6 from "node:process";
@@ -9674,15 +9705,15 @@ function harnessById(id) {
9674
9705
  }
9675
9706
  function present(harness, projectPath) {
9676
9707
  const path = configPath(harness, projectPath);
9677
- if (existsSync4(path)) {
9708
+ if (existsSync3(path)) {
9678
9709
  return true;
9679
9710
  }
9680
9711
  const root = harness.scope === "project" ? projectPath : homedir3();
9681
9712
  const own = dirname4(path);
9682
- if (own !== root && existsSync4(own)) {
9713
+ if (own !== root && existsSync3(own)) {
9683
9714
  return true;
9684
9715
  }
9685
- return harness.marker !== undefined && existsSync4(join7(root, harness.marker));
9716
+ return harness.marker !== undefined && existsSync3(join7(root, harness.marker));
9686
9717
  }
9687
9718
  function candidates(projectPath) {
9688
9719
  const found = [];
@@ -9695,7 +9726,7 @@ function candidates(projectPath) {
9695
9726
  }
9696
9727
  if (present(harness, projectPath)) {
9697
9728
  found.push({ harness, reason: "configured" });
9698
- } else if (harness.home !== undefined && existsSync4(join7(homedir3(), harness.home))) {
9729
+ } else if (harness.home !== undefined && existsSync3(join7(homedir3(), harness.home))) {
9699
9730
  found.push({ harness, reason: "installed" });
9700
9731
  }
9701
9732
  }
@@ -9717,7 +9748,7 @@ function groupByFile(harnesses, projectPath) {
9717
9748
  }
9718
9749
  function registered(harness, projectPath) {
9719
9750
  const path = configPath(harness, projectPath);
9720
- if (harness.snippet !== undefined || !existsSync4(path)) {
9751
+ if (harness.snippet !== undefined || !existsSync3(path)) {
9721
9752
  return false;
9722
9753
  }
9723
9754
  const text = readFileSync8(path, "utf8");
@@ -9746,7 +9777,7 @@ function recordedEnginePath(projectPath) {
9746
9777
  }
9747
9778
  const named = reach(entryEnvironment(harness, projectPath), "GODOT_PATH");
9748
9779
  const path = typeof named !== "string" || named === "" ? null : isAbsolute2(named) ? named : resolve4(projectPath, named);
9749
- if (path !== null && existsSync4(path)) {
9780
+ if (path !== null && existsSync3(path)) {
9750
9781
  return path;
9751
9782
  }
9752
9783
  }
@@ -9754,7 +9785,7 @@ function recordedEnginePath(projectPath) {
9754
9785
  }
9755
9786
  function mainCheckoutOf(projectPath) {
9756
9787
  let top = resolve4(projectPath);
9757
- while (!existsSync4(join7(top, ".git"))) {
9788
+ while (!existsSync3(join7(top, ".git"))) {
9758
9789
  const up = dirname4(top);
9759
9790
  if (up === top) {
9760
9791
  return null;
@@ -9771,7 +9802,7 @@ function mainCheckoutOf(projectPath) {
9771
9802
  }
9772
9803
  const entry = resolve4(top, pointer);
9773
9804
  const commonFile = join7(entry, "commondir");
9774
- if (!existsSync4(commonFile)) {
9805
+ if (!existsSync3(commonFile)) {
9775
9806
  return null;
9776
9807
  }
9777
9808
  const common = resolve4(entry, readFileSync8(commonFile, "utf8").trim());
@@ -9779,11 +9810,11 @@ function mainCheckoutOf(projectPath) {
9779
9810
  return null;
9780
9811
  }
9781
9812
  const main = join7(dirname4(common), relative2(top, resolve4(projectPath)));
9782
- return isSameDirectory(main, projectPath) || !existsSync4(join7(main, "project.godot")) ? null : main;
9813
+ return isSameDirectory(main, projectPath) || !existsSync3(join7(main, "project.godot")) ? null : main;
9783
9814
  }
9784
9815
  function worktreeCheckoutsOf(projectPath) {
9785
9816
  let top = resolve4(projectPath);
9786
- while (!existsSync4(join7(top, ".git"))) {
9817
+ while (!existsSync3(join7(top, ".git"))) {
9787
9818
  const up = dirname4(top);
9788
9819
  if (up === top) {
9789
9820
  return [];
@@ -9791,18 +9822,18 @@ function worktreeCheckoutsOf(projectPath) {
9791
9822
  top = up;
9792
9823
  }
9793
9824
  const listed = join7(top, ".git", "worktrees");
9794
- if (!statSync4(join7(top, ".git")).isDirectory() || !existsSync4(listed)) {
9825
+ if (!statSync4(join7(top, ".git")).isDirectory() || !existsSync3(listed)) {
9795
9826
  return [];
9796
9827
  }
9797
9828
  const below = relative2(top, resolve4(projectPath));
9798
9829
  return readdirSync2(listed).flatMap((name) => {
9799
9830
  const pointer = join7(listed, name, "gitdir");
9800
- if (!existsSync4(pointer)) {
9831
+ if (!existsSync3(pointer)) {
9801
9832
  return [];
9802
9833
  }
9803
9834
  const checkout = dirname4(resolve4(listed, name, readFileSync8(pointer, "utf8").trim()));
9804
9835
  const project = join7(checkout, below);
9805
- return existsSync4(join7(project, "project.godot")) ? [project] : [];
9836
+ return existsSync3(join7(project, "project.godot")) ? [project] : [];
9806
9837
  });
9807
9838
  }
9808
9839
  function entryEnvironment(harness, projectPath) {
@@ -9810,7 +9841,7 @@ function entryEnvironment(harness, projectPath) {
9810
9841
  return;
9811
9842
  }
9812
9843
  const path = configPath(harness, projectPath);
9813
- if (!existsSync4(path)) {
9844
+ if (!existsSync3(path)) {
9814
9845
  return;
9815
9846
  }
9816
9847
  let parsed;
@@ -9831,7 +9862,7 @@ function reach(held, key) {
9831
9862
  }
9832
9863
  function disconnect(harness, projectPath) {
9833
9864
  const path = configPath(harness, projectPath);
9834
- if (!existsSync4(path)) {
9865
+ if (!existsSync3(path)) {
9835
9866
  return { harness, path, action: "absent" };
9836
9867
  }
9837
9868
  if (harness.snippet !== undefined) {
@@ -9918,7 +9949,7 @@ function connect(harness, projectPath, launch) {
9918
9949
  if (harness.snippet !== undefined) {
9919
9950
  return { harness, path, action: "snippet", snippet: harness.snippet(launch) };
9920
9951
  }
9921
- const held = existsSync4(path) ? readFileSync8(path, "utf8") : "";
9952
+ const held = existsSync3(path) ? readFileSync8(path, "utf8") : "";
9922
9953
  if (harness.toml !== undefined) {
9923
9954
  const already = held.includes(harness.toml.identity ?? harness.toml.header);
9924
9955
  return put(harness, path, writeToml(held, harness.toml, launch), already);
@@ -11084,7 +11115,7 @@ var init_gdscript_source = __esm(() => {
11084
11115
  });
11085
11116
 
11086
11117
  // src/class-cache.ts
11087
- import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync5 } from "node:fs";
11118
+ import { existsSync as existsSync4, readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync5 } from "node:fs";
11088
11119
  import { join as join8, posix } from "node:path";
11089
11120
  function isToolScript(source) {
11090
11121
  return TOOL.test(codeOf(source));
@@ -11148,7 +11179,7 @@ function declaredClassOf(source) {
11148
11179
  }
11149
11180
  function eachScript(projectPath, each) {
11150
11181
  const visit = (directory, prefix) => {
11151
- if (existsSync5(join8(directory, ".gdignore"))) {
11182
+ if (existsSync4(join8(directory, ".gdignore"))) {
11152
11183
  return;
11153
11184
  }
11154
11185
  for (const entry of readdirSync3(directory, { withFileTypes: true })) {
@@ -11544,7 +11575,7 @@ function uncachedForTheEngineNote(projectPath, types) {
11544
11575
  }
11545
11576
  const one = types.length === 1;
11546
11577
  const named = types.map((type) => `${type.type} (${type.declaredIn})`).join(", ");
11547
- const cacheExists = existsSync5(join8(projectPath, ".godot", "global_script_class_cache.cfg"));
11578
+ const cacheExists = existsSync4(join8(projectPath, ".godot", "global_script_class_cache.cfg"));
11548
11579
  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.`;
11549
11580
  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.";
11550
11581
  }
@@ -11570,7 +11601,7 @@ function declaredSince(projectPath, paths, names, since) {
11570
11601
  });
11571
11602
  }
11572
11603
  function cachedAtMissingPaths(cached, projectPath) {
11573
- return [...cached].filter(([, path]) => path.startsWith("res://") && !existsSync5(join8(projectPath, path.slice("res://".length)))).map(([name]) => name).sort();
11604
+ return [...cached].filter(([, path]) => path.startsWith("res://") && !existsSync4(join8(projectPath, path.slice("res://".length)))).map(([name]) => name).sort();
11574
11605
  }
11575
11606
  function staleAgainst(cached, projectPath) {
11576
11607
  return [...declaredClasses(projectPath)].filter(([name, path]) => cached.get(name) !== path).map(([name]) => name);
@@ -12904,7 +12935,7 @@ var init_suite_judge = __esm(() => {
12904
12935
  // src/engine-launch.ts
12905
12936
  import {
12906
12937
  closeSync as closeSync4,
12907
- existsSync as existsSync6,
12938
+ existsSync as existsSync5,
12908
12939
  fstatSync as fstatSync2,
12909
12940
  openSync as openSync4,
12910
12941
  readdirSync as readdirSync4,
@@ -12944,7 +12975,7 @@ function godotNamed(value, cwd) {
12944
12975
  return null;
12945
12976
  }
12946
12977
  const path = resolve5(cwd, value);
12947
- if (!existsSync6(path) || statSync6(path).isDirectory()) {
12978
+ if (!existsSync5(path) || statSync6(path).isDirectory()) {
12948
12979
  throw new EngineUsageError(`--godot names ${path}, which is not an engine executable.`);
12949
12980
  }
12950
12981
  return path;
@@ -12975,7 +13006,7 @@ function resPathOf(entry, projectPath, cwd) {
12975
13006
  const file = caseAt?.[1] ?? entry;
12976
13007
  const fromProject = resolve5(projectPath, file);
12977
13008
  const fromHere = resolve5(cwd, file);
12978
- const absolute = isAbsolute3(file) || !existsSync6(fromProject) && existsSync6(fromHere) ? fromHere : fromProject;
13009
+ const absolute = isAbsolute3(file) || !existsSync5(fromProject) && existsSync5(fromHere) ? fromHere : fromProject;
12979
13010
  const inside = relative3(projectPath, absolute);
12980
13011
  if (inside.startsWith("..") || isAbsolute3(inside)) {
12981
13012
  throw new EngineUsageError(`${entry} is not inside the project at ${projectPath}.`);
@@ -12987,7 +13018,7 @@ function homeOf(projectPath) {
12987
13018
  return mainCheckoutOf(projectPath) ?? projectPath;
12988
13019
  }
12989
13020
  function sweepRunDirectories(runs, kept = KEPT_RUN_DIRECTORIES) {
12990
- if (!existsSync6(runs)) {
13021
+ if (!existsSync5(runs)) {
12991
13022
  return;
12992
13023
  }
12993
13024
  const ended = [];
@@ -13017,6 +13048,9 @@ function roomFor(most, processors, available, said = "of memory free", processor
13017
13048
  held: byMemory < processors ? `the machine has ${gigabytes(Math.max(0, available))} ${said}, ${gigabytes(MEMORY_KEPT)} of it kept for everything else and ${gigabytes(MEMORY_PER_ENGINE)} taken for each engine` : processorsSaid
13018
13049
  };
13019
13050
  }
13051
+ function roomForAnother(available, starting) {
13052
+ return available - MEMORY_KEPT - starting * MEMORY_PER_ENGINE >= MEMORY_PER_ENGINE;
13053
+ }
13020
13054
  async function memoryAvailable() {
13021
13055
  const level = await macMemoryLevel();
13022
13056
  if (level !== null) {
@@ -13221,7 +13255,7 @@ async function watchedEngine(launch, lock, args, directory, log, silenceSeconds,
13221
13255
  continue;
13222
13256
  }
13223
13257
  const { stoppedIn } = readRun(readLog(log));
13224
- const unstarted = helper !== null && !existsSync6(helper.pid) ? `, and it never started ${helper.how}: ${helperStep(helper.step)}` : "";
13258
+ const unstarted = helper !== null && !existsSync5(helper.pid) ? `, and it never started ${helper.how}: ${helperStep(helper.step)}` : "";
13225
13259
  ended = `the engine printed nothing for ${String(allowed.seconds)} s${countedBy(quiet, silent, at)}${stoppedIn === null ? "" : ` while running ${stoppedIn}`}, so it was ended${unstarted}`;
13226
13260
  stop();
13227
13261
  }
@@ -13307,7 +13341,7 @@ var init_engine_launch = __esm(() => {
13307
13341
  });
13308
13342
 
13309
13343
  // src/detection.ts
13310
- import { existsSync as existsSync7, readdirSync as readdirSync5, statSync as statSync7 } from "node:fs";
13344
+ import { existsSync as existsSync6, readdirSync as readdirSync5, statSync as statSync7 } from "node:fs";
13311
13345
  import { homedir as homedir4 } from "node:os";
13312
13346
  import { join as join10 } from "node:path";
13313
13347
  function resolveHomeDirectory() {
@@ -13318,7 +13352,7 @@ function resolveHomeDirectory() {
13318
13352
  }
13319
13353
  }
13320
13354
  function scanDirectoryForGodotBinaries(directory, platform) {
13321
- if (!directory || !existsSync7(directory)) {
13355
+ if (!directory || !existsSync6(directory)) {
13322
13356
  return [];
13323
13357
  }
13324
13358
  let entries;
@@ -13586,7 +13620,7 @@ var init_launch = __esm(() => {
13586
13620
  });
13587
13621
 
13588
13622
  // src/godot-path.ts
13589
- import { existsSync as existsSync8 } from "node:fs";
13623
+ import { existsSync as existsSync7 } from "node:fs";
13590
13624
  import { isAbsolute as isAbsolute4, normalize, resolve as resolve6 } from "node:path";
13591
13625
  function versionStartOf(error) {
13592
13626
  const failed = error ?? {};
@@ -13664,7 +13698,7 @@ class GodotLocator {
13664
13698
  if (known !== undefined) {
13665
13699
  return known;
13666
13700
  }
13667
- if (path !== "godot" && !existsSync8(path)) {
13701
+ if (path !== "godot" && !existsSync7(path)) {
13668
13702
  this.answered.set(path, "does not exist");
13669
13703
  return "does not exist";
13670
13704
  }
@@ -14046,7 +14080,7 @@ var init_engine_run = __esm(() => {
14046
14080
  });
14047
14081
 
14048
14082
  // src/doc-cache.ts
14049
- import { existsSync as existsSync9, readdirSync as readdirSync6, statSync as statSync8 } from "node:fs";
14083
+ import { existsSync as existsSync8, readdirSync as readdirSync6, statSync as statSync8 } from "node:fs";
14050
14084
  import { homedir as homedir5 } from "node:os";
14051
14085
  import { basename as basename5, dirname as dirname5, isAbsolute as isAbsolute5, join as join11 } from "node:path";
14052
14086
  import process9 from "node:process";
@@ -14054,7 +14088,7 @@ function editorCacheDirectory(godotPath, platform = process9.platform, env = pro
14054
14088
  const beside = dirname5(godotPath);
14055
14089
  const bundle = platform === "darwin" && basename5(beside) === "MacOS" && basename5(dirname5(beside)) === "Contents" ? dirname5(dirname5(dirname5(beside))) : null;
14056
14090
  for (const folder of bundle === null ? [beside] : [beside, bundle]) {
14057
- if (existsSync9(join11(folder, "._sc_")) || existsSync9(join11(folder, "_sc_"))) {
14091
+ if (existsSync8(join11(folder, "._sc_")) || existsSync8(join11(folder, "_sc_"))) {
14058
14092
  return join11(folder, "editor_data", "cache");
14059
14093
  }
14060
14094
  }
@@ -14102,7 +14136,7 @@ var init_doc_cache = __esm(() => {
14102
14136
  });
14103
14137
 
14104
14138
  // src/project-scan.ts
14105
- import { existsSync as existsSync10, readdirSync as readdirSync7, readFileSync as readFileSync12, statSync as statSync9 } from "node:fs";
14139
+ import { existsSync as existsSync9, readdirSync as readdirSync7, readFileSync as readFileSync12, statSync as statSync9 } from "node:fs";
14106
14140
  import { basename as basename6, extname as extname2, join as join12, relative as relative4, sep as sep3 } from "node:path";
14107
14141
  function skipped(name) {
14108
14142
  return name.startsWith(".") || SKIPPED.has(name);
@@ -14111,10 +14145,10 @@ function steppedOver(directory) {
14111
14145
  return gdignored(directory) || installedByUs(directory);
14112
14146
  }
14113
14147
  function gdignored(directory) {
14114
- return existsSync10(join12(directory, ".gdignore"));
14148
+ return existsSync9(join12(directory, ".gdignore"));
14115
14149
  }
14116
14150
  function installedByUs(directory) {
14117
- return existsSync10(join12(directory, VERSION_MARKER));
14151
+ return existsSync9(join12(directory, VERSION_MARKER));
14118
14152
  }
14119
14153
  function projectStructure(projectPath) {
14120
14154
  const structure = { scenes: 0, scripts: 0, assets: 0, other: 0 };
@@ -14227,7 +14261,7 @@ function scriptsWithoutUid(projectPath) {
14227
14261
  continue;
14228
14262
  }
14229
14263
  const extension = entry.name.split(".").pop()?.toLowerCase() ?? "";
14230
- if (CARRIES_A_UID.has(extension) && !existsSync10(join12(directory, `${entry.name}.uid`))) {
14264
+ if (CARRIES_A_UID.has(extension) && !existsSync9(join12(directory, `${entry.name}.uid`))) {
14231
14265
  found.push(spelled);
14232
14266
  }
14233
14267
  }
@@ -14494,7 +14528,7 @@ var init_project_scan = __esm(() => {
14494
14528
 
14495
14529
  // src/import-freshness.ts
14496
14530
  import { createHash as createHash2 } from "node:crypto";
14497
- import { existsSync as existsSync11, readdirSync as readdirSync8, readFileSync as readFileSync13, statSync as statSync10 } from "node:fs";
14531
+ import { existsSync as existsSync10, readdirSync as readdirSync8, readFileSync as readFileSync13, statSync as statSync10 } from "node:fs";
14498
14532
  import { join as join13 } from "node:path";
14499
14533
  function md5Of(file) {
14500
14534
  let stats;
@@ -14620,7 +14654,7 @@ function behind(projectPath, resPath, sidecarFile, sidecar, importedFrom) {
14620
14654
  return "its import file names no imported output, as one written before the engine imports from it does";
14621
14655
  }
14622
14656
  }
14623
- if (outputs.some((output) => !existsSync11(onDisk(projectPath, output)))) {
14657
+ if (outputs.some((output) => !existsSync10(onDisk(projectPath, output)))) {
14624
14658
  return "its imported output is not on disk";
14625
14659
  }
14626
14660
  const source = unquoted(deps.get("source_file"));
@@ -14645,7 +14679,7 @@ function staleImports(projectPath) {
14645
14679
  const stale = [];
14646
14680
  const importedFrom = importedSidecarMd5s(projectPath);
14647
14681
  const visit = (directory, resDirectory) => {
14648
- if (existsSync11(join13(directory, ".gdignore")) || existsSync11(join13(directory, VERSION_MARKER))) {
14682
+ if (existsSync10(join13(directory, ".gdignore")) || existsSync10(join13(directory, VERSION_MARKER))) {
14649
14683
  return;
14650
14684
  }
14651
14685
  let entries;
@@ -14736,7 +14770,7 @@ var init_import_freshness = __esm(() => {
14736
14770
 
14737
14771
  // src/library-copies.ts
14738
14772
  import {
14739
- existsSync as existsSync12,
14773
+ existsSync as existsSync11,
14740
14774
  mkdirSync as mkdirSync4,
14741
14775
  readdirSync as readdirSync9,
14742
14776
  readFileSync as readFileSync14,
@@ -14754,7 +14788,7 @@ function freeLibraryCopies(projectPath, platform = process.platform) {
14754
14788
  for (const library of windowsLibraries(projectPath)) {
14755
14789
  const folder = dirname6(library);
14756
14790
  const copy = `~${basename7(library)}`;
14757
- if (existsSync12(join14(folder, copy))) {
14791
+ if (existsSync11(join14(folder, copy))) {
14758
14792
  const aside = join14(folder, `${copy}.aside-${process.pid}-${Date.now()}`);
14759
14793
  try {
14760
14794
  renameSync3(join14(folder, copy), aside);
@@ -14780,12 +14814,26 @@ function freeLibraryCopies(projectPath, platform = process.platform) {
14780
14814
  }
14781
14815
  function seedExtensionList(projectPath) {
14782
14816
  const list = join14(projectPath, ".godot", "extension_list.cfg");
14783
- if (existsSync12(list)) {
14817
+ if (existsSync11(list)) {
14784
14818
  return null;
14785
14819
  }
14820
+ const found = unlistedExtensions(projectPath);
14821
+ if (found.length === 0) {
14822
+ return [];
14823
+ }
14824
+ mkdirSync4(dirname6(list), { recursive: true });
14825
+ writeFileSync7(list, `${found.join(`
14826
+ `)}
14827
+ `);
14828
+ return found;
14829
+ }
14830
+ function unlistedExtensions(projectPath) {
14831
+ if (existsSync11(join14(projectPath, ".godot", "extension_list.cfg"))) {
14832
+ return [];
14833
+ }
14786
14834
  const found = [];
14787
14835
  const visit = (directory, resDirectory) => {
14788
- if (existsSync12(join14(directory, ".gdignore"))) {
14836
+ if (existsSync11(join14(directory, ".gdignore"))) {
14789
14837
  return;
14790
14838
  }
14791
14839
  let entries;
@@ -14806,15 +14854,7 @@ function seedExtensionList(projectPath) {
14806
14854
  }
14807
14855
  };
14808
14856
  visit(projectPath, "res://");
14809
- if (found.length === 0) {
14810
- return [];
14811
- }
14812
- found.sort();
14813
- mkdirSync4(dirname6(list), { recursive: true });
14814
- writeFileSync7(list, `${found.join(`
14815
- `)}
14816
- `);
14817
- return found;
14857
+ return found.sort();
14818
14858
  }
14819
14859
  function windowsLibraries(projectPath) {
14820
14860
  const listed = readOrNull(join14(projectPath, ".godot", "extension_list.cfg"));
@@ -14864,12 +14904,12 @@ var init_library_copies = () => {};
14864
14904
 
14865
14905
  // src/reimport.ts
14866
14906
  import { createHash as createHash3 } from "node:crypto";
14867
- import { existsSync as existsSync13, readFileSync as readFileSync15, rmSync as rmSync8, statSync as statSync11, utimesSync, writeFileSync as writeFileSync8 } from "node:fs";
14907
+ import { existsSync as existsSync12, readFileSync as readFileSync15, rmSync as rmSync8, statSync as statSync11, utimesSync, writeFileSync as writeFileSync8 } from "node:fs";
14868
14908
  import { basename as basename8, join as join15 } from "node:path";
14869
14909
  function forceNextImport(projectPath, resourcePath) {
14870
14910
  const relative = resourcePath.replace(/^res:\/\//, "");
14871
14911
  const sidecar = join15(projectPath, `${relative}.import`);
14872
- if (!existsSync13(sidecar)) {
14912
+ if (!existsSync12(sidecar)) {
14873
14913
  return;
14874
14914
  }
14875
14915
  const { atime, mtimeMs } = statSync11(sidecar);
@@ -14884,7 +14924,7 @@ function importRecord(projectPath, resourcePath) {
14884
14924
  var init_reimport = () => {};
14885
14925
 
14886
14926
  // src/scratch.ts
14887
- import { existsSync as existsSync14, mkdtempSync as mkdtempSync2, readdirSync as readdirSync10, rmSync as rmSync9 } from "node:fs";
14927
+ import { existsSync as existsSync13, mkdtempSync as mkdtempSync2, readdirSync as readdirSync10, rmSync as rmSync9 } from "node:fs";
14888
14928
  import { tmpdir as tmpdir5 } from "node:os";
14889
14929
  import { join as join16 } from "node:path";
14890
14930
  import process10 from "node:process";
@@ -14943,7 +14983,7 @@ function tryAgain(path, attempt) {
14943
14983
  lastTryOnExit();
14944
14984
  }
14945
14985
  const after = AGAIN_AFTER_MS[attempt];
14946
- if (after === undefined || !existsSync14(path)) {
14986
+ if (after === undefined || !existsSync13(path)) {
14947
14987
  waiting.delete(path);
14948
14988
  if (after === undefined) {
14949
14989
  atExit.add(path);
@@ -15099,7 +15139,7 @@ var init_script_origins = __esm(() => {
15099
15139
  });
15100
15140
 
15101
15141
  // src/headless.ts
15102
- import { existsSync as existsSync15, readFileSync as readFileSync16, writeFileSync as writeFileSync9 } from "node:fs";
15142
+ import { existsSync as existsSync14, readFileSync as readFileSync16, writeFileSync as writeFileSync9 } from "node:fs";
15103
15143
  import { dirname as dirname7, join as join18 } from "node:path";
15104
15144
  function snakeCased(params) {
15105
15145
  const result = emptyRecord();
@@ -15388,7 +15428,7 @@ async function operationOutcome(engine, operation, params, projectPath) {
15388
15428
  };
15389
15429
  }
15390
15430
  function answerIn(file) {
15391
- if (!existsSync15(file)) {
15431
+ if (!existsSync14(file)) {
15392
15432
  return { kind: "none" };
15393
15433
  }
15394
15434
  const text = readFileSync16(file, "utf8");
@@ -15417,7 +15457,7 @@ var init_headless = __esm(() => {
15417
15457
  });
15418
15458
 
15419
15459
  // src/update-check.ts
15420
- import { existsSync as existsSync16, mkdirSync as mkdirSync5, readFileSync as readFileSync17, writeFileSync as writeFileSync10 } from "node:fs";
15460
+ import { existsSync as existsSync15, mkdirSync as mkdirSync5, readFileSync as readFileSync17, writeFileSync as writeFileSync10 } from "node:fs";
15421
15461
  import { homedir as homedir6, tmpdir as tmpdir6 } from "node:os";
15422
15462
  import { join as join19 } from "node:path";
15423
15463
  function packageUrl(root) {
@@ -15459,7 +15499,7 @@ function cacheFile(environment = process.env) {
15459
15499
  }
15460
15500
  function readCache(path) {
15461
15501
  try {
15462
- if (!existsSync16(path)) {
15502
+ if (!existsSync15(path)) {
15463
15503
  return null;
15464
15504
  }
15465
15505
  const parsed = JSON.parse(readFileSync17(path, "utf8"));
@@ -15939,7 +15979,7 @@ var init_ports = __esm(() => {
15939
15979
  });
15940
15980
 
15941
15981
  // src/lsp_client.ts
15942
- import { existsSync as existsSync17, realpathSync as realpathSync3 } from "node:fs";
15982
+ import { existsSync as existsSync16, realpathSync as realpathSync3 } from "node:fs";
15943
15983
  import { readFile, realpath } from "node:fs/promises";
15944
15984
  import { createConnection } from "node:net";
15945
15985
  import { dirname as dirname8, extname as extname3, join as join20, resolve as resolve7 } from "node:path";
@@ -16620,7 +16660,7 @@ async function resolveLSPPaths(projectPathValue, scriptPathValue) {
16620
16660
  } catch {
16621
16661
  throw new ArgumentRefusal(`Project path does not exist: ${requestedProjectPath}`);
16622
16662
  }
16623
- if (!existsSync17(join20(projectPath, "project.godot"))) {
16663
+ if (!existsSync16(join20(projectPath, "project.godot"))) {
16624
16664
  throw new ArgumentRefusal(`Not a Godot project: ${projectPath}. Point projectPath at the directory holding project.godot.`);
16625
16665
  }
16626
16666
  const contained = resolveWithinProject(projectPath, scriptPathValue);
@@ -17134,7 +17174,7 @@ function readParams(params, key) {
17134
17174
  import { createHash as createHash5 } from "node:crypto";
17135
17175
  import {
17136
17176
  cpSync,
17137
- existsSync as existsSync19,
17177
+ existsSync as existsSync18,
17138
17178
  mkdirSync as mkdirSync6,
17139
17179
  readdirSync as readdirSync12,
17140
17180
  readFileSync as readFileSync21,
@@ -17217,7 +17257,7 @@ function installedRuntimeDigest(projectPath) {
17217
17257
  }
17218
17258
  function digestMarker(projectPath, addon) {
17219
17259
  const marker = join22(projectPath, "addons", addon, DIGEST_MARKER);
17220
- if (!existsSync19(marker)) {
17260
+ if (!existsSync18(marker)) {
17221
17261
  return null;
17222
17262
  }
17223
17263
  const said = readFileSync21(marker, "utf8").trim();
@@ -17234,7 +17274,7 @@ function shippedLoader() {
17234
17274
  }
17235
17275
  function loaderState(projectPath) {
17236
17276
  const copy = join22(projectPath, ...RUNTIME_AUTOLOAD.path.split("/"));
17237
- if (!existsSync19(copy)) {
17277
+ if (!existsSync18(copy)) {
17238
17278
  return "missing";
17239
17279
  }
17240
17280
  const lines = (path) => readFileSync21(path, "utf8").replaceAll(`\r
@@ -17253,7 +17293,7 @@ function writeLoader(projectPath) {
17253
17293
  }
17254
17294
  function removeLoader(projectPath) {
17255
17295
  const copy = join22(projectPath, ...RUNTIME_AUTOLOAD.path.split("/"));
17256
- if (!existsSync19(copy)) {
17296
+ if (!existsSync18(copy)) {
17257
17297
  return false;
17258
17298
  }
17259
17299
  rmSync10(copy);
@@ -17269,10 +17309,10 @@ function shippedListedRunner() {
17269
17309
  }
17270
17310
  function gdUnit4Unusable(projectPath) {
17271
17311
  const marker = "addons/gdUnit4/plugin.cfg";
17272
- if (!existsSync19(join22(projectPath, ...marker.split("/")))) {
17312
+ if (!existsSync18(join22(projectPath, ...marker.split("/")))) {
17273
17313
  return { missing: true, reason: `gdUnit4 is not installed in this project: no ${marker}` };
17274
17314
  }
17275
- if (!existsSync19(join22(projectPath, ...GDUNIT4_CI_RUNNER.split("/")))) {
17315
+ if (!existsSync18(join22(projectPath, ...GDUNIT4_CI_RUNNER.split("/")))) {
17276
17316
  return {
17277
17317
  missing: false,
17278
17318
  reason: `gdUnit4 in this project is older than 6.0, which the shipped runner needs: no ${GDUNIT4_CI_RUNNER}`
@@ -17284,11 +17324,11 @@ function installAddons(projectPath, from = shippedAddonsDirectory()) {
17284
17324
  const installed = [];
17285
17325
  for (const name of ADDONS) {
17286
17326
  const source = join22(from, name);
17287
- if (!existsSync19(join22(source, addonMarking(name)))) {
17327
+ if (!existsSync18(join22(source, addonMarking(name)))) {
17288
17328
  throw new Error(`The package holds no ${name} addon at ${source}.`);
17289
17329
  }
17290
17330
  const target = join22(projectPath, "addons", name);
17291
- const replaced = existsSync19(target);
17331
+ const replaced = existsSync18(target);
17292
17332
  rmSync10(target, { recursive: true, force: true });
17293
17333
  mkdirSync6(dirname9(target), { recursive: true });
17294
17334
  cpSync(source, target, { recursive: true });
@@ -17304,7 +17344,7 @@ function installAddons(projectPath, from = shippedAddonsDirectory()) {
17304
17344
  }
17305
17345
  function installedAddonVersion(projectPath) {
17306
17346
  const marker = join22(projectPath, "addons", ADDONS[0], VERSION_MARKER);
17307
- if (!existsSync19(marker)) {
17347
+ if (!existsSync18(marker)) {
17308
17348
  return null;
17309
17349
  }
17310
17350
  const said = readFileSync21(marker, "utf8").trim();
@@ -17314,13 +17354,13 @@ function removeAddons(projectPath) {
17314
17354
  const removed = [];
17315
17355
  for (const name of ADDONS) {
17316
17356
  const target = join22(projectPath, "addons", name);
17317
- if (existsSync19(target)) {
17357
+ if (existsSync18(target)) {
17318
17358
  rmSync10(target, { recursive: true, force: true });
17319
17359
  removed.push(target);
17320
17360
  }
17321
17361
  }
17322
17362
  const addons = join22(projectPath, "addons");
17323
- if (removed.length > 0 && existsSync19(addons) && readdirSync12(addons).length === 0) {
17363
+ if (removed.length > 0 && existsSync18(addons) && readdirSync12(addons).length === 0) {
17324
17364
  rmdirSync(addons);
17325
17365
  removed.push(addons);
17326
17366
  }
@@ -17420,8 +17460,8 @@ function inspectProject(projectPath) {
17420
17460
  const addons = ADDONS.map((name) => {
17421
17461
  const directory = join22(projectPath, "addons", name);
17422
17462
  const marker = join22(directory, VERSION_MARKER);
17423
- const installed = existsSync19(directory);
17424
- const version = existsSync19(marker) ? readFileSync21(marker, "utf8").trim() : null;
17463
+ const installed = existsSync18(directory);
17464
+ const version = existsSync18(marker) ? readFileSync21(marker, "utf8").trim() : null;
17425
17465
  const current = version === SERVER_VERSION;
17426
17466
  if (!installed) {
17427
17467
  problems.push(`addons/${name} is not installed; run gdharness setup`);
@@ -17454,7 +17494,7 @@ function inspectProject(projectPath) {
17454
17494
  const ignoredAutoloads = [];
17455
17495
  const addonMissing = (path) => addons.some((addon) => !addon.installed && path.startsWith(`addons/${addon.name}/`));
17456
17496
  for (const [name, path] of named) {
17457
- if (!existsSync19(join22(projectPath, path))) {
17497
+ if (!existsSync18(join22(projectPath, path))) {
17458
17498
  if (!addonMissing(path)) {
17459
17499
  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`);
17460
17500
  }
@@ -18338,7 +18378,7 @@ var init_tool_definitions = __esm(() => {
18338
18378
  name: "scene_node",
18339
18379
  title: "Scene nodes",
18340
18380
  description: `One node in a scene file: add, read, set, duplicate, reparent or delete it, paint TileMap cells, or bake a navigation region. Any ClassDB node type or script class can be added, so a NavigationRegion2D, an AnimationTree or a Camera3D is an add with that nodeType and its properties, and another scene is instanced by an add with instancePath. A set with properties {"name": "Boss"} renames a node, and answers nodePath as its new path. A rename or a reparent carries the node paths naming the node, as the editor's rename does: NodePath values on nodes (in arrays, dictionaries, built-in resources, %unique paths) and the tracks its players' animations hold, saving a library kept in a .tres of its own, and answers each rewrite under retargeted and each path it left under notRetargeted. The move is followed into every other .tscn that instances or inherits this scene at any depth: the editable children, values, added nodes and connections named by the old path are rewritten, since Godot finds a moved node's values by unique_id but editable children only by path and drops the values kept below them on the next save, and that scene's node paths and tracks are carried as above. A delete rewrites no path, and answers under stillNaming what named the deleted node and now names nothing. A property holding a Resource takes the res:// path of one, so a texture, a material or a theme is a set like any other. A write is refused while the editor holds unsaved changes to the scene. A node this scene inherits takes values of this scene's own, and so does a node inside an instance of another scene once that instance's editableChildren is true; neither can be moved, renamed, copied or deleted, since the other scene makes it again on load. ${WITHOUT_AN_EDITOR}`,
18341
- answer: "get answers nodeType, the node's engine class, with scriptClass when its script declares a class_name; nodePath, its path from the root however it was named; setHere, the properties this scene's own file sets on it; and valuesFrom, the scene every other value comes from, when another scene makes the node. A set that gives a property the value the node has without it (what the scene it comes from gives, or its default) leaves it out of the file, as the editor does, and answers it under notStored, with notStoredNote saying what it follows now. retargeted lists each path a rename or a reparent rewrote, as {scenePath, nodePath, property or animation and track, from, to}, and notRetargeted each it left, with a reason: a track kept in another scene or an imported file, or a value another scene gives that the move left naming nothing. followed names the other scenes a move rewrote, and notFollowed any left as they were, with why. scriptsNaming lists each line of a script that reads a node a rename, a reparent or a delete took by the path it had, as {scenePath, nodePath, script, line, from, to}: the script is on the node at nodePath, or is one that node's script extends, in this scene or one instancing or inheriting it, and to is the path that reaches the node from there now, absent after a delete. It reads $Path, %Unique, and a string handed to get_node, get_node_or_null or has_node on the node itself; a path built at run time is not seen. Scripts are left as they were, as the editor's own rename leaves them, so each line listed fails until it is changed. A 2D bake_navigation that read no obstacle says in its note that all its outlines enclose is walkable, and names the nodes giving obstacles that sit under no region. stillNaming lists each node path and track, here and in the scenes instancing or inheriting this one, that named a deleted node; a property typed as a node, or an array or dictionary of nodes, holds the node itself, so the one that held a deleted node holds null there, as the editor saves it, and its entry adds cleared: true. deletedWithIt lists each node of this scene's own that went with it, the nodes inside an instance going with the instance. groups lists, sorted, every group a node is in, on a get, an add that gave addGroups and every set that changes them; get adds groupsHere, the groups this file puts it in, when another scene puts it in others, and layers, each layer mask it answers (collision_layer, collision_mask, visibility_layer) as the layers it holds, {layer, name} with the name project.godot gives the layer. Each of these lists is answered only when it names anything. add and set answer each property given under properties as the node holds it once written; alsoChanged gives the other properties the engine changed in step with a set, as a Control's offsets with its size, and those a reparent changed to keep the node where it is drawn or that the new parent sets, as a container gives a Control its layout_mode, as {was, now}; namesNoNode, each node path written naming no node; sharedWith, for a property written through a resource built into the scene, each other {node, property} holding it, which changed too; setByScript, what a script that is not a tool set as a headless write ran, which the file does not hold; loadsAs, a value given that the file holds and the node's own script changes as the scene loads, as it loads. get adds placement, a Node3D's position, rotation_degrees and scale from its transform. " + ALSO_SAVED,
18381
+ answer: "get answers nodeType, the node's engine class, with scriptClass when its script declares a class_name; nodePath, its path from the root however it was named; setHere, the properties this scene's own file sets on it; and valuesFrom, the scene every other value comes from, when another scene makes the node. A set that gives a property the value the node has without it (what the scene it comes from gives, or its default) leaves it out of the file, as the editor does, and answers it under notStored, with notStoredNote saying what it follows now. retargeted lists each path a rename or a reparent rewrote, as {scenePath, nodePath, property or animation and track, from, to}, and notRetargeted each it left, with a reason: a track kept in another scene or an imported file, or a value another scene gives that the move left naming nothing. followed names the other scenes a move rewrote, and notFollowed any left as they were, with why. scriptsNaming lists each line of a script that reads a node a rename, a reparent or a delete took by the path it had, as {scenePath, nodePath, script, line, from, to}: the script is on the node at nodePath, or is one that node's script extends, in this scene or one instancing or inheriting it, and to is the path that reaches the node from there now, absent after a delete. It reads $Path, %Unique, and a string handed to get_node, get_node_or_null or has_node on the node itself; a path built at run time is not seen. Scripts are left as they were, as the editor's own rename leaves them, so each line listed fails until it is changed. A 2D bake_navigation that read no obstacle says in its note that all its outlines enclose is walkable, and names the nodes giving obstacles that sit under no region. stillNaming lists each node path and track, here and in the scenes instancing or inheriting this one, that named a deleted node; a property typed as a node, or an array or dictionary of nodes, holds the node itself, so the one that held a deleted node holds null there, as the editor saves it, and its entry adds cleared: true. deletedWithIt lists each node of this scene's own that went with it, the nodes inside an instance going with the instance. connectionsRemoved lists each connection the file held from or to a node a delete took, as {sourceNodePath, signalName, targetNodePath, methodName}. groups lists, sorted, every group a node is in, on a get, an add that gave addGroups and every set that changes them; get adds groupsHere, the groups this file puts it in, when another scene puts it in others, and layers, each layer mask it answers (collision_layer, collision_mask, visibility_layer) as the layers it holds, {layer, name} with the name project.godot gives the layer. Each of these lists is answered only when it names anything. add and set answer each property given under properties as the node holds it once written; alsoChanged gives the other properties the engine changed in step with a set, as a Control's offsets with its size, and those a reparent changed to keep the node where it is drawn or that the new parent sets, as a container gives a Control its layout_mode, as {was, now}; namesNoNode, each node path written naming no node; sharedWith, for a property written through a resource built into the scene, each other {node, property} holding it, which changed too; setByScript, what a script that is not a tool set as a headless write ran, which the file does not hold; loadsAs, a value given that the file holds and the node's own script changes as the scene loads, as it loads. get adds placement, a Node3D's position, rotation_degrees and scale from its transform. " + ALSO_SAVED,
18342
18382
  parameters: {
18343
18383
  projectPath: PROJECT_PATH,
18344
18384
  scenePath: SCENE_PATH,
@@ -20025,7 +20065,7 @@ var init_tool_reference = __esm(() => {
20025
20065
  });
20026
20066
 
20027
20067
  // src/suite-plan.ts
20028
- import { existsSync as existsSync23, mkdirSync as mkdirSync9, readFileSync as readFileSync24 } from "node:fs";
20068
+ import { existsSync as existsSync22, mkdirSync as mkdirSync9, readFileSync as readFileSync24 } from "node:fs";
20029
20069
  import { dirname as dirname11, join as join26, posix as posix3 } from "node:path";
20030
20070
  function within(path, folder) {
20031
20071
  return path === folder || path.startsWith(`${folder}/`);
@@ -20437,7 +20477,7 @@ function windowNeedsOf(scripts, paths) {
20437
20477
  }
20438
20478
  function capsFrames(projectPath) {
20439
20479
  const file = `${projectPath}/project.godot`;
20440
- if (!existsSync23(file)) {
20480
+ if (!existsSync22(file)) {
20441
20481
  return false;
20442
20482
  }
20443
20483
  const cap = parseProjectGodot(readFileSync24(file, "utf8"))["application"]?.["run/max_fps"];
@@ -20445,14 +20485,14 @@ function capsFrames(projectPath) {
20445
20485
  }
20446
20486
  function gdUnitFailsOnPushErrors(projectPath) {
20447
20487
  const file = `${projectPath}/project.godot`;
20448
- if (!existsSync23(file)) {
20488
+ if (!existsSync22(file)) {
20449
20489
  return false;
20450
20490
  }
20451
20491
  return parseProjectGodot(readFileSync24(file, "utf8"))["gdunit4"]?.["report/godot/push_error"] === true;
20452
20492
  }
20453
20493
  function viewportOf(projectPath) {
20454
20494
  const file = `${projectPath}/project.godot`;
20455
- if (!existsSync23(file)) {
20495
+ if (!existsSync22(file)) {
20456
20496
  return null;
20457
20497
  }
20458
20498
  const text = readFileSync24(file, "utf8");
@@ -42074,7 +42114,7 @@ var init_stdio = __esm(() => {
42074
42114
  });
42075
42115
 
42076
42116
  // src/autoload-failure.ts
42077
- import { existsSync as existsSync25, readFileSync as readFileSync27 } from "node:fs";
42117
+ import { existsSync as existsSync24, readFileSync as readFileSync27 } from "node:fs";
42078
42118
  import { join as join29 } from "node:path";
42079
42119
  function scriptsAutoloaded(projectPath) {
42080
42120
  const scripts = new Map;
@@ -42090,7 +42130,7 @@ function scriptsAutoloaded(projectPath) {
42090
42130
  continue;
42091
42131
  }
42092
42132
  const scene = join29(projectPath, path);
42093
- if (!existsSync25(scene)) {
42133
+ if (!existsSync24(scene)) {
42094
42134
  continue;
42095
42135
  }
42096
42136
  try {
@@ -42113,11 +42153,11 @@ var init_autoload_failure = __esm(() => {
42113
42153
  });
42114
42154
 
42115
42155
  // src/runtime-client.ts
42116
- import { existsSync as existsSync26, readdirSync as readdirSync16, readFileSync as readFileSync28, statSync as statSync15, unlinkSync as unlinkSync3 } from "node:fs";
42156
+ import { existsSync as existsSync25, readdirSync as readdirSync16, readFileSync as readFileSync28, statSync as statSync15, unlinkSync as unlinkSync3 } from "node:fs";
42117
42157
  import { createConnection as createConnection2 } from "node:net";
42118
42158
  import { tmpdir as tmpdir7 } from "node:os";
42119
42159
  import { dirname as dirname14, join as join30, resolve as resolve12 } from "node:path";
42120
- import { setTimeout as delay5 } from "node:timers/promises";
42160
+ import { setTimeout as delay6 } from "node:timers/promises";
42121
42161
  function runtimeDirectory(variables = process.env) {
42122
42162
  const explicit = envValue("GDHARNESS_RUNTIME_DIR", variables);
42123
42163
  if (explicit) {
@@ -42137,7 +42177,7 @@ function runtimeDirectories(variables = process.env) {
42137
42177
  function errorReportOf(pid, directories = runtimeDirectories()) {
42138
42178
  for (const directory of directories) {
42139
42179
  const path = join30(directory, `runtime-${pid}.log`);
42140
- if (existsSync26(path)) {
42180
+ if (existsSync25(path)) {
42141
42181
  return path;
42142
42182
  }
42143
42183
  }
@@ -42283,7 +42323,7 @@ function strangersAmong(candidates, now, startTimes = startTimesOf) {
42283
42323
  }).map((one) => one.file));
42284
42324
  }
42285
42325
  function announcedIn(directory) {
42286
- if (!existsSync26(directory)) {
42326
+ if (!existsSync25(directory)) {
42287
42327
  return [];
42288
42328
  }
42289
42329
  const found = [];
@@ -42336,7 +42376,7 @@ function announcedIn(directory) {
42336
42376
  return found;
42337
42377
  }
42338
42378
  async function announcementEnded(pid, directories = runtimeDirectories()) {
42339
- const files = directories.map((directory) => join30(directory, `runtime-${pid}.json`)).filter((file) => existsSync26(file));
42379
+ const files = directories.map((directory) => join30(directory, `runtime-${pid}.json`)).filter((file) => existsSync25(file));
42340
42380
  const first = files[0];
42341
42381
  if (first === undefined) {
42342
42382
  return;
@@ -42347,7 +42387,7 @@ async function announcementEnded(pid, directories = runtimeDirectories()) {
42347
42387
  if (left <= 0) {
42348
42388
  return;
42349
42389
  }
42350
- await delay5(Math.min(LOOK_EVERY_MS, left));
42390
+ await delay6(Math.min(LOOK_EVERY_MS, left));
42351
42391
  }
42352
42392
  wentAway(first, pid);
42353
42393
  for (const file of files) {
@@ -42379,7 +42419,7 @@ async function announcedSince(projectPath, before, waiting = {}) {
42379
42419
  if (left <= 0 || waiting.giveUp?.() === true) {
42380
42420
  return [];
42381
42421
  }
42382
- await delay5(Math.min(LOOK_EVERY_MS, left));
42422
+ await delay6(Math.min(LOOK_EVERY_MS, left));
42383
42423
  }
42384
42424
  }
42385
42425
  function describe2(endpoint) {
@@ -42915,11 +42955,11 @@ var init_class_note = __esm(() => {
42915
42955
  });
42916
42956
 
42917
42957
  // src/config-pin.ts
42918
- import { existsSync as existsSync27, readFileSync as readFileSync32 } from "node:fs";
42958
+ import { existsSync as existsSync26, readFileSync as readFileSync32 } from "node:fs";
42919
42959
  import { join as join34 } from "node:path";
42920
42960
  function versionsNamedInConfig(projectPath) {
42921
42961
  const config = join34(projectPath, ".mcp.json");
42922
- if (!existsSync27(config)) {
42962
+ if (!existsSync26(config)) {
42923
42963
  return [];
42924
42964
  }
42925
42965
  let text;
@@ -42945,7 +42985,7 @@ var init_config_pin = __esm(() => {
42945
42985
  });
42946
42986
 
42947
42987
  // src/cut-test-run.ts
42948
- import { existsSync as existsSync28, mkdirSync as mkdirSync14, readFileSync as readFileSync33, rmSync as rmSync15, writeFileSync as writeFileSync16 } from "node:fs";
42988
+ import { existsSync as existsSync27, mkdirSync as mkdirSync14, readFileSync as readFileSync33, rmSync as rmSync15, writeFileSync as writeFileSync16 } from "node:fs";
42949
42989
  import { dirname as dirname18, join as join35 } from "node:path";
42950
42990
  function keptAt(projectPath) {
42951
42991
  return join35(projectPath, ".godot", "gdharness-reports", "cut-run.json");
@@ -42960,7 +43000,7 @@ function keepCutTestRun(projectPath, run) {
42960
43000
  }
42961
43001
  function takeCutTestRun(projectPath) {
42962
43002
  const path = keptAt(projectPath);
42963
- if (!existsSync28(path)) {
43003
+ if (!existsSync27(path)) {
42964
43004
  return null;
42965
43005
  }
42966
43006
  try {
@@ -43006,7 +43046,7 @@ var init_game_debugger = __esm(() => {
43006
43046
 
43007
43047
  // src/dap_client.ts
43008
43048
  import { createConnection as createConnection3 } from "node:net";
43009
- import { setTimeout as delay6 } from "node:timers/promises";
43049
+ import { setTimeout as delay7 } from "node:timers/promises";
43010
43050
  function fileKey(path) {
43011
43051
  return process.platform === "win32" ? path.replaceAll("\\", "/").toLowerCase() : path;
43012
43052
  }
@@ -43486,7 +43526,7 @@ class GodotDAPClient {
43486
43526
  await this.sendRequest(command, { threadId: resolvedThreadId });
43487
43527
  const deadline = Date.now() + this.stepPatienceMs;
43488
43528
  while (this.stops === before && this.connected && Date.now() < deadline) {
43489
- await delay6(50);
43529
+ await delay7(50);
43490
43530
  }
43491
43531
  return this.stops !== before;
43492
43532
  }
@@ -43512,7 +43552,7 @@ class GodotDAPClient {
43512
43552
  return answered;
43513
43553
  }
43514
43554
  } catch {}
43515
- await delay6(200);
43555
+ await delay7(200);
43516
43556
  }
43517
43557
  return null;
43518
43558
  }
@@ -43533,7 +43573,7 @@ class GodotDAPClient {
43533
43573
  break;
43534
43574
  }
43535
43575
  } catch {}
43536
- await delay6(200);
43576
+ await delay7(200);
43537
43577
  }
43538
43578
  if (scopes.length === 0) {
43539
43579
  throw new ReadRefusal(`The scopes of frame ${String(frame["id"])} did not arrive from the game within ${this.scopesPatienceMs / 1000}s. They come from the game through the editor, so a busy machine can take longer: ask again`);
@@ -43566,7 +43606,7 @@ class GodotDAPClient {
43566
43606
  return { frame, value, ...typeof type === "string" ? { type } : {} };
43567
43607
  }
43568
43608
  } catch {}
43569
- await delay6(200);
43609
+ await delay7(200);
43570
43610
  }
43571
43611
  throw new ReadRefusal(`What ${expression} comes to did not arrive from the game within ${this.evaluatePatienceMs / 1000}s. It comes from the game through the editor, and the first expression a game evaluates loads the script of every global class in the project first, static initialisers included, so one of those may still be running: ask again`);
43572
43612
  }
@@ -43728,7 +43768,7 @@ var init_dap_client = __esm(() => {
43728
43768
  // src/editor-log.ts
43729
43769
  import {
43730
43770
  closeSync as closeSync5,
43731
- existsSync as existsSync29,
43771
+ existsSync as existsSync28,
43732
43772
  mkdirSync as mkdirSync15,
43733
43773
  openSync as openSync5,
43734
43774
  readFileSync as readFileSync34,
@@ -43792,7 +43832,7 @@ function editorConsole(projectPath, editorPid, openedByAServer) {
43792
43832
  return { kind: "another editor", notedPid: noted?.pid ?? null };
43793
43833
  }
43794
43834
  const path = editorLogPath(projectPath);
43795
- if (!existsSync29(path)) {
43835
+ if (!existsSync28(path)) {
43796
43836
  return { kind: "not written" };
43797
43837
  }
43798
43838
  const log = new GameLog;
@@ -44011,7 +44051,7 @@ var init_editor_log = __esm(() => {
44011
44051
  });
44012
44052
 
44013
44053
  // src/rename.ts
44014
- import { existsSync as existsSync30, mkdirSync as mkdirSync16, readFileSync as readFileSync35, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync18 } from "node:fs";
44054
+ import { existsSync as existsSync29, mkdirSync as mkdirSync16, readFileSync as readFileSync35, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync18 } from "node:fs";
44015
44055
  import { dirname as dirname20, posix as posix4 } from "node:path";
44016
44056
 
44017
44057
  class Script {
@@ -44736,7 +44776,7 @@ function applyRewrites(rewrites) {
44736
44776
  if (now !== rewrite.before) {
44737
44777
  throw new Error(`${rewrite.path} changed on disk while the rename was being worked out; nothing was written`);
44738
44778
  }
44739
- if (rewrite.writeTo !== rewrite.absolute && existsSync30(rewrite.writeTo)) {
44779
+ if (rewrite.writeTo !== rewrite.absolute && existsSync29(rewrite.writeTo)) {
44740
44780
  throw new Error(`${rewrite.writeTo} already exists; nothing was written`);
44741
44781
  }
44742
44782
  }
@@ -44750,7 +44790,7 @@ function applyRewrites(rewrites) {
44750
44790
  let movedUid = false;
44751
44791
  if (rewrite.writeTo !== rewrite.absolute) {
44752
44792
  unlinkSync4(rewrite.absolute);
44753
- if (existsSync30(`${rewrite.absolute}.uid`)) {
44793
+ if (existsSync29(`${rewrite.absolute}.uid`)) {
44754
44794
  renameSync4(`${rewrite.absolute}.uid`, `${rewrite.writeTo}.uid`);
44755
44795
  movedUid = true;
44756
44796
  }
@@ -44796,7 +44836,7 @@ var init_rename = __esm(() => {
44796
44836
  });
44797
44837
 
44798
44838
  // src/rename-symbol.ts
44799
- import { existsSync as existsSync31, mkdirSync as mkdirSync17, readdirSync as readdirSync17, realpathSync as realpathSync5, rmSync as rmSync17, writeFileSync as writeFileSync19 } from "node:fs";
44839
+ import { existsSync as existsSync30, mkdirSync as mkdirSync17, readdirSync as readdirSync17, realpathSync as realpathSync5, rmSync as rmSync17, writeFileSync as writeFileSync19 } from "node:fs";
44800
44840
  import { basename as basename10, dirname as dirname21, join as join37, relative as relative7, resolve as resolve13 } from "node:path";
44801
44841
  function resourcePathOf(projectPath, absolute) {
44802
44842
  const inside = relative7(onDiskSpelling(projectPath), onDiskSpelling(absolute));
@@ -44864,7 +44904,7 @@ async function renameSymbol(request, services) {
44864
44904
  reason: `newScriptPath must be a .gd path inside the project, and ${request.newScriptPath} is not.`
44865
44905
  };
44866
44906
  }
44867
- if (existsSync31(request.newScriptPath)) {
44907
+ if (existsSync30(request.newScriptPath)) {
44868
44908
  return { ok: false, reason: `${moveTo} already exists, so the script cannot be moved there.` };
44869
44909
  }
44870
44910
  }
@@ -45041,7 +45081,7 @@ async function renameSymbol(request, services) {
45041
45081
  scripts,
45042
45082
  moves: new Map([[declaringPath, moveTo]]),
45043
45083
  named: [declaringPath],
45044
- exists: (path) => existsSync31(`${projectPath}/${path.slice("res://".length)}`)
45084
+ exists: (path) => existsSync30(`${projectPath}/${path.slice("res://".length)}`)
45045
45085
  }, plan);
45046
45086
  }
45047
45087
  plan = mentionIgnored(plan, ignoredTexts(projectPath), symbol, moveTo === null ? [] : [declaringPath]);
@@ -45316,7 +45356,7 @@ var init_rename_symbol = __esm(() => {
45316
45356
 
45317
45357
  // src/file-move.ts
45318
45358
  import {
45319
- existsSync as existsSync32,
45359
+ existsSync as existsSync31,
45320
45360
  mkdirSync as mkdirSync18,
45321
45361
  readdirSync as readdirSync18,
45322
45362
  readFileSync as readFileSync36,
@@ -45349,7 +45389,7 @@ function unseenByTheEngine(projectPath, path) {
45349
45389
  }
45350
45390
  if (at < steps.length - 1) {
45351
45391
  directory = join38(directory, step);
45352
- if (existsSync32(join38(directory, ".gdignore"))) {
45392
+ if (existsSync31(join38(directory, ".gdignore"))) {
45353
45393
  return `${path} is under a directory holding a .gdignore, which the engine does not load`;
45354
45394
  }
45355
45395
  }
@@ -45361,12 +45401,12 @@ function installedAddonOf(projectPath, path) {
45361
45401
  if (steps[0] !== "addons" || steps[1] === undefined) {
45362
45402
  return null;
45363
45403
  }
45364
- return existsSync32(join38(projectPath, "addons", steps[1], VERSION_MARKER)) ? `res://addons/${steps[1]}` : null;
45404
+ return existsSync31(join38(projectPath, "addons", steps[1], VERSION_MARKER)) ? `res://addons/${steps[1]}` : null;
45365
45405
  }
45366
45406
  function binaryResources(projectPath) {
45367
45407
  const found = [];
45368
45408
  const visit = (directory, prefix) => {
45369
- if (existsSync32(join38(directory, ".gdignore"))) {
45409
+ if (existsSync31(join38(directory, ".gdignore"))) {
45370
45410
  return;
45371
45411
  }
45372
45412
  for (const entry of readdirSync18(directory, { withFileTypes: true })) {
@@ -45403,7 +45443,7 @@ function planFileMove(projectPath, absoluteFrom, absoluteTo) {
45403
45443
  if (to === null) {
45404
45444
  return { ok: false, reason: `newPath must be a path inside the project, and ${absoluteTo} is not.` };
45405
45445
  }
45406
- if (!existsSync32(absoluteFrom)) {
45446
+ if (!existsSync31(absoluteFrom)) {
45407
45447
  return { ok: false, reason: `There is nothing at ${from} to move.` };
45408
45448
  }
45409
45449
  if (from === to) {
@@ -45432,7 +45472,7 @@ function planFileMove(projectPath, absoluteFrom, absoluteTo) {
45432
45472
  if (isDirectory && to.startsWith(`${from}/`)) {
45433
45473
  return { ok: false, reason: `${from} cannot be moved into itself.` };
45434
45474
  }
45435
- if (existsSync32(absoluteTo) && !sameFile(absoluteFrom, absoluteTo)) {
45475
+ if (existsSync31(absoluteTo) && !sameFile(absoluteFrom, absoluteTo)) {
45436
45476
  return { ok: false, reason: `${to} already exists, so nothing was moved there.` };
45437
45477
  }
45438
45478
  const unseen = unseenByTheEngine(projectPath, to);
@@ -45440,7 +45480,7 @@ function planFileMove(projectPath, absoluteFrom, absoluteTo) {
45440
45480
  return { ok: false, reason: `${unseen}, so nothing there could load what was moved.` };
45441
45481
  }
45442
45482
  if (!isDirectory) {
45443
- 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))));
45483
+ 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))));
45444
45484
  if (owner !== undefined && owner !== null) {
45445
45485
  return { ok: false, reason: `${from} belongs to ${owner} and moves with it: move ${owner} instead.` };
45446
45486
  }
@@ -45462,7 +45502,7 @@ function planFileMove(projectPath, absoluteFrom, absoluteTo) {
45462
45502
  } else {
45463
45503
  moves.set(from, to);
45464
45504
  for (const sidecar of SIDECARS) {
45465
- if (existsSync32(`${absoluteFrom}${sidecar}`)) {
45505
+ if (existsSync31(`${absoluteFrom}${sidecar}`)) {
45466
45506
  moves.set(`${from}${sidecar}`, `${to}${sidecar}`);
45467
45507
  }
45468
45508
  }
@@ -45474,7 +45514,7 @@ function planFileMove(projectPath, absoluteFrom, absoluteTo) {
45474
45514
  scripts,
45475
45515
  moves,
45476
45516
  named: [from],
45477
- exists: (path) => existsSync32(join38(projectPath, path.slice("res://".length)))
45517
+ exists: (path) => existsSync31(join38(projectPath, path.slice("res://".length)))
45478
45518
  }, { edits: [], mentions: [] });
45479
45519
  plan = mentionIgnored(plan, ignoredTexts(projectPath), null, [from]);
45480
45520
  const binaries = [];
@@ -45545,13 +45585,13 @@ function applyFileMove(outcome) {
45545
45585
  }
45546
45586
  }
45547
45587
  for (const file of outcome.moved) {
45548
- if (!existsSync32(file.absoluteFrom)) {
45588
+ if (!existsSync31(file.absoluteFrom)) {
45549
45589
  throw new Error(`${file.from} is gone from disk; nothing was written`);
45550
45590
  }
45551
45591
  if (file.text !== null && readFileSync36(file.absoluteFrom, "utf8") !== file.text.before) {
45552
45592
  throw new Error(`${file.from} changed on disk while the move was being worked out; nothing was written`);
45553
45593
  }
45554
- if (existsSync32(file.absoluteTo) && !sameFile(file.absoluteFrom, file.absoluteTo)) {
45594
+ if (existsSync31(file.absoluteTo) && !sameFile(file.absoluteFrom, file.absoluteTo)) {
45555
45595
  throw new Error(`${file.to} already exists; nothing was written`);
45556
45596
  }
45557
45597
  }
@@ -50277,10 +50317,10 @@ var init_server_instructions = __esm(() => {
50277
50317
  });
50278
50318
 
50279
50319
  // src/suites-scene.ts
50280
- import { existsSync as existsSync33, mkdirSync as mkdirSync22, writeFileSync as writeFileSync22 } from "node:fs";
50320
+ import { existsSync as existsSync32, mkdirSync as mkdirSync22, writeFileSync as writeFileSync22 } from "node:fs";
50281
50321
  import { join as join42, relative as relative9, sep as sep5 } from "node:path";
50282
50322
  function hasSuitesScene(projectPath) {
50283
- return existsSync33(join42(projectPath, SUITES_SCENE));
50323
+ return existsSync32(join42(projectPath, SUITES_SCENE));
50284
50324
  }
50285
50325
  function suitesSceneArgs(projectPath, suites) {
50286
50326
  const runs = join42(projectPath, ".godot", "gdharness", "suite-scenes");
@@ -50315,7 +50355,7 @@ var init_suites_scene = __esm(() => {
50315
50355
  });
50316
50356
 
50317
50357
  // src/test-selection.ts
50318
- import { existsSync as existsSync34 } from "node:fs";
50358
+ import { existsSync as existsSync33 } from "node:fs";
50319
50359
  import { basename as basename13, join as join43 } from "node:path";
50320
50360
  function casesOutOfPath(projectPath, given, tests) {
50321
50361
  const entries = Array.isArray(given) ? given : [given];
@@ -50360,12 +50400,12 @@ function casesIn(scripts, suite) {
50360
50400
  }
50361
50401
  function scriptsWithoutCases(projectPath, asked) {
50362
50402
  const scripts = new ProjectScripts(projectPath);
50363
- return asked.filter((path) => path.endsWith(".gd") && existsSync34(join43(projectPath, path.slice("res://".length))) && casesIn(scripts, path).length === 0);
50403
+ return asked.filter((path) => path.endsWith(".gd") && existsSync33(join43(projectPath, path.slice("res://".length))) && casesIn(scripts, path).length === 0);
50364
50404
  }
50365
50405
  function suitesUnder(projectPath, asked) {
50366
50406
  const scripts = projectFiles(projectPath, [".gd"]).map((path) => `res://${path}`);
50367
50407
  return [
50368
- ...new Set(asked.flatMap((path) => path.endsWith(".gd") ? existsSync34(join43(projectPath, path.slice("res://".length))) ? [path] : [] : scripts.filter((script) => script.startsWith(`${path}/`))))
50408
+ ...new Set(asked.flatMap((path) => path.endsWith(".gd") ? existsSync33(join43(projectPath, path.slice("res://".length))) ? [path] : [] : scripts.filter((script) => script.startsWith(`${path}/`))))
50369
50409
  ];
50370
50410
  }
50371
50411
  function selectTests(projectPath, asked, given) {
@@ -50431,7 +50471,7 @@ import {
50431
50471
  closeSync as closeSync6,
50432
50472
  constants,
50433
50473
  copyFileSync as copyFileSync2,
50434
- existsSync as existsSync35,
50474
+ existsSync as existsSync34,
50435
50475
  fstatSync as fstatSync3,
50436
50476
  mkdirSync as mkdirSync23,
50437
50477
  openSync as openSync7,
@@ -50444,7 +50484,7 @@ import {
50444
50484
  writeFileSync as writeFileSync23
50445
50485
  } from "node:fs";
50446
50486
  import { basename as basename14, dirname as dirname25, extname as extname6, isAbsolute as isAbsolute8, join as join44, normalize as normalize2, relative as relative10 } from "node:path";
50447
- import { setTimeout as delay7 } from "node:timers/promises";
50487
+ import { setTimeout as delay8 } from "node:timers/promises";
50448
50488
  import { fileURLToPath as fileURLToPath5 } from "node:url";
50449
50489
  function editorRestartTimeoutMs() {
50450
50490
  return waitFromEnv("GDHARNESS_EDITOR_RESTART_TIMEOUT_MS", 90000);
@@ -50459,7 +50499,7 @@ function greetingWaitMs() {
50459
50499
  function pictureToSend(pngPath, jpegPath) {
50460
50500
  const png = readFileSync40(pngPath);
50461
50501
  const beside = pngPath.replace(/\.png$/, ".jpg");
50462
- const jpeg = jpegPath !== undefined && normalize2(jpegPath) === normalize2(beside) && existsSync35(beside) ? readFileSync40(beside) : null;
50502
+ const jpeg = jpegPath !== undefined && normalize2(jpegPath) === normalize2(beside) && existsSync34(beside) ? readFileSync40(beside) : null;
50463
50503
  const sent = jpeg !== null && jpeg.length < png.length ? jpeg : png;
50464
50504
  return {
50465
50505
  data: sent.toString("base64"),
@@ -50499,7 +50539,7 @@ function writtenFileRefusal(path, rule) {
50499
50539
  return `${named} ${path} does not end in ${rule.extensions.join(" or ")}, which is what ${what} is.`;
50500
50540
  }
50501
50541
  const directory = realAsFarAsItExists(dirname25(path));
50502
- if (!existsSync35(directory)) {
50542
+ if (!existsSync34(directory)) {
50503
50543
  return `${named}'s directory ${dirname25(path)} does not exist; ${what} creates no directories.`;
50504
50544
  }
50505
50545
  const where = join44(directory, basename14(path));
@@ -50507,7 +50547,7 @@ function writtenFileRefusal(path, rule) {
50507
50547
  if (inside !== undefined) {
50508
50548
  return `${named} ${path} is inside the project at ${inside}; ${what} is saved outside it, so it never becomes part of the game.`;
50509
50549
  }
50510
- const taken = rule.writes(where).find((file) => existsSync35(file));
50550
+ const taken = rule.writes(where).find((file) => existsSync34(file));
50511
50551
  if (taken !== undefined) {
50512
50552
  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.`;
50513
50553
  }
@@ -50731,7 +50771,7 @@ async function untilGone(pids, withinMs = stopWaitMs()) {
50731
50771
  const gone = () => pids.every((pid) => !alive(pid));
50732
50772
  const deadline = Date.now() + withinMs;
50733
50773
  while (!gone() && Date.now() < deadline) {
50734
- await delay7(50);
50774
+ await delay8(50);
50735
50775
  }
50736
50776
  return gone();
50737
50777
  }
@@ -51293,7 +51333,7 @@ function unsavedInEditorNote(scripts) {
51293
51333
  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.`;
51294
51334
  }
51295
51335
  function editorAddonMissing(projectPath) {
51296
- if (!existsSync35(join44(projectPath, "project.godot"))) {
51336
+ if (!existsSync34(join44(projectPath, "project.godot"))) {
51297
51337
  return null;
51298
51338
  }
51299
51339
  const report = inspectProject(projectPath);
@@ -51837,7 +51877,7 @@ function uncaughtNote(uncaught) {
51837
51877
  }
51838
51878
  function elsewhereIn(projectPath, asked) {
51839
51879
  const wanted = asked.replace(/^res:\/\//, "").replace(/\/+$/, "");
51840
- if (wanted === "" || existsSync35(join44(projectPath, wanted))) {
51880
+ if (wanted === "" || existsSync34(join44(projectPath, wanted))) {
51841
51881
  return "";
51842
51882
  }
51843
51883
  const root = (wanted.split("/")[0] ?? "").toLowerCase();
@@ -51860,7 +51900,7 @@ function windowNoteFor(needing, sharing) {
51860
51900
  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}`;
51861
51901
  }
51862
51902
  function testPathsIn(projectPath, given, named = "path") {
51863
- const defaults = TEST_DIRECTORIES.filter((directory) => existsSync35(join44(projectPath, directory)));
51903
+ const defaults = TEST_DIRECTORIES.filter((directory) => existsSync34(join44(projectPath, directory)));
51864
51904
  const entries = given === undefined || given === null || given === "" ? defaults.length > 0 ? defaults : TEST_DIRECTORIES : given;
51865
51905
  const listed = Array.isArray(entries) ? entries : [entries];
51866
51906
  if (listed.length === 0) {
@@ -52147,7 +52187,7 @@ class GodotServer {
52147
52187
  taken = true;
52148
52188
  this.logDebug(`Took port ${wanted} over from pid ${announced.pid}`);
52149
52189
  } catch {
52150
- await delay7(HANDOVER_POLL_MS);
52190
+ await delay8(HANDOVER_POLL_MS);
52151
52191
  }
52152
52192
  }
52153
52193
  this.notHandedOverBy = taken ? null : announced.pid;
@@ -52285,7 +52325,7 @@ class GodotServer {
52285
52325
  argv: process.argv.slice(1),
52286
52326
  cwd,
52287
52327
  project: this.ownProject,
52288
- mcpJson: existsSync35(mcpJson) ? mcpJson : null
52328
+ mcpJson: existsSync34(mcpJson) ? mcpJson : null
52289
52329
  });
52290
52330
  if (predecessor !== null) {
52291
52331
  writeLifecycle("replaced", { project: this.ownProject, predecessor });
@@ -52427,7 +52467,7 @@ class GodotServer {
52427
52467
  return checked.response;
52428
52468
  }
52429
52469
  const named = args["projectPath"];
52430
- if (typeof named === "string" && existsSync35(join44(named, "project.godot"))) {
52470
+ if (typeof named === "string" && existsSync34(join44(named, "project.godot"))) {
52431
52471
  this.lastProjectPath = named;
52432
52472
  }
52433
52473
  this.updates.refresh();
@@ -53063,7 +53103,7 @@ class GodotServer {
53063
53103
  return this.createErrorResponse("line is required: the one-based line to stop on.");
53064
53104
  }
53065
53105
  if (op === "set") {
53066
- if (!existsSync35(located.absolutePath)) {
53106
+ if (!existsSync34(located.absolutePath)) {
53067
53107
  return this.missingScript(project.value.path, located.relativePath);
53068
53108
  }
53069
53109
  const nothing = lineNothingStopsOn(located.absolutePath, located.relativePath, line);
@@ -53168,7 +53208,7 @@ class GodotServer {
53168
53208
  return { ok: false, response: this.createErrorResponse("projectPath is required.") };
53169
53209
  }
53170
53210
  const file = join44(path, "project.godot");
53171
- if (!existsSync35(file)) {
53211
+ if (!existsSync34(file)) {
53172
53212
  return {
53173
53213
  ok: false,
53174
53214
  response: this.createErrorResponse(`Not a Godot project: ${path}`, [
@@ -53994,7 +54034,7 @@ class GodotServer {
53994
54034
  if (place !== null && !place.ok) {
53995
54035
  return this.createErrorResponse(place.reason);
53996
54036
  }
53997
- if (place !== null && !existsSync35(place.absolutePath)) {
54037
+ if (place !== null && !existsSync34(place.absolutePath)) {
53998
54038
  const folders = readdirSync20(project.value.path, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name).sort();
53999
54039
  return this.createErrorResponse(`There is nothing at res://${place.relativePath} to search.${folders.length === 0 ? "" : ` The project's folders are ${folders.join(", ")}.`}`);
54000
54040
  }
@@ -54185,7 +54225,7 @@ ${platform}`;
54185
54225
  output.absolutePath
54186
54226
  ];
54187
54227
  this.logDebug(`Exporting: ${engine.value} ${exportArgs.join(" ")}`);
54188
- const writtenAt = () => existsSync35(output.absolutePath) ? statSync20(output.absolutePath).mtimeMs : null;
54228
+ const writtenAt = () => existsSync34(output.absolutePath) ? statSync20(output.absolutePath).mtimeMs : null;
54189
54229
  const caches = editorCacheDirectory(engine.value);
54190
54230
  const exportOnce = async () => {
54191
54231
  const before = writtenAt();
@@ -54215,7 +54255,7 @@ ${platform}`;
54215
54255
  return this.createErrorResponse(`Export could not be run: ${ending.failure ?? "the engine gave no exit status"}`);
54216
54256
  }
54217
54257
  const beside = writtenBeside(listedBefore, filesIn(folder), basename14(output.absolutePath), dirname25(output.relativePath).replaceAll("\\", "/"));
54218
- return exportAnswer(ending, { preset, outputPath: output.relativePath, debug, ...pack ? { pack } : {} }, before, writtenAt(), beside, docCacheNote, existsSync35(output.absolutePath) ? statSync20(output.absolutePath).size : null, importedFirstAnswer(imported));
54258
+ return exportAnswer(ending, { preset, outputPath: output.relativePath, debug, ...pack ? { pack } : {} }, before, writtenAt(), beside, docCacheNote, existsSync34(output.absolutePath) ? statSync20(output.absolutePath).size : null, importedFirstAnswer(imported));
54219
54259
  }
54220
54260
  reportTestProgress(log) {
54221
54261
  const progress = callProgress();
@@ -54276,7 +54316,7 @@ ${platform}`;
54276
54316
  if (movie !== null) {
54277
54317
  return this.createErrorResponse(movie);
54278
54318
  }
54279
- const missing = paths.value.filter((path) => !existsSync35(join44(project.value.path, path.slice("res://".length))));
54319
+ const missing = paths.value.filter((path) => !existsSync34(join44(project.value.path, path.slice("res://".length))));
54280
54320
  const projectScripts = new ProjectScripts(project.value.path);
54281
54321
  const present = paths.value.filter((path) => !missing.includes(path));
54282
54322
  const asked = projectScripts.searchedAsTold(present);
@@ -54468,7 +54508,7 @@ ${platform}`;
54468
54508
  await untilGone([run.process.pid]);
54469
54509
  }
54470
54510
  await run.settled;
54471
- const helperFailed = onDesktop ? helperFailure(helperFiles.error) ?? (existsSync35(helperFiles.pid) ? null : `it never started, and ${helperStep(helperFiles.step)}`) : null;
54511
+ const helperFailed = onDesktop ? helperFailure(helperFiles.error) ?? (existsSync34(helperFiles.pid) ? null : `it never started, and ${helperStep(helperFiles.step)}`) : null;
54472
54512
  if (helperFailed !== null) {
54473
54513
  discard(join44(project.value.path, ".godot", ...ours.split("/")), userData);
54474
54514
  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}`);
@@ -54484,10 +54524,10 @@ ${platform}`;
54484
54524
  const reportsDir = join44(project.value.path, ".godot", ...ours.split("/"));
54485
54525
  let report = null;
54486
54526
  let reportProblem = null;
54487
- const casePrinted = withNestedErrors(readRun(existsSync35(engineLog) ? readFileSync40(engineLog, "utf8") : ""), run.log.all);
54527
+ const casePrinted = withNestedErrors(readRun(existsSync34(engineLog) ? readFileSync40(engineLog, "utf8") : ""), run.log.all);
54488
54528
  const declaredErrors = readExpected(expectedFile);
54489
54529
  try {
54490
- 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))) : [];
54530
+ 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))) : [];
54491
54531
  const newest = written.at(-1);
54492
54532
  if (newest !== undefined) {
54493
54533
  report = parseJUnit(readFileSync40(join44(reportsDir, newest, "results.xml"), "utf8"));
@@ -54814,7 +54854,7 @@ ${error.text}`;
54814
54854
  if (!location.ok) {
54815
54855
  return this.createErrorResponse(location.reason, PATH_SOLUTIONS);
54816
54856
  }
54817
- if (!existsSync35(location.absolutePath)) {
54857
+ if (!existsSync34(location.absolutePath)) {
54818
54858
  return this.missingScript(project.value.path, location.relativePath);
54819
54859
  }
54820
54860
  ignored = scriptsUnderGdignore(project.value.path, [location.relativePath]);
@@ -54904,7 +54944,7 @@ ${error.text}`;
54904
54944
  const wanted = `res://${relativePath}`;
54905
54945
  const folder = dirname25(relativePath.replaceAll("\\", "/"));
54906
54946
  const inFolder = join44(projectPath, folder);
54907
- const beside = existsSync35(inFolder) ? readdirSync20(inFolder, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => `res://${folder === "." ? "" : `${folder}/`}${entry.name}`) : [];
54947
+ const beside = existsSync34(inFolder) ? readdirSync20(inFolder, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => `res://${folder === "." ? "" : `${folder}/`}${entry.name}`) : [];
54908
54948
  return this.createErrorResponse(withNearestFiles(`Script file does not exist: ${wanted}`, wanted, scripts, beside));
54909
54949
  }
54910
54950
  async compileScripts(projectPath, paths) {
@@ -55032,7 +55072,7 @@ ${error.text}`;
55032
55072
  const cached = cachedClasses(projectPath);
55033
55073
  const sourceOf = (resourcePath) => {
55034
55074
  const contained = resolveWithinProject(projectPath, resourcePath);
55035
- if (!contained.ok || !existsSync35(contained.absolutePath)) {
55075
+ if (!contained.ok || !existsSync34(contained.absolutePath)) {
55036
55076
  return null;
55037
55077
  }
55038
55078
  try {
@@ -55126,7 +55166,7 @@ ${error.text}`;
55126
55166
  }
55127
55167
  sourceOfClass(projectPath, resourcePath) {
55128
55168
  const contained = resolveWithinProject(projectPath, resourcePath);
55129
- if (!contained.ok || !existsSync35(contained.absolutePath)) {
55169
+ if (!contained.ok || !existsSync34(contained.absolutePath)) {
55130
55170
  return null;
55131
55171
  }
55132
55172
  try {
@@ -55428,7 +55468,7 @@ ${error.text}`;
55428
55468
  try {
55429
55469
  const askedAt = Date.now();
55430
55470
  const asked = this.godotBridge.invokeTool("playing_status", {}, { counted: false });
55431
- const answer = await Promise.race([asked, delay7(PLAYING_STATUS_MS).then(() => null)]);
55471
+ const answer = await Promise.race([asked, delay8(PLAYING_STATUS_MS).then(() => null)]);
55432
55472
  if (answer === null) {
55433
55473
  this.logDebug(`playing_status did not answer within ${PLAYING_STATUS_MS}ms`);
55434
55474
  asked.then(() => {
@@ -55453,7 +55493,7 @@ ${error.text}`;
55453
55493
  try {
55454
55494
  const answer = await Promise.race([
55455
55495
  this.godotBridge.invokeTool("scan_status", {}, { counted: false }),
55456
- delay7(PLAYING_STATUS_MS).then(() => null)
55496
+ delay8(PLAYING_STATUS_MS).then(() => null)
55457
55497
  ]);
55458
55498
  if (answer === null) {
55459
55499
  return null;
@@ -55595,7 +55635,7 @@ ${error.text}`;
55595
55635
  if (answer.serversNote === undefined || adapterFailed || Date.now() >= deadline) {
55596
55636
  return answer;
55597
55637
  }
55598
- await delay7(500);
55638
+ await delay8(500);
55599
55639
  }
55600
55640
  }
55601
55641
  async rebindTheDebugAdapter(servers) {
@@ -55856,7 +55896,7 @@ ${error.text}`;
55856
55896
  if (Date.now() >= deadline) {
55857
55897
  return false;
55858
55898
  }
55859
- await delay7(250);
55899
+ await delay8(250);
55860
55900
  }
55861
55901
  }
55862
55902
  async handleLaunchEditor(args) {
@@ -55994,7 +56034,7 @@ ${error.text}`;
55994
56034
  if (!paths.ok) {
55995
56035
  return refused(paths.reason, PATH_SOLUTIONS);
55996
56036
  }
55997
- const missing = paths.value.filter((path) => !existsSync35(join44(projectPath, path.slice("res://".length))));
56037
+ const missing = paths.value.filter((path) => !existsSync34(join44(projectPath, path.slice("res://".length))));
55998
56038
  if (missing.length > 0) {
55999
56039
  return refused(`Nothing at ${missing.join(" and ")} in the project at ${projectPath}.`, PATH_SOLUTIONS);
56000
56040
  }
@@ -56039,7 +56079,7 @@ ${error.text}`;
56039
56079
  return this.createErrorResponse(sceneToRun.reason, PATH_SOLUTIONS);
56040
56080
  }
56041
56081
  const build = readNonEmptyString(args, "executable");
56042
- if (build === undefined && sceneToRun?.ok && !existsSync35(sceneToRun.absolutePath)) {
56082
+ if (build === undefined && sceneToRun?.ok && !existsSync34(sceneToRun.absolutePath)) {
56043
56083
  return this.createErrorResponse(`No scene at res://${sceneToRun.relativePath} in the project at ${project.value.path}.`, PATH_SOLUTIONS);
56044
56084
  }
56045
56085
  const exported = build === undefined ? null : exportedBuild(project.value.path, build);
@@ -56167,7 +56207,7 @@ ${error.text}`;
56167
56207
  }
56168
56208
  async runtimeUp(projectPath, before, budget, withArgs) {
56169
56209
  const budgetMs = budget.ms;
56170
- if (!existsSync35(join44(projectPath, RUNTIME_SCRIPT))) {
56210
+ if (!existsSync34(join44(projectPath, RUNTIME_SCRIPT))) {
56171
56211
  return runtimeVerdict(null, {
56172
56212
  addon: false,
56173
56213
  budgetMs,
@@ -56305,7 +56345,7 @@ ${error.text}`;
56305
56345
  const sendingFrom = Date.now();
56306
56346
  const breakpoints = await this.dapHoldingBreakpointsOf(projectPath).reapplyBreakpoints();
56307
56347
  this.logDebug(`Breakpoints were sent again after ${Date.now() - sendingFrom}ms`);
56308
- const slot = await slotForCall();
56348
+ const slot = await slotForCall(true);
56309
56349
  if (profiled) {
56310
56350
  const armed = await this.handleViaBridge("profile_start", {
56311
56351
  arm: true,
@@ -56508,7 +56548,7 @@ ${error.text}`;
56508
56548
  if (Date.now() >= deadline) {
56509
56549
  return false;
56510
56550
  }
56511
- await delay7(100);
56551
+ await delay8(100);
56512
56552
  }
56513
56553
  }
56514
56554
  async endActiveGame(reason, going, graceful) {
@@ -56768,11 +56808,11 @@ ${error.text}`;
56768
56808
  return Object.assign(started, { settled, stop });
56769
56809
  }
56770
56810
  async launchKeptGame(godotPath, cmdArgs, projectPath, env, desktop, profiled = false, debugged = true) {
56811
+ const slot = await slotForCall(true);
56771
56812
  const startedAt = Date.now();
56772
56813
  const transcript = openTranscript(startedAt);
56773
56814
  closeSync6(transcript.fd);
56774
56815
  const profile = profiled ? profilePath(startedAt) : undefined;
56775
- const slot = await slotForCall();
56776
56816
  const gameEnv = onTheSlot(profiled ? { ...env ?? process.env, [PROFILE_FROM_START]: "1" } : env ?? process.env, slot.lock);
56777
56817
  let launched;
56778
56818
  try {
@@ -57242,7 +57282,7 @@ ${error.text}`;
57242
57282
  };
57243
57283
  const going = await this.runStillGoing(run);
57244
57284
  const projectPath = run.projectPath;
57245
- const projectGone = projectPath !== null && !existsSync35(join44(projectPath, "project.godot"));
57285
+ const projectGone = projectPath !== null && !existsSync34(join44(projectPath, "project.godot"));
57246
57286
  if (projectGone && callersName !== undefined) {
57247
57287
  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"]);
57248
57288
  }
@@ -57400,7 +57440,7 @@ ${error.text}`;
57400
57440
  return true;
57401
57441
  }
57402
57442
  }
57403
- await delay7(100);
57443
+ await delay8(100);
57404
57444
  }
57405
57445
  return false;
57406
57446
  }
@@ -57420,7 +57460,7 @@ ${error.text}`;
57420
57460
  while (cancelled?.aborted !== true && await this.runStillGoing(run) && Date.now() < until) {
57421
57461
  this.drainEditorOutput(run);
57422
57462
  this.drainTranscript(run);
57423
- await delay7(RUN_POLL_MS);
57463
+ await delay8(RUN_POLL_MS);
57424
57464
  }
57425
57465
  return await this.handleGetDebugOutput(args, await this.runStillGoing(run) ? budgetMs : undefined);
57426
57466
  }
@@ -57473,7 +57513,7 @@ ${error.text}`;
57473
57513
  if (Date.now() >= until) {
57474
57514
  return false;
57475
57515
  }
57476
- await delay7(50);
57516
+ await delay8(50);
57477
57517
  }
57478
57518
  }
57479
57519
  async handleEditorConsole(args) {
@@ -57627,7 +57667,7 @@ ${error.text}`;
57627
57667
  notes.push(endedWithoutACode({
57628
57668
  throughEditor: run.throughEditor,
57629
57669
  announced: announced !== undefined || run.announcedPid !== undefined,
57630
- couldAnnounce: run.projectPath !== null && existsSync35(join44(run.projectPath, RUNTIME_SCRIPT)),
57670
+ couldAnnounce: run.projectPath !== null && existsSync34(join44(run.projectPath, RUNTIME_SCRIPT)),
57631
57671
  endedHere: typeof run.endedHere === "string",
57632
57672
  pickedUp: run.pickedUp === true
57633
57673
  }));
@@ -58509,7 +58549,7 @@ ${error.text}`;
58509
58549
  if (!scriptPath.ok) {
58510
58550
  return this.createErrorResponse(scriptPath.reason);
58511
58551
  }
58512
- if (!existsSync35(scriptPath.absolutePath)) {
58552
+ if (!existsSync34(scriptPath.absolutePath)) {
58513
58553
  return this.missingScript(projectPath, scriptPath.relativePath);
58514
58554
  }
58515
58555
  const asked = readNonEmptyString(args, "newScriptPath");
@@ -59153,7 +59193,7 @@ ${error.text}`;
59153
59193
  async ownRunOnItsWay(projectPath, budgetMs) {
59154
59194
  const run = await this.currentRun();
59155
59195
  const project = projectPath ?? run?.projectPath ?? null;
59156
- if (run === null || project === null || run.announcedPid !== undefined || run.projectPath !== null && !isSameDirectory(run.projectPath, project) || !existsSync35(join44(project, RUNTIME_SCRIPT)) || !await this.runStillGoing(run)) {
59196
+ if (run === null || project === null || run.announcedPid !== undefined || run.projectPath !== null && !isSameDirectory(run.projectPath, project) || !existsSync34(join44(project, RUNTIME_SCRIPT)) || !await this.runStillGoing(run)) {
59157
59197
  return null;
59158
59198
  }
59159
59199
  const already = runtimesAnnounced().running;
@@ -59606,7 +59646,7 @@ var init_server = __esm(() => {
59606
59646
  init_bridge_announce();
59607
59647
  init_engine_launch();
59608
59648
  init_engine_slots();
59609
- import { existsSync as existsSync36 } from "node:fs";
59649
+ import { existsSync as existsSync35 } from "node:fs";
59610
59650
  import { dirname as dirname26, join as join45, resolve as resolve15 } from "node:path";
59611
59651
 
59612
59652
  // src/error-mode.ts
@@ -59645,7 +59685,7 @@ init_alive();
59645
59685
  init_engine_launch();
59646
59686
  init_lsp_client();
59647
59687
  init_process_children();
59648
- import { existsSync as existsSync18, readdirSync as readdirSync11, readFileSync as readFileSync19, unlinkSync as unlinkSync2 } from "node:fs";
59688
+ import { existsSync as existsSync17, readdirSync as readdirSync11, readFileSync as readFileSync19, unlinkSync as unlinkSync2 } from "node:fs";
59649
59689
  import { connect as connect2 } from "node:net";
59650
59690
  import { join as join21, resolve as resolve8 } from "node:path";
59651
59691
  var EDITOR_RECORD_PROTOCOL = 1;
@@ -59757,7 +59797,7 @@ function lspOptionsOf(args, cwd) {
59757
59797
  }
59758
59798
  }
59759
59799
  const projectPath = resolve8(cwd, named ?? ".");
59760
- if (!existsSync18(join21(projectPath, "project.godot"))) {
59800
+ if (!existsSync17(join21(projectPath, "project.godot"))) {
59761
59801
  throw new EngineUsageError(`Not a Godot project: ${projectPath} holds no project.godot.`);
59762
59802
  }
59763
59803
  return { projectPath, port, waitSeconds };
@@ -59864,7 +59904,7 @@ init_setup();
59864
59904
  init_setup();
59865
59905
  init_tool_definitions();
59866
59906
  init_tool_reference();
59867
- import { existsSync as existsSync20, mkdirSync as mkdirSync7, readdirSync as readdirSync13, rmSync as rmSync11, writeFileSync as writeFileSync12 } from "node:fs";
59907
+ import { existsSync as existsSync19, mkdirSync as mkdirSync7, readdirSync as readdirSync13, rmSync as rmSync11, writeFileSync as writeFileSync12 } from "node:fs";
59868
59908
  import { basename as basename9, dirname as dirname10, join as join23 } from "node:path";
59869
59909
  var SKILL_NAME = "gdharness";
59870
59910
  var SHARED_SKILLS = join23(".agents", "skills");
@@ -60136,7 +60176,7 @@ function everySkillDirectory(projectPath, harnesses) {
60136
60176
  function removeSkill(directories, projectPath) {
60137
60177
  const removed = [];
60138
60178
  for (const directory of directories) {
60139
- if (existsSync20(directory)) {
60179
+ if (existsSync19(directory)) {
60140
60180
  rmSync11(directory, { recursive: true, force: true });
60141
60181
  pruneEmpty(dirname10(directory), projectPath);
60142
60182
  removed.push(directory);
@@ -60158,7 +60198,7 @@ function pruneEmpty(directory, projectPath) {
60158
60198
  function writeSkill(directories, version) {
60159
60199
  const files = skillFiles(version);
60160
60200
  return directories.map((directory) => {
60161
- const replaced = existsSync20(directory);
60201
+ const replaced = existsSync19(directory);
60162
60202
  rmSync11(directory, { recursive: true, force: true });
60163
60203
  for (const [name, contents] of files) {
60164
60204
  const path = join23(directory, name);
@@ -60175,7 +60215,7 @@ init_engine_slots();
60175
60215
  init_log_read();
60176
60216
  init_setup();
60177
60217
  init_suite_judge();
60178
- import { existsSync as existsSync21, mkdirSync as mkdirSync8, readFileSync as readFileSync22, rmSync as rmSync12 } from "node:fs";
60218
+ import { existsSync as existsSync20, mkdirSync as mkdirSync8, readFileSync as readFileSync22, rmSync as rmSync12 } from "node:fs";
60179
60219
  import { availableParallelism as availableParallelism4 } from "node:os";
60180
60220
  import { join as join24, resolve as resolve10 } from "node:path";
60181
60221
  import process13 from "node:process";
@@ -60217,9 +60257,9 @@ function spreadOptionsOf(args, cwd) {
60217
60257
  }
60218
60258
  const first = positional[0];
60219
60259
  const named = first === undefined ? null : resolve10(cwd, first);
60220
- const projectNamed = named !== null && existsSync21(join24(named, "project.godot"));
60260
+ const projectNamed = named !== null && existsSync20(join24(named, "project.godot"));
60221
60261
  const projectPath = projectNamed ? named : resolve10(cwd);
60222
- if (!existsSync21(join24(projectPath, "project.godot"))) {
60262
+ if (!existsSync20(join24(projectPath, "project.godot"))) {
60223
60263
  throw new EngineUsageError(`Not a Godot project: ${projectPath} holds no project.godot.`);
60224
60264
  }
60225
60265
  const scenes = positional.slice(projectNamed ? 1 : 0);
@@ -60227,7 +60267,7 @@ function spreadOptionsOf(args, cwd) {
60227
60267
  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(", ")}.`);
60228
60268
  }
60229
60269
  const scene = resPathOf(scenes[0] ?? "", projectPath, cwd);
60230
- if (!existsSync21(join24(projectPath, scene.slice("res://".length)))) {
60270
+ if (!existsSync20(join24(projectPath, scene.slice("res://".length)))) {
60231
60271
  throw new EngineUsageError(`Nothing at ${scene} in the project at ${projectPath}.`);
60232
60272
  }
60233
60273
  const benchArguments = dashes === -1 ? [] : args.slice(dashes + 1);
@@ -60298,7 +60338,7 @@ function shareFaults(played) {
60298
60338
  return faults;
60299
60339
  }
60300
60340
  async function runSpreadCommand(options, godotPath) {
60301
- if (!existsSync21(join24(options.projectPath, SHARE_SCRIPT))) {
60341
+ if (!existsSync20(join24(options.projectPath, SHARE_SCRIPT))) {
60302
60342
  throw new EngineUsageError(`res://${SHARE_SCRIPT} is not in the project, so its bench cannot ask GdhShare for outcomes. Run gdharness setup.`);
60303
60343
  }
60304
60344
  const startedAt = Date.now();
@@ -60363,7 +60403,7 @@ async function runSpreadCommand(options, godotPath) {
60363
60403
  const faults = left.flatMap((worker) => engineFaults(worker, options.godotVersion));
60364
60404
  const arms = left.map((_, index) => {
60365
60405
  const file = join24(shareDirectory, `worker-${String(index)}.arms`);
60366
- return existsSync21(file) ? armsPlayed(readFileSync22(file, "utf8")) : [];
60406
+ return existsSync20(file) ? armsPlayed(readFileSync22(file, "utf8")) : [];
60367
60407
  });
60368
60408
  faults.push(...shareFaults(arms));
60369
60409
  if (faults.length > 0) {
@@ -60373,7 +60413,7 @@ async function runSpreadCommand(options, godotPath) {
60373
60413
  console.log(readLog(gather.log).replace(CONTROL_SEQUENCE, "").trimEnd());
60374
60414
  const gatherFaults = engineFaults(gather, options.godotVersion);
60375
60415
  const gatheredFile = join24(shareDirectory, "gathered.arms");
60376
- const gathered = new Set((existsSync21(gatheredFile) ? armsPlayed(readFileSync22(gatheredFile, "utf8")) ?? [] : []).map((arm) => arm.arm));
60416
+ const gathered = new Set((existsSync20(gatheredFile) ? armsPlayed(readFileSync22(gatheredFile, "utf8")) ?? [] : []).map((arm) => arm.arm));
60377
60417
  const ungathered = (arms[0] ?? []).filter((arm) => !gathered.has(arm.arm)).map((arm) => arm.arm);
60378
60418
  if (ungathered.length > 0) {
60379
60419
  gatherFaults.push(`the gathering run never asked for ${ungathered.join(", ")}, which the workers played: it went another way through the arms than they did`);
@@ -60424,7 +60464,7 @@ function engineFaults(engine, godotVersion) {
60424
60464
  const said = code === null ? "without an exit code" : code >>> 0 >= WINDOWS_EXCEPTION2 ? exitNamed(code) : String(code);
60425
60465
  faults.push(`${engine.name}: the engine exited ${said}`);
60426
60466
  }
60427
- if (!existsSync21(engine.log)) {
60467
+ if (!existsSync20(engine.log)) {
60428
60468
  return faults;
60429
60469
  }
60430
60470
  const printed = readRun(readLog(engine.log));
@@ -60440,7 +60480,7 @@ function engineFaults(engine, godotVersion) {
60440
60480
  }
60441
60481
  function progressOf(logs) {
60442
60482
  const each = logs.map((log, index) => {
60443
- const text = existsSync21(log) ? readLog(log) : "";
60483
+ const text = existsSync20(log) ? readLog(log) : "";
60444
60484
  const last = [...text.matchAll(PROGRESS)].at(-1);
60445
60485
  return last === undefined ? `worker ${String(index)} has played no arm yet` : `worker ${String(index)} at ${last[1] ?? ""} ${last[2] ?? ""} of ${last[3] ?? ""}`;
60446
60486
  });
@@ -60472,7 +60512,7 @@ init_reimport();
60472
60512
  init_setup();
60473
60513
  import {
60474
60514
  copyFileSync,
60475
- existsSync as existsSync24,
60515
+ existsSync as existsSync23,
60476
60516
  mkdirSync as mkdirSync10,
60477
60517
  readdirSync as readdirSync15,
60478
60518
  readFileSync as readFileSync26,
@@ -60483,12 +60523,13 @@ import {
60483
60523
  import { availableParallelism as availableParallelism5 } from "node:os";
60484
60524
  import { dirname as dirname13, join as join28, relative as relative5, resolve as resolve11, sep as sep4 } from "node:path";
60485
60525
  import process14 from "node:process";
60526
+ import { setTimeout as delay5 } from "node:timers/promises";
60486
60527
 
60487
60528
  // src/suite-inputs.ts
60488
60529
  init_class_cache();
60489
60530
  init_gdscript_source();
60490
60531
  import { createHash as createHash6 } from "node:crypto";
60491
- import { existsSync as existsSync22, readdirSync as readdirSync14, readFileSync as readFileSync23, statSync as statSync13 } from "node:fs";
60532
+ import { existsSync as existsSync21, readdirSync as readdirSync14, readFileSync as readFileSync23, statSync as statSync13 } from "node:fs";
60492
60533
  import { join as join25, posix as posix2 } from "node:path";
60493
60534
  var EVERY_FILE = "res://";
60494
60535
  var CACHE_HELD = "cache:";
@@ -60506,7 +60547,7 @@ var ADDON = /^res:\/\/addons\/[^/]+\//;
60506
60547
  var TEXT_RESOURCE = /\.(?:tscn|tres|gdextension)$/;
60507
60548
  function reachedBySuite(file) {
60508
60549
  const bySuite = new Map;
60509
- if (!existsSync22(file)) {
60550
+ if (!existsSync21(file)) {
60510
60551
  return bySuite;
60511
60552
  }
60512
60553
  const paths = (value) => Array.isArray(value) ? value.filter((path) => typeof path === "string") : [];
@@ -60616,7 +60657,7 @@ ${this.read(path).digest}
60616
60657
  const hash = createHash6("sha256");
60617
60658
  let modified = 0;
60618
60659
  const directory = join25(this.scripts.projectPath, root.slice("res://".length));
60619
- if (existsSync22(directory)) {
60660
+ if (existsSync21(directory)) {
60620
60661
  walkSeen(directory, (file, under, stat) => {
60621
60662
  hash.update(`${under}
60622
60663
  `).update(readFileSync23(file));
@@ -60627,7 +60668,7 @@ ${this.read(path).digest}
60627
60668
  }
60628
60669
  readAnew(path) {
60629
60670
  const file = join25(this.scripts.projectPath, path.slice("res://".length));
60630
- if (!existsSync22(file)) {
60671
+ if (!existsSync21(file)) {
60631
60672
  return { digest: "missing", follows: [], also: [], modified: 0 };
60632
60673
  }
60633
60674
  const stat = statSync13(file);
@@ -60638,12 +60679,12 @@ ${this.read(path).digest}
60638
60679
  }
60639
60680
  const bytes = readFileSync23(file);
60640
60681
  const digest = createHash6("sha256").update(bytes).digest("hex");
60641
- const also = [`${path}.import`, `${path}.uid`].filter((beside) => existsSync22(join25(this.scripts.projectPath, beside.slice("res://".length))));
60682
+ const also = [`${path}.import`, `${path}.uid`].filter((beside) => existsSync21(join25(this.scripts.projectPath, beside.slice("res://".length))));
60642
60683
  const follows = [];
60643
60684
  if (TEXT_RESOURCE.test(path)) {
60644
60685
  for (const [named] of bytes.toString("latin1").matchAll(RES_LITERAL)) {
60645
60686
  const target = join25(this.scripts.projectPath, named.slice("res://".length));
60646
- (existsSync22(target) && statSync13(target).isDirectory() ? also : follows).push(named);
60687
+ (existsSync21(target) && statSync13(target).isDirectory() ? also : follows).push(named);
60647
60688
  }
60648
60689
  } else if (path.endsWith(".gd")) {
60649
60690
  const reaches = this.scriptReaches(path);
@@ -60830,7 +60871,7 @@ function joinedString(expression, named) {
60830
60871
  }
60831
60872
  function walkSeen(root, seen) {
60832
60873
  const walk = (directory, under) => {
60833
- if (existsSync22(join25(directory, ".gdignore"))) {
60874
+ if (existsSync21(join25(directory, ".gdignore"))) {
60834
60875
  return;
60835
60876
  }
60836
60877
  for (const entry of readdirSync14(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
@@ -60848,7 +60889,7 @@ function walkSeen(root, seen) {
60848
60889
  }
60849
60890
  function extensionsOf(projectPath) {
60850
60891
  const list = join25(projectPath, ".godot", "extension_list.cfg");
60851
- return existsSync22(list) ? readFileSync23(list, "utf8").split(`
60892
+ return existsSync21(list) ? readFileSync23(list, "utf8").split(`
60852
60893
  `).map((line) => line.trim()).filter((line) => line.startsWith("res://")) : [];
60853
60894
  }
60854
60895
 
@@ -60879,6 +60920,7 @@ function getLocalVersion() {
60879
60920
 
60880
60921
  // src/suite-run.ts
60881
60922
  var LAST_RUN_FILE = "last-run.json";
60923
+ var COMPILED_FILE = "compiled-together.json";
60882
60924
  var SLOWEST_NAMED = 5;
60883
60925
  var SILENCE_TIMES_TAKEN = 4;
60884
60926
  function silenceWhile(running, times, floorSeconds) {
@@ -60936,9 +60978,9 @@ function testOptionsOf(args, cwd) {
60936
60978
  }
60937
60979
  const first = positional[0];
60938
60980
  const named = first === undefined ? null : resolve11(cwd, first);
60939
- const projectNamed = named !== null && existsSync24(join28(named, "project.godot"));
60981
+ const projectNamed = named !== null && existsSync23(join28(named, "project.godot"));
60940
60982
  const projectPath = projectNamed ? named : resolve11(cwd);
60941
- if (!existsSync24(join28(projectPath, "project.godot"))) {
60983
+ if (!existsSync23(join28(projectPath, "project.godot"))) {
60942
60984
  throw new EngineUsageError(`Not a Godot project: ${projectPath} holds no project.godot.`);
60943
60985
  }
60944
60986
  const last = (flag) => valued.get(flag)?.at(-1);
@@ -60973,12 +61015,12 @@ function seedOf(value) {
60973
61015
  return seed;
60974
61016
  }
60975
61017
  function rootsOf(options) {
60976
- return options.roots.length > 0 ? options.roots : TEST_DIRECTORIES.filter((root) => existsSync24(join28(options.projectPath, root))).map((root) => `res://${root}`);
61018
+ return options.roots.length > 0 ? options.roots : TEST_DIRECTORIES.filter((root) => existsSync23(join28(options.projectPath, root))).map((root) => `res://${root}`);
60977
61019
  }
60978
61020
  function searchedRoots(options) {
60979
61021
  return options.selected.length === 0 ? rootsOf(options) : options.selected.filter((entry) => {
60980
61022
  const directory = join28(options.projectPath, entry.slice("res://".length));
60981
- return existsSync24(directory) && statSync14(directory).isDirectory();
61023
+ return existsSync23(directory) && statSync14(directory).isDirectory();
60982
61024
  });
60983
61025
  }
60984
61026
  function selectedSuites(scripts, options) {
@@ -60995,9 +61037,9 @@ function selectedSuites(scripts, options) {
60995
61037
  const caseAt = /^(res:\/\/.*\.gd):(\w+)$/.exec(entry);
60996
61038
  const path = caseAt?.[1] ?? entry;
60997
61039
  const directory = join28(options.projectPath, path.slice(6));
60998
- const suites = existsSync24(directory) && statSync14(directory).isDirectory() ? scripts.suitesUnder([path.replace(/\/$/, "")]) : [scripts.suite(path)].filter((suite) => suite !== null);
61040
+ const suites = existsSync23(directory) && statSync14(directory).isDirectory() ? scripts.suitesUnder([path.replace(/\/$/, "")]) : [scripts.suite(path)].filter((suite) => suite !== null);
60999
61041
  if (suites.length === 0) {
61000
- 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}.`);
61042
+ 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}.`);
61001
61043
  }
61002
61044
  for (const suite of suites) {
61003
61045
  const picked = chosen.get(suite.path) ?? { suite, cases: new Set };
@@ -61121,11 +61163,11 @@ async function runTestCommand(options, godotPath) {
61121
61163
  failsOnPushErrors: gdUnitFailsOnPushErrors(options.projectPath)
61122
61164
  };
61123
61165
  try {
61124
- const neverImported = cachedClasses(options.projectPath) === null;
61125
- if (neverImported && !options.importFirst) {
61126
- console.log("The project has never been imported, so it is imported first.");
61166
+ const needed = options.importFirst ? null : importNeeded(options.projectPath);
61167
+ if (needed !== null) {
61168
+ console.log(needed);
61127
61169
  }
61128
- if (options.importFirst || neverImported) {
61170
+ if (options.importFirst || needed !== null) {
61129
61171
  const imported = await importProject(launch);
61130
61172
  if (imported !== null) {
61131
61173
  logs.keep();
@@ -61140,9 +61182,10 @@ async function runTestCommand(options, godotPath) {
61140
61182
  readFileSync26(shippedListedRunner(), "utf8"),
61141
61183
  engineSaid(godotPath),
61142
61184
  ...options.reachAlso.map((path) => `${path}
61143
- ${existsSync24(path) ? readFileSync26(path, "latin1") : "missing"}`)
61185
+ ${existsSync23(path) ? readFileSync26(path, "latin1") : "missing"}`)
61144
61186
  ];
61145
61187
  const everySuite = suites;
61188
+ const compileKept = options.changedOnly ? { file: join28(state, COMPILED_FILE), scripts, always } : null;
61146
61189
  if (options.changedOnly) {
61147
61190
  const inputs = new SuiteInputs(scripts, always);
61148
61191
  const passedBefore = readPassed(passedFile);
@@ -61156,7 +61199,7 @@ ${existsSync24(path) ? readFileSync26(path, "latin1") : "missing"}`)
61156
61199
  }
61157
61200
  if (suites.length === 0) {
61158
61201
  console.log("Nothing has changed since every suite last passed.");
61159
- const compiled = await compileCheck(launch, everySuite);
61202
+ const compiled = await compileUnlessUnchanged(launch, everySuite, compileKept);
61160
61203
  const problems = [...compiled.faults.map((fault) => `${COMPILE_CHECK}: ${fault}`), ...uncollected];
61161
61204
  if (problems.length === 0) {
61162
61205
  rmSync13(runDirectory, { recursive: true, force: true });
@@ -61179,12 +61222,18 @@ ${existsSync24(path) ? readFileSync26(path, "latin1") : "missing"}`)
61179
61222
  if (memory.unread !== undefined) {
61180
61223
  console.log(`Windows did not say how much memory it can still commit (${memory.unread}), so engines are sized by the physical memory free.`);
61181
61224
  }
61182
- const room = options.cores === null ? roomFor(options.engines, availableParallelism5(), memory.bytes, memory.said) : roomFor(options.engines, options.cores, memory.bytes, memory.said, `--cores holds it to ${plural(options.cores, "processor")}`);
61225
+ const roomWith = (bytes) => options.cores === null ? roomFor(options.engines, availableParallelism5(), bytes, memory.said) : roomFor(options.engines, options.cores, bytes, memory.said, `--cores holds it to ${plural(options.cores, "processor")}`);
61226
+ const byMemory = roomWith(memory.bytes);
61227
+ const unheld = roomWith(Number.POSITIVE_INFINITY);
61228
+ const unheldUnits = unitsOf(suites, times, splitPastFor(suites, times, unheld.engines));
61229
+ const heldLanes = lanesOf(dealt(unheldUnits, declared, unheld.engines));
61230
+ const memoryHeld = options.order === null && byMemory.engines < heldLanes;
61231
+ const room = memoryHeld ? unheld : byMemory;
61183
61232
  if (options.cores !== null && process14.platform === "darwin") {
61184
61233
  console.log("macOS offers no way to hold a process to some processors, so --cores holds only the number of engines here.");
61185
61234
  }
61186
61235
  const splitPast = splitPastFor(suites, times, room.engines);
61187
- const units = unitsOf(suites, times, splitPast);
61236
+ const units = memoryHeld ? unheldUnits : unitsOf(suites, times, splitPast);
61188
61237
  const past = splitPast > SPLIT_PAST_SECONDS ? `an engine's share of this run (${String(Math.round(splitPast))} s)` : `${String(SPLIT_PAST_SECONDS)} s`;
61189
61238
  const plans = options.order === null ? dealt(units, declared, room.engines) : [inOneEngine(ordered(units, options.order), declared)];
61190
61239
  const functions = suites.reduce((sum, suite) => sum + suite.cases.length, 0);
@@ -61217,24 +61266,28 @@ ${existsSync24(path) ? readFileSync26(path, "latin1") : "missing"}`)
61217
61266
  say(`Kept whole in one engine, since ${one ? "it declares" : "each declares"} GDHARNESS_TOGETHER: ${named(keptWhole)}.`);
61218
61267
  }
61219
61268
  const lanes = [...new Set(plans.map((plan) => plan.lane))].map((lane) => plans.flatMap((plan, index) => plan.lane === lane ? [{ plan, index }] : []));
61269
+ const startable = memoryHeld ? Math.min(byMemory.engines, lanes.length) : lanes.length;
61220
61270
  const taken = [];
61221
- while (taken.length < lanes.length) {
61271
+ while (taken.length < startable) {
61222
61272
  const lock = await slots.takeFree();
61223
61273
  if (lock === null) {
61224
61274
  break;
61225
61275
  }
61226
61276
  taken.push(lock);
61227
61277
  }
61228
- const shared = options.order === null && lanes.length > 1 && taken.length < lanes.length;
61229
- if (shared) {
61230
- say(sharesSaid(taken.length, lanes.length));
61278
+ if (memoryHeld) {
61279
+ say(memorySaid(byMemory.engines, lanes.length, byMemory.held ?? ""));
61280
+ }
61281
+ const shared = options.order === null && lanes.length > 1 && (memoryHeld || taken.length < lanes.length);
61282
+ if (shared && taken.length < startable) {
61283
+ say(sharesSaid(taken.length, startable));
61231
61284
  }
61232
61285
  const handed = new HandedSlot;
61233
- const compiling = compileCheck(launch, everySuite, handed);
61286
+ const compiling = compileUnlessUnchanged(launch, everySuite, compileKept, handed);
61234
61287
  compiling.catch(() => {
61235
61288
  return;
61236
61289
  });
61237
- let ran = shared ? await runShares(launch, units, declared, lanes.length, taken, times, handed) : (await Promise.all(lanes.map((lane, at) => runLane(launch, lane, times, taken[at] ?? null, handed)))).flat().sort((a, b) => a.index - b.index);
61290
+ let ran = shared ? await runShares(launch, units, declared, lanes.length, taken, times, handed, memoryHeld ? new MemoryGate(slots, async () => (await memoryAvailable()).bytes) : undefined) : (await Promise.all(lanes.map((lane, at) => runLane(launch, lane, times, taken[at] ?? null, handed)))).flat().sort((a, b) => a.index - b.index);
61238
61291
  if (ran.some((engine) => engine.verdict.starved) && ran.some((engine) => !engine.verdict.passed)) {
61239
61292
  say("An engine ran out of memory, so every engine that failed runs again, one at a time.");
61240
61293
  const again = [];
@@ -61261,6 +61314,55 @@ ${existsSync24(path) ? readFileSync26(path, "latin1") : "missing"}`)
61261
61314
  function sharesSaid(free, lanes) {
61262
61315
  return `${free === 0 ? "None" : String(free)} of the ${String(lanes)} slots this run uses ${free === 1 ? "was" : "were"} free as it began, so its engines are handed the suites a share at a time as each starts, and an engine starts as each slot comes free.`;
61263
61316
  }
61317
+ function memorySaid(room, lanes, held) {
61318
+ return `Memory had room for ${room === 1 ? "one" : String(room)} of these ${String(lanes)} engines at once as the run began, since ${held}, so its engines are handed the suites a share at a time, and another starts whenever memory has room for it.`;
61319
+ }
61320
+ var MEMORY_LOOK_MS = 2000;
61321
+ var ENGINE_SETTLING_MS = 30000;
61322
+
61323
+ class MemoryGate {
61324
+ slots;
61325
+ read;
61326
+ now;
61327
+ lookMs;
61328
+ going = new Set;
61329
+ turn = Promise.resolve();
61330
+ constructor(slots, read, now = Date.now, lookMs = MEMORY_LOOK_MS) {
61331
+ this.slots = slots;
61332
+ this.read = read;
61333
+ this.now = now;
61334
+ this.lookMs = lookMs;
61335
+ }
61336
+ admit(signal) {
61337
+ const admitted = this.turn.then(() => this.room(signal));
61338
+ this.turn = admitted.catch(() => {
61339
+ return;
61340
+ });
61341
+ return admitted;
61342
+ }
61343
+ async room(signal) {
61344
+ let unmark;
61345
+ try {
61346
+ for (;; ) {
61347
+ signal.throwIfAborted();
61348
+ const at = this.now();
61349
+ const starting = [...this.going].filter((one) => at - one.at < ENGINE_SETTLING_MS).length;
61350
+ if (this.going.size === 0 || roomForAnother(await this.read(), starting)) {
61351
+ break;
61352
+ }
61353
+ unmark ??= this.slots.markWaiting();
61354
+ await delay5(this.lookMs, undefined, { signal });
61355
+ }
61356
+ } finally {
61357
+ unmark?.();
61358
+ }
61359
+ const engine = { at: this.now() };
61360
+ this.going.add(engine);
61361
+ return () => {
61362
+ this.going.delete(engine);
61363
+ };
61364
+ }
61365
+ }
61264
61366
  function roomSaid(engines, lanes, unheld, held, asked) {
61265
61367
  if (held === undefined || lanes >= unheld) {
61266
61368
  return "";
@@ -61286,7 +61388,7 @@ function readPassed(file) {
61286
61388
  function recordPassed(file, projectPath, ran, failedAcross, inputs, began) {
61287
61389
  const passed = readPassed(file);
61288
61390
  for (const path of Object.keys(passed)) {
61289
- if (!existsSync24(join28(projectPath, path.slice("res://".length)))) {
61391
+ if (!existsSync23(join28(projectPath, path.slice("res://".length)))) {
61290
61392
  delete passed[path];
61291
61393
  }
61292
61394
  }
@@ -61335,6 +61437,9 @@ class HandedSlot {
61335
61437
  lock = new Promise((resolve) => {
61336
61438
  this.handOver = resolve;
61337
61439
  });
61440
+ decline() {
61441
+ this.wanted = false;
61442
+ }
61338
61443
  give(lock) {
61339
61444
  if (!this.wanted) {
61340
61445
  return false;
@@ -61388,6 +61493,41 @@ async function compileCheck(launch, suites, handed) {
61388
61493
  }
61389
61494
  return { faults: judgeCompile(readRun(readFileSync26(log, "utf8")), end), log };
61390
61495
  }
61496
+ function compiledPrint(kept, projectPath, suites) {
61497
+ const inputs = new SuiteInputs(kept.scripts, kept.always);
61498
+ const classes = [...cachedClasses(projectPath)?.values() ?? []];
61499
+ const read = inputs.inputsOf([...suites.map((suite) => suite.path), ...classes]);
61500
+ return { inputs, read, print: inputs.printOf(read) };
61501
+ }
61502
+ async function compileUnlessUnchanged(launch, suites, kept, handed) {
61503
+ if (kept === null) {
61504
+ return compileCheck(launch, suites, handed);
61505
+ }
61506
+ const before = compiledPrint(kept, launch.projectPath, suites).print;
61507
+ if (readKeptPrint(kept.file) === before) {
61508
+ handed?.decline();
61509
+ console.log("Every script compiled together on these same files when last checked, so it is not compiled again.");
61510
+ return { faults: [], log: "" };
61511
+ }
61512
+ const began = Date.now();
61513
+ const compiled = await compileCheck(launch, suites, handed);
61514
+ const after = compiledPrint(kept, launch.projectPath, suites);
61515
+ if (compiled.faults.length === 0 && !after.inputs.modifiedAfter(after.read, began)) {
61516
+ writeJson(kept.file, { print: after.print });
61517
+ } else {
61518
+ rmSync13(kept.file, { force: true });
61519
+ }
61520
+ return compiled;
61521
+ }
61522
+ function readKeptPrint(file) {
61523
+ try {
61524
+ const parsed = JSON.parse(readFileSync26(file, "utf8"));
61525
+ const print = parsed?.print;
61526
+ return typeof print === "string" ? print : null;
61527
+ } catch {
61528
+ return null;
61529
+ }
61530
+ }
61391
61531
  function printCompiled(compiled, logs) {
61392
61532
  if (compiled.faults.length === 0) {
61393
61533
  return;
@@ -61412,6 +61552,21 @@ function importFault(printed) {
61412
61552
  ].join(" and ");
61413
61553
  return `it printed ${counted}, the first ${first.warning ? "warning" : "error"} ${JSON.stringify(first.text)}`;
61414
61554
  }
61555
+ function importNeeded(projectPath) {
61556
+ const cached = cachedClasses(projectPath);
61557
+ if (cached === null) {
61558
+ return "The project has never been imported, so it is imported first.";
61559
+ }
61560
+ const unlisted = unlistedExtensions(projectPath);
61561
+ if (unlisted.length > 0) {
61562
+ return `No import has listed the project's extensions, ${named(unlisted)}, so the engine would load none of them, and the project is imported first.`;
61563
+ }
61564
+ const uncached = staleAgainst(cached, projectPath).sort();
61565
+ if (uncached.length > 0) {
61566
+ return `The class cache does not list ${named(uncached)} where the scripts declare ${uncached.length === 1 ? "it" : "them"}, so the project is imported first.`;
61567
+ }
61568
+ return null;
61569
+ }
61415
61570
  async function importProject(launch) {
61416
61571
  const seeded = seedExtensionList(launch.projectPath);
61417
61572
  if (seeded !== null && seeded.length > 0) {
@@ -61459,35 +61614,48 @@ async function runLane(launch, lane, times, taken, handed) {
61459
61614
  doneWith(launch, lock, handed);
61460
61615
  }
61461
61616
  }
61462
- async function runShares(launch, units, declared, lanes, taken, times, handed) {
61617
+ async function runShares(launch, units, declared, lanes, taken, times, handed, memory) {
61463
61618
  const shares = new Shares(units, declared, lanes);
61464
61619
  const handedOut = new AbortController;
61465
61620
  let engines = 0;
61621
+ const empty = () => shares.empty;
61466
61622
  const lane = async (at) => {
61467
61623
  let lock = taken[at] ?? null;
61468
- if (lock === null) {
61469
- try {
61470
- lock = await launch.slots.take(handedOut.signal);
61471
- } catch (error) {
61472
- if (handedOut.signal.aborted) {
61473
- return [];
61474
- }
61475
- throw error;
61476
- }
61477
- }
61624
+ const ran = [];
61478
61625
  try {
61479
- const ran = [];
61480
- for (let plan = shares.next(at);plan !== null; plan = shares.next(at)) {
61481
- if (shares.empty) {
61626
+ while (!empty()) {
61627
+ let ended;
61628
+ try {
61629
+ ended = await memory?.admit(handedOut.signal);
61630
+ lock ??= await launch.slots.take(handedOut.signal);
61631
+ } catch (error) {
61632
+ ended?.();
61633
+ if (handedOut.signal.aborted) {
61634
+ break;
61635
+ }
61636
+ throw error;
61637
+ }
61638
+ const plan = shares.next(at);
61639
+ if (plan === null) {
61640
+ ended?.();
61641
+ break;
61642
+ }
61643
+ if (empty()) {
61482
61644
  handedOut.abort();
61483
61645
  }
61484
61646
  const index = engines;
61485
61647
  engines += 1;
61486
- ran.push(await runEngine2(launch, plan, index, times, "", lock));
61648
+ try {
61649
+ ran.push(await runEngine2(launch, plan, index, times, "", lock));
61650
+ } finally {
61651
+ ended?.();
61652
+ }
61487
61653
  }
61488
61654
  return ran;
61489
61655
  } finally {
61490
- doneWith(launch, lock, handed);
61656
+ if (lock !== null) {
61657
+ doneWith(launch, lock, handed);
61658
+ }
61491
61659
  }
61492
61660
  };
61493
61661
  return (await Promise.all(Array.from({ length: lanes }, (_, at) => lane(at)))).flat().sort((a, b) => a.index - b.index);
@@ -61582,7 +61750,7 @@ async function runEngine2(launch, plan, index, times, again = "", slot = null) {
61582
61750
  }
61583
61751
  var REPORT_FILES_NAMED = 3;
61584
61752
  function reportsFault(reports) {
61585
- const files = existsSync24(reports) ? readdirSync15(reports, { recursive: true, encoding: "utf8" }).filter((file) => statSync14(join28(reports, file)).isFile()).sort() : [];
61753
+ const files = existsSync23(reports) ? readdirSync15(reports, { recursive: true, encoding: "utf8" }).filter((file) => statSync14(join28(reports, file)).isFile()).sort() : [];
61586
61754
  if (files.length === 0) {
61587
61755
  return null;
61588
61756
  }
@@ -61595,7 +61763,7 @@ function report(ran, compiled, across, uncollected, startedAt, logs, printOutput
61595
61763
  for (const engine of ran) {
61596
61764
  console.log("");
61597
61765
  console.log(`--- what engine ${String(engine.index)} printed, running ${named(engine.plan.suites.map((suite) => suite.path))}:`);
61598
- console.log(existsSync24(engine.log) ? readLog(engine.log).replace(CONTROL_SEQUENCE, "").trimEnd() : "(no log was written)");
61766
+ console.log(existsSync23(engine.log) ? readLog(engine.log).replace(CONTROL_SEQUENCE, "").trimEnd() : "(no log was written)");
61599
61767
  }
61600
61768
  }
61601
61769
  const failed = ran.filter((engine) => !engine.verdict.passed);
@@ -61606,7 +61774,7 @@ function report(ran, compiled, across, uncollected, startedAt, logs, printOutput
61606
61774
  for (const fault of engine.verdict.faults) {
61607
61775
  console.log(` ${fault}`);
61608
61776
  }
61609
- if (existsSync24(engine.log)) {
61777
+ if (existsSync23(engine.log)) {
61610
61778
  const verdict = [
61611
61779
  `gdharness: ${heading.slice(4)}`,
61612
61780
  ...engine.verdict.faults.map((fault) => ` ${fault}`)
@@ -61701,6 +61869,9 @@ function report(ran, compiled, across, uncollected, startedAt, logs, printOutput
61701
61869
  const problems = failed.reduce((sum, engine) => sum + engine.verdict.faults.length, compiled.faults.length + across.length + uncollected.length);
61702
61870
  console.log(`Failed: ${plural(problems, "problem")}, listed above. Ran ${totals}`);
61703
61871
  console.log(`Every engine's output is kept under ${logs.shown} until ${String(KEPT_RUN_DIRECTORIES)} later runs have failed.`);
61872
+ if (logs.shown !== logs.directory) {
61873
+ console.log(`That is a copy beside the main checkout. The run wrote them under ${logs.directory} in this worktree, and they go with it when the worktree is removed.`);
61874
+ }
61704
61875
  return 1;
61705
61876
  }
61706
61877
  function writeEarlyResult(targets, startedAt, problems, logs) {
@@ -61742,7 +61913,7 @@ class UsageError extends Refusal {
61742
61913
  function projectArgument(at) {
61743
61914
  const named = args.slice(at).find((value) => !value.startsWith("--"));
61744
61915
  const projectPath = resolve15(named ?? ".");
61745
- if (!existsSync36(join45(projectPath, "project.godot"))) {
61916
+ if (!existsSync35(join45(projectPath, "project.godot"))) {
61746
61917
  throw new UsageError(`Not a Godot project: ${projectPath} holds no project.godot.`);
61747
61918
  }
61748
61919
  return projectPath;
@@ -61806,7 +61977,7 @@ async function registerRuntime(godot, projectPath) {
61806
61977
  }
61807
61978
  const path = (named ?? "").replace(/^res:\/\//, "");
61808
61979
  console.log(`${RUNTIME_AUTOLOAD.name} autoload left at ${named}, which this project registers itself`);
61809
- if (!existsSync36(join45(projectPath, path))) {
61980
+ if (!existsSync35(join45(projectPath, path))) {
61810
61981
  console.log(" that file is not in this project, so it boots with a missing script");
61811
61982
  }
61812
61983
  console.log(` ${useTheShippedLoader(RUNTIME_AUTOLOAD.name, path)}`);
@@ -61939,7 +62110,7 @@ async function setup() {
61939
62110
  console.log("no harness configured; name one yourself, and gdharness harnesses lists them all");
61940
62111
  }
61941
62112
  if (!args.includes("--no-skill")) {
61942
- const directories = skillDirectories(chosen.harnesses, projectPath, existsSync36);
62113
+ const directories = skillDirectories(chosen.harnesses, projectPath, existsSync35);
61943
62114
  for (const written of writeSkill(directories, getLocalVersion())) {
61944
62115
  console.log(`skill: ${written.replaced ? "replaced" : "written"} ${written.path}`);
61945
62116
  }
@@ -62059,7 +62230,7 @@ async function upgrade() {
62059
62230
  moved.push(took.from);
62060
62231
  }
62061
62232
  }
62062
- for (const written of writeSkill(skillDirectories(already, projectPath, existsSync36), version)) {
62233
+ for (const written of writeSkill(skillDirectories(already, projectPath, existsSync35), version)) {
62063
62234
  console.log(`skill: ${written.replaced ? "replaced" : "written"} ${written.path}`);
62064
62235
  }
62065
62236
  console.log(`