@outerlayer/cli 0.34.0-next.20261026161241 → 0.34.0-next.20261026182624

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.
@@ -1 +1 @@
1
- {"id":"2026-10-26T16:14:37.797Z+2a1ebb8","root":"/home/runner/_work/outerlayer/outerlayer","pkg":"outerlayer"}
1
+ {"id":"2026-10-26T18:28:05.559Z+12e29af","root":"/home/runner/_work/outerlayer/outerlayer","pkg":"outerlayer"}
@@ -1,15 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { probeCredentials } from './chunk-E6OVLJTR.js';
4
- import './chunk-U6AWVO6L.js';
5
- import './chunk-HOUFCUMH.js';
6
- import './chunk-VWZHOFBP.js';
7
- import './chunk-4G4IH4A7.js';
8
- import './chunk-ZVB57WI6.js';
9
- import './chunk-TS3EFB7S.js';
3
+ import { probeCredentials } from './chunk-LTN2YFLR.js';
10
4
  import './chunk-3JVYMD4G.js';
5
+ import './chunk-ERTIEYDG.js';
11
6
  import './chunk-E7R2GIAW.js';
12
7
  import './chunk-MH6QLXUO.js';
8
+ import './chunk-HOUFCUMH.js';
9
+ import './chunk-P3CHDKXD.js';
10
+ import './chunk-TS3EFB7S.js';
11
+ import './chunk-SZU4YCBH.js';
12
+ import './chunk-ZVB57WI6.js';
13
+ import './chunk-6D7H5DMZ.js';
13
14
  import './chunk-P3NPTFLF.js';
14
15
  import './chunk-I3LTIAOR.js';
