loki-mode 11.17.74 → 11.17.76
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/dashboard/__init__.py +1 -1
- package/docs/CLI-REFERENCE.md +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/docs/v10/FAILURE-CLASSES.md +19 -0
- package/docs/v10/PROGRESS.md +6 -0
- package/loki-ts/dist/loki.js +1212 -1212
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/packages/control-plane/dist/server.js +462 -359
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/web-app/dist/assets/{AdminPage-BMEz6PjD.js → AdminPage-C9CQBRCv.js} +1 -1
- package/web-app/dist/assets/{Avatar-CWqr7n5f.js → Avatar-BhmBNUPT.js} +1 -1
- package/web-app/dist/assets/{Badge-0HwtDygF.js → Badge-BvCq2-AU.js} +1 -1
- package/web-app/dist/assets/{Button-9dckZRDN.js → Button-TBmtKOqA.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-nYMuXSfl.js → CockpitPage-BO-zbB8z.js} +1 -1
- package/web-app/dist/assets/{ComparePage-Bc5srye5.js → ComparePage-CKscZK_O.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-BkDMHZsx.js → ErrorBoundary-BrkeH2Y3.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-M8zrEQxG.js → EvidenceReceiptPanel-f9uCX3yS.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-MvOtqrJO.js → GitHubIssuesPanel-CAqtVRHw.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-Cx6sFkSQ.js → GitHubPRsPanel-Jtx_ikWN.js} +1 -1
- package/web-app/dist/assets/{HomePage-KoGFVyhn.js → HomePage-_mPIzGn9.js} +2 -2
- package/web-app/dist/assets/{LoginPage-BJKuRfBJ.js → LoginPage-Cd92GhII.js} +1 -1
- package/web-app/dist/assets/{MagicPage-CH19MKyX.js → MagicPage-BmIqtGm5.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-CTiPy6uL.js → MetricsPage-3CfsaG_m.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-B3x9Admx.js → NotFoundPage-Br-g9AbW.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-B7NMYrmn.js → ProjectPage-Dx2AA5Y7.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-BNbo3wR3.js → ProjectsPage-DLHDbZoy.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-Dk9w3rKx.js → SettingsPage-D94kuRCH.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-Dk7LBonS.js → ShowcasePage-CItGSA7Y.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-FTbJ_2Hn.js → SystemSettingsPage-DecZOv_a.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-CdKmEVIO.js → TeamsPage-e0AUkZug.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-Du6EHrwu.js → TemplatesPage-CRUokO5z.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-BTlTI6D7.js → TerminalOutput-BDmhduwO.js} +1 -1
- package/web-app/dist/assets/{activity-BXuoHaM2.js → activity-D8ql1RlC.js} +1 -1
- package/web-app/dist/assets/{bell-DCDgirjw.js → bell-orReNr4N.js} +1 -1
- package/web-app/dist/assets/{bot-vJgiSrdQ.js → bot-CHD-p3yx.js} +1 -1
- package/web-app/dist/assets/{check-D-RGuqkl.js → check-CoV5lgtT.js} +1 -1
- package/web-app/dist/assets/{chevron-left-NKl5Cd-R.js → chevron-left-BNTcjUYJ.js} +1 -1
- package/web-app/dist/assets/{circle-alert-ByXEu_ry.js → circle-alert-Ctw93lag.js} +1 -1
- package/web-app/dist/assets/{clock-sHF7TkaL.js → clock-ghwe17Mr.js} +1 -1
- package/web-app/dist/assets/{cloud-D6mqiMKo.js → cloud-CPdhMe5M.js} +1 -1
- package/web-app/dist/assets/{code-xml-huk-YFT0.js → code-xml-D_ls460O.js} +1 -1
- package/web-app/dist/assets/{database-BOlnZ1VP.js → database--txjFRm7.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-BkQRFa0q.js → dollar-sign-yBTfA9B-.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-ugbZnTSY.js → file-code-corner-flbM-wFK.js} +1 -1
- package/web-app/dist/assets/{file-plus-C36sokvh.js → file-plus-ZqP1rdyQ.js} +1 -1
- package/web-app/dist/assets/{globe-CJQelTw1.js → globe-BxvmypwQ.js} +1 -1
- package/web-app/dist/assets/{hammer-DPzU4Wtq.js → hammer-UCzYuJUR.js} +1 -1
- package/web-app/dist/assets/{index-CmNcswQv.js → index-CuPW6Ff_.js} +3 -3
- package/web-app/dist/assets/{layers-DzMH-GEN.js → layers-DOUrmTFo.js} +1 -1
- package/web-app/dist/assets/{loader-circle-BNbNqvck.js → loader-circle-XV4GqxO0.js} +1 -1
- package/web-app/dist/assets/{lock-9PCIcJ6T.js → lock-Bp3KTqJq.js} +1 -1
- package/web-app/dist/assets/{package-j3aJqney.js → package-BPNFJPhi.js} +1 -1
- package/web-app/dist/assets/{plus-DGAY2LNf.js → plus-D5AJ9CbB.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-BBJiyS_M.js → refresh-cw-MiVr91M1.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-BNLXFero.js → rotate-ccw-Bc97bvIq.js} +1 -1
- package/web-app/dist/assets/{scroll-text-CGG6Enap.js → scroll-text-DC1RvHx-.js} +1 -1
- package/web-app/dist/assets/{server-Bv6QDqpn.js → server-CSA-j7xn.js} +1 -1
- package/web-app/dist/assets/{shield-alert-BFJHSdqK.js → shield-alert-ubbkSf0j.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-BGbIHMwH.js → thumbs-up-CxpcA4EK.js} +1 -1
- package/web-app/dist/assets/{trash-2-C7mlnJL3.js → trash-2-Bh1Pdz1Z.js} +1 -1
- package/web-app/dist/assets/{trending-down-BbxICDz5.js → trending-down-isclw9oO.js} +1 -1
- package/web-app/dist/assets/{trending-up-DQqCw2fH.js → trending-up-CHGt_Ghb.js} +1 -1
- package/web-app/dist/assets/{upload-SWiggmcJ.js → upload-DEdgXqPK.js} +1 -1
- package/web-app/dist/assets/{usePolling-CTxzJty2.js → usePolling-6K1dXGbq.js} +1 -1
- package/web-app/dist/assets/{user-DPVl5QyH.js → user-BsWjcTD2.js} +1 -1
- package/web-app/dist/index.html +1 -1
|
@@ -9894,13 +9894,104 @@ var init_stop_restore = __esm(() => {
|
|
|
9894
9894
|
});
|
|
9895
9895
|
|
|
9896
9896
|
// ../../loki-ts/src/util/base_guard.ts
|
|
9897
|
+
import { existsSync as existsSync24, readdirSync as readdirSync15, readFileSync as readFileSync30, readlinkSync, realpathSync as realpathSync17, symlinkSync } from "fs";
|
|
9898
|
+
import { basename as basename13, join as join39, relative as relative3, resolve as resolve13, sep as sep11 } from "path";
|
|
9899
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
9900
|
+
function insideAny(p, roots) {
|
|
9901
|
+
const under = (q) => roots.some((r) => q === r || q.startsWith(r + sep11));
|
|
9902
|
+
if (under(resolve13(p)))
|
|
9903
|
+
return true;
|
|
9904
|
+
try {
|
|
9905
|
+
return under(realpathSync17(p));
|
|
9906
|
+
} catch {
|
|
9907
|
+
return false;
|
|
9908
|
+
}
|
|
9909
|
+
}
|
|
9910
|
+
function namedPaths(file, text2) {
|
|
9911
|
+
const out2 = text2.split(/\r?\n/).map((l) => l.trim()).filter((l) => l !== "");
|
|
9912
|
+
if (basename13(file) !== "direct_url.json")
|
|
9913
|
+
return out2;
|
|
9914
|
+
const url = JSON.parse(text2).url;
|
|
9915
|
+
return typeof url === "string" && url.startsWith("file:") ? [...out2, fileURLToPath4(url)] : out2;
|
|
9916
|
+
}
|
|
9917
|
+
function depsSeeHead(pkgDir, repoDir) {
|
|
9918
|
+
let roots;
|
|
9919
|
+
try {
|
|
9920
|
+
roots = [...new Set([resolve13(repoDir), realpathSync17(repoDir)])];
|
|
9921
|
+
} catch {
|
|
9922
|
+
return true;
|
|
9923
|
+
}
|
|
9924
|
+
let seen = 0;
|
|
9925
|
+
const walk = (dir, own) => {
|
|
9926
|
+
for (const e of readdirSync15(dir, { withFileTypes: true })) {
|
|
9927
|
+
if (++seen > WALK_BOUND)
|
|
9928
|
+
return true;
|
|
9929
|
+
const p = join39(dir, e.name);
|
|
9930
|
+
if (e.isSymbolicLink()) {
|
|
9931
|
+
const t = resolve13(dir, readlinkSync(p));
|
|
9932
|
+
let rt = t;
|
|
9933
|
+
try {
|
|
9934
|
+
rt = realpathSync17(t);
|
|
9935
|
+
} catch {}
|
|
9936
|
+
if (insideAny(t, roots) && !own.some((r) => rt === r || rt.startsWith(r + sep11)))
|
|
9937
|
+
return true;
|
|
9938
|
+
} else if (e.isDirectory()) {
|
|
9939
|
+
if (walk(p, own))
|
|
9940
|
+
return true;
|
|
9941
|
+
} else if (REPO_LINK_FILE.test(e.name)) {
|
|
9942
|
+
const text2 = readFileSync30(p, "utf8");
|
|
9943
|
+
if (roots.some((r) => text2.includes(r)) || namedPaths(p, text2).some((n2) => insideAny(n2, roots)))
|
|
9944
|
+
return true;
|
|
9945
|
+
}
|
|
9946
|
+
}
|
|
9947
|
+
return false;
|
|
9948
|
+
};
|
|
9949
|
+
try {
|
|
9950
|
+
return ["node_modules", ".venv"].some((d) => {
|
|
9951
|
+
try {
|
|
9952
|
+
const top = join39(pkgDir, d);
|
|
9953
|
+
return walk(top, [...new Set([resolve13(top), realpathSync17(top)])]);
|
|
9954
|
+
} catch (e) {
|
|
9955
|
+
if (e.code === "ENOENT")
|
|
9956
|
+
return false;
|
|
9957
|
+
throw e;
|
|
9958
|
+
}
|
|
9959
|
+
});
|
|
9960
|
+
} catch {
|
|
9961
|
+
return true;
|
|
9962
|
+
}
|
|
9963
|
+
}
|
|
9964
|
+
async function zeroOnBase(cands, baseDir, repoDir, run, note) {
|
|
9965
|
+
const zero = [];
|
|
9966
|
+
for (const c of cands) {
|
|
9967
|
+
const src = join39(repoDir, relative3(baseDir, c.cwd));
|
|
9968
|
+
if (depsSeeHead(src, repoDir))
|
|
9969
|
+
continue;
|
|
9970
|
+
for (const d of ["node_modules", ".venv"]) {
|
|
9971
|
+
try {
|
|
9972
|
+
if (existsSync24(join39(src, d)) && !existsSync24(join39(c.cwd, d)))
|
|
9973
|
+
symlinkSync(join39(src, d), join39(c.cwd, d));
|
|
9974
|
+
} catch {}
|
|
9975
|
+
}
|
|
9976
|
+
const b = await run(c), last = c.args[c.args.length - 1] ?? "";
|
|
9977
|
+
const k = classifyCheck({ kind: "test", ok: b.ok, cut: b.cut, missing: b.missing, out: b.out, ...goRunner(c.cmd, c.args), path: /\.[cm]?[jt]s$/.test(last) ? last : undefined });
|
|
9978
|
+
if (k.result === "not_run" && k.n === 0 && !b.cut && !b.missing) {
|
|
9979
|
+
zero.push(c.name);
|
|
9980
|
+
note(c.name);
|
|
9981
|
+
}
|
|
9982
|
+
}
|
|
9983
|
+
return zero;
|
|
9984
|
+
}
|
|
9985
|
+
var WALK_BOUND = 50000, REPO_LINK_FILE;
|
|
9897
9986
|
var init_base_guard = __esm(() => {
|
|
9987
|
+
init_check_result();
|
|
9898
9988
|
init_run_status();
|
|
9899
9989
|
init_safe_git();
|
|
9990
|
+
REPO_LINK_FILE = /\.pth$|\.egg-link$|^direct_url\.json$|^__editable___.*_finder\.py$/;
|
|
9900
9991
|
});
|
|
9901
9992
|
|
|
9902
9993
|
// ../../loki-ts/src/features/speed/unit_mode.ts
|
|
9903
|
-
import { closeSync as closeSync7, constants, fstatSync as fstatSync5, lstatSync as lstatSync9, openSync as openSync7, readSync as readSync6, realpathSync as
|
|
9994
|
+
import { closeSync as closeSync7, constants, fstatSync as fstatSync5, lstatSync as lstatSync9, openSync as openSync7, readSync as readSync6, realpathSync as realpathSync18 } from "fs";
|
|
9904
9995
|
function readBounded(path) {
|
|
9905
9996
|
const l = lstatSync9(path);
|
|
9906
9997
|
if (l.isSymbolicLink() || !l.isFile() || l.size > MAX_SPEC_BYTES)
|
|
@@ -10719,14 +10810,15 @@ function failCount(out2) {
|
|
|
10719
10810
|
`).reverse().map((x) => x.trim()).find((x) => /^(?:=+ )?\d+ \w+.* in [\d.]+s|^Tests?:?\s+\d/.test(x)), m = /^(?:#|\u2139) fail (\d+)$/m.exec(out2);
|
|
10720
10811
|
return l ? n2(l, /(\d+) failed/) + n2(l, /(\d+) errors?/) : m ? +m[1] : null;
|
|
10721
10812
|
}
|
|
10722
|
-
function failIds(
|
|
10723
|
-
const ids = [...new Set(output.split(`
|
|
10813
|
+
function failIds(raw2) {
|
|
10814
|
+
const output = stripAnsi(raw2), ids = [...new Set(output.split(`
|
|
10724
10815
|
`).map((l) => ID_LINE.exec(l.trim())).flatMap((m) => m ? [(m.slice(1).find(Boolean) ?? "").trim()] : []).filter(Boolean))];
|
|
10725
10816
|
const c = failCount(output);
|
|
10726
10817
|
return c && ids.length >= c ? ids : [];
|
|
10727
10818
|
}
|
|
10728
10819
|
var ID_LINE;
|
|
10729
10820
|
var init_failures = __esm(() => {
|
|
10821
|
+
init_check_result();
|
|
10730
10822
|
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\s+(.+)|\u00d7\s+(.+?)(?:\s+\d+(?:\.\d+)?\s*m?s)?)$/;
|
|
10731
10823
|
});
|
|
10732
10824
|
|
|
@@ -10749,25 +10841,25 @@ var init_state = __esm(() => {
|
|
|
10749
10841
|
|
|
10750
10842
|
// ../../loki-ts/src/runner/repo_profile.ts
|
|
10751
10843
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
10752
|
-
import { existsSync as
|
|
10753
|
-
import { basename as
|
|
10844
|
+
import { existsSync as existsSync25, lstatSync as lstatSync10, readFileSync as readFileSync31, mkdirSync as mkdirSync14, readdirSync as readdirSync16, renameSync as renameSync9, rmSync as rmSync8, writeFileSync as writeFileSync17 } from "fs";
|
|
10845
|
+
import { basename as basename14, join as join40, resolve as resolve14, isAbsolute as isAbsolute4 } from "path";
|
|
10754
10846
|
function detectFormatters(repoDir) {
|
|
10755
10847
|
const out2 = [];
|
|
10756
|
-
const has = (...fs2) => fs2.some((f) =>
|
|
10757
|
-
const pp = read(
|
|
10848
|
+
const has = (...fs2) => fs2.some((f) => existsSync25(join40(repoDir, f)));
|
|
10849
|
+
const pp = read(join40(repoDir, "pyproject.toml")), pj = read(join40(repoDir, "package.json"));
|
|
10758
10850
|
if (/\[tool\.ruff/.test(pp) || has("ruff.toml", ".ruff.toml"))
|
|
10759
10851
|
out2.push({ tool: "ruff", argv: ["ruff", "format"], exts: /\.pyi?$/ });
|
|
10760
10852
|
let prettierKey = false;
|
|
10761
10853
|
try {
|
|
10762
10854
|
prettierKey = pj !== "" && "prettier" in JSON.parse(pj);
|
|
10763
10855
|
} catch {}
|
|
10764
|
-
const local =
|
|
10765
|
-
if ((prettierKey ||
|
|
10856
|
+
const local = join40(repoDir, "node_modules", ".bin", "prettier");
|
|
10857
|
+
if ((prettierKey || readdirSync16(repoDir).some((f) => /^(\.prettierrc(\.[a-z0-9]+)?|prettier\.config\.[cm]?[jt]s)$/.test(f))) && existsSync25(local))
|
|
10766
10858
|
out2.push({ tool: "prettier", argv: [local, "--write"], exts: /\.(?:[cm]?[jt]sx?|json|css|scss|md|ya?ml|html)$/ });
|
|
10767
10859
|
if (has("go.mod"))
|
|
10768
10860
|
out2.push({ tool: "gofmt", argv: ["gofmt", "-w"], exts: /\.go$/ });
|
|
10769
10861
|
if (has("rustfmt.toml", ".rustfmt.toml")) {
|
|
10770
|
-
const ed = /^\s*edition\s*=\s*"(\d+)"/m.exec(read(
|
|
10862
|
+
const ed = /^\s*edition\s*=\s*"(\d+)"/m.exec(read(join40(repoDir, "Cargo.toml")))?.[1];
|
|
10771
10863
|
out2.push({ tool: "rustfmt", argv: ["rustfmt", ...ed ? ["--edition", ed] : []], exts: /\.rs$/ });
|
|
10772
10864
|
}
|
|
10773
10865
|
return out2;
|
|
@@ -10776,7 +10868,7 @@ function runFormatters(repoDir, files, env) {
|
|
|
10776
10868
|
const fmts = detectFormatters(repoDir);
|
|
10777
10869
|
const mine = fmts.length ? files.filter((f) => {
|
|
10778
10870
|
try {
|
|
10779
|
-
return lstatSync10(
|
|
10871
|
+
return lstatSync10(join40(repoDir, f)).isFile();
|
|
10780
10872
|
} catch {
|
|
10781
10873
|
return false;
|
|
10782
10874
|
}
|
|
@@ -10789,7 +10881,7 @@ function runFormatters(repoDir, files, env) {
|
|
|
10789
10881
|
}
|
|
10790
10882
|
function loadProfile(repoDir) {
|
|
10791
10883
|
try {
|
|
10792
|
-
const p = JSON.parse(
|
|
10884
|
+
const p = JSON.parse(readFileSync31(commandProfilePath(repoDir), "utf8"));
|
|
10793
10885
|
return p?.version === 1 && Array.isArray(p.commands) && p.baseline ? p : null;
|
|
10794
10886
|
} catch {
|
|
10795
10887
|
return null;
|
|
@@ -10803,10 +10895,11 @@ function attribute(repoDir, baseSha, failing) {
|
|
|
10803
10895
|
return split(failing.map((f) => ({ ...f, base })), base.size);
|
|
10804
10896
|
}
|
|
10805
10897
|
function split(failing, known) {
|
|
10898
|
+
const unparsed = failing.filter((f) => !f.ids?.length && f.base.size > 0).length;
|
|
10806
10899
|
const pre = failing.filter((f) => f.eligible && f.ids?.length && f.ids.every((i) => f.base.has(i)));
|
|
10807
10900
|
const introduced = failing.filter((f) => !pre.includes(f)).map((f) => f.name);
|
|
10808
10901
|
if (pre.length === 0)
|
|
10809
|
-
return { preExistingChecks: [], preExistingIds: [], introducedChecks: introduced, line: `baseline: ${known} known failure(s) before this run; none of the failing checks match them, ${introduced.length} introduced (blocking)` };
|
|
10902
|
+
return { preExistingChecks: [], preExistingIds: [], introducedChecks: introduced, line: `baseline: ${known} known failure(s) before this run; ${unparsed ? `head failure ids unparseable for ${unparsed} failing check(s), cannot compare` : "none of the failing checks match them"}, ${introduced.length} introduced (blocking)` };
|
|
10810
10903
|
return {
|
|
10811
10904
|
preExistingChecks: pre.map((f) => f.name),
|
|
10812
10905
|
preExistingIds: pre.flatMap((f) => f.ids ?? []),
|
|
@@ -10890,9 +10983,9 @@ async function staticPreExisting(tool, prefix, files, io) {
|
|
|
10890
10983
|
}
|
|
10891
10984
|
return attributeStatic(tool, head.out, baseOut, 1).preExisting;
|
|
10892
10985
|
}
|
|
10893
|
-
var commandProfilePath = (repoDir) =>
|
|
10986
|
+
var commandProfilePath = (repoDir) => join40(repoDir, ".loki", "state", "repo-profile.json"), read = (p) => {
|
|
10894
10987
|
try {
|
|
10895
|
-
return
|
|
10988
|
+
return readFileSync31(p, "utf8");
|
|
10896
10989
|
} catch {
|
|
10897
10990
|
return "";
|
|
10898
10991
|
}
|
|
@@ -10938,14 +11031,14 @@ var init_context = __esm(() => {
|
|
|
10938
11031
|
});
|
|
10939
11032
|
|
|
10940
11033
|
// ../../loki-ts/src/util/steer.ts
|
|
10941
|
-
import { appendFileSync as appendFileSync2, closeSync as closeSync8, constants as constants2, fstatSync as fstatSync6, readdirSync as
|
|
11034
|
+
import { appendFileSync as appendFileSync2, closeSync as closeSync8, constants as constants2, fstatSync as fstatSync6, readdirSync as readdirSync17, lstatSync as lstatSync11, mkdirSync as mkdirSync15, linkSync as linkSync2, openSync as openSync8, readFileSync as readFileSync32, readSync as readSync7, renameSync as renameSync10, statSync as statSync16, lutimesSync, rmSync as rmSync9, unlinkSync as unlinkSync6, writeFileSync as writeFileSync18, existsSync as existsSync26 } from "fs";
|
|
10942
11035
|
import { createHash as createHash9, randomBytes as randomBytes4 } from "crypto";
|
|
10943
|
-
import { basename as
|
|
11036
|
+
import { basename as basename15, join as join41 } from "path";
|
|
10944
11037
|
function archiveTo(logs, prefix, src, link = linkSync2, onLinked) {
|
|
10945
11038
|
for (let i = 0;; i++) {
|
|
10946
11039
|
const name = i === 0 ? `${prefix}.md` : `${prefix}-${i}.md`;
|
|
10947
11040
|
try {
|
|
10948
|
-
link(src,
|
|
11041
|
+
link(src, join41(logs, name));
|
|
10949
11042
|
} catch (e) {
|
|
10950
11043
|
const code = e.code;
|
|
10951
11044
|
if (code === "EEXIST")
|
|
@@ -10953,7 +11046,7 @@ function archiveTo(logs, prefix, src, link = linkSync2, onLinked) {
|
|
|
10953
11046
|
if (code !== "EPERM" && code !== "ENOTSUP" && code !== "EXDEV" && code !== "EMLINK")
|
|
10954
11047
|
throw e;
|
|
10955
11048
|
const name2 = `${prefix}-${randomBytes4(4).toString("hex")}.md`;
|
|
10956
|
-
renameSync10(src,
|
|
11049
|
+
renameSync10(src, join41(logs, name2));
|
|
10957
11050
|
onLinked?.(name2);
|
|
10958
11051
|
return name2;
|
|
10959
11052
|
}
|
|
@@ -10968,14 +11061,14 @@ function orphanAlreadyArchived(logs, claim) {
|
|
|
10968
11061
|
const c = lstatSync11(claim);
|
|
10969
11062
|
if (!c.isFile())
|
|
10970
11063
|
return false;
|
|
10971
|
-
for (const a of
|
|
11064
|
+
for (const a of readdirSync17(logs)) {
|
|
10972
11065
|
if (!/^human-input-.*\.md$/.test(a))
|
|
10973
11066
|
continue;
|
|
10974
11067
|
try {
|
|
10975
|
-
const s = statSync16(
|
|
11068
|
+
const s = statSync16(join41(logs, a));
|
|
10976
11069
|
if (s.ino !== c.ino || s.dev !== c.dev)
|
|
10977
11070
|
continue;
|
|
10978
|
-
if (/^human-input-(ORPHAN|REJECTED)-/.test(a) ||
|
|
11071
|
+
if (/^human-input-(ORPHAN|REJECTED)-/.test(a) || existsSync26(appliedMarker(logs, a)))
|
|
10979
11072
|
return true;
|
|
10980
11073
|
} catch {}
|
|
10981
11074
|
}
|
|
@@ -10984,7 +11077,7 @@ function orphanAlreadyArchived(logs, claim) {
|
|
|
10984
11077
|
function sweepOrphans(logs, stamp2, unapplied, link, nowMs = Date.now()) {
|
|
10985
11078
|
let names;
|
|
10986
11079
|
try {
|
|
10987
|
-
names =
|
|
11080
|
+
names = readdirSync17(logs);
|
|
10988
11081
|
} catch {
|
|
10989
11082
|
return;
|
|
10990
11083
|
}
|
|
@@ -10992,7 +11085,7 @@ function sweepOrphans(logs, stamp2, unapplied, link, nowMs = Date.now()) {
|
|
|
10992
11085
|
for (const n2 of names)
|
|
10993
11086
|
if (n2.startsWith(".applied-") && !present.has(n2.slice(".applied-".length))) {
|
|
10994
11087
|
try {
|
|
10995
|
-
unlinkSync6(
|
|
11088
|
+
unlinkSync6(join41(logs, n2));
|
|
10996
11089
|
} catch {}
|
|
10997
11090
|
}
|
|
10998
11091
|
for (const n2 of names) {
|
|
@@ -11009,7 +11102,7 @@ function sweepOrphans(logs, stamp2, unapplied, link, nowMs = Date.now()) {
|
|
|
11009
11102
|
if (alive) {
|
|
11010
11103
|
let ageMs = 0;
|
|
11011
11104
|
try {
|
|
11012
|
-
ageMs = nowMs - statSync16(
|
|
11105
|
+
ageMs = nowMs - statSync16(join41(logs, n2)).mtimeMs;
|
|
11013
11106
|
} catch {
|
|
11014
11107
|
continue;
|
|
11015
11108
|
}
|
|
@@ -11017,11 +11110,11 @@ function sweepOrphans(logs, stamp2, unapplied, link, nowMs = Date.now()) {
|
|
|
11017
11110
|
continue;
|
|
11018
11111
|
}
|
|
11019
11112
|
try {
|
|
11020
|
-
if (orphanAlreadyArchived(logs,
|
|
11021
|
-
unlinkSync6(
|
|
11113
|
+
if (orphanAlreadyArchived(logs, join41(logs, n2))) {
|
|
11114
|
+
unlinkSync6(join41(logs, n2));
|
|
11022
11115
|
continue;
|
|
11023
11116
|
}
|
|
11024
|
-
archiveTo(logs, `human-input-ORPHAN-${stamp2}`,
|
|
11117
|
+
archiveTo(logs, `human-input-ORPHAN-${stamp2}`, join41(logs, n2), link);
|
|
11025
11118
|
unapplied("orphaned claim");
|
|
11026
11119
|
} catch (e) {
|
|
11027
11120
|
if (e.code === "ENOENT")
|
|
@@ -11033,17 +11126,17 @@ function sweepOrphans(logs, stamp2, unapplied, link, nowMs = Date.now()) {
|
|
|
11033
11126
|
function consumeSteer(repoDir, env = process.env, now2 = () => new Date, sink, hooks2) {
|
|
11034
11127
|
if (/^(0|false)$/i.test(env.LOKI_PROMPT_INJECTION ?? ""))
|
|
11035
11128
|
return null;
|
|
11036
|
-
const f =
|
|
11129
|
+
const f = join41(repoDir, ".loki", "HUMAN_INPUT.md");
|
|
11037
11130
|
const unapplied = (reason) => {
|
|
11038
11131
|
sink?.push({ rev: 0, source: null, actor: null, sha: "", at: now2().getTime(), unapplied: true, reason });
|
|
11039
11132
|
};
|
|
11040
11133
|
let fd = -1, claimed = "";
|
|
11041
11134
|
try {
|
|
11042
|
-
const logs =
|
|
11135
|
+
const logs = join41(repoDir, ".loki", "logs");
|
|
11043
11136
|
mkdirSync15(logs, { recursive: true });
|
|
11044
11137
|
const stamp2 = now2().toISOString().replace(/[-:]/g, "").replace(/\..*/, "");
|
|
11045
11138
|
sweepOrphans(logs, stamp2, unapplied, hooks2?.link, now2().getTime());
|
|
11046
|
-
claimed =
|
|
11139
|
+
claimed = join41(logs, `.claim-${process.pid}-${randomBytes4(6).toString("hex")}`);
|
|
11047
11140
|
try {
|
|
11048
11141
|
renameSync10(f, claimed);
|
|
11049
11142
|
} catch (e) {
|
|
@@ -11134,10 +11227,10 @@ function consumeSteer(repoDir, env = process.env, now2 = () => new Date, sink, h
|
|
|
11134
11227
|
} catch {
|
|
11135
11228
|
if (claimed) {
|
|
11136
11229
|
try {
|
|
11137
|
-
archiveTo(
|
|
11230
|
+
archiveTo(join41(repoDir, ".loki", "logs"), `human-input-${now2().toISOString().replace(/[-:]/g, "").replace(/\..*/, "")}`, claimed, hooks2?.link);
|
|
11138
11231
|
unapplied("logs dir unwritable or file unreadable");
|
|
11139
11232
|
} catch {
|
|
11140
|
-
unapplied(`steer stranded at .loki/logs/${
|
|
11233
|
+
unapplied(`steer stranded at .loki/logs/${basename15(claimed)}`);
|
|
11141
11234
|
}
|
|
11142
11235
|
} else
|
|
11143
11236
|
try {
|
|
@@ -11153,10 +11246,10 @@ function consumeSteer(repoDir, env = process.env, now2 = () => new Date, sink, h
|
|
|
11153
11246
|
}
|
|
11154
11247
|
}
|
|
11155
11248
|
function recordRevisions(repoDir, text2, archived, at) {
|
|
11156
|
-
const file =
|
|
11249
|
+
const file = join41(repoDir, ".loki", "intent-revisions.jsonl");
|
|
11157
11250
|
let last = 0;
|
|
11158
11251
|
try {
|
|
11159
|
-
for (const l of
|
|
11252
|
+
for (const l of readFileSync32(file, "utf8").split(`
|
|
11160
11253
|
`)) {
|
|
11161
11254
|
try {
|
|
11162
11255
|
last = Math.max(last, Number(JSON.parse(l).rev) || 0);
|
|
@@ -11210,7 +11303,7 @@ function staleAtSeal(repoDir, ctx) {
|
|
|
11210
11303
|
const frozen = ctx.outputs === undefined || ctx.outputs().wall !== undefined || ctx.wallSealed === true;
|
|
11211
11304
|
return [...new Set([...staleWallRevisions(ctx.intentRevisions, frozen ? ctx.timeline : []), ...late])];
|
|
11212
11305
|
}
|
|
11213
|
-
var STEER_MAX_BYTES, STEER_STAGES, STEER_CLAIM_MAX_AGE_MS, appliedMarker = (logs, archive) =>
|
|
11306
|
+
var STEER_MAX_BYTES, STEER_STAGES, STEER_CLAIM_MAX_AGE_MS, appliedMarker = (logs, archive) => join41(logs, `.applied-${archive}`), REV_HDR, STEER_REMEDY;
|
|
11214
11307
|
var init_steer = __esm(() => {
|
|
11215
11308
|
init_context();
|
|
11216
11309
|
STEER_MAX_BYTES = 1024 * 1024;
|
|
@@ -11222,20 +11315,20 @@ var init_steer = __esm(() => {
|
|
|
11222
11315
|
|
|
11223
11316
|
// ../../loki-ts/src/util/run_outputs.ts
|
|
11224
11317
|
import { createHash as createHash10 } from "crypto";
|
|
11225
|
-
import { existsSync as
|
|
11226
|
-
import { join as
|
|
11318
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync16, readdirSync as readdirSync18, readFileSync as readFileSync33, statSync as statSync17, writeFileSync as writeFileSync19 } from "fs";
|
|
11319
|
+
import { join as join42, resolve as resolve15 } from "path";
|
|
11227
11320
|
function intentRevisionsBlock(revs) {
|
|
11228
11321
|
const r = (revs ?? []).filter((r2) => r2.unapplied !== true).map(({ rev, source, actor, sha: sha2 }) => ({ rev, source, actor, sha: sha2 }));
|
|
11229
11322
|
return r.length ? { intent_revisions: r } : {};
|
|
11230
11323
|
}
|
|
11231
11324
|
function seededCorpusBlock(env = process.env) {
|
|
11232
|
-
const dir = env["LOKI_SEEDED_DEFECTS_DIR"] ||
|
|
11325
|
+
const dir = env["LOKI_SEEDED_DEFECTS_DIR"] || join42(REPO_ROOT, "benchmarks", "seeded-defects");
|
|
11233
11326
|
try {
|
|
11234
|
-
const bytes =
|
|
11327
|
+
const bytes = readFileSync33(join42(dir, "manifest.json")), version2 = createHash10("sha256").update(bytes).digest("hex");
|
|
11235
11328
|
const ids = (JSON.parse(bytes.toString("utf8")).defects ?? []).map((d) => d.id);
|
|
11236
11329
|
let rate = null;
|
|
11237
11330
|
try {
|
|
11238
|
-
const res = JSON.parse(
|
|
11331
|
+
const res = JSON.parse(readFileSync33(join42(dir, "results", "wrong-pass.json"), "utf8"));
|
|
11239
11332
|
const runs2 = res.manifest_sha256 === version2 && Array.isArray(res.runs) ? res.runs : [];
|
|
11240
11333
|
const complete = (o) => !!o && Object.keys(o).length === ids.length && ids.every((id) => typeof id === "string" && (o[id] === "SEALED" || o[id] === "NOT_SEALED"));
|
|
11241
11334
|
const top = runs2.filter((r) => r.setup === "top"), floor = runs2.filter((r) => r.setup === "floor");
|
|
@@ -11519,7 +11612,7 @@ var init_registry2 = __esm(() => {
|
|
|
11519
11612
|
|
|
11520
11613
|
// ../../loki-ts/src/features/receipt_dsse.ts
|
|
11521
11614
|
import { createPublicKey as createPublicKey3, sign as sign2, verify as verify3 } from "crypto";
|
|
11522
|
-
import { readFileSync as
|
|
11615
|
+
import { readFileSync as readFileSync34 } from "fs";
|
|
11523
11616
|
function pae(payloadType, body) {
|
|
11524
11617
|
const t = Buffer.from(payloadType, "utf8");
|
|
11525
11618
|
return Buffer.concat([Buffer.from(`DSSEv1 ${t.length} `), t, Buffer.from(` ${body.length} `), body]);
|
|
@@ -11596,7 +11689,7 @@ function verifyDsseReceipt(env, d) {
|
|
|
11596
11689
|
}
|
|
11597
11690
|
function runIdGuard(receiptPath, runId2) {
|
|
11598
11691
|
try {
|
|
11599
|
-
return envelopeRunIdProblem(JSON.parse(
|
|
11692
|
+
return envelopeRunIdProblem(JSON.parse(readFileSync34(receiptPath, "utf8")), runId2);
|
|
11600
11693
|
} catch {
|
|
11601
11694
|
return null;
|
|
11602
11695
|
}
|
|
@@ -11661,18 +11754,18 @@ var init_seal_drift = __esm(() => {
|
|
|
11661
11754
|
});
|
|
11662
11755
|
|
|
11663
11756
|
// ../../loki-ts/src/util/spec_file.ts
|
|
11664
|
-
import { isAbsolute as isAbsolute5, join as
|
|
11757
|
+
import { isAbsolute as isAbsolute5, join as join43, relative as relative4 } from "path";
|
|
11665
11758
|
function specReceiptBlock(env) {
|
|
11666
11759
|
const { LOKI_E10_SPEC_PATH: p, LOKI_E10_SPEC_SHA256: sha2 } = env;
|
|
11667
11760
|
if (!p || !sha2)
|
|
11668
11761
|
return {};
|
|
11669
|
-
const rel = isAbsolute5(p) && env.LOKI_E10_REPO_DIR ?
|
|
11762
|
+
const rel = isAbsolute5(p) && env.LOKI_E10_REPO_DIR ? relative4(env.LOKI_E10_REPO_DIR, p) : p;
|
|
11670
11763
|
return { spec: { path: rel, sha256: sha2 } };
|
|
11671
11764
|
}
|
|
11672
11765
|
var SPEC_DIR;
|
|
11673
11766
|
var init_spec_file = __esm(() => {
|
|
11674
11767
|
init_types();
|
|
11675
|
-
SPEC_DIR =
|
|
11768
|
+
SPEC_DIR = join43(".loki", "specs");
|
|
11676
11769
|
});
|
|
11677
11770
|
|
|
11678
11771
|
// ../../loki-ts/src/util/reviewer_brief.ts
|
|
@@ -11702,11 +11795,11 @@ var init_run_cap = __esm(() => {
|
|
|
11702
11795
|
});
|
|
11703
11796
|
|
|
11704
11797
|
// ../../loki-ts/src/util/mutation_proof.ts
|
|
11705
|
-
import { existsSync as
|
|
11798
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync17, mkdtempSync as mkdtempSync3, readFileSync as readFileSync35, rmSync as rmSync10, symlinkSync as symlinkSync2, writeFileSync as writeFileSync20 } from "fs";
|
|
11706
11799
|
import { tmpdir as tmpdir4 } from "os";
|
|
11707
|
-
import { basename as
|
|
11800
|
+
import { basename as basename16, dirname as dirname15, isAbsolute as isAbsolute6, join as join44, relative as relative5 } from "path";
|
|
11708
11801
|
function mutationProof(i) {
|
|
11709
|
-
const rels = i.wallFiles.map((f) => isAbsolute6(f.path) ?
|
|
11802
|
+
const rels = i.wallFiles.map((f) => isAbsolute6(f.path) ? relative5(i.repoDir, f.path) : f.path);
|
|
11710
11803
|
if (rels.length === 0)
|
|
11711
11804
|
return np("no Wall tests");
|
|
11712
11805
|
const tests = rels.flatMap((rel) => {
|
|
@@ -11722,28 +11815,28 @@ function mutationProof(i) {
|
|
|
11722
11815
|
const deadline = Date.now() + budgetS * 1000, remaining = () => deadline - Date.now();
|
|
11723
11816
|
let parent = null, wt = null, added = false;
|
|
11724
11817
|
try {
|
|
11725
|
-
parent = mkdtempSync3(
|
|
11726
|
-
wt =
|
|
11818
|
+
parent = mkdtempSync3(join44(tmpdir4(), "loki-mutproof-"));
|
|
11819
|
+
wt = join44(parent, "wt");
|
|
11727
11820
|
const add3 = git(i.repoDir, ["worktree", "add", "--detach", wt, i.baseSha], Math.max(1000, Math.min(30000, remaining())));
|
|
11728
|
-
added =
|
|
11821
|
+
added = existsSync28(wt) || add3.status === 0;
|
|
11729
11822
|
if (add3.status !== 0)
|
|
11730
11823
|
return np("could not create the base worktree");
|
|
11731
11824
|
for (const rel of rels) {
|
|
11732
|
-
const sealed =
|
|
11733
|
-
if (!
|
|
11825
|
+
const sealed = join44(i.runDir, "wall", basename16(rel)), src = existsSync28(sealed) ? sealed : join44(i.repoDir, rel);
|
|
11826
|
+
if (!existsSync28(src))
|
|
11734
11827
|
return np(`Wall file missing: ${rel}`);
|
|
11735
|
-
mkdirSync17(dirname15(
|
|
11736
|
-
writeFileSync20(
|
|
11828
|
+
mkdirSync17(dirname15(join44(wt, rel)), { recursive: true });
|
|
11829
|
+
writeFileSync20(join44(wt, rel), readFileSync35(src));
|
|
11737
11830
|
}
|
|
11738
11831
|
for (const rel of rels) {
|
|
11739
11832
|
const parts = rel.split("/").slice(0, -1);
|
|
11740
11833
|
for (let n2 = 0;n2 <= parts.length; n2++) {
|
|
11741
11834
|
const anc = parts.slice(0, n2).join("/");
|
|
11742
11835
|
for (const d of DEP_DIRS) {
|
|
11743
|
-
const src =
|
|
11744
|
-
if (
|
|
11836
|
+
const src = join44(i.repoDir, anc, d), dst = join44(wt, anc, d);
|
|
11837
|
+
if (existsSync28(src) && !existsSync28(dst)) {
|
|
11745
11838
|
try {
|
|
11746
|
-
|
|
11839
|
+
symlinkSync2(src, dst);
|
|
11747
11840
|
} catch {}
|
|
11748
11841
|
}
|
|
11749
11842
|
}
|
|
@@ -11887,14 +11980,14 @@ var init_shell = __esm(() => {
|
|
|
11887
11980
|
});
|
|
11888
11981
|
|
|
11889
11982
|
// ../../loki-ts/src/util/python.ts
|
|
11890
|
-
import { accessSync, constants as constants3, existsSync as
|
|
11983
|
+
import { accessSync, constants as constants3, existsSync as existsSync29, mkdtempSync as mkdtempSync4, readFileSync as readFileSync36, realpathSync as realpathSync19, rmSync as rmSync11, statSync as statSync18 } from "fs";
|
|
11891
11984
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
11892
11985
|
import { tmpdir as tmpdir5 } from "os";
|
|
11893
11986
|
async function findPython3() {
|
|
11894
11987
|
if (_pythonCache !== undefined)
|
|
11895
11988
|
return _pythonCache;
|
|
11896
11989
|
const homebrew = "/opt/homebrew/bin/python3.12";
|
|
11897
|
-
if (
|
|
11990
|
+
if (existsSync29(homebrew)) {
|
|
11898
11991
|
_pythonCache = homebrew;
|
|
11899
11992
|
return homebrew;
|
|
11900
11993
|
}
|
|
@@ -12245,7 +12338,7 @@ var init_wall_manifest = __esm(() => {
|
|
|
12245
12338
|
|
|
12246
12339
|
// ../../loki-ts/src/features/wall_manifest_wire.ts
|
|
12247
12340
|
import { createHash as createHash12 } from "crypto";
|
|
12248
|
-
import { basename as
|
|
12341
|
+
import { basename as basename17, dirname as dirname16 } from "path";
|
|
12249
12342
|
function blobEntries(ls) {
|
|
12250
12343
|
const out2 = [];
|
|
12251
12344
|
for (const raw2 of ls.toString("latin1").split("\x00")) {
|
|
@@ -12275,12 +12368,12 @@ function wallManifestFor(repoDir, tree, task, env = process.env) {
|
|
|
12275
12368
|
return null;
|
|
12276
12369
|
const low = task.toLowerCase().replace(/\\/g, "/");
|
|
12277
12370
|
const token = (n2) => new RegExp(`(?<![A-Za-z0-9_])${n2.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![A-Za-z0-9_])`).test(low);
|
|
12278
|
-
const dirModule = (e) => /^(index|__init__|mod|main)\.[^.]+$/.test(
|
|
12279
|
-
const matched = all.filter((e) => SOURCE.test(e.path) && (token(
|
|
12371
|
+
const dirModule = (e) => /^(index|__init__|mod|main)\.[^.]+$/.test(basename17(e.path)) && e.path.includes("/") && token(dirname16(e.path));
|
|
12372
|
+
const matched = all.filter((e) => SOURCE.test(e.path) && (token(basename17(e.path)) || token(e.path) || token(basename17(e.path).replace(/\.[^.]*$/, "")) || dirModule(e)));
|
|
12280
12373
|
const spans = (p) => [...low.matchAll(new RegExp(`(?<![A-Za-z0-9_])${p.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![A-Za-z0-9_])`, "g"))].map((m) => [m.index, m.index + m[0].length]);
|
|
12281
12374
|
const occ = new Map(matched.map((e) => [e, spans(e.path)]));
|
|
12282
12375
|
const exact = (e) => occ.get(e).some(([s, t]) => !matched.some((o) => o !== e && o.path.length > e.path.length && occ.get(o).some(([s2, t2]) => s2 <= s && t <= t2)));
|
|
12283
|
-
const byPath2 = matched.filter(exact).sort((a, b) => b.path.length - a.path.length), byBase = matched.filter((e) => !byPath2.includes(e) && token(
|
|
12376
|
+
const byPath2 = matched.filter(exact).sort((a, b) => b.path.length - a.path.length), byBase = matched.filter((e) => !byPath2.includes(e) && token(basename17(e.path)));
|
|
12284
12377
|
const named = [...byPath2, ...byBase, ...matched.filter((e) => !byPath2.includes(e) && !byBase.includes(e))].slice(0, MAX_NAMED);
|
|
12285
12378
|
const tests = all.filter((e) => TESTISH.test(e.path)).slice(0, MAX_FILES), listed = tests.filter((e) => !SOURCE.test(e.path));
|
|
12286
12379
|
const want = [...new Set([...all.filter((e) => CONFIG.test(e.path)), ...tests.filter((e) => SOURCE.test(e.path)), ...named])];
|
|
@@ -12337,9 +12430,9 @@ Example: test('name', () => { assert.strictEqual(fn(1), 2); }); Run: node --tes
|
|
|
12337
12430
|
|
|
12338
12431
|
// ../../loki-ts/src/util/holdout.ts
|
|
12339
12432
|
import { createHash as createHash13 } from "crypto";
|
|
12340
|
-
import { appendFileSync as appendFileSync3, copyFileSync as copyFileSync2, existsSync as
|
|
12433
|
+
import { appendFileSync as appendFileSync3, copyFileSync as copyFileSync2, existsSync as existsSync30, mkdirSync as mkdirSync18, readFileSync as readFileSync37, rmSync as rmSync12, writeFileSync as writeFileSync21 } from "fs";
|
|
12341
12434
|
import { tmpdir as tmpdir6 } from "os";
|
|
12342
|
-
import { basename as
|
|
12435
|
+
import { basename as basename18, join as join45, relative as relative6 } from "path";
|
|
12343
12436
|
function wallHoldoutRatio(env = process.env) {
|
|
12344
12437
|
if (env["LOKI_WALL_HOLDOUT"]?.trim() === "0")
|
|
12345
12438
|
return 0;
|
|
@@ -12370,32 +12463,32 @@ function stashHoldout(o) {
|
|
|
12370
12463
|
rmSync12(dir, { recursive: true, force: true });
|
|
12371
12464
|
mkdirSync18(dir, { recursive: true, mode: 448 });
|
|
12372
12465
|
const files = held.map((name) => {
|
|
12373
|
-
copyFileSync2(
|
|
12374
|
-
rmSync12(
|
|
12375
|
-
return { name, runner: o.runnerOf(name), sha256: sha2(
|
|
12466
|
+
copyFileSync2(join45(o.srcDir, name), join45(dir, name));
|
|
12467
|
+
rmSync12(join45(o.srcDir, name), { force: true });
|
|
12468
|
+
return { name, runner: o.runnerOf(name), sha256: sha2(readFileSync37(join45(dir, name), "utf8")) };
|
|
12376
12469
|
});
|
|
12377
|
-
writeFileSync21(
|
|
12470
|
+
writeFileSync21(join45(dir, MANIFEST), JSON.stringify({ targetDir: o.targetDir, files }));
|
|
12378
12471
|
return { dir, names: new Set(held) };
|
|
12379
12472
|
}
|
|
12380
12473
|
function stageHoldout(dir, repoDir) {
|
|
12381
12474
|
const put = [], tests = [], missing = [];
|
|
12382
12475
|
let man = null;
|
|
12383
12476
|
try {
|
|
12384
|
-
man = JSON.parse(
|
|
12477
|
+
man = JSON.parse(readFileSync37(join45(dir, MANIFEST), "utf8"));
|
|
12385
12478
|
} catch {}
|
|
12386
12479
|
if (!man)
|
|
12387
|
-
return { tests, missing: [`holdout store unreadable: ${
|
|
12480
|
+
return { tests, missing: [`holdout store unreadable: ${basename18(dir)}`], cleanup: () => {} };
|
|
12388
12481
|
mkdirSync18(man.targetDir, { recursive: true });
|
|
12389
12482
|
man.files.forEach((f, i) => {
|
|
12390
|
-
const src =
|
|
12391
|
-
if (!
|
|
12483
|
+
const src = join45(dir, f.name);
|
|
12484
|
+
if (!existsSync30(src) || sha2(readFileSync37(src, "utf8")) !== f.sha256) {
|
|
12392
12485
|
missing.push(`holdout ${i + 1} missing or altered`);
|
|
12393
12486
|
return;
|
|
12394
12487
|
}
|
|
12395
|
-
const dest =
|
|
12488
|
+
const dest = join45(man.targetDir, `loki_wall_holdout_${i + 1}${f.name.slice(f.name.indexOf("."))}`);
|
|
12396
12489
|
copyFileSync2(src, dest);
|
|
12397
12490
|
put.push(dest);
|
|
12398
|
-
tests.push({ runner: f.runner, path:
|
|
12491
|
+
tests.push({ runner: f.runner, path: relative6(repoDir, dest) });
|
|
12399
12492
|
});
|
|
12400
12493
|
return { tests, missing, cleanup: () => {
|
|
12401
12494
|
for (const p of put)
|
|
@@ -12405,11 +12498,11 @@ function stageHoldout(dir, repoDir) {
|
|
|
12405
12498
|
function recordHoldoutTriage(runDir, entry) {
|
|
12406
12499
|
try {
|
|
12407
12500
|
mkdirSync18(runDir, { recursive: true });
|
|
12408
|
-
appendFileSync3(
|
|
12501
|
+
appendFileSync3(join45(runDir, HOLDOUT_TRIAGE_FILE), JSON.stringify(entry) + `
|
|
12409
12502
|
`, { mode: 384 });
|
|
12410
12503
|
} catch {}
|
|
12411
12504
|
}
|
|
12412
|
-
var sha2 = (s) => createHash13("sha256").update(s).digest("hex"), WALL_HOLDOUT_DEFAULT_RATIO = 0.2, isHoldoutCheck = (name) => name.startsWith("holdout:"), holdoutDirFor = (runId2, repoDir) =>
|
|
12505
|
+
var sha2 = (s) => createHash13("sha256").update(s).digest("hex"), WALL_HOLDOUT_DEFAULT_RATIO = 0.2, isHoldoutCheck = (name) => name.startsWith("holdout:"), holdoutDirFor = (runId2, repoDir) => join45(tmpdir6(), `loki-e10-holdout-${sha2(`${runId2}:${repoDir}`).slice(0, 16)}`), MANIFEST = "manifest.json", WALL_HOLDOUT_MIN = 5, HOLDOUT_TRIAGE_FILE = "holdout-triage.jsonl";
|
|
12413
12506
|
var init_holdout = () => {};
|
|
12414
12507
|
|
|
12415
12508
|
// ../../loki-ts/src/runner/runner_errors.ts
|
|
@@ -12455,19 +12548,19 @@ var init_runner_errors = __esm(() => {
|
|
|
12455
12548
|
|
|
12456
12549
|
// ../../loki-ts/src/runner/load_owner.ts
|
|
12457
12550
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
12458
|
-
import { mkdtempSync as mkdtempSync5, realpathSync as
|
|
12551
|
+
import { mkdtempSync as mkdtempSync5, realpathSync as realpathSync20, rmSync as rmSync13 } from "fs";
|
|
12459
12552
|
import { tmpdir as tmpdir7 } from "os";
|
|
12460
|
-
import { basename as
|
|
12553
|
+
import { basename as basename19, extname as extname2, join as join46 } from "path";
|
|
12461
12554
|
function changedFilesNamed(out2, repoDir, changed) {
|
|
12462
12555
|
return changed.filter((f) => {
|
|
12463
|
-
if (out2.includes(f) || out2.includes(
|
|
12556
|
+
if (out2.includes(f) || out2.includes(join46(repoDir, f)))
|
|
12464
12557
|
return true;
|
|
12465
12558
|
const segs = f.split("/");
|
|
12466
12559
|
if (suffixes(segs, 2).some((x) => x !== f && bounded(out2, x, "(?![\\w-])")))
|
|
12467
12560
|
return true;
|
|
12468
12561
|
if (extname2(f) === ".go" && segs.length > 1 && suffixes(segs.slice(0, -1), 1).some((d) => new RegExp(`(?<=[\\w-])/${esc(d)}(?![\\w./-])`).test(out2)))
|
|
12469
12562
|
return true;
|
|
12470
|
-
const stem =
|
|
12563
|
+
const stem = basename19(f, extname2(f));
|
|
12471
12564
|
if (stem.length < 2 || stem === "index" || stem === "__init__")
|
|
12472
12565
|
return false;
|
|
12473
12566
|
return new RegExp(`(?<![\\w-])${esc(stem)}(?![\\w-])`).test(out2);
|
|
@@ -12477,7 +12570,7 @@ function loadSignature(out2, roots) {
|
|
|
12477
12570
|
let o = out2;
|
|
12478
12571
|
for (const r of roots.flatMap((x) => {
|
|
12479
12572
|
try {
|
|
12480
|
-
return [x,
|
|
12573
|
+
return [x, realpathSync20(x)];
|
|
12481
12574
|
} catch {
|
|
12482
12575
|
return [x];
|
|
12483
12576
|
}
|
|
@@ -12579,7 +12672,7 @@ async function loadErrorIsHarnessOwned(i) {
|
|
|
12579
12672
|
return false;
|
|
12580
12673
|
if (i.args.some((a) => changed.includes(a.replace(/^\.\//, ""))))
|
|
12581
12674
|
return false;
|
|
12582
|
-
const dir = mkdtempSync5(
|
|
12675
|
+
const dir = mkdtempSync5(join46(tmpdir7(), "e10-loadown-"));
|
|
12583
12676
|
const git3 = (args) => {
|
|
12584
12677
|
safeGit(i.repoDir, args, { stdio: "ignore" });
|
|
12585
12678
|
};
|
|
@@ -12611,7 +12704,7 @@ var init_load_owner = __esm(() => {
|
|
|
12611
12704
|
});
|
|
12612
12705
|
|
|
12613
12706
|
// ../../loki-ts/src/project_model/package_suite.ts
|
|
12614
|
-
import { join as
|
|
12707
|
+
import { join as join47 } from "path";
|
|
12615
12708
|
function packageSuiteSpecs(api) {
|
|
12616
12709
|
if (!isMultiRoot(api))
|
|
12617
12710
|
return null;
|
|
@@ -12621,29 +12714,32 @@ function packageSuiteSpecs(api) {
|
|
|
12621
12714
|
});
|
|
12622
12715
|
return specs.length ? specs : null;
|
|
12623
12716
|
}
|
|
12717
|
+
function suiteEnv(path) {
|
|
12718
|
+
return path ? { ...plainTestEnv(), PATH: path } : plainTestEnv();
|
|
12719
|
+
}
|
|
12624
12720
|
async function runPackageSuites(repoDir, signal, opts, checks, notProven) {
|
|
12625
12721
|
const api = loadProjectApi(repoDir), specs = packageSuiteSpecs(api);
|
|
12626
12722
|
if (!api || !specs)
|
|
12627
12723
|
return false;
|
|
12628
12724
|
for (const { name, cmd: cmd2, cwd, run: line2 } of specs) {
|
|
12629
12725
|
const started = Date.now();
|
|
12630
|
-
const r = await run(["bash", "-c", line2], { cwd:
|
|
12726
|
+
const r = await run(["bash", "-c", line2], { cwd: join47(repoDir, cwd), timeoutMs: opts.timeoutMs, env: suiteEnv(opts.path) });
|
|
12631
12727
|
const duration_s = (Date.now() - started) / 1000;
|
|
12632
12728
|
if (signal.aborted) {
|
|
12633
12729
|
checks.push({ name, cmd: cmd2, result: "not_run", duration_s });
|
|
12634
12730
|
notProven.add(`not run: ${name} (aborted)`);
|
|
12635
12731
|
continue;
|
|
12636
12732
|
}
|
|
12637
|
-
const out2 = `${r.stdout}
|
|
12638
|
-
${r.stderr}
|
|
12639
|
-
const lr = r.exitCode === 0 || !opts.baseSha ? undefined : await harnessLoadReason({ repoDir, baseSha: opts.baseSha, ...opts.skip ? { skip: opts.skip } : {}, out: out2, cmd: "bash", args: ["-c", line2], signal, cwd:
|
|
12733
|
+
const out2 = stripAnsi(`${r.stdout}
|
|
12734
|
+
${r.stderr}`);
|
|
12735
|
+
const lr = r.exitCode === 0 || !opts.baseSha ? undefined : await harnessLoadReason({ repoDir, baseSha: opts.baseSha, ...opts.skip ? { skip: opts.skip } : {}, out: out2, cmd: "bash", args: ["-c", line2], signal, cwd: join47(repoDir, cwd), env: suiteEnv(opts.path) });
|
|
12640
12736
|
if (lr) {
|
|
12641
12737
|
checks.push({ name, cmd: cmd2, result: "not_run", duration_s });
|
|
12642
12738
|
notProven.add(`${lr} (${name}; harness-owned)`);
|
|
12643
12739
|
continue;
|
|
12644
12740
|
}
|
|
12645
12741
|
const cls = classifyCheck({ kind: "test", ok: r.exitCode === 0, out: out2, ...goRunner(line2) });
|
|
12646
|
-
checks.push({ name, cmd: cmd2, result: cls.result, duration_s, ...cls.result === "fail" ? { ids: failIds(out2) } : {} });
|
|
12742
|
+
checks.push({ name, cmd: cmd2, result: cls.result, duration_s, ...cls.result === "fail" ? { ids: failIds(out2), excerpt: failureExcerpt(out2, repoDir) } : {} });
|
|
12647
12743
|
if (cls.result === "not_run")
|
|
12648
12744
|
notProven.add(`not run: ${name} (${cls.reason ?? NO_TESTS_REASON})`);
|
|
12649
12745
|
}
|
|
@@ -12682,8 +12778,8 @@ var init_install = __esm(() => {
|
|
|
12682
12778
|
});
|
|
12683
12779
|
|
|
12684
12780
|
// ../../loki-ts/src/features/runner_config.ts
|
|
12685
|
-
import { readFileSync as
|
|
12686
|
-
import { dirname as dirname17, join as
|
|
12781
|
+
import { readFileSync as readFileSync38 } from "fs";
|
|
12782
|
+
import { dirname as dirname17, join as join48, normalize as normalize2 } from "path";
|
|
12687
12783
|
function tomlKey2(s, i = 0, eq2 = true) {
|
|
12688
12784
|
const parts = [], ws = () => {
|
|
12689
12785
|
while (/\s/.test(s[i] ?? "x"))
|
|
@@ -12960,8 +13056,8 @@ function referenced(cfg, text2) {
|
|
|
12960
13056
|
}
|
|
12961
13057
|
const dir = dirname17(cfg), explicit = ROOT_DIR.exec(text2), roots = [dir];
|
|
12962
13058
|
if (explicit)
|
|
12963
|
-
roots.push("", ...explicit[1] ? [
|
|
12964
|
-
return [...raw2.flatMap((r) => r.startsWith("/") ? [normalize2(r.slice(1))] : roots.map((root) => normalize2(
|
|
13059
|
+
roots.push("", ...explicit[1] ? [join48(dir, explicit[1])] : []);
|
|
13060
|
+
return [...raw2.flatMap((r) => r.startsWith("/") ? [normalize2(r.slice(1))] : roots.map((root) => normalize2(join48(root, r.replace(/^<rootDir>\/?/, ""))))), ...patchedTargets(cfg, text2).map((t) => normalize2(join48(dir, t)))];
|
|
12965
13061
|
}
|
|
12966
13062
|
function runnerConfigNotes(repoDir, baseSha, head, changed, signal) {
|
|
12967
13063
|
const notes = new Set, ch = new Set(changed.map((c) => normalize2(c)));
|
|
@@ -13041,7 +13137,7 @@ var PKG_KEYS, RAW_CONFIGS, RUNNER_CONFIGS, DEP_MAPS, RUNNER_DEP, LOCAL_SPEC, dep
|
|
|
13041
13137
|
}
|
|
13042
13138
|
}, headText = (dir, f) => {
|
|
13043
13139
|
try {
|
|
13044
|
-
return
|
|
13140
|
+
return readFileSync38(join48(dir, f), "utf8");
|
|
13045
13141
|
} catch {
|
|
13046
13142
|
return "";
|
|
13047
13143
|
}
|
|
@@ -13081,19 +13177,19 @@ var init_runner_config = __esm(() => {
|
|
|
13081
13177
|
|
|
13082
13178
|
// ../../loki-ts/src/e10ext/assert_delta.ts
|
|
13083
13179
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
13084
|
-
import { mkdtempSync as mkdtempSync6, readFileSync as
|
|
13180
|
+
import { mkdtempSync as mkdtempSync6, readFileSync as readFileSync39, rmSync as rmSync14 } from "fs";
|
|
13085
13181
|
import { tmpdir as tmpdir8 } from "os";
|
|
13086
|
-
import { join as
|
|
13087
|
-
import { basename as
|
|
13182
|
+
import { join as join49 } from "path";
|
|
13183
|
+
import { basename as basename20 } from "path";
|
|
13088
13184
|
function classifyAssertDelta(inp) {
|
|
13089
|
-
const f =
|
|
13185
|
+
const f = basename20(inp.path);
|
|
13090
13186
|
if (!/^(test_.*|.*_test)\.py$/.test(f))
|
|
13091
13187
|
return WEAKENED;
|
|
13092
13188
|
if (inp.headCounts.run !== inp.baseCounts.run || inp.headCounts.skipped !== inp.baseCounts.skipped)
|
|
13093
13189
|
return WEAKENED;
|
|
13094
13190
|
let cwd = "";
|
|
13095
13191
|
try {
|
|
13096
|
-
cwd = mkdtempSync6(
|
|
13192
|
+
cwd = mkdtempSync6(join49(tmpdir8(), "loki-ad-"));
|
|
13097
13193
|
const raw2 = execFileSync4("python3", ["-I", "-c", PY], {
|
|
13098
13194
|
input: JSON.stringify({ path: inp.path, base: inp.base, head: inp.head, task: inp.task }),
|
|
13099
13195
|
cwd,
|
|
@@ -13124,7 +13220,7 @@ function assertDeltaNotes(repoDir, baseSha, headRef, path, task, baseCounts, hea
|
|
|
13124
13220
|
return null;
|
|
13125
13221
|
try {
|
|
13126
13222
|
const show = (ref) => safeGit(repoDir, ["show", `${ref}:${path}`]);
|
|
13127
|
-
const head = headRef ? show(headRef) :
|
|
13223
|
+
const head = headRef ? show(headRef) : readFileSync39(join49(repoDir, path), "utf8");
|
|
13128
13224
|
const r = classifyTestEdit(path, show(baseSha), head, task, baseCounts, headCounts);
|
|
13129
13225
|
return r[0]?.kind === "literal-only" ? r.map((e) => `assertion value changed (not shown to be required by the task): ${e.file}:${e.line} ${e.old} -> ${e.new}`) : null;
|
|
13130
13226
|
} catch {
|
|
@@ -13307,7 +13403,7 @@ var init_select = __esm(() => {
|
|
|
13307
13403
|
});
|
|
13308
13404
|
|
|
13309
13405
|
// ../../loki-ts/src/util/wall_owned.ts
|
|
13310
|
-
import { isAbsolute as isAbsolute7, join as
|
|
13406
|
+
import { isAbsolute as isAbsolute7, join as join50, relative as relative7 } from "path";
|
|
13311
13407
|
function failingLocations(raw2, cwd, repoDir) {
|
|
13312
13408
|
const out2 = raw2.replace(ANSI2, "").replace(/\r\n?/g, `
|
|
13313
13409
|
`), files = new Set;
|
|
@@ -13339,7 +13435,7 @@ function failingLocations(raw2, cwd, repoDir) {
|
|
|
13339
13435
|
}
|
|
13340
13436
|
if (errors2 === 0 || located !== errors2)
|
|
13341
13437
|
return null;
|
|
13342
|
-
return [...files].map((f) =>
|
|
13438
|
+
return [...files].map((f) => relative7(repoDir, isAbsolute7(f) ? f : join50(cwd, f)));
|
|
13343
13439
|
}
|
|
13344
13440
|
function wallOwnedFailure(raw2, cwd, repoDir, wall) {
|
|
13345
13441
|
const locs = failingLocations(raw2, cwd, repoDir);
|
|
@@ -13352,25 +13448,25 @@ var init_wall_owned = __esm(() => {
|
|
|
13352
13448
|
|
|
13353
13449
|
// ../../loki-ts/src/util/app_probe.ts
|
|
13354
13450
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
13355
|
-
import { existsSync as
|
|
13356
|
-
import { join as
|
|
13451
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync19, readFileSync as readFileSync40, renameSync as renameSync11, writeFileSync as writeFileSync22 } from "fs";
|
|
13452
|
+
import { join as join51 } from "path";
|
|
13357
13453
|
function readJson4(p) {
|
|
13358
13454
|
try {
|
|
13359
|
-
const v = JSON.parse(
|
|
13455
|
+
const v = JSON.parse(readFileSync40(p, "utf8"));
|
|
13360
13456
|
return v && typeof v === "object" ? v : null;
|
|
13361
13457
|
} catch {
|
|
13362
13458
|
return null;
|
|
13363
13459
|
}
|
|
13364
13460
|
}
|
|
13365
13461
|
function stopApp(repoDir, opts = {}) {
|
|
13366
|
-
const runner = opts.runnerPath ??
|
|
13367
|
-
if (!
|
|
13462
|
+
const runner = opts.runnerPath ?? join51(REPO_ROOT, "autonomy", "app-runner.sh");
|
|
13463
|
+
if (!existsSync31(runner) || !existsSync31(join51(repoDir, ".loki", "app-runner", "app.pid")))
|
|
13368
13464
|
return;
|
|
13369
13465
|
spawnSync6("bash", ["-c", STOP, "app-probe", repoDir, runner], { cwd: repoDir, env: plainTestEnv(), timeout: opts.timeoutMs ?? 60000, killSignal: "SIGKILL", stdio: "ignore" });
|
|
13370
13466
|
}
|
|
13371
13467
|
async function appProbe(repoDir, lokiDir2, opts = {}) {
|
|
13372
|
-
const timeoutMs = opts.timeoutMs ?? 60000, runner = opts.runnerPath ??
|
|
13373
|
-
const dir =
|
|
13468
|
+
const timeoutMs = opts.timeoutMs ?? 60000, runner = opts.runnerPath ?? join51(REPO_ROOT, "autonomy", "app-runner.sh");
|
|
13469
|
+
const dir = join51(repoDir, ".loki", "app-runner"), checks = [];
|
|
13374
13470
|
const t0 = Date.now();
|
|
13375
13471
|
const mk2 = (name, result, reason) => ({ name, cmd: "autonomy/app-runner.sh", result, duration_s: (Date.now() - t0) / 1000, reason });
|
|
13376
13472
|
const sh = (script) => {
|
|
@@ -13378,7 +13474,7 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
|
|
|
13378
13474
|
return { out: r.stdout ?? "", status: r.error ? null : r.status };
|
|
13379
13475
|
};
|
|
13380
13476
|
let pid = null, url = null;
|
|
13381
|
-
if (!
|
|
13477
|
+
if (!existsSync31(runner))
|
|
13382
13478
|
return { checks: [mk2("app boot", "not_run", "app-runner.sh not found"), mk2("http probe", "not_run", "app not booted")], pid, url };
|
|
13383
13479
|
try {
|
|
13384
13480
|
const b = sh(BOOT);
|
|
@@ -13388,9 +13484,9 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
|
|
|
13388
13484
|
return { checks, pid, url };
|
|
13389
13485
|
}
|
|
13390
13486
|
const ir = Number(m[1]), sr = Number(m[2]), hr = Number(m[3]);
|
|
13391
|
-
const pidTxt =
|
|
13487
|
+
const pidTxt = existsSync31(join51(dir, "app.pid")) ? readFileSync40(join51(dir, "app.pid"), "utf8").trim() : "";
|
|
13392
13488
|
pid = /^\d+$/.test(pidTxt) && sr >= 0 ? Number(pidTxt) : null;
|
|
13393
|
-
const st = readJson4(
|
|
13489
|
+
const st = readJson4(join51(dir, "state.json"));
|
|
13394
13490
|
url = typeof st?.["url"] === "string" ? st["url"] : null;
|
|
13395
13491
|
if (sr < 0) {
|
|
13396
13492
|
checks.push(mk2("app boot", "not_run", ir === 0 ? "app-runner detected no app" : "no runnable app detected or runtime missing"), mk2("http probe", "not_run", "app not booted"));
|
|
@@ -13401,7 +13497,7 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
|
|
|
13401
13497
|
return { checks, pid, url };
|
|
13402
13498
|
}
|
|
13403
13499
|
checks.push(mk2("app boot", "pass", "app process started"));
|
|
13404
|
-
const health = readJson4(
|
|
13500
|
+
const health = readJson4(join51(dir, "health.json"));
|
|
13405
13501
|
checks.push(hr === 0 && health?.["ok"] === true ? mk2("http probe", "pass", "health.json ok") : mk2("http probe", "fail", "app-runner health check failed"));
|
|
13406
13502
|
if (opts.specText !== undefined && checks[1]?.result === "pass" && url)
|
|
13407
13503
|
checks.push(await functionalVerify(opts, url, dir, lokiDir2, timeoutMs));
|
|
@@ -13414,10 +13510,10 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
|
|
|
13414
13510
|
async function functionalVerify(opts, url, dir, lokiDir2, timeoutMs) {
|
|
13415
13511
|
const t0 = Date.now();
|
|
13416
13512
|
const res = (result, reason) => ({ name: "functional verify", cmd: "autonomy/lib/functional-verify.py", result, duration_s: (Date.now() - t0) / 1000, reason });
|
|
13417
|
-
const py = await findPython3(), script = opts.verifyPath ??
|
|
13418
|
-
if (!py || !
|
|
13513
|
+
const py = await findPython3(), script = opts.verifyPath ?? join51(REPO_ROOT, "autonomy", "lib", "functional-verify.py");
|
|
13514
|
+
if (!py || !existsSync31(script))
|
|
13419
13515
|
return res("not_run", "python3 or functional-verify.py unavailable");
|
|
13420
|
-
const specFile =
|
|
13516
|
+
const specFile = join51(dir, "spec.txt");
|
|
13421
13517
|
writeFileSync22(specFile, opts.specText ?? "");
|
|
13422
13518
|
const r = spawnSync6(py, ["-I", script, specFile, url], { env: plainTestEnv(), encoding: "utf8", timeout: timeoutMs, killSignal: "SIGKILL", stdio: ["ignore", "pipe", "ignore"] });
|
|
13423
13519
|
let out2 = null;
|
|
@@ -13429,11 +13525,11 @@ async function functionalVerify(opts, url, dir, lokiDir2, timeoutMs) {
|
|
|
13429
13525
|
}
|
|
13430
13526
|
if (!out2 || r.status !== 0)
|
|
13431
13527
|
return res("not_run", "functional harness produced no result");
|
|
13432
|
-
const q =
|
|
13528
|
+
const q = join51(lokiDir2, "quality");
|
|
13433
13529
|
mkdirSync19(q, { recursive: true });
|
|
13434
|
-
const tmp =
|
|
13530
|
+
const tmp = join51(q, `functional-results.json.tmp.${process.pid}`);
|
|
13435
13531
|
writeFileSync22(tmp, JSON.stringify(out2, null, 2));
|
|
13436
|
-
renameSync11(tmp,
|
|
13532
|
+
renameSync11(tmp, join51(q, "functional-results.json"));
|
|
13437
13533
|
const s = String(out2["functional_status"] ?? "inconclusive");
|
|
13438
13534
|
return res(s === "verified" ? "pass" : s === "failed" ? "fail" : "not_run", `functional_status ${s}`);
|
|
13439
13535
|
}
|
|
@@ -13463,16 +13559,16 @@ app_runner_stop >/dev/null 2>&1
|
|
|
13463
13559
|
});
|
|
13464
13560
|
|
|
13465
13561
|
// ../../loki-ts/src/util/secure_scan.ts
|
|
13466
|
-
import { existsSync as
|
|
13562
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync20, mkdtempSync as mkdtempSync7, readFileSync as readFileSync41, realpathSync as realpathSync21, rmSync as rmSync15, statSync as statSync19, writeFileSync as writeFileSync23 } from "fs";
|
|
13467
13563
|
import { randomBytes as randomBytes5 } from "crypto";
|
|
13468
13564
|
import { tmpdir as tmpdir9 } from "os";
|
|
13469
|
-
import { basename as
|
|
13565
|
+
import { basename as basename21, dirname as dirname18, join as join52, resolve as resolve16, sep as sep12 } from "path";
|
|
13470
13566
|
function fail(error) {
|
|
13471
13567
|
return { ok: false, findings: [], error };
|
|
13472
13568
|
}
|
|
13473
13569
|
async function runSecureScan(targetDir, opts = {}) {
|
|
13474
|
-
const script = opts.scriptPath ??
|
|
13475
|
-
if (!
|
|
13570
|
+
const script = opts.scriptPath ?? join52(REPO_ROOT, "autonomy", "lib", "secure-scan.py");
|
|
13571
|
+
if (!existsSync32(script))
|
|
13476
13572
|
return fail(`secure-scan script not found: ${script}`);
|
|
13477
13573
|
const py = await findPython3();
|
|
13478
13574
|
if (!py)
|
|
@@ -13523,7 +13619,7 @@ function isWorkTreeRoot(dir) {
|
|
|
13523
13619
|
if (top === null)
|
|
13524
13620
|
return false;
|
|
13525
13621
|
try {
|
|
13526
|
-
return
|
|
13622
|
+
return realpathSync21(top.trim()) === realpathSync21(dir);
|
|
13527
13623
|
} catch {
|
|
13528
13624
|
return false;
|
|
13529
13625
|
}
|
|
@@ -13641,7 +13737,7 @@ async function scanAddedLines(repoDir, opts = {}) {
|
|
|
13641
13737
|
const skipped2 = [];
|
|
13642
13738
|
for (const p of untracked.split("\x00").filter(Boolean)) {
|
|
13643
13739
|
try {
|
|
13644
|
-
const st = statSync19(
|
|
13740
|
+
const st = statSync19(join52(repoDir, p));
|
|
13645
13741
|
if (!st.isFile())
|
|
13646
13742
|
continue;
|
|
13647
13743
|
if (st.size > MAX_ADDED_FILE_BYTES) {
|
|
@@ -13656,23 +13752,23 @@ async function scanAddedLines(repoDir, opts = {}) {
|
|
|
13656
13752
|
continue;
|
|
13657
13753
|
}
|
|
13658
13754
|
const lines2 = new Map;
|
|
13659
|
-
|
|
13755
|
+
readFileSync41(join52(repoDir, p), "utf8").split(`
|
|
13660
13756
|
`).forEach((t, i) => lines2.set(i + 1, t));
|
|
13661
13757
|
added.set(p, lines2);
|
|
13662
13758
|
} catch {}
|
|
13663
13759
|
}
|
|
13664
13760
|
if (added.size === 0)
|
|
13665
13761
|
return { ok: true, findings: skipped2 };
|
|
13666
|
-
const mirror = mkdtempSync7(
|
|
13762
|
+
const mirror = mkdtempSync7(join52(tmpdir9(), "loki-secure-added-"));
|
|
13667
13763
|
try {
|
|
13668
|
-
const root =
|
|
13764
|
+
const root = resolve16(mirror) + sep12;
|
|
13669
13765
|
const chunkMap = new Map;
|
|
13670
13766
|
const chunkRoot = `.loki-chunks-${randomBytes5(6).toString("hex")}`;
|
|
13671
13767
|
let chunkSeq = 0;
|
|
13672
13768
|
for (const [p, lines2] of added) {
|
|
13673
13769
|
if (lines2.size === 0)
|
|
13674
13770
|
continue;
|
|
13675
|
-
const dest =
|
|
13771
|
+
const dest = resolve16(mirror, p);
|
|
13676
13772
|
if (!dest.startsWith(root))
|
|
13677
13773
|
continue;
|
|
13678
13774
|
let max = 0;
|
|
@@ -13709,8 +13805,8 @@ async function scanAddedLines(repoDir, opts = {}) {
|
|
|
13709
13805
|
chunks.push(cur);
|
|
13710
13806
|
const whole = chunks.length === 1;
|
|
13711
13807
|
for (const c of chunks) {
|
|
13712
|
-
const rel = whole ? p :
|
|
13713
|
-
const out2 = whole ? dest :
|
|
13808
|
+
const rel = whole ? p : join52(chunkRoot, String(chunkSeq++), basename21(p));
|
|
13809
|
+
const out2 = whole ? dest : resolve16(mirror, rel);
|
|
13714
13810
|
if (!out2.startsWith(root))
|
|
13715
13811
|
break;
|
|
13716
13812
|
chunkMap.set(rel, { file: p, lines: c.orig });
|
|
@@ -13727,7 +13823,7 @@ async function scanAddedLines(repoDir, opts = {}) {
|
|
|
13727
13823
|
for (let f of r.findings) {
|
|
13728
13824
|
if (f.rule !== "secret-in-client-file")
|
|
13729
13825
|
continue;
|
|
13730
|
-
const c = chunkMap.get(f.file.split(
|
|
13826
|
+
const c = chunkMap.get(f.file.split(sep12).join("/"));
|
|
13731
13827
|
if (c)
|
|
13732
13828
|
f = { ...f, file: c.file, line: c.lines[f.line - 1] ?? f.line };
|
|
13733
13829
|
const kind = /A live (\S+)/.exec(f.message)?.[1] ?? "provider key";
|
|
@@ -13859,9 +13955,9 @@ var init_route_block = __esm(() => {
|
|
|
13859
13955
|
// ../../loki-ts/src/features/visual_evidence.ts
|
|
13860
13956
|
import { spawn as spawn8 } from "child_process";
|
|
13861
13957
|
import { createHash as createHash14, randomBytes as randomBytes6 } from "crypto";
|
|
13862
|
-
import { existsSync as
|
|
13958
|
+
import { existsSync as existsSync33, lstatSync as lstatSync12, mkdirSync as mkdirSync21, readdirSync as readdirSync19, readFileSync as readFileSync42, writeFileSync as writeFileSync24 } from "fs";
|
|
13863
13959
|
import { createServer } from "net";
|
|
13864
|
-
import { dirname as dirname19, isAbsolute as isAbsolute8, join as
|
|
13960
|
+
import { dirname as dirname19, isAbsolute as isAbsolute8, join as join53, normalize as normalize3, relative as relative8, sep as sep13 } from "path";
|
|
13865
13961
|
function routeFor(file) {
|
|
13866
13962
|
let r = file.replace(/^(?:.*?\/)?(?:app|pages|src|public)\//, "").replace(/^(?:routes|pages)\//, "");
|
|
13867
13963
|
r = r.replace(/\.(?:html|jsx|tsx|vue|svelte)$/, "").replace(/\/?(?:page|index|\+page)$/, "");
|
|
@@ -13871,7 +13967,7 @@ function hashScreens(runDir, rels) {
|
|
|
13871
13967
|
const out2 = [];
|
|
13872
13968
|
for (const rel of rels) {
|
|
13873
13969
|
try {
|
|
13874
|
-
out2.push({ path: rel, sha256: sha256File(
|
|
13970
|
+
out2.push({ path: rel, sha256: sha256File(join53(runDir, rel)) });
|
|
13875
13971
|
} catch {}
|
|
13876
13972
|
}
|
|
13877
13973
|
return out2;
|
|
@@ -13884,14 +13980,14 @@ function checkScreens(runDir, screens) {
|
|
|
13884
13980
|
return "evidence_screens entry is malformed";
|
|
13885
13981
|
if (isAbsolute8(s.path) || normalize3(s.path).startsWith(".."))
|
|
13886
13982
|
return `evidence screenshot path escapes the evidence dir: ${s.path}`;
|
|
13887
|
-
const file =
|
|
13983
|
+
const file = join53(runDir, s.path);
|
|
13888
13984
|
let cur = runDir;
|
|
13889
|
-
for (const seg of normalize3(s.path).split(
|
|
13890
|
-
cur =
|
|
13985
|
+
for (const seg of normalize3(s.path).split(sep13)) {
|
|
13986
|
+
cur = join53(cur, seg);
|
|
13891
13987
|
if (isSymlink(cur))
|
|
13892
13988
|
return `evidence screenshot path is a symlink: ${s.path}`;
|
|
13893
13989
|
}
|
|
13894
|
-
if (!
|
|
13990
|
+
if (!existsSync33(file))
|
|
13895
13991
|
return `evidence screenshot is missing: ${s.path}`;
|
|
13896
13992
|
if (!isRegularFile(file))
|
|
13897
13993
|
return `evidence screenshot is not a regular file: ${s.path}`;
|
|
@@ -13934,11 +14030,11 @@ async function waitUp(url, ms, signal) {
|
|
|
13934
14030
|
}
|
|
13935
14031
|
function openapiPaths(repoDir) {
|
|
13936
14032
|
for (const f of ["openapi.json", "openapi.yaml", "openapi.yml", "swagger.json"]) {
|
|
13937
|
-
const p =
|
|
13938
|
-
if (!
|
|
14033
|
+
const p = join53(repoDir, f);
|
|
14034
|
+
if (!existsSync33(p))
|
|
13939
14035
|
continue;
|
|
13940
14036
|
try {
|
|
13941
|
-
const txt =
|
|
14037
|
+
const txt = readFileSync42(p, "utf8");
|
|
13942
14038
|
const paths = f.endsWith(".json") ? Object.keys(JSON.parse(txt).paths ?? {}) : [...txt.matchAll(/^ {2}(\/[^\s:]*):\s*$/gm)].map((m) => m[1]);
|
|
13943
14039
|
return paths.filter((x) => !x.includes("{")).slice(0, 10);
|
|
13944
14040
|
} catch {
|
|
@@ -13952,24 +14048,24 @@ async function recordE2eMedia(repoDir, runDir, relDir, base, routes, ms, signal)
|
|
|
13952
14048
|
if (!pw || !pkg)
|
|
13953
14049
|
return { rels: [], skipped: "playwright e2e video and trace skipped: @playwright/test is not installed in the repo" };
|
|
13954
14050
|
try {
|
|
13955
|
-
const dir =
|
|
14051
|
+
const dir = join53(runDir, relDir, "e2e");
|
|
13956
14052
|
mkdirSync21(dir, { recursive: true });
|
|
13957
|
-
writeFileSync24(
|
|
13958
|
-
writeFileSync24(
|
|
14053
|
+
writeFileSync24(join53(dir, "walk.spec.cjs"), e2eSpecSource(pkg, base, routes));
|
|
14054
|
+
writeFileSync24(join53(dir, "playwright.config.cjs"), `module.exports = { testDir: ".", testMatch: "walk.spec.cjs", outputDir: "./out", reporter: "null", use: { video: "on", trace: "on" } };
|
|
13959
14055
|
`);
|
|
13960
|
-
if (!await shoot(pw, ["test", "--config",
|
|
14056
|
+
if (!await shoot(pw, ["test", "--config", join53(dir, "playwright.config.cjs")], repoDir, ms, signal))
|
|
13961
14057
|
return { rels: [], skipped: "playwright e2e video and trace skipped: the run failed or timed out" };
|
|
13962
14058
|
const rels = [];
|
|
13963
14059
|
const walk = (d) => {
|
|
13964
|
-
for (const e of
|
|
13965
|
-
const full =
|
|
14060
|
+
for (const e of readdirSync19(d, { withFileTypes: true })) {
|
|
14061
|
+
const full = join53(d, e.name);
|
|
13966
14062
|
if (e.isDirectory())
|
|
13967
14063
|
walk(full);
|
|
13968
14064
|
else if (e.isFile() && /\.(webm|zip)$/.test(e.name))
|
|
13969
|
-
rels.push(
|
|
14065
|
+
rels.push(join53(relDir, "e2e", relative8(dir, full)));
|
|
13970
14066
|
}
|
|
13971
14067
|
};
|
|
13972
|
-
walk(
|
|
14068
|
+
walk(join53(dir, "out"));
|
|
13973
14069
|
return rels.length > 0 ? { rels, skipped: null } : { rels, skipped: "playwright e2e video and trace skipped: no video or trace was produced" };
|
|
13974
14070
|
} catch (e) {
|
|
13975
14071
|
return { rels: [], skipped: `playwright e2e video and trace skipped: ${String(e?.message ?? e).slice(0, 120)}` };
|
|
@@ -14048,22 +14144,22 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
14048
14144
|
if (!visualEvidenceEnabled(opts.env))
|
|
14049
14145
|
return skip("LOKI_VISUAL_EVIDENCE is 0");
|
|
14050
14146
|
const api = loadProjectApi(repoDir), boot = isMultiRoot(api) ? api.uiBoot() : null;
|
|
14051
|
-
const appDir = boot ?
|
|
14052
|
-
const pkgPath =
|
|
14147
|
+
const appDir = boot ? join53(repoDir, boot.boot.cwd) : repoDir;
|
|
14148
|
+
const pkgPath = join53(appDir, "package.json");
|
|
14053
14149
|
let script = null;
|
|
14054
14150
|
if (!boot) {
|
|
14055
|
-
if (!
|
|
14056
|
-
const subs = ["backend", "frontend"].filter((d) =>
|
|
14151
|
+
if (!existsSync33(pkgPath)) {
|
|
14152
|
+
const subs = ["backend", "frontend"].filter((d) => existsSync33(join53(repoDir, d, "package.json")));
|
|
14057
14153
|
const has = (d) => {
|
|
14058
14154
|
try {
|
|
14059
|
-
return pickScript(JSON.parse(
|
|
14155
|
+
return pickScript(JSON.parse(readFileSync42(join53(repoDir, d, "package.json"), "utf8"))) !== null;
|
|
14060
14156
|
} catch {
|
|
14061
14157
|
return false;
|
|
14062
14158
|
}
|
|
14063
14159
|
};
|
|
14064
14160
|
return skip(noRootReason(subs, subs.filter((d) => !has(d))));
|
|
14065
14161
|
}
|
|
14066
|
-
script = pickScript(JSON.parse(
|
|
14162
|
+
script = pickScript(JSON.parse(readFileSync42(pkgPath, "utf8")));
|
|
14067
14163
|
if (!script)
|
|
14068
14164
|
return skip("no dev, preview or start script");
|
|
14069
14165
|
}
|
|
@@ -14090,20 +14186,20 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
14090
14186
|
}
|
|
14091
14187
|
if (!await waitUp(base, left(), signal))
|
|
14092
14188
|
return skip(aborted() ? "aborted" : `${script} server did not answer within ${Math.round(budget / 1000)}s`);
|
|
14093
|
-
const evRoot =
|
|
14189
|
+
const evRoot = join53(runDir, "evidence");
|
|
14094
14190
|
if (isSymlink(evRoot))
|
|
14095
14191
|
return skip("evidence dir is a symlink");
|
|
14096
14192
|
mkdirSync21(evRoot, { recursive: true });
|
|
14097
14193
|
if (pages.length > 0) {
|
|
14098
|
-
const rel0 =
|
|
14099
|
-
mkdirSync21(
|
|
14194
|
+
const rel0 = join53("evidence", randomBytes6(6).toString("hex"));
|
|
14195
|
+
mkdirSync21(join53(runDir, rel0));
|
|
14100
14196
|
const rels = [];
|
|
14101
14197
|
for (const route of [...new Set(pages.map(routeFor))].slice(0, opts.maxRoutes ?? MAX_ROUTES)) {
|
|
14102
14198
|
if (aborted() || left() <= 0)
|
|
14103
14199
|
break;
|
|
14104
|
-
const rel =
|
|
14105
|
-
const ok = await shoot(pw, ["screenshot", `${base}${route}`,
|
|
14106
|
-
if (ok && !aborted() && !isSymlink(
|
|
14200
|
+
const rel = join53(rel0, `${screenName(route)}.png`);
|
|
14201
|
+
const ok = await shoot(pw, ["screenshot", `${base}${route}`, join53(runDir, rel)], appDir, left(), signal);
|
|
14202
|
+
if (ok && !aborted() && !isSymlink(join53(runDir, rel)) && existsSync33(join53(runDir, rel)))
|
|
14107
14203
|
rels.push(rel);
|
|
14108
14204
|
}
|
|
14109
14205
|
if (aborted())
|
|
@@ -14128,9 +14224,9 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
14128
14224
|
}
|
|
14129
14225
|
if (aborted())
|
|
14130
14226
|
return skip("aborted");
|
|
14131
|
-
const hdir =
|
|
14227
|
+
const hdir = join53(evRoot, randomBytes6(6).toString("hex"));
|
|
14132
14228
|
mkdirSync21(hdir);
|
|
14133
|
-
writeFileSync24(
|
|
14229
|
+
writeFileSync24(join53(hdir, "http.json"), JSON.stringify(rows, null, 2) + `
|
|
14134
14230
|
`);
|
|
14135
14231
|
return { screens: [], http: true, skipped: null };
|
|
14136
14232
|
} catch (e) {
|
|
@@ -14159,12 +14255,12 @@ function receiptScreensProblem(receiptPath, receipt) {
|
|
|
14159
14255
|
return `visual evidence failed (LOKI_VISUAL_GATE=1): ${receipt["evidence_failed"]}`;
|
|
14160
14256
|
return receipt["evidence_screens"] === undefined ? null : checkScreens(dirname19(receiptPath), receipt["evidence_screens"]);
|
|
14161
14257
|
}
|
|
14162
|
-
var visualEvidenceEnabled = (env = process.env) => env["LOKI_VISUAL_EVIDENCE"] !== "0", visualGateEnabled = (env = process.env) => env["LOKI_VISUAL_GATE"] === "1", PAGE_RE, isPageFile = (p) => PAGE_RE.test(p), screenName = (route) => (route === "/" ? "index" : route.slice(1).replace(/[^A-Za-z0-9._-]+/g, "_")) || "index", sha256File = (p) => createHash14("sha256").update(
|
|
14163
|
-
const bin =
|
|
14164
|
-
return
|
|
14258
|
+
var visualEvidenceEnabled = (env = process.env) => env["LOKI_VISUAL_EVIDENCE"] !== "0", visualGateEnabled = (env = process.env) => env["LOKI_VISUAL_GATE"] === "1", PAGE_RE, isPageFile = (p) => PAGE_RE.test(p), screenName = (route) => (route === "/" ? "index" : route.slice(1).replace(/[^A-Za-z0-9._-]+/g, "_")) || "index", sha256File = (p) => createHash14("sha256").update(readFileSync42(p)).digest("hex"), playwrightBin = (repoDir) => {
|
|
14259
|
+
const bin = join53(repoDir, "node_modules", ".bin", "playwright");
|
|
14260
|
+
return existsSync33(bin) ? bin : null;
|
|
14165
14261
|
}, playwrightTestPkg = (repoDir) => {
|
|
14166
|
-
const d =
|
|
14167
|
-
return
|
|
14262
|
+
const d = join53(repoDir, "node_modules", "@playwright", "test");
|
|
14263
|
+
return existsSync33(join53(d, "package.json")) ? d : null;
|
|
14168
14264
|
}, e2eSpecSource = (pkgDir, base, routes) => `const { test } = require(${JSON.stringify(pkgDir)});
|
|
14169
14265
|
test("loki e2e walkthrough", async ({ page }) => {
|
|
14170
14266
|
for (const r of ${JSON.stringify(routes)}) { await page.goto(${JSON.stringify(base)} + r); await page.waitForLoadState("load"); }
|
|
@@ -14210,7 +14306,7 @@ var init_outbox = __esm(() => {
|
|
|
14210
14306
|
});
|
|
14211
14307
|
|
|
14212
14308
|
// ../../loki-ts/src/engine10/stages/pr.ts
|
|
14213
|
-
import { join as
|
|
14309
|
+
import { join as join54 } from "path";
|
|
14214
14310
|
var DEFAULT_PUSH_SH, DEFAULT_PUSH_GITLAB_SH;
|
|
14215
14311
|
var init_pr = __esm(() => {
|
|
14216
14312
|
init_types();
|
|
@@ -14229,20 +14325,20 @@ var init_pr = __esm(() => {
|
|
|
14229
14325
|
init_receipt_surface();
|
|
14230
14326
|
init_yaml_key();
|
|
14231
14327
|
init_outbox();
|
|
14232
|
-
DEFAULT_PUSH_SH =
|
|
14233
|
-
DEFAULT_PUSH_GITLAB_SH =
|
|
14328
|
+
DEFAULT_PUSH_SH = join54(REPO_ROOT, "autonomy/lib/engine10-push.sh");
|
|
14329
|
+
DEFAULT_PUSH_GITLAB_SH = join54(REPO_ROOT, "autonomy/lib/engine10-push-gitlab.sh");
|
|
14234
14330
|
});
|
|
14235
14331
|
|
|
14236
14332
|
// ../../loki-ts/src/util/pr_lessons.ts
|
|
14237
|
-
import { existsSync as
|
|
14238
|
-
import { dirname as dirname20, join as
|
|
14333
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync8, readFileSync as readFileSync43, rmSync as rmSync16, writeFileSync as writeFileSync25 } from "fs";
|
|
14334
|
+
import { dirname as dirname20, join as join55 } from "path";
|
|
14239
14335
|
import { createHash as createHash15 } from "crypto";
|
|
14240
14336
|
function loadLessons(repoDir) {
|
|
14241
14337
|
const p = lessonsPath(repoDir);
|
|
14242
|
-
if (!
|
|
14338
|
+
if (!existsSync34(p))
|
|
14243
14339
|
return [];
|
|
14244
14340
|
try {
|
|
14245
|
-
const j = JSON.parse(
|
|
14341
|
+
const j = JSON.parse(readFileSync43(p, "utf-8"));
|
|
14246
14342
|
return Array.isArray(j.lessons) ? j.lessons : [];
|
|
14247
14343
|
} catch {
|
|
14248
14344
|
return [];
|
|
@@ -14284,7 +14380,7 @@ function recordRunVerdict(repoDir, runId2, verdict) {
|
|
|
14284
14380
|
if (dirty)
|
|
14285
14381
|
save(repoDir, lessons);
|
|
14286
14382
|
}
|
|
14287
|
-
var lessonsPath = (repoDir) =>
|
|
14383
|
+
var lessonsPath = (repoDir) => join55(repoDir, ".loki", "memory", "semantic", "pr-lessons.json"), KINDS;
|
|
14288
14384
|
var init_pr_lessons = __esm(() => {
|
|
14289
14385
|
init_atomic();
|
|
14290
14386
|
init_safe_git();
|
|
@@ -14310,9 +14406,9 @@ var init_attempts = __esm(() => {
|
|
|
14310
14406
|
var init_mcp_config = () => {};
|
|
14311
14407
|
|
|
14312
14408
|
// ../../loki-ts/src/providers/claude_flags.ts
|
|
14313
|
-
import { existsSync as
|
|
14409
|
+
import { existsSync as existsSync35, readFileSync as readFileSync44 } from "fs";
|
|
14314
14410
|
import { resolve as resolvePath, dirname as dirname21 } from "path";
|
|
14315
|
-
import { fileURLToPath as
|
|
14411
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
14316
14412
|
function claudeFlagSupported(flag, helpText) {
|
|
14317
14413
|
const txt = helpText ?? _claudeHelpCache;
|
|
14318
14414
|
if (txt === null || txt === undefined) {
|
|
@@ -14358,14 +14454,14 @@ function leanReviewerFlags(opts = {}) {
|
|
|
14358
14454
|
}
|
|
14359
14455
|
function designArchetypesText() {
|
|
14360
14456
|
try {
|
|
14361
|
-
const moduleDir = dirname21(
|
|
14457
|
+
const moduleDir = dirname21(fileURLToPath5(import.meta.url));
|
|
14362
14458
|
for (const rel of [
|
|
14363
14459
|
["..", "..", "..", "references", "design-archetypes.md"],
|
|
14364
14460
|
["..", "..", "references", "design-archetypes.md"]
|
|
14365
14461
|
]) {
|
|
14366
14462
|
const p = resolvePath(moduleDir, ...rel);
|
|
14367
|
-
if (
|
|
14368
|
-
return
|
|
14463
|
+
if (existsSync35(p))
|
|
14464
|
+
return readFileSync44(p, "utf8");
|
|
14369
14465
|
}
|
|
14370
14466
|
} catch {}
|
|
14371
14467
|
return "";
|
|
@@ -14450,14 +14546,14 @@ var init_providers = __esm(() => {
|
|
|
14450
14546
|
});
|
|
14451
14547
|
|
|
14452
14548
|
// ../../loki-ts/src/runner/router/route_record.ts
|
|
14453
|
-
import { existsSync as
|
|
14454
|
-
import { join as
|
|
14549
|
+
import { existsSync as existsSync36, lstatSync as lstatSync13, mkdirSync as mkdirSync23, readFileSync as readFileSync45, writeFileSync as writeFileSync26 } from "fs";
|
|
14550
|
+
import { join as join56 } from "path";
|
|
14455
14551
|
function loadRouteRecord(runDir) {
|
|
14456
14552
|
try {
|
|
14457
|
-
const p =
|
|
14458
|
-
if (!
|
|
14553
|
+
const p = join56(runDir, ROUTE_RECORD_FILE);
|
|
14554
|
+
if (!existsSync36(p) || !lstatSync13(p).isFile())
|
|
14459
14555
|
return;
|
|
14460
|
-
const v = JSON.parse(
|
|
14556
|
+
const v = JSON.parse(readFileSync45(p, "utf8"));
|
|
14461
14557
|
return typeof v === "object" && v !== null && !Array.isArray(v) ? v : undefined;
|
|
14462
14558
|
} catch {
|
|
14463
14559
|
return;
|
|
@@ -14605,14 +14701,14 @@ __export(exports_deep, {
|
|
|
14605
14701
|
DEFAULT_SECRET_SCAN_SH: () => DEFAULT_SECRET_SCAN_SH,
|
|
14606
14702
|
DEFAULT_PUSH_SH: () => DEFAULT_PUSH_SH2
|
|
14607
14703
|
});
|
|
14608
|
-
import { copyFileSync as copyFileSync3, existsSync as
|
|
14704
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync37, lstatSync as lstatSync14, mkdirSync as mkdirSync24, mkdtempSync as mkdtempSync9, rmSync as rmSync17, writeFileSync as writeFileSync27 } from "fs";
|
|
14609
14705
|
import { tmpdir as tmpdir10 } from "os";
|
|
14610
|
-
import { dirname as dirname22, join as
|
|
14706
|
+
import { dirname as dirname22, join as join57 } from "path";
|
|
14611
14707
|
function sessionCouncil(sessions) {
|
|
14612
14708
|
return { async run(input, signal) {
|
|
14613
|
-
const cwd = mkdtempSync9(
|
|
14709
|
+
const cwd = mkdtempSync9(join57(tmpdir10(), "loki-deep-council-"));
|
|
14614
14710
|
try {
|
|
14615
|
-
writeFileSync27(
|
|
14711
|
+
writeFileSync27(join57(cwd, "diff.patch"), input.diff, "utf8");
|
|
14616
14712
|
const r = await sessions.run({
|
|
14617
14713
|
stage: "deep",
|
|
14618
14714
|
tier: "development",
|
|
@@ -14658,7 +14754,7 @@ async function runFullSuite(ctx, signal, opts, checks, notProven) {
|
|
|
14658
14754
|
const r = await run([spec.cmd, ...spec.args], {
|
|
14659
14755
|
cwd: ctx.repoDir,
|
|
14660
14756
|
timeoutMs: opts.fullSuiteTimeoutMs ?? FULL_SUITE_TIMEOUT_MS,
|
|
14661
|
-
|
|
14757
|
+
env: suiteEnv(opts.path)
|
|
14662
14758
|
});
|
|
14663
14759
|
const durationS = (Date.now() - started) / 1000;
|
|
14664
14760
|
if (signal.aborted) {
|
|
@@ -14666,15 +14762,15 @@ async function runFullSuite(ctx, signal, opts, checks, notProven) {
|
|
|
14666
14762
|
notProven.add(`not run: ${name} (aborted)`);
|
|
14667
14763
|
continue;
|
|
14668
14764
|
}
|
|
14669
|
-
const out2 = `${r.stdout}
|
|
14670
|
-
${r.stderr}
|
|
14765
|
+
const out2 = stripAnsi(`${r.stdout}
|
|
14766
|
+
${r.stderr}`), lr = r.exitCode === 0 ? undefined : await harnessLoadReason({ repoDir: ctx.repoDir, baseSha: ctx.baseSha, skip: installOwned(ctx.repoDir, ctx.outputs().intake?.install_created), out: out2, cmd: spec.cmd, args: spec.args, signal, ...opts.path ? { env: { PATH: opts.path } } : {} });
|
|
14671
14767
|
if (lr) {
|
|
14672
14768
|
checks.push({ name, cmd: [spec.cmd, ...spec.args].join(" "), result: "not_run", duration_s: durationS });
|
|
14673
14769
|
notProven.add(`${lr} (${name}; harness-owned)`);
|
|
14674
14770
|
continue;
|
|
14675
14771
|
}
|
|
14676
14772
|
const cls = classifyCheck({ kind: "test", ok: r.exitCode === 0, out: out2, ...goRunner(spec.cmd, spec.args) });
|
|
14677
|
-
checks.push({ name, cmd: [spec.cmd, ...spec.args].join(" "), result: cls.result, duration_s: durationS, ...cls.result === "fail" ? { ids: failIds(out2) } : {} });
|
|
14773
|
+
checks.push({ name, cmd: [spec.cmd, ...spec.args].join(" "), result: cls.result, duration_s: durationS, ...cls.result === "fail" ? { ids: failIds(out2), excerpt: failureExcerpt(out2, ctx.repoDir) } : {} });
|
|
14678
14774
|
if (cls.result === "not_run")
|
|
14679
14775
|
notProven.add(`not run: ${name} (${cls.reason ?? NO_TESTS_REASON})`);
|
|
14680
14776
|
}
|
|
@@ -14682,7 +14778,7 @@ ${r.stderr}`, lr = r.exitCode === 0 ? undefined : await harnessLoadReason({ repo
|
|
|
14682
14778
|
async function runAppBoot(ctx, opts, checks, notProven) {
|
|
14683
14779
|
let r;
|
|
14684
14780
|
try {
|
|
14685
|
-
r = await (opts.appProbe ?? appProbe)(ctx.repoDir,
|
|
14781
|
+
r = await (opts.appProbe ?? appProbe)(ctx.repoDir, join57(ctx.repoDir, ".loki"));
|
|
14686
14782
|
} catch (err) {
|
|
14687
14783
|
r = { checks: [{ name: "app boot", cmd: "autonomy/app-runner.sh", result: "not_run", duration_s: 0, reason: `app probe threw: ${err.message}` }], pid: null, url: null };
|
|
14688
14784
|
}
|
|
@@ -14724,12 +14820,12 @@ async function runCouncilCheck(ctx, changed, baseSha, signal, opts, checks, notP
|
|
|
14724
14820
|
}
|
|
14725
14821
|
}
|
|
14726
14822
|
async function secureScanChanged(repoDir, changed, opts) {
|
|
14727
|
-
const dir = mkdtempSync9(
|
|
14823
|
+
const dir = mkdtempSync9(join57(tmpdir10(), "loki-deep-secure-"));
|
|
14728
14824
|
try {
|
|
14729
14825
|
for (const f of changed)
|
|
14730
|
-
if (
|
|
14731
|
-
mkdirSync24(dirname22(
|
|
14732
|
-
copyFileSync3(
|
|
14826
|
+
if (existsSync37(join57(repoDir, f)) && lstatSync14(join57(repoDir, f)).isFile()) {
|
|
14827
|
+
mkdirSync24(dirname22(join57(dir, f)), { recursive: true });
|
|
14828
|
+
copyFileSync3(join57(repoDir, f), join57(dir, f));
|
|
14733
14829
|
}
|
|
14734
14830
|
return await runSecureScan(dir, { ...opts.secureScanPath ? { scriptPath: opts.secureScanPath } : {}, timeoutMs: 60000 });
|
|
14735
14831
|
} finally {
|
|
@@ -14738,7 +14834,7 @@ async function secureScanChanged(repoDir, changed, opts) {
|
|
|
14738
14834
|
}
|
|
14739
14835
|
async function runSecretScan(ctx, changed, opts, checks, notProven) {
|
|
14740
14836
|
const scriptPath = opts.secretScanShPath ?? DEFAULT_SECRET_SCAN_SH, name = "security scan", cmd2 = "secret-scan.sh + secure-scan.py";
|
|
14741
|
-
if (!
|
|
14837
|
+
if (!existsSync37(scriptPath)) {
|
|
14742
14838
|
checks.push({ name, cmd: cmd2, result: "not_run", duration_s: 0 });
|
|
14743
14839
|
notProven.add(`not run: ${name} (secret-scan.sh not found)`);
|
|
14744
14840
|
return;
|
|
@@ -14749,7 +14845,7 @@ async function runSecretScan(ctx, changed, opts, checks, notProven) {
|
|
|
14749
14845
|
}
|
|
14750
14846
|
const inline = 'script="$1"; shift; . "$script" || exit 3; hit=0; for f in "$@"; do if _commit_scan_secret_file "$f" || _commit_path_looks_secret "$f"; then printf "%s\\n" "$f"; hit=1; fi; done; exit "$hit"';
|
|
14751
14847
|
const started = Date.now();
|
|
14752
|
-
const r = await run(["bash", "-c", inline, "_", scriptPath, ...changed.map((f) =>
|
|
14848
|
+
const r = await run(["bash", "-c", inline, "_", scriptPath, ...changed.map((f) => join57(ctx.repoDir, f))], { cwd: ctx.repoDir, timeoutMs: 30000 });
|
|
14753
14849
|
const sec = await secureScanChanged(ctx.repoDir, changed, opts), gaps = [], reasons = [];
|
|
14754
14850
|
const hits = r.exitCode === 3 ? [] : r.stdout.split(`
|
|
14755
14851
|
`).map((l) => l.trim()).filter(Boolean), high = sec.findings.filter((f) => String(f.severity).toUpperCase() === "HIGH");
|
|
@@ -14790,7 +14886,7 @@ async function postResults(ctx, opts, checks, notProven, statusState) {
|
|
|
14790
14886
|
const prNumber = prUrl ? PR_NUMBER_RE.exec(prUrl)?.[1] : undefined;
|
|
14791
14887
|
if (prNumber) {
|
|
14792
14888
|
mkdirSync24(ctx.runDir, { recursive: true });
|
|
14793
|
-
const bodyFile =
|
|
14889
|
+
const bodyFile = join57(ctx.runDir, "deep-comment.md");
|
|
14794
14890
|
writeFileSync27(bodyFile, buildCommentBody(checks, notProven, statusState), "utf8");
|
|
14795
14891
|
const commentResult = await run(["bash", scriptPath, ...commentArgv(prNumber, bodyFile)], { cwd: ctx.repoDir, env, timeoutMs: 30000 });
|
|
14796
14892
|
if (commentResult.exitCode !== 0)
|
|
@@ -14844,7 +14940,7 @@ async function runDeep(ctx, signal, opts = {}) {
|
|
|
14844
14940
|
const sig = signReceipt(`${ctx.runId}-deep`, addendumSha256);
|
|
14845
14941
|
const addendum = { ...addendumBody, addendum_sha256: addendumSha256, verification: { jwt: sig.jwt, kid: sig.kid } };
|
|
14846
14942
|
mkdirSync24(ctx.runDir, { recursive: true });
|
|
14847
|
-
writeFileSync27(
|
|
14943
|
+
writeFileSync27(join57(ctx.runDir, "receipt-addendum-1.json"), JSON.stringify(addendum, null, 2) + `
|
|
14848
14944
|
`);
|
|
14849
14945
|
const pushNotProven = await postResults(ctx, opts, checks, notProvenList, statusState);
|
|
14850
14946
|
const allNotProven = [...notProvenList, ...pushNotProven];
|
|
@@ -14880,9 +14976,9 @@ var init_deep = __esm(() => {
|
|
|
14880
14976
|
});
|
|
14881
14977
|
|
|
14882
14978
|
// ../../loki-ts/src/engine10/stages/verify.ts
|
|
14883
|
-
import { existsSync as
|
|
14979
|
+
import { existsSync as existsSync38, mkdtempSync as mkdtempSync10, rmSync as rmSync18 } from "fs";
|
|
14884
14980
|
import { tmpdir as tmpdir11 } from "os";
|
|
14885
|
-
import { isAbsolute as isAbsolute9, join as
|
|
14981
|
+
import { isAbsolute as isAbsolute9, join as join58, relative as relative9 } from "path";
|
|
14886
14982
|
async function runOnce2(cmd2, args, cwd, signal, opts) {
|
|
14887
14983
|
if (!Bun.which(cmd2, { PATH: opts.path ?? process.env["PATH"] ?? "" }))
|
|
14888
14984
|
return { ok: false, missing: true, cut: false, out: "" };
|
|
@@ -14945,17 +15041,18 @@ async function runCheck(ctx, name, cmd2, args, signal, checks, opts = {}) {
|
|
|
14945
15041
|
ctx.emit("test.result", "verify", opts.opaque ? { ...pubHold(check) } : { ...check });
|
|
14946
15042
|
return check;
|
|
14947
15043
|
}
|
|
14948
|
-
async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal) {
|
|
14949
|
-
const out2 = { ids: [], names: [], weak: [], cnt: {} };
|
|
15044
|
+
async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal, zeroOk = true) {
|
|
15045
|
+
const out2 = { ids: [], names: [], weak: [], zero: [], cnt: {} };
|
|
14950
15046
|
const pairs = checks.flatMap((c) => {
|
|
14951
15047
|
const t = tests.find((x) => testCheckName(x) === c.name);
|
|
14952
15048
|
return t ? [{ c, t }] : [];
|
|
14953
15049
|
});
|
|
14954
15050
|
const un = pairs.filter(({ t }) => !changed.includes(t.path));
|
|
14955
15051
|
const sus = pairs.filter(({ c }) => rel.has(c.name) && c.result === "pass");
|
|
14956
|
-
|
|
15052
|
+
const zc = zeroOk ? un.filter(({ c, t }) => c.result === "not_run" && !c.owner && (c.reason ?? "").startsWith(NO_TESTS_REASON) && !wall.has(c.name) && !rel.has(c.name) && !isHoldoutCheck(c.name) && !changed.includes(t.path)) : [];
|
|
15053
|
+
if (!(un.some(({ c }) => c.result === "fail" && c.ids?.length) || sus.length || zc.length) || signal.aborted)
|
|
14957
15054
|
return out2;
|
|
14958
|
-
const dir = mkdtempSync10(
|
|
15055
|
+
const dir = mkdtempSync10(join58(tmpdir11(), "e10-base-"));
|
|
14959
15056
|
const git4 = (args) => {
|
|
14960
15057
|
safeGit(ctx.repoDir, args, { stdio: "ignore", repoDrivers: true });
|
|
14961
15058
|
};
|
|
@@ -14968,6 +15065,7 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal)
|
|
|
14968
15065
|
const red = !b.ok && !b.cut ? failIds(b.out) : [];
|
|
14969
15066
|
base.set(c, { red, n: ran(b.out) ?? summaryPassFailCount(b.out), sk: skipped(b.out) });
|
|
14970
15067
|
}
|
|
15068
|
+
out2.zero = await zeroOnBase(zc.map(({ c, t }) => ({ name: c.name, ...commandFor(t, dir, api) })), dir, ctx.repoDir, (r) => runOnce2(r.cmd, r.args, r.cwd, signal, {}), (n2) => ctx.emit("test.skipped_on_base", "verify", { note: `skipped on base: ${n2}`, check: n2 }));
|
|
14971
15069
|
out2.weak = sus.filter(({ c }) => (c.sk ?? 0) > base.get(c).sk || (c.n ?? 0) < base.get(c).n).map(({ c }) => c.name);
|
|
14972
15070
|
for (const { c } of sus) {
|
|
14973
15071
|
out2.cnt[c.name] = { b: { run: base.get(c).n, skipped: base.get(c).sk }, h: { run: c.n ?? 0, skipped: c.sk ?? 0 } };
|
|
@@ -14993,7 +15091,7 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal)
|
|
|
14993
15091
|
return out2;
|
|
14994
15092
|
}
|
|
14995
15093
|
function isLokiModeRepo(repoDir) {
|
|
14996
|
-
return
|
|
15094
|
+
return existsSync38(join58(repoDir, "scripts", "select-tests.sh"));
|
|
14997
15095
|
}
|
|
14998
15096
|
async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
|
|
14999
15097
|
const { api, ...runOpts } = opts;
|
|
@@ -15015,9 +15113,9 @@ async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
|
|
|
15015
15113
|
}
|
|
15016
15114
|
for (const g of groupByPackage(api, ctx.repoDir, changed.filter((f) => /\.(ts|tsx|js|jsx)$/.test(f)))) {
|
|
15017
15115
|
const sfx = g.root === "." ? "" : `:${g.root}`, co = g.root === "." ? opts : { ...opts, cwd: g.cwd };
|
|
15018
|
-
if (
|
|
15116
|
+
if (existsSync38(join58(g.cwd, "tsconfig.json")))
|
|
15019
15117
|
await runCheck(ctx, `lint:tsc${sfx}`, "npx", ["--no-install", "tsc", "--noEmit", "-p", "."], signal, checks, { ...co, kind: "static" });
|
|
15020
|
-
if (ESLINT_CONFIGS.some((f) =>
|
|
15118
|
+
if (ESLINT_CONFIGS.some((f) => existsSync38(join58(g.cwd, f)))) {
|
|
15021
15119
|
const c = await runCheck(ctx, `lint:eslint${sfx}`, "npx", ["--no-install", "eslint", ...g.rel], signal, checks, { ...co, kind: "static" });
|
|
15022
15120
|
if (await excuseLint(ctx, signal, c, "eslint", "npx", ["--no-install", "eslint"], g.cwd, g.rel, co))
|
|
15023
15121
|
pre.push(c.name);
|
|
@@ -15032,7 +15130,7 @@ var CHECK_TIMEOUT_MS = 60000, excerpts, isHold = (c) => isHoldoutCheck(c.name),
|
|
|
15032
15130
|
return r.missing || r.cut ? null : r;
|
|
15033
15131
|
}, base: (f) => {
|
|
15034
15132
|
try {
|
|
15035
|
-
return safeGit(ctx.repoDir, ["show", `${ctx.baseSha}:${
|
|
15133
|
+
return safeGit(ctx.repoDir, ["show", `${ctx.baseSha}:${relative9(ctx.repoDir, join58(cwd, f))}`], { stdio: ["ignore", "pipe", "ignore"] });
|
|
15036
15134
|
} catch {
|
|
15037
15135
|
return null;
|
|
15038
15136
|
}
|
|
@@ -15053,6 +15151,7 @@ var init_verify = __esm(() => {
|
|
|
15053
15151
|
init_types();
|
|
15054
15152
|
init_resolve();
|
|
15055
15153
|
init_safe_git();
|
|
15154
|
+
init_base_guard();
|
|
15056
15155
|
init_repo_profile();
|
|
15057
15156
|
init_check_result();
|
|
15058
15157
|
init_check_result();
|
|
@@ -15095,7 +15194,7 @@ var init_verify = __esm(() => {
|
|
|
15095
15194
|
const impacted = ctx.tests.impacted(map, changed);
|
|
15096
15195
|
const changedTestFiles = map.tests.filter((t) => changed.includes(t.path));
|
|
15097
15196
|
const wall = ctx.outputs().wall ?? {};
|
|
15098
|
-
const wallPaths = new Set((wall.files ?? []).map((f) => isAbsolute9(f.path) ?
|
|
15197
|
+
const wallPaths = new Set((wall.files ?? []).map((f) => isAbsolute9(f.path) ? relative9(ctx.repoDir, f.path) : f.path));
|
|
15099
15198
|
const intake = ctx.outputs().intake, repoMap = loadRepoMap(intake?.repomap_ref), relevant2 = ctx.tests.impacted(map, namedFiles(intake?.task ?? "", repoMap));
|
|
15100
15199
|
const harness = map.runners.length === 0 ? harnessRunners(map.runners, repoMap?.files ?? [])[0] : undefined, wallTests = [...map.tests.filter((t) => wallPaths.has(t.path)), ...harness ? [...wallPaths].filter((p) => /[._](?:test|spec)\.[cm]?[jt]sx?$/.test(p) && !map.tests.some((t) => t.path === p)).map((path) => ({ runner: harness, path })) : []];
|
|
15101
15200
|
const tests = failedFirst(dedupeTests([...impacted, ...changedTestFiles, ...wallTests, ...relevant2]), ctx.outputs().verify?.checks);
|
|
@@ -15126,7 +15225,8 @@ var init_verify = __esm(() => {
|
|
|
15126
15225
|
ctx.emit("test.result", "verify", { ...pubHold(k) });
|
|
15127
15226
|
}
|
|
15128
15227
|
const targetNames = new Set([...[...wallTests, ...relevant2].map(testCheckName), ...checks.filter(isHold).map((c) => c.name)]);
|
|
15129
|
-
const
|
|
15228
|
+
const cfgChanged = testConfigChanged(ctx.repoDir, ctx.baseSha, changed);
|
|
15229
|
+
const preRed = await subtractBase(ctx, api, checks, tests, changed, new Set(wallTests.map(testCheckName)), new Set(relevant2.map(testCheckName)), signal, cfgChanged.length === 0 && changed.every(isTestFile));
|
|
15130
15230
|
const attr = attribute(ctx.repoDir, ctx.baseSha, checks.filter((c) => c.result === "fail" && !preRed.names.includes(c.name)).map((c) => ({ name: c.name, ids: c.ids, eligible: !targetNames.has(c.name) && !changed.includes(c.name.slice(c.name.indexOf(":") + 1)) })));
|
|
15131
15231
|
attr.introducedChecks = [...new Set(attr.introducedChecks.map((n2) => isHoldoutCheck(n2) ? "holdout" : n2))];
|
|
15132
15232
|
preRed.names.push(...attr.preExistingChecks);
|
|
@@ -15154,6 +15254,8 @@ var init_verify = __esm(() => {
|
|
|
15154
15254
|
const k = { name: c.name, cmd: c.cmd, result: c.result, duration_s: c.duration_s, ...c.reason ? { reason: c.reason } : {} };
|
|
15155
15255
|
checks.push(k);
|
|
15156
15256
|
ctx.emit("test.result", "verify", { ...k });
|
|
15257
|
+
if (c.excerpt)
|
|
15258
|
+
excerpts.set(k, c.excerpt);
|
|
15157
15259
|
}
|
|
15158
15260
|
const fa = attributeFullSuite(ctx.repoDir, ctx.baseSha, full, checks.filter((c) => c.result === "fail" && !preRed.names.includes(c.name)).flatMap((c) => c.ids ?? []), changed);
|
|
15159
15261
|
preRed.names.push(...fa.preExistingChecks);
|
|
@@ -15165,7 +15267,6 @@ var init_verify = __esm(() => {
|
|
|
15165
15267
|
recordRisk(ctx.repoDir, risk);
|
|
15166
15268
|
}
|
|
15167
15269
|
}
|
|
15168
|
-
const cfgChanged = testConfigChanged(ctx.repoDir, ctx.baseSha, changed);
|
|
15169
15270
|
const covered = (f) => ctx.tests.impacted(map, [f]).some((t) => checks.some((c) => c.name === testCheckName(t) && hasExecutedProof([c])));
|
|
15170
15271
|
const uncoveredChanged = changed.filter((f) => CODE_EXT.test(f) && !isTestFile(f) && !wallPaths.has(f) && !cfgChanged.includes(f) && !covered(f));
|
|
15171
15272
|
const flaky = checks.filter((c) => c.result === "flaky").map((c) => isHold(c) ? "holdout" : c.name);
|
|
@@ -15195,14 +15296,14 @@ ${x}` : c.cmd };
|
|
|
15195
15296
|
const weakened = [...modifiedRel, ...cfgChanged.map((f) => `test configuration changed: ${f}`), ...preRed.weak.map((n2) => `skipped or fewer tests than base: ${n2}`)];
|
|
15196
15297
|
const notProven = [...weakened, ...intake?.deps_not_proven ?? [], ...pub.filter((c) => c.name === "holdout" && c.result !== "pass").map((c) => c.result === "not_run" ? "holdout not executed" : "holdout check failed"), ...[...fullNotProven].filter((n2) => !n2.startsWith("full suite (no test runner")), ...pub.filter((c) => c.owner === "harness" && c.name !== "holdout").map((c) => `${c.reason} (${c.name}; harness-owned, no fix rounds)`), ...new Set(checks.filter((c) => c.interpreter === "system" && c.result !== "not_run").map((c) => c.name.startsWith("lint:") ? "lint ran on the system ruff" : "tests ran on the system interpreter"))];
|
|
15197
15298
|
const wallNames = new Set(wallTests.map(testCheckName)), wallRun = checks.filter((c) => wallNames.has(c.name) || isHold(c)), wallPassed = wallRun.some((c) => c.result === "fail") ? false : wallRun.length > 0 && wallRun.every((c) => c.result === "pass") ? true : undefined;
|
|
15198
|
-
return { status: "completed", data: { checks: pub, flaky, ...wallPassed === undefined ? {} : { wall_passed: wallPassed }, failures_grouped: failuresGrouped, holdout_failed: holdoutFailed, changed_files: changed, not_proven: notProven, pre_red: preRed.ids, pre_red_checks: preRed.names, ...attr.line ? { baseline_line: attr.line, introduced_checks: attr.introducedChecks } : {}, test_counts: testCounts, uncovered_changed: uncoveredChanged, target_checks: checks.filter((c) => c.result === "pass" && targetNames.has(c.name)).map((c) => isHold(c) ? "holdout" : c.name), risk } };
|
|
15299
|
+
return { status: "completed", data: { checks: pub, flaky, ...wallPassed === undefined ? {} : { wall_passed: wallPassed }, failures_grouped: failuresGrouped, holdout_failed: holdoutFailed, changed_files: changed, not_proven: notProven, pre_red: preRed.ids, pre_red_checks: preRed.names, skipped_on_base: preRed.zero, ...attr.line ? { baseline_line: attr.line, introduced_checks: attr.introducedChecks } : {}, test_counts: testCounts, uncovered_changed: uncoveredChanged, target_checks: checks.filter((c) => c.result === "pass" && targetNames.has(c.name)).map((c) => isHold(c) ? "holdout" : c.name), risk } };
|
|
15199
15300
|
}
|
|
15200
15301
|
};
|
|
15201
15302
|
});
|
|
15202
15303
|
|
|
15203
15304
|
// ../../loki-ts/src/project_model/conventions.ts
|
|
15204
|
-
import { existsSync as
|
|
15205
|
-
import { dirname as dirname23, join as
|
|
15305
|
+
import { existsSync as existsSync39, readdirSync as readdirSync20, readFileSync as readFileSync46 } from "fs";
|
|
15306
|
+
import { dirname as dirname23, join as join59 } from "path";
|
|
15206
15307
|
function parseJsonc(text2) {
|
|
15207
15308
|
let out2 = "", i = 0;
|
|
15208
15309
|
while (i < text2.length) {
|
|
@@ -15237,25 +15338,25 @@ function moduleOf(file, depth = 0) {
|
|
|
15237
15338
|
const ext = typeof j.extends === "string" ? j.extends : null;
|
|
15238
15339
|
if (!ext || !ext.startsWith("."))
|
|
15239
15340
|
return null;
|
|
15240
|
-
const next =
|
|
15241
|
-
return
|
|
15341
|
+
const next = join59(dirname23(file), ext.endsWith(".json") ? ext : `${ext}.json`);
|
|
15342
|
+
return existsSync39(next) ? moduleOf(next, depth + 1) : null;
|
|
15242
15343
|
}
|
|
15243
15344
|
function readPackageConventions(pkgDir, runner = null) {
|
|
15244
15345
|
let names = [];
|
|
15245
15346
|
try {
|
|
15246
|
-
names =
|
|
15347
|
+
names = readdirSync20(pkgDir).filter((f) => f.endsWith(".json")).sort((x, y) => x.length - y.length || x.localeCompare(y));
|
|
15247
15348
|
} catch {
|
|
15248
15349
|
return null;
|
|
15249
15350
|
}
|
|
15250
15351
|
let packageType = null, tsModule = null;
|
|
15251
15352
|
for (const n2 of names) {
|
|
15252
|
-
const j = readJson5(
|
|
15353
|
+
const j = readJson5(join59(pkgDir, n2));
|
|
15253
15354
|
if (!j)
|
|
15254
15355
|
continue;
|
|
15255
15356
|
if (packageType === null && typeof j.type === "string" && typeof j.name === "string")
|
|
15256
15357
|
packageType = j.type;
|
|
15257
15358
|
if (tsModule === null && j.compilerOptions !== undefined)
|
|
15258
|
-
tsModule = moduleOf(
|
|
15359
|
+
tsModule = moduleOf(join59(pkgDir, n2));
|
|
15259
15360
|
}
|
|
15260
15361
|
if (packageType === null && tsModule === null)
|
|
15261
15362
|
return null;
|
|
@@ -15277,7 +15378,7 @@ function conventionViolation(c, fileName, content) {
|
|
|
15277
15378
|
}
|
|
15278
15379
|
var readJson5 = (p) => {
|
|
15279
15380
|
try {
|
|
15280
|
-
const v = parseJsonc(
|
|
15381
|
+
const v = parseJsonc(readFileSync46(p, "utf8"));
|
|
15281
15382
|
return v && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
15282
15383
|
} catch {
|
|
15283
15384
|
return null;
|
|
@@ -15287,9 +15388,9 @@ var init_conventions = () => {};
|
|
|
15287
15388
|
|
|
15288
15389
|
// ../../loki-ts/src/engine10/stages/wall.ts
|
|
15289
15390
|
import { spawnSync as spawnSync7 } from "child_process";
|
|
15290
|
-
import { existsSync as
|
|
15391
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync25, mkdtempSync as mkdtempSync11, readFileSync as readFileSync47, readdirSync as readdirSync21, rmSync as rmSync19, writeFileSync as writeFileSync28 } from "fs";
|
|
15291
15392
|
import { tmpdir as tmpdir12 } from "os";
|
|
15292
|
-
import { dirname as dirname24, join as
|
|
15393
|
+
import { dirname as dirname24, join as join60, relative as relative10 } from "path";
|
|
15293
15394
|
|
|
15294
15395
|
class RealBaseTestRunner {
|
|
15295
15396
|
api;
|
|
@@ -15352,10 +15453,10 @@ ${acceptance.map((a) => `Acceptance: ${a}`).join(`
|
|
|
15352
15453
|
function loadTaskText(ctx, fromPrior) {
|
|
15353
15454
|
if (fromPrior)
|
|
15354
15455
|
return fromPrior;
|
|
15355
|
-
const issueJsonPath = process.env.LOKI_E10_ISSUE_JSON ??
|
|
15356
|
-
if (
|
|
15456
|
+
const issueJsonPath = process.env.LOKI_E10_ISSUE_JSON ?? join60(ctx.runDir, "issue.json");
|
|
15457
|
+
if (existsSync40(issueJsonPath)) {
|
|
15357
15458
|
try {
|
|
15358
|
-
const issue = JSON.parse(
|
|
15459
|
+
const issue = JSON.parse(readFileSync47(issueJsonPath, "utf8"));
|
|
15359
15460
|
const text2 = [issue.title, issue.body].filter((s) => typeof s === "string" && s.length > 0).join(`
|
|
15360
15461
|
|
|
15361
15462
|
`);
|
|
@@ -15367,7 +15468,7 @@ function loadTaskText(ctx, fromPrior) {
|
|
|
15367
15468
|
}
|
|
15368
15469
|
function wallTargetDir(repoDir, existingTests) {
|
|
15369
15470
|
const first = existingTests[0];
|
|
15370
|
-
return first ?
|
|
15471
|
+
return first ? join60(repoDir, dirname24(first.path)) : join60(repoDir, "tests");
|
|
15371
15472
|
}
|
|
15372
15473
|
function guessRunner(fileName, runners) {
|
|
15373
15474
|
if (fileName.endsWith(".py"))
|
|
@@ -15399,12 +15500,12 @@ async function wallAuthor(ctx, signal, retry) {
|
|
|
15399
15500
|
return done({ status: "skipped", data: { size: sz.size, files: [], no_interpreter: true, not_proven: ["Wall skipped: no project test interpreter"] }, reason: "Wall skipped: no project test interpreter" });
|
|
15400
15501
|
const tree = prior.intake?.tree;
|
|
15401
15502
|
const repomapText = repoMapText(ctx.repoDir, tree, repomapRef, WALL_MAP_MAX_LINES);
|
|
15402
|
-
const targetDir = wallTargetDir(ctx.repoDir, existingTests), pkg = loadProjectApi(ctx.repoDir)?.packageOf(`${
|
|
15403
|
-
const conv2 = readPackageConventions(
|
|
15404
|
-
const cwd = mkdtempSync11(
|
|
15503
|
+
const targetDir = wallTargetDir(ctx.repoDir, existingTests), pkg = loadProjectApi(ctx.repoDir)?.packageOf(`${relative10(ctx.repoDir, targetDir)}/x`);
|
|
15504
|
+
const conv2 = readPackageConventions(join60(ctx.repoDir, pkg?.root ?? "."), pkg?.runner ?? null);
|
|
15505
|
+
const cwd = mkdtempSync11(join60(tmpdir12(), "loki-e15-wall-"));
|
|
15405
15506
|
const wm = wallManifestFor(ctx.repoDir, tree, task);
|
|
15406
15507
|
for (const [n2, c] of [["task.md", task], ["repomap.txt", repomapText], ...wm ? [["wall_manifest.txt", wm.text]] : []])
|
|
15407
|
-
writeFileSync28(
|
|
15508
|
+
writeFileSync28(join60(cwd, n2), c, "utf8");
|
|
15408
15509
|
const model = retry?.model ?? wallFirstModel(sz.size), iterationId = `${ctx.runId}-wall${retry?.suffix ?? ""}`;
|
|
15409
15510
|
const session = await ctx.sessions.run({
|
|
15410
15511
|
stage: "wall",
|
|
@@ -15420,15 +15521,15 @@ async function wallAuthor(ctx, signal, retry) {
|
|
|
15420
15521
|
rmSync19(cwd, { recursive: true, force: true });
|
|
15421
15522
|
return done({ status: "failed", data: { iteration_ids: [iterationId], model }, reason: "wall session aborted, killed, or timed out", killed: true });
|
|
15422
15523
|
}
|
|
15423
|
-
const all =
|
|
15424
|
-
const sealedDir =
|
|
15524
|
+
const all = readdirSync21(cwd).filter((f) => f.startsWith(WALL_PREFIX)), held = stashHoldout({ runId: ctx.runId, repoDir: ctx.repoDir, srcDir: cwd, targetDir, names: all.filter((n2) => !conventionViolation(conv2, n2, readFileSync47(join60(cwd, n2), "utf8"))), runnerOf: (n2) => guessRunner(n2, runners) }), generated = all.filter((n2) => !held?.names.has(n2));
|
|
15525
|
+
const sealedDir = join60(ctx.runDir, "wall");
|
|
15425
15526
|
if (generated.length > 0)
|
|
15426
15527
|
mkdirSync25(sealedDir, { recursive: true });
|
|
15427
15528
|
const contents = new Map;
|
|
15428
15529
|
const discarded = [];
|
|
15429
15530
|
for (const name of generated) {
|
|
15430
|
-
const content =
|
|
15431
|
-
writeFileSync28(
|
|
15531
|
+
const content = readFileSync47(join60(cwd, name), "utf8"), bad = conventionViolation(conv2, name, content);
|
|
15532
|
+
writeFileSync28(join60(sealedDir, name), content, "utf8");
|
|
15432
15533
|
if (bad)
|
|
15433
15534
|
discarded.push({ file: name, reason: `${bad}; wall test did not compile under the package config` });
|
|
15434
15535
|
else
|
|
@@ -15455,19 +15556,19 @@ function* installCore(ctx, a, baseDir, opts) {
|
|
|
15455
15556
|
const content = contents.get(name);
|
|
15456
15557
|
if (content === undefined)
|
|
15457
15558
|
continue;
|
|
15458
|
-
const dest =
|
|
15559
|
+
const dest = join60(targetDir, name), runner = guessRunner(name, runners);
|
|
15459
15560
|
writeFileSync28(dest, content, "utf8");
|
|
15460
15561
|
sealedFiles.push({ path: dest, sha256: sha2562(content) });
|
|
15461
15562
|
readOnlyFiles.push({ path: dest, content });
|
|
15462
15563
|
if (runner)
|
|
15463
|
-
wallTests.push({ runner, path:
|
|
15564
|
+
wallTests.push({ runner, path: relative10(ctx.repoDir, dest) });
|
|
15464
15565
|
}
|
|
15465
15566
|
ctx.wallSealed = true;
|
|
15466
15567
|
ctx.emit("wall.sealed", "wall", { files: sealedFiles, ...a.manifestSha256 ? { manifest_sha256: a.manifestSha256 } : {} });
|
|
15467
15568
|
const baseRunner = opts.baseRunner ?? new RealBaseTestRunner, baseRun = { pass: 0, fail: 0, not_run: discarded.length }, notRunFiles = [];
|
|
15468
15569
|
const each = yield { runner: baseRunner, tests: wallTests };
|
|
15469
15570
|
for (const [i, t] of wallTests.entries()) {
|
|
15470
|
-
const e = each?.[i], r = e ?? baseRunner.run(baseDir, [t]), abs =
|
|
15571
|
+
const e = each?.[i], r = e ?? baseRunner.run(baseDir, [t]), abs = join60(ctx.repoDir, t.path);
|
|
15471
15572
|
baseRun.pass += r.pass;
|
|
15472
15573
|
baseRun.fail += r.fail;
|
|
15473
15574
|
baseRun.not_run += r.not_run ?? 0;
|
|
@@ -15508,7 +15609,7 @@ async function runWall(ctx, signal, opts = {}) {
|
|
|
15508
15609
|
if (a.kind === "authored") {
|
|
15509
15610
|
for (const f of first.data.files ?? [])
|
|
15510
15611
|
rmSync19(f.path, { force: true });
|
|
15511
|
-
rmSync19(
|
|
15612
|
+
rmSync19(join60(ctx.runDir, "wall"), { recursive: true, force: true });
|
|
15512
15613
|
ctx.wallSealed = false;
|
|
15513
15614
|
}
|
|
15514
15615
|
removeHoldout(ctx.runId, ctx.repoDir);
|
|
@@ -15544,15 +15645,15 @@ var init_wall = __esm(() => {
|
|
|
15544
15645
|
});
|
|
15545
15646
|
|
|
15546
15647
|
// ../../loki-ts/src/e10ext/discard.ts
|
|
15547
|
-
import { chmodSync as chmodSync5, closeSync as closeSync9, lstatSync as lstatSync15, mkdirSync as mkdirSync26, openSync as openSync9, readFileSync as
|
|
15548
|
-
import { dirname as dirname25, join as
|
|
15648
|
+
import { chmodSync as chmodSync5, closeSync as closeSync9, lstatSync as lstatSync15, mkdirSync as mkdirSync26, openSync as openSync9, readFileSync as readFileSync48, realpathSync as realpathSync23, rmdirSync, unlinkSync as unlinkSync7, writeFileSync as writeFileSync29 } from "fs";
|
|
15649
|
+
import { dirname as dirname25, join as join61, relative as relative11, sep as sep14 } from "path";
|
|
15549
15650
|
function safeRestore(repoDir, f, want, mode) {
|
|
15550
|
-
const root =
|
|
15651
|
+
const root = realpathSync23(repoDir), fp = join61(root, f), rel = relative11(root, dirname25(fp));
|
|
15551
15652
|
if (rel.startsWith(".."))
|
|
15552
15653
|
throw new Error("outside repo");
|
|
15553
15654
|
let cur = root;
|
|
15554
|
-
for (const part of rel === "" ? [] : rel.split(
|
|
15555
|
-
cur =
|
|
15655
|
+
for (const part of rel === "" ? [] : rel.split(sep14)) {
|
|
15656
|
+
cur = join61(cur, part);
|
|
15556
15657
|
let st2;
|
|
15557
15658
|
try {
|
|
15558
15659
|
st2 = lstatSync15(cur);
|
|
@@ -15569,7 +15670,7 @@ function safeRestore(repoDir, f, want, mode) {
|
|
|
15569
15670
|
} catch {
|
|
15570
15671
|
st = null;
|
|
15571
15672
|
}
|
|
15572
|
-
if (st?.isFile() &&
|
|
15673
|
+
if (st?.isFile() && readFileSync48(fp).equals(want)) {
|
|
15573
15674
|
chmodSync5(fp, mode);
|
|
15574
15675
|
return;
|
|
15575
15676
|
}
|
|
@@ -15606,7 +15707,7 @@ async function discardIfSatisfied(git4, base, o, staged, keep, repoDir) {
|
|
|
15606
15707
|
return { status: "failed", data: {}, reason: "already-satisfied discard failed" };
|
|
15607
15708
|
const notProven = [];
|
|
15608
15709
|
for (const [f, v] of Object.entries(o.intake?.preexisting_untracked_blobs ?? {})) {
|
|
15609
|
-
const fp =
|
|
15710
|
+
const fp = join61(repoDir, f);
|
|
15610
15711
|
try {
|
|
15611
15712
|
if (v.startsWith("!")) {
|
|
15612
15713
|
const st = lstatSync15(fp);
|
|
@@ -15625,7 +15726,7 @@ async function discardIfSatisfied(git4, base, o, staged, keep, repoDir) {
|
|
|
15625
15726
|
try {
|
|
15626
15727
|
let m = 420;
|
|
15627
15728
|
try {
|
|
15628
|
-
const l = lstatSync15(
|
|
15729
|
+
const l = lstatSync15(join61(repoDir, f));
|
|
15629
15730
|
if (l.isFile())
|
|
15630
15731
|
m = l.mode & 511;
|
|
15631
15732
|
} catch {}
|
|
@@ -15672,7 +15773,7 @@ var init_commit_filter = __esm(() => {
|
|
|
15672
15773
|
});
|
|
15673
15774
|
|
|
15674
15775
|
// ../../loki-ts/src/e10ext/scope.ts
|
|
15675
|
-
import { basename as
|
|
15776
|
+
import { basename as basename23, dirname as dirname27 } from "path";
|
|
15676
15777
|
function contractText(o) {
|
|
15677
15778
|
const c = o.intake?.contract_snapshot?.contract;
|
|
15678
15779
|
return Array.isArray(c?.criteria) ? c.criteria.map((x) => typeof x?.text === "string" ? x.text : "").join(`
|
|
@@ -15687,7 +15788,7 @@ function outsideScope(o, staged) {
|
|
|
15687
15788
|
${typeof o.intake?.task === "string" ? o.intake.task : ""}
|
|
15688
15789
|
${contractText(o)}`, pre = o.intake?.preexisting_dirty ?? {};
|
|
15689
15790
|
const toks = surfaceTokens(text2), plannedDirs = new Set(rel.map((r) => dirname27(r)).filter((d) => d !== "."));
|
|
15690
|
-
return staged.filter(({ st, f }) => st !== "A" && !isTestFile(f) && !Object.hasOwn(pre, f) && !rel.includes(f) && !mentions(text2, f) && !mentions(text2,
|
|
15791
|
+
return staged.filter(({ st, f }) => st !== "A" && !isTestFile(f) && !Object.hasOwn(pre, f) && !rel.includes(f) && !mentions(text2, f) && !mentions(text2, basename23(f)) && !plannedDirs.has(dirname27(f)) && !dirSegs(f).some((d) => toks.has(d))).map(({ f }) => f);
|
|
15691
15792
|
}
|
|
15692
15793
|
function flagOutsideScope(o, staged) {
|
|
15693
15794
|
const unit = unitFlags(staged, process.env, o.intake?.preexisting_dirty ?? {});
|
|
@@ -15702,14 +15803,14 @@ var init_scope2 = __esm(() => {
|
|
|
15702
15803
|
});
|
|
15703
15804
|
|
|
15704
15805
|
// ../../loki-ts/src/council/role_agents.ts
|
|
15705
|
-
import { existsSync as
|
|
15806
|
+
import { existsSync as existsSync41, readdirSync as readdirSync22, readFileSync as readFileSync49 } from "fs";
|
|
15706
15807
|
import { homedir as homedir9 } from "os";
|
|
15707
|
-
import { join as
|
|
15808
|
+
import { join as join62 } from "path";
|
|
15708
15809
|
function agentDirs(repoDir, env = process.env) {
|
|
15709
|
-
return [env["LOKI_AGENTS_PROJECT_DIR"] ||
|
|
15810
|
+
return [env["LOKI_AGENTS_PROJECT_DIR"] || join62(repoDir, ".loki", "agents"), env["LOKI_AGENTS_USER_DIR"] || join62(env["XDG_CONFIG_HOME"] || join62(homedir9(), ".config"), "loki", "agents")];
|
|
15710
15811
|
}
|
|
15711
15812
|
function parseAgent(file, stem2) {
|
|
15712
|
-
const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(
|
|
15813
|
+
const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(readFileSync49(file, "utf8"));
|
|
15713
15814
|
if (!m)
|
|
15714
15815
|
return null;
|
|
15715
15816
|
const body = m[2].trim();
|
|
@@ -15723,18 +15824,18 @@ function parseAgent(file, stem2) {
|
|
|
15723
15824
|
}
|
|
15724
15825
|
function loadRoleAgent(repoDir, role, env = process.env) {
|
|
15725
15826
|
for (const d of agentDirs(repoDir, env)) {
|
|
15726
|
-
if (!
|
|
15827
|
+
if (!existsSync41(d))
|
|
15727
15828
|
continue;
|
|
15728
15829
|
let names;
|
|
15729
15830
|
try {
|
|
15730
|
-
names =
|
|
15831
|
+
names = readdirSync22(d).filter((n2) => n2.endsWith(".md") && !n2.startsWith(".")).sort();
|
|
15731
15832
|
} catch {
|
|
15732
15833
|
continue;
|
|
15733
15834
|
}
|
|
15734
15835
|
const ordered = [...names.filter((n2) => n2 === `${role}.md`), ...names.filter((n2) => n2 !== `${role}.md`)];
|
|
15735
15836
|
for (const n2 of ordered) {
|
|
15736
15837
|
try {
|
|
15737
|
-
const a = parseAgent(
|
|
15838
|
+
const a = parseAgent(join62(d, n2), n2.slice(0, -3));
|
|
15738
15839
|
if (a && a.role === role)
|
|
15739
15840
|
return a;
|
|
15740
15841
|
} catch {}
|
|
@@ -15752,7 +15853,7 @@ var init_role_agents = __esm(() => {
|
|
|
15752
15853
|
|
|
15753
15854
|
// ../../loki-ts/src/util/child_ledger.ts
|
|
15754
15855
|
import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync27 } from "fs";
|
|
15755
|
-
import { join as
|
|
15856
|
+
import { join as join63 } from "path";
|
|
15756
15857
|
function unmeasuredRecord(phase, model, source) {
|
|
15757
15858
|
return { phase, model, input_tokens: 0, output_tokens: 0, cache_creation_tokens: 0, cache_read_tokens: 0, source, cost_status: "unmeasured" };
|
|
15758
15859
|
}
|
|
@@ -15777,9 +15878,9 @@ function recordFromClaudeResult(phase, payload, source = "claude-json") {
|
|
|
15777
15878
|
}
|
|
15778
15879
|
function appendChildLedger(lokiDir2, rec2) {
|
|
15779
15880
|
try {
|
|
15780
|
-
const dir =
|
|
15881
|
+
const dir = join63(lokiDir2, "metrics");
|
|
15781
15882
|
mkdirSync27(dir, { recursive: true });
|
|
15782
|
-
appendFileSync4(
|
|
15883
|
+
appendFileSync4(join63(dir, "child-sessions.jsonl"), `${JSON.stringify(rec2)}
|
|
15783
15884
|
`);
|
|
15784
15885
|
return true;
|
|
15785
15886
|
} catch {
|
|
@@ -15829,14 +15930,14 @@ var init_colors = __esm(() => {
|
|
|
15829
15930
|
});
|
|
15830
15931
|
|
|
15831
15932
|
// ../../loki-ts/src/util/run_summary.ts
|
|
15832
|
-
import { existsSync as
|
|
15833
|
-
import { join as
|
|
15933
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync28, readFileSync as readFileSync50, renameSync as renameSync12, statSync as statSync20, writeFileSync as writeFileSync30 } from "fs";
|
|
15934
|
+
import { join as join64 } from "path";
|
|
15834
15935
|
function readRiskRecord(repoDir, sinceMs = 0) {
|
|
15835
15936
|
try {
|
|
15836
|
-
const p =
|
|
15937
|
+
const p = join64(repoDir, ".loki", "state", "risk-tier.json");
|
|
15837
15938
|
if (statSync20(p).mtimeMs < sinceMs)
|
|
15838
15939
|
return null;
|
|
15839
|
-
const r = JSON.parse(
|
|
15940
|
+
const r = JSON.parse(readFileSync50(p, "utf8"));
|
|
15840
15941
|
return r && typeof r === "object" ? r : null;
|
|
15841
15942
|
} catch {
|
|
15842
15943
|
return null;
|
|
@@ -15851,8 +15952,8 @@ var init_run_summary = __esm(() => {
|
|
|
15851
15952
|
});
|
|
15852
15953
|
|
|
15853
15954
|
// ../../loki-ts/src/engine10/stages/xreview.ts
|
|
15854
|
-
import { existsSync as
|
|
15855
|
-
import { join as
|
|
15955
|
+
import { existsSync as existsSync43, readFileSync as readFileSync51 } from "fs";
|
|
15956
|
+
import { join as join65 } from "path";
|
|
15856
15957
|
function minVerdict(verdict, review) {
|
|
15857
15958
|
const ceiling = review?.level === "block" ? "PARTIAL" : verdict;
|
|
15858
15959
|
return RANK3[ceiling] < RANK3[verdict] ? ceiling : verdict;
|
|
@@ -15865,11 +15966,11 @@ function explicitReview(repoDir, env) {
|
|
|
15865
15966
|
if (flag && isOff(ev))
|
|
15866
15967
|
return "off";
|
|
15867
15968
|
for (const f of ["loki.yaml", "loki.yml"]) {
|
|
15868
|
-
const p =
|
|
15869
|
-
if (!
|
|
15969
|
+
const p = join65(repoDir, f);
|
|
15970
|
+
if (!existsSync43(p))
|
|
15870
15971
|
continue;
|
|
15871
15972
|
try {
|
|
15872
|
-
const m = /^review:[ \t]*["']?([A-Za-z]+)["']?[ \t]*(?:#.*)?$/m.exec(
|
|
15973
|
+
const m = /^review:[ \t]*["']?([A-Za-z]+)["']?[ \t]*(?:#.*)?$/m.exec(readFileSync51(p, "utf8"));
|
|
15873
15974
|
const v = asProvider(m?.[1]);
|
|
15874
15975
|
if (v)
|
|
15875
15976
|
return v;
|
|
@@ -15952,7 +16053,7 @@ Review ONLY the diff below. Do not modify files.` : "You are an independent code
|
|
|
15952
16053
|
try {
|
|
15953
16054
|
if (p === "claude")
|
|
15954
16055
|
await ensureClaudeHelpCache();
|
|
15955
|
-
const r = await withChildLedger(run,
|
|
16056
|
+
const r = await withChildLedger(run, join65(ctx.repoDir, ".loki"), "xreview")(reviewArgv(p, prompt, process.env, p === "claude" ? agent?.model : undefined), { cwd: ctx.repoDir, timeoutMs: TIMEOUT_MS });
|
|
15956
16057
|
if (r.exitCode !== 0)
|
|
15957
16058
|
return { provider: p, level: "not_run", notes: [`cross-review not run: ${p} exited ${r.exitCode}`] };
|
|
15958
16059
|
return parseReview(p, r.stdout);
|
|
@@ -16048,8 +16149,8 @@ See also: loki cost --detail (what a run ALREADY spent)
|
|
|
16048
16149
|
});
|
|
16049
16150
|
|
|
16050
16151
|
// ../../loki-ts/src/features/contract.ts
|
|
16051
|
-
import { existsSync as
|
|
16052
|
-
import { dirname as dirname28, join as
|
|
16152
|
+
import { existsSync as existsSync44, lstatSync as lstatSync16, mkdirSync as mkdirSync29, readFileSync as readFileSync52, rmSync as rmSync20, writeFileSync as writeFileSync31 } from "fs";
|
|
16153
|
+
import { dirname as dirname28, join as join66 } from "path";
|
|
16053
16154
|
import { createHash as createHash16 } from "crypto";
|
|
16054
16155
|
function contractEnabled(env = process.env) {
|
|
16055
16156
|
return env["LOKI_CONTRACT"] !== "0";
|
|
@@ -16081,7 +16182,7 @@ function untracedLines(trace) {
|
|
|
16081
16182
|
return trace.criteria.filter((c) => c.status === "no_match").map((c) => `contract ${sanitizeCriterion(c.id)} untraced (no keyword match in changed files): ${sanitizeCriterion(c.text)}`);
|
|
16082
16183
|
}
|
|
16083
16184
|
function contractPath(repoDir) {
|
|
16084
|
-
return
|
|
16185
|
+
return join66(repoDir, ".loki", "contract.json");
|
|
16085
16186
|
}
|
|
16086
16187
|
function readContract(repoDir) {
|
|
16087
16188
|
const p = contractPath(repoDir);
|
|
@@ -16097,7 +16198,7 @@ function readContract(repoDir) {
|
|
|
16097
16198
|
return { contract: null, notes: ["contract unreadable: too large"], sha256: null };
|
|
16098
16199
|
let raw2;
|
|
16099
16200
|
try {
|
|
16100
|
-
raw2 =
|
|
16201
|
+
raw2 = readFileSync52(p);
|
|
16101
16202
|
} catch {
|
|
16102
16203
|
return { contract: null, notes: ["contract unreadable: read failed"], sha256: null };
|
|
16103
16204
|
}
|
|
@@ -16166,17 +16267,17 @@ var init_contract = __esm(() => {
|
|
|
16166
16267
|
init_safe_git();
|
|
16167
16268
|
STOP3 = new Set(["the", "and", "for", "with", "that", "this", "must", "should", "shall", "when", "then", "are", "was", "all", "any", "can", "not", "has", "have", "from", "into", "each", "user", "users"]);
|
|
16168
16269
|
MAX_CONTRACT_BYTES = 1024 * 1024;
|
|
16169
|
-
REQ_MAP_REL =
|
|
16270
|
+
REQ_MAP_REL = join66(".loki", "state", "requirements-map.json");
|
|
16170
16271
|
REQ_STOP = new Set(["with", "that", "this", "from", "have", "will", "should", "must", "when", "then", "into", "each", "every", "user", "users", "page", "able", "allow", "support", "ensure", "using", "their", "there", "which", "shall"]);
|
|
16171
16272
|
});
|
|
16172
16273
|
|
|
16173
16274
|
// ../../loki-ts/src/features/speed/seal_group.ts
|
|
16174
16275
|
import { createHash as createHash17 } from "crypto";
|
|
16175
|
-
import { existsSync as
|
|
16176
|
-
import { dirname as dirname29, join as
|
|
16276
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync30, readdirSync as readdirSync23, readFileSync as readFileSync53, renameSync as renameSync13, statSync as statSync21, writeFileSync as writeFileSync32 } from "fs";
|
|
16277
|
+
import { dirname as dirname29, join as join67 } from "path";
|
|
16177
16278
|
function sealGroup(runDir, rh) {
|
|
16178
|
-
const manifestPath =
|
|
16179
|
-
if (!
|
|
16279
|
+
const manifestPath = join67(runDir, "group", "manifest.json");
|
|
16280
|
+
if (!existsSync45(manifestPath))
|
|
16180
16281
|
return { section: undefined, notProven: [], problems: 0, allUnitsPass: true };
|
|
16181
16282
|
const notProven = [];
|
|
16182
16283
|
let problems = 0;
|
|
@@ -16200,10 +16301,10 @@ function sealGroup(runDir, rh) {
|
|
|
16200
16301
|
return fail2(`unit ${index2} has an invalid, duplicate or case-colliding id`);
|
|
16201
16302
|
seen.add(id);
|
|
16202
16303
|
seenLower.add(id.toLowerCase());
|
|
16203
|
-
const dir =
|
|
16304
|
+
const dir = join67(unitsDir(runDir), id), rp = join67(dir, "receipt.json"), ep = join67(dir, "events.jsonl");
|
|
16204
16305
|
let bytes;
|
|
16205
16306
|
try {
|
|
16206
|
-
bytes =
|
|
16307
|
+
bytes = readFileSync53(rp);
|
|
16207
16308
|
} catch {
|
|
16208
16309
|
return fail2(`unit ${id} sub-receipt missing`);
|
|
16209
16310
|
}
|
|
@@ -16220,7 +16321,7 @@ function sealGroup(runDir, rh) {
|
|
|
16220
16321
|
unit_id: id,
|
|
16221
16322
|
sub_receipt_sha256: sha3(bytes),
|
|
16222
16323
|
receipt_sha256: sub2["receipt_sha256"],
|
|
16223
|
-
events_file_sha256:
|
|
16324
|
+
events_file_sha256: existsSync45(ep) ? sha3(readFileSync53(ep)) : null,
|
|
16224
16325
|
verdict,
|
|
16225
16326
|
goal: text2(u["goal"], 200),
|
|
16226
16327
|
files: (Array.isArray(u["files"]) ? u["files"] : []).map((f) => text2(f, 200)).filter(Boolean).slice(0, 50),
|
|
@@ -16245,7 +16346,7 @@ async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
|
|
|
16245
16346
|
const bad = (reason) => ({ verdict: "TAMPERED", reason: `group: ${reason}` });
|
|
16246
16347
|
const g = receipt["group"];
|
|
16247
16348
|
if (g === undefined)
|
|
16248
|
-
return
|
|
16349
|
+
return existsSync45(join67(runDir, "group", "manifest.json")) ? bad("group directory present but the receipt has no group section") : null;
|
|
16249
16350
|
if (!isObj10(g) || !ID_RE.test(String(g["group_id"] ?? "")) || !Array.isArray(g["units"]) || g["units"].length === 0)
|
|
16250
16351
|
return bad("group section malformed");
|
|
16251
16352
|
const entries = g["units"];
|
|
@@ -16257,20 +16358,20 @@ async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
|
|
|
16257
16358
|
return bad("unit directories do not match the receipt (missing or extra unit)");
|
|
16258
16359
|
let unchecked = null;
|
|
16259
16360
|
for (let i = 0;i < entries.length; i++) {
|
|
16260
|
-
const e = entries[i], id = ids[i], dir =
|
|
16361
|
+
const e = entries[i], id = ids[i], dir = join67(unitsDir(runDir), id), rp = join67(dir, "receipt.json"), ep = join67(dir, "events.jsonl");
|
|
16261
16362
|
if (e["index"] !== i)
|
|
16262
16363
|
return bad(`unit ${id} is out of order (index ${String(e["index"])} at position ${i})`);
|
|
16263
16364
|
let bytes;
|
|
16264
16365
|
try {
|
|
16265
16366
|
if (!statSync21(dir).isDirectory())
|
|
16266
16367
|
return bad(`unit ${id} is not a directory`);
|
|
16267
|
-
bytes =
|
|
16368
|
+
bytes = readFileSync53(rp);
|
|
16268
16369
|
} catch {
|
|
16269
16370
|
return bad(`unit ${id} sub-receipt missing`);
|
|
16270
16371
|
}
|
|
16271
16372
|
if (sha3(bytes) !== e["sub_receipt_sha256"])
|
|
16272
16373
|
return bad(`unit ${id} sub-receipt does not match its recorded hash`);
|
|
16273
|
-
const evSha =
|
|
16374
|
+
const evSha = existsSync45(ep) ? sha3(readFileSync53(ep)) : null;
|
|
16274
16375
|
if (evSha !== (e["events_file_sha256"] ?? null))
|
|
16275
16376
|
return bad(`unit ${id} events.jsonl does not match its recorded hash`);
|
|
16276
16377
|
const sub2 = readJson6(rp);
|
|
@@ -16293,15 +16394,15 @@ function compositeVerdict(childVerdicts) {
|
|
|
16293
16394
|
const failed2 = childVerdicts.filter((v) => v === "FAILED" || !["VERIFIED", "ALREADY_SATISFIED", "PARTIAL", "SPEC_CONFLICT"].includes(v)).length;
|
|
16294
16395
|
return capGroupVerdict(base, { section: undefined, notProven: [], problems: failed2, allUnitsPass: childVerdicts.every((v) => PASSING.has(v)) });
|
|
16295
16396
|
}
|
|
16296
|
-
var ID_RE, PASSING, sha3 = (b) => createHash17("sha256").update(b).digest("hex"), isObj10 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), text2 = (v, cap) => typeof v === "string" ? v.replace(/[\x00-\x1f\x7f]+/g, " ").trim().slice(0, cap) : "", num4 = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : 0, unitsDir = (runDir) =>
|
|
16397
|
+
var ID_RE, PASSING, sha3 = (b) => createHash17("sha256").update(b).digest("hex"), isObj10 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), text2 = (v, cap) => typeof v === "string" ? v.replace(/[\x00-\x1f\x7f]+/g, " ").trim().slice(0, cap) : "", num4 = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : 0, unitsDir = (runDir) => join67(runDir, "group", "units"), readJson6 = (p) => {
|
|
16297
16398
|
try {
|
|
16298
|
-
return JSON.parse(
|
|
16399
|
+
return JSON.parse(readFileSync53(p, "utf8"));
|
|
16299
16400
|
} catch {
|
|
16300
16401
|
return;
|
|
16301
16402
|
}
|
|
16302
16403
|
}, dirNames = (d) => {
|
|
16303
16404
|
try {
|
|
16304
|
-
return
|
|
16405
|
+
return readdirSync23(d).filter((n3) => !n3.startsWith(".")).sort();
|
|
16305
16406
|
} catch {
|
|
16306
16407
|
return null;
|
|
16307
16408
|
}
|
|
@@ -16313,8 +16414,8 @@ var init_seal_group = __esm(() => {
|
|
|
16313
16414
|
});
|
|
16314
16415
|
|
|
16315
16416
|
// ../../loki-ts/src/supply/supply_guard.ts
|
|
16316
|
-
import { existsSync as
|
|
16317
|
-
import { basename as
|
|
16417
|
+
import { existsSync as existsSync46, readFileSync as readFileSync54, statSync as statSync22 } from "fs";
|
|
16418
|
+
import { basename as basename24, join as join68 } from "path";
|
|
16318
16419
|
function supplyEnabled(env) {
|
|
16319
16420
|
return env["LOKI_SUPPLY_GUARD"] !== "0";
|
|
16320
16421
|
}
|
|
@@ -16326,16 +16427,16 @@ function supplyVerdict(verdict, r) {
|
|
|
16326
16427
|
return r.blocked && verdict === "VERIFIED" ? "FAILED" : verdict;
|
|
16327
16428
|
}
|
|
16328
16429
|
function isManifestPath(path) {
|
|
16329
|
-
return MANIFESTS.test(
|
|
16430
|
+
return MANIFESTS.test(basename24(path));
|
|
16330
16431
|
}
|
|
16331
16432
|
function readDeclared(repoDir) {
|
|
16332
|
-
const p =
|
|
16333
|
-
if (!
|
|
16433
|
+
const p = join68(repoDir, ".loki", DECLARED_FILE);
|
|
16434
|
+
if (!existsSync46(p))
|
|
16334
16435
|
return { deps: [], problem: null };
|
|
16335
16436
|
try {
|
|
16336
16437
|
if (statSync22(p).size > MAX_FILE_BYTES)
|
|
16337
16438
|
return { deps: [], problem: "declaration file too large" };
|
|
16338
|
-
const j = JSON.parse(
|
|
16439
|
+
const j = JSON.parse(readFileSync54(p, "utf8"));
|
|
16339
16440
|
if (!Array.isArray(j))
|
|
16340
16441
|
return { deps: [], problem: "declaration is not a JSON array" };
|
|
16341
16442
|
const deps = [];
|
|
@@ -16355,11 +16456,11 @@ function readDeclared(repoDir) {
|
|
|
16355
16456
|
}
|
|
16356
16457
|
}
|
|
16357
16458
|
function readAllowlist(repoDir) {
|
|
16358
|
-
const p =
|
|
16359
|
-
if (!
|
|
16459
|
+
const p = join68(repoDir, ".loki", "supply-allowlist");
|
|
16460
|
+
if (!existsSync46(p))
|
|
16360
16461
|
return new Set;
|
|
16361
16462
|
try {
|
|
16362
|
-
return new Set(
|
|
16463
|
+
return new Set(readFileSync54(p, "utf8").split(`
|
|
16363
16464
|
`).map((l) => l.replace(/#.*$/, "").trim()).filter(Boolean));
|
|
16364
16465
|
} catch {
|
|
16365
16466
|
return new Set;
|
|
@@ -16400,7 +16501,7 @@ function userConfigPrivate(eco, repoDir, env, goEnv = {}, name = "") {
|
|
|
16400
16501
|
if (eco === "npm") {
|
|
16401
16502
|
if (privateUrlList([env["npm_config_registry"] ?? "", env["NPM_CONFIG_REGISTRY"] ?? ""]))
|
|
16402
16503
|
return true;
|
|
16403
|
-
return files(
|
|
16504
|
+
return files(join68(repoDir, ".npmrc"), home ? join68(home, ".npmrc") : "").some((t) => t.split(`
|
|
16404
16505
|
`).some((l) => {
|
|
16405
16506
|
const m = /^\s*(?:(@[^:\s]+):)?registry\s*=\s*(\S+)/.exec(l);
|
|
16406
16507
|
return !!m && privateUrl(m[2]) && (m[1] === undefined || name.startsWith(`${m[1]}/`));
|
|
@@ -16409,7 +16510,7 @@ function userConfigPrivate(eco, repoDir, env, goEnv = {}, name = "") {
|
|
|
16409
16510
|
if (eco === "pypi") {
|
|
16410
16511
|
if (privateUrlList([env["PIP_INDEX_URL"] ?? "", env["PIP_EXTRA_INDEX_URL"] ?? ""]))
|
|
16411
16512
|
return true;
|
|
16412
|
-
const cfg = [env["PIP_CONFIG_FILE"] ?? "", home ?
|
|
16513
|
+
const cfg = [env["PIP_CONFIG_FILE"] ?? "", home ? join68(home, ".config", "pip", "pip.conf") : "", home ? join68(home, ".pip", "pip.conf") : "", join68(repoDir, "pip.conf")];
|
|
16413
16514
|
return files(...cfg).some((t) => t.split(`
|
|
16414
16515
|
`).some((l) => {
|
|
16415
16516
|
const m = /^\s*(?:extra-)?index-url\s*[=:]\s*(.+)$/.exec(l);
|
|
@@ -16419,7 +16520,7 @@ function userConfigPrivate(eco, repoDir, env, goEnv = {}, name = "") {
|
|
|
16419
16520
|
if (eco === "cargo") {
|
|
16420
16521
|
if (Object.keys(env).some((k) => /^CARGO_REGISTRIES_.+_INDEX$/.test(k) || /^CARGO_SOURCE_/.test(k)))
|
|
16421
16522
|
return true;
|
|
16422
|
-
return files(
|
|
16523
|
+
return files(join68(repoDir, ".cargo", "config.toml"), join68(repoDir, ".cargo", "config"), home ? join68(home, ".cargo", "config.toml") : "", home ? join68(home, ".cargo", "config") : "").some((t) => /^\s*\[(registries\.|source\.)/m.test(t) || /replace-with\s*=/.test(t));
|
|
16423
16524
|
}
|
|
16424
16525
|
if (eco === "go") {
|
|
16425
16526
|
const gp = goEnv["GOPROXY"] ?? env["GOPROXY"] ?? "";
|
|
@@ -16542,7 +16643,7 @@ var MIN_AGE_DAYS = 7, DECLARED_FILE = "supply-declared.json", MAX_CHECKED = 50,
|
|
|
16542
16643
|
}
|
|
16543
16644
|
}, PUBLIC_HOSTS, hostOf = (u) => u.trim().toLowerCase().replace(/^[a-z][a-z0-9+.-]*:\/\//, "").replace(/^www\./, "").split(/[/?#\s]/)[0].replace(/^[^@]*@/, "").replace(/:\d+$/, ""), privateUrl = (u) => /[a-z0-9]/i.test(u) && !PUBLIC_HOSTS.has(hostOf(u)), readSmall = (p) => {
|
|
16544
16645
|
try {
|
|
16545
|
-
return statSync22(p).size <= MAX_FILE_BYTES ?
|
|
16646
|
+
return statSync22(p).size <= MAX_FILE_BYTES ? readFileSync54(p, "utf8") : "";
|
|
16546
16647
|
} catch {
|
|
16547
16648
|
return "";
|
|
16548
16649
|
}
|
|
@@ -16558,8 +16659,8 @@ var init_supply_guard = __esm(() => {
|
|
|
16558
16659
|
|
|
16559
16660
|
// ../../loki-ts/src/engine10/stages/seal.ts
|
|
16560
16661
|
import { createHash as createHash18 } from "crypto";
|
|
16561
|
-
import { existsSync as
|
|
16562
|
-
import { basename as
|
|
16662
|
+
import { existsSync as existsSync47, readdirSync as readdirSync24, mkdirSync as mkdirSync31, readFileSync as readFileSync55 } from "fs";
|
|
16663
|
+
import { basename as basename25, isAbsolute as isAbsolute11, join as join69, relative as relative12 } from "path";
|
|
16563
16664
|
function receiptSha256(r) {
|
|
16564
16665
|
const { verification: _v, receipt_sha256: _h, ...body } = r;
|
|
16565
16666
|
return sha2562(canonicalJson(body));
|
|
@@ -16630,7 +16731,7 @@ function renderReceiptMd(r) {
|
|
|
16630
16731
|
`);
|
|
16631
16732
|
}
|
|
16632
16733
|
var DEEP_NOT_PROVEN, SIGNING_UNAVAILABLE = "receipt signing unavailable (no usable signing key: invalid key or unwritable ~/.loki/keys)", AGENT_ONLY_REASON = "only agent-authored tests executed (no agent-independent proof)", WALL_GREEN_ON_BASE_REASON = "Wall green on base: no Wall test discriminates the change", EXCLUDE_LOKI = ":(exclude).loki", sha2562 = (s) => createHash18("sha256").update(s).digest("hex"), str4 = (v) => typeof v === "string" && v !== "" ? v : null, strs2 = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string" && x !== "") : [], receiptRel = (ctx) => {
|
|
16633
|
-
const r =
|
|
16734
|
+
const r = relative12(ctx.repoDir, join69(ctx.runDir, "receipt.json"));
|
|
16634
16735
|
return r.startsWith("..") || isAbsolute11(r) ? `.loki/runs/${ctx.runId}/receipt.json` : r;
|
|
16635
16736
|
}, commitStage, wallGreenOnBaseOf = (o) => {
|
|
16636
16737
|
const b = o.wall?.base_run ?? {};
|
|
@@ -16750,8 +16851,8 @@ var init_seal = __esm(() => {
|
|
|
16750
16851
|
notProven.add(`Wall test not executed: ${wallNotRun} file(s), no reason recorded`);
|
|
16751
16852
|
if (wallNotRun > 0) {
|
|
16752
16853
|
try {
|
|
16753
|
-
const kept = new Set((Array.isArray(o.wall?.files) ? o.wall.files : []).map((f) =>
|
|
16754
|
-
for (const n3 of
|
|
16854
|
+
const kept = new Set((Array.isArray(o.wall?.files) ? o.wall.files : []).map((f) => basename25(String(f.path))));
|
|
16855
|
+
for (const n3 of readdirSync24(join69(ctx.runDir, "wall")).sort())
|
|
16755
16856
|
if (!kept.has(n3))
|
|
16756
16857
|
notProven.add(`wall test discarded: ${n3} (not_run)`);
|
|
16757
16858
|
} catch {}
|
|
@@ -16779,8 +16880,10 @@ var init_seal = __esm(() => {
|
|
|
16779
16880
|
for (const f of uncoveredAfterLimit)
|
|
16780
16881
|
notProven.add(`changed, untested after limit: ${f}`);
|
|
16781
16882
|
for (const c of checks)
|
|
16782
|
-
if (c.result === "not_run")
|
|
16883
|
+
if (c.result === "not_run" && !strs2(o.verify?.skipped_on_base).includes(c.name))
|
|
16783
16884
|
notProven.add(`not run: ${c.name}`);
|
|
16885
|
+
for (const n3 of strs2(o.verify?.skipped_on_base))
|
|
16886
|
+
notProven.add(`skipped on base (excused): ${n3}`);
|
|
16784
16887
|
for (const f of strs2(o.verify?.flaky))
|
|
16785
16888
|
notProven.add(`flaky test: ${f}`);
|
|
16786
16889
|
for (const n3 of verifyNotProven)
|
|
@@ -16814,19 +16917,19 @@ var init_seal = __esm(() => {
|
|
|
16814
16917
|
for (const [s, d] of Object.entries(o))
|
|
16815
16918
|
if (typeof d?.duration_s === "number")
|
|
16816
16919
|
stages[s] = d.duration_s;
|
|
16817
|
-
const T = hooks.time, time = T ? T.build(ctx, stages, T.firstEventMs(
|
|
16920
|
+
const T = hooks.time, time = T ? T.build(ctx, stages, T.firstEventMs(join69(ctx.runDir, "events.jsonl"))) : { wall_s: Object.values(stages).reduce((a, b) => a + (b ?? 0), 0), stages }, totalS = T?.reconciled(time) ?? null;
|
|
16818
16921
|
const iterIds = [...new Set([...Object.values(o).flatMap((d) => [...strs2(d?.iteration_ids), ...strs2([d?.iteration_id])]), ...ctx.sessionIds?.() ?? []])];
|
|
16819
16922
|
if (iterIds.length === 0)
|
|
16820
16923
|
notProven.add("cost not measured (no iteration ids recorded)");
|
|
16821
16924
|
const cost = ctx.cost.read(ctx.repoDir, iterIds);
|
|
16822
16925
|
if (cost.unmetered)
|
|
16823
16926
|
notProven.add("cost unmetered (CLI invoker; recorded as 0)");
|
|
16824
|
-
const eventsPath =
|
|
16927
|
+
const eventsPath = join69(ctx.runDir, "events.jsonl");
|
|
16825
16928
|
const wallFiles = Array.isArray(o.wall?.files) ? o.wall.files : [];
|
|
16826
16929
|
const wallPassed = typeof o.verify?.wall_passed === "boolean" ? o.verify.wall_passed : null;
|
|
16827
16930
|
if (wallFiles.length > 0 && wallPassed === null)
|
|
16828
16931
|
notProven.add("wall result not recorded by verify");
|
|
16829
|
-
const routeBlock = buildRouteBlock(process.env, ctx.provider, o.implement?.route ?? o.plan?.route_record ?? (routerEnabled(process.env) ? loadRouteRecord(ctx.runDir) : undefined), cost.router ?? (routerEnabled(process.env) ? sumResultCosts(
|
|
16932
|
+
const routeBlock = buildRouteBlock(process.env, ctx.provider, o.implement?.route ?? o.plan?.route_record ?? (routerEnabled(process.env) ? loadRouteRecord(ctx.runDir) : undefined), cost.router ?? (routerEnabled(process.env) ? sumResultCosts(join69(ctx.repoDir, ".loki"), liveArchivedCosts(join69(ctx.repoDir, ".loki"), iterIds, UNMETERED)).router : undefined), ctx.model);
|
|
16830
16933
|
if (routeBlock)
|
|
16831
16934
|
for (const l of routeNotProven(routeBlock))
|
|
16832
16935
|
notProven.add(l);
|
|
@@ -16868,7 +16971,7 @@ var init_seal = __esm(() => {
|
|
|
16868
16971
|
provider: ctx.provider,
|
|
16869
16972
|
model: ctx.model,
|
|
16870
16973
|
resumed: o.intake?.resumed === true,
|
|
16871
|
-
events_sha256: sha2562(
|
|
16974
|
+
events_sha256: sha2562(existsSync47(eventsPath) ? readFileSync55(eventsPath) : ""),
|
|
16872
16975
|
...await sealEvidence(ctx.repoDir, ctx.runDir, o, notProven, signal, ctx.emit),
|
|
16873
16976
|
log_seal: true,
|
|
16874
16977
|
toolchain: collectToolchain(),
|
|
@@ -16892,10 +16995,10 @@ var init_seal = __esm(() => {
|
|
|
16892
16995
|
}
|
|
16893
16996
|
const receipt = { ...body, receipt_sha256: hash, verification: { jwt: sig.jwt, kid: sig.kid } };
|
|
16894
16997
|
mkdirSync31(ctx.runDir, { recursive: true });
|
|
16895
|
-
const path =
|
|
16998
|
+
const path = join69(ctx.runDir, "receipt.json");
|
|
16896
16999
|
atomicWriteText(path, JSON.stringify(receipt, null, 2) + `
|
|
16897
17000
|
`);
|
|
16898
|
-
atomicWriteText(
|
|
17001
|
+
atomicWriteText(join69(ctx.runDir, "receipt.md"), renderReceiptMd(receipt));
|
|
16899
17002
|
recordRun(process.env, ctx.repoDir, ranModel(o.implement, ctx.model, o.fix), verdict, cost.usd, cost.unmetered === true, totalS);
|
|
16900
17003
|
try {
|
|
16901
17004
|
hooks.sealed?.(ctx.runDir, JSON.parse(JSON.stringify(receipt), (_k, v) => v && typeof v === "object" ? Object.freeze(v) : v));
|
|
@@ -16920,14 +17023,14 @@ var init_seal = __esm(() => {
|
|
|
16920
17023
|
});
|
|
16921
17024
|
|
|
16922
17025
|
// ../../loki-ts/src/util/composite_seal.ts
|
|
16923
|
-
import { existsSync as
|
|
16924
|
-
import { basename as
|
|
17026
|
+
import { existsSync as existsSync48, readFileSync as readFileSync56 } from "fs";
|
|
17027
|
+
import { basename as basename26, dirname as dirname31, join as join70 } from "path";
|
|
16925
17028
|
function logProblem(runDir, integ) {
|
|
16926
17029
|
if (typeof integ["log_sha256"] !== "string")
|
|
16927
17030
|
return null;
|
|
16928
17031
|
let b;
|
|
16929
17032
|
try {
|
|
16930
|
-
b =
|
|
17033
|
+
b = readFileSync56(join70(runDir, "integration.log"));
|
|
16931
17034
|
} catch {
|
|
16932
17035
|
return "integration.log is missing but integration.json records its hash";
|
|
16933
17036
|
}
|
|
@@ -16950,13 +17053,13 @@ async function verifyComposite(receiptPath, receipt, rh, verifyOne, deps = {}) {
|
|
|
16950
17053
|
return bad("body malformed");
|
|
16951
17054
|
let ibytes;
|
|
16952
17055
|
try {
|
|
16953
|
-
ibytes =
|
|
17056
|
+
ibytes = readFileSync56(join70(runDir, "integration.json"));
|
|
16954
17057
|
} catch {
|
|
16955
17058
|
return bad("integration.json missing");
|
|
16956
17059
|
}
|
|
16957
17060
|
if (sha3(ibytes) !== receipt["integration_sha256"])
|
|
16958
17061
|
return bad("integration.json does not match its recorded hash");
|
|
16959
|
-
const integ = readJson6(
|
|
17062
|
+
const integ = readJson6(join70(runDir, "integration.json"));
|
|
16960
17063
|
if (!isObj10(integ) || !isObj10(integ["outcomes"]))
|
|
16961
17064
|
return bad("integration.json has no outcomes");
|
|
16962
17065
|
const iprob = integrationProblem(integ);
|
|
@@ -16991,10 +17094,10 @@ async function verifyComposite(receiptPath, receipt, rh, verifyOne, deps = {}) {
|
|
|
16991
17094
|
return bad(`child ${text2(repo, 80) || "?"} has an invalid receipt path`);
|
|
16992
17095
|
if (outcomes[repo] !== "ok")
|
|
16993
17096
|
return bad(`child ${text2(repo, 80)} did not finish ok in integration.json`);
|
|
16994
|
-
const rp =
|
|
17097
|
+
const rp = join70(runDir, rel);
|
|
16995
17098
|
let bytes;
|
|
16996
17099
|
try {
|
|
16997
|
-
bytes =
|
|
17100
|
+
bytes = readFileSync56(rp);
|
|
16998
17101
|
} catch {
|
|
16999
17102
|
return bad(`child ${repo} receipt missing`);
|
|
17000
17103
|
}
|
|
@@ -17043,8 +17146,8 @@ var init_keys_cmd = __esm(() => {
|
|
|
17043
17146
|
});
|
|
17044
17147
|
|
|
17045
17148
|
// ../../loki-ts/src/engine10/verify_cmd.ts
|
|
17046
|
-
import { existsSync as
|
|
17047
|
-
import { basename as
|
|
17149
|
+
import { existsSync as existsSync49, readFileSync as readFileSync57, renameSync as renameSync14, statSync as statSync24, writeFileSync as writeFileSync33 } from "fs";
|
|
17150
|
+
import { basename as basename27, dirname as dirname32, join as join71 } from "path";
|
|
17048
17151
|
import { createHash as createHash19, createPublicKey as createPublicKey4, verify as verify4 } from "crypto";
|
|
17049
17152
|
function pubFor(kid, given) {
|
|
17050
17153
|
if (given)
|
|
@@ -17052,7 +17155,7 @@ function pubFor(kid, given) {
|
|
|
17052
17155
|
const active = loadSigningKey(false);
|
|
17053
17156
|
const pubs = (process.env["LOKI_RECEIPT_RETIRED_PUBKEYS"] ?? "").split(":").map((f) => f.trim()).filter(Boolean).flatMap((f) => {
|
|
17054
17157
|
try {
|
|
17055
|
-
return [createPublicKey4(
|
|
17158
|
+
return [createPublicKey4(readFileSync57(f))];
|
|
17056
17159
|
} catch {
|
|
17057
17160
|
return [];
|
|
17058
17161
|
}
|
|
@@ -17096,10 +17199,10 @@ function checkEventLog(receiptPath, receipt) {
|
|
|
17096
17199
|
const claims = st !== null && typeof st === "object" && Object.keys(st).length > 0;
|
|
17097
17200
|
return claims ? "the receipt records stages but binds the empty-log hash, so no events.jsonl can back it (missing, empty or non-empty); the receipt is forged or was sealed without a log. Re-run the task to produce a fresh receipt" : null;
|
|
17098
17201
|
}
|
|
17099
|
-
const path =
|
|
17100
|
-
if (!
|
|
17202
|
+
const path = join71(dirname32(receiptPath), "events.jsonl");
|
|
17203
|
+
if (!existsSync49(path))
|
|
17101
17204
|
return "events.jsonl is missing";
|
|
17102
|
-
const raw2 =
|
|
17205
|
+
const raw2 = readFileSync57(path, "utf8"), events2 = readEvents(path), lines2 = raw2.split(`
|
|
17103
17206
|
`).filter((l) => l.trim() !== "");
|
|
17104
17207
|
if (events2.length !== lines2.length || events2.some((e, i) => e.seq !== i))
|
|
17105
17208
|
return "events.jsonl has a forged, edited or missing line";
|
|
@@ -17115,7 +17218,7 @@ function checkEventLog(receiptPath, receipt) {
|
|
|
17115
17218
|
return h.digest("hex") === bound ? null : "events.jsonl does not match the hash recorded at seal";
|
|
17116
17219
|
}
|
|
17117
17220
|
function checkLogSeal(receiptPath, hash, kid, given) {
|
|
17118
|
-
const path =
|
|
17221
|
+
const path = join71(dirname32(receiptPath), "events.jsonl"), events2 = readEvents(path), done = events2.findIndex((e) => e.type === "run.completed");
|
|
17119
17222
|
if (!events2.some((e) => e.type === "receipt.sealed" && e.data["receipt_sha256"] === hash))
|
|
17120
17223
|
return { verdict: "TAMPERED", reason: "events.jsonl has no receipt.sealed event for this receipt" };
|
|
17121
17224
|
if (done < 0)
|
|
@@ -17123,7 +17226,7 @@ function checkLogSeal(receiptPath, hash, kid, given) {
|
|
|
17123
17226
|
const seal = events2[done + 1], d = seal?.type === "log.sealed" ? seal.data : null;
|
|
17124
17227
|
if (!d)
|
|
17125
17228
|
return { verdict: "TAMPERED", reason: "events.jsonl has no signed log.sealed line after run.completed" };
|
|
17126
|
-
const lines2 =
|
|
17229
|
+
const lines2 = readFileSync57(path, "utf8").split(`
|
|
17127
17230
|
`).filter((l) => l.trim() !== ""), sha4 = createHash19("sha256").update(lines2.slice(0, done + 1).join(`
|
|
17128
17231
|
`) + `
|
|
17129
17232
|
`).digest("hex");
|
|
@@ -17133,11 +17236,11 @@ function checkLogSeal(receiptPath, hash, kid, given) {
|
|
|
17133
17236
|
return null;
|
|
17134
17237
|
}
|
|
17135
17238
|
async function verifyReceipt(receiptPath, deps = {}) {
|
|
17136
|
-
if (!
|
|
17239
|
+
if (!existsSync49(receiptPath))
|
|
17137
17240
|
return { verdict: "UNCHECKED", reasons: [`receipt not found: ${receiptPath}`] };
|
|
17138
17241
|
let receipt;
|
|
17139
17242
|
try {
|
|
17140
|
-
receipt = JSON.parse((deps.read ?? ((p) =>
|
|
17243
|
+
receipt = JSON.parse((deps.read ?? ((p) => readFileSync57(p, "utf8")))(receiptPath));
|
|
17141
17244
|
} catch {
|
|
17142
17245
|
return { verdict: "UNCHECKED", reasons: ["receipt.json is not valid JSON"] };
|
|
17143
17246
|
}
|
|
@@ -17226,8 +17329,8 @@ var init_verify_cmd = __esm(() => {
|
|
|
17226
17329
|
});
|
|
17227
17330
|
|
|
17228
17331
|
// src/server/app.ts
|
|
17229
|
-
import { existsSync as
|
|
17230
|
-
import { join as
|
|
17332
|
+
import { existsSync as existsSync51, readFileSync as readFileSync60, statSync as statSync25 } from "fs";
|
|
17333
|
+
import { join as join74, resolve as resolve17, sep as sep16 } from "path";
|
|
17231
17334
|
|
|
17232
17335
|
// node_modules/hono/dist/request/constants.js
|
|
17233
17336
|
var GET_MATCH_RESULT = Symbol();
|
|
@@ -27499,9 +27602,9 @@ function mount20(ctx) {
|
|
|
27499
27602
|
}
|
|
27500
27603
|
|
|
27501
27604
|
// src/server/routes/verify.ts
|
|
27502
|
-
import { readFileSync as
|
|
27605
|
+
import { readFileSync as readFileSync58, realpathSync as realpathSync24 } from "fs";
|
|
27503
27606
|
import { createPublicKey as createPublicKey5 } from "crypto";
|
|
27504
|
-
import { join as
|
|
27607
|
+
import { join as join72, sep as sep15 } from "path";
|
|
27505
27608
|
init_verify_cmd();
|
|
27506
27609
|
init_seal();
|
|
27507
27610
|
init_receipt_dsse();
|
|
@@ -27528,15 +27631,15 @@ function mount21(ctx) {
|
|
|
27528
27631
|
return done(404, "receipt not available", "not_found");
|
|
27529
27632
|
let runDir, file;
|
|
27530
27633
|
try {
|
|
27531
|
-
const root =
|
|
27532
|
-
runDir =
|
|
27533
|
-
if (runDir !==
|
|
27634
|
+
const root = realpathSync24(join72(repo.p, ".loki", "runs"));
|
|
27635
|
+
runDir = realpathSync24(join72(root, run2));
|
|
27636
|
+
if (runDir !== join72(root, run2))
|
|
27534
27637
|
return done(404, "receipt not found", "not_found");
|
|
27535
|
-
file =
|
|
27638
|
+
file = realpathSync24(join72(runDir, "receipt.json"));
|
|
27536
27639
|
} catch {
|
|
27537
27640
|
return done(404, "receipt not found", "not_found");
|
|
27538
27641
|
}
|
|
27539
|
-
if (!file.startsWith(runDir +
|
|
27642
|
+
if (!file.startsWith(runDir + sep15))
|
|
27540
27643
|
return done(404, "receipt not found", "not_found");
|
|
27541
27644
|
let integrity, reasons, sha4 = null, outcome = "UNREADABLE";
|
|
27542
27645
|
try {
|
|
@@ -27551,7 +27654,7 @@ function mount21(ctx) {
|
|
|
27551
27654
|
sha4 = r.receiptSha256 ?? null;
|
|
27552
27655
|
}
|
|
27553
27656
|
try {
|
|
27554
|
-
outcome = outcomeOf(JSON.parse(
|
|
27657
|
+
outcome = outcomeOf(JSON.parse(readFileSync58(file, "utf8")));
|
|
27555
27658
|
} catch {
|
|
27556
27659
|
outcome = "UNREADABLE";
|
|
27557
27660
|
}
|
|
@@ -27613,8 +27716,8 @@ function ttlCache(ttlMs = PROBE_CACHE_MS, now2 = Date.now) {
|
|
|
27613
27716
|
}
|
|
27614
27717
|
|
|
27615
27718
|
// src/server/legacy/shim.ts
|
|
27616
|
-
import { existsSync as
|
|
27617
|
-
import { join as
|
|
27719
|
+
import { existsSync as existsSync50, readFileSync as readFileSync59 } from "fs";
|
|
27720
|
+
import { join as join73 } from "path";
|
|
27618
27721
|
|
|
27619
27722
|
// src/server/legacy/routes.ts
|
|
27620
27723
|
var LEGACY_ROUTES = [
|
|
@@ -27992,10 +28095,10 @@ var logged = new Set;
|
|
|
27992
28095
|
var toHono = (p) => p.replace(/\{([A-Za-z_]+):path\}/g, ":$1{.+}").replace(/\{([A-Za-z_]+)\}/g, ":$1");
|
|
27993
28096
|
var NOT_SUPPORTED = "not yet supported by the Control Plane";
|
|
27994
28097
|
var repoVersion = () => {
|
|
27995
|
-
for (const f of [
|
|
28098
|
+
for (const f of [join73(import.meta.dir, "../../../../../VERSION")]) {
|
|
27996
28099
|
try {
|
|
27997
|
-
if (
|
|
27998
|
-
return
|
|
28100
|
+
if (existsSync50(f))
|
|
28101
|
+
return readFileSync59(f, "utf8").trim();
|
|
27999
28102
|
} catch {}
|
|
28000
28103
|
}
|
|
28001
28104
|
return "unknown";
|
|
@@ -28177,7 +28280,7 @@ function legacyShim(opts) {
|
|
|
28177
28280
|
|
|
28178
28281
|
// src/server/app.ts
|
|
28179
28282
|
var MAX_BODY2 = 1e6;
|
|
28180
|
-
var defaultUiDir = () => [
|
|
28283
|
+
var defaultUiDir = () => [join74(import.meta.dir, "../../ui/dist"), join74(import.meta.dir, "../ui/dist")].find((d) => existsSync51(join74(d, "index.html")));
|
|
28181
28284
|
function createApp(opts) {
|
|
28182
28285
|
const uiDir = opts.uiDir ?? defaultUiDir();
|
|
28183
28286
|
const { db, sqlite } = openDb(opts.dbPath);
|
|
@@ -28206,10 +28309,10 @@ function createApp(opts) {
|
|
|
28206
28309
|
await next();
|
|
28207
28310
|
});
|
|
28208
28311
|
const readInstalled = () => {
|
|
28209
|
-
for (const f of [process.env.LOKI_VERSION_FILE,
|
|
28312
|
+
for (const f of [process.env.LOKI_VERSION_FILE, join74(import.meta.dir, "../../../../VERSION")]) {
|
|
28210
28313
|
try {
|
|
28211
28314
|
if (f)
|
|
28212
|
-
return
|
|
28315
|
+
return readFileSync60(f, "utf8").trim() || "unknown";
|
|
28213
28316
|
} catch {}
|
|
28214
28317
|
}
|
|
28215
28318
|
return "unknown";
|
|
@@ -28318,13 +28421,13 @@ function createApp(opts) {
|
|
|
28318
28421
|
}
|
|
28319
28422
|
if (!uiDir || p.startsWith("/v1/"))
|
|
28320
28423
|
return c.json({ error: "not found" }, 404);
|
|
28321
|
-
const root =
|
|
28322
|
-
const f =
|
|
28323
|
-
if (f.startsWith(root +
|
|
28424
|
+
const root = resolve17(uiDir);
|
|
28425
|
+
const f = resolve17(root, `.${p}`);
|
|
28426
|
+
if (f.startsWith(root + sep16) && existsSync51(f) && statSync25(f).isFile())
|
|
28324
28427
|
return new Response(Bun.file(f));
|
|
28325
28428
|
if (/\.[a-z0-9]+$/i.test(p))
|
|
28326
28429
|
return c.json({ error: "not found" }, 404);
|
|
28327
|
-
return new Response(Bun.file(
|
|
28430
|
+
return new Response(Bun.file(join74(root, "index.html")));
|
|
28328
28431
|
});
|
|
28329
28432
|
return { app, db, close: () => {
|
|
28330
28433
|
clearInterval(reconciler);
|