terminalhire 0.42.36 → 0.42.37
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/dist/bin/jpi-claim.js +52 -17
- package/dist/bin/jpi-dispatch.js +52 -17
- package/dist/bin/jpi-mcp.js +52 -17
- package/dist/bin/jpi-run.js +52 -17
- package/package.json +1 -1
package/dist/bin/jpi-claim.js
CHANGED
|
@@ -26207,12 +26207,22 @@ function reportedCounts(classified, reparsed) {
|
|
|
26207
26207
|
function readCounts(stdout, stderr = "") {
|
|
26208
26208
|
const out = `${stdout}
|
|
26209
26209
|
${stderr}`;
|
|
26210
|
+
const matched = [];
|
|
26210
26211
|
for (const reader of READERS) {
|
|
26211
26212
|
const counts = reader.read(out);
|
|
26212
26213
|
if (counts)
|
|
26213
|
-
|
|
26214
|
+
matched.push({ reader, counts });
|
|
26214
26215
|
}
|
|
26215
|
-
|
|
26216
|
+
const first = matched[0];
|
|
26217
|
+
if (first === void 0)
|
|
26218
|
+
return null;
|
|
26219
|
+
const legs = matched.filter(({ reader }) => !matched.some((m) => reader.shadowedBy?.includes(m.reader.runner)));
|
|
26220
|
+
const partial = legs.length > 1 || (first.reader.summaries?.(out) ?? 1) > 1;
|
|
26221
|
+
return {
|
|
26222
|
+
...first.counts,
|
|
26223
|
+
runner: first.reader.runner,
|
|
26224
|
+
...partial ? { coverage: "partial" } : {}
|
|
26225
|
+
};
|
|
26216
26226
|
}
|
|
26217
26227
|
function coverageThresholdUnmet(facts, counts) {
|
|
26218
26228
|
if (counts === null || counts.runner !== "node-tap")
|
|
@@ -26371,7 +26381,7 @@ function isGreen(outcome) {
|
|
|
26371
26381
|
function isOurFault(outcome) {
|
|
26372
26382
|
return LIMIT_OWNER[outcome] === "ours";
|
|
26373
26383
|
}
|
|
26374
|
-
var VERIFICATION_OUTCOMES, int, withSuiteFailures, READERS, SUPPORTED_RUNNERS, COVERAGE_TABLE, EXEC_FAILURE, SUITE_REPORTED_FAILURE, MISSING_SYSTEM_DEPENDENCY, OFFLINE_BUILD_GAP, LIMIT_OWNER;
|
|
26384
|
+
var VERIFICATION_OUTCOMES, int, withSuiteFailures, countLines, READERS, SUPPORTED_RUNNERS, COVERAGE_TABLE, EXEC_FAILURE, SUITE_REPORTED_FAILURE, MISSING_SYSTEM_DEPENDENCY, OFFLINE_BUILD_GAP, LIMIT_OWNER;
|
|
26375
26385
|
var init_classify2 = __esm({
|
|
26376
26386
|
"../../packages/envrun/dist/classify.js"() {
|
|
26377
26387
|
"use strict";
|
|
@@ -26390,6 +26400,7 @@ var init_classify2 = __esm({
|
|
|
26390
26400
|
return counts;
|
|
26391
26401
|
return { ...counts, tests_failed: int(/(\d+) failed/.exec(suiteLine[1])) };
|
|
26392
26402
|
};
|
|
26403
|
+
countLines = (out, re) => (out.match(re) ?? []).length;
|
|
26393
26404
|
READERS = [
|
|
26394
26405
|
{
|
|
26395
26406
|
// `node --test` TAP. Anchored to line start, which is what makes it a
|
|
@@ -26401,7 +26412,10 @@ var init_classify2 = __esm({
|
|
|
26401
26412
|
if (!pass || !fail2)
|
|
26402
26413
|
return null;
|
|
26403
26414
|
return { tests_passed: int(pass), tests_failed: int(fail2) };
|
|
26404
|
-
}
|
|
26415
|
+
},
|
|
26416
|
+
// One `# pass N` per invocation, so a script that runs `node --test` once per file
|
|
26417
|
+
// prints many. envrun's own offline leg printed 67 and was read as the first one's 4.
|
|
26418
|
+
summaries: (out) => countLines(out, /^# pass \d+$/gm)
|
|
26405
26419
|
},
|
|
26406
26420
|
{
|
|
26407
26421
|
// node-tap's runner summary, which is NOT the `# pass N` / `# fail N` pair
|
|
@@ -26428,7 +26442,8 @@ var init_classify2 = __esm({
|
|
|
26428
26442
|
tests_passed: int(/\bpass: (\d+)/.exec(line[1])),
|
|
26429
26443
|
tests_failed: int(/\bfail: (\d+)/.exec(line[1]))
|
|
26430
26444
|
};
|
|
26431
|
-
}
|
|
26445
|
+
},
|
|
26446
|
+
summaries: (out) => countLines(out, /^# \{ total: \d+[^}\n]* \}$/gm)
|
|
26432
26447
|
},
|
|
26433
26448
|
{
|
|
26434
26449
|
// jest: `Tests: 1 failed, 2 passed, 3 total`
|
|
@@ -26441,7 +26456,8 @@ var init_classify2 = __esm({
|
|
|
26441
26456
|
tests_passed: int(/(\d+) passed/.exec(line[1])),
|
|
26442
26457
|
tests_failed: int(/(\d+) failed/.exec(line[1]))
|
|
26443
26458
|
}, /^Test Suites:\s+(.+?)\s*$/m.exec(out));
|
|
26444
|
-
}
|
|
26459
|
+
},
|
|
26460
|
+
summaries: (out) => countLines(out, /^Tests:\s+[^\n]*\btotal\b/gm)
|
|
26445
26461
|
},
|
|
26446
26462
|
{
|
|
26447
26463
|
// vitest: `Tests 3 passed (3)` / `Tests 1 failed | 2 passed (3)`
|
|
@@ -26458,7 +26474,12 @@ var init_classify2 = __esm({
|
|
|
26458
26474
|
if (!passed && !failed)
|
|
26459
26475
|
return null;
|
|
26460
26476
|
return withSuiteFailures({ tests_passed: int(passed), tests_failed: int(failed) }, files);
|
|
26461
|
-
}
|
|
26477
|
+
},
|
|
26478
|
+
// One invocation prints one `Test Files` line, and a numeric `Tests` line only when a
|
|
26479
|
+
// spec loaded (the every-spec-failed shape above has none). The larger of the two
|
|
26480
|
+
// counts invocations without counting a paired block twice; reading `Tests` alone
|
|
26481
|
+
// missed an all-failed run that followed a passing one (Codex review).
|
|
26482
|
+
summaries: (out) => Math.max(countLines(out, /^\s*Tests\s+[^\n]*\(\d+\)\s*$/gm), countLines(out, /^\s*Test Files\s+[^\n]*\(\d+\)\s*$/gm))
|
|
26462
26483
|
},
|
|
26463
26484
|
{
|
|
26464
26485
|
// pytest summary rule: `===== 297 passed in 0.54s =====`,
|
|
@@ -26481,7 +26502,10 @@ var init_classify2 = __esm({
|
|
|
26481
26502
|
if (!passed && !failed && !errors)
|
|
26482
26503
|
return null;
|
|
26483
26504
|
return { tests_passed: int(passed), tests_failed: int(failed) + int(errors) };
|
|
26484
|
-
}
|
|
26505
|
+
},
|
|
26506
|
+
// Only FINAL tallies, which carry pytest's `in 0.54s`. The interim banners the reader
|
|
26507
|
+
// skips above carry no duration, and counting them would mark every red run partial.
|
|
26508
|
+
summaries: (out) => Math.max(1, countLines(out, /^=+ [^\n]*?(?:passed|failed|error|no tests ran)[^\n]*? in [\d.]+s[^\n]*? =+$/gm))
|
|
26485
26509
|
},
|
|
26486
26510
|
{
|
|
26487
26511
|
// Maven surefire's per-module summary (TERM-1122), measured against surefire
|
|
@@ -26543,7 +26567,8 @@ var init_classify2 = __esm({
|
|
|
26543
26567
|
return null;
|
|
26544
26568
|
const failed = Number(m[1]);
|
|
26545
26569
|
return { tests_passed: Number(m[2]) - failed, tests_failed: failed };
|
|
26546
|
-
}
|
|
26570
|
+
},
|
|
26571
|
+
summaries: (out) => Math.max(1, countLines(out, /^\d+% tests passed, \d+ tests? failed out of \d+$/gm))
|
|
26547
26572
|
},
|
|
26548
26573
|
{
|
|
26549
26574
|
// mocha: ` 440 passing (1s)` and ` 2 failing`
|
|
@@ -26554,7 +26579,8 @@ var init_classify2 = __esm({
|
|
|
26554
26579
|
if (!passing && !failing)
|
|
26555
26580
|
return null;
|
|
26556
26581
|
return { tests_passed: int(passing), tests_failed: int(failing) };
|
|
26557
|
-
}
|
|
26582
|
+
},
|
|
26583
|
+
summaries: (out) => Math.max(countLines(out, /^\s*\d+ passing\b/gm), countLines(out, /^\s*\d+ failing\b/gm))
|
|
26558
26584
|
},
|
|
26559
26585
|
{
|
|
26560
26586
|
// ava: ` 3 tests passed` / ` 1 test failed`
|
|
@@ -26565,7 +26591,8 @@ var init_classify2 = __esm({
|
|
|
26565
26591
|
if (!passed && !failed)
|
|
26566
26592
|
return null;
|
|
26567
26593
|
return { tests_passed: int(passed), tests_failed: int(failed) };
|
|
26568
|
-
}
|
|
26594
|
+
},
|
|
26595
|
+
summaries: (out) => Math.max(countLines(out, /^\s*\d+ tests? passed\b/gm), countLines(out, /^\s*\d+ tests? failed\b/gm))
|
|
26569
26596
|
},
|
|
26570
26597
|
{
|
|
26571
26598
|
// uvu: a `Total:` / `Passed:` / `Skipped:` block.
|
|
@@ -26578,7 +26605,8 @@ var init_classify2 = __esm({
|
|
|
26578
26605
|
const t = int(total);
|
|
26579
26606
|
const p = int(passed);
|
|
26580
26607
|
return { tests_passed: p, tests_failed: Math.max(0, t - p) };
|
|
26581
|
-
}
|
|
26608
|
+
},
|
|
26609
|
+
summaries: (out) => countLines(out, /^\s*Total:\s+\d+/gm)
|
|
26582
26610
|
},
|
|
26583
26611
|
{
|
|
26584
26612
|
/**
|
|
@@ -26613,6 +26641,7 @@ var init_classify2 = __esm({
|
|
|
26613
26641
|
* those would double them against their parent.
|
|
26614
26642
|
*/
|
|
26615
26643
|
runner: "bare TAP",
|
|
26644
|
+
shadowedBy: ["node --test (TAP)", "node-tap"],
|
|
26616
26645
|
read: (out) => {
|
|
26617
26646
|
let n = 0;
|
|
26618
26647
|
let failed = 0;
|
|
@@ -30358,9 +30387,9 @@ function renderVerdictLine(r) {
|
|
|
30358
30387
|
const t = fmtMs(r.wallMs);
|
|
30359
30388
|
switch (r.outcome) {
|
|
30360
30389
|
case "completed":
|
|
30361
|
-
return `GREEN ${String(r.counts?.tests_passed ?? 0)} test(s) passed, none failed
|
|
30390
|
+
return `GREEN ${String(r.counts?.tests_passed ?? 0)} test(s) passed, none failed ` + (r.counts?.coverage === "partial" ? `(${PARTIAL_COUNTS_NOTE}) ` : "") + `\u2014 ${t}${r.preview ? ` \u2014 ${r.preview.url}` : ""}`;
|
|
30362
30391
|
case "tests-failed":
|
|
30363
|
-
return `RED ${r.counts ? `${String(r.counts.tests_failed)} test(s) failed` : `exit ${String(r.exitCode)}`} \u2014 ${t}${r.preview ? ` \u2014 ${r.preview.url}` : ""}`;
|
|
30392
|
+
return `RED ${r.counts ? `${String(r.counts.tests_failed)} test(s) failed` : `exit ${String(r.exitCode)}`}` + (r.counts?.coverage === "partial" ? ` (${PARTIAL_COUNTS_NOTE})` : "") + ` \u2014 ${t}${r.preview ? ` \u2014 ${r.preview.url}` : ""}`;
|
|
30364
30393
|
case "no-tests-observed":
|
|
30365
30394
|
return `NOTHING RAN the suite reported zero tests passed and zero failed \u2014 ${t}`;
|
|
30366
30395
|
case "counts-unparsed":
|
|
@@ -30414,7 +30443,7 @@ function exitCodeFor(r) {
|
|
|
30414
30443
|
return 2;
|
|
30415
30444
|
return exitCodeForOutcome(r.outcome);
|
|
30416
30445
|
}
|
|
30417
|
-
var RUN_TEST_COMMAND_SOURCES, RUN_IMAGE_SOURCES, RUN_RESULT_SCHEMA, RUN_RESULT_FIELDS, RENDER_NONE, FIELD_VIEWS;
|
|
30446
|
+
var RUN_TEST_COMMAND_SOURCES, RUN_IMAGE_SOURCES, RUN_RESULT_SCHEMA, PARTIAL_COUNTS_NOTE, RUN_RESULT_FIELDS, RENDER_NONE, FIELD_VIEWS;
|
|
30418
30447
|
var init_result = __esm({
|
|
30419
30448
|
"../../packages/envrun/dist/result.js"() {
|
|
30420
30449
|
"use strict";
|
|
@@ -30437,6 +30466,7 @@ var init_result = __esm({
|
|
|
30437
30466
|
"founder-declared"
|
|
30438
30467
|
];
|
|
30439
30468
|
RUN_RESULT_SCHEMA = "terminalhire.verification-run/1";
|
|
30469
|
+
PARTIAL_COUNTS_NOTE = "from one of several test summaries in the output, so not a total for the whole run";
|
|
30440
30470
|
RUN_RESULT_FIELDS = [
|
|
30441
30471
|
"schema",
|
|
30442
30472
|
"runId",
|
|
@@ -30482,7 +30512,7 @@ var init_result = __esm({
|
|
|
30482
30512
|
testCommand: (r) => r.testCommand === null ? null : `test command ${r.testCommand}`,
|
|
30483
30513
|
testOutputTail: RENDER_NONE,
|
|
30484
30514
|
// printed as a block below the fields, when red
|
|
30485
|
-
counts: (r) => r.counts === null ? null : `tests ${String(r.counts.tests_passed)} passed, ${String(r.counts.tests_failed)} failed (${r.counts.runner})
|
|
30515
|
+
counts: (r) => r.counts === null ? null : `tests ${String(r.counts.tests_passed)} passed, ${String(r.counts.tests_failed)} failed (${r.counts.runner})` + (r.counts.coverage === "partial" ? ` \u2014 ${PARTIAL_COUNTS_NOTE}` : ""),
|
|
30486
30516
|
wallMs: (r) => `round trip ${fmtMs(r.wallMs)}`,
|
|
30487
30517
|
installMs: (r) => r.installMs === void 0 ? null : `install step ${fmtMs(r.installMs)}`,
|
|
30488
30518
|
testMs: (r) => r.testMs === void 0 ? null : `test step ${fmtMs(r.testMs)}`,
|
|
@@ -30581,7 +30611,11 @@ function toTestRunResult(result, outputSha256) {
|
|
|
30581
30611
|
return {
|
|
30582
30612
|
exit_code: result.exitCode ?? -1,
|
|
30583
30613
|
...outputSha256 === void 0 ? {} : { output_sha256: outputSha256 },
|
|
30584
|
-
...result.counts === null ? {} : {
|
|
30614
|
+
...result.counts === null ? {} : {
|
|
30615
|
+
tests_passed: result.counts.tests_passed,
|
|
30616
|
+
tests_failed: result.counts.tests_failed,
|
|
30617
|
+
...result.counts.coverage === "partial" ? { tests_coverage: "partial" } : {}
|
|
30618
|
+
}
|
|
30585
30619
|
};
|
|
30586
30620
|
}
|
|
30587
30621
|
function toAcceptancePredicate(pair, opts = {}) {
|
|
@@ -38033,6 +38067,7 @@ __export(dist_exports, {
|
|
|
38033
38067
|
LabelWatch: () => LabelWatch,
|
|
38034
38068
|
MIN_GIT_VERSION_FOR_END_OF_OPTIONS: () => MIN_GIT_VERSION_FOR_END_OF_OPTIONS,
|
|
38035
38069
|
OUTCOME_TO_BUDGET: () => OUTCOME_TO_BUDGET,
|
|
38070
|
+
PARTIAL_COUNTS_NOTE: () => PARTIAL_COUNTS_NOTE,
|
|
38036
38071
|
PATH_REFUSAL_CODES: () => PATH_REFUSAL_CODES,
|
|
38037
38072
|
PLACEMENTS: () => PLACEMENTS,
|
|
38038
38073
|
PLACEMENT_ALIASES: () => PLACEMENT_ALIASES,
|
package/dist/bin/jpi-dispatch.js
CHANGED
|
@@ -31982,12 +31982,22 @@ function reportedCounts(classified, reparsed) {
|
|
|
31982
31982
|
function readCounts(stdout, stderr = "") {
|
|
31983
31983
|
const out = `${stdout}
|
|
31984
31984
|
${stderr}`;
|
|
31985
|
+
const matched = [];
|
|
31985
31986
|
for (const reader of READERS) {
|
|
31986
31987
|
const counts = reader.read(out);
|
|
31987
31988
|
if (counts)
|
|
31988
|
-
|
|
31989
|
+
matched.push({ reader, counts });
|
|
31989
31990
|
}
|
|
31990
|
-
|
|
31991
|
+
const first = matched[0];
|
|
31992
|
+
if (first === void 0)
|
|
31993
|
+
return null;
|
|
31994
|
+
const legs = matched.filter(({ reader }) => !matched.some((m) => reader.shadowedBy?.includes(m.reader.runner)));
|
|
31995
|
+
const partial2 = legs.length > 1 || (first.reader.summaries?.(out) ?? 1) > 1;
|
|
31996
|
+
return {
|
|
31997
|
+
...first.counts,
|
|
31998
|
+
runner: first.reader.runner,
|
|
31999
|
+
...partial2 ? { coverage: "partial" } : {}
|
|
32000
|
+
};
|
|
31991
32001
|
}
|
|
31992
32002
|
function coverageThresholdUnmet(facts, counts) {
|
|
31993
32003
|
if (counts === null || counts.runner !== "node-tap")
|
|
@@ -32146,7 +32156,7 @@ function isGreen(outcome) {
|
|
|
32146
32156
|
function isOurFault(outcome) {
|
|
32147
32157
|
return LIMIT_OWNER[outcome] === "ours";
|
|
32148
32158
|
}
|
|
32149
|
-
var VERIFICATION_OUTCOMES, int, withSuiteFailures, READERS, SUPPORTED_RUNNERS, COVERAGE_TABLE, EXEC_FAILURE, SUITE_REPORTED_FAILURE, MISSING_SYSTEM_DEPENDENCY, OFFLINE_BUILD_GAP, LIMIT_OWNER;
|
|
32159
|
+
var VERIFICATION_OUTCOMES, int, withSuiteFailures, countLines, READERS, SUPPORTED_RUNNERS, COVERAGE_TABLE, EXEC_FAILURE, SUITE_REPORTED_FAILURE, MISSING_SYSTEM_DEPENDENCY, OFFLINE_BUILD_GAP, LIMIT_OWNER;
|
|
32150
32160
|
var init_classify2 = __esm({
|
|
32151
32161
|
"../../packages/envrun/dist/classify.js"() {
|
|
32152
32162
|
"use strict";
|
|
@@ -32165,6 +32175,7 @@ var init_classify2 = __esm({
|
|
|
32165
32175
|
return counts;
|
|
32166
32176
|
return { ...counts, tests_failed: int(/(\d+) failed/.exec(suiteLine[1])) };
|
|
32167
32177
|
};
|
|
32178
|
+
countLines = (out, re) => (out.match(re) ?? []).length;
|
|
32168
32179
|
READERS = [
|
|
32169
32180
|
{
|
|
32170
32181
|
// `node --test` TAP. Anchored to line start, which is what makes it a
|
|
@@ -32176,7 +32187,10 @@ var init_classify2 = __esm({
|
|
|
32176
32187
|
if (!pass || !fail2)
|
|
32177
32188
|
return null;
|
|
32178
32189
|
return { tests_passed: int(pass), tests_failed: int(fail2) };
|
|
32179
|
-
}
|
|
32190
|
+
},
|
|
32191
|
+
// One `# pass N` per invocation, so a script that runs `node --test` once per file
|
|
32192
|
+
// prints many. envrun's own offline leg printed 67 and was read as the first one's 4.
|
|
32193
|
+
summaries: (out) => countLines(out, /^# pass \d+$/gm)
|
|
32180
32194
|
},
|
|
32181
32195
|
{
|
|
32182
32196
|
// node-tap's runner summary, which is NOT the `# pass N` / `# fail N` pair
|
|
@@ -32203,7 +32217,8 @@ var init_classify2 = __esm({
|
|
|
32203
32217
|
tests_passed: int(/\bpass: (\d+)/.exec(line[1])),
|
|
32204
32218
|
tests_failed: int(/\bfail: (\d+)/.exec(line[1]))
|
|
32205
32219
|
};
|
|
32206
|
-
}
|
|
32220
|
+
},
|
|
32221
|
+
summaries: (out) => countLines(out, /^# \{ total: \d+[^}\n]* \}$/gm)
|
|
32207
32222
|
},
|
|
32208
32223
|
{
|
|
32209
32224
|
// jest: `Tests: 1 failed, 2 passed, 3 total`
|
|
@@ -32216,7 +32231,8 @@ var init_classify2 = __esm({
|
|
|
32216
32231
|
tests_passed: int(/(\d+) passed/.exec(line[1])),
|
|
32217
32232
|
tests_failed: int(/(\d+) failed/.exec(line[1]))
|
|
32218
32233
|
}, /^Test Suites:\s+(.+?)\s*$/m.exec(out));
|
|
32219
|
-
}
|
|
32234
|
+
},
|
|
32235
|
+
summaries: (out) => countLines(out, /^Tests:\s+[^\n]*\btotal\b/gm)
|
|
32220
32236
|
},
|
|
32221
32237
|
{
|
|
32222
32238
|
// vitest: `Tests 3 passed (3)` / `Tests 1 failed | 2 passed (3)`
|
|
@@ -32233,7 +32249,12 @@ var init_classify2 = __esm({
|
|
|
32233
32249
|
if (!passed && !failed)
|
|
32234
32250
|
return null;
|
|
32235
32251
|
return withSuiteFailures({ tests_passed: int(passed), tests_failed: int(failed) }, files);
|
|
32236
|
-
}
|
|
32252
|
+
},
|
|
32253
|
+
// One invocation prints one `Test Files` line, and a numeric `Tests` line only when a
|
|
32254
|
+
// spec loaded (the every-spec-failed shape above has none). The larger of the two
|
|
32255
|
+
// counts invocations without counting a paired block twice; reading `Tests` alone
|
|
32256
|
+
// missed an all-failed run that followed a passing one (Codex review).
|
|
32257
|
+
summaries: (out) => Math.max(countLines(out, /^\s*Tests\s+[^\n]*\(\d+\)\s*$/gm), countLines(out, /^\s*Test Files\s+[^\n]*\(\d+\)\s*$/gm))
|
|
32237
32258
|
},
|
|
32238
32259
|
{
|
|
32239
32260
|
// pytest summary rule: `===== 297 passed in 0.54s =====`,
|
|
@@ -32256,7 +32277,10 @@ var init_classify2 = __esm({
|
|
|
32256
32277
|
if (!passed && !failed && !errors)
|
|
32257
32278
|
return null;
|
|
32258
32279
|
return { tests_passed: int(passed), tests_failed: int(failed) + int(errors) };
|
|
32259
|
-
}
|
|
32280
|
+
},
|
|
32281
|
+
// Only FINAL tallies, which carry pytest's `in 0.54s`. The interim banners the reader
|
|
32282
|
+
// skips above carry no duration, and counting them would mark every red run partial.
|
|
32283
|
+
summaries: (out) => Math.max(1, countLines(out, /^=+ [^\n]*?(?:passed|failed|error|no tests ran)[^\n]*? in [\d.]+s[^\n]*? =+$/gm))
|
|
32260
32284
|
},
|
|
32261
32285
|
{
|
|
32262
32286
|
// Maven surefire's per-module summary (TERM-1122), measured against surefire
|
|
@@ -32318,7 +32342,8 @@ var init_classify2 = __esm({
|
|
|
32318
32342
|
return null;
|
|
32319
32343
|
const failed = Number(m[1]);
|
|
32320
32344
|
return { tests_passed: Number(m[2]) - failed, tests_failed: failed };
|
|
32321
|
-
}
|
|
32345
|
+
},
|
|
32346
|
+
summaries: (out) => Math.max(1, countLines(out, /^\d+% tests passed, \d+ tests? failed out of \d+$/gm))
|
|
32322
32347
|
},
|
|
32323
32348
|
{
|
|
32324
32349
|
// mocha: ` 440 passing (1s)` and ` 2 failing`
|
|
@@ -32329,7 +32354,8 @@ var init_classify2 = __esm({
|
|
|
32329
32354
|
if (!passing && !failing)
|
|
32330
32355
|
return null;
|
|
32331
32356
|
return { tests_passed: int(passing), tests_failed: int(failing) };
|
|
32332
|
-
}
|
|
32357
|
+
},
|
|
32358
|
+
summaries: (out) => Math.max(countLines(out, /^\s*\d+ passing\b/gm), countLines(out, /^\s*\d+ failing\b/gm))
|
|
32333
32359
|
},
|
|
32334
32360
|
{
|
|
32335
32361
|
// ava: ` 3 tests passed` / ` 1 test failed`
|
|
@@ -32340,7 +32366,8 @@ var init_classify2 = __esm({
|
|
|
32340
32366
|
if (!passed && !failed)
|
|
32341
32367
|
return null;
|
|
32342
32368
|
return { tests_passed: int(passed), tests_failed: int(failed) };
|
|
32343
|
-
}
|
|
32369
|
+
},
|
|
32370
|
+
summaries: (out) => Math.max(countLines(out, /^\s*\d+ tests? passed\b/gm), countLines(out, /^\s*\d+ tests? failed\b/gm))
|
|
32344
32371
|
},
|
|
32345
32372
|
{
|
|
32346
32373
|
// uvu: a `Total:` / `Passed:` / `Skipped:` block.
|
|
@@ -32353,7 +32380,8 @@ var init_classify2 = __esm({
|
|
|
32353
32380
|
const t = int(total);
|
|
32354
32381
|
const p = int(passed);
|
|
32355
32382
|
return { tests_passed: p, tests_failed: Math.max(0, t - p) };
|
|
32356
|
-
}
|
|
32383
|
+
},
|
|
32384
|
+
summaries: (out) => countLines(out, /^\s*Total:\s+\d+/gm)
|
|
32357
32385
|
},
|
|
32358
32386
|
{
|
|
32359
32387
|
/**
|
|
@@ -32388,6 +32416,7 @@ var init_classify2 = __esm({
|
|
|
32388
32416
|
* those would double them against their parent.
|
|
32389
32417
|
*/
|
|
32390
32418
|
runner: "bare TAP",
|
|
32419
|
+
shadowedBy: ["node --test (TAP)", "node-tap"],
|
|
32391
32420
|
read: (out) => {
|
|
32392
32421
|
let n = 0;
|
|
32393
32422
|
let failed = 0;
|
|
@@ -36133,9 +36162,9 @@ function renderVerdictLine(r) {
|
|
|
36133
36162
|
const t = fmtMs(r.wallMs);
|
|
36134
36163
|
switch (r.outcome) {
|
|
36135
36164
|
case "completed":
|
|
36136
|
-
return `GREEN ${String(r.counts?.tests_passed ?? 0)} test(s) passed, none failed
|
|
36165
|
+
return `GREEN ${String(r.counts?.tests_passed ?? 0)} test(s) passed, none failed ` + (r.counts?.coverage === "partial" ? `(${PARTIAL_COUNTS_NOTE}) ` : "") + `\u2014 ${t}${r.preview ? ` \u2014 ${r.preview.url}` : ""}`;
|
|
36137
36166
|
case "tests-failed":
|
|
36138
|
-
return `RED ${r.counts ? `${String(r.counts.tests_failed)} test(s) failed` : `exit ${String(r.exitCode)}`} \u2014 ${t}${r.preview ? ` \u2014 ${r.preview.url}` : ""}`;
|
|
36167
|
+
return `RED ${r.counts ? `${String(r.counts.tests_failed)} test(s) failed` : `exit ${String(r.exitCode)}`}` + (r.counts?.coverage === "partial" ? ` (${PARTIAL_COUNTS_NOTE})` : "") + ` \u2014 ${t}${r.preview ? ` \u2014 ${r.preview.url}` : ""}`;
|
|
36139
36168
|
case "no-tests-observed":
|
|
36140
36169
|
return `NOTHING RAN the suite reported zero tests passed and zero failed \u2014 ${t}`;
|
|
36141
36170
|
case "counts-unparsed":
|
|
@@ -36189,7 +36218,7 @@ function exitCodeFor(r) {
|
|
|
36189
36218
|
return 2;
|
|
36190
36219
|
return exitCodeForOutcome(r.outcome);
|
|
36191
36220
|
}
|
|
36192
|
-
var RUN_TEST_COMMAND_SOURCES, RUN_IMAGE_SOURCES, RUN_RESULT_SCHEMA, RUN_RESULT_FIELDS, RENDER_NONE, FIELD_VIEWS;
|
|
36221
|
+
var RUN_TEST_COMMAND_SOURCES, RUN_IMAGE_SOURCES, RUN_RESULT_SCHEMA, PARTIAL_COUNTS_NOTE, RUN_RESULT_FIELDS, RENDER_NONE, FIELD_VIEWS;
|
|
36193
36222
|
var init_result = __esm({
|
|
36194
36223
|
"../../packages/envrun/dist/result.js"() {
|
|
36195
36224
|
"use strict";
|
|
@@ -36212,6 +36241,7 @@ var init_result = __esm({
|
|
|
36212
36241
|
"founder-declared"
|
|
36213
36242
|
];
|
|
36214
36243
|
RUN_RESULT_SCHEMA = "terminalhire.verification-run/1";
|
|
36244
|
+
PARTIAL_COUNTS_NOTE = "from one of several test summaries in the output, so not a total for the whole run";
|
|
36215
36245
|
RUN_RESULT_FIELDS = [
|
|
36216
36246
|
"schema",
|
|
36217
36247
|
"runId",
|
|
@@ -36257,7 +36287,7 @@ var init_result = __esm({
|
|
|
36257
36287
|
testCommand: (r) => r.testCommand === null ? null : `test command ${r.testCommand}`,
|
|
36258
36288
|
testOutputTail: RENDER_NONE,
|
|
36259
36289
|
// printed as a block below the fields, when red
|
|
36260
|
-
counts: (r) => r.counts === null ? null : `tests ${String(r.counts.tests_passed)} passed, ${String(r.counts.tests_failed)} failed (${r.counts.runner})
|
|
36290
|
+
counts: (r) => r.counts === null ? null : `tests ${String(r.counts.tests_passed)} passed, ${String(r.counts.tests_failed)} failed (${r.counts.runner})` + (r.counts.coverage === "partial" ? ` \u2014 ${PARTIAL_COUNTS_NOTE}` : ""),
|
|
36261
36291
|
wallMs: (r) => `round trip ${fmtMs(r.wallMs)}`,
|
|
36262
36292
|
installMs: (r) => r.installMs === void 0 ? null : `install step ${fmtMs(r.installMs)}`,
|
|
36263
36293
|
testMs: (r) => r.testMs === void 0 ? null : `test step ${fmtMs(r.testMs)}`,
|
|
@@ -36356,7 +36386,11 @@ function toTestRunResult(result, outputSha256) {
|
|
|
36356
36386
|
return {
|
|
36357
36387
|
exit_code: result.exitCode ?? -1,
|
|
36358
36388
|
...outputSha256 === void 0 ? {} : { output_sha256: outputSha256 },
|
|
36359
|
-
...result.counts === null ? {} : {
|
|
36389
|
+
...result.counts === null ? {} : {
|
|
36390
|
+
tests_passed: result.counts.tests_passed,
|
|
36391
|
+
tests_failed: result.counts.tests_failed,
|
|
36392
|
+
...result.counts.coverage === "partial" ? { tests_coverage: "partial" } : {}
|
|
36393
|
+
}
|
|
36360
36394
|
};
|
|
36361
36395
|
}
|
|
36362
36396
|
function toAcceptancePredicate(pair, opts = {}) {
|
|
@@ -43808,6 +43842,7 @@ __export(dist_exports, {
|
|
|
43808
43842
|
LabelWatch: () => LabelWatch,
|
|
43809
43843
|
MIN_GIT_VERSION_FOR_END_OF_OPTIONS: () => MIN_GIT_VERSION_FOR_END_OF_OPTIONS,
|
|
43810
43844
|
OUTCOME_TO_BUDGET: () => OUTCOME_TO_BUDGET,
|
|
43845
|
+
PARTIAL_COUNTS_NOTE: () => PARTIAL_COUNTS_NOTE,
|
|
43811
43846
|
PATH_REFUSAL_CODES: () => PATH_REFUSAL_CODES,
|
|
43812
43847
|
PLACEMENTS: () => PLACEMENTS,
|
|
43813
43848
|
PLACEMENT_ALIASES: () => PLACEMENT_ALIASES,
|
package/dist/bin/jpi-mcp.js
CHANGED
|
@@ -26748,12 +26748,22 @@ function reportedCounts(classified, reparsed) {
|
|
|
26748
26748
|
function readCounts(stdout, stderr = "") {
|
|
26749
26749
|
const out = `${stdout}
|
|
26750
26750
|
${stderr}`;
|
|
26751
|
+
const matched = [];
|
|
26751
26752
|
for (const reader of READERS) {
|
|
26752
26753
|
const counts = reader.read(out);
|
|
26753
26754
|
if (counts)
|
|
26754
|
-
|
|
26755
|
+
matched.push({ reader, counts });
|
|
26755
26756
|
}
|
|
26756
|
-
|
|
26757
|
+
const first = matched[0];
|
|
26758
|
+
if (first === void 0)
|
|
26759
|
+
return null;
|
|
26760
|
+
const legs = matched.filter(({ reader }) => !matched.some((m) => reader.shadowedBy?.includes(m.reader.runner)));
|
|
26761
|
+
const partial2 = legs.length > 1 || (first.reader.summaries?.(out) ?? 1) > 1;
|
|
26762
|
+
return {
|
|
26763
|
+
...first.counts,
|
|
26764
|
+
runner: first.reader.runner,
|
|
26765
|
+
...partial2 ? { coverage: "partial" } : {}
|
|
26766
|
+
};
|
|
26757
26767
|
}
|
|
26758
26768
|
function coverageThresholdUnmet(facts, counts) {
|
|
26759
26769
|
if (counts === null || counts.runner !== "node-tap")
|
|
@@ -26912,7 +26922,7 @@ function isGreen(outcome) {
|
|
|
26912
26922
|
function isOurFault(outcome) {
|
|
26913
26923
|
return LIMIT_OWNER[outcome] === "ours";
|
|
26914
26924
|
}
|
|
26915
|
-
var VERIFICATION_OUTCOMES, int, withSuiteFailures, READERS, SUPPORTED_RUNNERS, COVERAGE_TABLE, EXEC_FAILURE, SUITE_REPORTED_FAILURE, MISSING_SYSTEM_DEPENDENCY, OFFLINE_BUILD_GAP, LIMIT_OWNER;
|
|
26925
|
+
var VERIFICATION_OUTCOMES, int, withSuiteFailures, countLines, READERS, SUPPORTED_RUNNERS, COVERAGE_TABLE, EXEC_FAILURE, SUITE_REPORTED_FAILURE, MISSING_SYSTEM_DEPENDENCY, OFFLINE_BUILD_GAP, LIMIT_OWNER;
|
|
26916
26926
|
var init_classify2 = __esm({
|
|
26917
26927
|
"../../packages/envrun/dist/classify.js"() {
|
|
26918
26928
|
"use strict";
|
|
@@ -26931,6 +26941,7 @@ var init_classify2 = __esm({
|
|
|
26931
26941
|
return counts;
|
|
26932
26942
|
return { ...counts, tests_failed: int(/(\d+) failed/.exec(suiteLine[1])) };
|
|
26933
26943
|
};
|
|
26944
|
+
countLines = (out, re) => (out.match(re) ?? []).length;
|
|
26934
26945
|
READERS = [
|
|
26935
26946
|
{
|
|
26936
26947
|
// `node --test` TAP. Anchored to line start, which is what makes it a
|
|
@@ -26942,7 +26953,10 @@ var init_classify2 = __esm({
|
|
|
26942
26953
|
if (!pass || !fail2)
|
|
26943
26954
|
return null;
|
|
26944
26955
|
return { tests_passed: int(pass), tests_failed: int(fail2) };
|
|
26945
|
-
}
|
|
26956
|
+
},
|
|
26957
|
+
// One `# pass N` per invocation, so a script that runs `node --test` once per file
|
|
26958
|
+
// prints many. envrun's own offline leg printed 67 and was read as the first one's 4.
|
|
26959
|
+
summaries: (out) => countLines(out, /^# pass \d+$/gm)
|
|
26946
26960
|
},
|
|
26947
26961
|
{
|
|
26948
26962
|
// node-tap's runner summary, which is NOT the `# pass N` / `# fail N` pair
|
|
@@ -26969,7 +26983,8 @@ var init_classify2 = __esm({
|
|
|
26969
26983
|
tests_passed: int(/\bpass: (\d+)/.exec(line[1])),
|
|
26970
26984
|
tests_failed: int(/\bfail: (\d+)/.exec(line[1]))
|
|
26971
26985
|
};
|
|
26972
|
-
}
|
|
26986
|
+
},
|
|
26987
|
+
summaries: (out) => countLines(out, /^# \{ total: \d+[^}\n]* \}$/gm)
|
|
26973
26988
|
},
|
|
26974
26989
|
{
|
|
26975
26990
|
// jest: `Tests: 1 failed, 2 passed, 3 total`
|
|
@@ -26982,7 +26997,8 @@ var init_classify2 = __esm({
|
|
|
26982
26997
|
tests_passed: int(/(\d+) passed/.exec(line[1])),
|
|
26983
26998
|
tests_failed: int(/(\d+) failed/.exec(line[1]))
|
|
26984
26999
|
}, /^Test Suites:\s+(.+?)\s*$/m.exec(out));
|
|
26985
|
-
}
|
|
27000
|
+
},
|
|
27001
|
+
summaries: (out) => countLines(out, /^Tests:\s+[^\n]*\btotal\b/gm)
|
|
26986
27002
|
},
|
|
26987
27003
|
{
|
|
26988
27004
|
// vitest: `Tests 3 passed (3)` / `Tests 1 failed | 2 passed (3)`
|
|
@@ -26999,7 +27015,12 @@ var init_classify2 = __esm({
|
|
|
26999
27015
|
if (!passed && !failed)
|
|
27000
27016
|
return null;
|
|
27001
27017
|
return withSuiteFailures({ tests_passed: int(passed), tests_failed: int(failed) }, files);
|
|
27002
|
-
}
|
|
27018
|
+
},
|
|
27019
|
+
// One invocation prints one `Test Files` line, and a numeric `Tests` line only when a
|
|
27020
|
+
// spec loaded (the every-spec-failed shape above has none). The larger of the two
|
|
27021
|
+
// counts invocations without counting a paired block twice; reading `Tests` alone
|
|
27022
|
+
// missed an all-failed run that followed a passing one (Codex review).
|
|
27023
|
+
summaries: (out) => Math.max(countLines(out, /^\s*Tests\s+[^\n]*\(\d+\)\s*$/gm), countLines(out, /^\s*Test Files\s+[^\n]*\(\d+\)\s*$/gm))
|
|
27003
27024
|
},
|
|
27004
27025
|
{
|
|
27005
27026
|
// pytest summary rule: `===== 297 passed in 0.54s =====`,
|
|
@@ -27022,7 +27043,10 @@ var init_classify2 = __esm({
|
|
|
27022
27043
|
if (!passed && !failed && !errors)
|
|
27023
27044
|
return null;
|
|
27024
27045
|
return { tests_passed: int(passed), tests_failed: int(failed) + int(errors) };
|
|
27025
|
-
}
|
|
27046
|
+
},
|
|
27047
|
+
// Only FINAL tallies, which carry pytest's `in 0.54s`. The interim banners the reader
|
|
27048
|
+
// skips above carry no duration, and counting them would mark every red run partial.
|
|
27049
|
+
summaries: (out) => Math.max(1, countLines(out, /^=+ [^\n]*?(?:passed|failed|error|no tests ran)[^\n]*? in [\d.]+s[^\n]*? =+$/gm))
|
|
27026
27050
|
},
|
|
27027
27051
|
{
|
|
27028
27052
|
// Maven surefire's per-module summary (TERM-1122), measured against surefire
|
|
@@ -27084,7 +27108,8 @@ var init_classify2 = __esm({
|
|
|
27084
27108
|
return null;
|
|
27085
27109
|
const failed = Number(m[1]);
|
|
27086
27110
|
return { tests_passed: Number(m[2]) - failed, tests_failed: failed };
|
|
27087
|
-
}
|
|
27111
|
+
},
|
|
27112
|
+
summaries: (out) => Math.max(1, countLines(out, /^\d+% tests passed, \d+ tests? failed out of \d+$/gm))
|
|
27088
27113
|
},
|
|
27089
27114
|
{
|
|
27090
27115
|
// mocha: ` 440 passing (1s)` and ` 2 failing`
|
|
@@ -27095,7 +27120,8 @@ var init_classify2 = __esm({
|
|
|
27095
27120
|
if (!passing && !failing)
|
|
27096
27121
|
return null;
|
|
27097
27122
|
return { tests_passed: int(passing), tests_failed: int(failing) };
|
|
27098
|
-
}
|
|
27123
|
+
},
|
|
27124
|
+
summaries: (out) => Math.max(countLines(out, /^\s*\d+ passing\b/gm), countLines(out, /^\s*\d+ failing\b/gm))
|
|
27099
27125
|
},
|
|
27100
27126
|
{
|
|
27101
27127
|
// ava: ` 3 tests passed` / ` 1 test failed`
|
|
@@ -27106,7 +27132,8 @@ var init_classify2 = __esm({
|
|
|
27106
27132
|
if (!passed && !failed)
|
|
27107
27133
|
return null;
|
|
27108
27134
|
return { tests_passed: int(passed), tests_failed: int(failed) };
|
|
27109
|
-
}
|
|
27135
|
+
},
|
|
27136
|
+
summaries: (out) => Math.max(countLines(out, /^\s*\d+ tests? passed\b/gm), countLines(out, /^\s*\d+ tests? failed\b/gm))
|
|
27110
27137
|
},
|
|
27111
27138
|
{
|
|
27112
27139
|
// uvu: a `Total:` / `Passed:` / `Skipped:` block.
|
|
@@ -27119,7 +27146,8 @@ var init_classify2 = __esm({
|
|
|
27119
27146
|
const t = int(total);
|
|
27120
27147
|
const p = int(passed);
|
|
27121
27148
|
return { tests_passed: p, tests_failed: Math.max(0, t - p) };
|
|
27122
|
-
}
|
|
27149
|
+
},
|
|
27150
|
+
summaries: (out) => countLines(out, /^\s*Total:\s+\d+/gm)
|
|
27123
27151
|
},
|
|
27124
27152
|
{
|
|
27125
27153
|
/**
|
|
@@ -27154,6 +27182,7 @@ var init_classify2 = __esm({
|
|
|
27154
27182
|
* those would double them against their parent.
|
|
27155
27183
|
*/
|
|
27156
27184
|
runner: "bare TAP",
|
|
27185
|
+
shadowedBy: ["node --test (TAP)", "node-tap"],
|
|
27157
27186
|
read: (out) => {
|
|
27158
27187
|
let n = 0;
|
|
27159
27188
|
let failed = 0;
|
|
@@ -30899,9 +30928,9 @@ function renderVerdictLine(r) {
|
|
|
30899
30928
|
const t = fmtMs(r.wallMs);
|
|
30900
30929
|
switch (r.outcome) {
|
|
30901
30930
|
case "completed":
|
|
30902
|
-
return `GREEN ${String(r.counts?.tests_passed ?? 0)} test(s) passed, none failed
|
|
30931
|
+
return `GREEN ${String(r.counts?.tests_passed ?? 0)} test(s) passed, none failed ` + (r.counts?.coverage === "partial" ? `(${PARTIAL_COUNTS_NOTE}) ` : "") + `\u2014 ${t}${r.preview ? ` \u2014 ${r.preview.url}` : ""}`;
|
|
30903
30932
|
case "tests-failed":
|
|
30904
|
-
return `RED ${r.counts ? `${String(r.counts.tests_failed)} test(s) failed` : `exit ${String(r.exitCode)}`} \u2014 ${t}${r.preview ? ` \u2014 ${r.preview.url}` : ""}`;
|
|
30933
|
+
return `RED ${r.counts ? `${String(r.counts.tests_failed)} test(s) failed` : `exit ${String(r.exitCode)}`}` + (r.counts?.coverage === "partial" ? ` (${PARTIAL_COUNTS_NOTE})` : "") + ` \u2014 ${t}${r.preview ? ` \u2014 ${r.preview.url}` : ""}`;
|
|
30905
30934
|
case "no-tests-observed":
|
|
30906
30935
|
return `NOTHING RAN the suite reported zero tests passed and zero failed \u2014 ${t}`;
|
|
30907
30936
|
case "counts-unparsed":
|
|
@@ -30955,7 +30984,7 @@ function exitCodeFor(r) {
|
|
|
30955
30984
|
return 2;
|
|
30956
30985
|
return exitCodeForOutcome(r.outcome);
|
|
30957
30986
|
}
|
|
30958
|
-
var RUN_TEST_COMMAND_SOURCES, RUN_IMAGE_SOURCES, RUN_RESULT_SCHEMA, RUN_RESULT_FIELDS, RENDER_NONE, FIELD_VIEWS;
|
|
30987
|
+
var RUN_TEST_COMMAND_SOURCES, RUN_IMAGE_SOURCES, RUN_RESULT_SCHEMA, PARTIAL_COUNTS_NOTE, RUN_RESULT_FIELDS, RENDER_NONE, FIELD_VIEWS;
|
|
30959
30988
|
var init_result = __esm({
|
|
30960
30989
|
"../../packages/envrun/dist/result.js"() {
|
|
30961
30990
|
"use strict";
|
|
@@ -30978,6 +31007,7 @@ var init_result = __esm({
|
|
|
30978
31007
|
"founder-declared"
|
|
30979
31008
|
];
|
|
30980
31009
|
RUN_RESULT_SCHEMA = "terminalhire.verification-run/1";
|
|
31010
|
+
PARTIAL_COUNTS_NOTE = "from one of several test summaries in the output, so not a total for the whole run";
|
|
30981
31011
|
RUN_RESULT_FIELDS = [
|
|
30982
31012
|
"schema",
|
|
30983
31013
|
"runId",
|
|
@@ -31023,7 +31053,7 @@ var init_result = __esm({
|
|
|
31023
31053
|
testCommand: (r) => r.testCommand === null ? null : `test command ${r.testCommand}`,
|
|
31024
31054
|
testOutputTail: RENDER_NONE,
|
|
31025
31055
|
// printed as a block below the fields, when red
|
|
31026
|
-
counts: (r) => r.counts === null ? null : `tests ${String(r.counts.tests_passed)} passed, ${String(r.counts.tests_failed)} failed (${r.counts.runner})
|
|
31056
|
+
counts: (r) => r.counts === null ? null : `tests ${String(r.counts.tests_passed)} passed, ${String(r.counts.tests_failed)} failed (${r.counts.runner})` + (r.counts.coverage === "partial" ? ` \u2014 ${PARTIAL_COUNTS_NOTE}` : ""),
|
|
31027
31057
|
wallMs: (r) => `round trip ${fmtMs(r.wallMs)}`,
|
|
31028
31058
|
installMs: (r) => r.installMs === void 0 ? null : `install step ${fmtMs(r.installMs)}`,
|
|
31029
31059
|
testMs: (r) => r.testMs === void 0 ? null : `test step ${fmtMs(r.testMs)}`,
|
|
@@ -31122,7 +31152,11 @@ function toTestRunResult(result, outputSha256) {
|
|
|
31122
31152
|
return {
|
|
31123
31153
|
exit_code: result.exitCode ?? -1,
|
|
31124
31154
|
...outputSha256 === void 0 ? {} : { output_sha256: outputSha256 },
|
|
31125
|
-
...result.counts === null ? {} : {
|
|
31155
|
+
...result.counts === null ? {} : {
|
|
31156
|
+
tests_passed: result.counts.tests_passed,
|
|
31157
|
+
tests_failed: result.counts.tests_failed,
|
|
31158
|
+
...result.counts.coverage === "partial" ? { tests_coverage: "partial" } : {}
|
|
31159
|
+
}
|
|
31126
31160
|
};
|
|
31127
31161
|
}
|
|
31128
31162
|
function toAcceptancePredicate(pair, opts = {}) {
|
|
@@ -38574,6 +38608,7 @@ __export(dist_exports, {
|
|
|
38574
38608
|
LabelWatch: () => LabelWatch,
|
|
38575
38609
|
MIN_GIT_VERSION_FOR_END_OF_OPTIONS: () => MIN_GIT_VERSION_FOR_END_OF_OPTIONS,
|
|
38576
38610
|
OUTCOME_TO_BUDGET: () => OUTCOME_TO_BUDGET,
|
|
38611
|
+
PARTIAL_COUNTS_NOTE: () => PARTIAL_COUNTS_NOTE,
|
|
38577
38612
|
PATH_REFUSAL_CODES: () => PATH_REFUSAL_CODES,
|
|
38578
38613
|
PLACEMENTS: () => PLACEMENTS,
|
|
38579
38614
|
PLACEMENT_ALIASES: () => PLACEMENT_ALIASES,
|
package/dist/bin/jpi-run.js
CHANGED
|
@@ -582,12 +582,22 @@ function reportedCounts(classified, reparsed) {
|
|
|
582
582
|
function readCounts(stdout, stderr = "") {
|
|
583
583
|
const out = `${stdout}
|
|
584
584
|
${stderr}`;
|
|
585
|
+
const matched = [];
|
|
585
586
|
for (const reader of READERS) {
|
|
586
587
|
const counts = reader.read(out);
|
|
587
588
|
if (counts)
|
|
588
|
-
|
|
589
|
+
matched.push({ reader, counts });
|
|
589
590
|
}
|
|
590
|
-
|
|
591
|
+
const first = matched[0];
|
|
592
|
+
if (first === void 0)
|
|
593
|
+
return null;
|
|
594
|
+
const legs = matched.filter(({ reader }) => !matched.some((m) => reader.shadowedBy?.includes(m.reader.runner)));
|
|
595
|
+
const partial = legs.length > 1 || (first.reader.summaries?.(out) ?? 1) > 1;
|
|
596
|
+
return {
|
|
597
|
+
...first.counts,
|
|
598
|
+
runner: first.reader.runner,
|
|
599
|
+
...partial ? { coverage: "partial" } : {}
|
|
600
|
+
};
|
|
591
601
|
}
|
|
592
602
|
function coverageThresholdUnmet(facts, counts) {
|
|
593
603
|
if (counts === null || counts.runner !== "node-tap")
|
|
@@ -746,7 +756,7 @@ function isGreen(outcome) {
|
|
|
746
756
|
function isOurFault(outcome) {
|
|
747
757
|
return LIMIT_OWNER[outcome] === "ours";
|
|
748
758
|
}
|
|
749
|
-
var VERIFICATION_OUTCOMES, int, withSuiteFailures, READERS, SUPPORTED_RUNNERS, COVERAGE_TABLE, EXEC_FAILURE, SUITE_REPORTED_FAILURE, MISSING_SYSTEM_DEPENDENCY, OFFLINE_BUILD_GAP, LIMIT_OWNER;
|
|
759
|
+
var VERIFICATION_OUTCOMES, int, withSuiteFailures, countLines, READERS, SUPPORTED_RUNNERS, COVERAGE_TABLE, EXEC_FAILURE, SUITE_REPORTED_FAILURE, MISSING_SYSTEM_DEPENDENCY, OFFLINE_BUILD_GAP, LIMIT_OWNER;
|
|
750
760
|
var init_classify = __esm({
|
|
751
761
|
"../../packages/envrun/dist/classify.js"() {
|
|
752
762
|
"use strict";
|
|
@@ -765,6 +775,7 @@ var init_classify = __esm({
|
|
|
765
775
|
return counts;
|
|
766
776
|
return { ...counts, tests_failed: int(/(\d+) failed/.exec(suiteLine[1])) };
|
|
767
777
|
};
|
|
778
|
+
countLines = (out, re) => (out.match(re) ?? []).length;
|
|
768
779
|
READERS = [
|
|
769
780
|
{
|
|
770
781
|
// `node --test` TAP. Anchored to line start, which is what makes it a
|
|
@@ -776,7 +787,10 @@ var init_classify = __esm({
|
|
|
776
787
|
if (!pass || !fail2)
|
|
777
788
|
return null;
|
|
778
789
|
return { tests_passed: int(pass), tests_failed: int(fail2) };
|
|
779
|
-
}
|
|
790
|
+
},
|
|
791
|
+
// One `# pass N` per invocation, so a script that runs `node --test` once per file
|
|
792
|
+
// prints many. envrun's own offline leg printed 67 and was read as the first one's 4.
|
|
793
|
+
summaries: (out) => countLines(out, /^# pass \d+$/gm)
|
|
780
794
|
},
|
|
781
795
|
{
|
|
782
796
|
// node-tap's runner summary, which is NOT the `# pass N` / `# fail N` pair
|
|
@@ -803,7 +817,8 @@ var init_classify = __esm({
|
|
|
803
817
|
tests_passed: int(/\bpass: (\d+)/.exec(line[1])),
|
|
804
818
|
tests_failed: int(/\bfail: (\d+)/.exec(line[1]))
|
|
805
819
|
};
|
|
806
|
-
}
|
|
820
|
+
},
|
|
821
|
+
summaries: (out) => countLines(out, /^# \{ total: \d+[^}\n]* \}$/gm)
|
|
807
822
|
},
|
|
808
823
|
{
|
|
809
824
|
// jest: `Tests: 1 failed, 2 passed, 3 total`
|
|
@@ -816,7 +831,8 @@ var init_classify = __esm({
|
|
|
816
831
|
tests_passed: int(/(\d+) passed/.exec(line[1])),
|
|
817
832
|
tests_failed: int(/(\d+) failed/.exec(line[1]))
|
|
818
833
|
}, /^Test Suites:\s+(.+?)\s*$/m.exec(out));
|
|
819
|
-
}
|
|
834
|
+
},
|
|
835
|
+
summaries: (out) => countLines(out, /^Tests:\s+[^\n]*\btotal\b/gm)
|
|
820
836
|
},
|
|
821
837
|
{
|
|
822
838
|
// vitest: `Tests 3 passed (3)` / `Tests 1 failed | 2 passed (3)`
|
|
@@ -833,7 +849,12 @@ var init_classify = __esm({
|
|
|
833
849
|
if (!passed && !failed)
|
|
834
850
|
return null;
|
|
835
851
|
return withSuiteFailures({ tests_passed: int(passed), tests_failed: int(failed) }, files);
|
|
836
|
-
}
|
|
852
|
+
},
|
|
853
|
+
// One invocation prints one `Test Files` line, and a numeric `Tests` line only when a
|
|
854
|
+
// spec loaded (the every-spec-failed shape above has none). The larger of the two
|
|
855
|
+
// counts invocations without counting a paired block twice; reading `Tests` alone
|
|
856
|
+
// missed an all-failed run that followed a passing one (Codex review).
|
|
857
|
+
summaries: (out) => Math.max(countLines(out, /^\s*Tests\s+[^\n]*\(\d+\)\s*$/gm), countLines(out, /^\s*Test Files\s+[^\n]*\(\d+\)\s*$/gm))
|
|
837
858
|
},
|
|
838
859
|
{
|
|
839
860
|
// pytest summary rule: `===== 297 passed in 0.54s =====`,
|
|
@@ -856,7 +877,10 @@ var init_classify = __esm({
|
|
|
856
877
|
if (!passed && !failed && !errors)
|
|
857
878
|
return null;
|
|
858
879
|
return { tests_passed: int(passed), tests_failed: int(failed) + int(errors) };
|
|
859
|
-
}
|
|
880
|
+
},
|
|
881
|
+
// Only FINAL tallies, which carry pytest's `in 0.54s`. The interim banners the reader
|
|
882
|
+
// skips above carry no duration, and counting them would mark every red run partial.
|
|
883
|
+
summaries: (out) => Math.max(1, countLines(out, /^=+ [^\n]*?(?:passed|failed|error|no tests ran)[^\n]*? in [\d.]+s[^\n]*? =+$/gm))
|
|
860
884
|
},
|
|
861
885
|
{
|
|
862
886
|
// Maven surefire's per-module summary (TERM-1122), measured against surefire
|
|
@@ -918,7 +942,8 @@ var init_classify = __esm({
|
|
|
918
942
|
return null;
|
|
919
943
|
const failed = Number(m[1]);
|
|
920
944
|
return { tests_passed: Number(m[2]) - failed, tests_failed: failed };
|
|
921
|
-
}
|
|
945
|
+
},
|
|
946
|
+
summaries: (out) => Math.max(1, countLines(out, /^\d+% tests passed, \d+ tests? failed out of \d+$/gm))
|
|
922
947
|
},
|
|
923
948
|
{
|
|
924
949
|
// mocha: ` 440 passing (1s)` and ` 2 failing`
|
|
@@ -929,7 +954,8 @@ var init_classify = __esm({
|
|
|
929
954
|
if (!passing && !failing)
|
|
930
955
|
return null;
|
|
931
956
|
return { tests_passed: int(passing), tests_failed: int(failing) };
|
|
932
|
-
}
|
|
957
|
+
},
|
|
958
|
+
summaries: (out) => Math.max(countLines(out, /^\s*\d+ passing\b/gm), countLines(out, /^\s*\d+ failing\b/gm))
|
|
933
959
|
},
|
|
934
960
|
{
|
|
935
961
|
// ava: ` 3 tests passed` / ` 1 test failed`
|
|
@@ -940,7 +966,8 @@ var init_classify = __esm({
|
|
|
940
966
|
if (!passed && !failed)
|
|
941
967
|
return null;
|
|
942
968
|
return { tests_passed: int(passed), tests_failed: int(failed) };
|
|
943
|
-
}
|
|
969
|
+
},
|
|
970
|
+
summaries: (out) => Math.max(countLines(out, /^\s*\d+ tests? passed\b/gm), countLines(out, /^\s*\d+ tests? failed\b/gm))
|
|
944
971
|
},
|
|
945
972
|
{
|
|
946
973
|
// uvu: a `Total:` / `Passed:` / `Skipped:` block.
|
|
@@ -953,7 +980,8 @@ var init_classify = __esm({
|
|
|
953
980
|
const t = int(total);
|
|
954
981
|
const p = int(passed);
|
|
955
982
|
return { tests_passed: p, tests_failed: Math.max(0, t - p) };
|
|
956
|
-
}
|
|
983
|
+
},
|
|
984
|
+
summaries: (out) => countLines(out, /^\s*Total:\s+\d+/gm)
|
|
957
985
|
},
|
|
958
986
|
{
|
|
959
987
|
/**
|
|
@@ -988,6 +1016,7 @@ var init_classify = __esm({
|
|
|
988
1016
|
* those would double them against their parent.
|
|
989
1017
|
*/
|
|
990
1018
|
runner: "bare TAP",
|
|
1019
|
+
shadowedBy: ["node --test (TAP)", "node-tap"],
|
|
991
1020
|
read: (out) => {
|
|
992
1021
|
let n = 0;
|
|
993
1022
|
let failed = 0;
|
|
@@ -4733,9 +4762,9 @@ function renderVerdictLine(r) {
|
|
|
4733
4762
|
const t = fmtMs(r.wallMs);
|
|
4734
4763
|
switch (r.outcome) {
|
|
4735
4764
|
case "completed":
|
|
4736
|
-
return `GREEN ${String(r.counts?.tests_passed ?? 0)} test(s) passed, none failed
|
|
4765
|
+
return `GREEN ${String(r.counts?.tests_passed ?? 0)} test(s) passed, none failed ` + (r.counts?.coverage === "partial" ? `(${PARTIAL_COUNTS_NOTE}) ` : "") + `\u2014 ${t}${r.preview ? ` \u2014 ${r.preview.url}` : ""}`;
|
|
4737
4766
|
case "tests-failed":
|
|
4738
|
-
return `RED ${r.counts ? `${String(r.counts.tests_failed)} test(s) failed` : `exit ${String(r.exitCode)}`} \u2014 ${t}${r.preview ? ` \u2014 ${r.preview.url}` : ""}`;
|
|
4767
|
+
return `RED ${r.counts ? `${String(r.counts.tests_failed)} test(s) failed` : `exit ${String(r.exitCode)}`}` + (r.counts?.coverage === "partial" ? ` (${PARTIAL_COUNTS_NOTE})` : "") + ` \u2014 ${t}${r.preview ? ` \u2014 ${r.preview.url}` : ""}`;
|
|
4739
4768
|
case "no-tests-observed":
|
|
4740
4769
|
return `NOTHING RAN the suite reported zero tests passed and zero failed \u2014 ${t}`;
|
|
4741
4770
|
case "counts-unparsed":
|
|
@@ -4789,7 +4818,7 @@ function exitCodeFor(r) {
|
|
|
4789
4818
|
return 2;
|
|
4790
4819
|
return exitCodeForOutcome(r.outcome);
|
|
4791
4820
|
}
|
|
4792
|
-
var RUN_TEST_COMMAND_SOURCES, RUN_IMAGE_SOURCES, RUN_RESULT_SCHEMA, RUN_RESULT_FIELDS, RENDER_NONE, FIELD_VIEWS;
|
|
4821
|
+
var RUN_TEST_COMMAND_SOURCES, RUN_IMAGE_SOURCES, RUN_RESULT_SCHEMA, PARTIAL_COUNTS_NOTE, RUN_RESULT_FIELDS, RENDER_NONE, FIELD_VIEWS;
|
|
4793
4822
|
var init_result = __esm({
|
|
4794
4823
|
"../../packages/envrun/dist/result.js"() {
|
|
4795
4824
|
"use strict";
|
|
@@ -4812,6 +4841,7 @@ var init_result = __esm({
|
|
|
4812
4841
|
"founder-declared"
|
|
4813
4842
|
];
|
|
4814
4843
|
RUN_RESULT_SCHEMA = "terminalhire.verification-run/1";
|
|
4844
|
+
PARTIAL_COUNTS_NOTE = "from one of several test summaries in the output, so not a total for the whole run";
|
|
4815
4845
|
RUN_RESULT_FIELDS = [
|
|
4816
4846
|
"schema",
|
|
4817
4847
|
"runId",
|
|
@@ -4857,7 +4887,7 @@ var init_result = __esm({
|
|
|
4857
4887
|
testCommand: (r) => r.testCommand === null ? null : `test command ${r.testCommand}`,
|
|
4858
4888
|
testOutputTail: RENDER_NONE,
|
|
4859
4889
|
// printed as a block below the fields, when red
|
|
4860
|
-
counts: (r) => r.counts === null ? null : `tests ${String(r.counts.tests_passed)} passed, ${String(r.counts.tests_failed)} failed (${r.counts.runner})
|
|
4890
|
+
counts: (r) => r.counts === null ? null : `tests ${String(r.counts.tests_passed)} passed, ${String(r.counts.tests_failed)} failed (${r.counts.runner})` + (r.counts.coverage === "partial" ? ` \u2014 ${PARTIAL_COUNTS_NOTE}` : ""),
|
|
4861
4891
|
wallMs: (r) => `round trip ${fmtMs(r.wallMs)}`,
|
|
4862
4892
|
installMs: (r) => r.installMs === void 0 ? null : `install step ${fmtMs(r.installMs)}`,
|
|
4863
4893
|
testMs: (r) => r.testMs === void 0 ? null : `test step ${fmtMs(r.testMs)}`,
|
|
@@ -4956,7 +4986,11 @@ function toTestRunResult(result, outputSha256) {
|
|
|
4956
4986
|
return {
|
|
4957
4987
|
exit_code: result.exitCode ?? -1,
|
|
4958
4988
|
...outputSha256 === void 0 ? {} : { output_sha256: outputSha256 },
|
|
4959
|
-
...result.counts === null ? {} : {
|
|
4989
|
+
...result.counts === null ? {} : {
|
|
4990
|
+
tests_passed: result.counts.tests_passed,
|
|
4991
|
+
tests_failed: result.counts.tests_failed,
|
|
4992
|
+
...result.counts.coverage === "partial" ? { tests_coverage: "partial" } : {}
|
|
4993
|
+
}
|
|
4960
4994
|
};
|
|
4961
4995
|
}
|
|
4962
4996
|
function toAcceptancePredicate(pair, opts = {}) {
|
|
@@ -12583,6 +12617,7 @@ __export(dist_exports, {
|
|
|
12583
12617
|
LabelWatch: () => LabelWatch,
|
|
12584
12618
|
MIN_GIT_VERSION_FOR_END_OF_OPTIONS: () => MIN_GIT_VERSION_FOR_END_OF_OPTIONS,
|
|
12585
12619
|
OUTCOME_TO_BUDGET: () => OUTCOME_TO_BUDGET,
|
|
12620
|
+
PARTIAL_COUNTS_NOTE: () => PARTIAL_COUNTS_NOTE,
|
|
12586
12621
|
PATH_REFUSAL_CODES: () => PATH_REFUSAL_CODES,
|
|
12587
12622
|
PLACEMENTS: () => PLACEMENTS,
|
|
12588
12623
|
PLACEMENT_ALIASES: () => PLACEMENT_ALIASES,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "terminalhire",
|
|
3
|
-
"version": "0.42.
|
|
3
|
+
"version": "0.42.37",
|
|
4
4
|
"description": "Developer jobs and paid bounties, matched in the terminal — ambient matches in the Claude Code spinner. Claim a scoped bounty and get paid when the poster accepts it.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|