15
16
  import './chunk-LD3BHLK7.js';
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ import { resolvePackRoot } from './chunk-ZQSANKS4.js';
4
+ import { CHECK_ITEM_REASON_MAX_LENGTH, CheckItemsSchema } from './chunk-EOTMDIYC.js';
5
+ import { createHash } from 'crypto';
6
+ import { join } from 'path';
7
+ import { pathToFileURL } from 'url';
8
+
9
+ createRequire(import.meta.url);
10
+ var ARTIFACT_PROOF_REASON = "Its declared artifact proves it; the judge does not judge artifacts.";
11
+ var NO_CITING_TEST_REASON = "No test cites this criterion, and it declares no artifact proof.";
12
+ var NO_VERDICT_REASON = "The judge gave no result for this criterion.";
13
+ function criterionInputs(input) {
14
+ const paths = [...new Set((input.citations[input.criterion.id] ?? []).map((citation) => citation.path))].sort();
15
+ const hash = createHash("sha256");
16
+ const part = (text) => {
17
+ hash.update(`${Buffer.byteLength(text)}:`);
18
+ hash.update(text);
19
+ };
20
+ part("judge-criterion-v1");
21
+ part(input.brief);
22
+ part(input.criterion.id);
23
+ part(input.criterion.text);
24
+ part(input.criterion.proof ?? "");
25
+ for (const path of paths) {
26
+ part(path);
27
+ part(input.testFiles.get(path) ?? "");
28
+ }
29
+ return hash.digest("hex");
30
+ }
31
+ var HTTPS_LINK = /^https:\/\/\S+$/;
32
+ function refsFor(id, citations) {
33
+ const refs = (citations[id] ?? []).slice(0, 20).map((citation) => ({
34
+ path: citation.path,
35
+ line: citation.line,
36
+ // Only an https link becomes an href on a page; any other is left off rather than refusing the check.
37
+ ...HTTPS_LINK.test(citation.href ?? "") ? { href: citation.href } : {}
38
+ }));
39
+ return refs.length === 0 ? void 0 : refs;
40
+ }
41
+ function planCriteria(input) {
42
+ const previousById = new Map(input.previous.map((item) => [item.id, item]));
43
+ const settled = [];
44
+ const toJudge = [];
45
+ for (const criterion of input.criteria) {
46
+ const inputs = input.inputs.get(criterion.id);
47
+ const base = { id: criterion.id, criterion: criterion.id, ...inputs === void 0 ? {} : { inputs } };
48
+ const refs = refsFor(criterion.id, input.citations);
49
+ if (criterion.proof !== null) {
50
+ settled.push({ ...base, result: "skipped", reason: ARTIFACT_PROOF_REASON });
51
+ continue;
52
+ }
53
+ if (refs === void 0) {
54
+ settled.push({ ...base, result: "fail", reason: NO_CITING_TEST_REASON });
55
+ continue;
56
+ }
57
+ const kept = previousById.get(criterion.id);
58
+ if (kept !== void 0 && inputs !== void 0 && kept.inputs === inputs && (kept.result === "pass" || kept.result === "fail")) {
59
+ settled.push({ ...base, result: kept.result, ...kept.reason === void 0 ? {} : { reason: kept.reason }, refs });
60
+ continue;
61
+ }
62
+ toJudge.push(criterion);
63
+ }
64
+ return { settled, toJudge };
65
+ }
66
+ var MAX_ANSWER_ENTRIES = 500;
67
+ function readAnswer(raw) {
68
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return { ok: false, problem: "expected an object" };
69
+ const { result, items } = raw;
70
+ if (result !== void 0 && result !== "pass" && result !== "fail") return { ok: false, problem: 'result: must be "pass" or "fail"' };
71
+ if (items !== void 0 && !Array.isArray(items)) return { ok: false, problem: "items: must be an array" };
72
+ const entries = items ?? [];
73
+ if (entries.length > MAX_ANSWER_ENTRIES) return { ok: false, problem: `items: at most ${MAX_ANSWER_ENTRIES} entries` };
74
+ const read = [];
75
+ for (const [index, entry] of entries.entries()) {
76
+ const { id, result: itemResult, reason } = typeof entry === "object" && entry !== null ? entry : {};
77
+ if (typeof id !== "string" || id === "" || id.length > 200) return { ok: false, problem: `items.${index}.id: must be text of 1 to 200 characters` };
78
+ if (itemResult !== "pass" && itemResult !== "fail") return { ok: false, problem: `items.${index}.result: must be "pass" or "fail"` };
79
+ if (reason !== void 0 && typeof reason !== "string") return { ok: false, problem: `items.${index}.reason: must be text` };
80
+ read.push({ id, result: itemResult, ...reason === void 0 ? {} : { reason } });
81
+ }
82
+ return { ok: true, answer: { ...result === void 0 ? {} : { result }, items: read } };
83
+ }
84
+ function parseJudgeAnswer(text) {
85
+ if (text === void 0 || text.trim() === "") return void 0;
86
+ let raw;
87
+ try {
88
+ raw = JSON.parse(text);
89
+ } catch {
90
+ return { ok: false, reason: "the judge's items.json is not JSON" };
91
+ }
92
+ const read = readAnswer(raw);
93
+ return read.ok ? read : { ok: false, reason: `the judge's items.json does not match its shape: ${read.problem}` };
94
+ }
95
+ function oneLineReason(text) {
96
+ if (text === void 0) return void 0;
97
+ const line = text.replace(/\s+/g, " ").trim();
98
+ if (line === "") return void 0;
99
+ return line.length <= CHECK_ITEM_REASON_MAX_LENGTH ? line : `${line.slice(0, CHECK_ITEM_REASON_MAX_LENGTH - 1)}\u2026`;
100
+ }
101
+ function judgedItems(input) {
102
+ return input.toJudge.map((criterion) => {
103
+ const said = input.results.get(criterion.id);
104
+ const inputs = input.inputs.get(criterion.id);
105
+ const refs = refsFor(criterion.id, input.citations);
106
+ const reason = said === void 0 ? NO_VERDICT_REASON : oneLineReason(said.reason);
107
+ return {
108
+ id: criterion.id,
109
+ criterion: criterion.id,
110
+ result: said?.result ?? "fail",
111
+ ...reason === void 0 ? {} : { reason },
112
+ ...refs === void 0 ? {} : { refs },
113
+ ...inputs === void 0 || said === void 0 ? {} : { inputs }
114
+ };
115
+ });
116
+ }
117
+ function inCriteriaOrder(items, criteria) {
118
+ const order = new Map(criteria.map((criterion, index) => [criterion.id, index]));
119
+ return [...items].sort((a, b) => (order.get(a.id) ?? Number.MAX_SAFE_INTEGER) - (order.get(b.id) ?? Number.MAX_SAFE_INTEGER));
120
+ }
121
+ function itemsSentence(items, noun) {
122
+ const failing = items.filter((item) => item.result === "fail").map((item) => item.id);
123
+ if (failing.length === 0) return void 0;
124
+ return `${failing.length} of ${items.length} ${items.length === 1 ? noun.one : noun.many} not satisfied: ${failing.join(", ")}`;
125
+ }
126
+ var MAX_TEST_FILES = 2e4;
127
+ var MAX_TEST_FILE_BYTES = 1024 * 1024;
128
+ async function loadCitationFinder() {
129
+ return await import(pathToFileURL(join(resolvePackRoot(), "maintained", "outerlayer-build", "scripts", "criterion-citations.mjs")).href);
130
+ }
131
+ function criteriaOf(workItem) {
132
+ const criteria = Object(Object(workItem).criteria);
133
+ if (!Array.isArray(criteria.items)) return void 0;
134
+ const drafted = criteria.drafted === true;
135
+ const items = [];
136
+ for (const entry of criteria.items) {
137
+ const { id, text, proof } = Object(entry);
138
+ if (typeof id !== "string" || typeof text !== "string") continue;
139
+ items.push({ id, text, proof: typeof proof === "string" ? proof : null, drafted });
140
+ }
141
+ return items.length === 0 ? void 0 : items;
142
+ }
143
+ function hostItemsOf(workItem, name) {
144
+ const checks = Object(workItem).checks;
145
+ if (!Array.isArray(checks)) return [];
146
+ const check = checks.find((entry) => Object(entry).name === name);
147
+ if (check?.source !== "host") return [];
148
+ const parsed = CheckItemsSchema.safeParse(check.items);
149
+ return parsed.success ? parsed.data : [];
150
+ }
151
+
152
+ export { MAX_TEST_FILES, MAX_TEST_FILE_BYTES, NO_CITING_TEST_REASON, NO_VERDICT_REASON, criteriaOf, criterionInputs, hostItemsOf, inCriteriaOrder, itemsSentence, judgedItems, loadCitationFinder, oneLineReason, parseJudgeAnswer, planCriteria };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { scrubReason, stripTerminalControls } from './chunk-4G4IH4A7.js';
3
+ import { scrubReason, stripTerminalControls } from './chunk-SZU4YCBH.js';
4
4
  import { checkFit, RUNNER_RESERVE_BYTES } from './chunk-V2VJYK46.js';
