gdharness 1.3.25 → 1.3.27

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
@@ -10915,6 +10915,7 @@ function readRun(printed) {
10915
10915
  executed,
10916
10916
  unloadable,
10917
10917
  stoppedIn,
10918
+ running: last === null ? null : { suite: last.path, during },
10918
10919
  leftOut,
10919
10920
  engineVersion,
10920
10921
  orphansLeft
@@ -11395,7 +11396,7 @@ async function inTurns(items, at, run) {
11395
11396
  function heldToCores(cores, command, args, platform = process6.platform) {
11396
11397
  return cores === null || platform !== "linux" ? { command, args: [...args] } : { command: "taskset", args: ["-c", `0-${String(cores - 1)}`, command, ...args] };
11397
11398
  }
11398
- async function watchedEngine(launch, args, directory, log, silenceSeconds) {
11399
+ async function watchedEngine(launch, args, directory, log, silenceSeconds, silenceIn) {
11399
11400
  const user = join7(directory, "user");
11400
11401
  const env = { ...process6.env, APPDATA: user, XDG_DATA_HOME: user };
11401
11402
  const output = openSync2(log, "w");
@@ -11468,6 +11469,7 @@ async function watchedEngine(launch, args, directory, log, silenceSeconds) {
11468
11469
  const started = Date.now();
11469
11470
  let lastGrowth = started;
11470
11471
  let text = "";
11472
+ let allowed = { size: -1, seconds: silenceSeconds };
11471
11473
  while (!finished.now) {
11472
11474
  await delay2(LOOK_MS);
11473
11475
  const deadline = launch.deadlineSeconds;
@@ -11488,9 +11490,18 @@ async function watchedEngine(launch, args, directory, log, silenceSeconds) {
11488
11490
  stop();
11489
11491
  }
11490
11492
  } else if (ended === null && Date.now() - lastGrowth > silenceSeconds * 1000) {
11491
- const stoppedIn = readRun(text).stoppedIn;
11493
+ if (allowed.size !== size) {
11494
+ allowed = {
11495
+ size,
11496
+ seconds: silenceIn === undefined ? silenceSeconds : Math.max(silenceSeconds, silenceIn(readRun(text)))
11497
+ };
11498
+ }
11499
+ if (Date.now() - lastGrowth <= allowed.seconds * 1000) {
11500
+ continue;
11501
+ }
11502
+ const { stoppedIn } = readRun(text);
11492
11503
  const unstarted = helper !== null && !existsSync5(helper.pid) ? `, and it never started ${helper.how}: ${helperStep(helper.step)}` : "";
11493
- ended = `the engine printed nothing for ${String(silenceSeconds)} s${stoppedIn === null ? "" : ` while running ${stoppedIn}`}, so it was ended${unstarted}`;
11504
+ ended = `the engine printed nothing for ${String(allowed.seconds)} s${stoppedIn === null ? "" : ` while running ${stoppedIn}`}, so it was ended${unstarted}`;
11494
11505
  stop();
11495
11506
  }
11496
11507
  }
@@ -11591,8 +11602,54 @@ var init_call_signal = __esm(() => {
11591
11602
  current = new AsyncLocalStorage;
11592
11603
  });
11593
11604
 
11605
+ // src/whole-file.ts
11606
+ import { renameSync, rmSync as rmSync5, writeFileSync as writeFileSync5 } from "node:fs";
11607
+ function writeWhole(path, text) {
11608
+ const partial = `${path}.${process.pid}.partial`;
11609
+ try {
11610
+ writeFileSync5(partial, text, "utf8");
11611
+ } catch {
11612
+ return false;
11613
+ }
11614
+ const until = Date.now() + HELD_FILE_MS;
11615
+ for (;; ) {
11616
+ try {
11617
+ renameSync(partial, path);
11618
+ return true;
11619
+ } catch (error) {
11620
+ const code = error.code ?? "";
11621
+ if (!HELD_BY_A_READER.has(code) || Date.now() >= until) {
11622
+ try {
11623
+ rmSync5(partial, { force: true });
11624
+ } catch {}
11625
+ return false;
11626
+ }
11627
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, HELD_FILE_RETRY_MS);
11628
+ }
11629
+ }
11630
+ }
11631
+ function removeWhole(path) {
11632
+ const until = Date.now() + HELD_FILE_MS;
11633
+ for (;; ) {
11634
+ try {
11635
+ rmSync5(path, { force: true });
11636
+ return true;
11637
+ } catch (error) {
11638
+ const code = error.code ?? "";
11639
+ if (!HELD_BY_A_READER.has(code) || Date.now() >= until) {
11640
+ return false;
11641
+ }
11642
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, HELD_FILE_RETRY_MS);
11643
+ }
11644
+ }
11645
+ }
11646
+ var HELD_FILE_MS = 1000, HELD_FILE_RETRY_MS = 10, HELD_BY_A_READER;
11647
+ var init_whole_file = __esm(() => {
11648
+ HELD_BY_A_READER = new Set(["EPERM", "EACCES", "EBUSY"]);
11649
+ });
11650
+
11594
11651
  // src/engine-slots.ts
11595
- import { closeSync as closeSync3, mkdirSync as mkdirSync3, openSync as openSync3, readFileSync as readFileSync7, rmSync as rmSync5, statSync as statSync6, writeSync as writeSync2 } from "node:fs";
11652
+ import { closeSync as closeSync3, mkdirSync as mkdirSync3, openSync as openSync3, readFileSync as readFileSync7, rmSync as rmSync6, statSync as statSync6, writeSync as writeSync2 } from "node:fs";
11596
11653
  import { availableParallelism as availableParallelism2, homedir as homedir2 } from "node:os";
11597
11654
  import { join as join8, resolve as resolve4 } from "node:path";
11598
11655
  import process7 from "node:process";
@@ -11657,6 +11714,7 @@ async function ownStart() {
11657
11714
  class EngineSlots {
11658
11715
  starts = new Map;
11659
11716
  held = new Set;
11717
+ marks = new Set;
11660
11718
  saidAt = Number.NEGATIVE_INFINITY;
11661
11719
  directory;
11662
11720
  count;
@@ -11672,38 +11730,65 @@ class EngineSlots {
11672
11730
  mkdirSync3(this.directory, { recursive: true });
11673
11731
  const began = Date.now();
11674
11732
  let said = Number.NEGATIVE_INFINITY;
11675
- for (;; ) {
11676
- signal?.throwIfAborted();
11677
- for (let slot = 0;slot < this.count; slot += 1) {
11678
- const lock = join8(this.directory, `${String(slot)}.lock`);
11679
- if (this.made(lock) || await this.takenOver(lock)) {
11680
- this.held.add(lock);
11681
- return lock;
11733
+ let mark;
11734
+ try {
11735
+ for (;; ) {
11736
+ signal?.throwIfAborted();
11737
+ for (let slot = 0;slot < this.count; slot += 1) {
11738
+ const lock = join8(this.directory, `${String(slot)}.lock`);
11739
+ if (this.made(lock) || await this.takenOver(lock)) {
11740
+ this.held.add(lock);
11741
+ return lock;
11742
+ }
11682
11743
  }
11683
- }
11684
- const now = Date.now();
11685
- if (waiting !== undefined) {
11686
- if (now - said >= WAIT_SAID_MS) {
11687
- said = now;
11688
- waiting(now - began);
11744
+ mark ??= this.waitMarked();
11745
+ const now = Date.now();
11746
+ if (waiting !== undefined) {
11747
+ if (now - said >= WAIT_SAID_MS) {
11748
+ said = now;
11749
+ waiting(now - began);
11750
+ }
11751
+ } else if (this.say !== undefined && this.held.size === 0 && now - began >= COMMAND_WAIT_SAID_MS && now - this.saidAt >= WAIT_SAID_MS) {
11752
+ this.saidAt = now;
11753
+ this.say(slotWaitSaid(now - began, this.count, this.directory));
11689
11754
  }
11690
- } else if (this.say !== undefined && this.held.size === 0 && now - began >= COMMAND_WAIT_SAID_MS && now - this.saidAt >= WAIT_SAID_MS) {
11691
- this.saidAt = now;
11692
- this.say(slotWaitSaid(now - began, this.count, this.directory));
11755
+ await delay3(SLOT_WAIT_MS, undefined, signal === undefined ? {} : { signal });
11756
+ }
11757
+ } finally {
11758
+ if (mark !== undefined && this.marks.delete(mark)) {
11759
+ removeWhole(mark);
11693
11760
  }
11694
- await delay3(SLOT_WAIT_MS, undefined, signal === undefined ? {} : { signal });
11695
11761
  }
11696
11762
  }
11763
+ waitMarked() {
11764
+ const marks = join8(this.directory, WAITING_FOLDER);
11765
+ waitsMarked += 1;
11766
+ const mark = join8(marks, `${String(this.holder.pid)}-${String(waitsMarked)}.json`);
11767
+ try {
11768
+ mkdirSync3(marks, { recursive: true });
11769
+ } catch {
11770
+ return;
11771
+ }
11772
+ if (!this.made(mark)) {
11773
+ return;
11774
+ }
11775
+ this.marks.add(mark);
11776
+ return mark;
11777
+ }
11697
11778
  releaseAll() {
11698
11779
  for (const lock of this.held) {
11699
11780
  this.release(lock);
11700
11781
  }
11782
+ for (const mark of this.marks) {
11783
+ this.marks.delete(mark);
11784
+ removeWhole(mark);
11785
+ }
11701
11786
  }
11702
11787
  release(lock) {
11703
11788
  this.held.delete(lock);
11704
11789
  try {
11705
11790
  if (holderOf(readFileSync7(lock, "utf8"))?.pid === this.holder.pid) {
11706
- rmSync5(lock, { force: true });
11791
+ removeWhole(lock);
11707
11792
  }
11708
11793
  } catch {}
11709
11794
  }
@@ -11729,7 +11814,7 @@ class EngineSlots {
11729
11814
  if (!this.made(steal)) {
11730
11815
  try {
11731
11816
  if (Date.now() - statSync6(steal).mtimeMs > UNWRITTEN_MS) {
11732
- rmSync5(steal, { force: true });
11817
+ rmSync6(steal, { force: true });
11733
11818
  }
11734
11819
  } catch {}
11735
11820
  return false;
@@ -11739,13 +11824,13 @@ class EngineSlots {
11739
11824
  return false;
11740
11825
  }
11741
11826
  try {
11742
- rmSync5(lock, { force: true });
11827
+ rmSync6(lock, { force: true });
11743
11828
  } catch {
11744
11829
  return false;
11745
11830
  }
11746
11831
  return this.made(lock);
11747
11832
  } finally {
11748
- rmSync5(steal, { force: true });
11833
+ rmSync6(steal, { force: true });
11749
11834
  }
11750
11835
  }
11751
11836
  async free(lock) {
@@ -11808,12 +11893,13 @@ async function inASlot(body) {
11808
11893
  held.release();
11809
11894
  }
11810
11895
  }
11811
- var SLOTS_VARIABLE = "GODOT_ENGINE_SLOTS", SLOT_COUNT_VARIABLE = "GODOT_ENGINE_SLOT_COUNT", PROCESSORS_A_SLOT = 5, START_TOLERANCE_MS = 2000, UNWRITTEN_MS = 1e4, SLOT_WAIT_MS = 50, WAIT_SAID_MS = 20000, COMMAND_WAIT_SAID_MS = 2000, START_READ_MS = 1e4, ours, saidTo;
11896
+ var SLOTS_VARIABLE = "GODOT_ENGINE_SLOTS", SLOT_COUNT_VARIABLE = "GODOT_ENGINE_SLOT_COUNT", PROCESSORS_A_SLOT = 5, START_TOLERANCE_MS = 2000, UNWRITTEN_MS = 1e4, SLOT_WAIT_MS = 50, WAIT_SAID_MS = 20000, COMMAND_WAIT_SAID_MS = 2000, START_READ_MS = 1e4, WAITING_FOLDER = "waiting", waitsMarked = 0, ours, saidTo;
11812
11897
  var init_engine_slots = __esm(() => {
11813
11898
  init_alive();
11814
11899
  init_call_signal();
11815
11900
  init_engine_launch();
11816
11901
  init_process_children();
11902
+ init_whole_file();
11817
11903
  });
11818
11904
 
11819
11905
  // src/detection.ts
@@ -13061,9 +13147,9 @@ import {
13061
13147
  mkdirSync as mkdirSync4,
13062
13148
  readdirSync as readdirSync8,
13063
13149
  readFileSync as readFileSync10,
13064
- renameSync,
13150
+ renameSync as renameSync2,
13065
13151
  unlinkSync,
13066
- writeFileSync as writeFileSync5
13152
+ writeFileSync as writeFileSync6
13067
13153
  } from "node:fs";
13068
13154
  import { basename as basename6, dirname as dirname6, isAbsolute as isAbsolute6, join as join13 } from "node:path";
13069
13155
  function freeLibraryCopies(projectPath, platform = process.platform) {
@@ -13078,7 +13164,7 @@ function freeLibraryCopies(projectPath, platform = process.platform) {
13078
13164
  if (existsSync11(join13(folder, copy))) {
13079
13165
  const aside = join13(folder, `${copy}.aside-${process.pid}-${Date.now()}`);
13080
13166
  try {
13081
- renameSync(join13(folder, copy), aside);
13167
+ renameSync2(join13(folder, copy), aside);
13082
13168
  setAside.push(aside);
13083
13169
  } catch {}
13084
13170
  }
@@ -13132,7 +13218,7 @@ function seedExtensionList(projectPath) {
13132
13218
  }
13133
13219
  found.sort();
13134
13220
  mkdirSync4(dirname6(list), { recursive: true });
13135
- writeFileSync5(list, `${found.join(`
13221
+ writeFileSync6(list, `${found.join(`
13136
13222
  `)}
13137
13223
  `);
13138
13224
  return found;
@@ -13185,7 +13271,7 @@ var init_library_copies = () => {};
13185
13271
 
13186
13272
  // src/reimport.ts
13187
13273
  import { createHash as createHash3 } from "node:crypto";
13188
- import { existsSync as existsSync12, readFileSync as readFileSync11, rmSync as rmSync6, statSync as statSync11, utimesSync, writeFileSync as writeFileSync6 } from "node:fs";
13274
+ import { existsSync as existsSync12, readFileSync as readFileSync11, rmSync as rmSync7, statSync as statSync11, utimesSync, writeFileSync as writeFileSync7 } from "node:fs";
13189
13275
  import { basename as basename7, join as join14 } from "node:path";
13190
13276
  function forceNextImport(projectPath, resourcePath) {
13191
13277
  const relative = resourcePath.replace(/^res:\/\//, "");
@@ -13194,9 +13280,9 @@ function forceNextImport(projectPath, resourcePath) {
13194
13280
  return;
13195
13281
  }
13196
13282
  const { atime, mtimeMs } = statSync11(sidecar);
13197
- writeFileSync6(sidecar, readFileSync11(sidecar, "utf8").replace(/^valid=false\r?\n/m, ""));
13283
+ writeFileSync7(sidecar, readFileSync11(sidecar, "utf8").replace(/^valid=false\r?\n/m, ""));
13198
13284
  utimesSync(sidecar, atime, new Date(mtimeMs + 2000));
13199
- rmSync6(importRecord(projectPath, resourcePath), { force: true });
13285
+ rmSync7(importRecord(projectPath, resourcePath), { force: true });
13200
13286
  }
13201
13287
  function importRecord(projectPath, resourcePath) {
13202
13288
  const digest = createHash3("md5").update(resourcePath).digest("hex");
@@ -13205,7 +13291,7 @@ function importRecord(projectPath, resourcePath) {
13205
13291
  var init_reimport = () => {};
13206
13292
 
13207
13293
  // src/scratch.ts
13208
- import { existsSync as existsSync13, mkdtempSync as mkdtempSync2, readdirSync as readdirSync9, rmSync as rmSync7 } from "node:fs";
13294
+ import { existsSync as existsSync13, mkdtempSync as mkdtempSync2, readdirSync as readdirSync9, rmSync as rmSync8 } from "node:fs";
13209
13295
  import { tmpdir as tmpdir3 } from "node:os";
13210
13296
  import { join as join15 } from "node:path";
13211
13297
  import process10 from "node:process";
@@ -13252,7 +13338,7 @@ function discard(...paths) {
13252
13338
  return left;
13253
13339
  }
13254
13340
  function remove(path) {
13255
- rmSync7(path, SWEPT);
13341
+ rmSync8(path, SWEPT);
13256
13342
  }
13257
13343
  function tryAgain(path, attempt) {
13258
13344
  if (attempt === 0) {
@@ -13420,7 +13506,7 @@ var init_script_origins = __esm(() => {
13420
13506
  });
13421
13507
 
13422
13508
  // src/headless.ts
13423
- import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "node:fs";
13509
+ import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
13424
13510
  import { dirname as dirname7, join as join17 } from "node:path";
13425
13511
  function snakeCased(params) {
13426
13512
  const result = emptyRecord();
@@ -13615,7 +13701,7 @@ async function operationOutcome(engine, operation, params, projectPath) {
13615
13701
  const paramsDir = scratchDirectory("params");
13616
13702
  const paramsFile = join17(paramsDir, `${operation}.json`);
13617
13703
  const answerFile = join17(paramsDir, "answer.json");
13618
- writeFileSync7(paramsFile, JSON.stringify(snakeCased(params)), "utf8");
13704
+ writeFileSync8(paramsFile, JSON.stringify(snakeCased(params)), "utf8");
13619
13705
  const args = [
13620
13706
  "--headless",
13621
13707
  ...engine.editor === true ? ["--editor"] : [],
@@ -13736,7 +13822,7 @@ var init_headless = __esm(() => {
13736
13822
  });
13737
13823
 
13738
13824
  // src/update-check.ts
13739
- import { existsSync as existsSync15, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "node:fs";
13825
+ import { existsSync as existsSync15, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "node:fs";
13740
13826
  import { homedir as homedir5, tmpdir as tmpdir4 } from "node:os";
13741
13827
  import { join as join18 } from "node:path";
13742
13828
  function packageUrl(root) {
@@ -13798,7 +13884,7 @@ function readCache(path) {
13798
13884
  }
13799
13885
  function writeCache(path, entry) {
13800
13886
  try {
13801
- writeFileSync8(path, JSON.stringify(entry), { encoding: "utf8", mode: 384 });
13887
+ writeFileSync9(path, JSON.stringify(entry), { encoding: "utf8", mode: 384 });
13802
13888
  } catch {}
13803
13889
  }
13804
13890
  function parts(version) {
@@ -15453,9 +15539,9 @@ import {
15453
15539
  readdirSync as readdirSync11,
15454
15540
  readFileSync as readFileSync17,
15455
15541
  rmdirSync,
15456
- rmSync as rmSync8,
15542
+ rmSync as rmSync9,
15457
15543
  statSync as statSync12,
15458
- writeFileSync as writeFileSync9
15544
+ writeFileSync as writeFileSync10
15459
15545
  } from "node:fs";
15460
15546
  import { dirname as dirname9, join as join21 } from "node:path";
15461
15547
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -15543,7 +15629,7 @@ function writeLoader(projectPath) {
15543
15629
  }
15544
15630
  const copy = join21(projectPath, ...RUNTIME_AUTOLOAD.path.split("/"));
15545
15631
  mkdirSync6(dirname9(copy), { recursive: true });
15546
- writeFileSync9(copy, readFileSync17(shippedLoader()));
15632
+ writeFileSync10(copy, readFileSync17(shippedLoader()));
15547
15633
  return true;
15548
15634
  }
15549
15635
  function removeLoader(projectPath) {
@@ -15551,8 +15637,8 @@ function removeLoader(projectPath) {
15551
15637
  if (!existsSync18(copy)) {
15552
15638
  return false;
15553
15639
  }
15554
- rmSync8(copy);
15555
- rmSync8(`${copy}.uid`, { force: true });
15640
+ rmSync9(copy);
15641
+ rmSync9(`${copy}.uid`, { force: true });
15556
15642
  const folder = dirname9(copy);
15557
15643
  if (readdirSync11(folder).length === 0) {
15558
15644
  rmdirSync(folder);
@@ -15584,16 +15670,16 @@ function installAddons(projectPath, from = shippedAddonsDirectory()) {
15584
15670
  }
15585
15671
  const target = join21(projectPath, "addons", name);
15586
15672
  const replaced = existsSync18(target);
15587
- rmSync8(target, { recursive: true, force: true });
15673
+ rmSync9(target, { recursive: true, force: true });
15588
15674
  mkdirSync6(dirname9(target), { recursive: true });
15589
15675
  cpSync(source, target, { recursive: true });
15590
- writeFileSync9(join21(target, VERSION_MARKER), `${SERVER_VERSION}
15676
+ writeFileSync10(join21(target, VERSION_MARKER), `${SERVER_VERSION}
15591
15677
  `);
15592
15678
  installed.push({ name, path: target, replaced });
15593
15679
  }
15594
- writeFileSync9(join21(projectPath, "addons", ADDONS[0], DIGEST_MARKER), `${editorAddonDigest(from)}
15680
+ writeFileSync10(join21(projectPath, "addons", ADDONS[0], DIGEST_MARKER), `${editorAddonDigest(from)}
15595
15681
  `);
15596
- writeFileSync9(join21(projectPath, "addons", RUNTIME_ADDON, DIGEST_MARKER), `${runtimeAddonDigest(from)}
15682
+ writeFileSync10(join21(projectPath, "addons", RUNTIME_ADDON, DIGEST_MARKER), `${runtimeAddonDigest(from)}
15597
15683
  `);
15598
15684
  return installed;
15599
15685
  }
@@ -15610,7 +15696,7 @@ function removeAddons(projectPath) {
15610
15696
  for (const name of ADDONS) {
15611
15697
  const target = join21(projectPath, "addons", name);
15612
15698
  if (existsSync18(target)) {
15613
- rmSync8(target, { recursive: true, force: true });
15699
+ rmSync9(target, { recursive: true, force: true });
15614
15700
  removed.push(target);
15615
15701
  }
15616
15702
  }
@@ -18248,37 +18334,6 @@ var init_tool_reference = __esm(() => {
18248
18334
  init_tool_definitions();
18249
18335
  });
18250
18336
 
18251
- // src/whole-file.ts
18252
- import { renameSync as renameSync2, rmSync as rmSync11, writeFileSync as writeFileSync11 } from "node:fs";
18253
- function writeWhole(path, text) {
18254
- const partial = `${path}.${process.pid}.partial`;
18255
- try {
18256
- writeFileSync11(partial, text, "utf8");
18257
- } catch {
18258
- return false;
18259
- }
18260
- const until = Date.now() + HELD_FILE_MS;
18261
- for (;; ) {
18262
- try {
18263
- renameSync2(partial, path);
18264
- return true;
18265
- } catch (error) {
18266
- const code = error.code ?? "";
18267
- if (!HELD_BY_A_READER.has(code) || Date.now() >= until) {
18268
- try {
18269
- rmSync11(partial, { force: true });
18270
- } catch {}
18271
- return false;
18272
- }
18273
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, HELD_FILE_RETRY_MS);
18274
- }
18275
- }
18276
- }
18277
- var HELD_FILE_MS = 1000, HELD_FILE_RETRY_MS = 10, HELD_BY_A_READER;
18278
- var init_whole_file = __esm(() => {
18279
- HELD_BY_A_READER = new Set(["EPERM", "EACCES", "EBUSY"]);
18280
- });
18281
-
18282
18337
  // src/suite-plan.ts
18283
18338
  import { existsSync as existsSync22, mkdirSync as mkdirSync9, readFileSync as readFileSync20 } from "node:fs";
18284
18339
  import { dirname as dirname11, join as join25, posix as posix3 } from "node:path";
@@ -57543,7 +57598,7 @@ init_setup();
57543
57598
  init_setup();
57544
57599
  init_tool_definitions();
57545
57600
  init_tool_reference();
57546
- import { existsSync as existsSync19, mkdirSync as mkdirSync7, readdirSync as readdirSync12, rmSync as rmSync9, writeFileSync as writeFileSync10 } from "node:fs";
57601
+ import { existsSync as existsSync19, mkdirSync as mkdirSync7, readdirSync as readdirSync12, rmSync as rmSync10, writeFileSync as writeFileSync11 } from "node:fs";
57547
57602
  import { basename as basename8, dirname as dirname10, join as join22 } from "node:path";
57548
57603
  var SKILL_NAME = "gdharness";
57549
57604
  var SHARED_SKILLS = join22(".agents", "skills");
@@ -57816,7 +57871,7 @@ function removeSkill(directories, projectPath) {
57816
57871
  const removed = [];
57817
57872
  for (const directory of directories) {
57818
57873
  if (existsSync19(directory)) {
57819
- rmSync9(directory, { recursive: true, force: true });
57874
+ rmSync10(directory, { recursive: true, force: true });
57820
57875
  pruneEmpty(dirname10(directory), projectPath);
57821
57876
  removed.push(directory);
57822
57877
  }
@@ -57830,7 +57885,7 @@ function pruneEmpty(directory, projectPath) {
57830
57885
  if (readdirSync12(path).length > 0) {
57831
57886
  return;
57832
57887
  }
57833
- rmSync9(path, { recursive: true, force: true });
57888
+ rmSync10(path, { recursive: true, force: true });
57834
57889
  path = dirname10(path);
57835
57890
  }
57836
57891
  }
@@ -57838,11 +57893,11 @@ function writeSkill(directories, version) {
57838
57893
  const files = skillFiles(version);
57839
57894
  return directories.map((directory) => {
57840
57895
  const replaced = existsSync19(directory);
57841
- rmSync9(directory, { recursive: true, force: true });
57896
+ rmSync10(directory, { recursive: true, force: true });
57842
57897
  for (const [name, contents] of files) {
57843
57898
  const path = join22(directory, name);
57844
57899
  mkdirSync7(dirname10(path), { recursive: true });
57845
- writeFileSync10(path, contents, "utf8");
57900
+ writeFileSync11(path, contents, "utf8");
57846
57901
  }
57847
57902
  return { path: directory, replaced };
57848
57903
  });
@@ -57853,7 +57908,7 @@ init_engine_launch();
57853
57908
  init_engine_slots();
57854
57909
  init_setup();
57855
57910
  init_suite_judge();
57856
- import { existsSync as existsSync20, mkdirSync as mkdirSync8, readFileSync as readFileSync18, rmSync as rmSync10 } from "node:fs";
57911
+ import { existsSync as existsSync20, mkdirSync as mkdirSync8, readFileSync as readFileSync18, rmSync as rmSync11 } from "node:fs";
57857
57912
  import { availableParallelism as availableParallelism3 } from "node:os";
57858
57913
  import { join as join23, resolve as resolve9 } from "node:path";
57859
57914
  import process13 from "node:process";
@@ -58063,7 +58118,7 @@ async function runSpreadCommand(options, godotPath) {
58063
58118
  const longest = Math.max(0, ...left.map((worker) => worker.seconds));
58064
58119
  console.log("");
58065
58120
  console.log(`Spread: ${plural(runs, "run")} in ${plural((arms[0] ?? []).length, "arm")} over ${plural(workers, "worker")}, ${((Date.now() - startedAt) / 1000).toFixed(1)} s; the longest worker took ${longest.toFixed(1)} s.`);
58066
- rmSync10(runDirectory, { recursive: true, force: true });
58121
+ rmSync11(runDirectory, { recursive: true, force: true });
58067
58122
  return 0;
58068
58123
  } finally {
58069
58124
  process13.off("SIGINT", interrupted);
@@ -58322,7 +58377,23 @@ function getLocalVersion() {
58322
58377
 
58323
58378
  // src/suite-run.ts
58324
58379
  var SLOWEST_NAMED = 5;
58325
- var SILENCE_TIMES_SLOWEST = 4;
58380
+ var SILENCE_TIMES_TAKEN = 4;
58381
+ function silenceWhile(running, times, floorSeconds) {
58382
+ const time = running === null ? undefined : times[running.suite];
58383
+ if (running === null || time === undefined) {
58384
+ return floorSeconds;
58385
+ }
58386
+ let taken;
58387
+ if (running.during === null || running.during === "before") {
58388
+ const cases = Object.values(time.cases).reduce((sum, seconds) => sum + seconds, 0);
58389
+ taken = Math.max(0, time.seconds - cases);
58390
+ } else {
58391
+ const func = funcOf(running.during);
58392
+ const row = rowOf(running.during);
58393
+ taken = (row === null ? undefined : time.rows?.[func]?.[row]) ?? time.cases[func];
58394
+ }
58395
+ return Math.max(floorSeconds, SILENCE_TIMES_TAKEN * (taken ?? 0));
58396
+ }
58326
58397
  var VALUED2 = new Set([
58327
58398
  "--engines",
58328
58399
  "--slots",
@@ -58616,12 +58687,12 @@ ${existsSync23(path) ? readFileSync22(path, "latin1") : "missing"}`)
58616
58687
  console.log(`Dealt out row by row, since ${byRows.length === 1 ? "it" : "each"} took more than ${String(SPLIT_PAST_SECONDS)} s last time: ${named(byRows)}.`);
58617
58688
  }
58618
58689
  const lanes = [...new Set(plans.map((plan) => plan.lane))].map((lane) => plans.flatMap((plan, index) => plan.lane === lane ? [{ plan, index }] : []));
58619
- let ran = (await inTurns(lanes, room.engines, (lane) => runLane(launch, lane, units))).flat().sort((a, b) => a.index - b.index);
58690
+ let ran = (await inTurns(lanes, room.engines, (lane) => runLane(launch, lane, times))).flat().sort((a, b) => a.index - b.index);
58620
58691
  if (ran.some((engine) => engine.verdict.starved) && ran.some((engine) => !engine.verdict.passed)) {
58621
58692
  console.log("An engine ran out of memory, so every engine that failed runs again, one at a time.");
58622
58693
  const again = [];
58623
58694
  for (const engine of ran) {
58624
- again.push(engine.verdict.passed ? engine : await runEngine2(launch, engine.plan, engine.index, units, "again"));
58695
+ again.push(engine.verdict.passed ? engine : await runEngine2(launch, engine.plan, engine.index, times, "again"));
58625
58696
  }
58626
58697
  ran = again;
58627
58698
  }
@@ -58712,19 +58783,19 @@ async function importProject(launch) {
58712
58783
  launch.slots.release(lock);
58713
58784
  }
58714
58785
  }
58715
- async function runLane(launch, lane, units) {
58786
+ async function runLane(launch, lane, times) {
58716
58787
  const lock = await launch.slots.take();
58717
58788
  try {
58718
58789
  const ran = [];
58719
58790
  for (const { plan, index } of lane) {
58720
- ran.push(await runEngine2(launch, plan, index, units, "", lock));
58791
+ ran.push(await runEngine2(launch, plan, index, times, "", lock));
58721
58792
  }
58722
58793
  return ran;
58723
58794
  } finally {
58724
58795
  launch.slots.release(lock);
58725
58796
  }
58726
58797
  }
58727
- async function runEngine2(launch, plan, index, units, again = "", slot = null) {
58798
+ async function runEngine2(launch, plan, index, times, again = "", slot = null) {
58728
58799
  const directory = join27(launch.runDirectory, `engine-${String(index)}${again === "" ? "" : `-${again}`}`);
58729
58800
  mkdirSync10(join27(directory, "user"), { recursive: true });
58730
58801
  const suitesFile = join27(directory, "suites.txt");
@@ -58772,15 +58843,12 @@ async function runEngine2(launch, plan, index, units, again = "", slot = null) {
58772
58843
  "--expected-out",
58773
58844
  expectedFile
58774
58845
  ];
58775
- const held = new Set(plan.suites.map((suite) => suite.path));
58776
- const slowest = Math.max(0, ...units.filter((unit) => held.has(unit.suite)).map((unit) => unit.cost));
58777
- const silence = Math.max(launch.silenceFloorSeconds, SILENCE_TIMES_SLOWEST * slowest);
58778
58846
  const log = join27(directory, "engine.log");
58779
58847
  const lock = slot ?? await launch.slots.take();
58780
58848
  const began = Date.now();
58781
58849
  let end;
58782
58850
  try {
58783
- end = await watchedEngine(launch, args, directory, log, silence);
58851
+ end = await watchedEngine(launch, args, directory, log, launch.silenceFloorSeconds, (printed) => silenceWhile(printed.running, times, launch.silenceFloorSeconds));
58784
58852
  } finally {
58785
58853
  if (slot === null) {
58786
58854
  launch.slots.release(lock);
package/build/keeper.js CHANGED
@@ -8482,6 +8482,36 @@ function commandWords(command) {
8482
8482
  return words;
8483
8483
  }
8484
8484
 
8485
+ // src/whole-file.ts
8486
+ import { renameSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
8487
+ var HELD_FILE_MS = 1000;
8488
+ var HELD_FILE_RETRY_MS = 10;
8489
+ var HELD_BY_A_READER = new Set(["EPERM", "EACCES", "EBUSY"]);
8490
+ function writeWhole(path, text) {
8491
+ const partial = `${path}.${process.pid}.partial`;
8492
+ try {
8493
+ writeFileSync2(partial, text, "utf8");
8494
+ } catch {
8495
+ return false;
8496
+ }
8497
+ const until = Date.now() + HELD_FILE_MS;
8498
+ for (;; ) {
8499
+ try {
8500
+ renameSync(partial, path);
8501
+ return true;
8502
+ } catch (error) {
8503
+ const code = error.code ?? "";
8504
+ if (!HELD_BY_A_READER.has(code) || Date.now() >= until) {
8505
+ try {
8506
+ rmSync2(partial, { force: true });
8507
+ } catch {}
8508
+ return false;
8509
+ }
8510
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, HELD_FILE_RETRY_MS);
8511
+ }
8512
+ }
8513
+ }
8514
+
8485
8515
  // src/game-log.ts
8486
8516
  var COLOUR_CODE = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g");
8487
8517
  var ADMITTED = {
@@ -8589,7 +8619,7 @@ var IMPORTABLE = new Set(IMPORTABLE_EXTENSIONS);
8589
8619
  var hashes = new Map;
8590
8620
 
8591
8621
  // src/scratch.ts
8592
- import { existsSync as existsSync2, mkdtempSync as mkdtempSync2, readdirSync, rmSync as rmSync2 } from "node:fs";
8622
+ import { existsSync as existsSync2, mkdtempSync as mkdtempSync2, readdirSync, rmSync as rmSync3 } from "node:fs";
8593
8623
  import { tmpdir as tmpdir2 } from "node:os";
8594
8624
  import { join as join4 } from "node:path";
8595
8625
  import process4 from "node:process";
@@ -8622,7 +8652,7 @@ function discard(...paths) {
8622
8652
  return left;
8623
8653
  }
8624
8654
  function remove(path) {
8625
- rmSync2(path, SWEPT);
8655
+ rmSync3(path, SWEPT);
8626
8656
  }
8627
8657
  function tryAgain(path, attempt) {
8628
8658
  if (attempt === 0) {
@@ -9453,7 +9483,7 @@ class GameDebugger {
9453
9483
 
9454
9484
  // src/keeper-channel.ts
9455
9485
  import { randomUUID } from "node:crypto";
9456
- import { mkdtempSync as mkdtempSync3, rmSync as rmSync3 } from "node:fs";
9486
+ import { mkdtempSync as mkdtempSync3, rmSync as rmSync4 } from "node:fs";
9457
9487
  import { connect, createServer as createServer2 } from "node:net";
9458
9488
  import { tmpdir as tmpdir3 } from "node:os";
9459
9489
  import { join as join7 } from "node:path";
@@ -9521,13 +9551,13 @@ async function listenForTheServer(end, debug) {
9521
9551
  close: () => {
9522
9552
  server.close();
9523
9553
  if (made !== null) {
9524
- rmSync3(made, { recursive: true, force: true });
9554
+ rmSync4(made, { recursive: true, force: true });
9525
9555
  }
9526
9556
  }
9527
9557
  };
9528
9558
  } catch {
9529
9559
  if (directory !== null) {
9530
- rmSync3(directory, { recursive: true, force: true });
9560
+ rmSync4(directory, { recursive: true, force: true });
9531
9561
  }
9532
9562
  return null;
9533
9563
  }
@@ -9636,36 +9666,6 @@ var LATE_ANSWER_MS = 30 * 60000;
9636
9666
  var lateAnswers = new Map;
9637
9667
  var untaken = new Map;
9638
9668
 
9639
- // src/whole-file.ts
9640
- import { renameSync, rmSync as rmSync4, writeFileSync as writeFileSync2 } from "node:fs";
9641
- var HELD_FILE_MS = 1000;
9642
- var HELD_FILE_RETRY_MS = 10;
9643
- var HELD_BY_A_READER = new Set(["EPERM", "EACCES", "EBUSY"]);
9644
- function writeWhole(path, text) {
9645
- const partial = `${path}.${process.pid}.partial`;
9646
- try {
9647
- writeFileSync2(partial, text, "utf8");
9648
- } catch {
9649
- return false;
9650
- }
9651
- const until = Date.now() + HELD_FILE_MS;
9652
- for (;; ) {
9653
- try {
9654
- renameSync(partial, path);
9655
- return true;
9656
- } catch (error) {
9657
- const code = error.code ?? "";
9658
- if (!HELD_BY_A_READER.has(code) || Date.now() >= until) {
9659
- try {
9660
- rmSync4(partial, { force: true });
9661
- } catch {}
9662
- return false;
9663
- }
9664
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, HELD_FILE_RETRY_MS);
9665
- }
9666
- }
9667
- }
9668
-
9669
9669
  // src/run-record.ts
9670
9670
  function runsDirectory() {
9671
9671
  return join9(runtimeDirectory(), "runs");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdharness",
3
- "version": "1.3.25",
3
+ "version": "1.3.27",
4
4
  "mcpName": "io.github.Aureliolo/gdharness",
5
5
  "description": "A harness for driving a Godot 4 project from an agent: editor addons, a runtime bridge into the running game, an MCP server in front of them, and a CLI that installs and diagnoses the Godot side.",
6
6
  "type": "module",