gdharness 0.12.6 → 0.12.9

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
@@ -7425,11 +7425,14 @@ class UpdateCheck {
7425
7425
  this.retryAt = now + this.backoffMs;
7426
7426
  this.backoffMs = Math.min(this.backoffMs * 2, MAX_RETRY_MS);
7427
7427
  }
7428
- notice() {
7428
+ notice(now = Date.now()) {
7429
7429
  const latest = this.latest;
7430
7430
  if (!this.enabled || latest === null || !isNewer(latest, this.current)) {
7431
7431
  return null;
7432
7432
  }
7433
+ if (this.checking && now - this.checkedAt >= CACHE_MS) {
7434
+ return null;
7435
+ }
7433
7436
  return {
7434
7437
  current: this.current,
7435
7438
  latest,
@@ -15427,7 +15430,7 @@ var init_tool_definitions = __esm(() => {
15427
15430
  },
15428
15431
  failFast: {
15429
15432
  type: "boolean",
15430
- description: "Stop at the first failure. Default false: the whole set runs."
15433
+ description: "Stop each suite at its first failing case. Default false: every case runs. With it on, the counts are of what ran, notRun says how many cases were left, and fixing what is named and running again finds the next one, which looks like a flaky tier and is not."
15431
15434
  },
15432
15435
  timeoutMs: {
15433
15436
  type: "number",
@@ -35167,16 +35170,20 @@ function parseJUnit(xml) {
35167
35170
  throw new MalformedReportError("No <testsuites> or <testsuite> in the report");
35168
35171
  }
35169
35172
  const suiteElements = top.name === "testsuite" ? [top] : top.children.filter((child) => child.name === "testsuite");
35170
- const suites = suiteElements.map((suite) => ({
35171
- name: suite.attributes["name"] ?? "",
35172
- path: pathOf(suite),
35173
- tests: count(suite.attributes, "tests"),
35174
- failures: count(suite.attributes, "failures"),
35175
- errors: count(suite.attributes, "errors"),
35176
- skipped: count(suite.attributes, "skipped"),
35177
- time: count(suite.attributes, "time"),
35178
- cases: suite.children.filter((child) => child.name === "testcase").map((element) => caseOf(suite, element))
35179
- }));
35173
+ const suites = suiteElements.map((suite) => {
35174
+ const cases = suite.children.filter((child) => child.name === "testcase").map((element) => caseOf(suite, element));
35175
+ return {
35176
+ name: suite.attributes["name"] ?? "",
35177
+ path: pathOf(suite),
35178
+ tests: cases.length,
35179
+ discovered: count(suite.attributes, "tests"),
35180
+ failures: cases.filter((entry) => entry.status === "failed").length,
35181
+ errors: cases.filter((entry) => entry.status === "error").length,
35182
+ skipped: cases.filter((entry) => entry.status === "skipped").length,
35183
+ time: count(suite.attributes, "time"),
35184
+ cases
35185
+ };
35186
+ });
35180
35187
  const all = suites.flatMap((suite) => suite.cases);
35181
35188
  return {
35182
35189
  tests: all.length,
@@ -37475,6 +37482,7 @@ class GodotServer {
37475
37482
  message: `${suite.orphans} node${suite.orphans === 1 ? "" : "s"} were still in the tree when this suite finished. A node built in a test and neither freed nor added to the tree is the usual cause; free it, or add it with auto_free().`
37476
37483
  }));
37477
37484
  const unclean = report.suites.filter((suite) => suite.failures > 0 || suite.errors > 0 || suite.skipped > 0 || orphansIn(suite.path) > 0);
37485
+ const notRun = report.suites.reduce((sum, suite) => sum + Math.max(0, suite.discovered - suite.tests), 0);
37478
37486
  return this.jsonTextResponse({
37479
37487
  passed: !hung && exitCode === 0 && report.failures === 0 && report.errors === 0,
37480
37488
  verdict,
@@ -37487,11 +37495,13 @@ class GodotServer {
37487
37495
  failed,
37488
37496
  warnings: warnings.length > 0 ? warnings : undefined,
37489
37497
  orphans: orphans.total > 0 ? orphans.total : undefined,
37490
- note: verdict.startsWith("warnings") && warnings.length === 0 ? "gdUnit4 exits 101 for orphan nodes when nothing failed, and this run printed no count of them: orphan reporting may be off in the project settings." : undefined,
37498
+ notRun: notRun > 0 ? notRun : undefined,
37499
+ note: verdict.startsWith("warnings") && warnings.length === 0 ? "gdUnit4 exits 101 for orphan nodes when nothing failed, and this run printed no count of them: orphan reporting may be off in the project settings." : notRun > 0 ? `This run stopped at the first failure in each suite it failed in, so ${notRun} case${notRun === 1 ? "" : "s"} never ran and count as neither passed nor failed. Leave failFast out to run every case.` : undefined,
37491
37500
  suites: unclean.map((suite) => ({
37492
37501
  name: suite.name,
37493
37502
  path: suite.path,
37494
37503
  tests: suite.tests,
37504
+ notRun: suite.discovered > suite.tests ? suite.discovered - suite.tests : undefined,
37495
37505
  failures: suite.failures,
37496
37506
  errors: suite.errors,
37497
37507
  skipped: suite.skipped,
package/build/index.js CHANGED
@@ -9996,11 +9996,14 @@ class UpdateCheck {
9996
9996
  this.retryAt = now + this.backoffMs;
9997
9997
  this.backoffMs = Math.min(this.backoffMs * 2, MAX_RETRY_MS);
9998
9998
  }
9999
- notice() {
9999
+ notice(now = Date.now()) {
10000
10000
  const latest = this.latest;
10001
10001
  if (!this.enabled || latest === null || !isNewer(latest, this.current)) {
10002
10002
  return null;
10003
10003
  }
10004
+ if (this.checking && now - this.checkedAt >= CACHE_MS) {
10005
+ return null;
10006
+ }
10004
10007
  return {
10005
10008
  current: this.current,
10006
10009
  latest,
@@ -26592,16 +26595,20 @@ function parseJUnit(xml) {
26592
26595
  throw new MalformedReportError("No <testsuites> or <testsuite> in the report");
26593
26596
  }
26594
26597
  const suiteElements = top.name === "testsuite" ? [top] : top.children.filter((child) => child.name === "testsuite");
26595
- const suites = suiteElements.map((suite) => ({
26596
- name: suite.attributes["name"] ?? "",
26597
- path: pathOf(suite),
26598
- tests: count(suite.attributes, "tests"),
26599
- failures: count(suite.attributes, "failures"),
26600
- errors: count(suite.attributes, "errors"),
26601
- skipped: count(suite.attributes, "skipped"),
26602
- time: count(suite.attributes, "time"),
26603
- cases: suite.children.filter((child) => child.name === "testcase").map((element) => caseOf(suite, element))
26604
- }));
26598
+ const suites = suiteElements.map((suite) => {
26599
+ const cases = suite.children.filter((child) => child.name === "testcase").map((element) => caseOf(suite, element));
26600
+ return {
26601
+ name: suite.attributes["name"] ?? "",
26602
+ path: pathOf(suite),
26603
+ tests: cases.length,
26604
+ discovered: count(suite.attributes, "tests"),
26605
+ failures: cases.filter((entry) => entry.status === "failed").length,
26606
+ errors: cases.filter((entry) => entry.status === "error").length,
26607
+ skipped: cases.filter((entry) => entry.status === "skipped").length,
26608
+ time: count(suite.attributes, "time"),
26609
+ cases
26610
+ };
26611
+ });
26605
26612
  const all = suites.flatMap((suite) => suite.cases);
26606
26613
  return {
26607
26614
  tests: all.length,
@@ -28298,7 +28305,7 @@ var TOOL_SPECS = [
28298
28305
  },
28299
28306
  failFast: {
28300
28307
  type: "boolean",
28301
- description: "Stop at the first failure. Default false: the whole set runs."
28308
+ description: "Stop each suite at its first failing case. Default false: every case runs. With it on, the counts are of what ran, notRun says how many cases were left, and fixing what is named and running again finds the next one, which looks like a flaky tier and is not."
28302
28309
  },
28303
28310
  timeoutMs: {
28304
28311
  type: "number",
@@ -30257,6 +30264,7 @@ class GodotServer {
30257
30264
  message: `${suite.orphans} node${suite.orphans === 1 ? "" : "s"} were still in the tree when this suite finished. A node built in a test and neither freed nor added to the tree is the usual cause; free it, or add it with auto_free().`
30258
30265
  }));
30259
30266
  const unclean = report.suites.filter((suite) => suite.failures > 0 || suite.errors > 0 || suite.skipped > 0 || orphansIn(suite.path) > 0);
30267
+ const notRun = report.suites.reduce((sum, suite) => sum + Math.max(0, suite.discovered - suite.tests), 0);
30260
30268
  return this.jsonTextResponse({
30261
30269
  passed: !hung && exitCode === 0 && report.failures === 0 && report.errors === 0,
30262
30270
  verdict,
@@ -30269,11 +30277,13 @@ class GodotServer {
30269
30277
  failed,
30270
30278
  warnings: warnings.length > 0 ? warnings : undefined,
30271
30279
  orphans: orphans.total > 0 ? orphans.total : undefined,
30272
- note: verdict.startsWith("warnings") && warnings.length === 0 ? "gdUnit4 exits 101 for orphan nodes when nothing failed, and this run printed no count of them: orphan reporting may be off in the project settings." : undefined,
30280
+ notRun: notRun > 0 ? notRun : undefined,
30281
+ note: verdict.startsWith("warnings") && warnings.length === 0 ? "gdUnit4 exits 101 for orphan nodes when nothing failed, and this run printed no count of them: orphan reporting may be off in the project settings." : notRun > 0 ? `This run stopped at the first failure in each suite it failed in, so ${notRun} case${notRun === 1 ? "" : "s"} never ran and count as neither passed nor failed. Leave failFast out to run every case.` : undefined,
30273
30282
  suites: unclean.map((suite) => ({
30274
30283
  name: suite.name,
30275
30284
  path: suite.path,
30276
30285
  tests: suite.tests,
30286
+ notRun: suite.discovered > suite.tests ? suite.discovered - suite.tests : undefined,
30277
30287
  failures: suite.failures,
30278
30288
  errors: suite.errors,
30279
30289
  skipped: suite.skipped,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdharness",
3
- "version": "0.12.6",
3
+ "version": "0.12.9",
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",