5
5
  import { RunnerAlreadyRunningError, readPidFile } from './chunk-LQHCNXPK.js';
6
6
  import { isSameProcess } from './chunk-JBJTC3UU.js';
@@ -0,0 +1,321 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ import { criteriaOf, loadCitationFinder, hostItemsOf, MAX_TEST_FILE_BYTES, MAX_TEST_FILES, criterionInputs, NO_CITING_TEST_REASON, NO_VERDICT_REASON, planCriteria } from './chunk-6D7H5DMZ.js';
4
+ import { WorkCommandError, resolveCredentials, getJson } from './chunk-JKNOJKVD.js';
5
+ import { C } from './chunk-ANPNT6PM.js';
6
+ import { sanitizeTerminal } from './chunk-MECW77XP.js';
7
+ import { defaultFetch } from './chunk-7QAJQDHS.js';
8
+ import { resolveRepoIdentity } from './chunk-Z7WMU3RA.js';
9
+ import { parseWorkItemEnv } from './chunk-T2Q7ISPE.js';
10
+ import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
11
+ import { readDeliveryRecord } from './chunk-YQR6E6OV.js';
12
+ import { inferArtifactKind, mediaTypeForArtifactPath, WORK_ITEM_COMMENT_MAX_BODY_LENGTH } from './chunk-EOTMDIYC.js';
13
+ import { createHash } from 'crypto';
14
+ import { spawnSync } from 'child_process';
15
+ import { existsSync, statSync, readFileSync } from 'fs';
16
+ import { resolve, dirname } from 'path';
17
+
18
+ createRequire(import.meta.url);
19
+ function kindProblem(declared, file) {
20
+ if (declared === "test") return "a test proof is recorded by CI, not by --record";
21
+ const kind = inferArtifactKind(mediaTypeForArtifactPath(file));
22
+ return kind === declared ? void 0 : `the kinds differ: the file is a ${kind}, but the criterion declares a ${declared} proof`;
23
+ }
24
+ function proofsCommentBody(head, lines) {
25
+ const header = `These proofs are not current at ${head.slice(0, 7)}:`;
26
+ const rows = lines.map((line) => `- ${line.id} (${line.proof}): ${line.reason}`);
27
+ const fits = (count2) => {
28
+ const left = rows.length - count2;
29
+ return [header, ...rows.slice(0, count2), ...left > 0 ? [`and ${left} more.`] : []].join("\n");
30
+ };
31
+ let count = rows.length;
32
+ while (count > 0 && fits(count).length > WORK_ITEM_COMMENT_MAX_BODY_LENGTH) count -= 1;
33
+ return fits(count);
34
+ }
35
+ function proofsCommentId(item, head, lines) {
36
+ const list = [...lines].sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0).map((line) => [line.id, line.proof, line.reason]);
37
+ const digest = createHash("sha256").update(JSON.stringify([item, head.toLowerCase(), list])).digest("hex");
38
+ return `proofs-${digest.slice(0, 32)}`;
39
+ }
40
+ function repositoryName(repository) {
41
+ return repository.replace(/\.git$/, "").split("/").filter((part) => part !== "").slice(-2).join("/").toLowerCase();
42
+ }
43
+ function ownPullRequest(pullRequests, requested, checkoutRepository) {
44
+ if (requested !== void 0) return { pr: requested };
45
+ const here = checkoutRepository === void 0 ? void 0 : repositoryName(checkoutRepository);
46
+ const open = pullRequests.filter(
47
+ (pr) => pr.state === "open" && typeof pr.prNumber === "number" && (here === void 0 || repositoryName(pr.repository ?? "") === here)
48
+ );
49
+ if (open.length > 1) return { ambiguous: open.map((pr) => pr.prNumber) };
50
+ return { pr: open[0]?.prNumber };
51
+ }
52
+ var NO_BRIEF = "";
53
+ var GITHUB_BLOB = /^https:\/\/github\.com\/[^/]+\/[^/]+\/blob\/([0-9a-f]{7,64})\//;
54
+ function commitOf(refs) {
55
+ for (const ref of refs) {
56
+ const match = GITHUB_BLOB.exec(ref.href ?? "");
57
+ if (match !== null) return match[1];
58
+ }
59
+ return void 0;
60
+ }
61
+ function unprovenCriteria(input) {
62
+ const { criteria, finder } = input;
63
+ const citations = finder.buildCitations({ ids: criteria.map((c) => c.id), files: [...input.headFiles], repository: null, sha: null });
64
+ const headTexts = new Map(input.headFiles.map((file) => [file.path, file.contents]));
65
+ const inputs = new Map(criteria.map((c) => [c.id, criterionInputs({ brief: NO_BRIEF, criterion: c, citations, testFiles: headTexts })]));
66
+ const notes = [];
67
+ const commits = /* @__PURE__ */ new Map();
68
+ const previous = /* @__PURE__ */ new Map();
69
+ const filesByCommit = /* @__PURE__ */ new Map();
70
+ for (const item of input.items) {
71
+ const criterion = criteria.find((c) => c.id === item.id);
72
+ if (criterion === void 0 || item.result !== "fail" || item.inputs === void 0) continue;
73
+ if (item.reason === NO_CITING_TEST_REASON || item.reason === NO_VERDICT_REASON) continue;
74
+ const commit = item.refs === void 0 ? void 0 : commitOf(item.refs);
75
+ if (commit === void 0) {
76
+ notes.push(`the links of ${item.id} name no commit`);
77
+ continue;
78
+ }
79
+ if (!filesByCommit.has(commit)) filesByCommit.set(commit, input.testFilesAt(commit));
80
+ const files = filesByCommit.get(commit);
81
+ if (files === void 0) {
82
+ notes.push(`this checkout does not hold ${item.id}'s cited tests at ${commit.slice(0, 7)}`);
83
+ continue;
84
+ }
85
+ const judgedCitations = finder.buildCitations({ ids: [item.id], files: [...files], repository: null, sha: null });
86
+ const judged = new Map(files.map((file) => [file.path, file.contents]));
87
+ commits.set(item.id, commit);
88
+ previous.set(item.id, { ...item, inputs: criterionInputs({ brief: NO_BRIEF, criterion, citations: judgedCitations, testFiles: judged }) });
89
+ }
90
+ const plan = planCriteria({ criteria, citations, inputs, previous: [...previous.values()] });
91
+ const settled = new Map(plan.settled.map((item) => [item.id, item]));
92
+ const entries = [];
93
+ for (const criterion of criteria) {
94
+ const item = settled.get(criterion.id);
95
+ if (item === void 0 || item.result !== "fail") continue;
96
+ if (item.refs === void 0) entries.push({ id: criterion.id, proof: null, state: "uncited" });
97
+ else entries.push({ id: criterion.id, proof: null, state: "failed", commit: commits.get(criterion.id) ?? "", reason: item.reason ?? "no reason recorded" });
98
+ }
99
+ return { entries, notes };
100
+ }
101
+ function git(cwd, args, input) {
102
+ const run = spawnSync("git", args, { cwd, input, maxBuffer: 268435456 });
103
+ if (run.status !== 0) throw new Error(`git ${args[0]} failed`);
104
+ return run.stdout;
105
+ }
106
+ function readObjects(cwd, specs) {
107
+ const out = git(cwd, ["cat-file", "--batch"], `${specs.join("\n")}
108
+ `);
109
+ const texts = [];
110
+ let at = 0;
111
+ for (let n = 0; n < specs.length; n += 1) {
112
+ const end = out.indexOf(10, at);
113
+ const header = out.subarray(at, end).toString("utf8");
114
+ at = end + 1;
115
+ const match = /^[0-9a-f]+ blob (\d+)$/.exec(header);
116
+ if (match === null) {
117
+ texts.push(void 0);
118
+ continue;
119
+ }
120
+ const size = Number(match[1]);
121
+ texts.push(out.subarray(at, at + size).toString("utf8"));
122
+ at += size + 1;
123
+ }
124
+ return texts;
125
+ }
126
+ function testFilesAt(cwd, head, isTest) {
127
+ try {
128
+ const listing = git(cwd, ["ls-tree", "-r", "-l", "-z", head]);
129
+ const picked = /* @__PURE__ */ new Map();
130
+ for (const entry of listing.toString("utf8").split("\0")) {
131
+ const match = /^(\d+) blob ([0-9a-f]+)\s+(\d+)\t(.*)$/s.exec(entry);
132
+ if (match === null || !match[1].startsWith("100") || Number(match[3]) > MAX_TEST_FILE_BYTES || !isTest.test(match[4])) continue;
133
+ if (picked.size >= MAX_TEST_FILES) break;
134
+ picked.set(match[4], match[2]);
135
+ }
136
+ const paths = [...picked.keys()];
137
+ const texts = readObjects(cwd, [...picked.values()]);
138
+ return paths.flatMap((path, n) => texts[n] === void 0 ? [] : [{ path, contents: texts[n] }]);
139
+ } catch {
140
+ return void 0;
141
+ }
142
+ }
143
+ function checkoutPlaces(cwd) {
144
+ for (let dir = resolve(cwd); ; dir = dirname(dir)) {
145
+ const dotGit = resolve(dir, ".git");
146
+ try {
147
+ if (statSync(dotGit).isDirectory()) return { root: dir, common: dotGit };
148
+ const named = /^gitdir:\s*(.+)$/m.exec(readFileSync(dotGit, "utf8"))?.[1]?.trim();
149
+ if (named === void 0) return void 0;
150
+ const gitDir = resolve(dir, named);
151
+ let common = gitDir;
152
+ try {
153
+ common = resolve(gitDir, readFileSync(resolve(gitDir, "commondir"), "utf8").trim());
154
+ } catch {
155
+ }
156
+ return { root: dir, common };
157
+ } catch {
158
+ }
159
+ if (dirname(dir) === dir) return void 0;
160
+ }
161
+ }
162
+ async function judgeCheckName(cwd) {
163
+ const places = checkoutPlaces(cwd);
164
+ if (places === void 0) return {};
165
+ const delivered = readDeliveryRecord(places.common);
166
+ const dir = delivered?.dir ?? places.root;
167
+ if (!existsSync(dir)) return { note: `the governed context at ${dir} is not readable` };
168
+ const { checksIn, isJudgeCheck } = await import('./host-checks-NDXNYOMA.js');
169
+ const quiet = { line: () => void 0, error: () => void 0 };
170
+ const check = checksIn(dir, quiet, "").checks.find((c) => isJudgeCheck(c) && c.judge.subjects === "criteria");
171
+ return check === void 0 ? {} : { name: check.name };
172
+ }
173
+ async function findUnproven(input) {
174
+ try {
175
+ const found = await judgeCheckName(input.cwd);
176
+ if (found.name === void 0) return { entries: [], notes: found.note === void 0 ? [] : [found.note] };
177
+ const criteria = criteriaOf(input.item);
178
+ if (criteria === void 0) return { entries: [], notes: [] };
179
+ const finder = await loadCitationFinder();
180
+ const headFiles = testFilesAt(input.cwd, input.head, finder.TEST_FILE);
181
+ if (headFiles === void 0) return { entries: [], notes: [`the test files at ${input.head.slice(0, 7)} cannot be read`] };
182
+ const items = hostItemsOf(input.item, found.name);
183
+ const result = unprovenCriteria({
184
+ criteria,
185
+ finder,
186
+ headFiles,
187
+ items,
188
+ testFilesAt: (commit) => testFilesAt(input.cwd, commit, finder.TEST_FILE)
189
+ });
190
+ const check = Object(input.item).checks?.find((c) => Object(c).name === found.name);
191
+ if (check?.source === "host" && check.result === "fail" && items.length === 0) result.notes.unshift("the gateway returned no check items for the judge's result");
192
+ return result;
193
+ } catch (err) {
194
+ return { entries: [], notes: [err instanceof Error ? err.message : String(err)] };
195
+ }
196
+ }
197
+
198
+ // src/work-proofs-cmd.ts
199
+ function liveHead(pr) {
200
+ if (pr.state !== "open" && pr.state !== "merged" || typeof pr.headSha !== "string" || pr.headSha === "") return void 0;
201
+ return pr.headSha.toLowerCase();
202
+ }
203
+ function otherPullRequestHeads(pullRequests, ownPr, checkoutRepository) {
204
+ const here = checkoutRepository === void 0 ? void 0 : repositoryName(checkoutRepository);
205
+ const heads = /* @__PURE__ */ new Set();
206
+ for (const pr of pullRequests) {
207
+ const head = liveHead(pr);
208
+ if (head === void 0) continue;
209
+ const isOwn = ownPr !== void 0 && pr.prNumber === ownPr && (here === void 0 || repositoryName(pr.repository ?? "") === here);
210
+ if (!isOwn) heads.add(head);
211
+ }
212
+ return heads;
213
+ }
214
+ function classifyProofs(data, checkoutHead) {
215
+ const heads = /* @__PURE__ */ new Set();
216
+ if (checkoutHead !== void 0 && checkoutHead !== "") heads.add(checkoutHead.toLowerCase());
217
+ data.pullRequests?.forEach((pr) => {
218
+ const head = liveHead(pr);
219
+ if (head !== void 0) heads.add(head);
220
+ });
221
+ return classifyProofsAt(data, heads);
222
+ }
223
+ function classifyProofsAt(data, heads) {
224
+ const entries = [];
225
+ for (const criterion of data.criteria?.items ?? []) {
226
+ if (criterion.proof === null || criterion.proof === "test") continue;
227
+ const newest = criterion.newestProof;
228
+ if (newest === null || newest === void 0) {
229
+ entries.push({ id: criterion.id, proof: criterion.proof, state: "missing", commit: null });
230
+ } else if (newest.commitSha !== null && heads.has(newest.commitSha.toLowerCase())) {
231
+ entries.push({ id: criterion.id, proof: criterion.proof, state: "current", commit: newest.commitSha });
232
+ } else {
233
+ entries.push({ id: criterion.id, proof: criterion.proof, state: "out-of-date", commit: newest.commitSha });
234
+ }
235
+ }
236
+ return entries;
237
+ }
238
+ var STATE_LABEL = { current: "current", "out-of-date": "out of date", missing: "missing" };
239
+ function renderEntry(e) {
240
+ const id = sanitizeTerminal(e.id);
241
+ if (e.state === "uncited") {
242
+ return `${id} none uncited No test at HEAD cites it. Put ${id} in a test's title or in a comment above the test, as in // proves ${id}`;
243
+ }
244
+ if (e.state === "failed") {
245
+ return `${id} none failed ${sanitizeTerminal(e.commit)} The judge failed it: ${sanitizeTerminal(e.reason)} No test that cites it has changed since. Change a test that cites ${id}.`;
246
+ }
247
+ return `${id} ${sanitizeTerminal(e.proof)} ${STATE_LABEL[e.state]} ${sanitizeTerminal(e.commit ?? "no commit")}`;
248
+ }
249
+ function render(entries, notes, json) {
250
+ if (json) return JSON.stringify(entries);
251
+ const lines = entries.length === 0 ? ["No criterion declares a proof other than test."] : entries.map(renderEntry);
252
+ if (notes.length > 0) lines.push(`The command could not check the judge's results: ${notes.map(sanitizeTerminal).join("; ")}.`);
253
+ return lines.join("\n");
254
+ }
255
+ function resolveProofsItem(opts) {
256
+ const env = opts.env ?? process.env;
257
+ let item;
258
+ if (opts.item !== void 0) {
259
+ item = parseTrackerNumber(opts.item);
260
+ if (item === void 0) throw new WorkCommandError(trackerNumberError("--item", opts.item));
261
+ } else if (env.OUTERLAYER_WORK !== void 0) {
262
+ const parsed = parseWorkItemEnv(env.OUTERLAYER_WORK);
263
+ if (!("number" in parsed)) throw new WorkCommandError(parsed.reason);
264
+ item = parsed.number;
265
+ }
266
+ if (item === void 0) {
267
+ throw new WorkCommandError("no work item. Pass --item <number>, or set OUTERLAYER_WORK to the item's number.");
268
+ }
269
+ return item;
270
+ }
271
+ async function runWorkProofs(opts) {
272
+ const item = resolveProofsItem(opts);
273
+ const creds = resolveCredentials(opts);
274
+ const { data } = await getJson(creds.url, `/v1/work-items/${item}`, creds.apiKey, creds.appId, opts.fetchImpl ?? defaultFetch);
275
+ const body = data;
276
+ const items = body.criteria?.items ?? [];
277
+ if (items.some((c) => c.proof !== null && c.proof !== "test" && !("newestProof" in c))) {
278
+ throw new WorkCommandError(
279
+ "the gateway does not report each criterion's newest proof. Update the gateway, then run this again."
280
+ );
281
+ }
282
+ const checkoutHead = opts.checkoutHead ?? resolveRepoIdentity(opts.cwd ?? process.cwd()).commitSha;
283
+ if (!checkoutHead) {
284
+ throw new WorkCommandError("cannot read the checkout's HEAD. Run this inside the git checkout, or pass the head explicitly.");
285
+ }
286
+ const declared = classifyProofs(body, checkoutHead);
287
+ const unproven = await findUnproven({ item: body, cwd: opts.cwd ?? process.cwd(), head: checkoutHead });
288
+ const entries = [...declared, ...unproven.entries];
289
+ const json = opts.json === true;
290
+ const output = render(entries, json ? [] : unproven.notes, json);
291
+ if (!opts.quiet) {
292
+ process.stdout.write(output + "\n");
293
+ if (json && unproven.notes.length > 0) process.stderr.write(`The command could not check the judge's results: ${unproven.notes.join("; ")}.
294
+ `);
295
+ }
296
+ const inRunnerBuild = (opts.env ?? process.env).OUTERLAYER_JOB_DIR !== void 0;
297
+ const declaredCurrent = declared.every((e) => e.state === "current");
298
+ return { entries, output, exitCode: declaredCurrent && !(inRunnerBuild && unproven.entries.length > 0) ? 0 : 1 };
299
+ }
300
+ async function runWorkProofsCommand(opts) {
301
+ try {
302
+ if (opts.record) {
303
+ const { runWorkProofsRecord } = await import('./work-proofs-record-NUCWR7ZJ.js');
304
+ const result2 = await runWorkProofsRecord(opts);
305
+ process.exitCode = result2.exitCode;
306
+ return;
307
+ }
308
+ const result = await runWorkProofs(opts);
309
+ process.exitCode = result.exitCode;
310
+ } catch (err) {
311
+ if (err instanceof WorkCommandError) {
312
+ process.stderr.write(`${C.red}\u2717${C.reset} ${err.message}
313
+ `);
314
+ process.exitCode = 2;
315
+ return;
316
+ }
317
+ throw err;
318
+ }
319
+ }
320
+
321
+ export { classifyProofs, classifyProofsAt, kindProblem, otherPullRequestHeads, ownPullRequest, proofsCommentBody, proofsCommentId, resolveProofsItem, runWorkProofs, runWorkProofsCommand };
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { reportFailedStart, fitImageBuildMemory } from './chunk-U6AWVO6L.js';
4
- import { writePendingUpdate } from './chunk-HOUFCUMH.js';
5
- import { renderUpdateSteps } from './chunk-VWZHOFBP.js';
6
- import { releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, readProvisionOut, workdirProblem, MICROVM_COMMAND_DIR, commandLogOffset, startMicroVmCommand, microVmCommandLine, runCommand, startSender, finishJob, sampleGuest, foldSample, isContainerTracked, isMicroVmTracked, probeMicroVmCommand, probeCommand, appendCommandLog, judgeProbe, EXIT_CODE_FILE, isTracked, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listUnreadableJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, GUEST_USAGE_INTERVAL_MS, hookLimitsFor, AttemptLogBook, microVmOomKills, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, listTrackedJobs, restartSender, serveLease, vmAlive, writeGuestGhConfig, ALREADY_RELEASED, inTeardown } from './chunk-4G4IH4A7.js';
7
- import { JOB_STATE_FORMAT, readsJobState, jobStateFormatOf } from './chunk-ZVB57WI6.js';
8
- import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-TS3EFB7S.js';
9
3
  import { decideInstalledSwitch } from './chunk-3JVYMD4G.js';
