loki-mode 11.17.45 → 11.17.46
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/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/lib/secret-scan.sh +4 -0
- package/autonomy/loki +25 -6
- package/completions/_loki +6 -0
- package/completions/loki.bash +8 -0
- package/dashboard/__init__.py +1 -1
- package/docs/CLI-REFERENCE.md +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/docs/v10/BOARD.md +30 -30
- package/docs/v10/FAILURE-CLASSES.md +8 -0
- package/docs/v10/PROGRESS.md +3 -0
- package/loki-ts/dist/loki.js +1267 -1252
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/packages/control-plane/dist/server.js +1742 -1717
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/web-app/dist/assets/{AdminPage-BCGIu6vt.js → AdminPage-DOQbb9S2.js} +1 -1
- package/web-app/dist/assets/{Avatar-FGro9b68.js → Avatar-DlCHpaY9.js} +1 -1
- package/web-app/dist/assets/{Badge-DZ0OOxdx.js → Badge-CsGRidkQ.js} +1 -1
- package/web-app/dist/assets/{Button-C702FTxi.js → Button-CaNiRTkv.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-B1CZaaXx.js → CockpitPage-B8sezC-W.js} +1 -1
- package/web-app/dist/assets/{ComparePage-DRd-w9yO.js → ComparePage-B36mEWLR.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-B9T1V8_Q.js → ErrorBoundary-BFGjCcE5.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-CScPICN7.js → EvidenceReceiptPanel-mFXX7T0e.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-BL8nzIoH.js → GitHubIssuesPanel-BjUOWEuY.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-W0FX5DSl.js → GitHubPRsPanel-CcLMzJZk.js} +1 -1
- package/web-app/dist/assets/{HomePage-_3jq9WUA.js → HomePage-9j8CciDG.js} +2 -2
- package/web-app/dist/assets/{LoginPage-DsPxoAOJ.js → LoginPage-BXEJEipC.js} +1 -1
- package/web-app/dist/assets/{MagicPage-nOER2-ZE.js → MagicPage-JJhHAzUo.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-CoiAlCTC.js → MetricsPage-g2murSvE.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-l46SOx1i.js → NotFoundPage-D3fshofn.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-DxO8dkf_.js → ProjectPage-B91c8gqI.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-DtNSAVm9.js → ProjectsPage-f-AqCLnm.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-DbNetRfY.js → SettingsPage-xmKoxIhv.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-BSzhjOYS.js → ShowcasePage-DxPIEO67.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-DWrN72dn.js → SystemSettingsPage-Cm9Dy2-W.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-CVFEOL9r.js → TeamsPage-xUmbM2Q6.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-IpcsZhEh.js → TemplatesPage-BF0atSP9.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-Bv9Zgwyj.js → TerminalOutput-BRR-hjM0.js} +1 -1
- package/web-app/dist/assets/{activity-CHgtGwwW.js → activity-bs7r0Zgu.js} +1 -1
- package/web-app/dist/assets/{bell-Ym0Mx2Xd.js → bell-BSBQU6oH.js} +1 -1
- package/web-app/dist/assets/{bot-C-6tA3JT.js → bot-IY1WHsy_.js} +1 -1
- package/web-app/dist/assets/{check-CyFyZ4Qi.js → check-BbLOs82D.js} +1 -1
- package/web-app/dist/assets/{chevron-left-B3SPNdcz.js → chevron-left-Dr_YJex2.js} +1 -1
- package/web-app/dist/assets/{circle-alert-DcKKeKmd.js → circle-alert-CdPabs5h.js} +1 -1
- package/web-app/dist/assets/{clock-CHLwYBFX.js → clock-DSSC0-0Q.js} +1 -1
- package/web-app/dist/assets/{cloud-CBE7j7iG.js → cloud-D_gWiz8h.js} +1 -1
- package/web-app/dist/assets/{code-xml-Cu-b65vO.js → code-xml-BeK0mcX9.js} +1 -1
- package/web-app/dist/assets/{database-DSJlQYxs.js → database-CcJkBSXN.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-BcPFsZq0.js → dollar-sign-B0KTo6gY.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-Dl_LDpv_.js → file-code-corner-Br9i1QUK.js} +1 -1
- package/web-app/dist/assets/{file-plus-BoLEmKCc.js → file-plus-Cntlx-H3.js} +1 -1
- package/web-app/dist/assets/{globe-4-KwsIUo.js → globe-BzTQwBst.js} +1 -1
- package/web-app/dist/assets/{hammer-CaG_crBz.js → hammer-DY5E-S_s.js} +1 -1
- package/web-app/dist/assets/{index-DD7FC7yd.js → index-D8iQaeY_.js} +3 -3
- package/web-app/dist/assets/{layers-BDQEO970.js → layers-fichWK2q.js} +1 -1
- package/web-app/dist/assets/{loader-circle-ENh48A-3.js → loader-circle-H4GEC-nt.js} +1 -1
- package/web-app/dist/assets/{lock-CcI4ltMK.js → lock-L2gybTp0.js} +1 -1
- package/web-app/dist/assets/{package-DA_Bt7Mx.js → package-C6GhNvrY.js} +1 -1
- package/web-app/dist/assets/{plus-r_jqdmwV.js → plus-C76f-H0b.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-B0o3B073.js → refresh-cw-CYrIM5Gt.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-D5EyaAC-.js → rotate-ccw-DuVzPMTc.js} +1 -1
- package/web-app/dist/assets/{scroll-text-DKrZwpKk.js → scroll-text-Ou40WwYD.js} +1 -1
- package/web-app/dist/assets/{server-FMLinzaf.js → server-CY2Y_apg.js} +1 -1
- package/web-app/dist/assets/{shield-alert-C5YWhIfX.js → shield-alert-CNf-jmi3.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-lWteH19H.js → thumbs-up-DNRc_NvO.js} +1 -1
- package/web-app/dist/assets/{trash-2-CTWsJujI.js → trash-2-CdzowWF_.js} +1 -1
- package/web-app/dist/assets/{trending-down-n969VpQb.js → trending-down-DtZEAOFe.js} +1 -1
- package/web-app/dist/assets/{trending-up-hNpwNjdL.js → trending-up-BwiPR3rB.js} +1 -1
- package/web-app/dist/assets/{upload-DmcM8inI.js → upload-BI_6o8oU.js} +1 -1
- package/web-app/dist/assets/{usePolling-CQCRI-UO.js → usePolling-TefZLSUZ.js} +1 -1
- package/web-app/dist/assets/{user-BCspLAnr.js → user-BzczgZi4.js} +1 -1
- package/web-app/dist/index.html +1 -1
|
@@ -7594,201 +7594,13 @@ var init_paths = __esm(() => {
|
|
|
7594
7594
|
REPO_ROOT = findRepoRoot();
|
|
7595
7595
|
});
|
|
7596
7596
|
|
|
7597
|
-
// ../../loki-ts/src/util/receipt_signer.ts
|
|
7598
|
-
import { createHash as createHash6, randomBytes as randomBytes3, createPrivateKey, createPublicKey as createPublicKey2, generateKeyPairSync, sign, verify as verify2 } from "crypto";
|
|
7599
|
-
import { chmodSync as chmodSync4, linkSync, mkdirSync as mkdirSync5, readdirSync as readdirSync9, readFileSync as readFileSync18, renameSync as renameSync4, statSync as statSync12, unlinkSync as unlinkSync3, writeFileSync as writeFileSync8 } from "fs";
|
|
7600
|
-
import { homedir as homedir8 } from "os";
|
|
7601
|
-
import { dirname as dirname7, join as join27 } from "path";
|
|
7602
|
-
function canonicalJson(x) {
|
|
7603
|
-
const walk = (v) => {
|
|
7604
|
-
if (Array.isArray(v))
|
|
7605
|
-
return `[${v.map(walk).join(",")}]`;
|
|
7606
|
-
if (v !== null && typeof v === "object") {
|
|
7607
|
-
const o = v;
|
|
7608
|
-
return `{${Object.keys(o).filter((k) => o[k] !== undefined).sort().map((k) => `${JSON.stringify(k)}:${walk(o[k])}`).join(",")}}`;
|
|
7609
|
-
}
|
|
7610
|
-
return JSON.stringify(v ?? null);
|
|
7611
|
-
};
|
|
7612
|
-
return walk(x).replace(/[\u0080-\uFFFF]/g, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`);
|
|
7613
|
-
}
|
|
7614
|
-
function loadSigningKey(generate = true) {
|
|
7615
|
-
try {
|
|
7616
|
-
const inline = process.env["LOKI_RECEIPT_SIGNING_KEY"]?.trim();
|
|
7617
|
-
let pem = inline ?? "";
|
|
7618
|
-
if (!inline) {
|
|
7619
|
-
const given = process.env["LOKI_RECEIPT_SIGNING_KEY_FILE"]?.trim();
|
|
7620
|
-
const file = given || join27(process.env["HOME"] || homedir8(), ".loki", "keys", RECEIPT_SIGNER_BASENAME);
|
|
7621
|
-
try {
|
|
7622
|
-
pem = readFileSync18(file);
|
|
7623
|
-
if (!given) {
|
|
7624
|
-
for (const [f, m] of [[file, 384], [dirname7(file), 448]])
|
|
7625
|
-
if (statSync12(f).mode & 63)
|
|
7626
|
-
chmodSync4(f, m);
|
|
7627
|
-
}
|
|
7628
|
-
} catch (e) {
|
|
7629
|
-
if (e.code !== "ENOENT" || !generate)
|
|
7630
|
-
return null;
|
|
7631
|
-
mkdirSync5(dirname7(dirname7(file)), { recursive: true, mode: 448 });
|
|
7632
|
-
mkdirSync5(dirname7(file), { recursive: true, mode: 448 });
|
|
7633
|
-
const tmp = `${file}.${randomBytes3(6).toString("hex")}.tmp`;
|
|
7634
|
-
writeFileSync8(tmp, generateKeyPairSync("ed25519").privateKey.export({ type: "pkcs8", format: "pem" }), { flag: "wx", mode: 384 });
|
|
7635
|
-
try {
|
|
7636
|
-
linkSync(tmp, file);
|
|
7637
|
-
} catch (l) {
|
|
7638
|
-
if (l.code !== "EEXIST")
|
|
7639
|
-
throw l;
|
|
7640
|
-
} finally {
|
|
7641
|
-
unlinkSync3(tmp);
|
|
7642
|
-
}
|
|
7643
|
-
pem = readFileSync18(file);
|
|
7644
|
-
}
|
|
7645
|
-
}
|
|
7646
|
-
const k = createPrivateKey(pem);
|
|
7647
|
-
return k.asymmetricKeyType === "ed25519" ? k : null;
|
|
7648
|
-
} catch {
|
|
7649
|
-
return null;
|
|
7650
|
-
}
|
|
7651
|
-
}
|
|
7652
|
-
function signReceipt(runId, hash) {
|
|
7653
|
-
const key = loadSigningKey();
|
|
7654
|
-
if (!key)
|
|
7655
|
-
return { jwt: null, kid: null };
|
|
7656
|
-
const kid = kidOf2(createPublicKey2(key));
|
|
7657
|
-
const input = `${b64u(canonicalJson({ alg: "EdDSA", typ: "JWT", kid }))}.${b64u(canonicalJson({ job_id: runId, run_id: runId, receipt_sha256: hash, iat: Math.floor(Date.now() / 1000) }))}`;
|
|
7658
|
-
return { jwt: `${input}.${b64u(sign(null, Buffer.from(input), key))}`, kid };
|
|
7659
|
-
}
|
|
7660
|
-
var RECEIPT_SIGNER_BASENAME = "receipt-ed25519.pem", b64u = (b) => Buffer.from(b).toString("base64url"), kidOf2 = (pub) => b64u(createHash6("sha256").update(`{"crv":"Ed25519","kty":"OKP","x":"${pub.export({ format: "jwk" }).x}"}`).digest());
|
|
7661
|
-
var init_receipt_signer = () => {};
|
|
7662
|
-
|
|
7663
|
-
// ../../loki-ts/src/engine10/registry.ts
|
|
7664
|
-
var init_registry = () => {};
|
|
7665
|
-
|
|
7666
|
-
// ../../loki-ts/src/engine10/types.ts
|
|
7667
|
-
function pushArgv(a) {
|
|
7668
|
-
switch (a.cmd) {
|
|
7669
|
-
case "push-pr":
|
|
7670
|
-
return ["push-pr", a.repoDir, a.branch, a.title, a.bodyFile, a.draft ? "1" : "0"];
|
|
7671
|
-
case "comment":
|
|
7672
|
-
return ["comment", a.runId, a.prUrl, a.file];
|
|
7673
|
-
case "status":
|
|
7674
|
-
return ["status", a.sha, a.state, a.description];
|
|
7675
|
-
case "issue-comment":
|
|
7676
|
-
return a.update ? ["issue-comment", "--update", a.issueRef, a.bodyFile] : ["issue-comment", a.issueRef, a.bodyFile];
|
|
7677
|
-
}
|
|
7678
|
-
}
|
|
7679
|
-
function taskBlock(task) {
|
|
7680
|
-
return ["Task (untrusted, quoted verbatim):", "<<<TASK", task, "TASK"];
|
|
7681
|
-
}
|
|
7682
|
-
var STAGE_BUDGETS;
|
|
7683
|
-
var init_types = __esm(() => {
|
|
7684
|
-
STAGE_BUDGETS = {
|
|
7685
|
-
intake: { targetS: 15, limitS: 60 },
|
|
7686
|
-
plan: { targetS: 45, limitS: 90 },
|
|
7687
|
-
wall: { targetS: 45, limitS: 90 },
|
|
7688
|
-
implement: { targetS: 180, limitS: 480 },
|
|
7689
|
-
verify: { targetS: 60, limitS: 120 },
|
|
7690
|
-
fix: { targetS: 90, limitS: 180 },
|
|
7691
|
-
commit: { targetS: 5, limitS: 30 },
|
|
7692
|
-
seal: { targetS: 15, limitS: 60 },
|
|
7693
|
-
pr: { targetS: 15, limitS: 60 },
|
|
7694
|
-
deep: { targetS: null, limitS: 2700 }
|
|
7695
|
-
};
|
|
7696
|
-
});
|
|
7697
|
-
|
|
7698
|
-
// ../../loki-ts/src/engine10/output.ts
|
|
7699
|
-
var init_output = __esm(() => {
|
|
7700
|
-
init_registry();
|
|
7701
|
-
init_redact();
|
|
7702
|
-
init_types();
|
|
7703
|
-
});
|
|
7704
|
-
|
|
7705
|
-
// ../../loki-ts/src/util/atomic.ts
|
|
7706
|
-
import {
|
|
7707
|
-
closeSync as closeSync5,
|
|
7708
|
-
fstatSync as fstatSync4,
|
|
7709
|
-
fsyncSync as fsyncSync2,
|
|
7710
|
-
lstatSync as lstatSync5,
|
|
7711
|
-
mkdirSync as mkdirSync6,
|
|
7712
|
-
openSync as openSync5,
|
|
7713
|
-
readSync as readSync4,
|
|
7714
|
-
renameSync as renameSync5,
|
|
7715
|
-
rmSync as rmSync5,
|
|
7716
|
-
statSync as statSync13,
|
|
7717
|
-
unlinkSync as unlinkSync4,
|
|
7718
|
-
writeFileSync as writeFileSync9,
|
|
7719
|
-
writeSync as writeSync3
|
|
7720
|
-
} from "fs";
|
|
7721
|
-
import { dirname as dirname8 } from "path";
|
|
7722
|
-
function durableWriteThenRename(target, body) {
|
|
7723
|
-
mkdirSync6(dirname8(target), { recursive: true });
|
|
7724
|
-
const tmp = tmpPathFor(target);
|
|
7725
|
-
const fd = openSync5(tmp, "w");
|
|
7726
|
-
try {
|
|
7727
|
-
writeSync3(fd, body);
|
|
7728
|
-
fsyncSync2(fd);
|
|
7729
|
-
} finally {
|
|
7730
|
-
closeSync5(fd);
|
|
7731
|
-
}
|
|
7732
|
-
renameSync5(tmp, target);
|
|
7733
|
-
fsyncParentDir(target);
|
|
7734
|
-
}
|
|
7735
|
-
function fsyncParentDir(target) {
|
|
7736
|
-
let dfd = null;
|
|
7737
|
-
try {
|
|
7738
|
-
dfd = openSync5(dirname8(target), "r");
|
|
7739
|
-
fsyncSync2(dfd);
|
|
7740
|
-
} catch {} finally {
|
|
7741
|
-
if (dfd !== null) {
|
|
7742
|
-
try {
|
|
7743
|
-
closeSync5(dfd);
|
|
7744
|
-
} catch {}
|
|
7745
|
-
}
|
|
7746
|
-
}
|
|
7747
|
-
}
|
|
7748
|
-
function atomicWriteJson(target, data) {
|
|
7749
|
-
durableWriteThenRename(target, `${JSON.stringify(data, null, 2)}
|
|
7750
|
-
`);
|
|
7751
|
-
}
|
|
7752
|
-
function tmpPathFor(target) {
|
|
7753
|
-
return `${target}.tmp.${process.pid}.${++_tmpCounter}`;
|
|
7754
|
-
}
|
|
7755
|
-
var _tmpCounter = 0, _appendChains;
|
|
7756
|
-
var init_atomic = __esm(() => {
|
|
7757
|
-
_appendChains = new Map;
|
|
7758
|
-
});
|
|
7759
|
-
|
|
7760
|
-
// ../../loki-ts/src/util/engine_origin.ts
|
|
7761
|
-
function readOriginUrl(repoDir) {
|
|
7762
|
-
try {
|
|
7763
|
-
const url = safeGit(repoDir, ["config", "--get", "remote.origin.url"]).trim();
|
|
7764
|
-
return url || null;
|
|
7765
|
-
} catch {
|
|
7766
|
-
return null;
|
|
7767
|
-
}
|
|
7768
|
-
}
|
|
7769
|
-
var init_engine_origin = __esm(() => {
|
|
7770
|
-
init_atomic();
|
|
7771
|
-
init_safe_git();
|
|
7772
|
-
});
|
|
7773
|
-
|
|
7774
|
-
// ../../loki-ts/src/e10ext/stop_restore.ts
|
|
7775
|
-
var init_stop_restore = __esm(() => {
|
|
7776
|
-
init_safe_git();
|
|
7777
|
-
});
|
|
7778
|
-
|
|
7779
|
-
// ../../loki-ts/src/util/base_guard.ts
|
|
7780
|
-
var init_base_guard = __esm(() => {
|
|
7781
|
-
init_run_status();
|
|
7782
|
-
init_safe_git();
|
|
7783
|
-
});
|
|
7784
|
-
|
|
7785
7597
|
// ../../loki-ts/src/engine10/cache.ts
|
|
7786
|
-
import { createHash as
|
|
7787
|
-
import { existsSync as existsSync15, mkdirSync as
|
|
7598
|
+
import { createHash as createHash6 } from "crypto";
|
|
7599
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync5, readFileSync as readFileSync18, writeFileSync as writeFileSync8 } from "fs";
|
|
7788
7600
|
import { resolve as resolve8 } from "path";
|
|
7789
7601
|
function repoKey(originUrl, repoDir) {
|
|
7790
7602
|
const basis = originUrl && originUrl.trim() !== "" ? originUrl : resolve8(repoDir);
|
|
7791
|
-
return
|
|
7603
|
+
return createHash6("sha256").update(basis).digest("hex");
|
|
7792
7604
|
}
|
|
7793
7605
|
function defaultCacheRoot() {
|
|
7794
7606
|
return resolve8(homeLokiDir(), "cache", "v10");
|
|
@@ -7800,7 +7612,7 @@ function readJson3(path, isValid = (_v) => true) {
|
|
|
7800
7612
|
if (!existsSync15(path))
|
|
7801
7613
|
return null;
|
|
7802
7614
|
try {
|
|
7803
|
-
const parsed = JSON.parse(
|
|
7615
|
+
const parsed = JSON.parse(readFileSync18(path, "utf8"));
|
|
7804
7616
|
return isValid(parsed) ? parsed : null;
|
|
7805
7617
|
} catch {
|
|
7806
7618
|
return null;
|
|
@@ -7924,12 +7736,12 @@ var init_lean_select = __esm(() => {
|
|
|
7924
7736
|
});
|
|
7925
7737
|
|
|
7926
7738
|
// ../../loki-ts/src/util/claude_model.ts
|
|
7927
|
-
import { readFileSync as
|
|
7739
|
+
import { readFileSync as readFileSync19 } from "fs";
|
|
7928
7740
|
import { resolve as resolve9 } from "path";
|
|
7929
7741
|
function resolveClaudeModel(want) {
|
|
7930
7742
|
try {
|
|
7931
7743
|
const path = process.env["LOKI_MODEL_CATALOG"] || resolve9(REPO_ROOT, "providers/model_catalog.json");
|
|
7932
|
-
return JSON.parse(
|
|
7744
|
+
return JSON.parse(readFileSync19(path, "utf8")).providers?.claude?.cli_aliases?.[want] ?? want;
|
|
7933
7745
|
} catch {
|
|
7934
7746
|
return want;
|
|
7935
7747
|
}
|
|
@@ -7939,6 +7751,13 @@ var init_claude_model = __esm(() => {
|
|
|
7939
7751
|
init_paths();
|
|
7940
7752
|
FAMILY_ALIASES = new Set(["haiku", "sonnet", "opus", "fable"]);
|
|
7941
7753
|
});
|
|
7754
|
+
|
|
7755
|
+
// ../../loki-ts/src/runner/watchdog.ts
|
|
7756
|
+
var warned;
|
|
7757
|
+
var init_watchdog = __esm(() => {
|
|
7758
|
+
warned = new Set;
|
|
7759
|
+
});
|
|
7760
|
+
|
|
7942
7761
|
// ../../loki-ts/src/providers/price_table.ts
|
|
7943
7762
|
var PRICE_TABLE;
|
|
7944
7763
|
var init_price_table = __esm(() => {
|
|
@@ -7961,25 +7780,25 @@ var init_price_table = __esm(() => {
|
|
|
7961
7780
|
});
|
|
7962
7781
|
|
|
7963
7782
|
// ../../loki-ts/src/providers/provider_cost.ts
|
|
7964
|
-
import { existsSync as existsSync16, mkdirSync as
|
|
7965
|
-
import { dirname as
|
|
7783
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync6, readdirSync as readdirSync9, readFileSync as readFileSync20, renameSync as renameSync4, writeFileSync as writeFileSync9 } from "fs";
|
|
7784
|
+
import { dirname as dirname7, join as join27 } from "path";
|
|
7966
7785
|
function withArchivedCosts(lokiRoot, ids, keep = () => true) {
|
|
7967
7786
|
let files = [];
|
|
7968
7787
|
try {
|
|
7969
|
-
files =
|
|
7788
|
+
files = readdirSync9(join27(lokiRoot, "metrics"));
|
|
7970
7789
|
} catch {}
|
|
7971
7790
|
return [...new Set([...ids, ...ids.flatMap((id) => files.filter((f) => f.startsWith(`result-cost-${id}-q`) && f.endsWith(".json")).map((f) => f.slice("result-cost-".length, -".json".length)).filter(keep))])];
|
|
7972
7791
|
}
|
|
7973
7792
|
function neverRan(path, unmeteredMarker) {
|
|
7974
7793
|
try {
|
|
7975
|
-
const r = JSON.parse(
|
|
7794
|
+
const r = JSON.parse(readFileSync20(path, "utf8")), n2 = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
7976
7795
|
return r["total_cost_usd"] === 0 && r["source"] !== unmeteredMarker && ["input_tokens", "output_tokens", "cache_read_tokens", "cache_creation_tokens"].every((k) => n2(r[k]) === 0);
|
|
7977
7796
|
} catch {
|
|
7978
7797
|
return false;
|
|
7979
7798
|
}
|
|
7980
7799
|
}
|
|
7981
7800
|
function liveArchivedCosts(lokiRoot, ids, unmeteredMarker) {
|
|
7982
|
-
return withArchivedCosts(lokiRoot, ids, (id) => !neverRan(
|
|
7801
|
+
return withArchivedCosts(lokiRoot, ids, (id) => !neverRan(join27(lokiRoot, "metrics", `result-cost-${id}.json`), unmeteredMarker));
|
|
7983
7802
|
}
|
|
7984
7803
|
var ESTIMATED_PROVIDERS;
|
|
7985
7804
|
var init_provider_cost = __esm(() => {
|
|
@@ -8031,8 +7850,8 @@ function routerMode(env = process.env) {
|
|
|
8031
7850
|
var routerEnabled = (env = process.env) => routerMode(env) === "on";
|
|
8032
7851
|
|
|
8033
7852
|
// ../../loki-ts/src/engine10/cost.ts
|
|
8034
|
-
import { readdirSync as
|
|
8035
|
-
import { join as
|
|
7853
|
+
import { readdirSync as readdirSync10, readFileSync as readFileSync21 } from "fs";
|
|
7854
|
+
import { join as join28 } from "path";
|
|
8036
7855
|
function routerTelemetryOn(env = process.env) {
|
|
8037
7856
|
return routerEnabled(env);
|
|
8038
7857
|
}
|
|
@@ -8040,7 +7859,7 @@ function num3(v) {
|
|
|
8040
7859
|
return typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
8041
7860
|
}
|
|
8042
7861
|
function resultCostPath(lokiRoot, iteration) {
|
|
8043
|
-
return
|
|
7862
|
+
return join28(lokiRoot, "metrics", `result-cost-${iteration}.json`);
|
|
8044
7863
|
}
|
|
8045
7864
|
function sumResultCosts(lokiRoot, iterations, context = []) {
|
|
8046
7865
|
const out2 = {
|
|
@@ -8071,7 +7890,7 @@ function sumResultCosts(lokiRoot, iterations, context = []) {
|
|
|
8071
7890
|
const parsed = new Map;
|
|
8072
7891
|
for (const iter of iterations) {
|
|
8073
7892
|
try {
|
|
8074
|
-
parsed.set(iter, JSON.parse(
|
|
7893
|
+
parsed.set(iter, JSON.parse(readFileSync21(resultCostPath(lokiRoot, iter), "utf8")));
|
|
8075
7894
|
} catch {}
|
|
8076
7895
|
}
|
|
8077
7896
|
const own = new Set(iterations);
|
|
@@ -8080,7 +7899,7 @@ function sumResultCosts(lokiRoot, iterations, context = []) {
|
|
|
8080
7899
|
if (own.has(iter))
|
|
8081
7900
|
continue;
|
|
8082
7901
|
try {
|
|
8083
|
-
lookup.push({ iter, rec: JSON.parse(
|
|
7902
|
+
lookup.push({ iter, rec: JSON.parse(readFileSync21(resultCostPath(lokiRoot, iter), "utf8")) });
|
|
8084
7903
|
} catch {}
|
|
8085
7904
|
}
|
|
8086
7905
|
const verdicts = hooks.costRecords?.resumeVerdicts(lookup) ?? { ambiguous: [], separate: [] };
|
|
@@ -8181,28 +8000,88 @@ var init_cost = __esm(() => {
|
|
|
8181
8000
|
init_provider_cost();
|
|
8182
8001
|
});
|
|
8183
8002
|
|
|
8003
|
+
// ../../loki-ts/src/util/atomic.ts
|
|
8004
|
+
import {
|
|
8005
|
+
closeSync as closeSync5,
|
|
8006
|
+
fstatSync as fstatSync4,
|
|
8007
|
+
fsyncSync as fsyncSync2,
|
|
8008
|
+
lstatSync as lstatSync5,
|
|
8009
|
+
mkdirSync as mkdirSync8,
|
|
8010
|
+
openSync as openSync5,
|
|
8011
|
+
readSync as readSync4,
|
|
8012
|
+
renameSync as renameSync5,
|
|
8013
|
+
rmSync as rmSync5,
|
|
8014
|
+
statSync as statSync12,
|
|
8015
|
+
unlinkSync as unlinkSync3,
|
|
8016
|
+
writeFileSync as writeFileSync11,
|
|
8017
|
+
writeSync as writeSync3
|
|
8018
|
+
} from "fs";
|
|
8019
|
+
import { dirname as dirname8 } from "path";
|
|
8020
|
+
function durableWriteThenRename(target, body) {
|
|
8021
|
+
mkdirSync8(dirname8(target), { recursive: true });
|
|
8022
|
+
const tmp = tmpPathFor(target);
|
|
8023
|
+
const fd = openSync5(tmp, "w");
|
|
8024
|
+
try {
|
|
8025
|
+
writeSync3(fd, body);
|
|
8026
|
+
fsyncSync2(fd);
|
|
8027
|
+
} finally {
|
|
8028
|
+
closeSync5(fd);
|
|
8029
|
+
}
|
|
8030
|
+
renameSync5(tmp, target);
|
|
8031
|
+
fsyncParentDir(target);
|
|
8032
|
+
}
|
|
8033
|
+
function fsyncParentDir(target) {
|
|
8034
|
+
let dfd = null;
|
|
8035
|
+
try {
|
|
8036
|
+
dfd = openSync5(dirname8(target), "r");
|
|
8037
|
+
fsyncSync2(dfd);
|
|
8038
|
+
} catch {} finally {
|
|
8039
|
+
if (dfd !== null) {
|
|
8040
|
+
try {
|
|
8041
|
+
closeSync5(dfd);
|
|
8042
|
+
} catch {}
|
|
8043
|
+
}
|
|
8044
|
+
}
|
|
8045
|
+
}
|
|
8046
|
+
function atomicWriteJson(target, data) {
|
|
8047
|
+
durableWriteThenRename(target, `${JSON.stringify(data, null, 2)}
|
|
8048
|
+
`);
|
|
8049
|
+
}
|
|
8050
|
+
function tmpPathFor(target) {
|
|
8051
|
+
return `${target}.tmp.${process.pid}.${++_tmpCounter}`;
|
|
8052
|
+
}
|
|
8053
|
+
var _tmpCounter = 0, _appendChains;
|
|
8054
|
+
var init_atomic = __esm(() => {
|
|
8055
|
+
_appendChains = new Map;
|
|
8056
|
+
});
|
|
8057
|
+
|
|
8184
8058
|
// ../../loki-ts/src/runner/budget.ts
|
|
8185
|
-
import { existsSync as existsSync17, mkdirSync as
|
|
8186
|
-
import { dirname as
|
|
8059
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync9, readdirSync as readdirSync11, readFileSync as readFileSync22, writeFileSync as writeFileSync12 } from "fs";
|
|
8060
|
+
import { dirname as dirname9, join as join29, resolve as resolve10 } from "path";
|
|
8187
8061
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8188
|
-
function loadDefaultMaxCostUsd() {
|
|
8189
|
-
const here =
|
|
8190
|
-
for (const rel of
|
|
8062
|
+
function loadDefaultMaxCostUsd(dataDirs = [["..", "..", "data"], ["..", "data"]]) {
|
|
8063
|
+
const here = dirname9(fileURLToPath2(import.meta.url));
|
|
8064
|
+
for (const rel of dataDirs) {
|
|
8191
8065
|
try {
|
|
8192
|
-
const j = JSON.parse(
|
|
8066
|
+
const j = JSON.parse(readFileSync22(resolve10(here, ...rel, "model-pricing.json"), "utf8"));
|
|
8193
8067
|
if (typeof j.default_max_cost_usd === "number" && Number.isFinite(j.default_max_cost_usd) && j.default_max_cost_usd > 0)
|
|
8194
8068
|
return j.default_max_cost_usd;
|
|
8195
8069
|
} catch {}
|
|
8196
8070
|
}
|
|
8071
|
+
if (!pricingFallbackWarned) {
|
|
8072
|
+
pricingFallbackWarned = true;
|
|
8073
|
+
process.stderr.write(`loki: warning: model-pricing.json is missing or unreadable (looked in ${dataDirs.map((r) => resolve10(here, ...r)).join(", ")}); using fallback default max cost $${DEFAULT_FALLBACK_USD}
|
|
8074
|
+
`);
|
|
8075
|
+
}
|
|
8197
8076
|
return DEFAULT_FALLBACK_USD;
|
|
8198
8077
|
}
|
|
8199
8078
|
function _loadPricing() {
|
|
8200
8079
|
try {
|
|
8201
|
-
const moduleDir =
|
|
8080
|
+
const moduleDir = dirname9(fileURLToPath2(import.meta.url));
|
|
8202
8081
|
const jsonPath = resolve10(moduleDir, "..", "..", "data", "model-pricing.json");
|
|
8203
8082
|
if (!existsSync17(jsonPath))
|
|
8204
8083
|
return _FALLBACK_PRICING;
|
|
8205
|
-
const raw2 = JSON.parse(
|
|
8084
|
+
const raw2 = JSON.parse(readFileSync22(jsonPath, "utf8"));
|
|
8206
8085
|
const pricing2 = raw2["pricing"];
|
|
8207
8086
|
if (!pricing2 || typeof pricing2 !== "object")
|
|
8208
8087
|
return _FALLBACK_PRICING;
|
|
@@ -8267,7 +8146,7 @@ function calculateCostFromRecords(records) {
|
|
|
8267
8146
|
}
|
|
8268
8147
|
return round4(total);
|
|
8269
8148
|
}
|
|
8270
|
-
var DEFAULT_FALLBACK_USD = 100, _FALLBACK_PRICING, PRICING, DEFAULT_PRICING_KEY = "sonnet";
|
|
8149
|
+
var DEFAULT_FALLBACK_USD = 100, pricingFallbackWarned = false, _FALLBACK_PRICING, PRICING, DEFAULT_PRICING_KEY = "sonnet", warnedCorruptBudget;
|
|
8271
8150
|
var init_budget = __esm(() => {
|
|
8272
8151
|
init_atomic();
|
|
8273
8152
|
init_paths();
|
|
@@ -8296,37 +8175,70 @@ var init_budget = __esm(() => {
|
|
|
8296
8175
|
"gpt-5.3-codex": { input: 1.75, output: 14, cache_read: 0.175, cache_write: 2.1875 }
|
|
8297
8176
|
};
|
|
8298
8177
|
PRICING = Object.freeze(_loadPricing());
|
|
8178
|
+
warnedCorruptBudget = new Set;
|
|
8299
8179
|
});
|
|
8300
8180
|
|
|
8301
|
-
// ../../loki-ts/src/
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
|
|
8305
|
-
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
}
|
|
8313
|
-
function insideRepo(repoDir, rel) {
|
|
8314
|
-
try {
|
|
8315
|
-
const real2 = realpathSync14(join31(repoDir, rel));
|
|
8316
|
-
const base = realpathSync14(repoDir);
|
|
8317
|
-
return real2 === base || real2.startsWith(base + sep9);
|
|
8318
|
-
} catch {
|
|
8319
|
-
return false;
|
|
8181
|
+
// ../../loki-ts/src/engine10/types.ts
|
|
8182
|
+
function pushArgv(a) {
|
|
8183
|
+
switch (a.cmd) {
|
|
8184
|
+
case "push-pr":
|
|
8185
|
+
return ["push-pr", a.repoDir, a.branch, a.title, a.bodyFile, a.draft ? "1" : "0"];
|
|
8186
|
+
case "comment":
|
|
8187
|
+
return ["comment", a.runId, a.prUrl, a.file];
|
|
8188
|
+
case "status":
|
|
8189
|
+
return ["status", a.sha, a.state, a.description];
|
|
8190
|
+
case "issue-comment":
|
|
8191
|
+
return a.update ? ["issue-comment", "--update", a.issueRef, a.bodyFile] : ["issue-comment", a.issueRef, a.bodyFile];
|
|
8320
8192
|
}
|
|
8321
8193
|
}
|
|
8322
|
-
function
|
|
8323
|
-
|
|
8194
|
+
function taskBlock(task) {
|
|
8195
|
+
return ["Task (untrusted, quoted verbatim):", "<<<TASK", task, "TASK"];
|
|
8196
|
+
}
|
|
8197
|
+
var STAGE_BUDGETS;
|
|
8198
|
+
var init_types = __esm(() => {
|
|
8199
|
+
STAGE_BUDGETS = {
|
|
8200
|
+
intake: { targetS: 15, limitS: 60 },
|
|
8201
|
+
plan: { targetS: 45, limitS: 90 },
|
|
8202
|
+
wall: { targetS: 45, limitS: 90 },
|
|
8203
|
+
implement: { targetS: 180, limitS: 480 },
|
|
8204
|
+
verify: { targetS: 60, limitS: 120 },
|
|
8205
|
+
fix: { targetS: 90, limitS: 180 },
|
|
8206
|
+
commit: { targetS: 5, limitS: 30 },
|
|
8207
|
+
seal: { targetS: 15, limitS: 60 },
|
|
8208
|
+
pr: { targetS: 15, limitS: 60 },
|
|
8209
|
+
deep: { targetS: null, limitS: 2700 }
|
|
8210
|
+
};
|
|
8211
|
+
});
|
|
8212
|
+
|
|
8213
|
+
// ../../loki-ts/src/runner/router/decision.ts
|
|
8214
|
+
var init_decision = () => {};
|
|
8215
|
+
|
|
8216
|
+
// ../../loki-ts/src/project_model/schema.ts
|
|
8217
|
+
import { existsSync as existsSync18, lstatSync as lstatSync6, realpathSync as realpathSync14, statSync as statSync13 } from "fs";
|
|
8218
|
+
import { isAbsolute, join as join30, normalize, sep as sep9 } from "path";
|
|
8219
|
+
function safeRel(p) {
|
|
8220
|
+
const n2 = normalize(p.trim()).split(sep9).join("/").replace(/\/$/, "");
|
|
8221
|
+
if (n2 === "" || isAbsolute(n2) || n2 === ".." || n2.startsWith("../"))
|
|
8222
|
+
return null;
|
|
8223
|
+
return n2;
|
|
8224
|
+
}
|
|
8225
|
+
function insideRepo(repoDir, rel) {
|
|
8226
|
+
try {
|
|
8227
|
+
const real2 = realpathSync14(join30(repoDir, rel));
|
|
8228
|
+
const base = realpathSync14(repoDir);
|
|
8229
|
+
return real2 === base || real2.startsWith(base + sep9);
|
|
8230
|
+
} catch {
|
|
8231
|
+
return false;
|
|
8232
|
+
}
|
|
8233
|
+
}
|
|
8234
|
+
function checkCitation(repoDir, raw2) {
|
|
8235
|
+
if (!isStr(raw2))
|
|
8324
8236
|
return "citation is not a non-empty string";
|
|
8325
8237
|
const rel = safeRel(raw2.replace(/:\d+(?:-\d+)?$/, ""));
|
|
8326
8238
|
if (rel === null)
|
|
8327
8239
|
return `citation "${raw2}" is not a repo-relative path`;
|
|
8328
|
-
const abs =
|
|
8329
|
-
if (!existsSync18(abs) || !
|
|
8240
|
+
const abs = join30(repoDir, rel);
|
|
8241
|
+
if (!existsSync18(abs) || !statSync13(abs).isFile() || !insideRepo(repoDir, rel))
|
|
8330
8242
|
return `citation "${raw2}" names a file that does not exist`;
|
|
8331
8243
|
return null;
|
|
8332
8244
|
}
|
|
@@ -8337,7 +8249,7 @@ function checkFingerprint(repoDir, raw2) {
|
|
|
8337
8249
|
if (rel === null)
|
|
8338
8250
|
return `fingerprint "${raw2}" is not a repo-relative path`;
|
|
8339
8251
|
try {
|
|
8340
|
-
if (!lstatSync6(
|
|
8252
|
+
if (!lstatSync6(join30(repoDir, rel)).isFile() || !insideRepo(repoDir, rel))
|
|
8341
8253
|
return `fingerprint "${raw2}" is not a regular file inside the repo`;
|
|
8342
8254
|
} catch {
|
|
8343
8255
|
return `fingerprint "${raw2}" names a file that does not exist`;
|
|
@@ -8365,8 +8277,8 @@ function checkDir(repoDir, v, where, errs) {
|
|
|
8365
8277
|
errs.push(`${where}: must be a repo-relative directory ("." for the repo root)`);
|
|
8366
8278
|
return ".";
|
|
8367
8279
|
}
|
|
8368
|
-
const abs =
|
|
8369
|
-
if (!existsSync18(abs) || !
|
|
8280
|
+
const abs = join30(repoDir, rel);
|
|
8281
|
+
if (!existsSync18(abs) || !statSync13(abs).isDirectory() || !insideRepo(repoDir, rel))
|
|
8370
8282
|
errs.push(`${where}: directory "${rel}" does not exist`);
|
|
8371
8283
|
return rel;
|
|
8372
8284
|
}
|
|
@@ -8468,7 +8380,7 @@ var init_schema = __esm(() => {
|
|
|
8468
8380
|
});
|
|
8469
8381
|
|
|
8470
8382
|
// ../../loki-ts/src/runner/router/history_store.ts
|
|
8471
|
-
import { existsSync as existsSync19, mkdirSync as
|
|
8383
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync10, readFileSync as readFileSync23, renameSync as renameSync6, rmSync as rmSync6, writeFileSync as writeFileSync13 } from "fs";
|
|
8472
8384
|
import { resolve as resolve11 } from "path";
|
|
8473
8385
|
function validRun(v) {
|
|
8474
8386
|
if (typeof v !== "object" || v === null)
|
|
@@ -8484,7 +8396,7 @@ function readRunHistory(key, cacheRoot) {
|
|
|
8484
8396
|
if (!existsSync19(path))
|
|
8485
8397
|
return [];
|
|
8486
8398
|
try {
|
|
8487
|
-
const parsed = JSON.parse(
|
|
8399
|
+
const parsed = JSON.parse(readFileSync23(path, "utf8"));
|
|
8488
8400
|
const runs2 = parsed?.runs;
|
|
8489
8401
|
return Array.isArray(runs2) ? runs2.filter(validRun) : [];
|
|
8490
8402
|
} catch {
|
|
@@ -8494,12 +8406,12 @@ function readRunHistory(key, cacheRoot) {
|
|
|
8494
8406
|
function appendRunOutcome(key, outcome, cacheRoot) {
|
|
8495
8407
|
try {
|
|
8496
8408
|
const runs2 = [...readRunHistory(key, cacheRoot), outcome].slice(-HISTORY_CAP);
|
|
8497
|
-
|
|
8409
|
+
mkdirSync10(repoCacheDir(key, cacheRoot), { recursive: true });
|
|
8498
8410
|
const target = historyPath(key, cacheRoot);
|
|
8499
8411
|
const tmp = `${target}.${process.pid}.tmp`;
|
|
8500
8412
|
try {
|
|
8501
|
-
|
|
8502
|
-
|
|
8413
|
+
writeFileSync13(tmp, JSON.stringify({ runs: runs2 }));
|
|
8414
|
+
renameSync6(tmp, target);
|
|
8503
8415
|
} catch (e) {
|
|
8504
8416
|
rmSync6(tmp, { force: true, recursive: false });
|
|
8505
8417
|
throw e;
|
|
@@ -8517,18 +8429,10 @@ var init_history_store = __esm(() => {
|
|
|
8517
8429
|
OWNERS = ["code", "harness", "env", "provider"];
|
|
8518
8430
|
});
|
|
8519
8431
|
|
|
8520
|
-
// ../../loki-ts/src/runner/model_downgrades.ts
|
|
8521
|
-
var init_model_downgrades = __esm(() => {
|
|
8522
|
-
init_sizing();
|
|
8523
|
-
init_model_rank();
|
|
8524
|
-
init_claude_model();
|
|
8525
|
-
init_decision();
|
|
8526
|
-
});
|
|
8527
|
-
|
|
8528
8432
|
// ../../loki-ts/src/project_model/gather.ts
|
|
8529
|
-
import { createHash as
|
|
8530
|
-
import { closeSync as closeSync6, lstatSync as lstatSync7, openSync as openSync6, readFileSync as
|
|
8531
|
-
import { dirname as
|
|
8433
|
+
import { createHash as createHash7 } from "crypto";
|
|
8434
|
+
import { closeSync as closeSync6, lstatSync as lstatSync7, openSync as openSync6, readFileSync as readFileSync24, readSync as readSync5 } from "fs";
|
|
8435
|
+
import { dirname as dirname10, join as join31 } from "path";
|
|
8532
8436
|
function listShallow(repoDir) {
|
|
8533
8437
|
try {
|
|
8534
8438
|
const out2 = safeGit(repoDir, ["ls-files", "-z"], { maxBuffer: 256 * 1024 * 1024 });
|
|
@@ -8538,10 +8442,10 @@ function listShallow(repoDir) {
|
|
|
8538
8442
|
}
|
|
8539
8443
|
}
|
|
8540
8444
|
function shallowDirs(repoDir) {
|
|
8541
|
-
return [...new Set(listShallow(repoDir).map((p) =>
|
|
8445
|
+
return [...new Set(listShallow(repoDir).map((p) => dirname10(p)))].sort();
|
|
8542
8446
|
}
|
|
8543
8447
|
function computeKey(repoDir, fingerprintFiles, dirs, committedHash = null) {
|
|
8544
|
-
const h =
|
|
8448
|
+
const h = createHash7("sha256");
|
|
8545
8449
|
h.update(`${MODEL_REV}
|
|
8546
8450
|
`);
|
|
8547
8451
|
if (committedHash !== null)
|
|
@@ -8554,9 +8458,9 @@ function computeKey(repoDir, fingerprintFiles, dirs, committedHash = null) {
|
|
|
8554
8458
|
if (checkFingerprint(repoDir, f) !== null)
|
|
8555
8459
|
h.update("invalid");
|
|
8556
8460
|
else {
|
|
8557
|
-
const abs =
|
|
8461
|
+
const abs = join31(repoDir, f);
|
|
8558
8462
|
const size = lstatSync7(abs).size;
|
|
8559
|
-
h.update(size <= GATHER_CAPS.maxHashBytes ?
|
|
8463
|
+
h.update(size <= GATHER_CAPS.maxHashBytes ? readFileSync24(abs) : `too-large:${size}`);
|
|
8560
8464
|
}
|
|
8561
8465
|
} catch {
|
|
8562
8466
|
h.update("missing");
|
|
@@ -8581,7 +8485,7 @@ function committedModelHash(raw2) {
|
|
|
8581
8485
|
if (typeof raw2 !== "object" || raw2 === null || Array.isArray(raw2))
|
|
8582
8486
|
return null;
|
|
8583
8487
|
const { key: _key, expiresAt: _exp, ...rest } = raw2;
|
|
8584
|
-
return
|
|
8488
|
+
return createHash7("sha256").update(JSON.stringify(rest)).digest("hex");
|
|
8585
8489
|
}
|
|
8586
8490
|
var GATHER_CAPS, depthOf = (p) => p.split("/").length, MODEL_REV = "model-rev:2";
|
|
8587
8491
|
var init_gather = __esm(() => {
|
|
@@ -8598,55 +8502,22 @@ var init_gather = __esm(() => {
|
|
|
8598
8502
|
};
|
|
8599
8503
|
});
|
|
8600
8504
|
|
|
8601
|
-
// ../../loki-ts/src/
|
|
8602
|
-
|
|
8603
|
-
import { join as join33 } from "path";
|
|
8604
|
-
function projectModelEnabled(env = process.env) {
|
|
8605
|
-
return env["LOKI_E10_PROJECT_MODEL"] !== "0";
|
|
8606
|
-
}
|
|
8607
|
-
function loadCached(repoDir, now2 = Date.now()) {
|
|
8505
|
+
// ../../loki-ts/src/util/engine_origin.ts
|
|
8506
|
+
function readOriginUrl(repoDir) {
|
|
8608
8507
|
try {
|
|
8609
|
-
|
|
8508
|
+
const url = safeGit(repoDir, ["config", "--get", "remote.origin.url"]).trim();
|
|
8509
|
+
return url || null;
|
|
8610
8510
|
} catch {
|
|
8611
8511
|
return null;
|
|
8612
8512
|
}
|
|
8613
8513
|
}
|
|
8614
|
-
|
|
8615
|
-
|
|
8616
|
-
|
|
8617
|
-
const ignore = (why) => {
|
|
8618
|
-
process.stderr.write(`loki: ignoring committed ${PROJECT_FILE}: ${why}; falling back to discovery
|
|
8619
|
-
`);
|
|
8620
|
-
return null;
|
|
8621
|
-
};
|
|
8622
|
-
let raw2;
|
|
8623
|
-
try {
|
|
8624
|
-
raw2 = JSON.parse(readFileSync26(join33(repoDir, PROJECT_FILE), "utf8"));
|
|
8625
|
-
} catch (e) {
|
|
8626
|
-
return ignore(`unreadable JSON (${e instanceof Error ? e.message : String(e)})`);
|
|
8627
|
-
}
|
|
8628
|
-
const hash = committedModelHash(raw2);
|
|
8629
|
-
if (hash === null)
|
|
8630
|
-
return ignore("not a JSON object");
|
|
8631
|
-
const r = raw2;
|
|
8632
|
-
if (r["schema"] !== PROJECT_MODEL_SCHEMA || r["status"] !== "ok")
|
|
8633
|
-
return ignore(`needs schema "${PROJECT_MODEL_SCHEMA}" and status "ok"`);
|
|
8634
|
-
const v = validateAnswer(repoDir, raw2);
|
|
8635
|
-
if (!v.ok)
|
|
8636
|
-
return ignore(v.errors.slice(0, 3).join("; "));
|
|
8637
|
-
return { model: { ...v.model, key: "" }, hash };
|
|
8638
|
-
}
|
|
8639
|
-
var PROJECT_FILE = ".loki/project.json", UNKNOWN_TTL_MS;
|
|
8640
|
-
var init_discover2 = __esm(() => {
|
|
8641
|
-
init_model_downgrades();
|
|
8642
|
-
init_types();
|
|
8643
|
-
init_gather();
|
|
8644
|
-
init_schema();
|
|
8645
|
-
UNKNOWN_TTL_MS = 60 * 60 * 1000;
|
|
8514
|
+
var init_engine_origin = __esm(() => {
|
|
8515
|
+
init_atomic();
|
|
8516
|
+
init_safe_git();
|
|
8646
8517
|
});
|
|
8647
8518
|
|
|
8648
8519
|
// ../../loki-ts/src/runner/router/history.ts
|
|
8649
|
-
import { dirname as
|
|
8520
|
+
import { dirname as dirname11, join as join32, resolve as resolve12 } from "path";
|
|
8650
8521
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
8651
8522
|
function shapeKey(model) {
|
|
8652
8523
|
if (!model || model.status !== "ok")
|
|
@@ -8678,7 +8549,7 @@ var init_history = __esm(() => {
|
|
|
8678
8549
|
init_cache();
|
|
8679
8550
|
init_engine_origin();
|
|
8680
8551
|
init_history_store();
|
|
8681
|
-
SHAPE_DEFAULTS_FILE = resolve12(
|
|
8552
|
+
SHAPE_DEFAULTS_FILE = resolve12(dirname11(fileURLToPath3(import.meta.url)), "..", "..", "..", "data", "router-shape-defaults.json");
|
|
8682
8553
|
});
|
|
8683
8554
|
|
|
8684
8555
|
// ../../loki-ts/src/runner/router/unit_model.ts
|
|
@@ -8740,6 +8611,7 @@ var init_budget_cap = __esm(() => {
|
|
|
8740
8611
|
// ../../loki-ts/src/engine10/session.ts
|
|
8741
8612
|
var STDERR_TAIL_BYTES, ADVISOR_MARKED_STAGES;
|
|
8742
8613
|
var init_session = __esm(() => {
|
|
8614
|
+
init_watchdog();
|
|
8743
8615
|
init_run_pid();
|
|
8744
8616
|
init_provider_cost();
|
|
8745
8617
|
init_model_routes();
|
|
@@ -8764,7 +8636,7 @@ var init_model_rank = __esm(() => {
|
|
|
8764
8636
|
});
|
|
8765
8637
|
|
|
8766
8638
|
// ../../loki-ts/src/engine10/sizing.ts
|
|
8767
|
-
import { existsSync as
|
|
8639
|
+
import { existsSync as existsSync20, readFileSync as readFileSync25 } from "fs";
|
|
8768
8640
|
import { basename as basename8 } from "path";
|
|
8769
8641
|
function namedFiles(task, map) {
|
|
8770
8642
|
return (map?.files ?? []).filter((f) => task.toLowerCase().includes(basename8(f).toLowerCase()));
|
|
@@ -8786,7 +8658,7 @@ function sizeTask(task, map, tests) {
|
|
|
8786
8658
|
}
|
|
8787
8659
|
function loadRepoMap(repomapRef) {
|
|
8788
8660
|
try {
|
|
8789
|
-
return repomapRef &&
|
|
8661
|
+
return repomapRef && existsSync20(repomapRef) ? JSON.parse(readFileSync25(repomapRef, "utf8")) : null;
|
|
8790
8662
|
} catch {
|
|
8791
8663
|
return null;
|
|
8792
8664
|
}
|
|
@@ -8820,1536 +8692,1690 @@ var init_sizing = __esm(() => {
|
|
|
8820
8692
|
resolveModelAlias = resolveClaudeModel;
|
|
8821
8693
|
});
|
|
8822
8694
|
|
|
8823
|
-
// ../../loki-ts/src/
|
|
8824
|
-
|
|
8825
|
-
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
|
|
8695
|
+
// ../../loki-ts/src/runner/model_downgrades.ts
|
|
8696
|
+
var init_model_downgrades = __esm(() => {
|
|
8697
|
+
init_sizing();
|
|
8698
|
+
init_model_rank();
|
|
8699
|
+
init_claude_model();
|
|
8700
|
+
init_decision();
|
|
8701
|
+
});
|
|
8702
|
+
|
|
8703
|
+
// ../../loki-ts/src/project_model/discover.ts
|
|
8704
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync11, readFileSync as readFileSync26, rmSync as rmSync7, writeFileSync as writeFileSync14 } from "fs";
|
|
8705
|
+
import { join as join34 } from "path";
|
|
8706
|
+
function projectModelEnabled(env = process.env) {
|
|
8707
|
+
return env["LOKI_E10_PROJECT_MODEL"] !== "0";
|
|
8708
|
+
}
|
|
8709
|
+
function loadCached(repoDir, now2 = Date.now()) {
|
|
8830
8710
|
try {
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
|
|
8834
|
-
const buf = Buffer.alloc(st.size + 1);
|
|
8835
|
-
let n2 = 0;
|
|
8836
|
-
for (;; ) {
|
|
8837
|
-
const r = readSync6(fd, buf, n2, buf.length - n2, null);
|
|
8838
|
-
if (r <= 0)
|
|
8839
|
-
break;
|
|
8840
|
-
n2 += r;
|
|
8841
|
-
if (n2 >= buf.length)
|
|
8842
|
-
return null;
|
|
8843
|
-
}
|
|
8844
|
-
return buf.subarray(0, n2).toString("utf8");
|
|
8845
|
-
} finally {
|
|
8846
|
-
closeSync7(fd);
|
|
8711
|
+
return parseCached(repoDir, JSON.parse(readFileSync26(join34(repoDir, PROJECT_FILE), "utf8")), now2);
|
|
8712
|
+
} catch {
|
|
8713
|
+
return null;
|
|
8847
8714
|
}
|
|
8848
8715
|
}
|
|
8849
|
-
function
|
|
8716
|
+
function loadCommitted(repoDir) {
|
|
8717
|
+
if (!isGitTracked(repoDir, PROJECT_FILE))
|
|
8718
|
+
return null;
|
|
8719
|
+
const ignore = (why) => {
|
|
8720
|
+
process.stderr.write(`loki: ignoring committed ${PROJECT_FILE}: ${why}; falling back to discovery
|
|
8721
|
+
`);
|
|
8722
|
+
return null;
|
|
8723
|
+
};
|
|
8724
|
+
let raw2;
|
|
8850
8725
|
try {
|
|
8851
|
-
|
|
8852
|
-
|
|
8726
|
+
raw2 = JSON.parse(readFileSync26(join34(repoDir, PROJECT_FILE), "utf8"));
|
|
8727
|
+
} catch (e) {
|
|
8728
|
+
return ignore(`unreadable JSON (${e instanceof Error ? e.message : String(e)})`);
|
|
8729
|
+
}
|
|
8730
|
+
const hash = committedModelHash(raw2);
|
|
8731
|
+
if (hash === null)
|
|
8732
|
+
return ignore("not a JSON object");
|
|
8733
|
+
const r = raw2;
|
|
8734
|
+
if (r["schema"] !== PROJECT_MODEL_SCHEMA || r["status"] !== "ok")
|
|
8735
|
+
return ignore(`needs schema "${PROJECT_MODEL_SCHEMA}" and status "ok"`);
|
|
8736
|
+
const v = validateAnswer(repoDir, raw2);
|
|
8737
|
+
if (!v.ok)
|
|
8738
|
+
return ignore(v.errors.slice(0, 3).join("; "));
|
|
8739
|
+
return { model: { ...v.model, key: "" }, hash };
|
|
8740
|
+
}
|
|
8741
|
+
var PROJECT_FILE = ".loki/project.json", UNKNOWN_TTL_MS;
|
|
8742
|
+
var init_discover2 = __esm(() => {
|
|
8743
|
+
init_model_downgrades();
|
|
8744
|
+
init_types();
|
|
8745
|
+
init_gather();
|
|
8746
|
+
init_schema();
|
|
8747
|
+
UNKNOWN_TTL_MS = 60 * 60 * 1000;
|
|
8748
|
+
});
|
|
8749
|
+
|
|
8750
|
+
// ../../loki-ts/src/project_model/api.ts
|
|
8751
|
+
import { posix } from "path";
|
|
8752
|
+
function projectApi(model) {
|
|
8753
|
+
const known = isRec2(model) && model.status === "ok";
|
|
8754
|
+
const packages = known && Array.isArray(model.packages) ? model.packages.filter(wellFormed) : [];
|
|
8755
|
+
const packageOf = (file) => {
|
|
8756
|
+
const f = clean(file);
|
|
8757
|
+
if (f === "")
|
|
8853
8758
|
return null;
|
|
8854
|
-
|
|
8855
|
-
|
|
8759
|
+
let best = null;
|
|
8760
|
+
for (const p of packages) {
|
|
8761
|
+
const hit = p.root === "." || f === p.root || f.startsWith(`${p.root}/`);
|
|
8762
|
+
if (hit && (best === null || p.root !== "." && (best.root === "." || p.root.length > best.root.length)))
|
|
8763
|
+
best = p;
|
|
8764
|
+
}
|
|
8765
|
+
return best;
|
|
8766
|
+
};
|
|
8767
|
+
return {
|
|
8768
|
+
model,
|
|
8769
|
+
known: () => known,
|
|
8770
|
+
packages: () => packages,
|
|
8771
|
+
workspaceKind: () => isRec2(model) && typeof model.workspaceKind === "string" ? model.workspaceKind : "unknown",
|
|
8772
|
+
packageRootOf: (file) => packageOf(file)?.root ?? null,
|
|
8773
|
+
packageOf,
|
|
8774
|
+
relativeToRoot: (file) => {
|
|
8775
|
+
const p = packageOf(file);
|
|
8776
|
+
return p ? p.root === "." ? clean(file) : clean(file).slice(p.root.length + 1) : null;
|
|
8777
|
+
},
|
|
8778
|
+
commandFor: (pkg, kind) => (packages.find((p) => p.root === clean(pkg) || p.name === pkg) ?? null)?.commands?.[kind] ?? null,
|
|
8779
|
+
dependsOn: (pkg) => {
|
|
8780
|
+
const d = (packages.find((p) => p.root === clean(pkg) || p.name === pkg) ?? null)?.dependsOn;
|
|
8781
|
+
return Array.isArray(d) ? d.filter((x) => typeof x === "string") : null;
|
|
8782
|
+
},
|
|
8783
|
+
installFor: (pkg) => {
|
|
8784
|
+
const i = (packages.find((p) => p.root === clean(pkg) || p.name === pkg) ?? null)?.install;
|
|
8785
|
+
return isRec2(i) && typeof i.cmd === "string" ? i : null;
|
|
8786
|
+
},
|
|
8787
|
+
hasUI: () => packages.some((p) => isRec2(p.ui) && p.ui.present === true),
|
|
8788
|
+
uiBoot: () => {
|
|
8789
|
+
for (const p of packages)
|
|
8790
|
+
if (isRec2(p.ui) && p.ui.present === true && isRec2(p.ui.boot))
|
|
8791
|
+
return { pkg: p, boot: p.ui.boot };
|
|
8856
8792
|
return null;
|
|
8857
|
-
|
|
8858
|
-
}
|
|
8859
|
-
return null;
|
|
8860
|
-
}
|
|
8793
|
+
}
|
|
8794
|
+
};
|
|
8861
8795
|
}
|
|
8862
|
-
|
|
8796
|
+
var clean = (p) => typeof p === "string" ? posix.normalize(p.replace(/\\/g, "/")).replace(/^\.\//, "") : "", isRec2 = (v) => typeof v === "object" && v !== null, wellFormed = (p) => isRec2(p) && typeof p.root === "string" && typeof p.name === "string";
|
|
8797
|
+
var init_api = () => {};
|
|
8798
|
+
|
|
8799
|
+
// ../../loki-ts/src/project_model/resolve.ts
|
|
8800
|
+
import { join as join35 } from "path";
|
|
8801
|
+
function loadProjectApi(repoDir, env = process.env) {
|
|
8802
|
+
if (!projectModelEnabled(env))
|
|
8803
|
+
return null;
|
|
8863
8804
|
try {
|
|
8864
|
-
const
|
|
8865
|
-
|
|
8805
|
+
const model = loadCached(repoDir);
|
|
8806
|
+
const api = model ? projectApi(model) : null;
|
|
8807
|
+
return api && api.known() ? api : null;
|
|
8866
8808
|
} catch {
|
|
8867
8809
|
return null;
|
|
8868
8810
|
}
|
|
8869
8811
|
}
|
|
8870
|
-
function
|
|
8871
|
-
|
|
8872
|
-
|
|
8812
|
+
function isMultiRoot(api) {
|
|
8813
|
+
return !!api && api.known() && api.packages().some((p) => p.root !== ".");
|
|
8814
|
+
}
|
|
8815
|
+
function siteFor(api, repoDir, file) {
|
|
8816
|
+
if (!isMultiRoot(api))
|
|
8873
8817
|
return null;
|
|
8874
|
-
|
|
8875
|
-
|
|
8876
|
-
if (!
|
|
8877
|
-
|
|
8878
|
-
return
|
|
8818
|
+
const pkg = api.packageOf(file);
|
|
8819
|
+
const rel = api.relativeToRoot(file);
|
|
8820
|
+
if (!pkg || pkg.root === "." || rel === null)
|
|
8821
|
+
return null;
|
|
8822
|
+
return { pkg, root: pkg.root, cwd: join35(repoDir, pkg.root), file: rel };
|
|
8879
8823
|
}
|
|
8880
|
-
function
|
|
8881
|
-
const
|
|
8882
|
-
|
|
8824
|
+
function groupByPackage(api, repoDir, files) {
|
|
8825
|
+
const out2 = new Map;
|
|
8826
|
+
for (const f of files) {
|
|
8827
|
+
const s = siteFor(api, repoDir, f);
|
|
8828
|
+
const root = s?.root ?? ".";
|
|
8829
|
+
const g = out2.get(root) ?? { root, cwd: s?.cwd ?? repoDir, files: [], rel: [] };
|
|
8830
|
+
g.files.push(f);
|
|
8831
|
+
g.rel.push(s?.file ?? f);
|
|
8832
|
+
out2.set(root, g);
|
|
8833
|
+
}
|
|
8834
|
+
return [...out2.values()];
|
|
8883
8835
|
}
|
|
8884
|
-
var
|
|
8885
|
-
|
|
8886
|
-
|
|
8887
|
-
CTRL = /[\x00-\x1f\x7f]/;
|
|
8888
|
-
memo = new Map;
|
|
8836
|
+
var init_resolve = __esm(() => {
|
|
8837
|
+
init_discover2();
|
|
8838
|
+
init_api();
|
|
8889
8839
|
});
|
|
8890
|
-
|
|
8891
|
-
|
|
8892
|
-
|
|
8893
|
-
for (let j = i + 1;j < s.length; ) {
|
|
8894
|
-
const c = s[j];
|
|
8895
|
-
if (c === "\\")
|
|
8896
|
-
j += 2;
|
|
8897
|
-
else if (c === "`")
|
|
8898
|
-
return j + 1;
|
|
8899
|
-
else if (c === "$" && s[j + 1] === "{") {
|
|
8900
|
-
let depth = 1;
|
|
8901
|
-
j += 2;
|
|
8902
|
-
while (j < s.length && depth > 0) {
|
|
8903
|
-
const k = skipLiteral(s, j);
|
|
8904
|
-
if (k !== j) {
|
|
8905
|
-
j = k;
|
|
8906
|
-
continue;
|
|
8907
|
-
}
|
|
8908
|
-
if (s[j] === "{")
|
|
8909
|
-
depth++;
|
|
8910
|
-
else if (s[j] === "}")
|
|
8911
|
-
depth--;
|
|
8912
|
-
j++;
|
|
8913
|
-
}
|
|
8914
|
-
} else
|
|
8915
|
-
j++;
|
|
8916
|
-
}
|
|
8917
|
-
return s.length;
|
|
8840
|
+
// ../../loki-ts/src/project_model/scope.ts
|
|
8841
|
+
function scopedOutOf(map) {
|
|
8842
|
+
return [...dropped.get(map) ?? []].sort();
|
|
8918
8843
|
}
|
|
8919
|
-
|
|
8920
|
-
|
|
8921
|
-
|
|
8922
|
-
|
|
8923
|
-
|
|
8924
|
-
|
|
8925
|
-
|
|
8926
|
-
|
|
8927
|
-
|
|
8928
|
-
|
|
8844
|
+
var apis, imports, dropped;
|
|
8845
|
+
var init_scope = __esm(() => {
|
|
8846
|
+
init_resolve();
|
|
8847
|
+
apis = new WeakMap;
|
|
8848
|
+
imports = new WeakMap;
|
|
8849
|
+
dropped = new WeakMap;
|
|
8850
|
+
});
|
|
8851
|
+
|
|
8852
|
+
// ../../loki-ts/src/util/test_file_text.ts
|
|
8853
|
+
import { basename as basename9 } from "path";
|
|
8854
|
+
function isTestFile(rel) {
|
|
8855
|
+
const name = basename9(rel);
|
|
8856
|
+
return JS_TEST_RE.test(name) || PY_TEST_RE.test(name) || GO_TEST_RE.test(name);
|
|
8929
8857
|
}
|
|
8930
|
-
|
|
8931
|
-
|
|
8932
|
-
|
|
8933
|
-
|
|
8934
|
-
|
|
8935
|
-
|
|
8936
|
-
|
|
8937
|
-
|
|
8938
|
-
|
|
8939
|
-
|
|
8940
|
-
|
|
8941
|
-
|
|
8942
|
-
|
|
8943
|
-
|
|
8944
|
-
|
|
8945
|
-
|
|
8946
|
-
|
|
8947
|
-
j++;
|
|
8948
|
-
else if (c === "[")
|
|
8949
|
-
inClass = true;
|
|
8950
|
-
else if (c === "]")
|
|
8951
|
-
inClass = false;
|
|
8952
|
-
else if (c === "/" && !inClass) {
|
|
8953
|
-
j++;
|
|
8954
|
-
while (j < s.length && /[a-z]/i.test(s[j]))
|
|
8955
|
-
j++;
|
|
8956
|
-
return j;
|
|
8858
|
+
var JS_TEST_RE, PY_TEST_RE, GO_TEST_RE;
|
|
8859
|
+
var init_test_file_text = __esm(() => {
|
|
8860
|
+
JS_TEST_RE = /\.(test|spec)\.[cm]?[jt]sx?$/;
|
|
8861
|
+
PY_TEST_RE = /^(test_.+|.+_test)\.py$/;
|
|
8862
|
+
GO_TEST_RE = /_test\.go$/;
|
|
8863
|
+
});
|
|
8864
|
+
|
|
8865
|
+
// ../../loki-ts/src/engine10/testmap.ts
|
|
8866
|
+
import { existsSync as existsSync22, readdirSync as readdirSync12, readFileSync as readFileSync27, realpathSync as realpathSync15 } from "fs";
|
|
8867
|
+
import { basename as basename10, extname, isAbsolute as isAbsolute2, join as join36, relative, sep as sep10 } from "path";
|
|
8868
|
+
function projectInterpreter(root) {
|
|
8869
|
+
const ve = process.env["VIRTUAL_ENV"], inRepo = (p) => {
|
|
8870
|
+
try {
|
|
8871
|
+
const r = relative(realpathSync15(root), realpathSync15(p));
|
|
8872
|
+
return r !== "" && !r.startsWith("..") && !isAbsolute2(r);
|
|
8873
|
+
} catch {
|
|
8874
|
+
return false;
|
|
8957
8875
|
}
|
|
8958
|
-
}
|
|
8959
|
-
return
|
|
8876
|
+
};
|
|
8877
|
+
return [join36(root, ".venv", "bin", "python"), join36(root, "venv", "bin", "python"), ...ve && inRepo(ve) ? [join36(ve, "bin", "python")] : []].some(existsSync22) ? "project" : "system";
|
|
8960
8878
|
}
|
|
8961
|
-
|
|
8962
|
-
|
|
8963
|
-
|
|
8964
|
-
|
|
8965
|
-
|
|
8966
|
-
|
|
8967
|
-
|
|
8968
|
-
|
|
8969
|
-
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8879
|
+
var SKIP_DIRS;
|
|
8880
|
+
var init_testmap = __esm(() => {
|
|
8881
|
+
init_resolve();
|
|
8882
|
+
init_scope();
|
|
8883
|
+
init_test_file_text();
|
|
8884
|
+
SKIP_DIRS = new Set([
|
|
8885
|
+
".git",
|
|
8886
|
+
"node_modules",
|
|
8887
|
+
"dist",
|
|
8888
|
+
"build",
|
|
8889
|
+
"target",
|
|
8890
|
+
"coverage",
|
|
8891
|
+
".venv",
|
|
8892
|
+
"venv",
|
|
8893
|
+
"__pycache__",
|
|
8894
|
+
".tox",
|
|
8895
|
+
".pytest_cache",
|
|
8896
|
+
".loki",
|
|
8897
|
+
".next"
|
|
8898
|
+
]);
|
|
8899
|
+
});
|
|
8900
|
+
|
|
8901
|
+
// ../../loki-ts/src/util/check_result.ts
|
|
8902
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync12, readFileSync as readFileSync28, realpathSync as realpathSync16, renameSync as renameSync7, writeFileSync as writeFileSync15 } from "fs";
|
|
8903
|
+
import { basename as basename11, isAbsolute as isAbsolute3, join as join37 } from "path";
|
|
8904
|
+
function plainTestEnv(base = process.env) {
|
|
8905
|
+
const e = {};
|
|
8906
|
+
for (const [k, v] of Object.entries(tokenFreeEnv(base)))
|
|
8907
|
+
if (typeof v === "string")
|
|
8908
|
+
e[k] = v;
|
|
8909
|
+
e["FORCE_COLOR"] = "0";
|
|
8910
|
+
e["NO_COLOR"] = "1";
|
|
8911
|
+
delete e["CLICOLOR_FORCE"];
|
|
8912
|
+
return e;
|
|
8983
8913
|
}
|
|
8984
|
-
function
|
|
8985
|
-
const
|
|
8986
|
-
|
|
8987
|
-
|
|
8988
|
-
|
|
8989
|
-
|
|
8914
|
+
function ran(raw2, path, ok) {
|
|
8915
|
+
const out2 = stripAnsi(raw2);
|
|
8916
|
+
const n2 = (s, re) => +(s.match(re)?.[1] ?? 0);
|
|
8917
|
+
const blk = out2.trimEnd().match(/(?:^|\n)((?:(?:#|\u2139) \w+ [\d.]+(?:\n|$)){5,})$/)?.[1];
|
|
8918
|
+
if (blk) {
|
|
8919
|
+
const c = n2(blk, /(?:#|\u2139) pass (\d+)/) + n2(blk, /(?:#|\u2139) fail (\d+)/);
|
|
8920
|
+
const nm = out2.match(/^(?:ok \d+ - |\u2714 )(\S+\.[cm]?[jt]s)(?: \(|$)/m)?.[1];
|
|
8921
|
+
return c === 1 && nm && (!path || basename11(nm) === basename11(path)) ? 0 : c;
|
|
8990
8922
|
}
|
|
8991
|
-
|
|
8992
|
-
|
|
8993
|
-
return
|
|
8923
|
+
const cg = cargoTrailer(out2);
|
|
8924
|
+
if (cg.length)
|
|
8925
|
+
return cg.reduce((t, l2) => t + n2(l2, /(\d+) passed/) + n2(l2, /(\d+) failed/), 0);
|
|
8926
|
+
const g = goCount(out2, ok);
|
|
8927
|
+
if (g !== undefined)
|
|
8928
|
+
return g;
|
|
8929
|
+
const tail = tailLines(out2);
|
|
8930
|
+
const l = tail.filter((x) => /^(?:=+ )?(?:\d+ \w+.*|no tests ran) in [\d.]+s|^\s*Tests?:?\s+\d|^No tests found/.test(x) && (!/^\s*Tests?:?\s+\d/.test(x) || tail.some((y) => /^\s*Test (?:Files|Suites):?\s+\d/.test(y)))).pop();
|
|
8931
|
+
if (!l)
|
|
8932
|
+
return null;
|
|
8933
|
+
return /^(?:=+ )?no tests (?:ran|found)|^No tests found|skipped/i.test(l) || /\d+ (?:passed|failed|errors?)/.test(l) ? n2(l, /(\d+) passed/) + n2(l, /(\d+) failed/) + n2(l, /(\d+) errors?/) : null;
|
|
8934
|
+
}
|
|
8935
|
+
function cargoTrailer(out2) {
|
|
8936
|
+
const ls = out2.split(`
|
|
8937
|
+
`).filter((x) => x.trim());
|
|
8938
|
+
while (ls.length && /^error: /.test(ls[ls.length - 1]))
|
|
8939
|
+
ls.pop();
|
|
8940
|
+
const segs = [];
|
|
8941
|
+
for (const l of ls) {
|
|
8942
|
+
if (/^running \d+ tests?\b/.test(l))
|
|
8943
|
+
segs.push([]);
|
|
8944
|
+
else if (segs.length && !/^\s*(?:Running |Doc-tests |Doctest)/.test(l))
|
|
8945
|
+
segs[segs.length - 1].push(l);
|
|
8994
8946
|
}
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
return
|
|
9001
|
-
for (let j = i + 1;j < s.length; j++) {
|
|
9002
|
-
if (s[j] === "\\")
|
|
9003
|
-
j++;
|
|
9004
|
-
else if (s[j] === c)
|
|
9005
|
-
return j + 1;
|
|
9006
|
-
else if (s[j] === `
|
|
9007
|
-
`)
|
|
9008
|
-
return i;
|
|
8947
|
+
const lastOf = (g) => g[g.length - 1]?.startsWith("test result: ") ? g[g.length - 1] : undefined;
|
|
8948
|
+
if (!segs.length) {
|
|
8949
|
+
const g = [];
|
|
8950
|
+
for (let k = ls.length - 1;k >= 0 && ls[k].startsWith("test result: "); k--)
|
|
8951
|
+
g.push(ls[k]);
|
|
8952
|
+
return g;
|
|
9009
8953
|
}
|
|
9010
|
-
|
|
8954
|
+
if (!lastOf(segs[segs.length - 1]))
|
|
8955
|
+
return [];
|
|
8956
|
+
return segs.flatMap((g) => lastOf(g) ?? []);
|
|
9011
8957
|
}
|
|
9012
|
-
function
|
|
9013
|
-
|
|
9014
|
-
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
|
|
9019
|
-
|
|
9020
|
-
if (s[i] === "{")
|
|
9021
|
-
depth++;
|
|
9022
|
-
else if (s[i] === "}" && --depth === 0)
|
|
9023
|
-
return i;
|
|
9024
|
-
i++;
|
|
9025
|
-
}
|
|
9026
|
-
return s.length;
|
|
8958
|
+
function bunCount(out2) {
|
|
8959
|
+
const ls = out2.split(`
|
|
8960
|
+
`).filter((x) => x.trim());
|
|
8961
|
+
if (!/^Ran \d+ tests? across \d+ files?\./.test(ls[ls.length - 1] ?? ""))
|
|
8962
|
+
return null;
|
|
8963
|
+
const blk = ls.slice(-9, -1);
|
|
8964
|
+
const last = (k) => +(blk.map((x) => x.match(new RegExp(`^\\s*(\\d+) ${k}\\s*$`))?.[1]).filter(Boolean).pop() ?? 0);
|
|
8965
|
+
return last("pass") + last("fail");
|
|
9027
8966
|
}
|
|
9028
|
-
function
|
|
9029
|
-
const
|
|
9030
|
-
|
|
9031
|
-
|
|
9032
|
-
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9037
|
-
|
|
9038
|
-
while (i < src.length) {
|
|
9039
|
-
const j = skipLiteral(src, i);
|
|
9040
|
-
if (j !== i) {
|
|
9041
|
-
if (!isComment(src, i))
|
|
9042
|
-
head += src.slice(i, j);
|
|
9043
|
-
i = j;
|
|
9044
|
-
continue;
|
|
9045
|
-
}
|
|
9046
|
-
const c = src[i];
|
|
9047
|
-
if (c === "(" || c === "[")
|
|
9048
|
-
p++;
|
|
9049
|
-
else if (c === ")" || c === "]")
|
|
9050
|
-
p--;
|
|
9051
|
-
if (c === "{" && p === 0) {
|
|
9052
|
-
const close = matchingBrace(src, i);
|
|
9053
|
-
const h = head.trim();
|
|
9054
|
-
const declaration = /^(export\s+)?(declare\s+)?(type|interface|enum)\b/.test(h);
|
|
9055
|
-
if (declaration || h === "" || /^export(\s+type)?$/.test(h) || /[:|&]$/.test(h)) {
|
|
9056
|
-
head += stripComments(src.slice(i, close + 1));
|
|
9057
|
-
i = close + 1;
|
|
9058
|
-
if (declaration && !/^(export\s+)?(declare\s+)?type\b/.test(h))
|
|
9059
|
-
push("", null, i);
|
|
9060
|
-
continue;
|
|
9061
|
-
}
|
|
9062
|
-
const body = src.slice(i + 1, close);
|
|
9063
|
-
const balanced = close < src.length;
|
|
9064
|
-
i = close + 1;
|
|
9065
|
-
if (src[i] === ";")
|
|
9066
|
-
i++;
|
|
9067
|
-
push("{", body, i, balanced);
|
|
9068
|
-
continue;
|
|
9069
|
-
}
|
|
9070
|
-
if (c === ";" && p === 0) {
|
|
9071
|
-
i++;
|
|
9072
|
-
push(";", null, i);
|
|
9073
|
-
continue;
|
|
9074
|
-
}
|
|
9075
|
-
if (c === `
|
|
9076
|
-
` && p === 0 && head.trim() && /^\s*(export|import)\b/.test(src.slice(i + 1, i + 40))) {
|
|
9077
|
-
push("", null, i);
|
|
9078
|
-
i++;
|
|
9079
|
-
start = i;
|
|
9080
|
-
continue;
|
|
9081
|
-
}
|
|
9082
|
-
head += c;
|
|
9083
|
-
i++;
|
|
9084
|
-
}
|
|
9085
|
-
push("", null, src.length);
|
|
9086
|
-
return out2;
|
|
8967
|
+
function unittestCount(out2, ok) {
|
|
8968
|
+
const ls = out2.split(`
|
|
8969
|
+
`).filter((x) => x.trim()), v = ls[ls.length - 1] ?? "", r = ls[ls.length - 2]?.match(/^Ran (\d+) tests? in [\d.]+s$/);
|
|
8970
|
+
if (!r || !/^(?:OK|FAILED)\b/.test(v))
|
|
8971
|
+
return null;
|
|
8972
|
+
if (ls.filter((x) => /^Ran \d+ tests? in [\d.]+s$/.test(x)).length > 1)
|
|
8973
|
+
return null;
|
|
8974
|
+
if (ok === true && v.startsWith("FAILED") || ok === false && v.startsWith("OK"))
|
|
8975
|
+
return null;
|
|
8976
|
+
return Math.max(0, +r[1] - +(v.match(/skipped=(\d+)/)?.[1] ?? 0) - +(v.match(/expected failures=(\d+)/)?.[1] ?? 0));
|
|
9087
8977
|
}
|
|
9088
|
-
function
|
|
9089
|
-
const
|
|
9090
|
-
|
|
9091
|
-
|
|
9092
|
-
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
|
|
9098
|
-
|
|
9099
|
-
|
|
9100
|
-
|
|
9101
|
-
|
|
9102
|
-
if (s[i] === "=" && s[i + 1] === ">")
|
|
9103
|
-
i++;
|
|
9104
|
-
else if (s[i] === "<")
|
|
9105
|
-
d2++;
|
|
9106
|
-
else if (s[i] === ">" && --d2 === 0) {
|
|
9107
|
-
i++;
|
|
9108
|
-
break;
|
|
9109
|
-
}
|
|
8978
|
+
function goCount(out2, ok) {
|
|
8979
|
+
const lines = out2.split(`
|
|
8980
|
+
`);
|
|
8981
|
+
if (!lines.some((x) => GO_PKG_RE.test(x)))
|
|
8982
|
+
return;
|
|
8983
|
+
const last = new Map, seen = new Set, skip = new Set, failPkg = ok !== true && lines.some((x) => /^FAIL\s+\S+\s+[\d.]+s\b/.test(x));
|
|
8984
|
+
for (const x of lines) {
|
|
8985
|
+
const r = x.match(/^=== RUN\s+(\S+)/), m = x.match(/^--- (PASS|FAIL|SKIP): (\S+)/);
|
|
8986
|
+
if (r)
|
|
8987
|
+
seen.add(r[1]);
|
|
8988
|
+
else if (m && (seen.has(m[2]) || m[1] === "FAIL" && failPkg)) {
|
|
8989
|
+
last.set(m[2], m[1]);
|
|
8990
|
+
if (m[1] === "SKIP")
|
|
8991
|
+
skip.add(m[2]);
|
|
9110
8992
|
}
|
|
9111
|
-
if (d2 !== 0)
|
|
9112
|
-
return -1;
|
|
9113
|
-
ws();
|
|
9114
8993
|
}
|
|
9115
|
-
|
|
9116
|
-
|
|
9117
|
-
|
|
9118
|
-
|
|
9119
|
-
|
|
9120
|
-
|
|
8994
|
+
for (const k of skip)
|
|
8995
|
+
last.set(k, "SKIP");
|
|
8996
|
+
if (ok === true && [...last.values()].includes("FAIL"))
|
|
8997
|
+
return null;
|
|
8998
|
+
const t = [...last.values()].filter((v) => v !== "SKIP").length;
|
|
8999
|
+
if (t > 0)
|
|
9000
|
+
return t;
|
|
9001
|
+
if (lines.some((x) => /^(?:=== RUN|PASS$|FAIL$|testing: warning: no tests to run)/.test(x)))
|
|
9002
|
+
return 0;
|
|
9003
|
+
return lines.filter((x) => GO_PKG_RE.test(x)).every((x) => /\[no tests? (?:files|to run)\]/.test(x)) ? 0 : null;
|
|
9004
|
+
}
|
|
9005
|
+
function goRunner(cmd, args) {
|
|
9006
|
+
const segs = args ? [[cmd, ...args]] : cmd.split(/&&|\|\||[;|\n]/).map((x) => x.trim().split(/\s+/).filter(Boolean));
|
|
9007
|
+
for (const t0 of segs) {
|
|
9008
|
+
const t = t0.map((x) => x.replace(/^["']|["']$/g, ""));
|
|
9009
|
+
let k = 0;
|
|
9010
|
+
for (;k < t.length; k++) {
|
|
9011
|
+
const x = t[k];
|
|
9012
|
+
if (/^[A-Za-z_]\w*=/.test(x) || /^(?:env|command|exec|time|nohup)$/.test(basename11(x)))
|
|
9013
|
+
continue;
|
|
9014
|
+
if (/^-/.test(x) && k > 0 && basename11(t[k - 1]) === "env") {
|
|
9015
|
+
if (x === "-u" || x === "-C" || x === "-S")
|
|
9016
|
+
k++;
|
|
9121
9017
|
continue;
|
|
9122
9018
|
}
|
|
9123
|
-
|
|
9124
|
-
d2++;
|
|
9125
|
-
else if (s[i] === ")" && --d2 === 0) {
|
|
9126
|
-
i++;
|
|
9127
|
-
break;
|
|
9128
|
-
}
|
|
9129
|
-
i++;
|
|
9019
|
+
break;
|
|
9130
9020
|
}
|
|
9131
|
-
if (
|
|
9132
|
-
return
|
|
9133
|
-
} else {
|
|
9134
|
-
const st = i;
|
|
9135
|
-
while (i < n2 && /[\w$]/.test(s[i]))
|
|
9136
|
-
i++;
|
|
9137
|
-
if (i === st)
|
|
9138
|
-
return -1;
|
|
9021
|
+
if (t[k] !== undefined && basename11(t[k]) === "go")
|
|
9022
|
+
return { runner: "go" };
|
|
9139
9023
|
}
|
|
9140
|
-
|
|
9141
|
-
|
|
9142
|
-
|
|
9143
|
-
|
|
9144
|
-
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
const k = skipLiteral(s, i);
|
|
9148
|
-
if (k !== i) {
|
|
9149
|
-
i = k;
|
|
9024
|
+
return {};
|
|
9025
|
+
}
|
|
9026
|
+
function goJson(out2) {
|
|
9027
|
+
let any = false, failed2 = false;
|
|
9028
|
+
for (const x of out2.split(`
|
|
9029
|
+
`)) {
|
|
9030
|
+
if (!x.trim() || /^go: /.test(x))
|
|
9150
9031
|
continue;
|
|
9032
|
+
let e;
|
|
9033
|
+
try {
|
|
9034
|
+
e = JSON.parse(x);
|
|
9035
|
+
} catch {
|
|
9036
|
+
return null;
|
|
9151
9037
|
}
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
else if (d === 0 && c === "=")
|
|
9158
|
-
return s[i + 1] === ">" ? i + 2 : -1;
|
|
9159
|
-
else if (d === 0 && c === ";")
|
|
9160
|
-
return -1;
|
|
9161
|
-
i++;
|
|
9038
|
+
if (!e || typeof e !== "object" || typeof e.Action !== "string")
|
|
9039
|
+
return null;
|
|
9040
|
+
any = true;
|
|
9041
|
+
if (e.Action === "fail")
|
|
9042
|
+
failed2 = true;
|
|
9162
9043
|
}
|
|
9163
|
-
return
|
|
9044
|
+
return any ? { failed: failed2 } : null;
|
|
9164
9045
|
}
|
|
9165
|
-
function
|
|
9166
|
-
|
|
9167
|
-
return null;
|
|
9168
|
-
let depth = 0, angle = 0;
|
|
9169
|
-
for (let i = 0;i < h.length; i++) {
|
|
9170
|
-
const c = h[i];
|
|
9171
|
-
if ("([{".includes(c))
|
|
9172
|
-
depth++;
|
|
9173
|
-
else if (")]}".includes(c))
|
|
9174
|
-
depth--;
|
|
9175
|
-
else if (depth === 0 && c === "<")
|
|
9176
|
-
angle++;
|
|
9177
|
-
else if (depth === 0 && c === ">" && h[i - 1] !== "=" && angle > 0)
|
|
9178
|
-
angle--;
|
|
9179
|
-
else if (c === "=" && depth === 0 && angle === 0 && !"=!<".includes(h[i - 1] ?? " ") && h[i + 1] !== "=" && h[i + 1] !== ">") {
|
|
9180
|
-
const rhs = h.slice(i + 1).trim();
|
|
9181
|
-
if (rhs.endsWith("=>") || /^(async\s+)?function\b/.test(rhs))
|
|
9182
|
-
return h;
|
|
9183
|
-
const len = arrowHeadLen(rhs);
|
|
9184
|
-
return `${h.slice(0, i).trim()}${len > 0 ? ` = ${rhs.slice(0, len)}` : ""}`;
|
|
9185
|
-
}
|
|
9186
|
-
}
|
|
9187
|
-
return h;
|
|
9046
|
+
function summaryPassFailCount(out2) {
|
|
9047
|
+
return ["pass", "fail"].reduce((t, k) => t + +([...out2.matchAll(new RegExp(`^(?:#|\\u2139) ${k} (\\d+)$`, "gm"))].pop()?.[1] ?? 0), 0);
|
|
9188
9048
|
}
|
|
9189
|
-
function
|
|
9190
|
-
|
|
9191
|
-
|
|
9192
|
-
for (let i = 0;i < h.length; ) {
|
|
9193
|
-
const k = skipLiteral(h, i);
|
|
9194
|
-
if (k !== i) {
|
|
9195
|
-
i = k;
|
|
9196
|
-
continue;
|
|
9197
|
-
}
|
|
9198
|
-
const c = h[i];
|
|
9199
|
-
if ("([{".includes(c))
|
|
9200
|
-
depth++;
|
|
9201
|
-
else if (")]}".includes(c))
|
|
9202
|
-
depth--;
|
|
9203
|
-
else if (depth === 0 && !init && c === "<")
|
|
9204
|
-
angle++;
|
|
9205
|
-
else if (depth === 0 && !init && c === ">" && h[i - 1] !== "=")
|
|
9206
|
-
angle = Math.max(0, angle - 1);
|
|
9207
|
-
else if (depth === 0 && angle === 0 && !init && c === "=" && h[i + 1] !== "=" && h[i + 1] !== ">" && !"=!<".includes(h[i - 1] ?? " ")) {
|
|
9208
|
-
init = true;
|
|
9209
|
-
const rest = h.slice(i + 1);
|
|
9210
|
-
const len = arrowHeadLen(rest.trimStart());
|
|
9211
|
-
if (len > 0) {
|
|
9212
|
-
i += 1 + (rest.length - rest.trimStart().length) + len;
|
|
9213
|
-
continue;
|
|
9214
|
-
}
|
|
9215
|
-
} else if (depth === 0 && angle === 0 && c === ",") {
|
|
9216
|
-
parts.push(h.slice(from, i));
|
|
9217
|
-
from = i + 1;
|
|
9218
|
-
init = false;
|
|
9219
|
-
}
|
|
9220
|
-
i++;
|
|
9221
|
-
}
|
|
9222
|
-
parts.push(h.slice(from));
|
|
9223
|
-
return parts;
|
|
9049
|
+
function skipped(raw2) {
|
|
9050
|
+
return stripAnsi(raw2).split(`
|
|
9051
|
+
`).filter((l) => /^(?:=+ )?\d+ \w+.* in [\d.]+s|^\s*Tests?:?\s+\d|^(?:#|\u2139) skipped \d/.test(l.trim())).reduce((t, l) => t + [...l.matchAll(/(\d+) (?:skipped|deselected|xfailed)|skipped (\d+)/g)].reduce((u, m) => u + +(m[1] ?? m[2]), 0), 0);
|
|
9224
9052
|
}
|
|
9225
|
-
function
|
|
9226
|
-
|
|
9227
|
-
const
|
|
9228
|
-
|
|
9229
|
-
|
|
9230
|
-
|
|
9231
|
-
|
|
9232
|
-
|
|
9233
|
-
|
|
9234
|
-
|
|
9235
|
-
|
|
9236
|
-
|
|
9237
|
-
|
|
9238
|
-
|
|
9239
|
-
|
|
9240
|
-
|
|
9241
|
-
|
|
9242
|
-
|
|
9243
|
-
|
|
9244
|
-
|
|
9245
|
-
|
|
9246
|
-
|
|
9247
|
-
|
|
9248
|
-
|
|
9249
|
-
|
|
9250
|
-
|
|
9251
|
-
|
|
9252
|
-
|
|
9253
|
-
|
|
9254
|
-
}
|
|
9255
|
-
|
|
9256
|
-
|
|
9257
|
-
|
|
9053
|
+
function testCount(raw2, path, ok) {
|
|
9054
|
+
const out2 = stripAnsi(raw2);
|
|
9055
|
+
const bu = bunCount(out2), ut = unittestCount(out2, ok);
|
|
9056
|
+
if (bu !== null)
|
|
9057
|
+
return bu;
|
|
9058
|
+
if (ut !== null)
|
|
9059
|
+
return ut;
|
|
9060
|
+
if (/^\s*(?:Test Files\s+0\b|No test files found)/m.test(out2) && !/^\s*Tests?\s+\d/m.test(out2))
|
|
9061
|
+
return 0;
|
|
9062
|
+
const r = ran(out2, path, ok);
|
|
9063
|
+
if (r !== null)
|
|
9064
|
+
return r;
|
|
9065
|
+
const tl = tailLines(out2);
|
|
9066
|
+
const pw = tl.filter((x) => /^\s*\d+ (?:passed|failed|flaky)\b/.test(x));
|
|
9067
|
+
if (pw.length && tl.some((x) => /^\s*\d+ passed \([\d.]+m?s\)/.test(x) || /^\s*\d+ failed$/.test(x)))
|
|
9068
|
+
return pw.reduce((t, x) => t + +x.trim().split(" ")[0], 0);
|
|
9069
|
+
const lastNum = (re) => {
|
|
9070
|
+
const m = [...out2.matchAll(re)].pop();
|
|
9071
|
+
return m ? +m[1] : null;
|
|
9072
|
+
};
|
|
9073
|
+
const mp = lastNum(/^\s*(\d+) passing\b/gm), mf = lastNum(/^\s*(\d+) failing\b/gm);
|
|
9074
|
+
if (mp !== null || mf !== null)
|
|
9075
|
+
return (mp ?? 0) + (mf ?? 0);
|
|
9076
|
+
return null;
|
|
9077
|
+
}
|
|
9078
|
+
function classifyCheck(i) {
|
|
9079
|
+
if (i.missing)
|
|
9080
|
+
return { result: "not_run", reason: "tool not found on PATH" };
|
|
9081
|
+
if (i.cut)
|
|
9082
|
+
return { result: "not_run", reason: "timed out or aborted" };
|
|
9083
|
+
if (i.kind === "static")
|
|
9084
|
+
return { result: i.ok ? "pass" : "fail" };
|
|
9085
|
+
const text2 = stripAnsi(i.out);
|
|
9086
|
+
if (i.runner === "go") {
|
|
9087
|
+
if (i.ok)
|
|
9088
|
+
return { result: "not_run", reason: GO_EXIT0_REASON };
|
|
9089
|
+
const j = goJson(text2);
|
|
9090
|
+
if (j)
|
|
9091
|
+
return j.failed ? { result: "fail" } : { result: "not_run", reason: UNCONFIRMED_REASON };
|
|
9092
|
+
return FAIL_EVIDENCE.test(text2) || GO_FAIL_EVIDENCE.test(text2) ? { result: "fail" } : { result: "not_run", reason: UNCONFIRMED_REASON };
|
|
9258
9093
|
}
|
|
9259
|
-
|
|
9094
|
+
const n2 = testCount(i.out, i.path, i.ok);
|
|
9095
|
+
if (!i.ok && FAIL_EVIDENCE.test(text2))
|
|
9096
|
+
return { result: "fail", ...n2 !== null ? { n: n2 } : {} };
|
|
9097
|
+
if (n2 === 0)
|
|
9098
|
+
return { result: "not_run", n: 0, reason: `${NO_TESTS_REASON} (ran 0 tests, empty or all skipped)` };
|
|
9099
|
+
if (!i.ok)
|
|
9100
|
+
return { result: "fail", ...n2 !== null ? { n: n2 } : {} };
|
|
9101
|
+
if (n2 === null)
|
|
9102
|
+
return { result: "not_run", reason: UNMEASURED_REASON };
|
|
9103
|
+
return { result: "pass", n: n2 };
|
|
9260
9104
|
}
|
|
9261
|
-
function
|
|
9262
|
-
|
|
9263
|
-
|
|
9264
|
-
|
|
9265
|
-
|
|
9266
|
-
|
|
9267
|
-
|
|
9268
|
-
|
|
9269
|
-
|
|
9270
|
-
|
|
9271
|
-
|
|
9272
|
-
|
|
9273
|
-
|
|
9274
|
-
|
|
9275
|
-
return true;
|
|
9276
|
-
i++;
|
|
9105
|
+
function checkProvenance(name, ctx) {
|
|
9106
|
+
const head = name.split(":")[0];
|
|
9107
|
+
if (LLM_JUDGES.has(head))
|
|
9108
|
+
return "llm_judge";
|
|
9109
|
+
if (head === "holdout")
|
|
9110
|
+
return "independent";
|
|
9111
|
+
if (!NON_RUNNER.has(head) && name.includes(":")) {
|
|
9112
|
+
const p = normPath(name.slice(name.indexOf(":") + 1));
|
|
9113
|
+
if (ctx.wallFiles.some((w) => normPath(w) === p))
|
|
9114
|
+
return "independent";
|
|
9115
|
+
if (ctx.addedFiles.some((a) => normPath(a) === p))
|
|
9116
|
+
return "agent_authored";
|
|
9117
|
+
if (ctx.modifiedFiles?.some((m) => normPath(m) === p))
|
|
9118
|
+
return "agent_authored";
|
|
9277
9119
|
}
|
|
9278
|
-
return
|
|
9120
|
+
return "exogenous";
|
|
9279
9121
|
}
|
|
9280
|
-
function
|
|
9281
|
-
const
|
|
9282
|
-
|
|
9283
|
-
|
|
9284
|
-
if (m.end !== "{" && /^[^=:<]*\(/.test(h) && !/^(?:(?:public|protected|private)\s+)?constructor\b/.test(h) && !/\)\s*:/.test(h))
|
|
9285
|
-
return false;
|
|
9286
|
-
return true;
|
|
9122
|
+
function summaryOf(a) {
|
|
9123
|
+
const why = a.tier === a.computed ? a.reasons.slice(0, 2).join("; ") : `computed ${a.computed}; override ${a.override?.from} to ${a.override?.to}: ${a.override?.reason}`;
|
|
9124
|
+
const def = a.checks_deferred;
|
|
9125
|
+
return `risk: ${a.tier} (${why}), ${def.length ? def.join(", ") : "no deeper checks"} not run`;
|
|
9287
9126
|
}
|
|
9288
|
-
function
|
|
9289
|
-
const
|
|
9290
|
-
|
|
9291
|
-
for (let j = from;j < n2; ) {
|
|
9292
|
-
const c = s[j];
|
|
9293
|
-
if (c === "\\")
|
|
9294
|
-
j += 2;
|
|
9295
|
-
else if (c === "`")
|
|
9296
|
-
return j + 1;
|
|
9297
|
-
else if (c === "$" && s[j + 1] === "{") {
|
|
9298
|
-
stack.push("$");
|
|
9299
|
-
return j + 2;
|
|
9300
|
-
} else
|
|
9301
|
-
j++;
|
|
9302
|
-
}
|
|
9303
|
-
return -1;
|
|
9304
|
-
};
|
|
9305
|
-
let prev = "", prev2 = "";
|
|
9306
|
-
const set = (c) => {
|
|
9307
|
-
prev2 = prev;
|
|
9308
|
-
prev = c;
|
|
9309
|
-
};
|
|
9310
|
-
for (let i = 0;i < n2; ) {
|
|
9311
|
-
const c = s[i];
|
|
9312
|
-
if (/\s/.test(c)) {
|
|
9313
|
-
i++;
|
|
9314
|
-
continue;
|
|
9315
|
-
}
|
|
9316
|
-
if (c === "/" && s[i + 1] === "/") {
|
|
9317
|
-
const e = s.indexOf(`
|
|
9318
|
-
`, i);
|
|
9319
|
-
if (e < 0)
|
|
9320
|
-
break;
|
|
9321
|
-
i = e;
|
|
9322
|
-
continue;
|
|
9323
|
-
}
|
|
9324
|
-
if (c === "/" && s[i + 1] === "*") {
|
|
9325
|
-
const e = s.indexOf("*/", i + 2);
|
|
9326
|
-
if (e < 0)
|
|
9327
|
-
return true;
|
|
9328
|
-
i = e + 2;
|
|
9329
|
-
continue;
|
|
9330
|
-
}
|
|
9331
|
-
if (c === "`" || c === "}" && stack[stack.length - 1] === "$") {
|
|
9332
|
-
if (c === "`" && jsx)
|
|
9333
|
-
return true;
|
|
9334
|
-
if (c === "}")
|
|
9335
|
-
stack.pop();
|
|
9336
|
-
const e = tpl(i + 1);
|
|
9337
|
-
if (e < 0)
|
|
9338
|
-
return true;
|
|
9339
|
-
i = e;
|
|
9340
|
-
set("a");
|
|
9341
|
-
continue;
|
|
9342
|
-
}
|
|
9343
|
-
if (c === '"' || c === "'") {
|
|
9344
|
-
let j = i + 1;
|
|
9345
|
-
for (;j < n2 && s[j] !== c; j++) {
|
|
9346
|
-
if (s[j] === "\\")
|
|
9347
|
-
j++;
|
|
9348
|
-
else if (s[j] === `
|
|
9349
|
-
`)
|
|
9350
|
-
return true;
|
|
9351
|
-
}
|
|
9352
|
-
if (j >= n2)
|
|
9353
|
-
return true;
|
|
9354
|
-
i = j + 1;
|
|
9355
|
-
set("a");
|
|
9356
|
-
continue;
|
|
9357
|
-
}
|
|
9358
|
-
if (c === "/") {
|
|
9359
|
-
if (jsx && prev === "<") {
|
|
9360
|
-
i++;
|
|
9361
|
-
set("/");
|
|
9362
|
-
continue;
|
|
9363
|
-
}
|
|
9364
|
-
if (commentBefore(s, i))
|
|
9365
|
-
return true;
|
|
9366
|
-
if (prev && !"(,=:[!&|?{;+-*%~^".includes(prev))
|
|
9367
|
-
return true;
|
|
9368
|
-
if ((prev === "+" || prev === "-") && prev2 === prev)
|
|
9369
|
-
return true;
|
|
9370
|
-
let j = i + 1, cls = false, closed = false;
|
|
9371
|
-
for (;j < n2; j++) {
|
|
9372
|
-
const d = s[j];
|
|
9373
|
-
if (d === `
|
|
9374
|
-
`)
|
|
9375
|
-
return true;
|
|
9376
|
-
if (d === "\\")
|
|
9377
|
-
j++;
|
|
9378
|
-
else if (d === "[")
|
|
9379
|
-
cls = true;
|
|
9380
|
-
else if (d === "]")
|
|
9381
|
-
cls = false;
|
|
9382
|
-
else if (d === "/" && !cls) {
|
|
9383
|
-
closed = true;
|
|
9384
|
-
break;
|
|
9385
|
-
}
|
|
9386
|
-
}
|
|
9387
|
-
if (!closed)
|
|
9388
|
-
return true;
|
|
9389
|
-
i = j + 1;
|
|
9390
|
-
while (i < n2 && /[a-z]/i.test(s[i]))
|
|
9391
|
-
i++;
|
|
9392
|
-
set("a");
|
|
9393
|
-
continue;
|
|
9394
|
-
}
|
|
9395
|
-
if (c === "(" || c === "[" || c === "{")
|
|
9396
|
-
stack.push(c);
|
|
9397
|
-
else if (c === ")" || c === "]" || c === "}") {
|
|
9398
|
-
const o = stack.pop();
|
|
9399
|
-
if (o !== (c === ")" ? "(" : c === "]" ? "[" : "{"))
|
|
9400
|
-
return true;
|
|
9401
|
-
}
|
|
9402
|
-
set(c);
|
|
9403
|
-
i++;
|
|
9404
|
-
}
|
|
9405
|
-
return stack.length > 0;
|
|
9127
|
+
function markExecuted(a, executed) {
|
|
9128
|
+
const checks_deferred = deferredOf(a.tier, a.checks_selected, executed);
|
|
9129
|
+
return { ...a, checks_deferred, summary: summaryOf({ ...a, checks_deferred }) + (a.advisories?.length ? `; advisory: ${a.advisories.join(", ")}` : "") };
|
|
9406
9130
|
}
|
|
9407
|
-
function
|
|
9408
|
-
|
|
9409
|
-
|
|
9410
|
-
|
|
9411
|
-
|
|
9412
|
-
|
|
9413
|
-
|
|
9414
|
-
continue;
|
|
9415
|
-
}
|
|
9416
|
-
const c = sig[i];
|
|
9417
|
-
if (c === "(")
|
|
9418
|
-
pd++;
|
|
9419
|
-
else if (c === ")")
|
|
9420
|
-
pd--;
|
|
9421
|
-
else if (c === "=" && pd > 0 && sig[i + 1] !== "=" && sig[i + 1] !== ">" && !"=!<".includes(sig[i - 1] ?? " ")) {
|
|
9422
|
-
out2 = out2.trimEnd() + " = ...";
|
|
9423
|
-
let d = 0, angle = 0, j = i + 1;
|
|
9424
|
-
for (;j < sig.length; ) {
|
|
9425
|
-
const l = skipLiteral(sig, j);
|
|
9426
|
-
if (l !== j) {
|
|
9427
|
-
j = l;
|
|
9428
|
-
continue;
|
|
9429
|
-
}
|
|
9430
|
-
const e = sig[j];
|
|
9431
|
-
if ("([{".includes(e))
|
|
9432
|
-
d++;
|
|
9433
|
-
else if (")]}".includes(e)) {
|
|
9434
|
-
if (d === 0)
|
|
9435
|
-
break;
|
|
9436
|
-
d--;
|
|
9437
|
-
} else if (e === "<" && /[\w$]/.test(sig[j - 1] ?? ""))
|
|
9438
|
-
angle++;
|
|
9439
|
-
else if (e === ">" && sig[j - 1] !== "=" && angle > 0)
|
|
9440
|
-
angle--;
|
|
9441
|
-
else if (e === "," && d === 0 && angle === 0)
|
|
9442
|
-
break;
|
|
9443
|
-
j++;
|
|
9444
|
-
}
|
|
9445
|
-
i = j;
|
|
9446
|
-
continue;
|
|
9131
|
+
function manifestDepsChanged(path, oldText, newText, patch) {
|
|
9132
|
+
if (/(^|\/)package\.json$/.test(path)) {
|
|
9133
|
+
try {
|
|
9134
|
+
const o = oldText.trim() ? JSON.parse(oldText) : {}, n2 = newText.trim() ? JSON.parse(newText) : {};
|
|
9135
|
+
return PKG_DEP_KEYS.some((k) => JSON.stringify(o?.[k] ?? {}) !== JSON.stringify(n2?.[k] ?? {}));
|
|
9136
|
+
} catch {
|
|
9137
|
+
return true;
|
|
9447
9138
|
}
|
|
9448
|
-
out2 += c;
|
|
9449
|
-
i++;
|
|
9450
9139
|
}
|
|
9451
|
-
|
|
9140
|
+
const changed = patch.split(`
|
|
9141
|
+
`).filter((l) => /^[+-]/.test(l) && !/^(\+\+\+|---)/.test(l));
|
|
9142
|
+
if (/(^|\/)go\.mod$/.test(path))
|
|
9143
|
+
return changed.some((l) => {
|
|
9144
|
+
const b = l.slice(1).trim();
|
|
9145
|
+
return b !== "" && !b.startsWith("//") && !/^(module|go|toolchain)\b/.test(b);
|
|
9146
|
+
});
|
|
9147
|
+
return changed.some((l) => {
|
|
9148
|
+
const b = l.slice(1).trim();
|
|
9149
|
+
if (/^"[A-Za-z][\w.-]*(\[[\w,.-]+\])?\s*([<>=~!]|;|@|"\s*,?\s*$)/.test(b))
|
|
9150
|
+
return true;
|
|
9151
|
+
const m = /^([A-Za-z][\w.-]*)\s*=\s*("[\^~<>=!*\d]|\{[^}]*version)/.exec(b);
|
|
9152
|
+
return !!m && !PYPROJECT_NONDEP.test(m[1]);
|
|
9153
|
+
});
|
|
9452
9154
|
}
|
|
9453
|
-
function
|
|
9454
|
-
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9155
|
+
function manifestsWithoutLock(files) {
|
|
9156
|
+
return files.filter((f) => f.deps && f.status !== "deleted").flatMap((f) => {
|
|
9157
|
+
const pair = MANIFEST_LOCKS.find(([m]) => m.test(f.path));
|
|
9158
|
+
if (!pair)
|
|
9159
|
+
return [];
|
|
9160
|
+
const d = dirOf(f.path);
|
|
9161
|
+
const locked = files.some((g) => pair[1].test(g.path) && (dirOf(g.path) === "" || d === dirOf(g.path) || d.startsWith(dirOf(g.path) + "/")));
|
|
9162
|
+
return locked ? [] : [f.path];
|
|
9163
|
+
});
|
|
9164
|
+
}
|
|
9165
|
+
function classifyRisk(files, env = process.env) {
|
|
9166
|
+
const lines = files.reduce((n2, f) => n2 + f.added + f.deleted, 0);
|
|
9167
|
+
const sensitive = files.flatMap((f) => {
|
|
9168
|
+
const hit = SENSITIVE.find(([, re]) => re.test(f.path));
|
|
9169
|
+
return hit && !isTestFile(f.path) ? [`${f.path} (${hit[0]})`] : [];
|
|
9170
|
+
});
|
|
9171
|
+
const testFiles = files.filter((f) => isTestFile(f.path));
|
|
9172
|
+
const testsDeleted = testFiles.filter((f) => f.status === "deleted").map((f) => f.path);
|
|
9173
|
+
const testsModified = [...testFiles.filter((f) => f.status !== "added" && f.status !== "deleted").map((f) => f.path), ...files.filter((f) => TEST_CFG.test(f.path)).map((f) => f.path)];
|
|
9174
|
+
const api = files.filter((f) => API.test(f.path) && !isTestFile(f.path)).map((f) => f.path);
|
|
9175
|
+
const high = [], med = [];
|
|
9176
|
+
if (sensitive.length)
|
|
9177
|
+
high.push(`sensitive paths: ${sensitive.slice(0, 5).join(", ")}${sensitive.length > 5 ? ` (+${sensitive.length - 5})` : ""}`);
|
|
9178
|
+
if (testsDeleted.length)
|
|
9179
|
+
high.push(`test files deleted: ${testsDeleted.join(", ")}`);
|
|
9180
|
+
if (api.length)
|
|
9181
|
+
high.push(`public API surface: ${api.slice(0, 3).join(", ")}`);
|
|
9182
|
+
if (files.length >= FILES_HIGH)
|
|
9183
|
+
high.push(`${files.length} files >= ${FILES_HIGH}`);
|
|
9184
|
+
if (lines >= LINES_HIGH)
|
|
9185
|
+
high.push(`${lines} changed lines >= ${LINES_HIGH}`);
|
|
9186
|
+
if (testsModified.length)
|
|
9187
|
+
med.push(`existing tests or test config modified: ${testsModified.slice(0, 3).join(", ")}`);
|
|
9188
|
+
if (files.length >= FILES_MEDIUM)
|
|
9189
|
+
med.push(`${files.length} files >= ${FILES_MEDIUM}`);
|
|
9190
|
+
if (lines >= LINES_MEDIUM)
|
|
9191
|
+
med.push(`${lines} changed lines >= ${LINES_MEDIUM}`);
|
|
9192
|
+
const computed = high.length ? "high" : med.length ? "medium" : "low";
|
|
9193
|
+
const reasons = high.length ? [...high, ...med] : med.length ? med : [`${files.length} file${files.length === 1 ? "" : "s"}, no sensitive paths`];
|
|
9194
|
+
let tier = computed, override, ignored;
|
|
9195
|
+
const asked = (env["LOKI_RISK_TIER"] ?? "").trim().toLowerCase();
|
|
9196
|
+
if (asked in RANK2 && asked !== computed) {
|
|
9197
|
+
const reason = (env["LOKI_RISK_OVERRIDE_REASON"] ?? "").trim();
|
|
9198
|
+
if (RANK2[asked] > RANK2[computed]) {
|
|
9199
|
+
tier = asked;
|
|
9200
|
+
override = { from: computed, to: asked, reason: reason || "raised by LOKI_RISK_TIER" };
|
|
9201
|
+
} else if (reason) {
|
|
9202
|
+
tier = asked;
|
|
9203
|
+
override = { from: computed, to: asked, reason };
|
|
9204
|
+
} else
|
|
9205
|
+
ignored = `LOKI_RISK_TIER=${asked} ignored: lowering from ${computed} needs LOKI_RISK_OVERRIDE_REASON`;
|
|
9206
|
+
}
|
|
9207
|
+
const plan = PLAN[tier], checks_deferred = deferredOf(tier, plan.selected, []);
|
|
9208
|
+
const advisories = manifestsWithoutLock(files).map((p) => `manifest changed without lockfile: ${p}`);
|
|
9209
|
+
const summary = summaryOf({ tier, computed, reasons, ...override ? { override } : {}, checks_deferred }) + (advisories.length ? `; advisory: ${advisories.join(", ")}` : "");
|
|
9210
|
+
return {
|
|
9211
|
+
version: 1,
|
|
9212
|
+
tier,
|
|
9213
|
+
computed,
|
|
9214
|
+
reasons,
|
|
9215
|
+
stats: { files: files.length, lines, sensitive, tests_modified: testsModified, tests_deleted: testsDeleted, api },
|
|
9216
|
+
checks_selected: plan.selected,
|
|
9217
|
+
checks_deferred,
|
|
9218
|
+
...override ? { override } : {},
|
|
9219
|
+
...ignored ? { override_ignored: ignored } : {},
|
|
9220
|
+
...advisories.length ? { advisories } : {},
|
|
9221
|
+
summary
|
|
9458
9222
|
};
|
|
9459
|
-
|
|
9460
|
-
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
|
|
9466
|
-
|
|
9467
|
-
|
|
9468
|
-
|
|
9223
|
+
}
|
|
9224
|
+
function changedFiles(repoDir, baseSha) {
|
|
9225
|
+
const run = (args) => safeGit(repoDir, args).split(`
|
|
9226
|
+
`).map((l) => l.trim()).filter(Boolean);
|
|
9227
|
+
const tracked = run(["diff", "--name-only", baseSha]);
|
|
9228
|
+
const untracked = run(["ls-files", "--others", "--exclude-standard"]);
|
|
9229
|
+
return [...new Set([...tracked, ...untracked])].filter((f) => !f.startsWith(".loki/"));
|
|
9230
|
+
}
|
|
9231
|
+
function diffFiles(repoDir, baseSha) {
|
|
9232
|
+
const paths = changedFiles(repoDir, baseSha), stat = new Map;
|
|
9233
|
+
for (const l of safeGit(repoDir, ["diff", "--numstat", baseSha]).split(`
|
|
9234
|
+
`)) {
|
|
9235
|
+
const [a, d, ...p] = l.split("\t"), path = p.join("\t");
|
|
9236
|
+
if (path)
|
|
9237
|
+
stat.set(path, { path, added: Number(a) || 0, deleted: Number(d) || 0 });
|
|
9238
|
+
}
|
|
9239
|
+
for (const l of safeGit(repoDir, ["diff", "--name-status", baseSha]).split(`
|
|
9240
|
+
`)) {
|
|
9241
|
+
const [s, ...p] = l.split("\t"), f = stat.get(p[p.length - 1] ?? "");
|
|
9242
|
+
if (f)
|
|
9243
|
+
f.status = s?.startsWith("A") ? "added" : s?.startsWith("D") ? "deleted" : "modified";
|
|
9244
|
+
}
|
|
9245
|
+
const out2 = paths.map((path) => {
|
|
9246
|
+
const f = stat.get(path);
|
|
9247
|
+
if (f)
|
|
9248
|
+
return f;
|
|
9249
|
+
let n2 = 0;
|
|
9250
|
+
try {
|
|
9251
|
+
n2 = readFileSync28(join37(repoDir, path), "utf8").split(`
|
|
9252
|
+
`).length;
|
|
9253
|
+
} catch {}
|
|
9254
|
+
return { path, added: n2, deleted: 0, status: "added" };
|
|
9255
|
+
});
|
|
9256
|
+
for (const f of out2) {
|
|
9257
|
+
if (f.status === "deleted" || !MANIFEST_LOCKS.some(([m]) => m.test(f.path)))
|
|
9469
9258
|
continue;
|
|
9470
|
-
|
|
9471
|
-
|
|
9472
|
-
|
|
9473
|
-
|
|
9474
|
-
|
|
9475
|
-
|
|
9476
|
-
|
|
9477
|
-
|
|
9478
|
-
|
|
9479
|
-
}
|
|
9480
|
-
if (badNext(i))
|
|
9481
|
-
return null;
|
|
9259
|
+
try {
|
|
9260
|
+
const oldText = f.status === "added" ? "" : safeGit(repoDir, ["show", `${baseSha}:${f.path}`]);
|
|
9261
|
+
const newText = readFileSync28(join37(repoDir, f.path), "utf8");
|
|
9262
|
+
const patch = f.status === "added" ? newText.split(`
|
|
9263
|
+
`).map((l) => `+${l}`).join(`
|
|
9264
|
+
`) : safeGit(repoDir, ["diff", "-U0", baseSha, "--", f.path]);
|
|
9265
|
+
if (manifestDepsChanged(f.path, oldText, newText, patch))
|
|
9266
|
+
f.deps = true;
|
|
9267
|
+
} catch {}
|
|
9482
9268
|
}
|
|
9483
9269
|
return out2;
|
|
9484
9270
|
}
|
|
9485
|
-
function
|
|
9486
|
-
|
|
9487
|
-
|
|
9488
|
-
|
|
9489
|
-
|
|
9490
|
-
|
|
9491
|
-
|
|
9492
|
-
|
|
9493
|
-
|
|
9494
|
-
|
|
9495
|
-
else if (")]}".includes(s[i]) && --d === 0)
|
|
9496
|
-
return i + 1;
|
|
9497
|
-
i++;
|
|
9271
|
+
function recordRisk(repoDir, a) {
|
|
9272
|
+
try {
|
|
9273
|
+
const dir = join37(repoDir, ".loki", "state"), p = join37(dir, "risk-tier.json");
|
|
9274
|
+
mkdirSync12(dir, { recursive: true });
|
|
9275
|
+
writeFileSync15(`${p}.tmp`, JSON.stringify(a, null, 2) + `
|
|
9276
|
+
`);
|
|
9277
|
+
renameSync7(`${p}.tmp`, p);
|
|
9278
|
+
return p;
|
|
9279
|
+
} catch {
|
|
9280
|
+
return null;
|
|
9498
9281
|
}
|
|
9499
|
-
return s.length;
|
|
9500
9282
|
}
|
|
9501
|
-
function
|
|
9502
|
-
|
|
9503
|
-
|
|
9504
|
-
|
|
9505
|
-
|
|
9506
|
-
|
|
9507
|
-
|
|
9508
|
-
|
|
9509
|
-
|
|
9510
|
-
|
|
9511
|
-
|
|
9512
|
-
|
|
9513
|
-
|
|
9514
|
-
|
|
9515
|
-
|
|
9516
|
-
|
|
9517
|
-
|
|
9518
|
-
|
|
9519
|
-
|
|
9520
|
-
|
|
9521
|
-
|
|
9522
|
-
|
|
9523
|
-
|
|
9524
|
-
|
|
9525
|
-
|
|
9283
|
+
function truncateBytes(s, cap) {
|
|
9284
|
+
const buf = Buffer.from(s, "utf8");
|
|
9285
|
+
return buf.length <= cap ? s : buf.subarray(0, Math.max(0, cap)).toString("utf8").replace(/\uFFFD$/, "");
|
|
9286
|
+
}
|
|
9287
|
+
function failureExcerpt(out2, repoDir = "", cap = EXCERPT_GROUP_CAP) {
|
|
9288
|
+
let t = stripAnsi(out2.slice(-65536)).replace(/\r/g, "");
|
|
9289
|
+
if (repoDir)
|
|
9290
|
+
t = t.split(repoDir.replace(/\/+$/, "") + "/").join("");
|
|
9291
|
+
const lines = t.split(`
|
|
9292
|
+
`).map((l) => l.replace(/\s+$/, ""));
|
|
9293
|
+
const pick = new Set;
|
|
9294
|
+
const take = (i, n2 = 1) => {
|
|
9295
|
+
for (let k = 0;k < n2 && i + k < lines.length; k++)
|
|
9296
|
+
if (lines[i + k].trim())
|
|
9297
|
+
pick.add(i + k);
|
|
9298
|
+
};
|
|
9299
|
+
lines.forEach((l, i) => {
|
|
9300
|
+
if (/^E\s/.test(l))
|
|
9301
|
+
take(i);
|
|
9302
|
+
else if (/^\s*(Expected|Received)\b/.test(l) || /^\s*expect\(.*\)\.\w+/.test(l))
|
|
9303
|
+
take(i);
|
|
9304
|
+
else if (/^[\w./@-]+\.py:\d+: /.test(l))
|
|
9305
|
+
take(i);
|
|
9306
|
+
else if (/AssertionError|^\s*(expected|actual)\b.*[:=]|^\s*(not ok|FAILED)\b/.test(l))
|
|
9307
|
+
take(i, 3);
|
|
9308
|
+
else if (/^\s*--- FAIL/.test(l))
|
|
9309
|
+
take(i, 4);
|
|
9310
|
+
else if (/^[\w./@-]+\.\w+(\(\d+,\d+\)|:\d+(:\d+)?)[:\s].*\b(error|TS\d+|[A-Z]{1,3}\d{3,4})\b/.test(l))
|
|
9311
|
+
take(i);
|
|
9312
|
+
});
|
|
9313
|
+
const lastFrame = lines.map((l, i) => /^[\w./@-]+\.py:\d+: /.test(l) ? i : -1).filter((i) => i >= 0).pop();
|
|
9314
|
+
if (lastFrame !== undefined && [...pick].some((i) => /^E\s/.test(lines[i])))
|
|
9315
|
+
take(lastFrame);
|
|
9316
|
+
let body = [...pick].sort((a, b) => a - b).map((i) => lines[i]).join(`
|
|
9317
|
+
`);
|
|
9318
|
+
if (!body)
|
|
9319
|
+
body = lines.filter((l) => l.trim()).slice(-6).join(`
|
|
9320
|
+
`);
|
|
9321
|
+
body = redactSecrets(body);
|
|
9322
|
+
return truncateBytes(body, cap);
|
|
9323
|
+
}
|
|
9324
|
+
function pytestCollectionIsRed(output, repoDir) {
|
|
9325
|
+
if (/ModuleNotFoundError/.test(output))
|
|
9326
|
+
return false;
|
|
9327
|
+
const real2 = (p) => {
|
|
9328
|
+
try {
|
|
9329
|
+
return realpathSync16(isAbsolute3(p) ? p : join37(repoDir, p));
|
|
9330
|
+
} catch {
|
|
9331
|
+
return null;
|
|
9526
9332
|
}
|
|
9527
|
-
|
|
9333
|
+
};
|
|
9334
|
+
const repoReal = real2(repoDir);
|
|
9335
|
+
const under = (p) => {
|
|
9336
|
+
const r = real2(p);
|
|
9337
|
+
return !!repoReal && !!r && (r === repoReal || r.startsWith(`${repoReal}/`));
|
|
9338
|
+
};
|
|
9339
|
+
const imp = /ImportError: cannot import name .* from ['"][\w.]+['"] \(([^)]+)\)/.exec(output);
|
|
9340
|
+
if (imp)
|
|
9341
|
+
return under(imp[1]);
|
|
9342
|
+
const hdr = [...output.matchAll(/^=+ short test summary info =+$/gm)].pop();
|
|
9343
|
+
if (!hdr)
|
|
9344
|
+
return false;
|
|
9345
|
+
const cls = [...output.slice(hdr.index).matchAll(/^ERROR \S+ - (\w+Error): /gm)].pop()?.[1];
|
|
9346
|
+
if (cls !== "AttributeError" && cls !== "NameError")
|
|
9347
|
+
return false;
|
|
9348
|
+
const start = output.search(/^_+ ERROR collecting /m);
|
|
9349
|
+
if (start < 0 || start > hdr.index)
|
|
9350
|
+
return false;
|
|
9351
|
+
const block = output.slice(start, hdr.index).split(/^-+ Captured .*$/m)[0];
|
|
9352
|
+
const eLines = [...block.matchAll(new RegExp(`^E {3}${cls}: (.*)$`, "gm"))];
|
|
9353
|
+
const eLine = eLines[eLines.length - 1];
|
|
9354
|
+
if (!eLine)
|
|
9355
|
+
return false;
|
|
9356
|
+
if (cls === "AttributeError") {
|
|
9357
|
+
const m = /^module ['"]([\w.]+)['"] has no attribute/.exec(eLine[1]);
|
|
9358
|
+
return !!m && moduleUnderRepo(repoDir, m[1]);
|
|
9528
9359
|
}
|
|
9529
|
-
|
|
9360
|
+
const frames = [...block.slice(0, eLine.index).matchAll(/^(.+?):\d+: in \S+\n\s*(.*)$/gm)];
|
|
9361
|
+
const last = frames[frames.length - 1];
|
|
9362
|
+
return !!last && under(last[1]) && !/^\s*(import\s|from\s\S+\s+import\b)/.test(last[2] ?? "");
|
|
9530
9363
|
}
|
|
9531
|
-
function
|
|
9532
|
-
const
|
|
9533
|
-
|
|
9534
|
-
|
|
9535
|
-
|
|
9536
|
-
if (
|
|
9537
|
-
return
|
|
9538
|
-
|
|
9539
|
-
|
|
9540
|
-
|
|
9541
|
-
|
|
9542
|
-
|
|
9543
|
-
|
|
9364
|
+
function moduleUnderRepo(repoDir, name) {
|
|
9365
|
+
const rel = name.replace(/\./g, "/");
|
|
9366
|
+
return existsSync23(join37(repoDir, `${rel}.py`)) || existsSync23(join37(repoDir, rel, "__init__.py"));
|
|
9367
|
+
}
|
|
9368
|
+
function pytestExit1IsRed(output) {
|
|
9369
|
+
if (/^!+ _pytest\.outcomes\.Exit\b/m.test(output))
|
|
9370
|
+
return false;
|
|
9371
|
+
if (/^=*\s*(\d+ \w+(, )?)*\d+ failed\b.* in [\d.]+s/.test(output.trimEnd().split(`
|
|
9372
|
+
`).pop() ?? ""))
|
|
9373
|
+
return true;
|
|
9374
|
+
const hdr = [...output.matchAll(/^=+ short test summary info =+$/gm)].pop();
|
|
9375
|
+
return !!hdr && /^FAILED \S+/m.test(output.slice(hdr.index));
|
|
9376
|
+
}
|
|
9377
|
+
function parsedFailCount(runner, output) {
|
|
9378
|
+
const m = runner === "bun" ? /^\s*(\d+)\s+fail\s*$/m.exec(output) : runner === "jest" ? /Tests:\s*(\d+)\s+failed/i.exec(output) : runner === "vitest" ? /Tests\s+(\d+)\s+failed/i.exec(output) : null;
|
|
9379
|
+
return m ? Number(m[1]) : 0;
|
|
9380
|
+
}
|
|
9381
|
+
function nodeIsRed(f, raw2) {
|
|
9382
|
+
const o = raw2.replace(/^# (?!(?:tests|suites|pass|fail|cancelled|skipped|todo|duration_ms|Subtest)\b)/gm, "");
|
|
9383
|
+
const mod = /^Error(?: \[\w+\])?: Cannot find (?:module|package) '([^']+)'(?:(?!\u2716)[\s\S])*?\nNode\.js v/m.exec(o), top = /^(\S+):\d+\n.*\n.*\n\n?(?:ReferenceError|SyntaxError)\b/m.exec(o);
|
|
9384
|
+
const named = [...o.matchAll(/^(?:\u2716|\s*not ok \d+ -) (?!failing tests:)(.+?)(?: \(|$)/gm)].some((m) => !f.path.endsWith(m[1]) && !m[1].endsWith(f.path)), blk = o.split("failing tests:")[1] ?? "", esm = /^SyntaxError: The requested module '([^']+)' does not provide an export named/m.exec(o), errs = [...blk.matchAll(/^ {2}(\w+Error): .*\n\s+at (?:.*\()?([^\s()]+?):\d+:\d+/gm), ...o.matchAll(/^ +name: '(\w+Error)'\n(?:.*\n)*? +stack: \|-\n\s+(?:.*\()?([^\s()]+?):\d+:\d+/gm)];
|
|
9385
|
+
return /^(?:#|\u2139) fail [1-9]/m.test(raw2) && (/^ {2}AssertionError\b/m.test(blk) || /^ +name: 'AssertionError'/m.test(o) || (mod && !named ? /^[./]/.test(mod[1]) : esm ? /^[./]/.test(esm[1]) : top ? !top[1].endsWith(f.path) : !errs.length || errs.some((e) => !/^(?:Reference|Syntax)Error$/.test(e[1]) || !(e[2].startsWith("node:") || e[2].endsWith(f.path)))));
|
|
9386
|
+
}
|
|
9387
|
+
function notRunReason(status, interpreter) {
|
|
9388
|
+
if (interpreter === "system")
|
|
9389
|
+
return "ran under the system interpreter, not the project's, so the result proves nothing";
|
|
9390
|
+
if (status === null)
|
|
9391
|
+
return "the test runner did not start or timed out";
|
|
9392
|
+
if (status === 126 || status === 127)
|
|
9393
|
+
return `the test runner command was not found or not executable (exit ${status})`;
|
|
9394
|
+
return status === 0 ? "exit 0 but no executed test count could be confirmed" : `exit ${status} but the runner output showed no readable failing test`;
|
|
9395
|
+
}
|
|
9396
|
+
function classify(f, status, output, repoDir, interpreter) {
|
|
9397
|
+
if (interpreter === "system")
|
|
9398
|
+
return "not_run";
|
|
9399
|
+
output = stripAnsi(output);
|
|
9400
|
+
if (status === null || status === 126 || status === 127)
|
|
9401
|
+
return "not_run";
|
|
9402
|
+
if (status === 0)
|
|
9403
|
+
return classifyCheck({ kind: "test", ok: true, out: output, path: f.path, ...f.runner === "go" ? { runner: "go" } : {} }).result === "pass" ? "pass" : "not_run";
|
|
9404
|
+
if (f.runner === "pytest")
|
|
9405
|
+
return status === 1 ? pytestExit1IsRed(output) ? "fail" : "not_run" : status === 2 ? pytestCollectionIsRed(output, repoDir) ? "fail" : "not_run" : "not_run";
|
|
9406
|
+
if (f.runner === "jest" || f.runner === "vitest" || f.runner === "bun")
|
|
9407
|
+
return parsedFailCount(f.runner, output) > 0 ? "fail" : "not_run";
|
|
9408
|
+
return f.runner === "node" && nodeIsRed(f, output) ? "fail" : "not_run";
|
|
9409
|
+
}
|
|
9410
|
+
var NO_TESTS_REASON = "no tests executed", GO_EXIT0_REASON = "test count could not be confirmed: go test output is produced by the code under test and cannot confirm execution (a Go exit 0 is never a pass)", UNCONFIRMED_REASON = "test count could not be confirmed", FAIL_EVIDENCE, GO_FAIL_EVIDENCE, UNMEASURED_REASON = "executed count unmeasured (Loki could not parse the runner summary, harness-owned)", stripAnsi = (s) => s.replace(/\u001b\][^\u0007\u001b]*(?:\u0007|\u001b\\)/g, "").replace(/(?:\u001b\[|\u009b)[0-9;?]*[ -\/]*[@-~]/g, "").replace(/\r\n?/g, `
|
|
9411
|
+
`), tailLines = (out2) => out2.split(`
|
|
9412
|
+
`).filter((x) => x.trim()).slice(-12), GO_PKG_RE, isExecutedProof = (c) => c.result === "pass" && typeof c.n === "number" && c.n > 0, hasExecutedProof = (checks) => checks.some(isExecutedProof), LLM_JUDGES, NON_RUNNER, normPath = (p) => p.replace(/^(?:\.\/)+/, ""), hasExogenousProof = (checks, ctx) => checks.some((c) => isExecutedProof(c) && ((p) => p !== "agent_authored" && p !== "llm_judge")(checkProvenance(c.name ?? "", ctx))), SENSITIVE, API, TEST_CFG, RANK2, FILES_MEDIUM = 4, FILES_HIGH = 15, LINES_MEDIUM = 100, LINES_HIGH = 500, RAN_ALWAYS, PLAN, LOW_SKIPPED, deferredOf = (tier, selected, executed) => (tier === "low" ? LOW_SKIPPED : selected).filter((c) => !RAN_ALWAYS.includes(c) && !executed.includes(c)), MANIFEST_LOCKS, dirOf = (p) => p.includes("/") ? p.slice(0, p.lastIndexOf("/")) : "", PKG_DEP_KEYS, PYPROJECT_NONDEP, EXCERPT_GROUP_CAP = 1500, EXCERPT_TOTAL_CAP = 6144;
|
|
9413
|
+
var init_check_result = __esm(() => {
|
|
9414
|
+
init_testmap();
|
|
9415
|
+
init_safe_git();
|
|
9416
|
+
init_redact();
|
|
9417
|
+
FAIL_EVIDENCE = /\[(?:build|setup) failed\]|^--- FAIL|^[\w./-]+\.go:\d+:\d+: \S|\b[1-9]\d* (?:failed|errors?)\b/m;
|
|
9418
|
+
GO_FAIL_EVIDENCE = /^FAIL\t\S+\t[\d.]+s$|^panic: /m;
|
|
9419
|
+
GO_PKG_RE = /^(?:ok|FAIL|\?)\s+\S+\s+(?:\(cached\)|[\d.]+s\b|\[(?:no test files|build failed|setup failed)\])/;
|
|
9420
|
+
LLM_JUDGES = new Set(["council", "xreview", "code_review", "devils_advocate", "magic_debate"]);
|
|
9421
|
+
NON_RUNNER = new Set(["lint", "typecheck", "holdout", "select-tests"]);
|
|
9422
|
+
SENSITIVE = [
|
|
9423
|
+
["auth", /(^|\/)(auth|oauth|sso|session|login|permission|rbac|acl)[\w.-]*(\/|\.|$)/i],
|
|
9424
|
+
["crypto", /(^|\/)(crypt|crypto|jwt|signing|keys?|secrets?|tokens?|credential|password)[\w.-]*(\/|\.|$)/i],
|
|
9425
|
+
["payments", /(^|\/)(payments?|billing|checkout|stripe|invoice)[\w.-]*(\/|\.|$)/i],
|
|
9426
|
+
["migration", /(^|\/)(migrations?|alembic)\/|\.sql$/i],
|
|
9427
|
+
["ci", /(^|\/)(\.github\/(workflows|actions)|\.gitlab-ci\.yml|\.circleci|Jenkinsfile|azure-pipelines)/i],
|
|
9428
|
+
["lockfile", /(^|\/)(package-lock\.json|pnpm-lock\.yaml|bun\.lockb?|go\.sum|[\w-]+\.lock)$/],
|
|
9429
|
+
["infra", /(^|\/)(Dockerfile[\w.-]*|docker-compose[\w.-]*\.ya?ml|terraform|helm|k8s|kubernetes|infra|deploy)(\/|\.|$)|\.tf$/i],
|
|
9430
|
+
["env", /(^|\/)\.env[\w.]*$/]
|
|
9431
|
+
];
|
|
9432
|
+
API = /(^|\/)(openapi|swagger)[\w.-]*\.(ya?ml|json)$|\.proto$|\.d\.ts$|(^|\/)(api|routes|public)\/|(^|\/)index\.(ts|js|py)$/i;
|
|
9433
|
+
TEST_CFG = /(^|\/)(conftest\.py|\.?pytest\.(ini|toml)|tox\.ini|jest\.config\.[\w.]+|vitest\.config\.[\w.]+)$/;
|
|
9434
|
+
RANK2 = { low: 0, medium: 1, high: 2 };
|
|
9435
|
+
RAN_ALWAYS = ["targeted tests", "lint of changed files"];
|
|
9436
|
+
PLAN = {
|
|
9437
|
+
low: { selected: [...RAN_ALWAYS] },
|
|
9438
|
+
medium: { selected: [...RAN_ALWAYS, "full test command", "one reviewer"] },
|
|
9439
|
+
high: { selected: [...RAN_ALWAYS, "full test command", "full suite", "council", "security scan"] }
|
|
9544
9440
|
};
|
|
9545
|
-
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
9441
|
+
LOW_SKIPPED = ["full test command", "reviewer", "council", "security scan"];
|
|
9442
|
+
MANIFEST_LOCKS = [
|
|
9443
|
+
[/(^|\/)package\.json$/, /(^|\/)(package-lock\.json|npm-shrinkwrap\.json|pnpm-lock\.yaml|yarn\.lock|bun\.lockb?)$/],
|
|
9444
|
+
[/(^|\/)pyproject\.toml$/, /(^|\/)(poetry\.lock|uv\.lock|pdm\.lock|Pipfile\.lock)$/],
|
|
9445
|
+
[/(^|\/)go\.mod$/, /(^|\/)go\.sum$/]
|
|
9446
|
+
];
|
|
9447
|
+
PKG_DEP_KEYS = ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"];
|
|
9448
|
+
PYPROJECT_NONDEP = /^(name|version|description|readme|license|requires-python|python|authors|maintainers|keywords|classifiers|homepage|repository|documentation|packages|include|exclude)$/;
|
|
9449
|
+
});
|
|
9450
|
+
|
|
9451
|
+
// ../../loki-ts/src/util/receipt_signer.ts
|
|
9452
|
+
import { createHash as createHash8, randomBytes as randomBytes3, createPrivateKey, createPublicKey as createPublicKey2, generateKeyPairSync, sign, verify as verify2 } from "crypto";
|
|
9453
|
+
import { chmodSync as chmodSync4, linkSync, mkdirSync as mkdirSync13, readdirSync as readdirSync13, readFileSync as readFileSync29, renameSync as renameSync8, statSync as statSync14, unlinkSync as unlinkSync4, writeFileSync as writeFileSync16 } from "fs";
|
|
9454
|
+
import { homedir as homedir8 } from "os";
|
|
9455
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
9456
|
+
import { dirname as dirname12, join as join38 } from "path";
|
|
9457
|
+
function canonicalJson(x) {
|
|
9458
|
+
const walk = (v) => {
|
|
9459
|
+
if (Array.isArray(v))
|
|
9460
|
+
return `[${v.map(walk).join(",")}]`;
|
|
9461
|
+
if (v !== null && typeof v === "object") {
|
|
9462
|
+
const o = v;
|
|
9463
|
+
return `{${Object.keys(o).filter((k) => o[k] !== undefined).sort().map((k) => `${JSON.stringify(k)}:${walk(o[k])}`).join(",")}}`;
|
|
9550
9464
|
}
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
|
|
9555
|
-
|
|
9556
|
-
|
|
9557
|
-
|
|
9558
|
-
|
|
9465
|
+
return JSON.stringify(v ?? null);
|
|
9466
|
+
};
|
|
9467
|
+
return walk(x).replace(/[\u0080-\uFFFF]/g, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`);
|
|
9468
|
+
}
|
|
9469
|
+
function loadSigningKey(generate = true) {
|
|
9470
|
+
try {
|
|
9471
|
+
const inline = process.env["LOKI_RECEIPT_SIGNING_KEY"]?.trim();
|
|
9472
|
+
let pem = inline ?? "";
|
|
9473
|
+
if (!inline) {
|
|
9474
|
+
const given = process.env["LOKI_RECEIPT_SIGNING_KEY_FILE"]?.trim();
|
|
9475
|
+
const file = given || join38(process.env["HOME"] || homedir8(), ".loki", "keys", RECEIPT_SIGNER_BASENAME);
|
|
9476
|
+
try {
|
|
9477
|
+
pem = readFileSync29(file);
|
|
9478
|
+
if (!given) {
|
|
9479
|
+
for (const [f, m] of [[file, 384], [dirname12(file), 448]])
|
|
9480
|
+
if (statSync14(f).mode & 63)
|
|
9481
|
+
chmodSync4(f, m);
|
|
9482
|
+
}
|
|
9483
|
+
} catch (e) {
|
|
9484
|
+
if (e.code !== "ENOENT" || !generate)
|
|
9485
|
+
return null;
|
|
9486
|
+
mkdirSync13(dirname12(dirname12(file)), { recursive: true, mode: 448 });
|
|
9487
|
+
mkdirSync13(dirname12(file), { recursive: true, mode: 448 });
|
|
9488
|
+
const tmp = `${file}.${randomBytes3(6).toString("hex")}.tmp`;
|
|
9489
|
+
writeFileSync16(tmp, generateKeyPairSync("ed25519").privateKey.export({ type: "pkcs8", format: "pem" }), { flag: "wx", mode: 384 });
|
|
9490
|
+
try {
|
|
9491
|
+
linkSync(tmp, file);
|
|
9492
|
+
} catch (l) {
|
|
9493
|
+
if (l.code !== "EEXIST")
|
|
9494
|
+
throw l;
|
|
9495
|
+
} finally {
|
|
9496
|
+
unlinkSync4(tmp);
|
|
9497
|
+
}
|
|
9498
|
+
pem = readFileSync29(file);
|
|
9499
|
+
}
|
|
9559
9500
|
}
|
|
9560
|
-
|
|
9501
|
+
const k = createPrivateKey(pem);
|
|
9502
|
+
return k.asymmetricKeyType === "ed25519" ? k : null;
|
|
9503
|
+
} catch {
|
|
9504
|
+
return null;
|
|
9561
9505
|
}
|
|
9562
|
-
take(close);
|
|
9563
|
-
return `${h.slice(0, open).trim()} { ${names.join(", ")} }`;
|
|
9564
9506
|
}
|
|
9565
|
-
function
|
|
9566
|
-
const
|
|
9567
|
-
|
|
9568
|
-
|
|
9569
|
-
|
|
9570
|
-
|
|
9571
|
-
|
|
9572
|
-
|
|
9573
|
-
|
|
9574
|
-
|
|
9575
|
-
|
|
9576
|
-
|
|
9577
|
-
|
|
9578
|
-
|
|
9579
|
-
const dropped = ms.some((m) => !strictMember(m)) || sigs.some((m) => m !== null && (hasTopSemi(m) || NOT_MEMBER.test(m)));
|
|
9580
|
-
const keep = dropped ? [] : sigs.filter((m) => !!m);
|
|
9581
|
-
const headM = maskDecorators(exportHead(h, ""));
|
|
9582
|
-
const memM = keep.map(maskDecorators);
|
|
9583
|
-
if (headM !== null && !memM.includes(null))
|
|
9584
|
-
lines.push(`${maskExtends(headM)} {`, ...memM.map((m) => ` ${m};`), "}");
|
|
9585
|
-
} else if (/^export\s+(default\s+)?@/.test(h)) {
|
|
9586
|
-
const dm = maskDecorators(h);
|
|
9587
|
-
if (dm !== null)
|
|
9588
|
-
lines.push(maskExtends(dm));
|
|
9589
|
-
} else if (/^export\s+default\s/.test(h)) {
|
|
9590
|
-
const rest = h.replace(/^export\s+default\s+/, "");
|
|
9591
|
-
const len = arrowHeadLen(rest);
|
|
9592
|
-
if (len > 0)
|
|
9593
|
-
lines.push(`export default ${rest.slice(0, len)}`);
|
|
9594
|
-
else if (/^(async\s+)?function\b/.test(rest))
|
|
9595
|
-
lines.push(memberSig(h) ?? h);
|
|
9596
|
-
else
|
|
9597
|
-
lines.push(/^[\w$.]+$/.test(rest) ? h : "export default ...");
|
|
9598
|
-
} else if (/^export\s+(const|let|var)\b/.test(h)) {
|
|
9599
|
-
lines.push(splitDeclarators(h).map((p) => memberSig(p.trim()) ?? p.trim()).join(", "));
|
|
9600
|
-
} else {
|
|
9601
|
-
lines.push(memberSig(h) ?? h);
|
|
9602
|
-
}
|
|
9603
|
-
if (!lines.length)
|
|
9604
|
-
continue;
|
|
9605
|
-
const masked = /^export\s+(declare\s+)?(type|interface|enum)\b|^export\s*(type\s*)?[{*]|^export\s+(default\s+)?(abstract\s+)?class\b/.test(h) ? lines : lines.map((l) => {
|
|
9606
|
-
const d = maskDecorators(l);
|
|
9607
|
-
return d === null ? null : maskDefaults(d);
|
|
9608
|
-
});
|
|
9609
|
-
if (masked.includes(null))
|
|
9610
|
-
continue;
|
|
9611
|
-
const done = masked;
|
|
9612
|
-
if (!done.some(hasTopSemi))
|
|
9613
|
-
out2.push(...done);
|
|
9507
|
+
function signReceipt(runId, hash) {
|
|
9508
|
+
const key = loadSigningKey();
|
|
9509
|
+
if (!key)
|
|
9510
|
+
return { jwt: null, kid: null };
|
|
9511
|
+
const kid = kidOf2(createPublicKey2(key));
|
|
9512
|
+
const input = `${b64u(canonicalJson({ alg: "EdDSA", typ: "JWT", kid }))}.${b64u(canonicalJson({ job_id: runId, run_id: runId, receipt_sha256: hash, iat: Math.floor(Date.now() / 1000) }))}`;
|
|
9513
|
+
return { jwt: `${input}.${b64u(sign(null, Buffer.from(input), key))}`, kid };
|
|
9514
|
+
}
|
|
9515
|
+
function toolVersion(bin) {
|
|
9516
|
+
try {
|
|
9517
|
+
const r = spawnSync2(bin, ["--version"], { env: plainTestEnv(), encoding: "utf8", timeout: 5000, killSignal: "SIGKILL", stdio: ["ignore", "pipe", "ignore"] });
|
|
9518
|
+
return r.status === 0 ? /\d+(\.\d+)+\S*/.exec(String(r.stdout))?.[0] ?? null : null;
|
|
9519
|
+
} catch {
|
|
9520
|
+
return null;
|
|
9614
9521
|
}
|
|
9615
|
-
return out2;
|
|
9616
9522
|
}
|
|
9617
|
-
var
|
|
9618
|
-
var
|
|
9619
|
-
|
|
9620
|
-
|
|
9621
|
-
RESERVED_AFTER_DECORATOR = /^(?:if|else|for|while|do|switch|case|try|catch|finally|return|throw|with|var|let|const|function|new|delete|typeof|void|yield|await|break|continue|import|debugger|instanceof|this|super|null|true|false)(?![\w$])/;
|
|
9523
|
+
var RECEIPT_SIGNER_BASENAME = "receipt-ed25519.pem", b64u = (b) => Buffer.from(b).toString("base64url"), kidOf2 = (pub) => b64u(createHash8("sha256").update(`{"crv":"Ed25519","kty":"OKP","x":"${pub.export({ format: "jwk" }).x}"}`).digest()), TOOLCHAIN_KEYS, collectToolchain = (probe = toolVersion) => ({ bun: process.versions["bun"] ?? probe("bun"), node: probe("node"), python3: probe("python3"), git: probe("git") });
|
|
9524
|
+
var init_receipt_signer = __esm(() => {
|
|
9525
|
+
init_check_result();
|
|
9526
|
+
TOOLCHAIN_KEYS = ["bun", "node", "python3", "git"];
|
|
9622
9527
|
});
|
|
9623
9528
|
|
|
9624
|
-
// ../../loki-ts/src/
|
|
9625
|
-
var
|
|
9626
|
-
|
|
9627
|
-
|
|
9529
|
+
// ../../loki-ts/src/engine10/registry.ts
|
|
9530
|
+
var init_registry = () => {};
|
|
9531
|
+
|
|
9532
|
+
// ../../loki-ts/src/engine10/output.ts
|
|
9533
|
+
var init_output = __esm(() => {
|
|
9534
|
+
init_registry();
|
|
9535
|
+
init_redact();
|
|
9536
|
+
init_types();
|
|
9628
9537
|
});
|
|
9629
9538
|
|
|
9630
|
-
// ../../loki-ts/src/e10ext/
|
|
9631
|
-
var
|
|
9632
|
-
|
|
9633
|
-
init_failure_memory();
|
|
9539
|
+
// ../../loki-ts/src/e10ext/stop_restore.ts
|
|
9540
|
+
var init_stop_restore = __esm(() => {
|
|
9541
|
+
init_safe_git();
|
|
9634
9542
|
});
|
|
9635
9543
|
|
|
9636
|
-
// ../../loki-ts/src/
|
|
9637
|
-
|
|
9638
|
-
|
|
9639
|
-
|
|
9640
|
-
`).reverse().map((x) => x.trim()).find((x) => /^(?:=+ )?\d+ \w+.* in [\d.]+s|^Tests?:?\s+\d/.test(x)), m = /^(?:#|\u2139) fail (\d+)$/m.exec(out2);
|
|
9641
|
-
return l ? n2(l, /(\d+) failed/) + n2(l, /(\d+) errors?/) : m ? +m[1] : null;
|
|
9642
|
-
}
|
|
9643
|
-
function failIds(output) {
|
|
9644
|
-
const ids = [...new Set(output.split(`
|
|
9645
|
-
`).map((l) => ID_LINE.exec(l.trim())).flatMap((m) => m ? [(m.slice(1).find(Boolean) ?? "").trim()] : []).filter(Boolean))];
|
|
9646
|
-
const c = failCount(output);
|
|
9647
|
-
return c && ids.length >= c ? ids : [];
|
|
9648
|
-
}
|
|
9649
|
-
var ID_LINE;
|
|
9650
|
-
var init_failures = __esm(() => {
|
|
9651
|
-
ID_LINE = /^(?:(?:FAILED|ERROR)\s+(\S+::\S*)(?:\s.*)?|\u25cf\s+(?!Console|Test suite failed)(.+)|not ok \d+ - (.+?)(?:\s+#.*)?|\u2716\s+(?!failing tests:)(.+?)(?:\s+\([\d.]+ms\))?|(?:FAIL|\u00d7)\s+(.+))$/;
|
|
9544
|
+
// ../../loki-ts/src/util/base_guard.ts
|
|
9545
|
+
var init_base_guard = __esm(() => {
|
|
9546
|
+
init_run_status();
|
|
9547
|
+
init_safe_git();
|
|
9652
9548
|
});
|
|
9653
9549
|
|
|
9654
|
-
// ../../loki-ts/src/
|
|
9655
|
-
import {
|
|
9656
|
-
function
|
|
9657
|
-
const
|
|
9658
|
-
|
|
9659
|
-
|
|
9660
|
-
|
|
9661
|
-
|
|
9662
|
-
|
|
9663
|
-
|
|
9664
|
-
for (const p of packages) {
|
|
9665
|
-
const hit = p.root === "." || f === p.root || f.startsWith(`${p.root}/`);
|
|
9666
|
-
if (hit && (best === null || p.root !== "." && (best.root === "." || p.root.length > best.root.length)))
|
|
9667
|
-
best = p;
|
|
9668
|
-
}
|
|
9669
|
-
return best;
|
|
9670
|
-
};
|
|
9671
|
-
return {
|
|
9672
|
-
model,
|
|
9673
|
-
known: () => known,
|
|
9674
|
-
packages: () => packages,
|
|
9675
|
-
workspaceKind: () => isRec2(model) && typeof model.workspaceKind === "string" ? model.workspaceKind : "unknown",
|
|
9676
|
-
packageRootOf: (file) => packageOf(file)?.root ?? null,
|
|
9677
|
-
packageOf,
|
|
9678
|
-
relativeToRoot: (file) => {
|
|
9679
|
-
const p = packageOf(file);
|
|
9680
|
-
return p ? p.root === "." ? clean(file) : clean(file).slice(p.root.length + 1) : null;
|
|
9681
|
-
},
|
|
9682
|
-
commandFor: (pkg, kind) => (packages.find((p) => p.root === clean(pkg) || p.name === pkg) ?? null)?.commands?.[kind] ?? null,
|
|
9683
|
-
dependsOn: (pkg) => {
|
|
9684
|
-
const d = (packages.find((p) => p.root === clean(pkg) || p.name === pkg) ?? null)?.dependsOn;
|
|
9685
|
-
return Array.isArray(d) ? d.filter((x) => typeof x === "string") : null;
|
|
9686
|
-
},
|
|
9687
|
-
installFor: (pkg) => {
|
|
9688
|
-
const i = (packages.find((p) => p.root === clean(pkg) || p.name === pkg) ?? null)?.install;
|
|
9689
|
-
return isRec2(i) && typeof i.cmd === "string" ? i : null;
|
|
9690
|
-
},
|
|
9691
|
-
hasUI: () => packages.some((p) => isRec2(p.ui) && p.ui.present === true),
|
|
9692
|
-
uiBoot: () => {
|
|
9693
|
-
for (const p of packages)
|
|
9694
|
-
if (isRec2(p.ui) && p.ui.present === true && isRec2(p.ui.boot))
|
|
9695
|
-
return { pkg: p, boot: p.ui.boot };
|
|
9550
|
+
// ../../loki-ts/src/features/speed/unit_mode.ts
|
|
9551
|
+
import { closeSync as closeSync7, constants, fstatSync as fstatSync5, lstatSync as lstatSync8, openSync as openSync7, readSync as readSync6, realpathSync as realpathSync17 } from "fs";
|
|
9552
|
+
function readBounded(path) {
|
|
9553
|
+
const l = lstatSync8(path);
|
|
9554
|
+
if (l.isSymbolicLink() || !l.isFile() || l.size > MAX_SPEC_BYTES)
|
|
9555
|
+
return null;
|
|
9556
|
+
const fd = openSync7(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
9557
|
+
try {
|
|
9558
|
+
const st = fstatSync5(fd);
|
|
9559
|
+
if (!st.isFile() || st.size > MAX_SPEC_BYTES)
|
|
9696
9560
|
return null;
|
|
9561
|
+
const buf = Buffer.alloc(st.size + 1);
|
|
9562
|
+
let n2 = 0;
|
|
9563
|
+
for (;; ) {
|
|
9564
|
+
const r = readSync6(fd, buf, n2, buf.length - n2, null);
|
|
9565
|
+
if (r <= 0)
|
|
9566
|
+
break;
|
|
9567
|
+
n2 += r;
|
|
9568
|
+
if (n2 >= buf.length)
|
|
9569
|
+
return null;
|
|
9697
9570
|
}
|
|
9698
|
-
|
|
9571
|
+
return buf.subarray(0, n2).toString("utf8");
|
|
9572
|
+
} finally {
|
|
9573
|
+
closeSync7(fd);
|
|
9574
|
+
}
|
|
9699
9575
|
}
|
|
9700
|
-
|
|
9701
|
-
var init_api = () => {};
|
|
9702
|
-
|
|
9703
|
-
// ../../loki-ts/src/project_model/resolve.ts
|
|
9704
|
-
import { join as join36 } from "path";
|
|
9705
|
-
function loadProjectApi(repoDir, env = process.env) {
|
|
9706
|
-
if (!projectModelEnabled(env))
|
|
9707
|
-
return null;
|
|
9576
|
+
function parseText(txt) {
|
|
9708
9577
|
try {
|
|
9709
|
-
const
|
|
9710
|
-
|
|
9711
|
-
|
|
9578
|
+
const j = JSON.parse(txt), ws = strs(j.writeSet), pack = strs(j.pack), tb = j.tokenBudget;
|
|
9579
|
+
if (typeof j.id !== "string" || !j.id || !ws || ws.length === 0 || !pack || typeof tb !== "number" || !Number.isFinite(tb) || !(tb > 0) || tb > MAX_TOKEN_BUDGET)
|
|
9580
|
+
return null;
|
|
9581
|
+
const acc = j.acceptance === undefined ? [] : strs(j.acceptance);
|
|
9582
|
+
if (acc === null)
|
|
9583
|
+
return null;
|
|
9584
|
+
return { id: j.id, writeSet: ws, pack, tokenBudget: tb, ...acc.length ? { acceptance: acc.map((a) => a.slice(0, 500)).slice(0, 50) } : {} };
|
|
9712
9585
|
} catch {
|
|
9713
9586
|
return null;
|
|
9714
9587
|
}
|
|
9715
9588
|
}
|
|
9716
|
-
function
|
|
9717
|
-
|
|
9718
|
-
|
|
9719
|
-
|
|
9720
|
-
|
|
9721
|
-
return null;
|
|
9722
|
-
const pkg = api.packageOf(file);
|
|
9723
|
-
const rel = api.relativeToRoot(file);
|
|
9724
|
-
if (!pkg || pkg.root === "." || rel === null)
|
|
9589
|
+
function parseSpec(path) {
|
|
9590
|
+
try {
|
|
9591
|
+
const txt = readBounded(path);
|
|
9592
|
+
return txt === null ? null : parseText(txt);
|
|
9593
|
+
} catch {
|
|
9725
9594
|
return null;
|
|
9726
|
-
return { pkg, root: pkg.root, cwd: join36(repoDir, pkg.root), file: rel };
|
|
9727
|
-
}
|
|
9728
|
-
function groupByPackage(api, repoDir, files) {
|
|
9729
|
-
const out2 = new Map;
|
|
9730
|
-
for (const f of files) {
|
|
9731
|
-
const s = siteFor(api, repoDir, f);
|
|
9732
|
-
const root = s?.root ?? ".";
|
|
9733
|
-
const g = out2.get(root) ?? { root, cwd: s?.cwd ?? repoDir, files: [], rel: [] };
|
|
9734
|
-
g.files.push(f);
|
|
9735
|
-
g.rel.push(s?.file ?? f);
|
|
9736
|
-
out2.set(root, g);
|
|
9737
9595
|
}
|
|
9738
|
-
return [...out2.values()];
|
|
9739
9596
|
}
|
|
9740
|
-
|
|
9741
|
-
|
|
9742
|
-
|
|
9743
|
-
|
|
9744
|
-
|
|
9745
|
-
|
|
9746
|
-
|
|
9597
|
+
function unitSpec(env = process.env) {
|
|
9598
|
+
const path = env["LOKI_UNIT_SPEC"], frozen = env["LOKI_UNIT_SPEC_FROZEN"];
|
|
9599
|
+
if (env["LOKI_SPEED"] === "0" || !path)
|
|
9600
|
+
return null;
|
|
9601
|
+
if (frozen !== undefined)
|
|
9602
|
+
return frozen.length <= MAX_SPEC_BYTES ? parseText(frozen) : null;
|
|
9603
|
+
if (!memo.has(path))
|
|
9604
|
+
memo.set(path, parseSpec(path));
|
|
9605
|
+
return memo.get(path) ?? null;
|
|
9747
9606
|
}
|
|
9748
|
-
|
|
9749
|
-
|
|
9750
|
-
|
|
9751
|
-
apis = new WeakMap;
|
|
9752
|
-
imports = new WeakMap;
|
|
9753
|
-
dropped = new WeakMap;
|
|
9754
|
-
});
|
|
9755
|
-
|
|
9756
|
-
// ../../loki-ts/src/util/test_file_text.ts
|
|
9757
|
-
import { basename as basename9 } from "path";
|
|
9758
|
-
function isTestFile(rel) {
|
|
9759
|
-
const name = basename9(rel);
|
|
9760
|
-
return JS_TEST_RE.test(name) || PY_TEST_RE.test(name) || GO_TEST_RE.test(name);
|
|
9607
|
+
function unitFlags(staged, env = process.env, pre = {}) {
|
|
9608
|
+
const s = unitSpec(env);
|
|
9609
|
+
return s ? staged.filter(({ f }) => !inWriteSet(s, f) && !Object.hasOwn(pre, f)).map(({ f }) => f) : null;
|
|
9761
9610
|
}
|
|
9762
|
-
var
|
|
9763
|
-
var
|
|
9764
|
-
|
|
9765
|
-
|
|
9766
|
-
|
|
9611
|
+
var MAX_SPEC_BYTES, MAX_TOKEN_BUDGET = 1e9, norm2 = (p) => p.replace(/^\.\//, ""), CTRL, strs = (v) => Array.isArray(v) && v.every((x) => typeof x === "string" && !CTRL.test(x)) ? v.map(norm2) : null, memo, inWriteSet = (spec, f) => spec.writeSet.some((w) => w.endsWith("/") ? f.startsWith(w) : f === w);
|
|
9612
|
+
var init_unit_mode = __esm(() => {
|
|
9613
|
+
MAX_SPEC_BYTES = 1024 * 1024;
|
|
9614
|
+
CTRL = /[\x00-\x1f\x7f]/;
|
|
9615
|
+
memo = new Map;
|
|
9767
9616
|
});
|
|
9768
9617
|
|
|
9769
|
-
// ../../loki-ts/src/
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
|
|
9773
|
-
|
|
9774
|
-
|
|
9775
|
-
|
|
9776
|
-
return
|
|
9777
|
-
|
|
9778
|
-
|
|
9779
|
-
|
|
9780
|
-
|
|
9781
|
-
|
|
9618
|
+
// ../../loki-ts/src/util/ts_signatures.ts
|
|
9619
|
+
function templateEnd(s, i) {
|
|
9620
|
+
for (let j = i + 1;j < s.length; ) {
|
|
9621
|
+
const c = s[j];
|
|
9622
|
+
if (c === "\\")
|
|
9623
|
+
j += 2;
|
|
9624
|
+
else if (c === "`")
|
|
9625
|
+
return j + 1;
|
|
9626
|
+
else if (c === "$" && s[j + 1] === "{") {
|
|
9627
|
+
let depth = 1;
|
|
9628
|
+
j += 2;
|
|
9629
|
+
while (j < s.length && depth > 0) {
|
|
9630
|
+
const k = skipLiteral(s, j);
|
|
9631
|
+
if (k !== j) {
|
|
9632
|
+
j = k;
|
|
9633
|
+
continue;
|
|
9634
|
+
}
|
|
9635
|
+
if (s[j] === "{")
|
|
9636
|
+
depth++;
|
|
9637
|
+
else if (s[j] === "}")
|
|
9638
|
+
depth--;
|
|
9639
|
+
j++;
|
|
9640
|
+
}
|
|
9641
|
+
} else
|
|
9642
|
+
j++;
|
|
9643
|
+
}
|
|
9644
|
+
return s.length;
|
|
9782
9645
|
}
|
|
9783
|
-
|
|
9784
|
-
|
|
9785
|
-
|
|
9786
|
-
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
|
|
9793
|
-
"target",
|
|
9794
|
-
"coverage",
|
|
9795
|
-
".venv",
|
|
9796
|
-
"venv",
|
|
9797
|
-
"__pycache__",
|
|
9798
|
-
".tox",
|
|
9799
|
-
".pytest_cache",
|
|
9800
|
-
".loki",
|
|
9801
|
-
".next"
|
|
9802
|
-
]);
|
|
9803
|
-
});
|
|
9804
|
-
|
|
9805
|
-
// ../../loki-ts/src/util/check_result.ts
|
|
9806
|
-
import { existsSync as existsSync23, mkdirSync as mkdirSync13, readFileSync as readFileSync29, realpathSync as realpathSync17, renameSync as renameSync8, writeFileSync as writeFileSync16 } from "fs";
|
|
9807
|
-
import { basename as basename11, isAbsolute as isAbsolute3, join as join38 } from "path";
|
|
9808
|
-
function plainTestEnv(base = process.env) {
|
|
9809
|
-
const e = {};
|
|
9810
|
-
for (const [k, v] of Object.entries(tokenFreeEnv(base)))
|
|
9811
|
-
if (typeof v === "string")
|
|
9812
|
-
e[k] = v;
|
|
9813
|
-
e["FORCE_COLOR"] = "0";
|
|
9814
|
-
e["NO_COLOR"] = "1";
|
|
9815
|
-
delete e["CLICOLOR_FORCE"];
|
|
9816
|
-
return e;
|
|
9646
|
+
function commentBefore(s, i) {
|
|
9647
|
+
let p = i - 1;
|
|
9648
|
+
while (p >= 0 && /\s/.test(s[p]))
|
|
9649
|
+
p--;
|
|
9650
|
+
if (p < 1)
|
|
9651
|
+
return false;
|
|
9652
|
+
if (s[p] === "/" && s[p - 1] === "*")
|
|
9653
|
+
return true;
|
|
9654
|
+
return s.slice(s.lastIndexOf(`
|
|
9655
|
+
`, p) + 1, p + 1).includes("//");
|
|
9817
9656
|
}
|
|
9818
|
-
function
|
|
9819
|
-
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
|
|
9824
|
-
|
|
9825
|
-
return
|
|
9657
|
+
function regexEnd(s, i) {
|
|
9658
|
+
if (commentBefore(s, i))
|
|
9659
|
+
return i;
|
|
9660
|
+
let p = i - 1;
|
|
9661
|
+
while (p >= 0 && /\s/.test(s[p]))
|
|
9662
|
+
p--;
|
|
9663
|
+
if (p >= 1 && (s[p] === "+" || s[p] === "-") && s[p - 1] === s[p])
|
|
9664
|
+
return i;
|
|
9665
|
+
if (p >= 0 && !REGEX_PREV.includes(s[p]) && !/\b(return|typeof|case|in|of|void|delete|throw)$/.test(s.slice(Math.max(0, p - 7), p + 1)))
|
|
9666
|
+
return i;
|
|
9667
|
+
let inClass = false;
|
|
9668
|
+
for (let j = i + 1;j < s.length; j++) {
|
|
9669
|
+
const c = s[j];
|
|
9670
|
+
if (c === `
|
|
9671
|
+
`)
|
|
9672
|
+
return i;
|
|
9673
|
+
if (c === "\\")
|
|
9674
|
+
j++;
|
|
9675
|
+
else if (c === "[")
|
|
9676
|
+
inClass = true;
|
|
9677
|
+
else if (c === "]")
|
|
9678
|
+
inClass = false;
|
|
9679
|
+
else if (c === "/" && !inClass) {
|
|
9680
|
+
j++;
|
|
9681
|
+
while (j < s.length && /[a-z]/i.test(s[j]))
|
|
9682
|
+
j++;
|
|
9683
|
+
return j;
|
|
9684
|
+
}
|
|
9826
9685
|
}
|
|
9827
|
-
|
|
9828
|
-
if (cg.length)
|
|
9829
|
-
return cg.reduce((t, l2) => t + n2(l2, /(\d+) passed/) + n2(l2, /(\d+) failed/), 0);
|
|
9830
|
-
const g = goCount(out2, ok);
|
|
9831
|
-
if (g !== undefined)
|
|
9832
|
-
return g;
|
|
9833
|
-
const tail = tailLines(out2);
|
|
9834
|
-
const l = tail.filter((x) => /^(?:=+ )?(?:\d+ \w+.*|no tests ran) in [\d.]+s|^\s*Tests?:?\s+\d|^No tests found/.test(x) && (!/^\s*Tests?:?\s+\d/.test(x) || tail.some((y) => /^\s*Test (?:Files|Suites):?\s+\d/.test(y)))).pop();
|
|
9835
|
-
if (!l)
|
|
9836
|
-
return null;
|
|
9837
|
-
return /^(?:=+ )?no tests (?:ran|found)|^No tests found|skipped/i.test(l) || /\d+ (?:passed|failed|errors?)/.test(l) ? n2(l, /(\d+) passed/) + n2(l, /(\d+) failed/) + n2(l, /(\d+) errors?/) : null;
|
|
9686
|
+
return i;
|
|
9838
9687
|
}
|
|
9839
|
-
function
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
|
|
9843
|
-
|
|
9844
|
-
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
|
|
9848
|
-
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
|
|
9852
|
-
|
|
9853
|
-
|
|
9854
|
-
|
|
9855
|
-
|
|
9856
|
-
|
|
9688
|
+
function stripComments(t) {
|
|
9689
|
+
let out2 = "";
|
|
9690
|
+
for (let i = 0;i < t.length; ) {
|
|
9691
|
+
if (isComment(t, i)) {
|
|
9692
|
+
const e = t[i + 1] === "/" ? t.indexOf(`
|
|
9693
|
+
`, i) < 0 ? t.length : t.indexOf(`
|
|
9694
|
+
`, i) : t.indexOf("*/", i + 2) < 0 ? t.length : t.indexOf("*/", i + 2) + 2;
|
|
9695
|
+
out2 += t[i + 1] === "/" ? "" : " ";
|
|
9696
|
+
i = e;
|
|
9697
|
+
continue;
|
|
9698
|
+
}
|
|
9699
|
+
const c = t[i];
|
|
9700
|
+
const k = c === '"' || c === "'" || c === "`" ? skipLiteral(t, i) : i;
|
|
9701
|
+
if (k !== i) {
|
|
9702
|
+
out2 += t.slice(i, k);
|
|
9703
|
+
i = k;
|
|
9704
|
+
continue;
|
|
9705
|
+
}
|
|
9706
|
+
out2 += c;
|
|
9707
|
+
i++;
|
|
9857
9708
|
}
|
|
9858
|
-
|
|
9859
|
-
return [];
|
|
9860
|
-
return segs.flatMap((g) => lastOf(g) ?? []);
|
|
9861
|
-
}
|
|
9862
|
-
function bunCount(out2) {
|
|
9863
|
-
const ls = out2.split(`
|
|
9864
|
-
`).filter((x) => x.trim());
|
|
9865
|
-
if (!/^Ran \d+ tests? across \d+ files?\./.test(ls[ls.length - 1] ?? ""))
|
|
9866
|
-
return null;
|
|
9867
|
-
const blk = ls.slice(-9, -1);
|
|
9868
|
-
const last = (k) => +(blk.map((x) => x.match(new RegExp(`^\\s*(\\d+) ${k}\\s*$`))?.[1]).filter(Boolean).pop() ?? 0);
|
|
9869
|
-
return last("pass") + last("fail");
|
|
9709
|
+
return out2;
|
|
9870
9710
|
}
|
|
9871
|
-
function
|
|
9872
|
-
const
|
|
9873
|
-
|
|
9874
|
-
|
|
9875
|
-
|
|
9876
|
-
|
|
9877
|
-
|
|
9878
|
-
if (
|
|
9879
|
-
|
|
9880
|
-
|
|
9711
|
+
function skipLiteral(s, i) {
|
|
9712
|
+
const c = s[i];
|
|
9713
|
+
if (c === "/" && s[i + 1] === "/") {
|
|
9714
|
+
const n2 = s.indexOf(`
|
|
9715
|
+
`, i);
|
|
9716
|
+
return n2 < 0 ? s.length : n2;
|
|
9717
|
+
}
|
|
9718
|
+
if (c === "/" && s[i + 1] === "*") {
|
|
9719
|
+
const n2 = s.indexOf("*/", i + 2);
|
|
9720
|
+
return n2 < 0 ? s.length : n2 + 2;
|
|
9721
|
+
}
|
|
9722
|
+
if (c === "/")
|
|
9723
|
+
return regexEnd(s, i);
|
|
9724
|
+
if (c === "`")
|
|
9725
|
+
return templateEnd(s, i);
|
|
9726
|
+
if (c !== '"' && c !== "'")
|
|
9727
|
+
return i;
|
|
9728
|
+
for (let j = i + 1;j < s.length; j++) {
|
|
9729
|
+
if (s[j] === "\\")
|
|
9730
|
+
j++;
|
|
9731
|
+
else if (s[j] === c)
|
|
9732
|
+
return j + 1;
|
|
9733
|
+
else if (s[j] === `
|
|
9734
|
+
`)
|
|
9735
|
+
return i;
|
|
9736
|
+
}
|
|
9737
|
+
return s.length;
|
|
9881
9738
|
}
|
|
9882
|
-
function
|
|
9883
|
-
|
|
9884
|
-
|
|
9885
|
-
|
|
9886
|
-
|
|
9887
|
-
|
|
9888
|
-
|
|
9889
|
-
const r = x.match(/^=== RUN\s+(\S+)/), m = x.match(/^--- (PASS|FAIL|SKIP): (\S+)/);
|
|
9890
|
-
if (r)
|
|
9891
|
-
seen.add(r[1]);
|
|
9892
|
-
else if (m && (seen.has(m[2]) || m[1] === "FAIL" && failPkg)) {
|
|
9893
|
-
last.set(m[2], m[1]);
|
|
9894
|
-
if (m[1] === "SKIP")
|
|
9895
|
-
skip.add(m[2]);
|
|
9739
|
+
function matchingBrace(s, open) {
|
|
9740
|
+
let depth = 0;
|
|
9741
|
+
for (let i = open;i < s.length; ) {
|
|
9742
|
+
const j = skipLiteral(s, i);
|
|
9743
|
+
if (j !== i) {
|
|
9744
|
+
i = j;
|
|
9745
|
+
continue;
|
|
9896
9746
|
}
|
|
9747
|
+
if (s[i] === "{")
|
|
9748
|
+
depth++;
|
|
9749
|
+
else if (s[i] === "}" && --depth === 0)
|
|
9750
|
+
return i;
|
|
9751
|
+
i++;
|
|
9897
9752
|
}
|
|
9898
|
-
|
|
9899
|
-
last.set(k, "SKIP");
|
|
9900
|
-
if (ok === true && [...last.values()].includes("FAIL"))
|
|
9901
|
-
return null;
|
|
9902
|
-
const t = [...last.values()].filter((v) => v !== "SKIP").length;
|
|
9903
|
-
if (t > 0)
|
|
9904
|
-
return t;
|
|
9905
|
-
if (lines.some((x) => /^(?:=== RUN|PASS$|FAIL$|testing: warning: no tests to run)/.test(x)))
|
|
9906
|
-
return 0;
|
|
9907
|
-
return lines.filter((x) => GO_PKG_RE.test(x)).every((x) => /\[no tests? (?:files|to run)\]/.test(x)) ? 0 : null;
|
|
9753
|
+
return s.length;
|
|
9908
9754
|
}
|
|
9909
|
-
function
|
|
9910
|
-
const
|
|
9911
|
-
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
|
|
9915
|
-
|
|
9916
|
-
|
|
9917
|
-
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
|
|
9755
|
+
function items(src) {
|
|
9756
|
+
const out2 = [];
|
|
9757
|
+
let start = 0, head = "", p = 0, i = 0;
|
|
9758
|
+
const push = (end, body, stop, balanced = true) => {
|
|
9759
|
+
if (head.trim())
|
|
9760
|
+
out2.push({ head, raw: src.slice(start, stop).trim(), end, body, balanced });
|
|
9761
|
+
head = "";
|
|
9762
|
+
p = 0;
|
|
9763
|
+
start = stop;
|
|
9764
|
+
};
|
|
9765
|
+
while (i < src.length) {
|
|
9766
|
+
const j = skipLiteral(src, i);
|
|
9767
|
+
if (j !== i) {
|
|
9768
|
+
if (!isComment(src, i))
|
|
9769
|
+
head += src.slice(i, j);
|
|
9770
|
+
i = j;
|
|
9771
|
+
continue;
|
|
9772
|
+
}
|
|
9773
|
+
const c = src[i];
|
|
9774
|
+
if (c === "(" || c === "[")
|
|
9775
|
+
p++;
|
|
9776
|
+
else if (c === ")" || c === "]")
|
|
9777
|
+
p--;
|
|
9778
|
+
if (c === "{" && p === 0) {
|
|
9779
|
+
const close = matchingBrace(src, i);
|
|
9780
|
+
const h = head.trim();
|
|
9781
|
+
const declaration = /^(export\s+)?(declare\s+)?(type|interface|enum)\b/.test(h);
|
|
9782
|
+
if (declaration || h === "" || /^export(\s+type)?$/.test(h) || /[:|&]$/.test(h)) {
|
|
9783
|
+
head += stripComments(src.slice(i, close + 1));
|
|
9784
|
+
i = close + 1;
|
|
9785
|
+
if (declaration && !/^(export\s+)?(declare\s+)?type\b/.test(h))
|
|
9786
|
+
push("", null, i);
|
|
9921
9787
|
continue;
|
|
9922
9788
|
}
|
|
9923
|
-
|
|
9789
|
+
const body = src.slice(i + 1, close);
|
|
9790
|
+
const balanced = close < src.length;
|
|
9791
|
+
i = close + 1;
|
|
9792
|
+
if (src[i] === ";")
|
|
9793
|
+
i++;
|
|
9794
|
+
push("{", body, i, balanced);
|
|
9795
|
+
continue;
|
|
9924
9796
|
}
|
|
9925
|
-
if (
|
|
9926
|
-
|
|
9927
|
-
|
|
9928
|
-
return {};
|
|
9929
|
-
}
|
|
9930
|
-
function goJson(out2) {
|
|
9931
|
-
let any = false, failed2 = false;
|
|
9932
|
-
for (const x of out2.split(`
|
|
9933
|
-
`)) {
|
|
9934
|
-
if (!x.trim() || /^go: /.test(x))
|
|
9797
|
+
if (c === ";" && p === 0) {
|
|
9798
|
+
i++;
|
|
9799
|
+
push(";", null, i);
|
|
9935
9800
|
continue;
|
|
9936
|
-
let e;
|
|
9937
|
-
try {
|
|
9938
|
-
e = JSON.parse(x);
|
|
9939
|
-
} catch {
|
|
9940
|
-
return null;
|
|
9941
9801
|
}
|
|
9942
|
-
if (
|
|
9943
|
-
|
|
9944
|
-
|
|
9945
|
-
|
|
9946
|
-
|
|
9802
|
+
if (c === `
|
|
9803
|
+
` && p === 0 && head.trim() && /^\s*(export|import)\b/.test(src.slice(i + 1, i + 40))) {
|
|
9804
|
+
push("", null, i);
|
|
9805
|
+
i++;
|
|
9806
|
+
start = i;
|
|
9807
|
+
continue;
|
|
9808
|
+
}
|
|
9809
|
+
head += c;
|
|
9810
|
+
i++;
|
|
9947
9811
|
}
|
|
9948
|
-
|
|
9949
|
-
|
|
9950
|
-
function summaryPassFailCount(out2) {
|
|
9951
|
-
return ["pass", "fail"].reduce((t, k) => t + +([...out2.matchAll(new RegExp(`^(?:#|\\u2139) ${k} (\\d+)$`, "gm"))].pop()?.[1] ?? 0), 0);
|
|
9952
|
-
}
|
|
9953
|
-
function skipped(raw2) {
|
|
9954
|
-
return stripAnsi(raw2).split(`
|
|
9955
|
-
`).filter((l) => /^(?:=+ )?\d+ \w+.* in [\d.]+s|^\s*Tests?:?\s+\d|^(?:#|\u2139) skipped \d/.test(l.trim())).reduce((t, l) => t + [...l.matchAll(/(\d+) (?:skipped|deselected|xfailed)|skipped (\d+)/g)].reduce((u, m) => u + +(m[1] ?? m[2]), 0), 0);
|
|
9812
|
+
push("", null, src.length);
|
|
9813
|
+
return out2;
|
|
9956
9814
|
}
|
|
9957
|
-
function
|
|
9958
|
-
const
|
|
9959
|
-
|
|
9960
|
-
|
|
9961
|
-
|
|
9962
|
-
|
|
9963
|
-
return ut;
|
|
9964
|
-
if (/^\s*(?:Test Files\s+0\b|No test files found)/m.test(out2) && !/^\s*Tests?\s+\d/m.test(out2))
|
|
9965
|
-
return 0;
|
|
9966
|
-
const r = ran(out2, path, ok);
|
|
9967
|
-
if (r !== null)
|
|
9968
|
-
return r;
|
|
9969
|
-
const tl = tailLines(out2);
|
|
9970
|
-
const pw = tl.filter((x) => /^\s*\d+ (?:passed|failed|flaky)\b/.test(x));
|
|
9971
|
-
if (pw.length && tl.some((x) => /^\s*\d+ passed \([\d.]+m?s\)/.test(x) || /^\s*\d+ failed$/.test(x)))
|
|
9972
|
-
return pw.reduce((t, x) => t + +x.trim().split(" ")[0], 0);
|
|
9973
|
-
const lastNum = (re) => {
|
|
9974
|
-
const m = [...out2.matchAll(re)].pop();
|
|
9975
|
-
return m ? +m[1] : null;
|
|
9815
|
+
function arrowHeadLen(s) {
|
|
9816
|
+
const n2 = s.length;
|
|
9817
|
+
let i = 0;
|
|
9818
|
+
const ws = () => {
|
|
9819
|
+
while (i < n2 && /\s/.test(s[i]))
|
|
9820
|
+
i++;
|
|
9976
9821
|
};
|
|
9977
|
-
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
return null;
|
|
9981
|
-
}
|
|
9982
|
-
function classifyCheck(i) {
|
|
9983
|
-
if (i.missing)
|
|
9984
|
-
return { result: "not_run", reason: "tool not found on PATH" };
|
|
9985
|
-
if (i.cut)
|
|
9986
|
-
return { result: "not_run", reason: "timed out or aborted" };
|
|
9987
|
-
if (i.kind === "static")
|
|
9988
|
-
return { result: i.ok ? "pass" : "fail" };
|
|
9989
|
-
const text2 = stripAnsi(i.out);
|
|
9990
|
-
if (i.runner === "go") {
|
|
9991
|
-
if (i.ok)
|
|
9992
|
-
return { result: "not_run", reason: GO_EXIT0_REASON };
|
|
9993
|
-
const j = goJson(text2);
|
|
9994
|
-
if (j)
|
|
9995
|
-
return j.failed ? { result: "fail" } : { result: "not_run", reason: UNCONFIRMED_REASON };
|
|
9996
|
-
return FAIL_EVIDENCE.test(text2) || GO_FAIL_EVIDENCE.test(text2) ? { result: "fail" } : { result: "not_run", reason: UNCONFIRMED_REASON };
|
|
9822
|
+
if (/^async\s/.test(s)) {
|
|
9823
|
+
i = 5;
|
|
9824
|
+
ws();
|
|
9997
9825
|
}
|
|
9998
|
-
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10002
|
-
|
|
10003
|
-
|
|
10004
|
-
|
|
10005
|
-
|
|
10006
|
-
|
|
10007
|
-
|
|
9826
|
+
if (s[i] === "<") {
|
|
9827
|
+
let d2 = 0;
|
|
9828
|
+
for (;i < n2; i++) {
|
|
9829
|
+
if (s[i] === "=" && s[i + 1] === ">")
|
|
9830
|
+
i++;
|
|
9831
|
+
else if (s[i] === "<")
|
|
9832
|
+
d2++;
|
|
9833
|
+
else if (s[i] === ">" && --d2 === 0) {
|
|
9834
|
+
i++;
|
|
9835
|
+
break;
|
|
9836
|
+
}
|
|
9837
|
+
}
|
|
9838
|
+
if (d2 !== 0)
|
|
9839
|
+
return -1;
|
|
9840
|
+
ws();
|
|
9841
|
+
}
|
|
9842
|
+
if (s[i] === "(") {
|
|
9843
|
+
let d2 = 0;
|
|
9844
|
+
for (;i < n2; ) {
|
|
9845
|
+
const k = skipLiteral(s, i);
|
|
9846
|
+
if (k !== i) {
|
|
9847
|
+
i = k;
|
|
9848
|
+
continue;
|
|
9849
|
+
}
|
|
9850
|
+
if (s[i] === "(")
|
|
9851
|
+
d2++;
|
|
9852
|
+
else if (s[i] === ")" && --d2 === 0) {
|
|
9853
|
+
i++;
|
|
9854
|
+
break;
|
|
9855
|
+
}
|
|
9856
|
+
i++;
|
|
9857
|
+
}
|
|
9858
|
+
if (d2 !== 0)
|
|
9859
|
+
return -1;
|
|
9860
|
+
} else {
|
|
9861
|
+
const st = i;
|
|
9862
|
+
while (i < n2 && /[\w$]/.test(s[i]))
|
|
9863
|
+
i++;
|
|
9864
|
+
if (i === st)
|
|
9865
|
+
return -1;
|
|
9866
|
+
}
|
|
9867
|
+
ws();
|
|
9868
|
+
if (s[i] === "=" && s[i + 1] === ">")
|
|
9869
|
+
return i + 2;
|
|
9870
|
+
if (s[i] !== ":")
|
|
9871
|
+
return -1;
|
|
9872
|
+
let d = 0;
|
|
9873
|
+
for (i++;i < n2; ) {
|
|
9874
|
+
const k = skipLiteral(s, i);
|
|
9875
|
+
if (k !== i) {
|
|
9876
|
+
i = k;
|
|
9877
|
+
continue;
|
|
9878
|
+
}
|
|
9879
|
+
const c = s[i];
|
|
9880
|
+
if ("([{".includes(c))
|
|
9881
|
+
d++;
|
|
9882
|
+
else if (")]}".includes(c))
|
|
9883
|
+
d--;
|
|
9884
|
+
else if (d === 0 && c === "=")
|
|
9885
|
+
return s[i + 1] === ">" ? i + 2 : -1;
|
|
9886
|
+
else if (d === 0 && c === ";")
|
|
9887
|
+
return -1;
|
|
9888
|
+
i++;
|
|
9889
|
+
}
|
|
9890
|
+
return -1;
|
|
10008
9891
|
}
|
|
10009
|
-
function
|
|
10010
|
-
|
|
10011
|
-
|
|
10012
|
-
|
|
10013
|
-
|
|
10014
|
-
|
|
10015
|
-
|
|
10016
|
-
|
|
10017
|
-
if (
|
|
10018
|
-
|
|
10019
|
-
if (
|
|
10020
|
-
|
|
10021
|
-
if (
|
|
10022
|
-
|
|
9892
|
+
function memberSig(h) {
|
|
9893
|
+
if (!h || /^(private|protected|#)/.test(h))
|
|
9894
|
+
return null;
|
|
9895
|
+
let depth = 0, angle = 0;
|
|
9896
|
+
for (let i = 0;i < h.length; i++) {
|
|
9897
|
+
const c = h[i];
|
|
9898
|
+
if ("([{".includes(c))
|
|
9899
|
+
depth++;
|
|
9900
|
+
else if (")]}".includes(c))
|
|
9901
|
+
depth--;
|
|
9902
|
+
else if (depth === 0 && c === "<")
|
|
9903
|
+
angle++;
|
|
9904
|
+
else if (depth === 0 && c === ">" && h[i - 1] !== "=" && angle > 0)
|
|
9905
|
+
angle--;
|
|
9906
|
+
else if (c === "=" && depth === 0 && angle === 0 && !"=!<".includes(h[i - 1] ?? " ") && h[i + 1] !== "=" && h[i + 1] !== ">") {
|
|
9907
|
+
const rhs = h.slice(i + 1).trim();
|
|
9908
|
+
if (rhs.endsWith("=>") || /^(async\s+)?function\b/.test(rhs))
|
|
9909
|
+
return h;
|
|
9910
|
+
const len = arrowHeadLen(rhs);
|
|
9911
|
+
return `${h.slice(0, i).trim()}${len > 0 ? ` = ${rhs.slice(0, len)}` : ""}`;
|
|
9912
|
+
}
|
|
10023
9913
|
}
|
|
10024
|
-
return
|
|
10025
|
-
}
|
|
10026
|
-
function summaryOf(a) {
|
|
10027
|
-
const why = a.tier === a.computed ? a.reasons.slice(0, 2).join("; ") : `computed ${a.computed}; override ${a.override?.from} to ${a.override?.to}: ${a.override?.reason}`;
|
|
10028
|
-
const def = a.checks_deferred;
|
|
10029
|
-
return `risk: ${a.tier} (${why}), ${def.length ? def.join(", ") : "no deeper checks"} not run`;
|
|
9914
|
+
return h;
|
|
10030
9915
|
}
|
|
10031
|
-
function
|
|
10032
|
-
const
|
|
10033
|
-
|
|
9916
|
+
function splitDeclarators(h) {
|
|
9917
|
+
const parts = [];
|
|
9918
|
+
let depth = 0, angle = 0, init = false, from = 0;
|
|
9919
|
+
for (let i = 0;i < h.length; ) {
|
|
9920
|
+
const k = skipLiteral(h, i);
|
|
9921
|
+
if (k !== i) {
|
|
9922
|
+
i = k;
|
|
9923
|
+
continue;
|
|
9924
|
+
}
|
|
9925
|
+
const c = h[i];
|
|
9926
|
+
if ("([{".includes(c))
|
|
9927
|
+
depth++;
|
|
9928
|
+
else if (")]}".includes(c))
|
|
9929
|
+
depth--;
|
|
9930
|
+
else if (depth === 0 && !init && c === "<")
|
|
9931
|
+
angle++;
|
|
9932
|
+
else if (depth === 0 && !init && c === ">" && h[i - 1] !== "=")
|
|
9933
|
+
angle = Math.max(0, angle - 1);
|
|
9934
|
+
else if (depth === 0 && angle === 0 && !init && c === "=" && h[i + 1] !== "=" && h[i + 1] !== ">" && !"=!<".includes(h[i - 1] ?? " ")) {
|
|
9935
|
+
init = true;
|
|
9936
|
+
const rest = h.slice(i + 1);
|
|
9937
|
+
const len = arrowHeadLen(rest.trimStart());
|
|
9938
|
+
if (len > 0) {
|
|
9939
|
+
i += 1 + (rest.length - rest.trimStart().length) + len;
|
|
9940
|
+
continue;
|
|
9941
|
+
}
|
|
9942
|
+
} else if (depth === 0 && angle === 0 && c === ",") {
|
|
9943
|
+
parts.push(h.slice(from, i));
|
|
9944
|
+
from = i + 1;
|
|
9945
|
+
init = false;
|
|
9946
|
+
}
|
|
9947
|
+
i++;
|
|
9948
|
+
}
|
|
9949
|
+
parts.push(h.slice(from));
|
|
9950
|
+
return parts;
|
|
10034
9951
|
}
|
|
10035
|
-
function
|
|
10036
|
-
|
|
10037
|
-
|
|
10038
|
-
|
|
10039
|
-
|
|
10040
|
-
|
|
10041
|
-
|
|
9952
|
+
function exportHead(h, end) {
|
|
9953
|
+
let depth = 0, last = -1, nn = -1;
|
|
9954
|
+
const star = /^export\s*(type\s*)?\*/.test(h.slice(0, 40));
|
|
9955
|
+
for (let i = 0;i < h.length; ) {
|
|
9956
|
+
const k = skipLiteral(h, i);
|
|
9957
|
+
if (k !== i) {
|
|
9958
|
+
last = k - 1;
|
|
9959
|
+
i = k;
|
|
9960
|
+
continue;
|
|
9961
|
+
}
|
|
9962
|
+
const c = h[i];
|
|
9963
|
+
if ("([{".includes(c))
|
|
9964
|
+
depth++;
|
|
9965
|
+
else if (")]}".includes(c))
|
|
9966
|
+
depth--;
|
|
9967
|
+
else if (depth === 0 && c === ";")
|
|
9968
|
+
return h.slice(0, i + 1);
|
|
9969
|
+
else if (depth === 0 && c === `
|
|
9970
|
+
` && last >= 0) {
|
|
9971
|
+
if (nn < i) {
|
|
9972
|
+
nn = i;
|
|
9973
|
+
while (nn < h.length && /\s/.test(h[nn]))
|
|
9974
|
+
nn++;
|
|
9975
|
+
}
|
|
9976
|
+
const tail = h.slice(Math.max(0, last - 300), last + 1);
|
|
9977
|
+
const next = h.slice(nn, nn + 12);
|
|
9978
|
+
const open = /[=|&,<(:?.+\-*/]$|=>$|\b(from|as|extends|keyof|typeof|type)$/.test(tail) || /^(from\b|extends\b|as\b|[|&?:.,=])/.test(next);
|
|
9979
|
+
if (!open && (!star || /\bfrom\s*(["'])[^"']*\1$/.test(tail)))
|
|
9980
|
+
return h.slice(0, last + 1);
|
|
10042
9981
|
}
|
|
9982
|
+
if (!/\s/.test(c))
|
|
9983
|
+
last = i;
|
|
9984
|
+
i++;
|
|
10043
9985
|
}
|
|
10044
|
-
|
|
10045
|
-
|
|
10046
|
-
|
|
10047
|
-
|
|
10048
|
-
|
|
10049
|
-
|
|
10050
|
-
|
|
10051
|
-
|
|
10052
|
-
|
|
10053
|
-
|
|
9986
|
+
return h.trimEnd() + (end === ";" ? ";" : "");
|
|
9987
|
+
}
|
|
9988
|
+
function hasTopSemi(line2) {
|
|
9989
|
+
let depth = 0;
|
|
9990
|
+
for (let i = 0;i < line2.length; ) {
|
|
9991
|
+
const k = skipLiteral(line2, i);
|
|
9992
|
+
if (k !== i) {
|
|
9993
|
+
i = k;
|
|
9994
|
+
continue;
|
|
9995
|
+
}
|
|
9996
|
+
const c = line2[i];
|
|
9997
|
+
if ("([{".includes(c))
|
|
9998
|
+
depth++;
|
|
9999
|
+
else if (")]}".includes(c))
|
|
10000
|
+
depth--;
|
|
10001
|
+
else if (c === ";" && depth <= 0 && line2.slice(i + 1).trim())
|
|
10054
10002
|
return true;
|
|
10055
|
-
|
|
10056
|
-
|
|
10057
|
-
|
|
10003
|
+
i++;
|
|
10004
|
+
}
|
|
10005
|
+
return false;
|
|
10058
10006
|
}
|
|
10059
|
-
function
|
|
10060
|
-
|
|
10061
|
-
|
|
10062
|
-
|
|
10063
|
-
|
|
10064
|
-
|
|
10065
|
-
|
|
10066
|
-
return locked ? [] : [f.path];
|
|
10067
|
-
});
|
|
10007
|
+
function strictMember(m) {
|
|
10008
|
+
const h = m.head.trim();
|
|
10009
|
+
if (!MEMBER_GRAMMAR.test(h) || NOT_MEMBER.test(h))
|
|
10010
|
+
return false;
|
|
10011
|
+
if (m.end !== "{" && /^[^=:<]*\(/.test(h) && !/^(?:(?:public|protected|private)\s+)?constructor\b/.test(h) && !/\)\s*:/.test(h))
|
|
10012
|
+
return false;
|
|
10013
|
+
return true;
|
|
10068
10014
|
}
|
|
10069
|
-
function
|
|
10070
|
-
const
|
|
10071
|
-
const
|
|
10072
|
-
|
|
10073
|
-
|
|
10074
|
-
|
|
10075
|
-
|
|
10076
|
-
|
|
10077
|
-
|
|
10078
|
-
|
|
10079
|
-
|
|
10080
|
-
|
|
10081
|
-
|
|
10082
|
-
|
|
10083
|
-
|
|
10084
|
-
|
|
10085
|
-
|
|
10086
|
-
|
|
10087
|
-
|
|
10088
|
-
|
|
10089
|
-
|
|
10090
|
-
|
|
10091
|
-
|
|
10092
|
-
|
|
10093
|
-
|
|
10094
|
-
|
|
10095
|
-
|
|
10096
|
-
|
|
10097
|
-
|
|
10098
|
-
|
|
10099
|
-
|
|
10100
|
-
|
|
10101
|
-
|
|
10102
|
-
|
|
10103
|
-
|
|
10104
|
-
|
|
10105
|
-
|
|
10106
|
-
|
|
10107
|
-
|
|
10108
|
-
|
|
10109
|
-
|
|
10015
|
+
function tsAmbiguous(s, jsx) {
|
|
10016
|
+
const n2 = s.length, stack = [];
|
|
10017
|
+
const tpl = (from) => {
|
|
10018
|
+
for (let j = from;j < n2; ) {
|
|
10019
|
+
const c = s[j];
|
|
10020
|
+
if (c === "\\")
|
|
10021
|
+
j += 2;
|
|
10022
|
+
else if (c === "`")
|
|
10023
|
+
return j + 1;
|
|
10024
|
+
else if (c === "$" && s[j + 1] === "{") {
|
|
10025
|
+
stack.push("$");
|
|
10026
|
+
return j + 2;
|
|
10027
|
+
} else
|
|
10028
|
+
j++;
|
|
10029
|
+
}
|
|
10030
|
+
return -1;
|
|
10031
|
+
};
|
|
10032
|
+
let prev = "", prev2 = "";
|
|
10033
|
+
const set = (c) => {
|
|
10034
|
+
prev2 = prev;
|
|
10035
|
+
prev = c;
|
|
10036
|
+
};
|
|
10037
|
+
for (let i = 0;i < n2; ) {
|
|
10038
|
+
const c = s[i];
|
|
10039
|
+
if (/\s/.test(c)) {
|
|
10040
|
+
i++;
|
|
10041
|
+
continue;
|
|
10042
|
+
}
|
|
10043
|
+
if (c === "/" && s[i + 1] === "/") {
|
|
10044
|
+
const e = s.indexOf(`
|
|
10045
|
+
`, i);
|
|
10046
|
+
if (e < 0)
|
|
10047
|
+
break;
|
|
10048
|
+
i = e;
|
|
10049
|
+
continue;
|
|
10050
|
+
}
|
|
10051
|
+
if (c === "/" && s[i + 1] === "*") {
|
|
10052
|
+
const e = s.indexOf("*/", i + 2);
|
|
10053
|
+
if (e < 0)
|
|
10054
|
+
return true;
|
|
10055
|
+
i = e + 2;
|
|
10056
|
+
continue;
|
|
10057
|
+
}
|
|
10058
|
+
if (c === "`" || c === "}" && stack[stack.length - 1] === "$") {
|
|
10059
|
+
if (c === "`" && jsx)
|
|
10060
|
+
return true;
|
|
10061
|
+
if (c === "}")
|
|
10062
|
+
stack.pop();
|
|
10063
|
+
const e = tpl(i + 1);
|
|
10064
|
+
if (e < 0)
|
|
10065
|
+
return true;
|
|
10066
|
+
i = e;
|
|
10067
|
+
set("a");
|
|
10068
|
+
continue;
|
|
10069
|
+
}
|
|
10070
|
+
if (c === '"' || c === "'") {
|
|
10071
|
+
let j = i + 1;
|
|
10072
|
+
for (;j < n2 && s[j] !== c; j++) {
|
|
10073
|
+
if (s[j] === "\\")
|
|
10074
|
+
j++;
|
|
10075
|
+
else if (s[j] === `
|
|
10076
|
+
`)
|
|
10077
|
+
return true;
|
|
10078
|
+
}
|
|
10079
|
+
if (j >= n2)
|
|
10080
|
+
return true;
|
|
10081
|
+
i = j + 1;
|
|
10082
|
+
set("a");
|
|
10083
|
+
continue;
|
|
10084
|
+
}
|
|
10085
|
+
if (c === "/") {
|
|
10086
|
+
if (jsx && prev === "<") {
|
|
10087
|
+
i++;
|
|
10088
|
+
set("/");
|
|
10089
|
+
continue;
|
|
10090
|
+
}
|
|
10091
|
+
if (commentBefore(s, i))
|
|
10092
|
+
return true;
|
|
10093
|
+
if (prev && !"(,=:[!&|?{;+-*%~^".includes(prev))
|
|
10094
|
+
return true;
|
|
10095
|
+
if ((prev === "+" || prev === "-") && prev2 === prev)
|
|
10096
|
+
return true;
|
|
10097
|
+
let j = i + 1, cls = false, closed = false;
|
|
10098
|
+
for (;j < n2; j++) {
|
|
10099
|
+
const d = s[j];
|
|
10100
|
+
if (d === `
|
|
10101
|
+
`)
|
|
10102
|
+
return true;
|
|
10103
|
+
if (d === "\\")
|
|
10104
|
+
j++;
|
|
10105
|
+
else if (d === "[")
|
|
10106
|
+
cls = true;
|
|
10107
|
+
else if (d === "]")
|
|
10108
|
+
cls = false;
|
|
10109
|
+
else if (d === "/" && !cls) {
|
|
10110
|
+
closed = true;
|
|
10111
|
+
break;
|
|
10112
|
+
}
|
|
10113
|
+
}
|
|
10114
|
+
if (!closed)
|
|
10115
|
+
return true;
|
|
10116
|
+
i = j + 1;
|
|
10117
|
+
while (i < n2 && /[a-z]/i.test(s[i]))
|
|
10118
|
+
i++;
|
|
10119
|
+
set("a");
|
|
10120
|
+
continue;
|
|
10121
|
+
}
|
|
10122
|
+
if (c === "(" || c === "[" || c === "{")
|
|
10123
|
+
stack.push(c);
|
|
10124
|
+
else if (c === ")" || c === "]" || c === "}") {
|
|
10125
|
+
const o = stack.pop();
|
|
10126
|
+
if (o !== (c === ")" ? "(" : c === "]" ? "[" : "{"))
|
|
10127
|
+
return true;
|
|
10128
|
+
}
|
|
10129
|
+
set(c);
|
|
10130
|
+
i++;
|
|
10110
10131
|
}
|
|
10111
|
-
|
|
10112
|
-
const advisories = manifestsWithoutLock(files).map((p) => `manifest changed without lockfile: ${p}`);
|
|
10113
|
-
const summary = summaryOf({ tier, computed, reasons, ...override ? { override } : {}, checks_deferred }) + (advisories.length ? `; advisory: ${advisories.join(", ")}` : "");
|
|
10114
|
-
return {
|
|
10115
|
-
version: 1,
|
|
10116
|
-
tier,
|
|
10117
|
-
computed,
|
|
10118
|
-
reasons,
|
|
10119
|
-
stats: { files: files.length, lines, sensitive, tests_modified: testsModified, tests_deleted: testsDeleted, api },
|
|
10120
|
-
checks_selected: plan.selected,
|
|
10121
|
-
checks_deferred,
|
|
10122
|
-
...override ? { override } : {},
|
|
10123
|
-
...ignored ? { override_ignored: ignored } : {},
|
|
10124
|
-
...advisories.length ? { advisories } : {},
|
|
10125
|
-
summary
|
|
10126
|
-
};
|
|
10127
|
-
}
|
|
10128
|
-
function changedFiles(repoDir, baseSha) {
|
|
10129
|
-
const run = (args) => safeGit(repoDir, args).split(`
|
|
10130
|
-
`).map((l) => l.trim()).filter(Boolean);
|
|
10131
|
-
const tracked = run(["diff", "--name-only", baseSha]);
|
|
10132
|
-
const untracked = run(["ls-files", "--others", "--exclude-standard"]);
|
|
10133
|
-
return [...new Set([...tracked, ...untracked])].filter((f) => !f.startsWith(".loki/"));
|
|
10132
|
+
return stack.length > 0;
|
|
10134
10133
|
}
|
|
10135
|
-
function
|
|
10136
|
-
|
|
10137
|
-
for (
|
|
10138
|
-
|
|
10139
|
-
|
|
10140
|
-
|
|
10141
|
-
|
|
10142
|
-
}
|
|
10143
|
-
for (const l of safeGit(repoDir, ["diff", "--name-status", baseSha]).split(`
|
|
10144
|
-
`)) {
|
|
10145
|
-
const [s, ...p] = l.split("\t"), f = stat.get(p[p.length - 1] ?? "");
|
|
10146
|
-
if (f)
|
|
10147
|
-
f.status = s?.startsWith("A") ? "added" : s?.startsWith("D") ? "deleted" : "modified";
|
|
10148
|
-
}
|
|
10149
|
-
const out2 = paths.map((path) => {
|
|
10150
|
-
const f = stat.get(path);
|
|
10151
|
-
if (f)
|
|
10152
|
-
return f;
|
|
10153
|
-
let n2 = 0;
|
|
10154
|
-
try {
|
|
10155
|
-
n2 = readFileSync29(join38(repoDir, path), "utf8").split(`
|
|
10156
|
-
`).length;
|
|
10157
|
-
} catch {}
|
|
10158
|
-
return { path, added: n2, deleted: 0, status: "added" };
|
|
10159
|
-
});
|
|
10160
|
-
for (const f of out2) {
|
|
10161
|
-
if (f.status === "deleted" || !MANIFEST_LOCKS.some(([m]) => m.test(f.path)))
|
|
10134
|
+
function maskDefaults(sig) {
|
|
10135
|
+
let out2 = "", pd = 0;
|
|
10136
|
+
for (let i = 0;i < sig.length; ) {
|
|
10137
|
+
const k = skipLiteral(sig, i);
|
|
10138
|
+
if (k !== i) {
|
|
10139
|
+
out2 += sig.slice(i, k);
|
|
10140
|
+
i = k;
|
|
10162
10141
|
continue;
|
|
10163
|
-
|
|
10164
|
-
|
|
10165
|
-
|
|
10166
|
-
|
|
10167
|
-
|
|
10168
|
-
|
|
10169
|
-
|
|
10170
|
-
|
|
10171
|
-
|
|
10142
|
+
}
|
|
10143
|
+
const c = sig[i];
|
|
10144
|
+
if (c === "(")
|
|
10145
|
+
pd++;
|
|
10146
|
+
else if (c === ")")
|
|
10147
|
+
pd--;
|
|
10148
|
+
else if (c === "=" && pd > 0 && sig[i + 1] !== "=" && sig[i + 1] !== ">" && !"=!<".includes(sig[i - 1] ?? " ")) {
|
|
10149
|
+
out2 = out2.trimEnd() + " = ...";
|
|
10150
|
+
let d = 0, angle = 0, j = i + 1;
|
|
10151
|
+
for (;j < sig.length; ) {
|
|
10152
|
+
const l = skipLiteral(sig, j);
|
|
10153
|
+
if (l !== j) {
|
|
10154
|
+
j = l;
|
|
10155
|
+
continue;
|
|
10156
|
+
}
|
|
10157
|
+
const e = sig[j];
|
|
10158
|
+
if ("([{".includes(e))
|
|
10159
|
+
d++;
|
|
10160
|
+
else if (")]}".includes(e)) {
|
|
10161
|
+
if (d === 0)
|
|
10162
|
+
break;
|
|
10163
|
+
d--;
|
|
10164
|
+
} else if (e === "<" && /[\w$]/.test(sig[j - 1] ?? ""))
|
|
10165
|
+
angle++;
|
|
10166
|
+
else if (e === ">" && sig[j - 1] !== "=" && angle > 0)
|
|
10167
|
+
angle--;
|
|
10168
|
+
else if (e === "," && d === 0 && angle === 0)
|
|
10169
|
+
break;
|
|
10170
|
+
j++;
|
|
10171
|
+
}
|
|
10172
|
+
i = j;
|
|
10173
|
+
continue;
|
|
10174
|
+
}
|
|
10175
|
+
out2 += c;
|
|
10176
|
+
i++;
|
|
10172
10177
|
}
|
|
10173
10178
|
return out2;
|
|
10174
10179
|
}
|
|
10175
|
-
function
|
|
10176
|
-
|
|
10177
|
-
|
|
10178
|
-
|
|
10179
|
-
|
|
10180
|
-
`);
|
|
10181
|
-
renameSync8(`${p}.tmp`, p);
|
|
10182
|
-
return p;
|
|
10183
|
-
} catch {
|
|
10184
|
-
return null;
|
|
10185
|
-
}
|
|
10186
|
-
}
|
|
10187
|
-
function truncateBytes(s, cap) {
|
|
10188
|
-
const buf = Buffer.from(s, "utf8");
|
|
10189
|
-
return buf.length <= cap ? s : buf.subarray(0, Math.max(0, cap)).toString("utf8").replace(/\uFFFD$/, "");
|
|
10190
|
-
}
|
|
10191
|
-
function failureExcerpt(out2, repoDir = "", cap = EXCERPT_GROUP_CAP) {
|
|
10192
|
-
let t = stripAnsi(out2.slice(-65536)).replace(/\r/g, "");
|
|
10193
|
-
if (repoDir)
|
|
10194
|
-
t = t.split(repoDir.replace(/\/+$/, "") + "/").join("");
|
|
10195
|
-
const lines = t.split(`
|
|
10196
|
-
`).map((l) => l.replace(/\s+$/, ""));
|
|
10197
|
-
const pick = new Set;
|
|
10198
|
-
const take = (i, n2 = 1) => {
|
|
10199
|
-
for (let k = 0;k < n2 && i + k < lines.length; k++)
|
|
10200
|
-
if (lines[i + k].trim())
|
|
10201
|
-
pick.add(i + k);
|
|
10180
|
+
function maskDecorators(sig) {
|
|
10181
|
+
let out2 = "";
|
|
10182
|
+
const badNext = (at) => {
|
|
10183
|
+
const r = sig.slice(at).trimStart();
|
|
10184
|
+
return !/[A-Za-z_$@]/.test(r[0] ?? "") || RESERVED_AFTER_DECORATOR.test(r);
|
|
10202
10185
|
};
|
|
10203
|
-
|
|
10204
|
-
|
|
10205
|
-
|
|
10206
|
-
|
|
10207
|
-
|
|
10208
|
-
|
|
10209
|
-
take(i);
|
|
10210
|
-
else if (/AssertionError|^\s*(expected|actual)\b.*[:=]|^\s*(not ok|FAILED)\b/.test(l))
|
|
10211
|
-
take(i, 3);
|
|
10212
|
-
else if (/^\s*--- FAIL/.test(l))
|
|
10213
|
-
take(i, 4);
|
|
10214
|
-
else if (/^[\w./@-]+\.\w+(\(\d+,\d+\)|:\d+(:\d+)?)[:\s].*\b(error|TS\d+|[A-Z]{1,3}\d{3,4})\b/.test(l))
|
|
10215
|
-
take(i);
|
|
10216
|
-
});
|
|
10217
|
-
const lastFrame = lines.map((l, i) => /^[\w./@-]+\.py:\d+: /.test(l) ? i : -1).filter((i) => i >= 0).pop();
|
|
10218
|
-
if (lastFrame !== undefined && [...pick].some((i) => /^E\s/.test(lines[i])))
|
|
10219
|
-
take(lastFrame);
|
|
10220
|
-
let body = [...pick].sort((a, b) => a - b).map((i) => lines[i]).join(`
|
|
10221
|
-
`);
|
|
10222
|
-
if (!body)
|
|
10223
|
-
body = lines.filter((l) => l.trim()).slice(-6).join(`
|
|
10224
|
-
`);
|
|
10225
|
-
body = redactSecrets(body);
|
|
10226
|
-
return truncateBytes(body, cap);
|
|
10227
|
-
}
|
|
10228
|
-
function pytestCollectionIsRed(output, repoDir) {
|
|
10229
|
-
if (/ModuleNotFoundError/.test(output))
|
|
10230
|
-
return false;
|
|
10231
|
-
const real2 = (p) => {
|
|
10232
|
-
try {
|
|
10233
|
-
return realpathSync17(isAbsolute3(p) ? p : join38(repoDir, p));
|
|
10234
|
-
} catch {
|
|
10235
|
-
return null;
|
|
10186
|
+
for (let i = 0;i < sig.length; ) {
|
|
10187
|
+
const k = skipLiteral(sig, i);
|
|
10188
|
+
if (k !== i) {
|
|
10189
|
+
out2 += sig.slice(i, k);
|
|
10190
|
+
i = k;
|
|
10191
|
+
continue;
|
|
10236
10192
|
}
|
|
10237
|
-
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
|
|
10241
|
-
|
|
10242
|
-
|
|
10243
|
-
|
|
10244
|
-
|
|
10245
|
-
|
|
10246
|
-
|
|
10247
|
-
|
|
10248
|
-
|
|
10249
|
-
|
|
10250
|
-
|
|
10251
|
-
|
|
10252
|
-
|
|
10253
|
-
if (start < 0 || start > hdr.index)
|
|
10254
|
-
return false;
|
|
10255
|
-
const block = output.slice(start, hdr.index).split(/^-+ Captured .*$/m)[0];
|
|
10256
|
-
const eLines = [...block.matchAll(new RegExp(`^E {3}${cls}: (.*)$`, "gm"))];
|
|
10257
|
-
const eLine = eLines[eLines.length - 1];
|
|
10258
|
-
if (!eLine)
|
|
10259
|
-
return false;
|
|
10260
|
-
if (cls === "AttributeError") {
|
|
10261
|
-
const m = /^module ['"]([\w.]+)['"] has no attribute/.exec(eLine[1]);
|
|
10262
|
-
return !!m && moduleUnderRepo(repoDir, m[1]);
|
|
10193
|
+
if (sig[i] !== "@") {
|
|
10194
|
+
out2 += sig[i];
|
|
10195
|
+
i++;
|
|
10196
|
+
continue;
|
|
10197
|
+
}
|
|
10198
|
+
const m = /^@[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*/.exec(sig.slice(i, i + 200));
|
|
10199
|
+
if (!m)
|
|
10200
|
+
return null;
|
|
10201
|
+
out2 += m[0];
|
|
10202
|
+
i += m[0].length;
|
|
10203
|
+
if (sig[i] === "(") {
|
|
10204
|
+
out2 += "(...)";
|
|
10205
|
+
i = skipBalanced(sig, i);
|
|
10206
|
+
}
|
|
10207
|
+
if (badNext(i))
|
|
10208
|
+
return null;
|
|
10263
10209
|
}
|
|
10264
|
-
|
|
10265
|
-
const last = frames[frames.length - 1];
|
|
10266
|
-
return !!last && under(last[1]) && !/^\s*(import\s|from\s\S+\s+import\b)/.test(last[2] ?? "");
|
|
10210
|
+
return out2;
|
|
10267
10211
|
}
|
|
10268
|
-
function
|
|
10269
|
-
|
|
10270
|
-
|
|
10212
|
+
function skipBalanced(s, i) {
|
|
10213
|
+
let d = 0;
|
|
10214
|
+
while (i < s.length) {
|
|
10215
|
+
const k = skipLiteral(s, i);
|
|
10216
|
+
if (k !== i) {
|
|
10217
|
+
i = k;
|
|
10218
|
+
continue;
|
|
10219
|
+
}
|
|
10220
|
+
if ("([{".includes(s[i]))
|
|
10221
|
+
d++;
|
|
10222
|
+
else if (")]}".includes(s[i]) && --d === 0)
|
|
10223
|
+
return i + 1;
|
|
10224
|
+
i++;
|
|
10225
|
+
}
|
|
10226
|
+
return s.length;
|
|
10271
10227
|
}
|
|
10272
|
-
function
|
|
10273
|
-
|
|
10274
|
-
|
|
10275
|
-
|
|
10276
|
-
|
|
10277
|
-
|
|
10278
|
-
|
|
10279
|
-
|
|
10228
|
+
function maskExtends(head) {
|
|
10229
|
+
let angle = 0, depth = 0;
|
|
10230
|
+
for (let i = 0;i < head.length; ) {
|
|
10231
|
+
const k = skipLiteral(head, i);
|
|
10232
|
+
if (k !== i) {
|
|
10233
|
+
i = k;
|
|
10234
|
+
continue;
|
|
10235
|
+
}
|
|
10236
|
+
const c = head[i];
|
|
10237
|
+
if ("([{".includes(c))
|
|
10238
|
+
depth++;
|
|
10239
|
+
else if (")]}".includes(c))
|
|
10240
|
+
depth--;
|
|
10241
|
+
else if (c === "<")
|
|
10242
|
+
angle++;
|
|
10243
|
+
else if (c === ">" && head[i - 1] !== "=")
|
|
10244
|
+
angle = Math.max(0, angle - 1);
|
|
10245
|
+
else if (depth === 0 && angle === 0 && /^extends\s/.test(head.slice(i)) && /\W/.test(head[i - 1] ?? " ")) {
|
|
10246
|
+
const from = i + 7;
|
|
10247
|
+
const im = /\simplements\s/.exec(head.slice(from));
|
|
10248
|
+
const end = im ? from + im.index : head.length;
|
|
10249
|
+
const expr = head.slice(from, end).trim();
|
|
10250
|
+
const ok = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*(?:<[^()]*>)?$/.test(expr);
|
|
10251
|
+
const tail = head.slice(end).trim();
|
|
10252
|
+
return `${head.slice(0, i)}extends ${ok ? expr : "..."}${tail ? ` ${tail}` : ""}`;
|
|
10253
|
+
}
|
|
10254
|
+
i++;
|
|
10255
|
+
}
|
|
10256
|
+
return head;
|
|
10280
10257
|
}
|
|
10281
|
-
function
|
|
10282
|
-
const
|
|
10283
|
-
|
|
10258
|
+
function enumSig(h) {
|
|
10259
|
+
const open = h.indexOf("{");
|
|
10260
|
+
if (open < 0)
|
|
10261
|
+
return null;
|
|
10262
|
+
const close = matchingBrace(h, open);
|
|
10263
|
+
if (close >= h.length)
|
|
10264
|
+
return null;
|
|
10265
|
+
const names = [];
|
|
10266
|
+
let depth = 0, from = open + 1;
|
|
10267
|
+
const take = (to) => {
|
|
10268
|
+
const nm = h.slice(from, to).split("=")[0].trim();
|
|
10269
|
+
if (nm)
|
|
10270
|
+
names.push(nm);
|
|
10271
|
+
};
|
|
10272
|
+
for (let i = open + 1;i < close; ) {
|
|
10273
|
+
const k = skipLiteral(h, i);
|
|
10274
|
+
if (k !== i) {
|
|
10275
|
+
i = k;
|
|
10276
|
+
continue;
|
|
10277
|
+
}
|
|
10278
|
+
const c = h[i];
|
|
10279
|
+
if ("([{".includes(c))
|
|
10280
|
+
depth++;
|
|
10281
|
+
else if (")]}".includes(c))
|
|
10282
|
+
depth--;
|
|
10283
|
+
else if (c === "," && depth === 0) {
|
|
10284
|
+
take(i);
|
|
10285
|
+
from = i + 1;
|
|
10286
|
+
}
|
|
10287
|
+
i++;
|
|
10288
|
+
}
|
|
10289
|
+
take(close);
|
|
10290
|
+
return `${h.slice(0, open).trim()} { ${names.join(", ")} }`;
|
|
10284
10291
|
}
|
|
10285
|
-
function
|
|
10286
|
-
const
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
|
|
10292
|
+
function tsSignatures(src, jsx) {
|
|
10293
|
+
const out2 = [];
|
|
10294
|
+
for (const it of items(src)) {
|
|
10295
|
+
const h = it.head.trim();
|
|
10296
|
+
if (!/^export\b/.test(h))
|
|
10297
|
+
continue;
|
|
10298
|
+
const lines = [];
|
|
10299
|
+
if (/^export\s+(declare\s+)?enum\b/.test(h)) {
|
|
10300
|
+
lines.push(enumSig(h) ?? exportHead(h, it.end));
|
|
10301
|
+
} else if (/^export\s+(declare\s+)?(type|interface)\b|^export\s*(type\s*)?[{*]/.test(h)) {
|
|
10302
|
+
lines.push(exportHead(h, it.end));
|
|
10303
|
+
} else if (/^export\s+(default\s+)?(abstract\s+)?class\b/.test(h)) {
|
|
10304
|
+
const ms = jsx || !it.balanced ? [] : items(it.body ?? "");
|
|
10305
|
+
const sigs = ms.map((m) => strictMember(m) ? memberSig(m.head.trim()) : null).map((m) => m === null ? null : maskDefaults(m));
|
|
10306
|
+
const dropped2 = ms.some((m) => !strictMember(m)) || sigs.some((m) => m !== null && (hasTopSemi(m) || NOT_MEMBER.test(m)));
|
|
10307
|
+
const keep = dropped2 ? [] : sigs.filter((m) => !!m);
|
|
10308
|
+
const headM = maskDecorators(exportHead(h, ""));
|
|
10309
|
+
const memM = keep.map(maskDecorators);
|
|
10310
|
+
if (headM !== null && !memM.includes(null))
|
|
10311
|
+
lines.push(`${maskExtends(headM)} {`, ...memM.map((m) => ` ${m};`), "}");
|
|
10312
|
+
} else if (/^export\s+(default\s+)?@/.test(h)) {
|
|
10313
|
+
const dm = maskDecorators(h);
|
|
10314
|
+
if (dm !== null)
|
|
10315
|
+
lines.push(maskExtends(dm));
|
|
10316
|
+
} else if (/^export\s+default\s/.test(h)) {
|
|
10317
|
+
const rest = h.replace(/^export\s+default\s+/, "");
|
|
10318
|
+
const len = arrowHeadLen(rest);
|
|
10319
|
+
if (len > 0)
|
|
10320
|
+
lines.push(`export default ${rest.slice(0, len)}`);
|
|
10321
|
+
else if (/^(async\s+)?function\b/.test(rest))
|
|
10322
|
+
lines.push(memberSig(h) ?? h);
|
|
10323
|
+
else
|
|
10324
|
+
lines.push(/^[\w$.]+$/.test(rest) ? h : "export default ...");
|
|
10325
|
+
} else if (/^export\s+(const|let|var)\b/.test(h)) {
|
|
10326
|
+
lines.push(splitDeclarators(h).map((p) => memberSig(p.trim()) ?? p.trim()).join(", "));
|
|
10327
|
+
} else {
|
|
10328
|
+
lines.push(memberSig(h) ?? h);
|
|
10329
|
+
}
|
|
10330
|
+
if (!lines.length)
|
|
10331
|
+
continue;
|
|
10332
|
+
const masked = /^export\s+(declare\s+)?(type|interface|enum)\b|^export\s*(type\s*)?[{*]|^export\s+(default\s+)?(abstract\s+)?class\b/.test(h) ? lines : lines.map((l) => {
|
|
10333
|
+
const d = maskDecorators(l);
|
|
10334
|
+
return d === null ? null : maskDefaults(d);
|
|
10335
|
+
});
|
|
10336
|
+
if (masked.includes(null))
|
|
10337
|
+
continue;
|
|
10338
|
+
const done = masked;
|
|
10339
|
+
if (!done.some(hasTopSemi))
|
|
10340
|
+
out2.push(...done);
|
|
10341
|
+
}
|
|
10342
|
+
return out2;
|
|
10290
10343
|
}
|
|
10291
|
-
|
|
10292
|
-
|
|
10293
|
-
|
|
10294
|
-
|
|
10295
|
-
|
|
10296
|
-
|
|
10297
|
-
|
|
10298
|
-
|
|
10344
|
+
var REGEX_PREV = "(,=:[!&|?{;+-*%~^", isComment = (s, i) => s[i] === "/" && (s[i + 1] === "/" || s[i + 1] === "*"), MODS = "(?:(?:public|private|protected|static|readonly|abstract|async|get|set|declare|override)\\s+)*", MEMBER_GRAMMAR, NOT_MEMBER, RESERVED_AFTER_DECORATOR;
|
|
10345
|
+
var init_ts_signatures = __esm(() => {
|
|
10346
|
+
MEMBER_GRAMMAR = new RegExp(`^(?:@[\\w$.]+(?:\\([^)]*\\))?\\s*)*${MODS}\\*?\\s*(?:[A-Za-z_$][\\w$]*|#[A-Za-z_$][\\w$]*|\\[[^\\]]*\\])\\s*[?!]?\\s*(?:[(<:=]|$)`);
|
|
10347
|
+
NOT_MEMBER = /^(return|const|let|var|if|else|for|while|do|switch|case|default|throw|try|catch|finally|new|await|yield|break|continue|import|export|function|delete|typeof|void)\b/;
|
|
10348
|
+
RESERVED_AFTER_DECORATOR = /^(?:if|else|for|while|do|switch|case|try|catch|finally|return|throw|with|var|let|const|function|new|delete|typeof|void|yield|await|break|continue|import|debugger|instanceof|this|super|null|true|false)(?![\w$])/;
|
|
10349
|
+
});
|
|
10350
|
+
|
|
10351
|
+
// ../../loki-ts/src/util/failure_memory.ts
|
|
10352
|
+
var init_failure_memory = __esm(() => {
|
|
10353
|
+
init_cache();
|
|
10354
|
+
init_safe_git();
|
|
10355
|
+
});
|
|
10356
|
+
|
|
10357
|
+
// ../../loki-ts/src/e10ext/repomemory.ts
|
|
10358
|
+
var init_repomemory = __esm(() => {
|
|
10359
|
+
init_cache();
|
|
10360
|
+
init_failure_memory();
|
|
10361
|
+
});
|
|
10362
|
+
|
|
10363
|
+
// ../../loki-ts/src/engine10/failures.ts
|
|
10364
|
+
function failCount(out2) {
|
|
10365
|
+
const n2 = (s, re) => +(s.match(re)?.[1] ?? 0);
|
|
10366
|
+
const l = out2.split(`
|
|
10367
|
+
`).reverse().map((x) => x.trim()).find((x) => /^(?:=+ )?\d+ \w+.* in [\d.]+s|^Tests?:?\s+\d/.test(x)), m = /^(?:#|\u2139) fail (\d+)$/m.exec(out2);
|
|
10368
|
+
return l ? n2(l, /(\d+) failed/) + n2(l, /(\d+) errors?/) : m ? +m[1] : null;
|
|
10299
10369
|
}
|
|
10300
|
-
function
|
|
10301
|
-
|
|
10302
|
-
|
|
10303
|
-
|
|
10304
|
-
|
|
10305
|
-
return "not_run";
|
|
10306
|
-
if (status === 0)
|
|
10307
|
-
return classifyCheck({ kind: "test", ok: true, out: output, path: f.path, ...f.runner === "go" ? { runner: "go" } : {} }).result === "pass" ? "pass" : "not_run";
|
|
10308
|
-
if (f.runner === "pytest")
|
|
10309
|
-
return status === 1 ? pytestExit1IsRed(output) ? "fail" : "not_run" : status === 2 ? pytestCollectionIsRed(output, repoDir) ? "fail" : "not_run" : "not_run";
|
|
10310
|
-
if (f.runner === "jest" || f.runner === "vitest" || f.runner === "bun")
|
|
10311
|
-
return parsedFailCount(f.runner, output) > 0 ? "fail" : "not_run";
|
|
10312
|
-
return f.runner === "node" && nodeIsRed(f, output) ? "fail" : "not_run";
|
|
10370
|
+
function failIds(output) {
|
|
10371
|
+
const ids = [...new Set(output.split(`
|
|
10372
|
+
`).map((l) => ID_LINE.exec(l.trim())).flatMap((m) => m ? [(m.slice(1).find(Boolean) ?? "").trim()] : []).filter(Boolean))];
|
|
10373
|
+
const c = failCount(output);
|
|
10374
|
+
return c && ids.length >= c ? ids : [];
|
|
10313
10375
|
}
|
|
10314
|
-
var
|
|
10315
|
-
|
|
10316
|
-
|
|
10317
|
-
var init_check_result = __esm(() => {
|
|
10318
|
-
init_testmap();
|
|
10319
|
-
init_safe_git();
|
|
10320
|
-
init_redact();
|
|
10321
|
-
FAIL_EVIDENCE = /\[(?:build|setup) failed\]|^--- FAIL|^[\w./-]+\.go:\d+:\d+: \S|\b[1-9]\d* (?:failed|errors?)\b/m;
|
|
10322
|
-
GO_FAIL_EVIDENCE = /^FAIL\t\S+\t[\d.]+s$|^panic: /m;
|
|
10323
|
-
GO_PKG_RE = /^(?:ok|FAIL|\?)\s+\S+\s+(?:\(cached\)|[\d.]+s\b|\[(?:no test files|build failed|setup failed)\])/;
|
|
10324
|
-
LLM_JUDGES = new Set(["council", "xreview", "code_review", "devils_advocate", "magic_debate"]);
|
|
10325
|
-
NON_RUNNER = new Set(["lint", "typecheck", "holdout", "select-tests"]);
|
|
10326
|
-
SENSITIVE = [
|
|
10327
|
-
["auth", /(^|\/)(auth|oauth|sso|session|login|permission|rbac|acl)[\w.-]*(\/|\.|$)/i],
|
|
10328
|
-
["crypto", /(^|\/)(crypt|crypto|jwt|signing|keys?|secrets?|tokens?|credential|password)[\w.-]*(\/|\.|$)/i],
|
|
10329
|
-
["payments", /(^|\/)(payments?|billing|checkout|stripe|invoice)[\w.-]*(\/|\.|$)/i],
|
|
10330
|
-
["migration", /(^|\/)(migrations?|alembic)\/|\.sql$/i],
|
|
10331
|
-
["ci", /(^|\/)(\.github\/(workflows|actions)|\.gitlab-ci\.yml|\.circleci|Jenkinsfile|azure-pipelines)/i],
|
|
10332
|
-
["lockfile", /(^|\/)(package-lock\.json|pnpm-lock\.yaml|bun\.lockb?|go\.sum|[\w-]+\.lock)$/],
|
|
10333
|
-
["infra", /(^|\/)(Dockerfile[\w.-]*|docker-compose[\w.-]*\.ya?ml|terraform|helm|k8s|kubernetes|infra|deploy)(\/|\.|$)|\.tf$/i],
|
|
10334
|
-
["env", /(^|\/)\.env[\w.]*$/]
|
|
10335
|
-
];
|
|
10336
|
-
API = /(^|\/)(openapi|swagger)[\w.-]*\.(ya?ml|json)$|\.proto$|\.d\.ts$|(^|\/)(api|routes|public)\/|(^|\/)index\.(ts|js|py)$/i;
|
|
10337
|
-
TEST_CFG = /(^|\/)(conftest\.py|\.?pytest\.(ini|toml)|tox\.ini|jest\.config\.[\w.]+|vitest\.config\.[\w.]+)$/;
|
|
10338
|
-
RANK2 = { low: 0, medium: 1, high: 2 };
|
|
10339
|
-
RAN_ALWAYS = ["targeted tests", "lint of changed files"];
|
|
10340
|
-
PLAN = {
|
|
10341
|
-
low: { selected: [...RAN_ALWAYS] },
|
|
10342
|
-
medium: { selected: [...RAN_ALWAYS, "full test command", "one reviewer"] },
|
|
10343
|
-
high: { selected: [...RAN_ALWAYS, "full test command", "full suite", "council", "security scan"] }
|
|
10344
|
-
};
|
|
10345
|
-
LOW_SKIPPED = ["full test command", "reviewer", "council", "security scan"];
|
|
10346
|
-
MANIFEST_LOCKS = [
|
|
10347
|
-
[/(^|\/)package\.json$/, /(^|\/)(package-lock\.json|npm-shrinkwrap\.json|pnpm-lock\.yaml|yarn\.lock|bun\.lockb?)$/],
|
|
10348
|
-
[/(^|\/)pyproject\.toml$/, /(^|\/)(poetry\.lock|uv\.lock|pdm\.lock|Pipfile\.lock)$/],
|
|
10349
|
-
[/(^|\/)go\.mod$/, /(^|\/)go\.sum$/]
|
|
10350
|
-
];
|
|
10351
|
-
PKG_DEP_KEYS = ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"];
|
|
10352
|
-
PYPROJECT_NONDEP = /^(name|version|description|readme|license|requires-python|python|authors|maintainers|keywords|classifiers|homepage|repository|documentation|packages|include|exclude)$/;
|
|
10376
|
+
var ID_LINE;
|
|
10377
|
+
var init_failures = __esm(() => {
|
|
10378
|
+
ID_LINE = /^(?:(?:FAILED|ERROR)\s+(\S+::\S*)(?:\s.*)?|\u25cf\s+(?!Console|Test suite failed)(.+)|not ok \d+ - (.+?)(?:\s+#.*)?|\u2716\s+(?!failing tests:)(.+?)(?:\s+\([\d.]+ms\))?|(?:FAIL|\u00d7)\s+(.+))$/;
|
|
10353
10379
|
});
|
|
10354
10380
|
|
|
10355
10381
|
// ../../loki-ts/src/runner/state.ts
|
|
@@ -10370,7 +10396,7 @@ var init_state = __esm(() => {
|
|
|
10370
10396
|
});
|
|
10371
10397
|
|
|
10372
10398
|
// ../../loki-ts/src/runner/repo_profile.ts
|
|
10373
|
-
import { spawnSync as
|
|
10399
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
10374
10400
|
import { existsSync as existsSync24, lstatSync as lstatSync9, readFileSync as readFileSync30, mkdirSync as mkdirSync14, readdirSync as readdirSync14, renameSync as renameSync9, rmSync as rmSync8, writeFileSync as writeFileSync17 } from "fs";
|
|
10375
10401
|
import { basename as basename12, join as join39, resolve as resolve13, isAbsolute as isAbsolute4 } from "path";
|
|
10376
10402
|
function detectFormatters(repoDir) {
|
|
@@ -10405,7 +10431,7 @@ function runFormatters(repoDir, files, env) {
|
|
|
10405
10431
|
}) : [];
|
|
10406
10432
|
return fmts.flatMap((fm) => {
|
|
10407
10433
|
const own = mine.filter((f) => fm.exts.test(f));
|
|
10408
|
-
const r = own.length ?
|
|
10434
|
+
const r = own.length ? spawnSync3(fm.argv[0], [...fm.argv.slice(1), ...own.map((f) => `./${f}`)], { cwd: repoDir, env, stdio: "ignore", timeout: 30000 }) : null;
|
|
10409
10435
|
return r && !r.error && r.status === 0 ? own : [];
|
|
10410
10436
|
});
|
|
10411
10437
|
}
|
|
@@ -11213,7 +11239,7 @@ var init_shell = __esm(() => {
|
|
|
11213
11239
|
|
|
11214
11240
|
// ../../loki-ts/src/util/python.ts
|
|
11215
11241
|
import { accessSync, constants as constants3, existsSync as existsSync27, mkdtempSync as mkdtempSync4, readFileSync as readFileSync34, realpathSync as realpathSync18, rmSync as rmSync11, statSync as statSync16 } from "fs";
|
|
11216
|
-
import { spawnSync as
|
|
11242
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
11217
11243
|
import { tmpdir as tmpdir5 } from "os";
|
|
11218
11244
|
async function findPython3() {
|
|
11219
11245
|
if (_pythonCache !== undefined)
|
|
@@ -11250,7 +11276,7 @@ function pySignatures(src) {
|
|
|
11250
11276
|
const py = resolvePython3();
|
|
11251
11277
|
if (!py)
|
|
11252
11278
|
return [];
|
|
11253
|
-
const r =
|
|
11279
|
+
const r = spawnSync4(py, ["-I", "-S", "-c", PY_SCRIPT], {
|
|
11254
11280
|
input: src.replace(/\r\n?/g, `
|
|
11255
11281
|
`),
|
|
11256
11282
|
cwd: tmpdir5(),
|
|
@@ -12402,7 +12428,7 @@ var init_runner_errors = __esm(() => {
|
|
|
12402
12428
|
});
|
|
12403
12429
|
|
|
12404
12430
|
// ../../loki-ts/src/runner/load_owner.ts
|
|
12405
|
-
import { spawnSync as
|
|
12431
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
12406
12432
|
import { mkdtempSync as mkdtempSync6, realpathSync as realpathSync19, rmSync as rmSync14 } from "fs";
|
|
12407
12433
|
import { tmpdir as tmpdir8 } from "os";
|
|
12408
12434
|
import { basename as basename18, extname as extname2, join as join46 } from "path";
|
|
@@ -12447,7 +12473,7 @@ function sameLoadError(head, base, headRoots, baseRoots) {
|
|
|
12447
12473
|
function killTree(pid) {
|
|
12448
12474
|
const all = [pid];
|
|
12449
12475
|
for (let k = 0;k < all.length; k++) {
|
|
12450
|
-
const kids =
|
|
12476
|
+
const kids = spawnSync5("pgrep", ["-P", String(all[k])], { encoding: "utf8", env: process.env }).stdout.split(/\s+/).filter(Boolean).map(Number);
|
|
12451
12477
|
all.push(...kids.filter((x) => Number.isInteger(x) && !all.includes(x)));
|
|
12452
12478
|
}
|
|
12453
12479
|
try {
|
|
@@ -12595,7 +12621,7 @@ var init_wall_owned = __esm(() => {
|
|
|
12595
12621
|
});
|
|
12596
12622
|
|
|
12597
12623
|
// ../../loki-ts/src/util/app_probe.ts
|
|
12598
|
-
import { spawnSync as
|
|
12624
|
+
import { spawnSync as spawnSync6 } from "child_process";
|
|
12599
12625
|
import { existsSync as existsSync29, mkdirSync as mkdirSync18, readFileSync as readFileSync38, renameSync as renameSync11, writeFileSync as writeFileSync21 } from "fs";
|
|
12600
12626
|
import { join as join48 } from "path";
|
|
12601
12627
|
function readJson4(p) {
|
|
@@ -12610,7 +12636,7 @@ function stopApp(repoDir, opts = {}) {
|
|
|
12610
12636
|
const runner = opts.runnerPath ?? join48(REPO_ROOT, "autonomy", "app-runner.sh");
|
|
12611
12637
|
if (!existsSync29(runner) || !existsSync29(join48(repoDir, ".loki", "app-runner", "app.pid")))
|
|
12612
12638
|
return;
|
|
12613
|
-
|
|
12639
|
+
spawnSync6("bash", ["-c", STOP, "app-probe", repoDir, runner], { cwd: repoDir, env: plainTestEnv(), timeout: opts.timeoutMs ?? 60000, killSignal: "SIGKILL", stdio: "ignore" });
|
|
12614
12640
|
}
|
|
12615
12641
|
async function appProbe(repoDir, lokiDir2, opts = {}) {
|
|
12616
12642
|
const timeoutMs = opts.timeoutMs ?? 60000, runner = opts.runnerPath ?? join48(REPO_ROOT, "autonomy", "app-runner.sh");
|
|
@@ -12618,7 +12644,7 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
|
|
|
12618
12644
|
const t0 = Date.now();
|
|
12619
12645
|
const mk2 = (name, result, reason) => ({ name, cmd: "autonomy/app-runner.sh", result, duration_s: (Date.now() - t0) / 1000, reason });
|
|
12620
12646
|
const sh = (script) => {
|
|
12621
|
-
const r =
|
|
12647
|
+
const r = spawnSync6("bash", ["-c", script, "app-probe", repoDir, runner], { cwd: repoDir, env: { ...plainTestEnv(), ...opts.env ?? {} }, encoding: "utf8", timeout: timeoutMs, killSignal: "SIGKILL", stdio: ["ignore", "pipe", "ignore"] });
|
|
12622
12648
|
return { out: r.stdout ?? "", status: r.error ? null : r.status };
|
|
12623
12649
|
};
|
|
12624
12650
|
let pid = null, url = null;
|
|
@@ -12663,7 +12689,7 @@ async function functionalVerify(opts, url, dir, lokiDir2, timeoutMs) {
|
|
|
12663
12689
|
return res("not_run", "python3 or functional-verify.py unavailable");
|
|
12664
12690
|
const specFile = join48(dir, "spec.txt");
|
|
12665
12691
|
writeFileSync21(specFile, opts.specText ?? "");
|
|
12666
|
-
const r =
|
|
12692
|
+
const r = spawnSync6(py, ["-I", script, specFile, url], { env: plainTestEnv(), encoding: "utf8", timeout: timeoutMs, killSignal: "SIGKILL", stdio: ["ignore", "pipe", "ignore"] });
|
|
12667
12693
|
let out2 = null;
|
|
12668
12694
|
try {
|
|
12669
12695
|
const v = JSON.parse(r.stdout ?? "");
|
|
@@ -14569,7 +14595,7 @@ var readJson5 = (p) => {
|
|
|
14569
14595
|
var init_conventions = () => {};
|
|
14570
14596
|
|
|
14571
14597
|
// ../../loki-ts/src/engine10/stages/wall.ts
|
|
14572
|
-
import { spawnSync as
|
|
14598
|
+
import { spawnSync as spawnSync7 } from "child_process";
|
|
14573
14599
|
import { existsSync as existsSync38, mkdirSync as mkdirSync24, mkdtempSync as mkdtempSync11, readFileSync as readFileSync45, readdirSync as readdirSync18, rmSync as rmSync19, writeFileSync as writeFileSync27 } from "fs";
|
|
14574
14600
|
import { tmpdir as tmpdir12 } from "os";
|
|
14575
14601
|
import { dirname as dirname23, join as join58, relative as relative8 } from "path";
|
|
@@ -14589,7 +14615,7 @@ class RealBaseTestRunner {
|
|
|
14589
14615
|
const api = this.api === undefined ? loadProjectApi(repoDir) : this.api;
|
|
14590
14616
|
for (const f of files) {
|
|
14591
14617
|
const { cmd, args, interpreter, cwd } = commandFor(f, repoDir, api);
|
|
14592
|
-
const r =
|
|
14618
|
+
const r = spawnSync7(cmd, f.runner === "pytest" ? [...args, "-rfE"] : args, { cwd, encoding: "utf8", timeout: Math.max(1000, this.timeoutMs), env: plainTestEnv() });
|
|
14593
14619
|
const status = r.error ? null : r.status;
|
|
14594
14620
|
const result = classify(f, status, stripAnsi(`${r.stdout ?? ""}
|
|
14595
14621
|
${r.stderr ?? ""}`), repoDir, interpreter);
|
|
@@ -16136,6 +16162,7 @@ var init_seal = __esm(() => {
|
|
|
16136
16162
|
events_sha256: sha2562(existsSync45(eventsPath) ? readFileSync53(eventsPath) : ""),
|
|
16137
16163
|
...await sealEvidence(ctx.repoDir, ctx.runDir, o, notProven, signal, ctx.emit),
|
|
16138
16164
|
log_seal: true,
|
|
16165
|
+
toolchain: collectToolchain(),
|
|
16139
16166
|
...receiptBlock(process.env, cost.usd, cost.unmetered === true, totalS),
|
|
16140
16167
|
...reviewReceipt(ctx.provider, xr).review ? { review: reviewReceipt(ctx.provider, xr).review } : {},
|
|
16141
16168
|
...mp ? { mutation_proof: mp.line, mutation_outcome: mp.outcome } : {},
|
|
@@ -16294,12 +16321,10 @@ function compositeHash(r) {
|
|
|
16294
16321
|
const { composite_sha256: _c, verification: _v, ...body } = r;
|
|
16295
16322
|
return sha3(canonicalJson(body));
|
|
16296
16323
|
}
|
|
16297
|
-
var COMPOSITE_SCHEMA = "loki.v10.composite/1",
|
|
16324
|
+
var COMPOSITE_SCHEMA = "loki.v10.composite/1", toolchainProblem = (t) => isObj10(t) && Object.keys(t).length === TOOLCHAIN_KEYS.length && TOOLCHAIN_KEYS.every((k) => t[k] === null || typeof t[k] === "string") ? null : "toolchain section is malformed", slugOf = (repo) => repo.replace(/\//g, "__"), isComposite = (r) => r["schema"] === COMPOSITE_SCHEMA, relOk = (p) => p !== "" && !p.startsWith("/") && !p.split("/").includes("..");
|
|
16298
16325
|
var init_composite_seal = __esm(() => {
|
|
16299
16326
|
init_receipt_signer();
|
|
16300
|
-
init_check_result();
|
|
16301
16327
|
init_seal_group();
|
|
16302
|
-
TOOLCHAIN_KEYS = ["bun", "node", "python3", "git"];
|
|
16303
16328
|
});
|
|
16304
16329
|
|
|
16305
16330
|
// ../../loki-ts/src/engine10/keys_cmd.ts
|