terminalhire 0.42.35 → 0.42.36
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 +577 -68
- package/dist/bin/jpi-dispatch.js +608 -80
- package/dist/bin/jpi-mcp.js +588 -73
- package/dist/bin/jpi-run.js +33429 -487
- package/package.json +1 -1
package/dist/bin/jpi-claim.js
CHANGED
|
@@ -30343,6 +30343,10 @@ var init_venueDescriptor = __esm({
|
|
|
30343
30343
|
function fmtMs(ms) {
|
|
30344
30344
|
return ms < 1e3 ? `${String(ms)}ms` : `${(ms / 1e3).toFixed(1)}s`;
|
|
30345
30345
|
}
|
|
30346
|
+
function fmtMinutes(ms) {
|
|
30347
|
+
const min = ms / 6e4;
|
|
30348
|
+
return Number.isInteger(min) ? String(min) : min.toFixed(1);
|
|
30349
|
+
}
|
|
30346
30350
|
function renderVerdictLine(r) {
|
|
30347
30351
|
if (r.status === "refused") {
|
|
30348
30352
|
const first = r.boundaryRefusals[0];
|
|
@@ -30366,7 +30370,7 @@ function renderVerdictLine(r) {
|
|
|
30366
30370
|
case "environment-exhausted":
|
|
30367
30371
|
return `OUR FAULT the run ran out of a resource we cap; your work has not been judged \u2014 ${t}`;
|
|
30368
30372
|
case "budget-exceeded":
|
|
30369
|
-
return `OUR LIMIT we stopped the run at our time limit; this is not a result about the work \u2014 ${t}`;
|
|
30373
|
+
return r.testTimeoutMs === void 0 ? `OUR LIMIT we stopped the run at our time limit; this is not a result about the work \u2014 ${t}` : `OUR LIMIT the ${fmtMinutes(r.testTimeoutMs)}-min test time limit set for this posting stopped the run; this is not a result about the work \u2014 ${t}`;
|
|
30370
30374
|
case null:
|
|
30371
30375
|
throw new Error("a verified run has no outcome \u2014 the result was assembled wrong");
|
|
30372
30376
|
}
|
|
@@ -30388,7 +30392,7 @@ function renderRunReport(r) {
|
|
|
30388
30392
|
if (r.status === "verified" && r.outcome === "counts-unparsed") {
|
|
30389
30393
|
lines.push("", "Your suite exited 0, but we could not read how many tests ran, so this is not a verdict either way.");
|
|
30390
30394
|
} else if (r.status === "verified" && r.outcome === "budget-exceeded") {
|
|
30391
|
-
lines.push("", "Our time limit ended the run; that says nothing about your work.");
|
|
30395
|
+
lines.push("", r.testTimeoutMs === void 0 ? "Our time limit ended the run; that says nothing about your work." : `The ${fmtMinutes(r.testTimeoutMs)}-min test time limit set for this posting ended the run; that says nothing about your work.`);
|
|
30392
30396
|
} else if (r.status === "verified" && r.outcome !== null && isOurFault(r.outcome)) {
|
|
30393
30397
|
lines.push("", "This is an environment failure on our side, not a statement about your work.");
|
|
30394
30398
|
}
|
|
@@ -30445,6 +30449,9 @@ var init_result = __esm({
|
|
|
30445
30449
|
"testOutputTail",
|
|
30446
30450
|
"counts",
|
|
30447
30451
|
"wallMs",
|
|
30452
|
+
"installMs",
|
|
30453
|
+
"testMs",
|
|
30454
|
+
"testTimeoutMs",
|
|
30448
30455
|
"targetRepo",
|
|
30449
30456
|
"targetSha",
|
|
30450
30457
|
"patchSha256",
|
|
@@ -30477,6 +30484,9 @@ var init_result = __esm({
|
|
|
30477
30484
|
// printed as a block below the fields, when red
|
|
30478
30485
|
counts: (r) => r.counts === null ? null : `tests ${String(r.counts.tests_passed)} passed, ${String(r.counts.tests_failed)} failed (${r.counts.runner})`,
|
|
30479
30486
|
wallMs: (r) => `round trip ${fmtMs(r.wallMs)}`,
|
|
30487
|
+
installMs: (r) => r.installMs === void 0 ? null : `install step ${fmtMs(r.installMs)}`,
|
|
30488
|
+
testMs: (r) => r.testMs === void 0 ? null : `test step ${fmtMs(r.testMs)}`,
|
|
30489
|
+
testTimeoutMs: (r) => r.testTimeoutMs === void 0 ? null : `time limit ${fmtMinutes(r.testTimeoutMs)} min`,
|
|
30480
30490
|
targetRepo: (r) => `target ${r.targetRepo}`,
|
|
30481
30491
|
targetSha: (r) => `commit ${r.targetSha.slice(0, 12)}`,
|
|
30482
30492
|
patchSha256: (r) => r.patchSha256 === null ? null : `patch ${r.patchSha256.slice(0, 12)}`,
|
|
@@ -30726,7 +30736,8 @@ var init_attestation2 = __esm({
|
|
|
30726
30736
|
"test-command-unavailable": null,
|
|
30727
30737
|
// null, with the same reasoning as `test-command-unavailable` and NOT
|
|
30728
30738
|
// `budget-exceeded` (TERM-644). A signed `budget-exceeded` records one fact:
|
|
30729
|
-
// the run hit
|
|
30739
|
+
// the run hit the time budget we applied — our default, or the one set for the
|
|
30740
|
+
// posting (TERM-1308), which is still ours to enforce. It blames no one (TERM-1289; `LIMIT_OWNER` in
|
|
30730
30741
|
// `classify.ts` owns that question), and it is not an acceptable run:
|
|
30731
30742
|
// `acceptRun` (`packages/attest/src/verify.ts`) refuses every `budget_outcome`
|
|
30732
30743
|
// except `completed`. Exhausting the tmpfs we sized, or an OOM kill from memory we
|
|
@@ -31425,7 +31436,7 @@ var init_gcpPlacement = __esm({
|
|
|
31425
31436
|
this.name = "GcpPlacementError";
|
|
31426
31437
|
}
|
|
31427
31438
|
};
|
|
31428
|
-
GCP_MAX_RUN_DURATION_SECONDS =
|
|
31439
|
+
GCP_MAX_RUN_DURATION_SECONDS = 10800;
|
|
31429
31440
|
GCP_MANAGED_LABEL_KEY = "th-managed";
|
|
31430
31441
|
GCP_RUN_LABEL_KEY = "th-run";
|
|
31431
31442
|
CONFIDENTIAL_SPACE_MACHINE_TYPE = "n2d-standard-2";
|
|
@@ -33321,9 +33332,9 @@ var init_placement = __esm({
|
|
|
33321
33332
|
});
|
|
33322
33333
|
|
|
33323
33334
|
// ../../packages/envspec/dist/yaml.js
|
|
33324
|
-
function parseYaml(source) {
|
|
33325
|
-
const lines = splitLines(source);
|
|
33326
|
-
const cursor = { lines, index: 0 };
|
|
33335
|
+
function parseYaml(source, limits = {}) {
|
|
33336
|
+
const lines = splitLines(source, limits.maxLineLength ?? Infinity);
|
|
33337
|
+
const cursor = { lines, index: 0, depth: 0, maxDepth: limits.maxDepth ?? Infinity };
|
|
33327
33338
|
skipIgnorable(cursor);
|
|
33328
33339
|
if (cursor.index >= lines.length)
|
|
33329
33340
|
return null;
|
|
@@ -33335,13 +33346,16 @@ function parseYaml(source) {
|
|
|
33335
33346
|
}
|
|
33336
33347
|
return value;
|
|
33337
33348
|
}
|
|
33338
|
-
function splitLines(source) {
|
|
33349
|
+
function splitLines(source, maxLineLength) {
|
|
33339
33350
|
const raw = source.replace(/\r\n/g, "\n").split("\n");
|
|
33340
33351
|
const out = [];
|
|
33341
33352
|
let sawDocumentStart = false;
|
|
33342
33353
|
for (let i = 0; i < raw.length; i += 1) {
|
|
33343
33354
|
const line = raw[i];
|
|
33344
33355
|
const number = i + 1;
|
|
33356
|
+
if (line.length > maxLineLength) {
|
|
33357
|
+
throw new YamlUnsupportedError("line-length", number, `line longer than ${maxLineLength} characters`);
|
|
33358
|
+
}
|
|
33345
33359
|
const withoutIndent = line.replace(/^[ ]+/, "");
|
|
33346
33360
|
const indent = line.length - withoutIndent.length;
|
|
33347
33361
|
if (/^[ ]*\t/.test(line)) {
|
|
@@ -33378,6 +33392,18 @@ function peek(cursor) {
|
|
|
33378
33392
|
return cursor.index < cursor.lines.length ? cursor.lines[cursor.index] : null;
|
|
33379
33393
|
}
|
|
33380
33394
|
function parseNode(cursor, indent) {
|
|
33395
|
+
if (cursor.depth >= cursor.maxDepth) {
|
|
33396
|
+
const at = peek(cursor);
|
|
33397
|
+
throw new YamlUnsupportedError("depth", at?.number ?? 0, `nesting deeper than ${cursor.maxDepth}`);
|
|
33398
|
+
}
|
|
33399
|
+
cursor.depth += 1;
|
|
33400
|
+
try {
|
|
33401
|
+
return parseNodeAt(cursor, indent);
|
|
33402
|
+
} finally {
|
|
33403
|
+
cursor.depth -= 1;
|
|
33404
|
+
}
|
|
33405
|
+
}
|
|
33406
|
+
function parseNodeAt(cursor, indent) {
|
|
33381
33407
|
const line = peek(cursor);
|
|
33382
33408
|
if (line === null)
|
|
33383
33409
|
return null;
|
|
@@ -33797,6 +33823,178 @@ var init_database = __esm({
|
|
|
33797
33823
|
}
|
|
33798
33824
|
});
|
|
33799
33825
|
|
|
33826
|
+
// ../../packages/envspec/dist/semverRange.js
|
|
33827
|
+
function rangeAdmits(version, range) {
|
|
33828
|
+
const locked = parseVersion(version);
|
|
33829
|
+
if (locked === null || range.length > MAX_RANGE_LENGTH)
|
|
33830
|
+
return null;
|
|
33831
|
+
let unknown = false;
|
|
33832
|
+
for (const alternative of range.split("||")) {
|
|
33833
|
+
const interval = parseSet(alternative);
|
|
33834
|
+
if (interval === null) {
|
|
33835
|
+
unknown = true;
|
|
33836
|
+
continue;
|
|
33837
|
+
}
|
|
33838
|
+
if (within(locked, interval))
|
|
33839
|
+
return true;
|
|
33840
|
+
}
|
|
33841
|
+
return unknown ? null : false;
|
|
33842
|
+
}
|
|
33843
|
+
function parseVersion(text) {
|
|
33844
|
+
const m = /^v?(\d+)\.(\d+)\.(\d+)(?:\+[0-9A-Za-z.-]+)?$/.exec(text.trim());
|
|
33845
|
+
if (m === null || !NUMBER.test(m[1]) || !NUMBER.test(m[2]) || !NUMBER.test(m[3]))
|
|
33846
|
+
return null;
|
|
33847
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
33848
|
+
}
|
|
33849
|
+
function parseSet(text) {
|
|
33850
|
+
const set = text.trim();
|
|
33851
|
+
if (set === "")
|
|
33852
|
+
return { low: null, high: null };
|
|
33853
|
+
const hyphen = /^(\S+)\s+-\s+(\S+)$/.exec(set);
|
|
33854
|
+
if (hyphen !== null) {
|
|
33855
|
+
const from = parsePartial(hyphen[1]);
|
|
33856
|
+
const to = parsePartial(hyphen[2]);
|
|
33857
|
+
if (from === null || to === null)
|
|
33858
|
+
return null;
|
|
33859
|
+
return intersect(atLeast2(from), atMost(to));
|
|
33860
|
+
}
|
|
33861
|
+
const comparators = set.replace(/(<=|>=|<|>|=|~>|~|\^)\s+/g, "$1").split(/\s+/);
|
|
33862
|
+
let interval = { low: null, high: null };
|
|
33863
|
+
for (const comparator of comparators) {
|
|
33864
|
+
const next = parseComparator(comparator);
|
|
33865
|
+
if (next === null)
|
|
33866
|
+
return null;
|
|
33867
|
+
interval = intersect(interval, next);
|
|
33868
|
+
}
|
|
33869
|
+
return interval;
|
|
33870
|
+
}
|
|
33871
|
+
function parsePartial(text) {
|
|
33872
|
+
const m = /^v?([^.]+)(?:\.([^.]+))?(?:\.([^.+]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(text);
|
|
33873
|
+
if (m === null)
|
|
33874
|
+
return null;
|
|
33875
|
+
const parts = [];
|
|
33876
|
+
let wild = false;
|
|
33877
|
+
for (const part of [m[1], m[2], m[3]]) {
|
|
33878
|
+
if (part === void 0 || /^[xX*]$/.test(part)) {
|
|
33879
|
+
wild = true;
|
|
33880
|
+
parts.push(null);
|
|
33881
|
+
continue;
|
|
33882
|
+
}
|
|
33883
|
+
if (wild || !NUMBER.test(part))
|
|
33884
|
+
return null;
|
|
33885
|
+
parts.push(Number(part));
|
|
33886
|
+
}
|
|
33887
|
+
return { major: parts[0] ?? null, minor: parts[1] ?? null, patch: parts[2] ?? null };
|
|
33888
|
+
}
|
|
33889
|
+
function parseComparator(text) {
|
|
33890
|
+
const m = /^(<=|>=|<|>|=|~>|~|\^)?(.*)$/.exec(text);
|
|
33891
|
+
if (m === null)
|
|
33892
|
+
return null;
|
|
33893
|
+
const operator = m[1] ?? "";
|
|
33894
|
+
const partial = parsePartial(m[2]);
|
|
33895
|
+
if (partial === null)
|
|
33896
|
+
return null;
|
|
33897
|
+
const { major, minor, patch } = partial;
|
|
33898
|
+
if (major === null) {
|
|
33899
|
+
return operator === "" || operator === "=" || operator === ">=" ? { low: null, high: null } : null;
|
|
33900
|
+
}
|
|
33901
|
+
switch (operator) {
|
|
33902
|
+
case "":
|
|
33903
|
+
case "=":
|
|
33904
|
+
return intersect(atLeast2(partial), atMost(partial));
|
|
33905
|
+
case ">=":
|
|
33906
|
+
return atLeast2(partial);
|
|
33907
|
+
case "<=":
|
|
33908
|
+
return atMost(partial);
|
|
33909
|
+
case ">":
|
|
33910
|
+
return { low: { at: bumpPartial(partial), inclusive: true }, high: null };
|
|
33911
|
+
case "<":
|
|
33912
|
+
return { low: null, high: { at: floor(partial), inclusive: false } };
|
|
33913
|
+
case "~":
|
|
33914
|
+
case "~>":
|
|
33915
|
+
return {
|
|
33916
|
+
low: { at: floor(partial), inclusive: true },
|
|
33917
|
+
high: { at: minor === null ? [major + 1, 0, 0] : [major, minor + 1, 0], inclusive: false }
|
|
33918
|
+
};
|
|
33919
|
+
case "^": {
|
|
33920
|
+
let high;
|
|
33921
|
+
if (major > 0 || minor === null)
|
|
33922
|
+
high = [major + 1, 0, 0];
|
|
33923
|
+
else if (minor > 0 || patch === null)
|
|
33924
|
+
high = [0, minor + 1, 0];
|
|
33925
|
+
else
|
|
33926
|
+
high = [0, 0, patch + 1];
|
|
33927
|
+
return { low: { at: floor(partial), inclusive: true }, high: { at: high, inclusive: false } };
|
|
33928
|
+
}
|
|
33929
|
+
default:
|
|
33930
|
+
return null;
|
|
33931
|
+
}
|
|
33932
|
+
}
|
|
33933
|
+
function floor(p) {
|
|
33934
|
+
return [p.major ?? 0, p.minor ?? 0, p.patch ?? 0];
|
|
33935
|
+
}
|
|
33936
|
+
function bumpPartial(p) {
|
|
33937
|
+
const major = p.major ?? 0;
|
|
33938
|
+
if (p.minor === null)
|
|
33939
|
+
return [major + 1, 0, 0];
|
|
33940
|
+
if (p.patch === null)
|
|
33941
|
+
return [major, p.minor + 1, 0];
|
|
33942
|
+
return [major, p.minor, p.patch + 1];
|
|
33943
|
+
}
|
|
33944
|
+
function atLeast2(p) {
|
|
33945
|
+
return p.major === null ? { low: null, high: null } : { low: { at: floor(p), inclusive: true }, high: null };
|
|
33946
|
+
}
|
|
33947
|
+
function atMost(p) {
|
|
33948
|
+
if (p.major === null)
|
|
33949
|
+
return { low: null, high: null };
|
|
33950
|
+
if (p.patch !== null && p.minor !== null) {
|
|
33951
|
+
return { low: null, high: { at: [p.major, p.minor, p.patch], inclusive: true } };
|
|
33952
|
+
}
|
|
33953
|
+
return { low: null, high: { at: bumpPartial(p), inclusive: false } };
|
|
33954
|
+
}
|
|
33955
|
+
function compare(a, b) {
|
|
33956
|
+
return a[0] - b[0] || a[1] - b[1] || a[2] - b[2];
|
|
33957
|
+
}
|
|
33958
|
+
function intersect(a, b) {
|
|
33959
|
+
const low = a.low === null ? b.low : b.low === null ? a.low : tighterLow(a.low, b.low);
|
|
33960
|
+
const high = a.high === null ? b.high : b.high === null ? a.high : tighterHigh(a.high, b.high);
|
|
33961
|
+
return { low, high };
|
|
33962
|
+
}
|
|
33963
|
+
function tighterLow(a, b) {
|
|
33964
|
+
const c = compare(a.at, b.at);
|
|
33965
|
+
if (c !== 0)
|
|
33966
|
+
return c > 0 ? a : b;
|
|
33967
|
+
return a.inclusive ? b : a;
|
|
33968
|
+
}
|
|
33969
|
+
function tighterHigh(a, b) {
|
|
33970
|
+
const c = compare(a.at, b.at);
|
|
33971
|
+
if (c !== 0)
|
|
33972
|
+
return c < 0 ? a : b;
|
|
33973
|
+
return a.inclusive ? b : a;
|
|
33974
|
+
}
|
|
33975
|
+
function within(v, interval) {
|
|
33976
|
+
const { low, high } = interval;
|
|
33977
|
+
if (low !== null) {
|
|
33978
|
+
const c = compare(v, low.at);
|
|
33979
|
+
if (c < 0 || c === 0 && !low.inclusive)
|
|
33980
|
+
return false;
|
|
33981
|
+
}
|
|
33982
|
+
if (high !== null) {
|
|
33983
|
+
const c = compare(v, high.at);
|
|
33984
|
+
if (c > 0 || c === 0 && !high.inclusive)
|
|
33985
|
+
return false;
|
|
33986
|
+
}
|
|
33987
|
+
return true;
|
|
33988
|
+
}
|
|
33989
|
+
var MAX_RANGE_LENGTH, NUMBER;
|
|
33990
|
+
var init_semverRange = __esm({
|
|
33991
|
+
"../../packages/envspec/dist/semverRange.js"() {
|
|
33992
|
+
"use strict";
|
|
33993
|
+
MAX_RANGE_LENGTH = 1024;
|
|
33994
|
+
NUMBER = /^(?:0|[1-9]\d{0,15})$/;
|
|
33995
|
+
}
|
|
33996
|
+
});
|
|
33997
|
+
|
|
33800
33998
|
// ../../packages/envspec/dist/manifest.js
|
|
33801
33999
|
function detectRuntime(repo) {
|
|
33802
34000
|
const candidates = [];
|
|
@@ -33878,47 +34076,155 @@ function lockfileGaps(repo) {
|
|
|
33878
34076
|
const pkg = readJsonObject(repo, "package.json");
|
|
33879
34077
|
if (pkg === null)
|
|
33880
34078
|
return null;
|
|
34079
|
+
const lockfile = ["package-lock.json", "npm-shrinkwrap.json", "yarn.lock", "pnpm-lock.yaml"].find((name) => repo.exists(name));
|
|
34080
|
+
if (lockfile === void 0)
|
|
34081
|
+
return null;
|
|
34082
|
+
const listingFor = lockfileListings(repo, pkg, lockfile);
|
|
34083
|
+
if (listingFor === null)
|
|
34084
|
+
return null;
|
|
34085
|
+
const missing = [];
|
|
34086
|
+
const rootListing = listingFor("");
|
|
34087
|
+
if (rootListing !== null) {
|
|
34088
|
+
for (const [n, r, sec] of wantedDependencies(pkg))
|
|
34089
|
+
if (!rootListing(n, r, sec))
|
|
34090
|
+
missing.push(`${n}@${r}`);
|
|
34091
|
+
}
|
|
34092
|
+
for (const dir of workspaceDirs(repo, pkg, lockfile)) {
|
|
34093
|
+
const listing = listingFor(dir);
|
|
34094
|
+
const manifest = readJsonObject(repo, `${dir}/package.json`);
|
|
34095
|
+
if (listing === null || manifest === null)
|
|
34096
|
+
continue;
|
|
34097
|
+
for (const [n, r, sec] of wantedDependencies(manifest)) {
|
|
34098
|
+
if (!listing(n, r, sec))
|
|
34099
|
+
missing.push(`${n}@${r} (${dir})`);
|
|
34100
|
+
}
|
|
34101
|
+
}
|
|
34102
|
+
return missing.length === 0 ? null : { lockfile, missing };
|
|
34103
|
+
}
|
|
34104
|
+
function wantedDependencies(pkg) {
|
|
33881
34105
|
const wanted = [];
|
|
34106
|
+
const optional = readObjectField(pkg, "optionalDependencies");
|
|
33882
34107
|
for (const section of DEPENDENCY_SECTIONS) {
|
|
33883
34108
|
const deps = readObjectField(pkg, section);
|
|
33884
34109
|
if (deps === null)
|
|
33885
34110
|
continue;
|
|
33886
34111
|
for (const [name, range] of Object.entries(deps)) {
|
|
34112
|
+
if (section === "dependencies" && readStringField(optional, name) !== null)
|
|
34113
|
+
continue;
|
|
33887
34114
|
if (typeof range === "string")
|
|
33888
|
-
wanted.push([name, range]);
|
|
34115
|
+
wanted.push([name, range, section]);
|
|
33889
34116
|
}
|
|
33890
34117
|
}
|
|
33891
|
-
|
|
33892
|
-
|
|
33893
|
-
|
|
33894
|
-
|
|
33895
|
-
|
|
33896
|
-
|
|
33897
|
-
return missing.length === 0 ? null : { lockfile, missing };
|
|
33898
|
-
};
|
|
33899
|
-
for (const lockfile of ["package-lock.json", "npm-shrinkwrap.json"]) {
|
|
33900
|
-
if (repo.exists(lockfile))
|
|
33901
|
-
return check(lockfile, npmLockListing(repo, lockfile));
|
|
34118
|
+
return wanted;
|
|
34119
|
+
}
|
|
34120
|
+
function lockfileListings(repo, pkg, lockfile) {
|
|
34121
|
+
if (lockfile === "yarn.lock") {
|
|
34122
|
+
const root = yarnLockListing(repo.readText(lockfile));
|
|
34123
|
+
return root === null ? null : (dir) => dir === "" ? root : null;
|
|
33902
34124
|
}
|
|
33903
|
-
if (
|
|
33904
|
-
|
|
33905
|
-
|
|
33906
|
-
|
|
34125
|
+
if (lockfile === "pnpm-lock.yaml") {
|
|
34126
|
+
const text = repo.readText(lockfile);
|
|
34127
|
+
const importers = pnpmImporters(text);
|
|
34128
|
+
const settings = pnpmSettings(text);
|
|
34129
|
+
const overrides = pnpmOverrides(text);
|
|
34130
|
+
if (importers === null || settings === null || overrides === null)
|
|
34131
|
+
return null;
|
|
34132
|
+
const honoured = sameOverrides(overrides, declaredPnpmOverrides(repo, pkg)) ? overrides : /* @__PURE__ */ new Map();
|
|
34133
|
+
const withOverrides = (listing) => (name, range, section) => {
|
|
34134
|
+
const override = honoured.get(name);
|
|
34135
|
+
return listing(name, range, section) || override !== void 0 && listing(name, override, section);
|
|
34136
|
+
};
|
|
34137
|
+
const withSettings = (listing) => (name, range, section) => !settings.autoInstallPeers && section === "peerDependencies" || settings.excludeLinksFromLockfile && range.startsWith("link:") || listing(name, range, section);
|
|
34138
|
+
const workspaceAware = text !== null && /^importers:/m.test(text);
|
|
34139
|
+
return (dir) => {
|
|
34140
|
+
const importer = importers.get(dir === "" ? "." : dir);
|
|
34141
|
+
if (importer !== void 0)
|
|
34142
|
+
return withSettings(withOverrides(pnpmImporterListing(importer)));
|
|
34143
|
+
return dir === "" || !workspaceAware ? null : () => false;
|
|
34144
|
+
};
|
|
33907
34145
|
}
|
|
33908
|
-
return
|
|
34146
|
+
return npmLockListings(repo, lockfile);
|
|
33909
34147
|
}
|
|
33910
|
-
function
|
|
34148
|
+
function npmLockListings(repo, lockfile) {
|
|
33911
34149
|
const lock = readJsonObject(repo, lockfile);
|
|
33912
34150
|
if (lock === null)
|
|
33913
34151
|
return null;
|
|
33914
|
-
const
|
|
33915
|
-
if (
|
|
33916
|
-
return (
|
|
34152
|
+
const packages = readObjectField(lock, "packages");
|
|
34153
|
+
if (readObjectField(packages, "") !== null) {
|
|
34154
|
+
return (dir) => {
|
|
34155
|
+
const entry = readObjectField(packages, dir);
|
|
34156
|
+
if (entry === null)
|
|
34157
|
+
return () => false;
|
|
34158
|
+
return (name, range) => DEPENDENCY_SECTIONS.some((s) => readStringField(readObjectField(entry, s), name) === range);
|
|
34159
|
+
};
|
|
33917
34160
|
}
|
|
33918
34161
|
const v1 = readObjectField(lock, "dependencies");
|
|
33919
34162
|
if (v1 === null)
|
|
33920
34163
|
return null;
|
|
33921
|
-
|
|
34164
|
+
const root = (name, range) => {
|
|
34165
|
+
const entry = readObjectField(v1, name);
|
|
34166
|
+
if (entry === null)
|
|
34167
|
+
return false;
|
|
34168
|
+
const version = readStringField(entry, "version");
|
|
34169
|
+
return version === null ? true : rangeAdmits(version, range) ?? true;
|
|
34170
|
+
};
|
|
34171
|
+
return (dir) => dir === "" ? root : null;
|
|
34172
|
+
}
|
|
34173
|
+
function workspaceDirs(repo, pkg, lockfile) {
|
|
34174
|
+
let patterns;
|
|
34175
|
+
if (lockfile === "pnpm-lock.yaml") {
|
|
34176
|
+
const text = repo.readText("pnpm-workspace.yaml");
|
|
34177
|
+
try {
|
|
34178
|
+
patterns = text === null ? [] : asStringList(mapGet(parseYaml(text, PNPM_LIMITS), "packages"));
|
|
34179
|
+
} catch (err) {
|
|
34180
|
+
if (!(err instanceof YamlUnsupportedError))
|
|
34181
|
+
throw err;
|
|
34182
|
+
patterns = [];
|
|
34183
|
+
}
|
|
34184
|
+
} else {
|
|
34185
|
+
const field = pkg["workspaces"];
|
|
34186
|
+
patterns = Array.isArray(field) ? field : readObjectField(pkg, "workspaces")?.["packages"];
|
|
34187
|
+
}
|
|
34188
|
+
if (!Array.isArray(patterns))
|
|
34189
|
+
return [];
|
|
34190
|
+
const budget = { visits: 0 };
|
|
34191
|
+
const included = /* @__PURE__ */ new Set();
|
|
34192
|
+
const excluded = /* @__PURE__ */ new Set();
|
|
34193
|
+
for (const raw of patterns) {
|
|
34194
|
+
if (typeof raw !== "string")
|
|
34195
|
+
continue;
|
|
34196
|
+
const negated = raw.startsWith("!");
|
|
34197
|
+
const pattern = (negated ? raw.slice(1) : raw).replace(/^\.\//, "").replace(/\/+$/, "");
|
|
34198
|
+
const segments = pattern.split("/");
|
|
34199
|
+
if (pattern === "" || /[{}[\]\\]/.test(pattern) || segments.some((s) => s === ".." || s === "." || s === "")) {
|
|
34200
|
+
continue;
|
|
34201
|
+
}
|
|
34202
|
+
for (const dir of matchSegments(repo, "", segments, 0, budget))
|
|
34203
|
+
(negated ? excluded : included).add(dir);
|
|
34204
|
+
}
|
|
34205
|
+
const manifestOf = (dir) => `${dir}/package.json`;
|
|
34206
|
+
return [...included].filter((dir) => !excluded.has(dir) && dir !== "" && readJsonObject(repo, manifestOf(dir)) !== null).sort().slice(0, WORKSPACE_LIMITS.maxWorkspaces);
|
|
34207
|
+
}
|
|
34208
|
+
function matchSegments(repo, base, segments, depth, budget) {
|
|
34209
|
+
if (segments.length === 0)
|
|
34210
|
+
return [base];
|
|
34211
|
+
if (depth > WORKSPACE_LIMITS.maxDepth || budget.visits >= WORKSPACE_LIMITS.maxVisits)
|
|
34212
|
+
return [];
|
|
34213
|
+
budget.visits += 1;
|
|
34214
|
+
const [head, ...rest] = segments;
|
|
34215
|
+
const at = (name) => base === "" ? name : `${base}/${name}`;
|
|
34216
|
+
const children = () => repo.listNames(base).filter((n) => n !== "node_modules" && !n.startsWith(".") && repo.isDirectory(at(n)));
|
|
34217
|
+
if (head === "**") {
|
|
34218
|
+
return [
|
|
34219
|
+
...matchSegments(repo, base, rest, depth + 1, budget),
|
|
34220
|
+
...children().flatMap((n) => matchSegments(repo, at(n), segments, depth + 1, budget))
|
|
34221
|
+
];
|
|
34222
|
+
}
|
|
34223
|
+
if (!/[*?]/.test(head)) {
|
|
34224
|
+
return head !== "node_modules" && repo.isDirectory(at(head)) ? matchSegments(repo, at(head), rest, depth + 1, budget) : [];
|
|
34225
|
+
}
|
|
34226
|
+
const re = new RegExp(`^${head.replace(/[.+^$()|]/g, "\\$&").replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]")}$`);
|
|
34227
|
+
return children().filter((n) => re.test(n)).flatMap((n) => matchSegments(repo, at(n), rest, depth + 1, budget));
|
|
33922
34228
|
}
|
|
33923
34229
|
function yarnLockListing(text) {
|
|
33924
34230
|
if (text === null || !/^(# yarn lockfile v1|__metadata:)/m.test(text))
|
|
@@ -33937,40 +34243,120 @@ function yarnLockListing(text) {
|
|
|
33937
34243
|
}
|
|
33938
34244
|
return (name, range) => specs.has(`${name}@${range}`);
|
|
33939
34245
|
}
|
|
33940
|
-
function
|
|
33941
|
-
|
|
34246
|
+
function pnpmImporterListing(importer) {
|
|
34247
|
+
return (name, range) => asString(mapGet(mapGet(importer, "specifiers"), name)) === range || PNPM_SECTIONS.some((section) => asString(mapGet(mapGet(mapGet(importer, section), name), "specifier")) === range);
|
|
34248
|
+
}
|
|
34249
|
+
function pnpmSettings(text) {
|
|
34250
|
+
if (text === null)
|
|
33942
34251
|
return null;
|
|
33943
|
-
const
|
|
33944
|
-
|
|
34252
|
+
const block = topLevelBlock(text.replace(/\r\n/g, "\n").split("\n"), "settings");
|
|
34253
|
+
let node = null;
|
|
34254
|
+
try {
|
|
34255
|
+
node = block === null ? null : mapGet(parseYaml(block, PNPM_LIMITS), "settings");
|
|
34256
|
+
} catch (err) {
|
|
34257
|
+
if (err instanceof YamlUnsupportedError)
|
|
34258
|
+
return null;
|
|
34259
|
+
throw err;
|
|
34260
|
+
}
|
|
34261
|
+
return {
|
|
34262
|
+
autoInstallPeers: asString(mapGet(node, "autoInstallPeers")) !== "false",
|
|
34263
|
+
excludeLinksFromLockfile: asString(mapGet(node, "excludeLinksFromLockfile")) === "true"
|
|
34264
|
+
};
|
|
34265
|
+
}
|
|
34266
|
+
function pnpmOverrides(text) {
|
|
34267
|
+
if (text === null)
|
|
33945
34268
|
return null;
|
|
33946
|
-
const
|
|
33947
|
-
|
|
33948
|
-
|
|
33949
|
-
|
|
33950
|
-
|
|
33951
|
-
|
|
33952
|
-
|
|
33953
|
-
|
|
33954
|
-
|
|
34269
|
+
const block = topLevelBlock(text.replace(/\r\n/g, "\n").split("\n"), "overrides");
|
|
34270
|
+
if (block === null)
|
|
34271
|
+
return /* @__PURE__ */ new Map();
|
|
34272
|
+
let node;
|
|
34273
|
+
try {
|
|
34274
|
+
node = mapGet(parseYaml(block, PNPM_LIMITS), "overrides");
|
|
34275
|
+
} catch (err) {
|
|
34276
|
+
if (err instanceof YamlUnsupportedError)
|
|
34277
|
+
return null;
|
|
34278
|
+
throw err;
|
|
34279
|
+
}
|
|
34280
|
+
if (node === null)
|
|
34281
|
+
return /* @__PURE__ */ new Map();
|
|
34282
|
+
if (!isMap(node))
|
|
34283
|
+
return null;
|
|
34284
|
+
const overrides = /* @__PURE__ */ new Map();
|
|
34285
|
+
for (const { key, value } of node.entries) {
|
|
34286
|
+
const spec = asString(value);
|
|
34287
|
+
if (spec === null)
|
|
34288
|
+
return null;
|
|
34289
|
+
overrides.set(key, spec);
|
|
34290
|
+
}
|
|
34291
|
+
return overrides;
|
|
33955
34292
|
}
|
|
33956
|
-
function
|
|
33957
|
-
const
|
|
33958
|
-
|
|
33959
|
-
|
|
33960
|
-
|
|
34293
|
+
function declaredPnpmOverrides(repo, pkg) {
|
|
34294
|
+
const sources = [
|
|
34295
|
+
readObjectField(readObjectField(pkg, "pnpm"), "overrides"),
|
|
34296
|
+
readObjectField(pkg, "resolutions")
|
|
34297
|
+
];
|
|
34298
|
+
const workspace = repo.readText("pnpm-workspace.yaml");
|
|
34299
|
+
if (workspace !== null) {
|
|
34300
|
+
let node;
|
|
34301
|
+
try {
|
|
34302
|
+
node = mapGet(parseYaml(workspace, PNPM_LIMITS), "overrides");
|
|
34303
|
+
} catch (err) {
|
|
34304
|
+
if (err instanceof YamlUnsupportedError)
|
|
34305
|
+
return null;
|
|
34306
|
+
throw err;
|
|
34307
|
+
}
|
|
34308
|
+
if (node !== null && !isMap(node))
|
|
34309
|
+
return null;
|
|
34310
|
+
if (isMap(node))
|
|
34311
|
+
sources.push(Object.fromEntries(node.entries.map((e) => [e.key, e.value])));
|
|
33961
34312
|
}
|
|
33962
|
-
const
|
|
33963
|
-
|
|
34313
|
+
const declared = /* @__PURE__ */ new Map();
|
|
34314
|
+
for (const source of sources) {
|
|
34315
|
+
for (const [key, value] of Object.entries(source ?? {})) {
|
|
34316
|
+
if (typeof value !== "string")
|
|
34317
|
+
return null;
|
|
34318
|
+
const seen = declared.get(key);
|
|
34319
|
+
if (seen !== void 0 && seen !== value)
|
|
34320
|
+
return null;
|
|
34321
|
+
declared.set(key, value);
|
|
34322
|
+
}
|
|
34323
|
+
}
|
|
34324
|
+
return declared;
|
|
34325
|
+
}
|
|
34326
|
+
function sameOverrides(a, b) {
|
|
34327
|
+
return b !== null && a.size === b.size && [...a].every(([key, value]) => b.get(key) === value);
|
|
34328
|
+
}
|
|
34329
|
+
function pnpmImporters(text) {
|
|
34330
|
+
if (text === null || !/^lockfileVersion:/m.test(text))
|
|
33964
34331
|
return null;
|
|
33965
|
-
const
|
|
33966
|
-
|
|
33967
|
-
|
|
33968
|
-
|
|
33969
|
-
|
|
33970
|
-
|
|
33971
|
-
|
|
34332
|
+
const lines = text.replace(/\r\n/g, "\n").split("\n");
|
|
34333
|
+
try {
|
|
34334
|
+
const importers = topLevelBlock(lines, "importers");
|
|
34335
|
+
if (importers !== null) {
|
|
34336
|
+
const node = mapGet(parseYaml(importers, PNPM_LIMITS), "importers");
|
|
34337
|
+
return isMap(node) ? new Map(node.entries.map((e) => [e.key, e.value])) : null;
|
|
34338
|
+
}
|
|
34339
|
+
const entries = [];
|
|
34340
|
+
for (const key of [...PNPM_SECTIONS, "specifiers"]) {
|
|
34341
|
+
const block = topLevelBlock(lines, key);
|
|
34342
|
+
if (block !== null)
|
|
34343
|
+
entries.push({ key, value: mapGet(parseYaml(block, PNPM_LIMITS), key) });
|
|
34344
|
+
}
|
|
34345
|
+
return /* @__PURE__ */ new Map([[".", { kind: "map", entries }]]);
|
|
34346
|
+
} catch (err) {
|
|
34347
|
+
if (err instanceof YamlUnsupportedError)
|
|
34348
|
+
return null;
|
|
34349
|
+
throw err;
|
|
33972
34350
|
}
|
|
33973
|
-
|
|
34351
|
+
}
|
|
34352
|
+
function topLevelBlock(lines, key) {
|
|
34353
|
+
const start = lines.findIndex((l) => l === `${key}:` || l.startsWith(`${key}: `));
|
|
34354
|
+
if (start === -1)
|
|
34355
|
+
return null;
|
|
34356
|
+
let end = start + 1;
|
|
34357
|
+
while (end < lines.length && (lines[end] === "" || /^[ \t#]/.test(lines[end])))
|
|
34358
|
+
end += 1;
|
|
34359
|
+
return lines.slice(start, end).join("\n");
|
|
33974
34360
|
}
|
|
33975
34361
|
function unfrozenInstall(command) {
|
|
33976
34362
|
const lead = /^(?:(?:sudo|time)\s+|env(?:\s+[A-Za-z_]\w*=\S*)*\s+)*/.exec(command)?.[0] ?? "";
|
|
@@ -34259,10 +34645,12 @@ function matchFirst(text, pattern) {
|
|
|
34259
34645
|
const match2 = pattern.exec(text);
|
|
34260
34646
|
return match2 === null ? null : match2[1];
|
|
34261
34647
|
}
|
|
34262
|
-
var RUNTIME_MANIFESTS, MAKEFILE_NAMES, C_FAMILY_SOURCE, MANIFEST_FILENAMES, JVM_BUILD_FILES, NPM_PLACEHOLDER_TEST, DEPENDENCY_SECTIONS, YARN_MUTABLE, REQUIREMENT_SPECIFIER, CPP_BUILD_FILES, CMAKE_DECLARES_TESTS, EXACT_VERSION;
|
|
34648
|
+
var RUNTIME_MANIFESTS, MAKEFILE_NAMES, C_FAMILY_SOURCE, MANIFEST_FILENAMES, JVM_BUILD_FILES, NPM_PLACEHOLDER_TEST, DEPENDENCY_SECTIONS, WORKSPACE_LIMITS, PNPM_LIMITS, PNPM_SECTIONS, YARN_MUTABLE, REQUIREMENT_SPECIFIER, CPP_BUILD_FILES, CMAKE_DECLARES_TESTS, EXACT_VERSION;
|
|
34263
34649
|
var init_manifest2 = __esm({
|
|
34264
34650
|
"../../packages/envspec/dist/manifest.js"() {
|
|
34265
34651
|
"use strict";
|
|
34652
|
+
init_semverRange();
|
|
34653
|
+
init_yaml();
|
|
34266
34654
|
RUNTIME_MANIFESTS = [
|
|
34267
34655
|
{ runtime: "node", files: ["package.json"] },
|
|
34268
34656
|
{ runtime: "python", files: ["pyproject.toml", "setup.py", "setup.cfg", "requirements.txt"] },
|
|
@@ -34286,6 +34674,9 @@ var init_manifest2 = __esm({
|
|
|
34286
34674
|
"optionalDependencies",
|
|
34287
34675
|
"peerDependencies"
|
|
34288
34676
|
];
|
|
34677
|
+
WORKSPACE_LIMITS = { maxDepth: 8, maxVisits: 2e3, maxWorkspaces: 200 };
|
|
34678
|
+
PNPM_LIMITS = { maxDepth: 8, maxLineLength: 4096 };
|
|
34679
|
+
PNPM_SECTIONS = ["dependencies", "devDependencies", "optionalDependencies"];
|
|
34289
34680
|
YARN_MUTABLE = "YARN_ENABLE_IMMUTABLE_INSTALLS=false";
|
|
34290
34681
|
REQUIREMENT_SPECIFIER = /^[A-Za-z0-9._-]+(\[[A-Za-z0-9._,-]+\])?([<>=!~]=?[A-Za-z0-9._*+-]+(,[<>=!~]=?[A-Za-z0-9._*+-]+)*)?$/;
|
|
34291
34682
|
CPP_BUILD_FILES = [
|
|
@@ -34366,21 +34757,50 @@ var init_references = __esm({
|
|
|
34366
34757
|
});
|
|
34367
34758
|
|
|
34368
34759
|
// ../../packages/envspec/dist/repo.js
|
|
34369
|
-
import { readdirSync as readdirSync4, readFileSync as readFileSync13, statSync as statSync5 } from "fs";
|
|
34760
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync13, realpathSync as realpathSync2, statSync as statSync5 } from "fs";
|
|
34370
34761
|
import { join as join26, relative as relative2, sep as sep7 } from "path";
|
|
34371
34762
|
function createRepoReader(repoPath) {
|
|
34372
34763
|
const resolveIn = (relativePath) => relativePath === "" ? repoPath : join26(repoPath, relativePath);
|
|
34373
34764
|
const toPosix = (absolute) => relative2(repoPath, absolute).split(sep7).join("/");
|
|
34765
|
+
let realRoot;
|
|
34766
|
+
const rootPrefix = () => {
|
|
34767
|
+
if (realRoot === void 0) {
|
|
34768
|
+
try {
|
|
34769
|
+
const real = realpathSync2(repoPath);
|
|
34770
|
+
realRoot = real.endsWith(sep7) ? real : real + sep7;
|
|
34771
|
+
} catch {
|
|
34772
|
+
realRoot = null;
|
|
34773
|
+
}
|
|
34774
|
+
}
|
|
34775
|
+
return realRoot;
|
|
34776
|
+
};
|
|
34777
|
+
const containedPath = (relativePath) => {
|
|
34778
|
+
const prefix = rootPrefix();
|
|
34779
|
+
if (prefix === null)
|
|
34780
|
+
return null;
|
|
34781
|
+
try {
|
|
34782
|
+
const real = realpathSync2(resolveIn(relativePath));
|
|
34783
|
+
return real + sep7 === prefix || real.startsWith(prefix) ? real : null;
|
|
34784
|
+
} catch {
|
|
34785
|
+
return null;
|
|
34786
|
+
}
|
|
34787
|
+
};
|
|
34374
34788
|
const readText = (relativePath) => {
|
|
34789
|
+
const real = containedPath(relativePath);
|
|
34790
|
+
if (real === null)
|
|
34791
|
+
return null;
|
|
34375
34792
|
try {
|
|
34376
|
-
return readFileSync13(
|
|
34793
|
+
return readFileSync13(real, "utf8");
|
|
34377
34794
|
} catch {
|
|
34378
34795
|
return null;
|
|
34379
34796
|
}
|
|
34380
34797
|
};
|
|
34381
34798
|
const statOf = (relativePath) => {
|
|
34799
|
+
const real = containedPath(relativePath);
|
|
34800
|
+
if (real === null)
|
|
34801
|
+
return null;
|
|
34382
34802
|
try {
|
|
34383
|
-
return statSync5(
|
|
34803
|
+
return statSync5(real);
|
|
34384
34804
|
} catch {
|
|
34385
34805
|
return null;
|
|
34386
34806
|
}
|
|
@@ -34426,11 +34846,14 @@ function createRepoReader(repoPath) {
|
|
|
34426
34846
|
const st = statOf(relativeDir);
|
|
34427
34847
|
if (st === null || !st.isDirectory())
|
|
34428
34848
|
return [];
|
|
34849
|
+
let names;
|
|
34429
34850
|
try {
|
|
34430
|
-
|
|
34851
|
+
names = readdirSync4(resolveIn(relativeDir));
|
|
34431
34852
|
} catch {
|
|
34432
34853
|
return [];
|
|
34433
34854
|
}
|
|
34855
|
+
const at = (name) => relativeDir === "" ? name : `${relativeDir}/${name}`;
|
|
34856
|
+
return names.filter((name) => containedPath(at(name)) !== null).sort();
|
|
34434
34857
|
}
|
|
34435
34858
|
};
|
|
34436
34859
|
}
|
|
@@ -36467,6 +36890,12 @@ async function runVerification(req, ctx) {
|
|
|
36467
36890
|
testOutputTail: outputTail,
|
|
36468
36891
|
counts: verdict.counts,
|
|
36469
36892
|
wallMs: Date.now() - startedAt,
|
|
36893
|
+
// TERM-1308: the steps' own durations, which `runEnvironmentSpec` measures, and the
|
|
36894
|
+
// limit applied to the test step. Absent rather than 0 or a default when there is
|
|
36895
|
+
// nothing to report, so a baseline never sizes a budget from a step that did not run.
|
|
36896
|
+
...verdict.install === null ? {} : { installMs: verdict.install.wallMs },
|
|
36897
|
+
...verdict.test === null ? {} : { testMs: verdict.test.wallMs },
|
|
36898
|
+
...req.testTimeoutMs === void 0 ? {} : { testTimeoutMs: req.testTimeoutMs },
|
|
36470
36899
|
targetRepo: publishableTarget(req.targetRepo),
|
|
36471
36900
|
targetSha: req.targetSha,
|
|
36472
36901
|
patchSha256,
|
|
@@ -38045,7 +38474,7 @@ import {
|
|
|
38045
38474
|
renameSync as renameSync6,
|
|
38046
38475
|
existsSync as existsSync14,
|
|
38047
38476
|
lstatSync as lstatSync5,
|
|
38048
|
-
realpathSync as
|
|
38477
|
+
realpathSync as realpathSync3,
|
|
38049
38478
|
rmSync as rmSync10,
|
|
38050
38479
|
readdirSync as readdirSync5,
|
|
38051
38480
|
statSync as statSync6,
|
|
@@ -38810,7 +39239,7 @@ function canonicalPath2(p) {
|
|
|
38810
39239
|
if (typeof p !== "string" || p === "") return p;
|
|
38811
39240
|
const resolved = pathResolve(p);
|
|
38812
39241
|
try {
|
|
38813
|
-
return
|
|
39242
|
+
return realpathSync3.native(resolved);
|
|
38814
39243
|
} catch {
|
|
38815
39244
|
return resolved;
|
|
38816
39245
|
}
|
|
@@ -38891,6 +39320,66 @@ async function fetchFreshClaimablePool() {
|
|
|
38891
39320
|
const contributions = (index?.contribute ?? []).filter((j) => j.source === "contribute");
|
|
38892
39321
|
return [...bounties, ...contributions];
|
|
38893
39322
|
}
|
|
39323
|
+
var BASELINE_STATUSES = /* @__PURE__ */ new Set([
|
|
39324
|
+
"pending",
|
|
39325
|
+
"not-scheduled",
|
|
39326
|
+
"passed",
|
|
39327
|
+
"failed",
|
|
39328
|
+
"unreadable",
|
|
39329
|
+
"no-tests",
|
|
39330
|
+
"over-ceiling",
|
|
39331
|
+
"not-runnable",
|
|
39332
|
+
"not-runnable-policy",
|
|
39333
|
+
"over-cap"
|
|
39334
|
+
]);
|
|
39335
|
+
var MIN_TEST_BUDGET_MINUTES = 5;
|
|
39336
|
+
var MAX_TEST_BUDGET_MINUTES = 120;
|
|
39337
|
+
function baselineFields(b) {
|
|
39338
|
+
const out = {};
|
|
39339
|
+
const m = b?.testBudgetMinutes;
|
|
39340
|
+
if (Number.isInteger(m) && m >= MIN_TEST_BUDGET_MINUTES && m <= MAX_TEST_BUDGET_MINUTES) {
|
|
39341
|
+
out.testBudgetMinutes = m;
|
|
39342
|
+
}
|
|
39343
|
+
if (typeof b?.baselineStatus === "string" && BASELINE_STATUSES.has(b.baselineStatus)) {
|
|
39344
|
+
out.baselineStatus = b.baselineStatus;
|
|
39345
|
+
}
|
|
39346
|
+
if (typeof b?.baselineSha === "string" && /^[0-9a-f]{7,40}$/.test(b.baselineSha)) {
|
|
39347
|
+
out.baselineSha = b.baselineSha;
|
|
39348
|
+
}
|
|
39349
|
+
return out;
|
|
39350
|
+
}
|
|
39351
|
+
function baselineLine({ baselineStatus, baselineSha, testBudgetMinutes } = {}) {
|
|
39352
|
+
const at = typeof baselineSha === "string" ? ` at ${baselineSha.slice(0, 12)}` : "";
|
|
39353
|
+
const limit2 = typeof testBudgetMinutes === "number" ? ` Time limit ${String(testBudgetMinutes)} min.` : "";
|
|
39354
|
+
switch (baselineStatus) {
|
|
39355
|
+
case "passed":
|
|
39356
|
+
return `Tests ran on Terminal Hire's machines${at} and passed.${limit2}`;
|
|
39357
|
+
case "failed":
|
|
39358
|
+
return `Tests ran on Terminal Hire's machines${at} and did not pass.${limit2}`;
|
|
39359
|
+
case "unreadable":
|
|
39360
|
+
return `Tests ran; Terminal Hire could not read the result.${limit2}`;
|
|
39361
|
+
case "no-tests":
|
|
39362
|
+
return `Tests ran and none were observed.${limit2}`;
|
|
39363
|
+
case "over-ceiling":
|
|
39364
|
+
return "Terminal Hire stopped this repository's tests at the 120-min limit.";
|
|
39365
|
+
case "not-runnable":
|
|
39366
|
+
return "Terminal Hire could not run this repository's tests.";
|
|
39367
|
+
case "not-runnable-policy":
|
|
39368
|
+
return "Terminal Hire does not run tests for postings shared at this level.";
|
|
39369
|
+
case "pending":
|
|
39370
|
+
return "Test time being measured.";
|
|
39371
|
+
case "over-cap":
|
|
39372
|
+
return "Test time not measured yet.";
|
|
39373
|
+
default:
|
|
39374
|
+
return null;
|
|
39375
|
+
}
|
|
39376
|
+
}
|
|
39377
|
+
function postingTestBudgetMinutes(bountyId) {
|
|
39378
|
+
if (typeof bountyId !== "string") return null;
|
|
39379
|
+
const job = findClaimableInCache(bountyId);
|
|
39380
|
+
if (!job || job.source !== "bounty") return null;
|
|
39381
|
+
return baselineFields(job.bounty).testBudgetMinutes ?? null;
|
|
39382
|
+
}
|
|
38894
39383
|
function extractClaimableFields(job) {
|
|
38895
39384
|
if (job.source === "contribute") {
|
|
38896
39385
|
const c = job.contribution ?? {};
|
|
@@ -38934,7 +39423,9 @@ function extractClaimableFields(job) {
|
|
|
38934
39423
|
// (`publicRunRequirements`). Carried, never derived here: the CLI has no copy of the
|
|
38935
39424
|
// repository before a claim, and a second derivation could disagree with the one the
|
|
38936
39425
|
// poster saw. Null when the index carries none.
|
|
38937
|
-
runRequirements: b.runRequirements && typeof b.runRequirements === "object" ? b.runRequirements : null
|
|
39426
|
+
runRequirements: b.runRequirements && typeof b.runRequirements === "object" ? b.runRequirements : null,
|
|
39427
|
+
// TERM-1308. Present only when the index row carries them; no key otherwise.
|
|
39428
|
+
...b.bountySource === "founder" ? baselineFields(b) : {}
|
|
38938
39429
|
};
|
|
38939
39430
|
}
|
|
38940
39431
|
function parseGitHubUrl(url) {
|
|
@@ -39545,6 +40036,7 @@ async function resolveBounty(arg) {
|
|
|
39545
40036
|
let founderPosting = false;
|
|
39546
40037
|
let claimMode = "open";
|
|
39547
40038
|
let runRequirements = null;
|
|
40039
|
+
let baseline = {};
|
|
39548
40040
|
let job = findClaimableInCache(arg) ?? (looksLikeShortRef(arg) ? findClaimableByShortRef(arg) : null);
|
|
39549
40041
|
let freshPool;
|
|
39550
40042
|
if (!job && looksLikeShortRef(arg)) {
|
|
@@ -39552,6 +40044,7 @@ async function resolveBounty(arg) {
|
|
|
39552
40044
|
if (freshPool) job = findByShortRefInPool(freshPool, arg);
|
|
39553
40045
|
}
|
|
39554
40046
|
if (job) {
|
|
40047
|
+
let testBudgetMinutes, baselineStatus, baselineSha;
|
|
39555
40048
|
({
|
|
39556
40049
|
bountyId,
|
|
39557
40050
|
title,
|
|
@@ -39562,8 +40055,16 @@ async function resolveBounty(arg) {
|
|
|
39562
40055
|
openPRsAtDiscovery,
|
|
39563
40056
|
founderPosting,
|
|
39564
40057
|
claimMode,
|
|
39565
|
-
runRequirements
|
|
40058
|
+
runRequirements,
|
|
40059
|
+
testBudgetMinutes,
|
|
40060
|
+
baselineStatus,
|
|
40061
|
+
baselineSha
|
|
39566
40062
|
} = extractClaimableFields(job));
|
|
40063
|
+
baseline = {
|
|
40064
|
+
...testBudgetMinutes === void 0 ? {} : { testBudgetMinutes },
|
|
40065
|
+
...baselineStatus === void 0 ? {} : { baselineStatus },
|
|
40066
|
+
...baselineSha === void 0 ? {} : { baselineSha }
|
|
40067
|
+
};
|
|
39567
40068
|
indexNativeId = bountyId;
|
|
39568
40069
|
} else {
|
|
39569
40070
|
const parsed = parseGitHubUrl(arg);
|
|
@@ -39635,7 +40136,8 @@ async function resolveBounty(arg) {
|
|
|
39635
40136
|
founderPosting,
|
|
39636
40137
|
claimMode,
|
|
39637
40138
|
// TERM-1259. Only a founder index hit carries these; every other path is null.
|
|
39638
|
-
runRequirements: runRequirements ?? null
|
|
40139
|
+
runRequirements: runRequirements ?? null,
|
|
40140
|
+
...baseline
|
|
39639
40141
|
};
|
|
39640
40142
|
}
|
|
39641
40143
|
function fmtOpenPRsLine(b) {
|
|
@@ -40344,6 +40846,8 @@ async function cmdPreview(arg, { json } = {}) {
|
|
|
40344
40846
|
openPRs: b.openPRs,
|
|
40345
40847
|
assignees: b.assignees,
|
|
40346
40848
|
contested: isContested(b),
|
|
40849
|
+
// TERM-1308. The posting's test budget and baseline, only when the index carried them.
|
|
40850
|
+
...baselineFields(b),
|
|
40347
40851
|
// Absent on a founder posting — see the scan above. A consumer must read
|
|
40348
40852
|
// "no policy key" as "no policy step exists here", never as "clean".
|
|
40349
40853
|
...policy ? {
|
|
@@ -40374,6 +40878,8 @@ async function cmdPreview(arg, { json } = {}) {
|
|
|
40374
40878
|
console.log(fmtOpenPRsLine(b));
|
|
40375
40879
|
const previewContested = fmtContestedWarning(b);
|
|
40376
40880
|
if (previewContested) console.log(previewContested);
|
|
40881
|
+
const previewBaseline = baselineLine(b);
|
|
40882
|
+
if (previewBaseline) console.log(` tests: ${previewBaseline}`);
|
|
40377
40883
|
if (policy) printPolicySection(policy);
|
|
40378
40884
|
if (process.stdout.isTTY) {
|
|
40379
40885
|
try {
|
|
@@ -44042,6 +44548,8 @@ export {
|
|
|
44042
44548
|
assertNoBooleanPath,
|
|
44043
44549
|
attemptSliceDelivery,
|
|
44044
44550
|
backgroundEnableFailed,
|
|
44551
|
+
baselineFields,
|
|
44552
|
+
baselineLine,
|
|
44045
44553
|
beatFounderPresence,
|
|
44046
44554
|
buildAssignmentComment,
|
|
44047
44555
|
buildPatchSubmission,
|
|
@@ -44094,6 +44602,7 @@ export {
|
|
|
44094
44602
|
pickBodySource,
|
|
44095
44603
|
pickExistingPr,
|
|
44096
44604
|
pickStartableClaim,
|
|
44605
|
+
postingTestBudgetMinutes,
|
|
44097
44606
|
printNextSteps,
|
|
44098
44607
|
printReleaseIsLocalOnly,
|
|
44099
44608
|
printResolveHint,
|