4
+ import { reportFailedStart, fitImageBuildMemory } from './chunk-ERTIEYDG.js';
10
5
  import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-E7R2GIAW.js';
11
6
  import { RUNNER_PROTOCOL } from './chunk-MH6QLXUO.js';
7
+ import { writePendingUpdate } from './chunk-HOUFCUMH.js';
8
+ import { renderUpdateSteps } from './chunk-P3CHDKXD.js';
9
+ import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-TS3EFB7S.js';
10
+ import { releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, readProvisionOut, workdirProblem, MICROVM_COMMAND_DIR, commandLogOffset, startMicroVmCommand, microVmCommandLine, runCommand, startSender, finishJob, sampleGuest, foldSample, isContainerTracked, isMicroVmTracked, probeMicroVmCommand, probeCommand, appendCommandLog, judgeProbe, EXIT_CODE_FILE, isTracked, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listUnreadableJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, GUEST_USAGE_INTERVAL_MS, hookLimitsFor, AttemptLogBook, microVmOomKills, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, listTrackedJobs, restartSender, serveLease, vmAlive, writeGuestGhConfig, ALREADY_RELEASED, inTeardown } from './chunk-SZU4YCBH.js';
11
+ import { JOB_STATE_FORMAT, readsJobState, jobStateFormatOf } from './chunk-ZVB57WI6.js';
12
12
  import { realBlockedProbes, checkBlockedWithSlots, largeBuildMemoryBytes, LARGE_BUILD_DISK_BYTES, checkManagedRoom, sliceMemoryOf } from './chunk-JC6AQ6PC.js';
13
13
  import { writeMarker, readMarker, currentVersion, removeMarker, isInLayout, startedThroughCurrent, entryIn, versionDir, switchCurrent, cleanVersions, stagingDir } from './chunk-YL3RWW7X.js';
14
14
  import { RepoFilter } from './chunk-TBT347UY.js';
@@ -3279,7 +3279,7 @@ async function startRunner(configPath, deps, startup) {
3279
3279
  check: update.check ? () => update.check(configPath) : async () => {
3280
3280
  const held = heldClaudeCredential();
3281
3281
  const env = held === void 0 ? process.env : { ...process.env, [held.variable]: held.value };
3282
- return (await import('./check-ERYYVAEM.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl, env });
3282
+ return (await import('./check-G2K76NEM.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl, env });
3283
3283
  },
3284
3284
  now: () => (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime(),
3285
3285
  log
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { stripTerminalControls } from './chunk-4G4IH4A7.js';
3
+ import { stripTerminalControls } from './chunk-SZU4YCBH.js';
4
4
  import { tagToPull, imageTag, pullInstruction, readUpdateStatus, runnerImageVersion } from './chunk-SDELQEG4.js';
5
5
  import { readFileSync } from 'fs';
6
6