gdharness 1.3.54 → 1.3.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/build/cli.js +392 -183
  2. package/build/keeper.js +802 -775
  3. package/package.json +1 -1
package/build/cli.js CHANGED
@@ -800,6 +800,30 @@ public static class GdhProcessTable
800
800
  return "";
801
801
  }
802
802
 
803
+ /// <summary>"pid seconds" on a line for each running one of the comma-separated pids, from one snapshot.</summary>
804
+ public static string ProcessorSecondsOf(string pids)
805
+ {
806
+ HashSet<int> wanted = new HashSet<int>();
807
+ foreach (string one in pids.Split(','))
808
+ {
809
+ int pid;
810
+ if (int.TryParse(one, NumberStyles.Integer, CultureInfo.InvariantCulture, out pid))
811
+ {
812
+ wanted.Add(pid);
813
+ }
814
+ }
815
+ StringBuilder said = new StringBuilder();
816
+ foreach (Entry entry in Snapshot())
817
+ {
818
+ if (wanted.Contains(entry.Pid))
819
+ {
820
+ said.Append(Number(entry.Pid)).Append(' ')
821
+ .Append((entry.Processor / 1e7).ToString("R", CultureInfo.InvariantCulture)).Append('\n');
822
+ }
823
+ }
824
+ return said.ToString();
825
+ }
826
+
803
827
  /// <summary>How many more bytes Windows will commit.</summary>
804
828
  public static string CommitLeft()
805
829
  {
@@ -2245,6 +2269,184 @@ var init_engine_slots = __esm(() => {
2245
2269
  init_whole_file();
2246
2270
  });
2247
2271
 
2272
+ // src/process-time.ts
2273
+ async function cpuSecondsOf(pid) {
2274
+ try {
2275
+ return process.platform === "win32" ? await secondsOnWindows(pid) : await askPosix2(pid);
2276
+ } catch {
2277
+ return;
2278
+ }
2279
+ }
2280
+ async function secondsOnWindows(pid) {
2281
+ const said = (await askProcessTable(`ProcessorSeconds(${pid})`, ASK_TIMEOUT_MS2)).trim();
2282
+ const seconds = Number(said);
2283
+ return said !== "" && Number.isFinite(seconds) ? seconds : undefined;
2284
+ }
2285
+ async function askPosix2(pid) {
2286
+ const { stdout } = await runHidden("ps", ["-o", "time=", "-p", String(pid)], { timeout: ASK_TIMEOUT_MS2 });
2287
+ return secondsFromClock(stdout.trim());
2288
+ }
2289
+ function secondsFromClock(printed) {
2290
+ if (printed === "") {
2291
+ return;
2292
+ }
2293
+ const dashed = printed.includes("-");
2294
+ const days = dashed ? printed.slice(0, printed.indexOf("-")) : null;
2295
+ const clock = dashed ? printed.slice(printed.indexOf("-") + 1) : printed;
2296
+ const parts = clock.split(":").map((part) => Number(part));
2297
+ if (parts.length === 0 || parts.some((part) => !Number.isFinite(part))) {
2298
+ return;
2299
+ }
2300
+ const seconds = parts.reduce((total, part) => total * 60 + part, 0);
2301
+ const extra = days === null ? 0 : Number(days) * 86400;
2302
+ return Number.isFinite(extra) ? seconds + extra : undefined;
2303
+ }
2304
+ var ASK_TIMEOUT_MS2 = 6000;
2305
+ var init_process_time = __esm(() => {
2306
+ init_process_table();
2307
+ init_spawn();
2308
+ });
2309
+
2310
+ // src/engine-spent.ts
2311
+ import { readFileSync as readFileSync7 } from "node:fs";
2312
+ import { availableParallelism as availableParallelism2, cpus } from "node:os";
2313
+ import { performance as performance2 } from "node:perf_hooks";
2314
+ function crowded(stretch, work, busy, cores) {
2315
+ return stretch > 0 && Math.max(0, busy - work) / (stretch * cores) >= BUSY;
2316
+ }
2317
+
2318
+ class Spent {
2319
+ byClock = 0;
2320
+ byWork = 0;
2321
+ since;
2322
+ cores;
2323
+ last;
2324
+ constructor(since, first, pid, cores = availableParallelism2()) {
2325
+ this.since = since;
2326
+ this.cores = cores;
2327
+ this.last = {
2328
+ at: since,
2329
+ machine: first?.machine ?? Number.NaN,
2330
+ processor: pid === undefined ? undefined : first?.processors?.get(pid)
2331
+ };
2332
+ }
2333
+ counted(sample, pid) {
2334
+ if (sample.at <= this.last.at) {
2335
+ return;
2336
+ }
2337
+ const stretch = sample.at - this.last.at;
2338
+ const processor = pid === undefined ? undefined : sample.processors?.get(pid);
2339
+ const work = processor === undefined || this.last.processor === undefined ? undefined : Math.max(0, processor - this.last.processor);
2340
+ if (work !== undefined && crowded(stretch, work, sample.machine - this.last.machine, this.cores)) {
2341
+ this.byWork += Math.min(work, stretch);
2342
+ } else {
2343
+ this.byClock += stretch;
2344
+ }
2345
+ this.last = { at: sample.at, machine: sample.machine, processor };
2346
+ }
2347
+ restart(at) {
2348
+ this.since = at;
2349
+ this.byClock = 0;
2350
+ this.byWork = 0;
2351
+ this.last = { ...this.last, at: Math.max(this.last.at, at) };
2352
+ }
2353
+ clock(now) {
2354
+ return now - this.since;
2355
+ }
2356
+ past(limit, now) {
2357
+ if (this.clock(now) > limit * STARVED) {
2358
+ return "clock";
2359
+ }
2360
+ return this.byClock + this.byWork > limit ? "own" : null;
2361
+ }
2362
+ }
2363
+ function nowSeconds() {
2364
+ return performance2.now() / 1000;
2365
+ }
2366
+ function machineSeconds() {
2367
+ return cpus().reduce((sum, core) => sum + core.times.user + core.times.nice + core.times.sys + core.times.irq, 0) / 1000;
2368
+ }
2369
+ function watching(pid, on) {
2370
+ if (on) {
2371
+ watched.add(pid);
2372
+ } else {
2373
+ watched.delete(pid);
2374
+ }
2375
+ }
2376
+ function sampled() {
2377
+ const now = Date.now();
2378
+ if (latest === null || now - latest.taken >= SAMPLE_MS) {
2379
+ latest = { taken: now, sample: take() };
2380
+ }
2381
+ return latest.sample;
2382
+ }
2383
+ async function take() {
2384
+ const at = nowSeconds();
2385
+ const machine = machineSeconds();
2386
+ const previous = quietAt;
2387
+ quietAt = { at, machine, processors: null };
2388
+ const share = previous === null || at <= previous.at ? 1 : (machine - previous.machine) / ((at - previous.at) * availableParallelism2());
2389
+ if (share < BUSY || watched.size === 0) {
2390
+ return quietAt;
2391
+ }
2392
+ return { at, machine, processors: await processorSecondsOf([...watched]) };
2393
+ }
2394
+ async function processorSecondsOf(pids) {
2395
+ const found = new Map;
2396
+ try {
2397
+ if (process.platform === "win32") {
2398
+ const said = await askProcessTable(`ProcessorSecondsOf('${pids.join(",")}')`, ASK_TIMEOUT_MS3);
2399
+ for (const line of said.split(/\r?\n/)) {
2400
+ const [pid, seconds] = line.trim().split(" ").map(Number);
2401
+ if (pid !== undefined && seconds !== undefined && Number.isFinite(pid) && Number.isFinite(seconds)) {
2402
+ found.set(pid, seconds);
2403
+ }
2404
+ }
2405
+ } else if (process.platform === "linux") {
2406
+ const ticks = await ticksASecond();
2407
+ for (const pid of pids) {
2408
+ try {
2409
+ const fields = (readFileSync7(`/proc/${String(pid)}/stat`, "utf8").split(")").pop() ?? "").trim().split(/\s+/);
2410
+ const used = Number(fields[11]) + Number(fields[12]);
2411
+ if (Number.isFinite(used)) {
2412
+ found.set(pid, used / ticks);
2413
+ }
2414
+ } catch {}
2415
+ }
2416
+ } else {
2417
+ const asked = (some) => runHidden("ps", ["-o", "pid=,time=", "-p", some.join(",")], { timeout: ASK_TIMEOUT_MS3 }).then((done) => done.stdout, (error) => {
2418
+ const printed = error.stdout;
2419
+ return typeof printed === "string" ? printed : "";
2420
+ });
2421
+ let stdout = await asked(pids);
2422
+ if (stdout.trim() === "" && pids.length > 1) {
2423
+ stdout = (await Promise.all(pids.map((pid) => asked([pid])))).join(`
2424
+ `);
2425
+ }
2426
+ for (const line of stdout.split(`
2427
+ `)) {
2428
+ const [pid, time] = line.trim().split(/\s+/);
2429
+ const seconds = time === undefined ? undefined : secondsFromClock(time);
2430
+ if (pid !== undefined && seconds !== undefined) {
2431
+ found.set(Number(pid), seconds);
2432
+ }
2433
+ }
2434
+ }
2435
+ } catch {}
2436
+ return found;
2437
+ }
2438
+ function ticksASecond() {
2439
+ ticks ??= runHidden("getconf", ["CLK_TCK"], { timeout: ASK_TIMEOUT_MS3 }).then(({ stdout }) => Number(stdout.trim()) || 100).catch(() => 100);
2440
+ return ticks;
2441
+ }
2442
+ var STARVED = 8, BUSY = 0.25, SAMPLE_MS = 1000, ASK_TIMEOUT_MS3 = 3000, watched, latest = null, quietAt = null, ticks = null;
2443
+ var init_engine_spent = __esm(() => {
2444
+ init_process_table();
2445
+ init_process_time();
2446
+ init_spawn();
2447
+ watched = new Set;
2448
+ });
2449
+
2248
2450
  // node_modules/yaml/dist/nodes/identity.js
2249
2451
  var require_identity = __commonJS(function(exports) {
2250
2452
  var ALIAS = Symbol.for("yaml.alias");
@@ -9381,7 +9583,7 @@ function alongside(execPath, name) {
9381
9583
  var init_runner = () => {};
9382
9584
 
9383
9585
  // src/harnesses.ts
9384
- import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync7, rmSync as rmSync5, statSync as statSync4, writeFileSync as writeFileSync5 } from "node:fs";
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";
9385
9587
  import { homedir as homedir3 } from "node:os";
9386
9588
  import { basename as basename4, dirname as dirname4, isAbsolute as isAbsolute2, join as join7, relative as relative2, resolve as resolve4 } from "node:path";
9387
9589
  import process6 from "node:process";
@@ -9518,7 +9720,7 @@ function registered(harness, projectPath) {
9518
9720
  if (harness.snippet !== undefined || !existsSync4(path)) {
9519
9721
  return false;
9520
9722
  }
9521
- const text = readFileSync7(path, "utf8");
9723
+ const text = readFileSync8(path, "utf8");
9522
9724
  if (harness.toml !== undefined) {
9523
9725
  return text.includes(harness.toml.identity ?? harness.toml.header);
9524
9726
  }
@@ -9563,7 +9765,7 @@ function mainCheckoutOf(projectPath) {
9563
9765
  if (!statSync4(marker).isFile()) {
9564
9766
  return null;
9565
9767
  }
9566
- const pointer = /^gitdir:\s*(.+)$/m.exec(readFileSync7(marker, "utf8"))?.[1]?.trim();
9768
+ const pointer = /^gitdir:\s*(.+)$/m.exec(readFileSync8(marker, "utf8"))?.[1]?.trim();
9567
9769
  if (pointer === undefined) {
9568
9770
  return null;
9569
9771
  }
@@ -9572,7 +9774,7 @@ function mainCheckoutOf(projectPath) {
9572
9774
  if (!existsSync4(commonFile)) {
9573
9775
  return null;
9574
9776
  }
9575
- const common = resolve4(entry, readFileSync7(commonFile, "utf8").trim());
9777
+ const common = resolve4(entry, readFileSync8(commonFile, "utf8").trim());
9576
9778
  if (basename4(common) !== ".git") {
9577
9779
  return null;
9578
9780
  }
@@ -9598,7 +9800,7 @@ function worktreeCheckoutsOf(projectPath) {
9598
9800
  if (!existsSync4(pointer)) {
9599
9801
  return [];
9600
9802
  }
9601
- const checkout = dirname4(resolve4(listed, name, readFileSync7(pointer, "utf8").trim()));
9803
+ const checkout = dirname4(resolve4(listed, name, readFileSync8(pointer, "utf8").trim()));
9602
9804
  const project = join7(checkout, below);
9603
9805
  return existsSync4(join7(project, "project.godot")) ? [project] : [];
9604
9806
  });
@@ -9613,7 +9815,7 @@ function entryEnvironment(harness, projectPath) {
9613
9815
  }
9614
9816
  let parsed;
9615
9817
  try {
9616
- parsed = JSON.parse(readFileSync7(path, "utf8"));
9818
+ parsed = JSON.parse(readFileSync8(path, "utf8"));
9617
9819
  } catch {
9618
9820
  return;
9619
9821
  }
@@ -9635,7 +9837,7 @@ function disconnect(harness, projectPath) {
9635
9837
  if (harness.snippet !== undefined) {
9636
9838
  return { harness, path, action: "manual" };
9637
9839
  }
9638
- const text = readFileSync7(path, "utf8");
9840
+ const text = readFileSync8(path, "utf8");
9639
9841
  if (harness.toml !== undefined) {
9640
9842
  return taken(harness, path, text, removeToml(text, harness.toml));
9641
9843
  }
@@ -9644,7 +9846,7 @@ function disconnect(harness, projectPath) {
9644
9846
  }
9645
9847
  let existing;
9646
9848
  try {
9647
- existing = JSON.parse(readFileSync7(path, "utf8"));
9849
+ existing = JSON.parse(readFileSync8(path, "utf8"));
9648
9850
  } catch {
9649
9851
  return { harness, path, action: "absent" };
9650
9852
  }
@@ -9716,7 +9918,7 @@ function connect(harness, projectPath, launch) {
9716
9918
  if (harness.snippet !== undefined) {
9717
9919
  return { harness, path, action: "snippet", snippet: harness.snippet(launch) };
9718
9920
  }
9719
- const held = existsSync4(path) ? readFileSync7(path, "utf8") : "";
9921
+ const held = existsSync4(path) ? readFileSync8(path, "utf8") : "";
9720
9922
  if (harness.toml !== undefined) {
9721
9923
  const already = held.includes(harness.toml.identity ?? harness.toml.header);
9722
9924
  return put(harness, path, writeToml(held, harness.toml, launch), already);
@@ -10882,7 +11084,7 @@ var init_gdscript_source = __esm(() => {
10882
11084
  });
10883
11085
 
10884
11086
  // src/class-cache.ts
10885
- import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync8, statSync as statSync5 } from "node:fs";
11087
+ import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync5 } from "node:fs";
10886
11088
  import { join as join8, posix } from "node:path";
10887
11089
  function isToolScript(source) {
10888
11090
  return TOOL.test(codeOf(source));
@@ -10957,7 +11159,7 @@ function eachScript(projectPath, each) {
10957
11159
  if (entry.isDirectory()) {
10958
11160
  visit(path, `${prefix}${entry.name}/`);
10959
11161
  } else if (entry.isFile() && entry.name.endsWith(".gd")) {
10960
- each(`res://${prefix}${entry.name}`, readFileSync8(path, "utf8"));
11162
+ each(`res://${prefix}${entry.name}`, readFileSync9(path, "utf8"));
10961
11163
  }
10962
11164
  }
10963
11165
  };
@@ -12095,7 +12297,7 @@ var init_junit = __esm(() => {
12095
12297
  });
12096
12298
 
12097
12299
  // src/suite-judge.ts
12098
- import { readFileSync as readFileSync9 } from "node:fs";
12300
+ import { readFileSync as readFileSync10 } from "node:fs";
12099
12301
  import { stripVTControlCharacters } from "node:util";
12100
12302
  function secondsOf(time) {
12101
12303
  let ms = 0;
@@ -12272,7 +12474,7 @@ function readRun(printed) {
12272
12474
  settleAfterCase("after");
12273
12475
  const joined = lines.join(`
12274
12476
  `);
12275
- const starved = STARVED.flatMap((pattern) => [...joined.matchAll(pattern)].map((found) => found[0]));
12477
+ const starved = STARVED2.flatMap((pattern) => [...joined.matchAll(pattern)].map((found) => found[0]));
12276
12478
  const unloadable = scriptErrorsPrinted(lines).map((error) => `${error.path}${error.line === null ? "" : `:${String(error.line)}`}: ${error.message}`);
12277
12479
  return {
12278
12480
  lines,
@@ -12306,7 +12508,7 @@ function versionFault(said, wanted) {
12306
12508
  function readExpected(file) {
12307
12509
  const declared = (value) => typeof value === "object" && value !== null ? value : {};
12308
12510
  try {
12309
- const parsed = JSON.parse(readFileSync9(file, "utf8"));
12511
+ const parsed = JSON.parse(readFileSync10(file, "utf8"));
12310
12512
  const read = typeof parsed === "object" && parsed !== null ? parsed : {};
12311
12513
  return { errors: declared(read["errors"]), warnings: declared(read["warnings"]) };
12312
12514
  } catch {
@@ -12652,7 +12854,7 @@ ${String(error.warning)}`);
12652
12854
  const neverPrinted = [...owed.values()].flatMap((debt) => debt.texts.map((text) => ({ suite: debt.suite, during: debt.during, text, warning: debt.warning })));
12653
12855
  return { printed: unexpected, neverPrinted };
12654
12856
  }
12655
- var SUITE_OPENED, TIME, CASE_LINE, STATISTICS, ERROR_LINE, WARNING_LINE, EXECUTED, MISMATCHED_ROW, UNRUNNABLE_CASE, BANNER, LEFT_OUT, DRIVER_FALLBACK, MACHINE_WARNED, ORPHANS_REPORTED, STARVED, NESTED_ERROR = "While attempting to print an error, another error was printed:", WINDOWS_EXITS, MEMORY_EXITS, GDUNIT_FAILED = 100, GDUNIT_ORPHANS = 101, GDUNIT_EXITS, GODOT_EXITS, CRASH_HEADER, CRASH_BUILD, QUEUE_OVERFLOW_LINE = "Object was deleted while awaiting a callback.", QUEUE_OVERFLOW_FRAMES, TAIL = 60, MOST_NAMED = 8, COMPILED_SAID = "gdharness compiled every script together";
12857
+ var SUITE_OPENED, TIME, CASE_LINE, STATISTICS, ERROR_LINE, WARNING_LINE, EXECUTED, MISMATCHED_ROW, UNRUNNABLE_CASE, BANNER, LEFT_OUT, DRIVER_FALLBACK, MACHINE_WARNED, ORPHANS_REPORTED, STARVED2, NESTED_ERROR = "While attempting to print an error, another error was printed:", WINDOWS_EXITS, MEMORY_EXITS, GDUNIT_FAILED = 100, GDUNIT_ORPHANS = 101, GDUNIT_EXITS, GODOT_EXITS, CRASH_HEADER, CRASH_BUILD, QUEUE_OVERFLOW_LINE = "Object was deleted while awaiting a callback.", QUEUE_OVERFLOW_FRAMES, TAIL = 60, MOST_NAMED = 8, COMPILED_SAID = "gdharness compiled every script together";
12656
12858
  var init_suite_judge = __esm(() => {
12657
12859
  init_engine_leaks();
12658
12860
  init_junit();
@@ -12670,7 +12872,7 @@ var init_suite_judge = __esm(() => {
12670
12872
  DRIVER_FALLBACK = /^\s*WARNING: Your video card drivers .*, switching to /;
12671
12873
  MACHINE_WARNED = /^\s*at: .*\((?:\.\/)?(?:platform|drivers)\//;
12672
12874
  ORPHANS_REPORTED = /^\s*WARNING: Detected \d+ (?:possible )?orphan nodes\.\s*$/;
12673
- STARVED = [
12875
+ STARVED2 = [
12674
12876
  /Parameter "mem(?:_new)?" is null\.?\s*\n\s*at: \w+ \((?:\.\/)?core\/(?:os\/memory\.cpp|templates\/cowdata\.h):/g,
12675
12877
  /ERROR: Failed decoding WebP image\.\s*\n\s*at: _webp_unpack/g
12676
12878
  ];
@@ -12706,16 +12908,24 @@ import {
12706
12908
  fstatSync as fstatSync2,
12707
12909
  openSync as openSync4,
12708
12910
  readdirSync as readdirSync4,
12911
+ readFileSync as readFileSync11,
12709
12912
  readSync as readSync2,
12710
12913
  rmSync as rmSync7,
12711
12914
  statSync as statSync6,
12712
12915
  writeFileSync as writeFileSync6,
12713
12916
  writeSync as writeSync4
12714
12917
  } from "node:fs";
12715
- import { availableParallelism as availableParallelism2, freemem, totalmem } from "node:os";
12918
+ import { availableParallelism as availableParallelism3, freemem, totalmem } from "node:os";
12716
12919
  import { isAbsolute as isAbsolute3, join as join9, relative as relative3, resolve as resolve5, sep as sep2 } from "node:path";
12717
12920
  import process7 from "node:process";
12718
12921
  import { setTimeout as delay3 } from "node:timers/promises";
12922
+ function countedBy(spent, past, at) {
12923
+ const clock = Math.round(spent.clock(at));
12924
+ if (past === "clock") {
12925
+ return `, ${String(STARVED)} times over on the clock (${String(clock)} s), the machine kept busy by other work`;
12926
+ }
12927
+ return spent.byWork === 0 ? "" : ` of its own, counted by its processor time while other work kept the machine busy (${String(clock)} s on the clock)`;
12928
+ }
12719
12929
  function plural(count, noun) {
12720
12930
  return `${String(count)} ${noun}${count === 1 ? "" : "s"}`;
12721
12931
  }
@@ -12741,7 +12951,7 @@ function godotNamed(value, cwd) {
12741
12951
  }
12742
12952
  function coresNamed(value) {
12743
12953
  const cores = wholeFlag(value, "--cores");
12744
- const most = Math.min(availableParallelism2(), 64);
12954
+ const most = Math.min(availableParallelism3(), 64);
12745
12955
  if (cores !== null && cores > most) {
12746
12956
  throw new EngineUsageError(`--cores ${String(cores)} is more than the ${String(most)} processors a run can be held to here.`);
12747
12957
  }
@@ -12932,19 +13142,49 @@ async function watchedEngine(launch, lock, args, directory, log, silenceSeconds,
12932
13142
  exited.then(() => {
12933
13143
  finished.now = true;
12934
13144
  });
13145
+ const hasFinished = () => finished.now;
12935
13146
  const reading = openSync4(log, "r");
13147
+ const engineAt = () => {
13148
+ if (helper === null) {
13149
+ return child.pid;
13150
+ }
13151
+ try {
13152
+ const pid = Number(readFileSync11(helper.pid, "utf8").trim());
13153
+ return Number.isInteger(pid) && pid > 0 ? pid : undefined;
13154
+ } catch {
13155
+ return;
13156
+ }
13157
+ };
13158
+ let pid = engineAt();
13159
+ if (pid !== undefined) {
13160
+ watching(pid, true);
13161
+ }
12936
13162
  try {
12937
13163
  let size = 0;
12938
- const started = Date.now();
12939
- let lastGrowth = started;
13164
+ const sample = launch.sample ?? sampled;
13165
+ const first = await sample();
13166
+ const running = new Spent(nowSeconds(), first, pid);
13167
+ const quiet = new Spent(nowSeconds(), first, pid);
12940
13168
  let carried = "";
12941
13169
  let allowed = { size: -1, seconds: silenceSeconds };
12942
13170
  while (!finished.now) {
12943
13171
  await delay3(LOOK_MS);
13172
+ if (pid === undefined) {
13173
+ pid = engineAt();
13174
+ if (pid !== undefined) {
13175
+ watching(pid, true);
13176
+ }
13177
+ }
13178
+ const taken = await sample();
13179
+ running.counted(taken, pid);
13180
+ quiet.counted(taken, pid);
13181
+ const at = nowSeconds();
13182
+ const gone = hasFinished() || pid !== undefined && !alive(pid);
12944
13183
  const deadline = launch.deadlineSeconds;
12945
- if (ended === null && deadline !== null && Date.now() - started > deadline * 1000) {
13184
+ const over = deadline === null || gone ? null : running.past(deadline, at);
13185
+ if (ended === null && deadline !== null && over !== null) {
12946
13186
  const stoppedIn = readRun(readLog(log)).stoppedIn;
12947
- ended = `the engine ran past the ${String(deadline)} s deadline${stoppedIn === null ? "" : ` while running ${stoppedIn}`}, so it was ended`;
13187
+ ended = `the engine ran past the ${String(deadline)} s deadline${countedBy(running, over, at)}${stoppedIn === null ? "" : ` while running ${stoppedIn}`}, so it was ended`;
12948
13188
  stop();
12949
13189
  }
12950
13190
  const now = fstatSync2(reading).size;
@@ -12964,24 +13204,25 @@ async function watchedEngine(launch, lock, args, directory, log, silenceSeconds,
12964
13204
  at += got;
12965
13205
  }
12966
13206
  size = now;
12967
- lastGrowth = Date.now();
13207
+ quiet.restart(at);
12968
13208
  if (ended === null && size > LOG_LIMIT_BYTES) {
12969
13209
  ended = `the engine printed more than the ${String(LOG_LIMIT_BYTES / 1024 / 1024)} MiB a log may hold, so it was ended`;
12970
13210
  stop();
12971
13211
  }
12972
- } else if (ended === null && Date.now() - lastGrowth > silenceSeconds * 1000) {
13212
+ } else if (ended === null && !gone && quiet.past(silenceSeconds, at) !== null) {
12973
13213
  if (allowed.size !== size) {
12974
13214
  allowed = {
12975
13215
  size,
12976
13216
  seconds: silenceIn === undefined ? silenceSeconds : Math.max(silenceSeconds, silenceIn(readRun(readLog(log))))
12977
13217
  };
12978
13218
  }
12979
- if (Date.now() - lastGrowth <= allowed.seconds * 1000) {
13219
+ const silent = quiet.past(allowed.seconds, at);
13220
+ if (silent === null) {
12980
13221
  continue;
12981
13222
  }
12982
13223
  const { stoppedIn } = readRun(readLog(log));
12983
13224
  const unstarted = helper !== null && !existsSync6(helper.pid) ? `, and it never started ${helper.how}: ${helperStep(helper.step)}` : "";
12984
- ended = `the engine printed nothing for ${String(allowed.seconds)} s${stoppedIn === null ? "" : ` while running ${stoppedIn}`}, so it was ended${unstarted}`;
13225
+ ended = `the engine printed nothing for ${String(allowed.seconds)} s${countedBy(quiet, silent, at)}${stoppedIn === null ? "" : ` while running ${stoppedIn}`}, so it was ended${unstarted}`;
12985
13226
  stop();
12986
13227
  }
12987
13228
  }
@@ -12991,6 +13232,9 @@ async function watchedEngine(launch, lock, args, directory, log, silenceSeconds,
12991
13232
  } finally {
12992
13233
  closeSync4(reading);
12993
13234
  launch.running.delete(stop);
13235
+ if (pid !== undefined) {
13236
+ watching(pid, false);
13237
+ }
12994
13238
  }
12995
13239
  const { code, signal } = await exited;
12996
13240
  const freeBytes = code !== null && code >>> 0 >= WINDOWS_EXCEPTION ? freemem() : undefined;
@@ -13047,6 +13291,7 @@ var init_engine_launch = __esm(() => {
13047
13291
  init_alive();
13048
13292
  init_desktop();
13049
13293
  init_engine_slots();
13294
+ init_engine_spent();
13050
13295
  init_errors();
13051
13296
  init_harnesses();
13052
13297
  init_log_read();
@@ -13857,7 +14102,7 @@ var init_doc_cache = __esm(() => {
13857
14102
  });
13858
14103
 
13859
14104
  // src/project-scan.ts
13860
- import { existsSync as existsSync10, readdirSync as readdirSync7, readFileSync as readFileSync10, statSync as statSync9 } from "node:fs";
14105
+ import { existsSync as existsSync10, readdirSync as readdirSync7, readFileSync as readFileSync12, statSync as statSync9 } from "node:fs";
13861
14106
  import { basename as basename6, extname as extname2, join as join12, relative as relative4, sep as sep3 } from "node:path";
13862
14107
  function skipped(name) {
13863
14108
  return name.startsWith(".") || SKIPPED.has(name);
@@ -13993,7 +14238,7 @@ function scriptsWithoutUid(projectPath) {
13993
14238
  function pathsInUidCache(projectPath) {
13994
14239
  let data;
13995
14240
  try {
13996
- data = readFileSync10(join12(projectPath, ".godot", "uid_cache.bin"));
14241
+ data = readFileSync12(join12(projectPath, ".godot", "uid_cache.bin"));
13997
14242
  } catch {
13998
14243
  return null;
13999
14244
  }
@@ -14055,7 +14300,7 @@ function projectTexts(projectPath) {
14055
14300
  if (!entry.isFile() || BINARY_EXTENSIONS.has(extension)) {
14056
14301
  continue;
14057
14302
  }
14058
- const bytes = readFileSync10(absolute);
14303
+ const bytes = readFileSync12(absolute);
14059
14304
  if (!isBinary(bytes)) {
14060
14305
  found.push({ path: `res://${spelled}`, absolute, text: bytes.toString("utf8") });
14061
14306
  }
@@ -14085,7 +14330,7 @@ function ignoredTexts(projectPath) {
14085
14330
  if (!under || !entry.isFile() || BINARY_EXTENSIONS.has(extension) || entry.name === ".gdignore") {
14086
14331
  continue;
14087
14332
  }
14088
- const bytes = readFileSync10(absolute);
14333
+ const bytes = readFileSync12(absolute);
14089
14334
  if (!isBinary(bytes)) {
14090
14335
  found.push({ path: `res://${spelled}`, absolute, text: bytes.toString("utf8") });
14091
14336
  }
@@ -14133,7 +14378,7 @@ function searchProject(projectPath, options) {
14133
14378
  if (extensions !== null && !extensions.has(extension)) {
14134
14379
  return;
14135
14380
  }
14136
- const bytes = readFileSync10(entryPath);
14381
+ const bytes = readFileSync12(entryPath);
14137
14382
  if (extensions === null && isBinary(bytes)) {
14138
14383
  return;
14139
14384
  }
@@ -14249,7 +14494,7 @@ var init_project_scan = __esm(() => {
14249
14494
 
14250
14495
  // src/import-freshness.ts
14251
14496
  import { createHash as createHash2 } from "node:crypto";
14252
- import { existsSync as existsSync11, readdirSync as readdirSync8, readFileSync as readFileSync11, statSync as statSync10 } from "node:fs";
14497
+ import { existsSync as existsSync11, readdirSync as readdirSync8, readFileSync as readFileSync13, statSync as statSync10 } from "node:fs";
14253
14498
  import { join as join13 } from "node:path";
14254
14499
  function md5Of(file) {
14255
14500
  let stats;
@@ -14264,7 +14509,7 @@ function md5Of(file) {
14264
14509
  }
14265
14510
  let md5;
14266
14511
  try {
14267
- md5 = createHash2("md5").update(readFileSync11(file)).digest("hex");
14512
+ md5 = createHash2("md5").update(readFileSync13(file)).digest("hex");
14268
14513
  } catch {
14269
14514
  return null;
14270
14515
  }
@@ -14298,7 +14543,7 @@ function importedIntoTheProject(projectPath, resPaths) {
14298
14543
  for (const resPath of resPaths) {
14299
14544
  let sidecar;
14300
14545
  try {
14301
- sidecar = readFileSync11(`${onDisk(projectPath, resPath)}.import`, "utf8");
14546
+ sidecar = readFileSync13(`${onDisk(projectPath, resPath)}.import`, "utf8");
14302
14547
  } catch {
14303
14548
  continue;
14304
14549
  }
@@ -14331,7 +14576,7 @@ function importedSidecarMd5s(projectPath) {
14331
14576
  }
14332
14577
  let text;
14333
14578
  try {
14334
- text = readFileSync11(join13(editor, `filesystem_cache${newest}`), "utf8");
14579
+ text = readFileSync13(join13(editor, `filesystem_cache${newest}`), "utf8");
14335
14580
  } catch {
14336
14581
  return found;
14337
14582
  }
@@ -14386,7 +14631,7 @@ function behind(projectPath, resPath, sidecarFile, sidecar, importedFrom) {
14386
14631
  const record = join13(projectPath, ".godot", "imported", `${name}-${createHash2("md5").update(resPath, "utf8").digest("hex")}.md5`);
14387
14632
  let recorded = "";
14388
14633
  try {
14389
- recorded = /^source_md5="([0-9a-f]*)"/m.exec(readFileSync11(record, "utf8"))?.[1] ?? "";
14634
+ recorded = /^source_md5="([0-9a-f]*)"/m.exec(readFileSync13(record, "utf8"))?.[1] ?? "";
14390
14635
  } catch {
14391
14636
  recorded = "";
14392
14637
  }
@@ -14430,7 +14675,7 @@ function staleImports(projectPath) {
14430
14675
  const sidecarFile = join13(directory, entry.name);
14431
14676
  let sidecar;
14432
14677
  try {
14433
- sidecar = readFileSync11(sidecarFile, "utf8");
14678
+ sidecar = readFileSync13(sidecarFile, "utf8");
14434
14679
  } catch {
14435
14680
  continue;
14436
14681
  }
@@ -14494,7 +14739,7 @@ import {
14494
14739
  existsSync as existsSync12,
14495
14740
  mkdirSync as mkdirSync4,
14496
14741
  readdirSync as readdirSync9,
14497
- readFileSync as readFileSync12,
14742
+ readFileSync as readFileSync14,
14498
14743
  renameSync as renameSync3,
14499
14744
  unlinkSync,
14500
14745
  writeFileSync as writeFileSync7
@@ -14610,7 +14855,7 @@ function resolveResource(projectPath, relativeTo, path) {
14610
14855
  }
14611
14856
  function readOrNull(path) {
14612
14857
  try {
14613
- return readFileSync12(path, "utf8");
14858
+ return readFileSync14(path, "utf8");
14614
14859
  } catch {
14615
14860
  return null;
14616
14861
  }
@@ -14619,7 +14864,7 @@ var init_library_copies = () => {};
14619
14864
 
14620
14865
  // src/reimport.ts
14621
14866
  import { createHash as createHash3 } from "node:crypto";
14622
- import { existsSync as existsSync13, readFileSync as readFileSync13, rmSync as rmSync8, statSync as statSync11, utimesSync, writeFileSync as writeFileSync8 } from "node:fs";
14867
+ import { existsSync as existsSync13, readFileSync as readFileSync15, rmSync as rmSync8, statSync as statSync11, utimesSync, writeFileSync as writeFileSync8 } from "node:fs";
14623
14868
  import { basename as basename8, join as join15 } from "node:path";
14624
14869
  function forceNextImport(projectPath, resourcePath) {
14625
14870
  const relative = resourcePath.replace(/^res:\/\//, "");
@@ -14628,7 +14873,7 @@ function forceNextImport(projectPath, resourcePath) {
14628
14873
  return;
14629
14874
  }
14630
14875
  const { atime, mtimeMs } = statSync11(sidecar);
14631
- writeFileSync8(sidecar, readFileSync13(sidecar, "utf8").replace(/^valid=false\r?\n/m, ""));
14876
+ writeFileSync8(sidecar, readFileSync15(sidecar, "utf8").replace(/^valid=false\r?\n/m, ""));
14632
14877
  utimesSync(sidecar, atime, new Date(mtimeMs + 2000));
14633
14878
  rmSync8(importRecord(projectPath, resourcePath), { force: true });
14634
14879
  }
@@ -14854,7 +15099,7 @@ var init_script_origins = __esm(() => {
14854
15099
  });
14855
15100
 
14856
15101
  // src/headless.ts
14857
- import { existsSync as existsSync15, readFileSync as readFileSync14, writeFileSync as writeFileSync9 } from "node:fs";
15102
+ import { existsSync as existsSync15, readFileSync as readFileSync16, writeFileSync as writeFileSync9 } from "node:fs";
14858
15103
  import { dirname as dirname7, join as join18 } from "node:path";
14859
15104
  function snakeCased(params) {
14860
15105
  const result = emptyRecord();
@@ -15146,7 +15391,7 @@ function answerIn(file) {
15146
15391
  if (!existsSync15(file)) {
15147
15392
  return { kind: "none" };
15148
15393
  }
15149
- const text = readFileSync14(file, "utf8");
15394
+ const text = readFileSync16(file, "utf8");
15150
15395
  try {
15151
15396
  const parsed = JSON.parse(text);
15152
15397
  return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? { kind: "answer", payload: parsed } : { kind: "unreadable", why: `it is JSON but not an object: ${text.slice(0, 200)}` };
@@ -15172,7 +15417,7 @@ var init_headless = __esm(() => {
15172
15417
  });
15173
15418
 
15174
15419
  // src/update-check.ts
15175
- import { existsSync as existsSync16, mkdirSync as mkdirSync5, readFileSync as readFileSync15, writeFileSync as writeFileSync10 } from "node:fs";
15420
+ import { existsSync as existsSync16, mkdirSync as mkdirSync5, readFileSync as readFileSync17, writeFileSync as writeFileSync10 } from "node:fs";
15176
15421
  import { homedir as homedir6, tmpdir as tmpdir6 } from "node:os";
15177
15422
  import { join as join19 } from "node:path";
15178
15423
  function packageUrl(root) {
@@ -15217,7 +15462,7 @@ function readCache(path) {
15217
15462
  if (!existsSync16(path)) {
15218
15463
  return null;
15219
15464
  }
15220
- const parsed = JSON.parse(readFileSync15(path, "utf8"));
15465
+ const parsed = JSON.parse(readFileSync17(path, "utf8"));
15221
15466
  if (typeof parsed !== "object" || parsed === null) {
15222
15467
  return null;
15223
15468
  }
@@ -15365,7 +15610,7 @@ var init_update_check = __esm(() => {
15365
15610
  });
15366
15611
 
15367
15612
  // src/server-version.ts
15368
- import { readFileSync as readFileSync16 } from "node:fs";
15613
+ import { readFileSync as readFileSync18 } from "node:fs";
15369
15614
  function staleAddon(addonDigest, shippedDigest) {
15370
15615
  return addonDigest !== shippedDigest;
15371
15616
  }
@@ -15424,7 +15669,7 @@ var init_server_version = __esm(() => {
15424
15669
  DEBUG_MODE = process.env["GDHARNESS_DEBUG"] === "1";
15425
15670
  SERVER_VERSION = (() => {
15426
15671
  try {
15427
- const pkg = JSON.parse(readFileSync16(new URL("../package.json", import.meta.url), "utf8"));
15672
+ const pkg = JSON.parse(readFileSync18(new URL("../package.json", import.meta.url), "utf8"));
15428
15673
  return typeof pkg.version === "string" ? pkg.version : "0.0.0";
15429
15674
  } catch {
15430
15675
  return "0.0.0";
@@ -16540,7 +16785,7 @@ var init_lsp_client = __esm(() => {
16540
16785
  });
16541
16786
 
16542
16787
  // src/resources.ts
16543
- import { readFileSync as readFileSync18, realpathSync as realpathSync4 } from "node:fs";
16788
+ import { readFileSync as readFileSync20, realpathSync as realpathSync4 } from "node:fs";
16544
16789
  import { extname as extname4, resolve as resolve9 } from "node:path";
16545
16790
  function ensureProjectPath(getProjectPath) {
16546
16791
  const projectPath = getProjectPath();
@@ -16736,7 +16981,7 @@ function readResourceText(uri, getProjectPath) {
16736
16981
  const parsedUri = parseGodotUri(uri);
16737
16982
  if (parsedUri.kind === "project-info") {
16738
16983
  const projectFilePath = resolveProjectFile(projectPath, "project.godot");
16739
- const rawProject = readFileSync18(projectFilePath, "utf-8");
16984
+ const rawProject = readFileSync20(projectFilePath, "utf-8");
16740
16985
  const parsedProject = parseProjectGodot(rawProject);
16741
16986
  return {
16742
16987
  mimeType: "application/json",
@@ -16745,7 +16990,7 @@ function readResourceText(uri, getProjectPath) {
16745
16990
  }
16746
16991
  const filePath = resolveProjectFile(projectPath, parsedUri.resourcePath);
16747
16992
  ensureAllowedExtension(parsedUri.kind, filePath);
16748
- const text = readFileSync18(filePath, "utf-8");
16993
+ const text = readFileSync20(filePath, "utf-8");
16749
16994
  return {
16750
16995
  mimeType: parsedUri.kind === "script" ? "text/x-gdscript" : "text/plain",
16751
16996
  text
@@ -16892,7 +17137,7 @@ import {
16892
17137
  existsSync as existsSync19,
16893
17138
  mkdirSync as mkdirSync6,
16894
17139
  readdirSync as readdirSync12,
16895
- readFileSync as readFileSync19,
17140
+ readFileSync as readFileSync21,
16896
17141
  rmdirSync,
16897
17142
  rmSync as rmSync10,
16898
17143
  statSync as statSync12,
@@ -16926,7 +17171,7 @@ function addonsDigest(names, from) {
16926
17171
  } else {
16927
17172
  hash.update(`${inside}
16928
17173
  `);
16929
- hash.update(readFileSync19(path));
17174
+ hash.update(readFileSync21(path));
16930
17175
  hash.update(`
16931
17176
  `);
16932
17177
  }
@@ -16975,7 +17220,7 @@ function digestMarker(projectPath, addon) {
16975
17220
  if (!existsSync19(marker)) {
16976
17221
  return null;
16977
17222
  }
16978
- const said = readFileSync19(marker, "utf8").trim();
17223
+ const said = readFileSync21(marker, "utf8").trim();
16979
17224
  return said === "" ? null : said;
16980
17225
  }
16981
17226
  function shippedAddonsDirectory() {
@@ -16992,7 +17237,7 @@ function loaderState(projectPath) {
16992
17237
  if (!existsSync19(copy)) {
16993
17238
  return "missing";
16994
17239
  }
16995
- const lines = (path) => readFileSync19(path, "utf8").replaceAll(`\r
17240
+ const lines = (path) => readFileSync21(path, "utf8").replaceAll(`\r
16996
17241
  `, `
16997
17242
  `);
16998
17243
  return lines(copy) === lines(shippedLoader()) ? "current" : "differs";
@@ -17003,7 +17248,7 @@ function writeLoader(projectPath) {
17003
17248
  }
17004
17249
  const copy = join22(projectPath, ...RUNTIME_AUTOLOAD.path.split("/"));
17005
17250
  mkdirSync6(dirname9(copy), { recursive: true });
17006
- writeFileSync11(copy, readFileSync19(shippedLoader()));
17251
+ writeFileSync11(copy, readFileSync21(shippedLoader()));
17007
17252
  return true;
17008
17253
  }
17009
17254
  function removeLoader(projectPath) {
@@ -17062,7 +17307,7 @@ function installedAddonVersion(projectPath) {
17062
17307
  if (!existsSync19(marker)) {
17063
17308
  return null;
17064
17309
  }
17065
- const said = readFileSync19(marker, "utf8").trim();
17310
+ const said = readFileSync21(marker, "utf8").trim();
17066
17311
  return said === "" ? null : said;
17067
17312
  }
17068
17313
  function removeAddons(projectPath) {
@@ -17117,7 +17362,7 @@ function loaderAmong(projectPath, named) {
17117
17362
  }
17118
17363
  let source = null;
17119
17364
  try {
17120
- source = readFileSync19(join22(projectPath, path), "utf8");
17365
+ source = readFileSync21(join22(projectPath, path), "utf8");
17121
17366
  } catch {}
17122
17367
  if (source?.includes(RUNTIME_SCRIPT)) {
17123
17368
  return { name: entry, path, exists: true };
@@ -17176,7 +17421,7 @@ function inspectProject(projectPath) {
17176
17421
  const directory = join22(projectPath, "addons", name);
17177
17422
  const marker = join22(directory, VERSION_MARKER);
17178
17423
  const installed = existsSync19(directory);
17179
- const version = existsSync19(marker) ? readFileSync19(marker, "utf8").trim() : null;
17424
+ const version = existsSync19(marker) ? readFileSync21(marker, "utf8").trim() : null;
17180
17425
  const current = version === SERVER_VERSION;
17181
17426
  if (!installed) {
17182
17427
  problems.push(`addons/${name} is not installed; run gdharness setup`);
@@ -17185,7 +17430,7 @@ function inspectProject(projectPath) {
17185
17430
  }
17186
17431
  return { name, installed, version, current };
17187
17432
  });
17188
- const settings = parseProjectGodot(readFileSync19(join22(projectPath, "project.godot"), "utf8"));
17433
+ const settings = parseProjectGodot(readFileSync21(join22(projectPath, "project.godot"), "utf8"));
17189
17434
  const pluginsEnabled = enabledPlugins(settings);
17190
17435
  for (const name of EDITOR_PLUGINS) {
17191
17436
  if (!pluginsEnabled.includes(name)) {
@@ -17905,7 +18150,7 @@ var init_tool_definitions = __esm(() => {
17905
18150
  {
17906
18151
  name: "project_export",
17907
18152
  title: "Export",
17908
- description: "Export presets and exports. add_preset writes a preset to export_presets.cfg with the keys the editor's Project > Export writes for a new one and every option a new preset of its platform shows, each at its default, and makes it the platform's runnable preset when the platform has none. set_preset changes a preset's export path, its resource filter and the files it lists, its include and exclude filters, its custom features and its platform's options, and answers under changed what each held before and holds now, and under unchanged what already held the value given, with saved false when that is all of it, since the file is then not written; nothing is written when any of it is refused. The option names are the exporter's own, as the Export dialog's Options tab shows them by their paths, such as binary_format/embed_pck, and a name the platform does not have is refused with the nearest it has, or all of them when none is near. An option the dialog shows only while another is on, such as codesign/identity behind codesign/enable, is taken when the preset has that one on or the same call turns it on, and otherwise refused naming what shows it. A secret option, such as a signing password, is written to .godot/export_credentials.cfg, where the editor keeps secrets out of the committed file, and its value is never answered. A file an option names that is not there is written and listed under missing_files, or for a secret its option under secretsNamingNoFile. remove_preset takes a preset out, and when it was its platform's runnable preset the next of that platform becomes it, under runnableNow, which is null when the platform has no other; a secret it held is taken out with it. It answers where this engine's export templates belong and whether the preset's platform has them, since an export needs them; list says the same for every preset. An editor open on the project does not see a preset added this way until it restarts. run answers bytes, the size of the output it wrote, and names, as alsoWritten, what else the export wrote beside its output, such as the .pck a Windows or Linux build cannot start without. Its entries are the errors and warnings the export printed, the newest two hundred distinct ones, one printed more than once carrying times, and errors and warnings count them; exported is true only when this run wrote the output and printed no error.",
18153
+ description: "Export presets and exports. add_preset writes a preset to export_presets.cfg with the keys the editor's Project > Export writes for a new one and every option a new preset of its platform shows, each at its default, and makes it the platform's runnable preset when the platform has none. set_preset changes a preset's export path, its resource filter and the files it lists, its include and exclude filters, its custom features and its platform's options, and answers under changed what each held before and holds now, and under unchanged what already held the value given, with saved false when that is all of it, since the file is then not written; nothing is written when any of it is refused. The option names are the exporter's own, as the Export dialog's Options tab shows them by their paths, such as binary_format/embed_pck, and a name the platform does not have is refused with the nearest it has, or all of them when none is near. An option the dialog shows only while another is on, such as codesign/identity behind codesign/enable, is taken when the preset has that one on or the same call turns it on, and otherwise refused naming what shows it. A secret option, such as a signing password, is written to .godot/export_credentials.cfg, where the editor keeps secrets out of the committed file, and its value is never answered. A file an option names that is not there is written and listed under missing_files, or for a secret its option under secretsNamingNoFile. remove_preset takes a preset out, and when it was its platform's runnable preset the next of that platform becomes it, under runnableNow, which is null when the platform has no other; a secret it held is taken out with it. It answers where this engine's export templates belong and whether the preset's platform has them, since an export needs them; list says the same for every preset. An editor open on the project does not see a preset added this way until it restarts. run first imports whatever changed on disk since it was imported, named under importedFirst, so the build carries each file as it is now. It answers bytes, the size of the output it wrote, and names, as alsoWritten, what else the export wrote beside its output, such as the .pck a Windows or Linux build cannot start without. Its entries are the errors and warnings the export printed, the newest two hundred distinct ones, one printed more than once carrying times, and errors and warnings count them; exported is true only when this run wrote the output and printed no error.",
17909
18154
  parameters: {
17910
18155
  projectPath: PROJECT_PATH,
17911
18156
  preset: {
@@ -19780,7 +20025,7 @@ var init_tool_reference = __esm(() => {
19780
20025
  });
19781
20026
 
19782
20027
  // src/suite-plan.ts
19783
- import { existsSync as existsSync23, mkdirSync as mkdirSync9, readFileSync as readFileSync22 } from "node:fs";
20028
+ import { existsSync as existsSync23, mkdirSync as mkdirSync9, readFileSync as readFileSync24 } from "node:fs";
19784
20029
  import { dirname as dirname11, join as join26, posix as posix3 } from "node:path";
19785
20030
  function within(path, folder) {
19786
20031
  return path === folder || path.startsWith(`${folder}/`);
@@ -19797,7 +20042,7 @@ class ProjectScripts {
19797
20042
  this.projectPath = projectPath;
19798
20043
  let settings = {};
19799
20044
  try {
19800
- settings = parseProjectGodot(readFileSync22(join26(projectPath, "project.godot"), "utf8"))["gdharness"] ?? {};
20045
+ settings = parseProjectGodot(readFileSync24(join26(projectPath, "project.godot"), "utf8"))["gdharness"] ?? {};
19801
20046
  } catch {}
19802
20047
  const [section, key] = [NOT_SEARCHED_SETTING, GUESS_WINDOW_SETTING].map((setting) => setting.slice("gdharness/".length));
19803
20048
  const listed = settings[section ?? ""];
@@ -19912,7 +20157,7 @@ class ProjectScripts {
19912
20157
  }
19913
20158
  function readTimes(file) {
19914
20159
  try {
19915
- const parsed = JSON.parse(readFileSync22(file, "utf8"));
20160
+ const parsed = JSON.parse(readFileSync24(file, "utf8"));
19916
20161
  return typeof parsed === "object" && parsed !== null ? parsed : {};
19917
20162
  } catch {
19918
20163
  return {};
@@ -20195,7 +20440,7 @@ function capsFrames(projectPath) {
20195
20440
  if (!existsSync23(file)) {
20196
20441
  return false;
20197
20442
  }
20198
- const cap = parseProjectGodot(readFileSync22(file, "utf8"))["application"]?.["run/max_fps"];
20443
+ const cap = parseProjectGodot(readFileSync24(file, "utf8"))["application"]?.["run/max_fps"];
20199
20444
  return typeof cap === "number" && cap > 0;
20200
20445
  }
20201
20446
  function gdUnitFailsOnPushErrors(projectPath) {
@@ -20203,14 +20448,14 @@ function gdUnitFailsOnPushErrors(projectPath) {
20203
20448
  if (!existsSync23(file)) {
20204
20449
  return false;
20205
20450
  }
20206
- return parseProjectGodot(readFileSync22(file, "utf8"))["gdunit4"]?.["report/godot/push_error"] === true;
20451
+ return parseProjectGodot(readFileSync24(file, "utf8"))["gdunit4"]?.["report/godot/push_error"] === true;
20207
20452
  }
20208
20453
  function viewportOf(projectPath) {
20209
20454
  const file = `${projectPath}/project.godot`;
20210
20455
  if (!existsSync23(file)) {
20211
20456
  return null;
20212
20457
  }
20213
- const text = readFileSync22(file, "utf8");
20458
+ const text = readFileSync24(file, "utf8");
20214
20459
  const width = /^window\/size\/viewport_width\s*=\s*(\d+)/m.exec(text)?.[1];
20215
20460
  const height = /^window\/size\/viewport_height\s*=\s*(\d+)/m.exec(text)?.[1];
20216
20461
  return width === undefined || height === undefined ? null : { width: Number(width), height: Number(height) };
@@ -41829,13 +42074,13 @@ var init_stdio = __esm(() => {
41829
42074
  });
41830
42075
 
41831
42076
  // src/autoload-failure.ts
41832
- import { existsSync as existsSync25, readFileSync as readFileSync25 } from "node:fs";
42077
+ import { existsSync as existsSync25, readFileSync as readFileSync27 } from "node:fs";
41833
42078
  import { join as join29 } from "node:path";
41834
42079
  function scriptsAutoloaded(projectPath) {
41835
42080
  const scripts = new Map;
41836
42081
  let settings;
41837
42082
  try {
41838
- settings = parseProjectGodot(readFileSync25(join29(projectPath, "project.godot"), "utf8"));
42083
+ settings = parseProjectGodot(readFileSync27(join29(projectPath, "project.godot"), "utf8"));
41839
42084
  } catch {
41840
42085
  return scripts;
41841
42086
  }
@@ -41849,7 +42094,7 @@ function scriptsAutoloaded(projectPath) {
41849
42094
  continue;
41850
42095
  }
41851
42096
  try {
41852
- for (const named of readFileSync25(scene, "utf8").matchAll(/^\[ext_resource\b[^\]]*\btype="Script"[^\]]*\bpath="(res:\/\/[^"]+)"/gm)) {
42097
+ for (const named of readFileSync27(scene, "utf8").matchAll(/^\[ext_resource\b[^\]]*\btype="Script"[^\]]*\bpath="(res:\/\/[^"]+)"/gm)) {
41853
42098
  scripts.set(named[1] ?? "", name);
41854
42099
  }
41855
42100
  } catch {}
@@ -41868,7 +42113,7 @@ var init_autoload_failure = __esm(() => {
41868
42113
  });
41869
42114
 
41870
42115
  // src/runtime-client.ts
41871
- import { existsSync as existsSync26, readdirSync as readdirSync16, readFileSync as readFileSync26, statSync as statSync15, unlinkSync as unlinkSync3 } from "node:fs";
42116
+ import { existsSync as existsSync26, readdirSync as readdirSync16, readFileSync as readFileSync28, statSync as statSync15, unlinkSync as unlinkSync3 } from "node:fs";
41872
42117
  import { createConnection as createConnection2 } from "node:net";
41873
42118
  import { tmpdir as tmpdir7 } from "node:os";
41874
42119
  import { dirname as dirname14, join as join30, resolve as resolve12 } from "node:path";
@@ -41923,7 +42168,7 @@ function reportAlreadyInTranscript(transcript, report) {
41923
42168
  function parseAnnouncement(file, pid) {
41924
42169
  let fields;
41925
42170
  try {
41926
- fields = asParams(JSON.parse(readFileSync26(file, "utf8")));
42171
+ fields = asParams(JSON.parse(readFileSync28(file, "utf8")));
41927
42172
  } catch {
41928
42173
  return { kind: "rubbish" };
41929
42174
  }
@@ -41995,7 +42240,7 @@ function discoverRuntimes(directories = runtimeDirectories()) {
41995
42240
  function wentAway(file, pid) {
41996
42241
  let project = "";
41997
42242
  try {
41998
- const fields = asParams(JSON.parse(readFileSync26(file, "utf8")));
42243
+ const fields = asParams(JSON.parse(readFileSync28(file, "utf8")));
41999
42244
  project = readString(readParams(fields, "project") ?? {}, "path") ?? "";
42000
42245
  } catch {
42001
42246
  return;
@@ -42510,14 +42755,14 @@ var init_runtime_client = __esm(() => {
42510
42755
  });
42511
42756
 
42512
42757
  // src/boot-note.ts
42513
- import { mkdirSync as mkdirSync11, readFileSync as readFileSync27, writeFileSync as writeFileSync14 } from "node:fs";
42758
+ import { mkdirSync as mkdirSync11, readFileSync as readFileSync29, writeFileSync as writeFileSync14 } from "node:fs";
42514
42759
  import { dirname as dirname15, join as join31 } from "node:path";
42515
42760
  function bootNotePath(projectPath) {
42516
42761
  return join31(projectPath, ".godot", "gdharness-boot.json");
42517
42762
  }
42518
42763
  function readScenes(projectPath) {
42519
42764
  try {
42520
- return asParams(asParams(JSON.parse(readFileSync27(bootNotePath(projectPath), "utf8")))["scenes"]);
42765
+ return asParams(asParams(JSON.parse(readFileSync29(bootNotePath(projectPath), "utf8")))["scenes"]);
42521
42766
  } catch {
42522
42767
  return {};
42523
42768
  }
@@ -42559,7 +42804,7 @@ var init_boot_note = __esm(() => {
42559
42804
  });
42560
42805
 
42561
42806
  // src/breakpoint-note.ts
42562
- import { mkdirSync as mkdirSync12, readFileSync as readFileSync28, rmSync as rmSync14, writeFileSync as writeFileSync15 } from "node:fs";
42807
+ import { mkdirSync as mkdirSync12, readFileSync as readFileSync30, rmSync as rmSync14, writeFileSync as writeFileSync15 } from "node:fs";
42563
42808
  import { dirname as dirname16, isAbsolute as isAbsolute7, join as join32, relative as relative6 } from "node:path";
42564
42809
  function breakpointNotePath(projectPath) {
42565
42810
  return join32(projectPath, ".godot", "gdharness-breakpoints.json");
@@ -42588,7 +42833,7 @@ function writeBreakpointNote(projectPath, held) {
42588
42833
  }
42589
42834
  function readBreakpointNote(projectPath) {
42590
42835
  try {
42591
- const parsed = JSON.parse(readFileSync28(breakpointNotePath(projectPath), "utf8"));
42836
+ const parsed = JSON.parse(readFileSync30(breakpointNotePath(projectPath), "utf8"));
42592
42837
  if (typeof parsed !== "object" || parsed === null || !Array.isArray(parsed.breakpoints)) {
42593
42838
  return [];
42594
42839
  }
@@ -42621,14 +42866,14 @@ var init_breakpoint_note = __esm(() => {
42621
42866
  });
42622
42867
 
42623
42868
  // src/class-note.ts
42624
- import { mkdirSync as mkdirSync13, readFileSync as readFileSync29 } from "node:fs";
42869
+ import { mkdirSync as mkdirSync13, readFileSync as readFileSync31 } from "node:fs";
42625
42870
  import { dirname as dirname17, join as join33 } from "node:path";
42626
42871
  function classNotePath(projectPath) {
42627
42872
  return join33(projectPath, ".godot", "gdharness-classes.json");
42628
42873
  }
42629
42874
  function readClassNote(projectPath) {
42630
42875
  try {
42631
- const fields = asParams(JSON.parse(readFileSync29(classNotePath(projectPath), "utf8")));
42876
+ const fields = asParams(JSON.parse(readFileSync31(classNotePath(projectPath), "utf8")));
42632
42877
  const rebuiltWith = readArray(fields, "rebuiltWith");
42633
42878
  if (rebuiltWith === undefined || !rebuiltWith.every((name) => typeof name === "string")) {
42634
42879
  return null;
@@ -42670,7 +42915,7 @@ var init_class_note = __esm(() => {
42670
42915
  });
42671
42916
 
42672
42917
  // src/config-pin.ts
42673
- import { existsSync as existsSync27, readFileSync as readFileSync30 } from "node:fs";
42918
+ import { existsSync as existsSync27, readFileSync as readFileSync32 } from "node:fs";
42674
42919
  import { join as join34 } from "node:path";
42675
42920
  function versionsNamedInConfig(projectPath) {
42676
42921
  const config = join34(projectPath, ".mcp.json");
@@ -42679,7 +42924,7 @@ function versionsNamedInConfig(projectPath) {
42679
42924
  }
42680
42925
  let text;
42681
42926
  try {
42682
- text = readFileSync30(config, "utf8");
42927
+ text = readFileSync32(config, "utf8");
42683
42928
  JSON.parse(text);
42684
42929
  } catch {
42685
42930
  return [];
@@ -42700,7 +42945,7 @@ var init_config_pin = __esm(() => {
42700
42945
  });
42701
42946
 
42702
42947
  // src/cut-test-run.ts
42703
- import { existsSync as existsSync28, mkdirSync as mkdirSync14, readFileSync as readFileSync31, rmSync as rmSync15, writeFileSync as writeFileSync16 } from "node:fs";
42948
+ import { existsSync as existsSync28, mkdirSync as mkdirSync14, readFileSync as readFileSync33, rmSync as rmSync15, writeFileSync as writeFileSync16 } from "node:fs";
42704
42949
  import { dirname as dirname18, join as join35 } from "node:path";
42705
42950
  function keptAt(projectPath) {
42706
42951
  return join35(projectPath, ".godot", "gdharness-reports", "cut-run.json");
@@ -42719,7 +42964,7 @@ function takeCutTestRun(projectPath) {
42719
42964
  return null;
42720
42965
  }
42721
42966
  try {
42722
- const run = JSON.parse(readFileSync31(path, "utf8"));
42967
+ const run = JSON.parse(readFileSync33(path, "utf8"));
42723
42968
  rmSync15(path, { force: true });
42724
42969
  return typeof run.cutAt === "string" && Array.isArray(run.paths) && run.paths.every((path) => typeof path === "string") ? run : null;
42725
42970
  } catch {
@@ -43486,7 +43731,7 @@ import {
43486
43731
  existsSync as existsSync29,
43487
43732
  mkdirSync as mkdirSync15,
43488
43733
  openSync as openSync5,
43489
- readFileSync as readFileSync32,
43734
+ readFileSync as readFileSync34,
43490
43735
  readSync as readSync3,
43491
43736
  rmSync as rmSync16,
43492
43737
  statSync as statSync16,
@@ -43501,7 +43746,7 @@ function editorLogNotePath(projectPath) {
43501
43746
  }
43502
43747
  function readEditorLogNote(projectPath) {
43503
43748
  try {
43504
- const fields = asParams(JSON.parse(readFileSync32(editorLogNotePath(projectPath), "utf8")));
43749
+ const fields = asParams(JSON.parse(readFileSync34(editorLogNotePath(projectPath), "utf8")));
43505
43750
  const pid = readNumber(fields, "pid");
43506
43751
  const startedAt = readString(fields, "startedAt");
43507
43752
  const processStartedAt = readNumber(fields, "processStartedAt");
@@ -43605,7 +43850,7 @@ function foldProgress(text) {
43605
43850
  function theFirstOf(path) {
43606
43851
  const whole = statSync16(path).size;
43607
43852
  if (whole <= MOST_CONSOLE_BYTES) {
43608
- return { text: readFileSync32(path, "utf8") };
43853
+ return { text: readFileSync34(path, "utf8") };
43609
43854
  }
43610
43855
  const handle = openSync5(path, "r");
43611
43856
  try {
@@ -43766,7 +44011,7 @@ var init_editor_log = __esm(() => {
43766
44011
  });
43767
44012
 
43768
44013
  // src/rename.ts
43769
- import { existsSync as existsSync30, mkdirSync as mkdirSync16, readFileSync as readFileSync33, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync18 } from "node:fs";
44014
+ import { existsSync as existsSync30, mkdirSync as mkdirSync16, readFileSync as readFileSync35, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync18 } from "node:fs";
43770
44015
  import { dirname as dirname20, posix as posix4 } from "node:path";
43771
44016
 
43772
44017
  class Script {
@@ -44487,7 +44732,7 @@ function rewritesOf(plan, texts, move) {
44487
44732
  }
44488
44733
  function applyRewrites(rewrites) {
44489
44734
  for (const rewrite of rewrites) {
44490
- const now = readFileSync33(rewrite.absolute, "utf8");
44735
+ const now = readFileSync35(rewrite.absolute, "utf8");
44491
44736
  if (now !== rewrite.before) {
44492
44737
  throw new Error(`${rewrite.path} changed on disk while the rename was being worked out; nothing was written`);
44493
44738
  }
@@ -45074,7 +45319,7 @@ import {
45074
45319
  existsSync as existsSync32,
45075
45320
  mkdirSync as mkdirSync18,
45076
45321
  readdirSync as readdirSync18,
45077
- readFileSync as readFileSync34,
45322
+ readFileSync as readFileSync36,
45078
45323
  renameSync as renameSync5,
45079
45324
  statSync as statSync17,
45080
45325
  writeFileSync as writeFileSync20
@@ -45234,7 +45479,7 @@ function planFileMove(projectPath, absoluteFrom, absoluteTo) {
45234
45479
  plan = mentionIgnored(plan, ignoredTexts(projectPath), null, [from]);
45235
45480
  const binaries = [];
45236
45481
  for (const path of binaryResources(projectPath)) {
45237
- const bytes = readFileSync34(join38(projectPath, path.slice("res://".length)));
45482
+ const bytes = readFileSync36(join38(projectPath, path.slice("res://".length)));
45238
45483
  const names = [...moves.keys()].find((moving) => bytes.includes(moving));
45239
45484
  if (names !== undefined) {
45240
45485
  binaries.push({
@@ -45295,7 +45540,7 @@ function planFileMove(projectPath, absoluteFrom, absoluteTo) {
45295
45540
  }
45296
45541
  function applyFileMove(outcome) {
45297
45542
  for (const rewrite of outcome.inPlace) {
45298
- if (readFileSync34(rewrite.absolute, "utf8") !== rewrite.before) {
45543
+ if (readFileSync36(rewrite.absolute, "utf8") !== rewrite.before) {
45299
45544
  throw new Error(`${rewrite.path} changed on disk while the move was being worked out; nothing was written`);
45300
45545
  }
45301
45546
  }
@@ -45303,7 +45548,7 @@ function applyFileMove(outcome) {
45303
45548
  if (!existsSync32(file.absoluteFrom)) {
45304
45549
  throw new Error(`${file.from} is gone from disk; nothing was written`);
45305
45550
  }
45306
- if (file.text !== null && readFileSync34(file.absoluteFrom, "utf8") !== file.text.before) {
45551
+ if (file.text !== null && readFileSync36(file.absoluteFrom, "utf8") !== file.text.before) {
45307
45552
  throw new Error(`${file.from} changed on disk while the move was being worked out; nothing was written`);
45308
45553
  }
45309
45554
  if (existsSync32(file.absoluteTo) && !sameFile(file.absoluteFrom, file.absoluteTo)) {
@@ -49218,44 +49463,6 @@ function notListeningNote(servers, greetedAgoMs) {
49218
49463
  var STARTING_MS = 20000;
49219
49464
  var init_port_probe = () => {};
49220
49465
 
49221
- // src/process-time.ts
49222
- async function cpuSecondsOf(pid) {
49223
- try {
49224
- return process.platform === "win32" ? await secondsOnWindows(pid) : await askPosix2(pid);
49225
- } catch {
49226
- return;
49227
- }
49228
- }
49229
- async function secondsOnWindows(pid) {
49230
- const said = (await askProcessTable(`ProcessorSeconds(${pid})`, ASK_TIMEOUT_MS2)).trim();
49231
- const seconds = Number(said);
49232
- return said !== "" && Number.isFinite(seconds) ? seconds : undefined;
49233
- }
49234
- async function askPosix2(pid) {
49235
- const { stdout } = await runHidden("ps", ["-o", "time=", "-p", String(pid)], { timeout: ASK_TIMEOUT_MS2 });
49236
- return secondsFromClock(stdout.trim());
49237
- }
49238
- function secondsFromClock(printed) {
49239
- if (printed === "") {
49240
- return;
49241
- }
49242
- const dashed = printed.includes("-");
49243
- const days = dashed ? printed.slice(0, printed.indexOf("-")) : null;
49244
- const clock = dashed ? printed.slice(printed.indexOf("-") + 1) : printed;
49245
- const parts = clock.split(":").map((part) => Number(part));
49246
- if (parts.length === 0 || parts.some((part) => !Number.isFinite(part))) {
49247
- return;
49248
- }
49249
- const seconds = parts.reduce((total, part) => total * 60 + part, 0);
49250
- const extra = days === null ? 0 : Number(days) * 86400;
49251
- return Number.isFinite(extra) ? seconds + extra : undefined;
49252
- }
49253
- var ASK_TIMEOUT_MS2 = 6000;
49254
- var init_process_time = __esm(() => {
49255
- init_process_table();
49256
- init_spawn();
49257
- });
49258
-
49259
49466
  // src/prompts.ts
49260
49467
  function listedPrompts() {
49261
49468
  return PROMPT_SPECS.map((spec) => ({
@@ -49393,7 +49600,7 @@ var init_prompts = __esm(() => {
49393
49600
  });
49394
49601
 
49395
49602
  // src/restart-note.ts
49396
- import { mkdirSync as mkdirSync20, readFileSync as readFileSync35, rmSync as rmSync18, writeFileSync as writeFileSync21 } from "node:fs";
49603
+ import { mkdirSync as mkdirSync20, readFileSync as readFileSync37, rmSync as rmSync18, writeFileSync as writeFileSync21 } from "node:fs";
49397
49604
  import { dirname as dirname24, join as join40 } from "node:path";
49398
49605
  function restartNotePath(projectPath) {
49399
49606
  return join40(projectPath, ".godot", "gdharness-restart.json");
@@ -49410,7 +49617,7 @@ function noteRestartBegun(note) {
49410
49617
  }
49411
49618
  function restartOwed(projectPath) {
49412
49619
  try {
49413
- const parsed = JSON.parse(readFileSync35(restartNotePath(projectPath), "utf8"));
49620
+ const parsed = JSON.parse(readFileSync37(restartNotePath(projectPath), "utf8"));
49414
49621
  if (typeof parsed !== "object" || parsed === null) {
49415
49622
  return null;
49416
49623
  }
@@ -49436,7 +49643,7 @@ var init_restart_note = __esm(() => {
49436
49643
 
49437
49644
  // src/run-record.ts
49438
49645
  import { createHash as createHash7 } from "node:crypto";
49439
- import { mkdirSync as mkdirSync21, openSync as openSync6, readdirSync as readdirSync19, readFileSync as readFileSync36, rmSync as rmSync19, statSync as statSync19 } from "node:fs";
49646
+ import { mkdirSync as mkdirSync21, openSync as openSync6, readdirSync as readdirSync19, readFileSync as readFileSync38, rmSync as rmSync19, statSync as statSync19 } from "node:fs";
49440
49647
  import { basename as basename12, join as join41, resolve as resolve14 } from "node:path";
49441
49648
  function runsDirectory() {
49442
49649
  return join41(runtimeDirectory(), "runs");
@@ -49460,7 +49667,7 @@ function writeLatestRun(servedBy, latest) {
49460
49667
  }
49461
49668
  function readLatestRun(servedBy, directory = runtimeDirectory()) {
49462
49669
  try {
49463
- const fields = JSON.parse(readFileSync36(latestRunPath(servedBy, directory), "utf8"));
49670
+ const fields = JSON.parse(readFileSync38(latestRunPath(servedBy, directory), "utf8"));
49464
49671
  if (typeof fields !== "object" || fields === null) {
49465
49672
  return null;
49466
49673
  }
@@ -49509,7 +49716,7 @@ function readEditorRunNote(projectPath) {
49509
49716
  function editorNoteAt(path) {
49510
49717
  let parsed;
49511
49718
  try {
49512
- parsed = JSON.parse(readFileSync36(path, "utf8"));
49719
+ parsed = JSON.parse(readFileSync38(path, "utf8"));
49513
49720
  } catch {
49514
49721
  return null;
49515
49722
  }
@@ -49559,7 +49766,7 @@ function everyRunRecord() {
49559
49766
  function recordAt(path) {
49560
49767
  let parsed;
49561
49768
  try {
49562
- parsed = JSON.parse(readFileSync36(path, "utf8"));
49769
+ parsed = JSON.parse(readFileSync38(path, "utf8"));
49563
49770
  } catch {
49564
49771
  return null;
49565
49772
  }
@@ -49640,7 +49847,7 @@ async function runningAs(pid) {
49640
49847
  const began = await startedAt(pid, null);
49641
49848
  const when = began === null ? {} : { startedAt: began };
49642
49849
  if (process.platform === "linux") {
49643
- const raw = readFileSync36(`/proc/${pid}/cmdline`, "utf8").replaceAll("\x00", " ").trim();
49850
+ const raw = readFileSync38(`/proc/${pid}/cmdline`, "utf8").replaceAll("\x00", " ").trim();
49644
49851
  return raw === "" ? null : { kind: "commandLine", text: raw, ...when };
49645
49852
  }
49646
49853
  const args = (await runHidden("ps", ["-p", String(pid), "-o", "args="], { timeout: 15000 })).stdout.trim();
@@ -49836,10 +50043,10 @@ var init_run_record = __esm(() => {
49836
50043
  });
49837
50044
 
49838
50045
  // src/script-profile.ts
49839
- import { readFileSync as readFileSync37 } from "node:fs";
50046
+ import { readFileSync as readFileSync39 } from "node:fs";
49840
50047
  function readProfileFile(path) {
49841
50048
  try {
49842
- const parsed = JSON.parse(readFileSync37(path, "utf8"));
50049
+ const parsed = JSON.parse(readFileSync39(path, "utf8"));
49843
50050
  return typeof parsed === "object" && typeof parsed.connected === "boolean" ? parsed : null;
49844
50051
  } catch {
49845
50052
  return null;
@@ -49897,7 +50104,7 @@ function writeProfileMark(path, mark) {
49897
50104
  }
49898
50105
  function readProfileMark(path) {
49899
50106
  try {
49900
- const parsed = JSON.parse(readFileSync37(path, "utf8"));
50107
+ const parsed = JSON.parse(readFileSync39(path, "utf8"));
49901
50108
  return typeof parsed === "object" && typeof parsed.totals === "object" ? parsed : null;
49902
50109
  } catch {
49903
50110
  return null;
@@ -50229,7 +50436,7 @@ import {
50229
50436
  mkdirSync as mkdirSync23,
50230
50437
  openSync as openSync7,
50231
50438
  readdirSync as readdirSync20,
50232
- readFileSync as readFileSync38,
50439
+ readFileSync as readFileSync40,
50233
50440
  readSync as readSync4,
50234
50441
  realpathSync as realpathSync6,
50235
50442
  rmdirSync as rmdirSync2,
@@ -50250,9 +50457,9 @@ function greetingWaitMs() {
50250
50457
  return waitFromEnv("GDHARNESS_GREETING_WAIT_MS", 1e4);
50251
50458
  }
50252
50459
  function pictureToSend(pngPath, jpegPath) {
50253
- const png = readFileSync38(pngPath);
50460
+ const png = readFileSync40(pngPath);
50254
50461
  const beside = pngPath.replace(/\.png$/, ".jpg");
50255
- const jpeg = jpegPath !== undefined && normalize2(jpegPath) === normalize2(beside) && existsSync35(beside) ? readFileSync38(beside) : null;
50462
+ const jpeg = jpegPath !== undefined && normalize2(jpegPath) === normalize2(beside) && existsSync35(beside) ? readFileSync40(beside) : null;
50256
50463
  const sent = jpeg !== null && jpeg.length < png.length ? jpeg : png;
50257
50464
  return {
50258
50465
  data: sent.toString("base64"),
@@ -50728,7 +50935,7 @@ function endedToStartThis(ended) {
50728
50935
  return ` ${which} was ended to start this one; its output is no longer what editor_output answers about.`;
50729
50936
  }
50730
50937
  function lineNothingStopsOn(absolutePath, relativePath, line) {
50731
- const text = readFileSync38(absolutePath, "utf8");
50938
+ const text = readFileSync40(absolutePath, "utf8");
50732
50939
  const lines = text === "" ? 0 : text.split(`
50733
50940
  `).length - (text.endsWith(`
50734
50941
  `) ? 1 : 0);
@@ -50939,7 +51146,7 @@ function notRunNote(notRun, failFast) {
50939
51146
  function presetsIn(projectPath) {
50940
51147
  let text;
50941
51148
  try {
50942
- text = readFileSync38(join44(projectPath, "export_presets.cfg"), "utf8");
51149
+ text = readFileSync40(join44(projectPath, "export_presets.cfg"), "utf8");
50943
51150
  } catch {
50944
51151
  return null;
50945
51152
  }
@@ -50983,7 +51190,7 @@ function exportPresetRefusal(projectPath, preset) {
50983
51190
  }
50984
51191
  return names.length === 0 ? `export_presets.cfg names no preset, so there is no '${preset}' to export with. project_export add_preset adds one.` : `This project has no export preset named '${preset}'. Its presets are ${names.map((name) => `'${name}'`).join(", ")}.`;
50985
51192
  }
50986
- function exportAnswer(ending, asked, before, after, beside = [], docCacheNote = null, bytes = null) {
51193
+ function exportAnswer(ending, asked, before, after, beside = [], docCacheNote = null, bytes = null, imports = {}) {
50987
51194
  const { log } = ending;
50988
51195
  const written = after !== null && after !== before;
50989
51196
  const notCopied = librariesNotCopied(log.all);
@@ -50997,6 +51204,7 @@ function exportAnswer(ending, asked, before, after, beside = [], docCacheNote =
50997
51204
  warnings: log.count("warning"),
50998
51205
  ...written && bytes !== null ? { bytes } : {},
50999
51206
  ...beside.length === 0 ? {} : { alsoWritten: beside },
51207
+ ...imports,
51000
51208
  ...notCopied.length === 0 ? {} : {
51001
51209
  librariesNotLoaded: notCopied,
51002
51210
  extensionNote: `The export could not load ${notCopied.join(" and ")}: on Windows an engine running as the editor, which an export is, loads a GDExtension from a ~ copy beside the library, and another engine on this project held that copy: it could not be moved aside before the export, or another engine made a new one in between. Export again once that engine has loaded or exited.`
@@ -51114,7 +51322,7 @@ function rewriteBusNamed(projectPath, from, to) {
51114
51322
  const rewritten = [];
51115
51323
  for (const file of projectFiles(projectPath, [".tscn", ".tres"])) {
51116
51324
  const absolute = join44(projectPath, file);
51117
- const lines = readFileSync38(absolute, "utf8").split(`
51325
+ const lines = readFileSync40(absolute, "utf8").split(`
51118
51326
  `);
51119
51327
  const at = [];
51120
51328
  const after = lines.map((line, index) => {
@@ -51133,7 +51341,7 @@ function rewriteBusNamed(projectPath, from, to) {
51133
51341
  }
51134
51342
  const namedInScripts = [];
51135
51343
  for (const file of projectFiles(projectPath, [".gd"])) {
51136
- readFileSync38(join44(projectPath, file), "utf8").split(`
51344
+ readFileSync40(join44(projectPath, file), "utf8").split(`
51137
51345
  `).forEach((line, index) => {
51138
51346
  if (line.includes(`"${from}"`)) {
51139
51347
  namedInScripts.push({ file: `res://${file}`, line: index + 1, text: line.trim() });
@@ -51418,7 +51626,7 @@ function profileFrameFunctions(projectPath) {
51418
51626
  let projectGodot = null;
51419
51627
  if (projectPath !== null) {
51420
51628
  try {
51421
- projectGodot = readFileSync38(join44(projectPath, "project.godot"), "utf8");
51629
+ projectGodot = readFileSync40(join44(projectPath, "project.godot"), "utf8");
51422
51630
  } catch {}
51423
51631
  }
51424
51632
  return frameFunctionsFor(queuedMessagesOf(projectGodot));
@@ -51442,7 +51650,7 @@ function projectSourceOf(projectPath) {
51442
51650
  let source = null;
51443
51651
  if (inside.ok) {
51444
51652
  try {
51445
- source = readFileSync38(inside.absolutePath, "utf8");
51653
+ source = readFileSync40(inside.absolutePath, "utf8");
51446
51654
  } catch {}
51447
51655
  }
51448
51656
  read.set(script, source);
@@ -51614,7 +51822,7 @@ function foldedEntriesAnswer(log, floor = "warning") {
51614
51822
  }
51615
51823
  function gdUnitFailsOnScriptErrors(projectPath) {
51616
51824
  try {
51617
- return settingKeys(readFileSync38(join44(projectPath, "project.godot"), "utf8")).get("gdunit4/report/godot/script_error") !== false;
51825
+ return settingKeys(readFileSync40(join44(projectPath, "project.godot"), "utf8")).get("gdunit4/report/godot/script_error") !== false;
51618
51826
  } catch {
51619
51827
  return true;
51620
51828
  }
@@ -51761,11 +51969,11 @@ function isDirectory(path) {
51761
51969
  }
51762
51970
  }
51763
51971
  function mainSceneOf(projectFile) {
51764
- const scene = parseProjectGodot(readFileSync38(projectFile, "utf8"))["application"]?.["run/main_scene"];
51972
+ const scene = parseProjectGodot(readFileSync40(projectFile, "utf8"))["application"]?.["run/main_scene"];
51765
51973
  return typeof scene === "string" && scene !== "" ? scene : null;
51766
51974
  }
51767
51975
  function editorPlaysHeadless(projectFile) {
51768
- const runArgs = parseProjectGodot(readFileSync38(projectFile, "utf8"))["editor"]?.["run/main_run_args"];
51976
+ const runArgs = parseProjectGodot(readFileSync40(projectFile, "utf8"))["editor"]?.["run/main_run_args"];
51769
51977
  return typeof runArgs === "string" && /(?:^|\s)--headless(?:\s|$)/.test(runArgs);
51770
51978
  }
51771
51979
  function ownArguments(params) {
@@ -53707,7 +53915,7 @@ class GodotServer {
53707
53915
  if (!engine.ok) {
53708
53916
  return engine.response;
53709
53917
  }
53710
- const application = parseProjectGodot(readFileSync38(project.value.file, "utf8"))["application"] ?? {};
53918
+ const application = parseProjectGodot(readFileSync40(project.value.file, "utf8"))["application"] ?? {};
53711
53919
  const name = application["config/name"];
53712
53920
  const mainScene = application["run/main_scene"];
53713
53921
  const info = {
@@ -53964,6 +54172,7 @@ ${platform}`;
53964
54172
  if (pack && extension !== ".pck" && extension !== ".zip") {
53965
54173
  return this.createErrorResponse(`A pack is written as a .pck or a .zip, and ${output.relativePath} is neither: the exporter picks the format by the extension.`, ["Give outputPath ending in .pck, or .zip for a zip of the resources"]);
53966
54174
  }
54175
+ const imported = await this.importWhatChanged(project.value.path);
53967
54176
  const exportLogs = scratchDirectory("export");
53968
54177
  const exportArgs = [
53969
54178
  "--headless",
@@ -54006,7 +54215,7 @@ ${platform}`;
54006
54215
  return this.createErrorResponse(`Export could not be run: ${ending.failure ?? "the engine gave no exit status"}`);
54007
54216
  }
54008
54217
  const beside = writtenBeside(listedBefore, filesIn(folder), basename14(output.absolutePath), dirname25(output.relativePath).replaceAll("\\", "/"));
54009
- return exportAnswer(ending, { preset, outputPath: output.relativePath, debug, ...pack ? { pack } : {} }, before, writtenAt(), beside, docCacheNote, existsSync35(output.absolutePath) ? statSync20(output.absolutePath).size : null);
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));
54010
54219
  }
54011
54220
  reportTestProgress(log) {
54012
54221
  const progress = callProgress();
@@ -54275,13 +54484,13 @@ ${platform}`;
54275
54484
  const reportsDir = join44(project.value.path, ".godot", ...ours.split("/"));
54276
54485
  let report = null;
54277
54486
  let reportProblem = null;
54278
- const casePrinted = withNestedErrors(readRun(existsSync35(engineLog) ? readFileSync38(engineLog, "utf8") : ""), run.log.all);
54487
+ const casePrinted = withNestedErrors(readRun(existsSync35(engineLog) ? readFileSync40(engineLog, "utf8") : ""), run.log.all);
54279
54488
  const declaredErrors = readExpected(expectedFile);
54280
54489
  try {
54281
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))) : [];
54282
54491
  const newest = written.at(-1);
54283
54492
  if (newest !== undefined) {
54284
- report = parseJUnit(readFileSync38(join44(reportsDir, newest, "results.xml"), "utf8"));
54493
+ report = parseJUnit(readFileSync40(join44(reportsDir, newest, "results.xml"), "utf8"));
54285
54494
  }
54286
54495
  } catch (error) {
54287
54496
  reportProblem = errorMessage(error);
@@ -54827,7 +55036,7 @@ ${error.text}`;
54827
55036
  return null;
54828
55037
  }
54829
55038
  try {
54830
- return readFileSync38(contained.absolutePath, "utf8");
55039
+ return readFileSync40(contained.absolutePath, "utf8");
54831
55040
  } catch {
54832
55041
  return null;
54833
55042
  }
@@ -54921,7 +55130,7 @@ ${error.text}`;
54921
55130
  return null;
54922
55131
  }
54923
55132
  try {
54924
- return readFileSync38(contained.absolutePath, "utf8");
55133
+ return readFileSync40(contained.absolutePath, "utf8");
54925
55134
  } catch {
54926
55135
  return null;
54927
55136
  }
@@ -55440,7 +55649,7 @@ ${error.text}`;
55440
55649
  return null;
55441
55650
  }
55442
55651
  try {
55443
- return settingKeys(readFileSync38(join44(projectPath, "project.godot"), "utf8"));
55652
+ return settingKeys(readFileSync40(join44(projectPath, "project.godot"), "utf8"));
55444
55653
  } catch {
55445
55654
  return null;
55446
55655
  }
@@ -56276,7 +56485,7 @@ ${error.text}`;
56276
56485
  return 0;
56277
56486
  }
56278
56487
  try {
56279
- return reportAlreadyInTranscript(readFileSync38(game.transcript), readFileSync38(report));
56488
+ return reportAlreadyInTranscript(readFileSync40(game.transcript), readFileSync40(report));
56280
56489
  } catch (error) {
56281
56490
  this.logDebug(`Could not compare a picked-up run's report with its transcript: ${errorMessage(error)}`);
56282
56491
  return 0;
@@ -58747,7 +58956,7 @@ ${error.text}`;
58747
58956
  }
58748
58957
  const escaped = symbol.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
58749
58958
  const declared = new RegExp(`^\\s*(?:@\\w+(?:\\([^)]*\\))?\\s+)*class_name\\s+${escaped}\\b`, "m");
58750
- if (declared.test(readFileSync38(scriptPath, "utf8"))) {
58959
+ if (declared.test(readFileSync40(scriptPath, "utf8"))) {
58751
58960
  return null;
58752
58961
  }
58753
58962
  const checked = await this.classesTheEditorCannotSee(args);
@@ -59436,7 +59645,7 @@ init_alive();
59436
59645
  init_engine_launch();
59437
59646
  init_lsp_client();
59438
59647
  init_process_children();
59439
- import { existsSync as existsSync18, readdirSync as readdirSync11, readFileSync as readFileSync17, unlinkSync as unlinkSync2 } from "node:fs";
59648
+ import { existsSync as existsSync18, readdirSync as readdirSync11, readFileSync as readFileSync19, unlinkSync as unlinkSync2 } from "node:fs";
59440
59649
  import { connect as connect2 } from "node:net";
59441
59650
  import { join as join21, resolve as resolve8 } from "node:path";
59442
59651
  var EDITOR_RECORD_PROTOCOL = 1;
@@ -59455,7 +59664,7 @@ function editorRecordsIn(projectPath) {
59455
59664
  for (const name of names) {
59456
59665
  const file = join21(directory, name);
59457
59666
  try {
59458
- const said = JSON.parse(readFileSync17(file, "utf8"));
59667
+ const said = JSON.parse(readFileSync19(file, "utf8"));
59459
59668
  const { protocol, pid, lsp_port: lspPort, written_at_ms: writtenAtMs } = said;
59460
59669
  if (protocol === EDITOR_RECORD_PROTOCOL && typeof pid === "number" && typeof lspPort === "number" && lspPort > 0 && typeof writtenAtMs === "number") {
59461
59670
  records.push({ file, pid, lspPort, writtenAtMs });
@@ -59966,8 +60175,8 @@ init_engine_slots();
59966
60175
  init_log_read();
59967
60176
  init_setup();
59968
60177
  init_suite_judge();
59969
- import { existsSync as existsSync21, mkdirSync as mkdirSync8, readFileSync as readFileSync20, rmSync as rmSync12 } from "node:fs";
59970
- import { availableParallelism as availableParallelism3 } from "node:os";
60178
+ import { existsSync as existsSync21, mkdirSync as mkdirSync8, readFileSync as readFileSync22, rmSync as rmSync12 } from "node:fs";
60179
+ import { availableParallelism as availableParallelism4 } from "node:os";
59971
60180
  import { join as join24, resolve as resolve10 } from "node:path";
59972
60181
  import process13 from "node:process";
59973
60182
  var SHARE = "--gdh-share=";
@@ -60123,7 +60332,7 @@ async function runSpreadCommand(options, godotPath) {
60123
60332
  let workers = options.workers;
60124
60333
  if (workers === null) {
60125
60334
  const memory = await memoryAvailable();
60126
- const processors = options.cores ?? availableParallelism3();
60335
+ const processors = options.cores ?? availableParallelism4();
60127
60336
  const room = roomFor(slotCount, processors, memory.bytes, memory.said);
60128
60337
  workers = room.engines;
60129
60338
  console.log(`${options.scene} over ${plural(workers, "worker")}${room.held === undefined ? "" : `, since ${room.held}`}.`);
@@ -60154,7 +60363,7 @@ async function runSpreadCommand(options, godotPath) {
60154
60363
  const faults = left.flatMap((worker) => engineFaults(worker, options.godotVersion));
60155
60364
  const arms = left.map((_, index) => {
60156
60365
  const file = join24(shareDirectory, `worker-${String(index)}.arms`);
60157
- return existsSync21(file) ? armsPlayed(readFileSync20(file, "utf8")) : [];
60366
+ return existsSync21(file) ? armsPlayed(readFileSync22(file, "utf8")) : [];
60158
60367
  });
60159
60368
  faults.push(...shareFaults(arms));
60160
60369
  if (faults.length > 0) {
@@ -60164,7 +60373,7 @@ async function runSpreadCommand(options, godotPath) {
60164
60373
  console.log(readLog(gather.log).replace(CONTROL_SEQUENCE, "").trimEnd());
60165
60374
  const gatherFaults = engineFaults(gather, options.godotVersion);
60166
60375
  const gatheredFile = join24(shareDirectory, "gathered.arms");
60167
- const gathered = new Set((existsSync21(gatheredFile) ? armsPlayed(readFileSync20(gatheredFile, "utf8")) ?? [] : []).map((arm) => arm.arm));
60376
+ const gathered = new Set((existsSync21(gatheredFile) ? armsPlayed(readFileSync22(gatheredFile, "utf8")) ?? [] : []).map((arm) => arm.arm));
60168
60377
  const ungathered = (arms[0] ?? []).filter((arm) => !gathered.has(arm.arm)).map((arm) => arm.arm);
60169
60378
  if (ungathered.length > 0) {
60170
60379
  gatherFaults.push(`the gathering run never asked for ${ungathered.join(", ")}, which the workers played: it went another way through the arms than they did`);
@@ -60266,12 +60475,12 @@ import {
60266
60475
  existsSync as existsSync24,
60267
60476
  mkdirSync as mkdirSync10,
60268
60477
  readdirSync as readdirSync15,
60269
- readFileSync as readFileSync24,
60478
+ readFileSync as readFileSync26,
60270
60479
  rmSync as rmSync13,
60271
60480
  statSync as statSync14,
60272
60481
  writeFileSync as writeFileSync13
60273
60482
  } from "node:fs";
60274
- import { availableParallelism as availableParallelism4 } from "node:os";
60483
+ import { availableParallelism as availableParallelism5 } from "node:os";
60275
60484
  import { dirname as dirname13, join as join28, relative as relative5, resolve as resolve11, sep as sep4 } from "node:path";
60276
60485
  import process14 from "node:process";
60277
60486
 
@@ -60279,7 +60488,7 @@ import process14 from "node:process";
60279
60488
  init_class_cache();
60280
60489
  init_gdscript_source();
60281
60490
  import { createHash as createHash6 } from "node:crypto";
60282
- import { existsSync as existsSync22, readdirSync as readdirSync14, readFileSync as readFileSync21, statSync as statSync13 } from "node:fs";
60491
+ import { existsSync as existsSync22, readdirSync as readdirSync14, readFileSync as readFileSync23, statSync as statSync13 } from "node:fs";
60283
60492
  import { join as join25, posix as posix2 } from "node:path";
60284
60493
  var EVERY_FILE = "res://";
60285
60494
  var CACHE_HELD = "cache:";
@@ -60303,7 +60512,7 @@ function reachedBySuite(file) {
60303
60512
  const paths = (value) => Array.isArray(value) ? value.filter((path) => typeof path === "string") : [];
60304
60513
  let autoloads = [];
60305
60514
  const resident = new Map;
60306
- for (const line of readFileSync21(file, "utf8").split(`
60515
+ for (const line of readFileSync23(file, "utf8").split(`
60307
60516
  `)) {
60308
60517
  if (line.trim() === "") {
60309
60518
  continue;
@@ -60398,7 +60607,7 @@ ${this.read(path).digest}
60398
60607
  let modified = 0;
60399
60608
  walkSeen(this.scripts.projectPath, (file, under, stat) => {
60400
60609
  hash.update(`${under}
60401
- `).update(readFileSync21(file));
60610
+ `).update(readFileSync23(file));
60402
60611
  modified = Math.max(modified, stat.mtimeMs);
60403
60612
  });
60404
60613
  return { digest: hash.digest("hex"), follows: [], also: [], modified };
@@ -60410,7 +60619,7 @@ ${this.read(path).digest}
60410
60619
  if (existsSync22(directory)) {
60411
60620
  walkSeen(directory, (file, under, stat) => {
60412
60621
  hash.update(`${under}
60413
- `).update(readFileSync21(file));
60622
+ `).update(readFileSync23(file));
60414
60623
  modified = Math.max(modified, stat.mtimeMs);
60415
60624
  });
60416
60625
  }
@@ -60427,7 +60636,7 @@ ${this.read(path).digest}
60427
60636
  return { digest: inside.join(`
60428
60637
  `), follows: [], also: [], modified: stat.mtimeMs };
60429
60638
  }
60430
- const bytes = readFileSync21(file);
60639
+ const bytes = readFileSync23(file);
60431
60640
  const digest = createHash6("sha256").update(bytes).digest("hex");
60432
60641
  const also = [`${path}.import`, `${path}.uid`].filter((beside) => existsSync22(join25(this.scripts.projectPath, beside.slice("res://".length))));
60433
60642
  const follows = [];
@@ -60639,7 +60848,7 @@ function walkSeen(root, seen) {
60639
60848
  }
60640
60849
  function extensionsOf(projectPath) {
60641
60850
  const list = join25(projectPath, ".godot", "extension_list.cfg");
60642
- return existsSync22(list) ? readFileSync21(list, "utf8").split(`
60851
+ return existsSync22(list) ? readFileSync23(list, "utf8").split(`
60643
60852
  `).map((line) => line.trim()).filter((line) => line.startsWith("res://")) : [];
60644
60853
  }
60645
60854
 
@@ -60648,7 +60857,7 @@ init_suite_judge();
60648
60857
  init_suite_plan();
60649
60858
 
60650
60859
  // src/version.ts
60651
- import { readFileSync as readFileSync23 } from "node:fs";
60860
+ import { readFileSync as readFileSync25 } from "node:fs";
60652
60861
  import { dirname as dirname12, join as join27 } from "node:path";
60653
60862
  import { fileURLToPath as fileURLToPath3 } from "node:url";
60654
60863
  function getLocalVersion() {
@@ -60659,7 +60868,7 @@ function getLocalVersion() {
60659
60868
  ];
60660
60869
  for (const packagePath of packageCandidates) {
60661
60870
  try {
60662
- const value = JSON.parse(readFileSync23(packagePath, "utf-8"));
60871
+ const value = JSON.parse(readFileSync25(packagePath, "utf-8"));
60663
60872
  if (typeof value === "object" && value !== null && "name" in value && value.name === "gdharness" && "version" in value && typeof value.version === "string") {
60664
60873
  return value.version;
60665
60874
  }
@@ -60928,10 +61137,10 @@ async function runTestCommand(options, godotPath) {
60928
61137
  const suitesBegan = Date.now();
60929
61138
  const always = [
60930
61139
  getLocalVersion(),
60931
- readFileSync24(shippedListedRunner(), "utf8"),
61140
+ readFileSync26(shippedListedRunner(), "utf8"),
60932
61141
  engineSaid(godotPath),
60933
61142
  ...options.reachAlso.map((path) => `${path}
60934
- ${existsSync24(path) ? readFileSync24(path, "latin1") : "missing"}`)
61143
+ ${existsSync24(path) ? readFileSync26(path, "latin1") : "missing"}`)
60935
61144
  ];
60936
61145
  const everySuite = suites;
60937
61146
  if (options.changedOnly) {
@@ -60970,7 +61179,7 @@ ${existsSync24(path) ? readFileSync24(path, "latin1") : "missing"}`)
60970
61179
  if (memory.unread !== undefined) {
60971
61180
  console.log(`Windows did not say how much memory it can still commit (${memory.unread}), so engines are sized by the physical memory free.`);
60972
61181
  }
60973
- const room = options.cores === null ? roomFor(options.engines, availableParallelism4(), memory.bytes, memory.said) : roomFor(options.engines, options.cores, memory.bytes, memory.said, `--cores holds it to ${plural(options.cores, "processor")}`);
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")}`);
60974
61183
  if (options.cores !== null && process14.platform === "darwin") {
60975
61184
  console.log("macOS offers no way to hold a process to some processors, so --cores holds only the number of engines here.");
60976
61185
  }
@@ -61061,7 +61270,7 @@ function roomSaid(engines, lanes, unheld, held, asked) {
61061
61270
  function readPassed(file) {
61062
61271
  let parsed;
61063
61272
  try {
61064
- parsed = JSON.parse(readFileSync24(file, "utf8"));
61273
+ parsed = JSON.parse(readFileSync26(file, "utf8"));
61065
61274
  } catch {
61066
61275
  return {};
61067
61276
  }
@@ -61177,7 +61386,7 @@ async function compileCheck(launch, suites, handed) {
61177
61386
  } finally {
61178
61387
  launch.slots.release(lock);
61179
61388
  }
61180
- return { faults: judgeCompile(readRun(readFileSync24(log, "utf8")), end), log };
61389
+ return { faults: judgeCompile(readRun(readFileSync26(log, "utf8")), end), log };
61181
61390
  }
61182
61391
  function printCompiled(compiled, logs) {
61183
61392
  if (compiled.faults.length === 0) {