loki-mode 11.17.74 → 11.17.75
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 +12 -0
- package/docs/v10/PROGRESS.md +3 -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 +445 -349
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/web-app/dist/assets/{AdminPage-BMEz6PjD.js → AdminPage-ckrZehcf.js} +1 -1
- package/web-app/dist/assets/{Avatar-CWqr7n5f.js → Avatar-B0cf3aVA.js} +1 -1
- package/web-app/dist/assets/{Badge-0HwtDygF.js → Badge-Ds_hvQoP.js} +1 -1
- package/web-app/dist/assets/{Button-9dckZRDN.js → Button-DTUAVmt5.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-nYMuXSfl.js → CockpitPage-DF7RtcXW.js} +1 -1
- package/web-app/dist/assets/{ComparePage-Bc5srye5.js → ComparePage-BHAQBZK0.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-BkDMHZsx.js → ErrorBoundary-Xg5ORKQJ.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-M8zrEQxG.js → EvidenceReceiptPanel-CdS9tMxc.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-MvOtqrJO.js → GitHubIssuesPanel-hvk0yVL-.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-Cx6sFkSQ.js → GitHubPRsPanel-CfIFqgI3.js} +1 -1
- package/web-app/dist/assets/{HomePage-KoGFVyhn.js → HomePage-CyijuFBr.js} +2 -2
- package/web-app/dist/assets/{LoginPage-BJKuRfBJ.js → LoginPage-B5S7e7ee.js} +1 -1
- package/web-app/dist/assets/{MagicPage-CH19MKyX.js → MagicPage-Bjc2F-ce.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-CTiPy6uL.js → MetricsPage-0jsT2phC.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-B3x9Admx.js → NotFoundPage-rQ2fotgB.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-B7NMYrmn.js → ProjectPage-BToxnl4V.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-BNbo3wR3.js → ProjectsPage-CDZb1rLe.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-Dk9w3rKx.js → SettingsPage-DZXRZ9gX.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-Dk7LBonS.js → ShowcasePage-Dx0RfAv3.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-FTbJ_2Hn.js → SystemSettingsPage-Bjh8M7PU.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-CdKmEVIO.js → TeamsPage-D8VRFBhr.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-Du6EHrwu.js → TemplatesPage-M2fz0DZW.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-BTlTI6D7.js → TerminalOutput-CFiTiJiH.js} +1 -1
- package/web-app/dist/assets/{activity-BXuoHaM2.js → activity-BpEti4MN.js} +1 -1
- package/web-app/dist/assets/{bell-DCDgirjw.js → bell-DGSGGaVr.js} +1 -1
- package/web-app/dist/assets/{bot-vJgiSrdQ.js → bot-BhbuP5Jx.js} +1 -1
- package/web-app/dist/assets/{check-D-RGuqkl.js → check-XA1EKiOV.js} +1 -1
- package/web-app/dist/assets/{chevron-left-NKl5Cd-R.js → chevron-left-BVn1BhDN.js} +1 -1
- package/web-app/dist/assets/{circle-alert-ByXEu_ry.js → circle-alert-CuDH-xVA.js} +1 -1
- package/web-app/dist/assets/{clock-sHF7TkaL.js → clock-DOexYJz7.js} +1 -1
- package/web-app/dist/assets/{cloud-D6mqiMKo.js → cloud-BzhyIUtk.js} +1 -1
- package/web-app/dist/assets/{code-xml-huk-YFT0.js → code-xml-8JwaEdd2.js} +1 -1
- package/web-app/dist/assets/{database-BOlnZ1VP.js → database-CHAlm7GD.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-BkQRFa0q.js → dollar-sign-DMn1Z2mk.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-ugbZnTSY.js → file-code-corner-DXUwz0qn.js} +1 -1
- package/web-app/dist/assets/{file-plus-C36sokvh.js → file-plus-9Avu5l_j.js} +1 -1
- package/web-app/dist/assets/{globe-CJQelTw1.js → globe-CaI5OyzR.js} +1 -1
- package/web-app/dist/assets/{hammer-DPzU4Wtq.js → hammer-39YmcOpO.js} +1 -1
- package/web-app/dist/assets/{index-CmNcswQv.js → index-Cud61p9W.js} +3 -3
- package/web-app/dist/assets/{layers-DzMH-GEN.js → layers-Cy4XzPLx.js} +1 -1
- package/web-app/dist/assets/{loader-circle-BNbNqvck.js → loader-circle-D-xd2rX_.js} +1 -1
- package/web-app/dist/assets/{lock-9PCIcJ6T.js → lock-BjX622xw.js} +1 -1
- package/web-app/dist/assets/{package-j3aJqney.js → package-DJM9D0vQ.js} +1 -1
- package/web-app/dist/assets/{plus-DGAY2LNf.js → plus-NJgfTSYU.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-BBJiyS_M.js → refresh-cw-bk2f-EWd.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-BNLXFero.js → rotate-ccw-CAhHbrgP.js} +1 -1
- package/web-app/dist/assets/{scroll-text-CGG6Enap.js → scroll-text-Hw2Dmd7B.js} +1 -1
- package/web-app/dist/assets/{server-Bv6QDqpn.js → server-BQbvhpJk.js} +1 -1
- package/web-app/dist/assets/{shield-alert-BFJHSdqK.js → shield-alert-C2MGmd4Q.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-BGbIHMwH.js → thumbs-up-BAQFLfSO.js} +1 -1
- package/web-app/dist/assets/{trash-2-C7mlnJL3.js → trash-2-okuerJdv.js} +1 -1
- package/web-app/dist/assets/{trending-down-BbxICDz5.js → trending-down-dl0Y9tN6.js} +1 -1
- package/web-app/dist/assets/{trending-up-DQqCw2fH.js → trending-up-CzeGIsMl.js} +1 -1
- package/web-app/dist/assets/{upload-SWiggmcJ.js → upload-tkq9_bgk.js} +1 -1
- package/web-app/dist/assets/{usePolling-CTxzJty2.js → usePolling-BQeWmnOa.js} +1 -1
- package/web-app/dist/assets/{user-DPVl5QyH.js → user-DOXirXaZ.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)
|
|
@@ -10749,25 +10840,25 @@ var init_state = __esm(() => {
|
|
|
10749
10840
|
|
|
10750
10841
|
// ../../loki-ts/src/runner/repo_profile.ts
|
|
10751
10842
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
10752
|
-
import { existsSync as
|
|
10753
|
-
import { basename as
|
|
10843
|
+
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";
|
|
10844
|
+
import { basename as basename14, join as join40, resolve as resolve14, isAbsolute as isAbsolute4 } from "path";
|
|
10754
10845
|
function detectFormatters(repoDir) {
|
|
10755
10846
|
const out2 = [];
|
|
10756
|
-
const has = (...fs2) => fs2.some((f) =>
|
|
10757
|
-
const pp = read(
|
|
10847
|
+
const has = (...fs2) => fs2.some((f) => existsSync25(join40(repoDir, f)));
|
|
10848
|
+
const pp = read(join40(repoDir, "pyproject.toml")), pj = read(join40(repoDir, "package.json"));
|
|
10758
10849
|
if (/\[tool\.ruff/.test(pp) || has("ruff.toml", ".ruff.toml"))
|
|
10759
10850
|
out2.push({ tool: "ruff", argv: ["ruff", "format"], exts: /\.pyi?$/ });
|
|
10760
10851
|
let prettierKey = false;
|
|
10761
10852
|
try {
|
|
10762
10853
|
prettierKey = pj !== "" && "prettier" in JSON.parse(pj);
|
|
10763
10854
|
} catch {}
|
|
10764
|
-
const local =
|
|
10765
|
-
if ((prettierKey ||
|
|
10855
|
+
const local = join40(repoDir, "node_modules", ".bin", "prettier");
|
|
10856
|
+
if ((prettierKey || readdirSync16(repoDir).some((f) => /^(\.prettierrc(\.[a-z0-9]+)?|prettier\.config\.[cm]?[jt]s)$/.test(f))) && existsSync25(local))
|
|
10766
10857
|
out2.push({ tool: "prettier", argv: [local, "--write"], exts: /\.(?:[cm]?[jt]sx?|json|css|scss|md|ya?ml|html)$/ });
|
|
10767
10858
|
if (has("go.mod"))
|
|
10768
10859
|
out2.push({ tool: "gofmt", argv: ["gofmt", "-w"], exts: /\.go$/ });
|
|
10769
10860
|
if (has("rustfmt.toml", ".rustfmt.toml")) {
|
|
10770
|
-
const ed = /^\s*edition\s*=\s*"(\d+)"/m.exec(read(
|
|
10861
|
+
const ed = /^\s*edition\s*=\s*"(\d+)"/m.exec(read(join40(repoDir, "Cargo.toml")))?.[1];
|
|
10771
10862
|
out2.push({ tool: "rustfmt", argv: ["rustfmt", ...ed ? ["--edition", ed] : []], exts: /\.rs$/ });
|
|
10772
10863
|
}
|
|
10773
10864
|
return out2;
|
|
@@ -10776,7 +10867,7 @@ function runFormatters(repoDir, files, env) {
|
|
|
10776
10867
|
const fmts = detectFormatters(repoDir);
|
|
10777
10868
|
const mine = fmts.length ? files.filter((f) => {
|
|
10778
10869
|
try {
|
|
10779
|
-
return lstatSync10(
|
|
10870
|
+
return lstatSync10(join40(repoDir, f)).isFile();
|
|
10780
10871
|
} catch {
|
|
10781
10872
|
return false;
|
|
10782
10873
|
}
|
|
@@ -10789,7 +10880,7 @@ function runFormatters(repoDir, files, env) {
|
|
|
10789
10880
|
}
|
|
10790
10881
|
function loadProfile(repoDir) {
|
|
10791
10882
|
try {
|
|
10792
|
-
const p = JSON.parse(
|
|
10883
|
+
const p = JSON.parse(readFileSync31(commandProfilePath(repoDir), "utf8"));
|
|
10793
10884
|
return p?.version === 1 && Array.isArray(p.commands) && p.baseline ? p : null;
|
|
10794
10885
|
} catch {
|
|
10795
10886
|
return null;
|
|
@@ -10890,9 +10981,9 @@ async function staticPreExisting(tool, prefix, files, io) {
|
|
|
10890
10981
|
}
|
|
10891
10982
|
return attributeStatic(tool, head.out, baseOut, 1).preExisting;
|
|
10892
10983
|
}
|
|
10893
|
-
var commandProfilePath = (repoDir) =>
|
|
10984
|
+
var commandProfilePath = (repoDir) => join40(repoDir, ".loki", "state", "repo-profile.json"), read = (p) => {
|
|
10894
10985
|
try {
|
|
10895
|
-
return
|
|
10986
|
+
return readFileSync31(p, "utf8");
|
|
10896
10987
|
} catch {
|
|
10897
10988
|
return "";
|
|
10898
10989
|
}
|
|
@@ -10938,14 +11029,14 @@ var init_context = __esm(() => {
|
|
|
10938
11029
|
});
|
|
10939
11030
|
|
|
10940
11031
|
// ../../loki-ts/src/util/steer.ts
|
|
10941
|
-
import { appendFileSync as appendFileSync2, closeSync as closeSync8, constants as constants2, fstatSync as fstatSync6, readdirSync as
|
|
11032
|
+
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
11033
|
import { createHash as createHash9, randomBytes as randomBytes4 } from "crypto";
|
|
10943
|
-
import { basename as
|
|
11034
|
+
import { basename as basename15, join as join41 } from "path";
|
|
10944
11035
|
function archiveTo(logs, prefix, src, link = linkSync2, onLinked) {
|
|
10945
11036
|
for (let i = 0;; i++) {
|
|
10946
11037
|
const name = i === 0 ? `${prefix}.md` : `${prefix}-${i}.md`;
|
|
10947
11038
|
try {
|
|
10948
|
-
link(src,
|
|
11039
|
+
link(src, join41(logs, name));
|
|
10949
11040
|
} catch (e) {
|
|
10950
11041
|
const code = e.code;
|
|
10951
11042
|
if (code === "EEXIST")
|
|
@@ -10953,7 +11044,7 @@ function archiveTo(logs, prefix, src, link = linkSync2, onLinked) {
|
|
|
10953
11044
|
if (code !== "EPERM" && code !== "ENOTSUP" && code !== "EXDEV" && code !== "EMLINK")
|
|
10954
11045
|
throw e;
|
|
10955
11046
|
const name2 = `${prefix}-${randomBytes4(4).toString("hex")}.md`;
|
|
10956
|
-
renameSync10(src,
|
|
11047
|
+
renameSync10(src, join41(logs, name2));
|
|
10957
11048
|
onLinked?.(name2);
|
|
10958
11049
|
return name2;
|
|
10959
11050
|
}
|
|
@@ -10968,14 +11059,14 @@ function orphanAlreadyArchived(logs, claim) {
|
|
|
10968
11059
|
const c = lstatSync11(claim);
|
|
10969
11060
|
if (!c.isFile())
|
|
10970
11061
|
return false;
|
|
10971
|
-
for (const a of
|
|
11062
|
+
for (const a of readdirSync17(logs)) {
|
|
10972
11063
|
if (!/^human-input-.*\.md$/.test(a))
|
|
10973
11064
|
continue;
|
|
10974
11065
|
try {
|
|
10975
|
-
const s = statSync16(
|
|
11066
|
+
const s = statSync16(join41(logs, a));
|
|
10976
11067
|
if (s.ino !== c.ino || s.dev !== c.dev)
|
|
10977
11068
|
continue;
|
|
10978
|
-
if (/^human-input-(ORPHAN|REJECTED)-/.test(a) ||
|
|
11069
|
+
if (/^human-input-(ORPHAN|REJECTED)-/.test(a) || existsSync26(appliedMarker(logs, a)))
|
|
10979
11070
|
return true;
|
|
10980
11071
|
} catch {}
|
|
10981
11072
|
}
|
|
@@ -10984,7 +11075,7 @@ function orphanAlreadyArchived(logs, claim) {
|
|
|
10984
11075
|
function sweepOrphans(logs, stamp2, unapplied, link, nowMs = Date.now()) {
|
|
10985
11076
|
let names;
|
|
10986
11077
|
try {
|
|
10987
|
-
names =
|
|
11078
|
+
names = readdirSync17(logs);
|
|
10988
11079
|
} catch {
|
|
10989
11080
|
return;
|
|
10990
11081
|
}
|
|
@@ -10992,7 +11083,7 @@ function sweepOrphans(logs, stamp2, unapplied, link, nowMs = Date.now()) {
|
|
|
10992
11083
|
for (const n2 of names)
|
|
10993
11084
|
if (n2.startsWith(".applied-") && !present.has(n2.slice(".applied-".length))) {
|
|
10994
11085
|
try {
|
|
10995
|
-
unlinkSync6(
|
|
11086
|
+
unlinkSync6(join41(logs, n2));
|
|
10996
11087
|
} catch {}
|
|
10997
11088
|
}
|
|
10998
11089
|
for (const n2 of names) {
|
|
@@ -11009,7 +11100,7 @@ function sweepOrphans(logs, stamp2, unapplied, link, nowMs = Date.now()) {
|
|
|
11009
11100
|
if (alive) {
|
|
11010
11101
|
let ageMs = 0;
|
|
11011
11102
|
try {
|
|
11012
|
-
ageMs = nowMs - statSync16(
|
|
11103
|
+
ageMs = nowMs - statSync16(join41(logs, n2)).mtimeMs;
|
|
11013
11104
|
} catch {
|
|
11014
11105
|
continue;
|
|
11015
11106
|
}
|
|
@@ -11017,11 +11108,11 @@ function sweepOrphans(logs, stamp2, unapplied, link, nowMs = Date.now()) {
|
|
|
11017
11108
|
continue;
|
|
11018
11109
|
}
|
|
11019
11110
|
try {
|
|
11020
|
-
if (orphanAlreadyArchived(logs,
|
|
11021
|
-
unlinkSync6(
|
|
11111
|
+
if (orphanAlreadyArchived(logs, join41(logs, n2))) {
|
|
11112
|
+
unlinkSync6(join41(logs, n2));
|
|
11022
11113
|
continue;
|
|
11023
11114
|
}
|
|
11024
|
-
archiveTo(logs, `human-input-ORPHAN-${stamp2}`,
|
|
11115
|
+
archiveTo(logs, `human-input-ORPHAN-${stamp2}`, join41(logs, n2), link);
|
|
11025
11116
|
unapplied("orphaned claim");
|
|
11026
11117
|
} catch (e) {
|
|
11027
11118
|
if (e.code === "ENOENT")
|
|
@@ -11033,17 +11124,17 @@ function sweepOrphans(logs, stamp2, unapplied, link, nowMs = Date.now()) {
|
|
|
11033
11124
|
function consumeSteer(repoDir, env = process.env, now2 = () => new Date, sink, hooks2) {
|
|
11034
11125
|
if (/^(0|false)$/i.test(env.LOKI_PROMPT_INJECTION ?? ""))
|
|
11035
11126
|
return null;
|
|
11036
|
-
const f =
|
|
11127
|
+
const f = join41(repoDir, ".loki", "HUMAN_INPUT.md");
|
|
11037
11128
|
const unapplied = (reason) => {
|
|
11038
11129
|
sink?.push({ rev: 0, source: null, actor: null, sha: "", at: now2().getTime(), unapplied: true, reason });
|
|
11039
11130
|
};
|
|
11040
11131
|
let fd = -1, claimed = "";
|
|
11041
11132
|
try {
|
|
11042
|
-
const logs =
|
|
11133
|
+
const logs = join41(repoDir, ".loki", "logs");
|
|
11043
11134
|
mkdirSync15(logs, { recursive: true });
|
|
11044
11135
|
const stamp2 = now2().toISOString().replace(/[-:]/g, "").replace(/\..*/, "");
|
|
11045
11136
|
sweepOrphans(logs, stamp2, unapplied, hooks2?.link, now2().getTime());
|
|
11046
|
-
claimed =
|
|
11137
|
+
claimed = join41(logs, `.claim-${process.pid}-${randomBytes4(6).toString("hex")}`);
|
|
11047
11138
|
try {
|
|
11048
11139
|
renameSync10(f, claimed);
|
|
11049
11140
|
} catch (e) {
|
|
@@ -11134,10 +11225,10 @@ function consumeSteer(repoDir, env = process.env, now2 = () => new Date, sink, h
|
|
|
11134
11225
|
} catch {
|
|
11135
11226
|
if (claimed) {
|
|
11136
11227
|
try {
|
|
11137
|
-
archiveTo(
|
|
11228
|
+
archiveTo(join41(repoDir, ".loki", "logs"), `human-input-${now2().toISOString().replace(/[-:]/g, "").replace(/\..*/, "")}`, claimed, hooks2?.link);
|
|
11138
11229
|
unapplied("logs dir unwritable or file unreadable");
|
|
11139
11230
|
} catch {
|
|
11140
|
-
unapplied(`steer stranded at .loki/logs/${
|
|
11231
|
+
unapplied(`steer stranded at .loki/logs/${basename15(claimed)}`);
|
|
11141
11232
|
}
|
|
11142
11233
|
} else
|
|
11143
11234
|
try {
|
|
@@ -11153,10 +11244,10 @@ function consumeSteer(repoDir, env = process.env, now2 = () => new Date, sink, h
|
|
|
11153
11244
|
}
|
|
11154
11245
|
}
|
|
11155
11246
|
function recordRevisions(repoDir, text2, archived, at) {
|
|
11156
|
-
const file =
|
|
11247
|
+
const file = join41(repoDir, ".loki", "intent-revisions.jsonl");
|
|
11157
11248
|
let last = 0;
|
|
11158
11249
|
try {
|
|
11159
|
-
for (const l of
|
|
11250
|
+
for (const l of readFileSync32(file, "utf8").split(`
|
|
11160
11251
|
`)) {
|
|
11161
11252
|
try {
|
|
11162
11253
|
last = Math.max(last, Number(JSON.parse(l).rev) || 0);
|
|
@@ -11210,7 +11301,7 @@ function staleAtSeal(repoDir, ctx) {
|
|
|
11210
11301
|
const frozen = ctx.outputs === undefined || ctx.outputs().wall !== undefined || ctx.wallSealed === true;
|
|
11211
11302
|
return [...new Set([...staleWallRevisions(ctx.intentRevisions, frozen ? ctx.timeline : []), ...late])];
|
|
11212
11303
|
}
|
|
11213
|
-
var STEER_MAX_BYTES, STEER_STAGES, STEER_CLAIM_MAX_AGE_MS, appliedMarker = (logs, archive) =>
|
|
11304
|
+
var STEER_MAX_BYTES, STEER_STAGES, STEER_CLAIM_MAX_AGE_MS, appliedMarker = (logs, archive) => join41(logs, `.applied-${archive}`), REV_HDR, STEER_REMEDY;
|
|
11214
11305
|
var init_steer = __esm(() => {
|
|
11215
11306
|
init_context();
|
|
11216
11307
|
STEER_MAX_BYTES = 1024 * 1024;
|
|
@@ -11222,20 +11313,20 @@ var init_steer = __esm(() => {
|
|
|
11222
11313
|
|
|
11223
11314
|
// ../../loki-ts/src/util/run_outputs.ts
|
|
11224
11315
|
import { createHash as createHash10 } from "crypto";
|
|
11225
|
-
import { existsSync as
|
|
11226
|
-
import { join as
|
|
11316
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync16, readdirSync as readdirSync18, readFileSync as readFileSync33, statSync as statSync17, writeFileSync as writeFileSync19 } from "fs";
|
|
11317
|
+
import { join as join42, resolve as resolve15 } from "path";
|
|
11227
11318
|
function intentRevisionsBlock(revs) {
|
|
11228
11319
|
const r = (revs ?? []).filter((r2) => r2.unapplied !== true).map(({ rev, source, actor, sha: sha2 }) => ({ rev, source, actor, sha: sha2 }));
|
|
11229
11320
|
return r.length ? { intent_revisions: r } : {};
|
|
11230
11321
|
}
|
|
11231
11322
|
function seededCorpusBlock(env = process.env) {
|
|
11232
|
-
const dir = env["LOKI_SEEDED_DEFECTS_DIR"] ||
|
|
11323
|
+
const dir = env["LOKI_SEEDED_DEFECTS_DIR"] || join42(REPO_ROOT, "benchmarks", "seeded-defects");
|
|
11233
11324
|
try {
|
|
11234
|
-
const bytes =
|
|
11325
|
+
const bytes = readFileSync33(join42(dir, "manifest.json")), version2 = createHash10("sha256").update(bytes).digest("hex");
|
|
11235
11326
|
const ids = (JSON.parse(bytes.toString("utf8")).defects ?? []).map((d) => d.id);
|
|
11236
11327
|
let rate = null;
|
|
11237
11328
|
try {
|
|
11238
|
-
const res = JSON.parse(
|
|
11329
|
+
const res = JSON.parse(readFileSync33(join42(dir, "results", "wrong-pass.json"), "utf8"));
|
|
11239
11330
|
const runs2 = res.manifest_sha256 === version2 && Array.isArray(res.runs) ? res.runs : [];
|
|
11240
11331
|
const complete = (o) => !!o && Object.keys(o).length === ids.length && ids.every((id) => typeof id === "string" && (o[id] === "SEALED" || o[id] === "NOT_SEALED"));
|
|
11241
11332
|
const top = runs2.filter((r) => r.setup === "top"), floor = runs2.filter((r) => r.setup === "floor");
|
|
@@ -11519,7 +11610,7 @@ var init_registry2 = __esm(() => {
|
|
|
11519
11610
|
|
|
11520
11611
|
// ../../loki-ts/src/features/receipt_dsse.ts
|
|
11521
11612
|
import { createPublicKey as createPublicKey3, sign as sign2, verify as verify3 } from "crypto";
|
|
11522
|
-
import { readFileSync as
|
|
11613
|
+
import { readFileSync as readFileSync34 } from "fs";
|
|
11523
11614
|
function pae(payloadType, body) {
|
|
11524
11615
|
const t = Buffer.from(payloadType, "utf8");
|
|
11525
11616
|
return Buffer.concat([Buffer.from(`DSSEv1 ${t.length} `), t, Buffer.from(` ${body.length} `), body]);
|
|
@@ -11596,7 +11687,7 @@ function verifyDsseReceipt(env, d) {
|
|
|
11596
11687
|
}
|
|
11597
11688
|
function runIdGuard(receiptPath, runId2) {
|
|
11598
11689
|
try {
|
|
11599
|
-
return envelopeRunIdProblem(JSON.parse(
|
|
11690
|
+
return envelopeRunIdProblem(JSON.parse(readFileSync34(receiptPath, "utf8")), runId2);
|
|
11600
11691
|
} catch {
|
|
11601
11692
|
return null;
|
|
11602
11693
|
}
|
|
@@ -11661,18 +11752,18 @@ var init_seal_drift = __esm(() => {
|
|
|
11661
11752
|
});
|
|
11662
11753
|
|
|
11663
11754
|
// ../../loki-ts/src/util/spec_file.ts
|
|
11664
|
-
import { isAbsolute as isAbsolute5, join as
|
|
11755
|
+
import { isAbsolute as isAbsolute5, join as join43, relative as relative4 } from "path";
|
|
11665
11756
|
function specReceiptBlock(env) {
|
|
11666
11757
|
const { LOKI_E10_SPEC_PATH: p, LOKI_E10_SPEC_SHA256: sha2 } = env;
|
|
11667
11758
|
if (!p || !sha2)
|
|
11668
11759
|
return {};
|
|
11669
|
-
const rel = isAbsolute5(p) && env.LOKI_E10_REPO_DIR ?
|
|
11760
|
+
const rel = isAbsolute5(p) && env.LOKI_E10_REPO_DIR ? relative4(env.LOKI_E10_REPO_DIR, p) : p;
|
|
11670
11761
|
return { spec: { path: rel, sha256: sha2 } };
|
|
11671
11762
|
}
|
|
11672
11763
|
var SPEC_DIR;
|
|
11673
11764
|
var init_spec_file = __esm(() => {
|
|
11674
11765
|
init_types();
|
|
11675
|
-
SPEC_DIR =
|
|
11766
|
+
SPEC_DIR = join43(".loki", "specs");
|
|
11676
11767
|
});
|
|
11677
11768
|
|
|
11678
11769
|
// ../../loki-ts/src/util/reviewer_brief.ts
|
|
@@ -11702,11 +11793,11 @@ var init_run_cap = __esm(() => {
|
|
|
11702
11793
|
});
|
|
11703
11794
|
|
|
11704
11795
|
// ../../loki-ts/src/util/mutation_proof.ts
|
|
11705
|
-
import { existsSync as
|
|
11796
|
+
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
11797
|
import { tmpdir as tmpdir4 } from "os";
|
|
11707
|
-
import { basename as
|
|
11798
|
+
import { basename as basename16, dirname as dirname15, isAbsolute as isAbsolute6, join as join44, relative as relative5 } from "path";
|
|
11708
11799
|
function mutationProof(i) {
|
|
11709
|
-
const rels = i.wallFiles.map((f) => isAbsolute6(f.path) ?
|
|
11800
|
+
const rels = i.wallFiles.map((f) => isAbsolute6(f.path) ? relative5(i.repoDir, f.path) : f.path);
|
|
11710
11801
|
if (rels.length === 0)
|
|
11711
11802
|
return np("no Wall tests");
|
|
11712
11803
|
const tests = rels.flatMap((rel) => {
|
|
@@ -11722,28 +11813,28 @@ function mutationProof(i) {
|
|
|
11722
11813
|
const deadline = Date.now() + budgetS * 1000, remaining = () => deadline - Date.now();
|
|
11723
11814
|
let parent = null, wt = null, added = false;
|
|
11724
11815
|
try {
|
|
11725
|
-
parent = mkdtempSync3(
|
|
11726
|
-
wt =
|
|
11816
|
+
parent = mkdtempSync3(join44(tmpdir4(), "loki-mutproof-"));
|
|
11817
|
+
wt = join44(parent, "wt");
|
|
11727
11818
|
const add3 = git(i.repoDir, ["worktree", "add", "--detach", wt, i.baseSha], Math.max(1000, Math.min(30000, remaining())));
|
|
11728
|
-
added =
|
|
11819
|
+
added = existsSync28(wt) || add3.status === 0;
|
|
11729
11820
|
if (add3.status !== 0)
|
|
11730
11821
|
return np("could not create the base worktree");
|
|
11731
11822
|
for (const rel of rels) {
|
|
11732
|
-
const sealed =
|
|
11733
|
-
if (!
|
|
11823
|
+
const sealed = join44(i.runDir, "wall", basename16(rel)), src = existsSync28(sealed) ? sealed : join44(i.repoDir, rel);
|
|
11824
|
+
if (!existsSync28(src))
|
|
11734
11825
|
return np(`Wall file missing: ${rel}`);
|
|
11735
|
-
mkdirSync17(dirname15(
|
|
11736
|
-
writeFileSync20(
|
|
11826
|
+
mkdirSync17(dirname15(join44(wt, rel)), { recursive: true });
|
|
11827
|
+
writeFileSync20(join44(wt, rel), readFileSync35(src));
|
|
11737
11828
|
}
|
|
11738
11829
|
for (const rel of rels) {
|
|
11739
11830
|
const parts = rel.split("/").slice(0, -1);
|
|
11740
11831
|
for (let n2 = 0;n2 <= parts.length; n2++) {
|
|
11741
11832
|
const anc = parts.slice(0, n2).join("/");
|
|
11742
11833
|
for (const d of DEP_DIRS) {
|
|
11743
|
-
const src =
|
|
11744
|
-
if (
|
|
11834
|
+
const src = join44(i.repoDir, anc, d), dst = join44(wt, anc, d);
|
|
11835
|
+
if (existsSync28(src) && !existsSync28(dst)) {
|
|
11745
11836
|
try {
|
|
11746
|
-
|
|
11837
|
+
symlinkSync2(src, dst);
|
|
11747
11838
|
} catch {}
|
|
11748
11839
|
}
|
|
11749
11840
|
}
|
|
@@ -11887,14 +11978,14 @@ var init_shell = __esm(() => {
|
|
|
11887
11978
|
});
|
|
11888
11979
|
|
|
11889
11980
|
// ../../loki-ts/src/util/python.ts
|
|
11890
|
-
import { accessSync, constants as constants3, existsSync as
|
|
11981
|
+
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
11982
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
11892
11983
|
import { tmpdir as tmpdir5 } from "os";
|
|
11893
11984
|
async function findPython3() {
|
|
11894
11985
|
if (_pythonCache !== undefined)
|
|
11895
11986
|
return _pythonCache;
|
|
11896
11987
|
const homebrew = "/opt/homebrew/bin/python3.12";
|
|
11897
|
-
if (
|
|
11988
|
+
if (existsSync29(homebrew)) {
|
|
11898
11989
|
_pythonCache = homebrew;
|
|
11899
11990
|
return homebrew;
|
|
11900
11991
|
}
|
|
@@ -12245,7 +12336,7 @@ var init_wall_manifest = __esm(() => {
|
|
|
12245
12336
|
|
|
12246
12337
|
// ../../loki-ts/src/features/wall_manifest_wire.ts
|
|
12247
12338
|
import { createHash as createHash12 } from "crypto";
|
|
12248
|
-
import { basename as
|
|
12339
|
+
import { basename as basename17, dirname as dirname16 } from "path";
|
|
12249
12340
|
function blobEntries(ls) {
|
|
12250
12341
|
const out2 = [];
|
|
12251
12342
|
for (const raw2 of ls.toString("latin1").split("\x00")) {
|
|
@@ -12275,12 +12366,12 @@ function wallManifestFor(repoDir, tree, task, env = process.env) {
|
|
|
12275
12366
|
return null;
|
|
12276
12367
|
const low = task.toLowerCase().replace(/\\/g, "/");
|
|
12277
12368
|
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(
|
|
12369
|
+
const dirModule = (e) => /^(index|__init__|mod|main)\.[^.]+$/.test(basename17(e.path)) && e.path.includes("/") && token(dirname16(e.path));
|
|
12370
|
+
const matched = all.filter((e) => SOURCE.test(e.path) && (token(basename17(e.path)) || token(e.path) || token(basename17(e.path).replace(/\.[^.]*$/, "")) || dirModule(e)));
|
|
12280
12371
|
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
12372
|
const occ = new Map(matched.map((e) => [e, spans(e.path)]));
|
|
12282
12373
|
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(
|
|
12374
|
+
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
12375
|
const named = [...byPath2, ...byBase, ...matched.filter((e) => !byPath2.includes(e) && !byBase.includes(e))].slice(0, MAX_NAMED);
|
|
12285
12376
|
const tests = all.filter((e) => TESTISH.test(e.path)).slice(0, MAX_FILES), listed = tests.filter((e) => !SOURCE.test(e.path));
|
|
12286
12377
|
const want = [...new Set([...all.filter((e) => CONFIG.test(e.path)), ...tests.filter((e) => SOURCE.test(e.path)), ...named])];
|
|
@@ -12337,9 +12428,9 @@ Example: test('name', () => { assert.strictEqual(fn(1), 2); }); Run: node --tes
|
|
|
12337
12428
|
|
|
12338
12429
|
// ../../loki-ts/src/util/holdout.ts
|
|
12339
12430
|
import { createHash as createHash13 } from "crypto";
|
|
12340
|
-
import { appendFileSync as appendFileSync3, copyFileSync as copyFileSync2, existsSync as
|
|
12431
|
+
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
12432
|
import { tmpdir as tmpdir6 } from "os";
|
|
12342
|
-
import { basename as
|
|
12433
|
+
import { basename as basename18, join as join45, relative as relative6 } from "path";
|
|
12343
12434
|
function wallHoldoutRatio(env = process.env) {
|
|
12344
12435
|
if (env["LOKI_WALL_HOLDOUT"]?.trim() === "0")
|
|
12345
12436
|
return 0;
|
|
@@ -12370,32 +12461,32 @@ function stashHoldout(o) {
|
|
|
12370
12461
|
rmSync12(dir, { recursive: true, force: true });
|
|
12371
12462
|
mkdirSync18(dir, { recursive: true, mode: 448 });
|
|
12372
12463
|
const files = held.map((name) => {
|
|
12373
|
-
copyFileSync2(
|
|
12374
|
-
rmSync12(
|
|
12375
|
-
return { name, runner: o.runnerOf(name), sha256: sha2(
|
|
12464
|
+
copyFileSync2(join45(o.srcDir, name), join45(dir, name));
|
|
12465
|
+
rmSync12(join45(o.srcDir, name), { force: true });
|
|
12466
|
+
return { name, runner: o.runnerOf(name), sha256: sha2(readFileSync37(join45(dir, name), "utf8")) };
|
|
12376
12467
|
});
|
|
12377
|
-
writeFileSync21(
|
|
12468
|
+
writeFileSync21(join45(dir, MANIFEST), JSON.stringify({ targetDir: o.targetDir, files }));
|
|
12378
12469
|
return { dir, names: new Set(held) };
|
|
12379
12470
|
}
|
|
12380
12471
|
function stageHoldout(dir, repoDir) {
|
|
12381
12472
|
const put = [], tests = [], missing = [];
|
|
12382
12473
|
let man = null;
|
|
12383
12474
|
try {
|
|
12384
|
-
man = JSON.parse(
|
|
12475
|
+
man = JSON.parse(readFileSync37(join45(dir, MANIFEST), "utf8"));
|
|
12385
12476
|
} catch {}
|
|
12386
12477
|
if (!man)
|
|
12387
|
-
return { tests, missing: [`holdout store unreadable: ${
|
|
12478
|
+
return { tests, missing: [`holdout store unreadable: ${basename18(dir)}`], cleanup: () => {} };
|
|
12388
12479
|
mkdirSync18(man.targetDir, { recursive: true });
|
|
12389
12480
|
man.files.forEach((f, i) => {
|
|
12390
|
-
const src =
|
|
12391
|
-
if (!
|
|
12481
|
+
const src = join45(dir, f.name);
|
|
12482
|
+
if (!existsSync30(src) || sha2(readFileSync37(src, "utf8")) !== f.sha256) {
|
|
12392
12483
|
missing.push(`holdout ${i + 1} missing or altered`);
|
|
12393
12484
|
return;
|
|
12394
12485
|
}
|
|
12395
|
-
const dest =
|
|
12486
|
+
const dest = join45(man.targetDir, `loki_wall_holdout_${i + 1}${f.name.slice(f.name.indexOf("."))}`);
|
|
12396
12487
|
copyFileSync2(src, dest);
|
|
12397
12488
|
put.push(dest);
|
|
12398
|
-
tests.push({ runner: f.runner, path:
|
|
12489
|
+
tests.push({ runner: f.runner, path: relative6(repoDir, dest) });
|
|
12399
12490
|
});
|
|
12400
12491
|
return { tests, missing, cleanup: () => {
|
|
12401
12492
|
for (const p of put)
|
|
@@ -12405,11 +12496,11 @@ function stageHoldout(dir, repoDir) {
|
|
|
12405
12496
|
function recordHoldoutTriage(runDir, entry) {
|
|
12406
12497
|
try {
|
|
12407
12498
|
mkdirSync18(runDir, { recursive: true });
|
|
12408
|
-
appendFileSync3(
|
|
12499
|
+
appendFileSync3(join45(runDir, HOLDOUT_TRIAGE_FILE), JSON.stringify(entry) + `
|
|
12409
12500
|
`, { mode: 384 });
|
|
12410
12501
|
} catch {}
|
|
12411
12502
|
}
|
|
12412
|
-
var sha2 = (s) => createHash13("sha256").update(s).digest("hex"), WALL_HOLDOUT_DEFAULT_RATIO = 0.2, isHoldoutCheck = (name) => name.startsWith("holdout:"), holdoutDirFor = (runId2, repoDir) =>
|
|
12503
|
+
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
12504
|
var init_holdout = () => {};
|
|
12414
12505
|
|
|
12415
12506
|
// ../../loki-ts/src/runner/runner_errors.ts
|
|
@@ -12455,19 +12546,19 @@ var init_runner_errors = __esm(() => {
|
|
|
12455
12546
|
|
|
12456
12547
|
// ../../loki-ts/src/runner/load_owner.ts
|
|
12457
12548
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
12458
|
-
import { mkdtempSync as mkdtempSync5, realpathSync as
|
|
12549
|
+
import { mkdtempSync as mkdtempSync5, realpathSync as realpathSync20, rmSync as rmSync13 } from "fs";
|
|
12459
12550
|
import { tmpdir as tmpdir7 } from "os";
|
|
12460
|
-
import { basename as
|
|
12551
|
+
import { basename as basename19, extname as extname2, join as join46 } from "path";
|
|
12461
12552
|
function changedFilesNamed(out2, repoDir, changed) {
|
|
12462
12553
|
return changed.filter((f) => {
|
|
12463
|
-
if (out2.includes(f) || out2.includes(
|
|
12554
|
+
if (out2.includes(f) || out2.includes(join46(repoDir, f)))
|
|
12464
12555
|
return true;
|
|
12465
12556
|
const segs = f.split("/");
|
|
12466
12557
|
if (suffixes(segs, 2).some((x) => x !== f && bounded(out2, x, "(?![\\w-])")))
|
|
12467
12558
|
return true;
|
|
12468
12559
|
if (extname2(f) === ".go" && segs.length > 1 && suffixes(segs.slice(0, -1), 1).some((d) => new RegExp(`(?<=[\\w-])/${esc(d)}(?![\\w./-])`).test(out2)))
|
|
12469
12560
|
return true;
|
|
12470
|
-
const stem =
|
|
12561
|
+
const stem = basename19(f, extname2(f));
|
|
12471
12562
|
if (stem.length < 2 || stem === "index" || stem === "__init__")
|
|
12472
12563
|
return false;
|
|
12473
12564
|
return new RegExp(`(?<![\\w-])${esc(stem)}(?![\\w-])`).test(out2);
|
|
@@ -12477,7 +12568,7 @@ function loadSignature(out2, roots) {
|
|
|
12477
12568
|
let o = out2;
|
|
12478
12569
|
for (const r of roots.flatMap((x) => {
|
|
12479
12570
|
try {
|
|
12480
|
-
return [x,
|
|
12571
|
+
return [x, realpathSync20(x)];
|
|
12481
12572
|
} catch {
|
|
12482
12573
|
return [x];
|
|
12483
12574
|
}
|
|
@@ -12579,7 +12670,7 @@ async function loadErrorIsHarnessOwned(i) {
|
|
|
12579
12670
|
return false;
|
|
12580
12671
|
if (i.args.some((a) => changed.includes(a.replace(/^\.\//, ""))))
|
|
12581
12672
|
return false;
|
|
12582
|
-
const dir = mkdtempSync5(
|
|
12673
|
+
const dir = mkdtempSync5(join46(tmpdir7(), "e10-loadown-"));
|
|
12583
12674
|
const git3 = (args) => {
|
|
12584
12675
|
safeGit(i.repoDir, args, { stdio: "ignore" });
|
|
12585
12676
|
};
|
|
@@ -12611,7 +12702,7 @@ var init_load_owner = __esm(() => {
|
|
|
12611
12702
|
});
|
|
12612
12703
|
|
|
12613
12704
|
// ../../loki-ts/src/project_model/package_suite.ts
|
|
12614
|
-
import { join as
|
|
12705
|
+
import { join as join47 } from "path";
|
|
12615
12706
|
function packageSuiteSpecs(api) {
|
|
12616
12707
|
if (!isMultiRoot(api))
|
|
12617
12708
|
return null;
|
|
@@ -12627,7 +12718,7 @@ async function runPackageSuites(repoDir, signal, opts, checks, notProven) {
|
|
|
12627
12718
|
return false;
|
|
12628
12719
|
for (const { name, cmd: cmd2, cwd, run: line2 } of specs) {
|
|
12629
12720
|
const started = Date.now();
|
|
12630
|
-
const r = await run(["bash", "-c", line2], { cwd:
|
|
12721
|
+
const r = await run(["bash", "-c", line2], { cwd: join47(repoDir, cwd), timeoutMs: opts.timeoutMs, ...opts.path ? { env: { PATH: opts.path } } : {} });
|
|
12631
12722
|
const duration_s = (Date.now() - started) / 1000;
|
|
12632
12723
|
if (signal.aborted) {
|
|
12633
12724
|
checks.push({ name, cmd: cmd2, result: "not_run", duration_s });
|
|
@@ -12636,7 +12727,7 @@ async function runPackageSuites(repoDir, signal, opts, checks, notProven) {
|
|
|
12636
12727
|
}
|
|
12637
12728
|
const out2 = `${r.stdout}
|
|
12638
12729
|
${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:
|
|
12730
|
+
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), ...opts.path ? { env: { PATH: opts.path } } : {} });
|
|
12640
12731
|
if (lr) {
|
|
12641
12732
|
checks.push({ name, cmd: cmd2, result: "not_run", duration_s });
|
|
12642
12733
|
notProven.add(`${lr} (${name}; harness-owned)`);
|
|
@@ -12682,8 +12773,8 @@ var init_install = __esm(() => {
|
|
|
12682
12773
|
});
|
|
12683
12774
|
|
|
12684
12775
|
// ../../loki-ts/src/features/runner_config.ts
|
|
12685
|
-
import { readFileSync as
|
|
12686
|
-
import { dirname as dirname17, join as
|
|
12776
|
+
import { readFileSync as readFileSync38 } from "fs";
|
|
12777
|
+
import { dirname as dirname17, join as join48, normalize as normalize2 } from "path";
|
|
12687
12778
|
function tomlKey2(s, i = 0, eq2 = true) {
|
|
12688
12779
|
const parts = [], ws = () => {
|
|
12689
12780
|
while (/\s/.test(s[i] ?? "x"))
|
|
@@ -12960,8 +13051,8 @@ function referenced(cfg, text2) {
|
|
|
12960
13051
|
}
|
|
12961
13052
|
const dir = dirname17(cfg), explicit = ROOT_DIR.exec(text2), roots = [dir];
|
|
12962
13053
|
if (explicit)
|
|
12963
|
-
roots.push("", ...explicit[1] ? [
|
|
12964
|
-
return [...raw2.flatMap((r) => r.startsWith("/") ? [normalize2(r.slice(1))] : roots.map((root) => normalize2(
|
|
13054
|
+
roots.push("", ...explicit[1] ? [join48(dir, explicit[1])] : []);
|
|
13055
|
+
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
13056
|
}
|
|
12966
13057
|
function runnerConfigNotes(repoDir, baseSha, head, changed, signal) {
|
|
12967
13058
|
const notes = new Set, ch = new Set(changed.map((c) => normalize2(c)));
|
|
@@ -13041,7 +13132,7 @@ var PKG_KEYS, RAW_CONFIGS, RUNNER_CONFIGS, DEP_MAPS, RUNNER_DEP, LOCAL_SPEC, dep
|
|
|
13041
13132
|
}
|
|
13042
13133
|
}, headText = (dir, f) => {
|
|
13043
13134
|
try {
|
|
13044
|
-
return
|
|
13135
|
+
return readFileSync38(join48(dir, f), "utf8");
|
|
13045
13136
|
} catch {
|
|
13046
13137
|
return "";
|
|
13047
13138
|
}
|
|
@@ -13081,19 +13172,19 @@ var init_runner_config = __esm(() => {
|
|
|
13081
13172
|
|
|
13082
13173
|
// ../../loki-ts/src/e10ext/assert_delta.ts
|
|
13083
13174
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
13084
|
-
import { mkdtempSync as mkdtempSync6, readFileSync as
|
|
13175
|
+
import { mkdtempSync as mkdtempSync6, readFileSync as readFileSync39, rmSync as rmSync14 } from "fs";
|
|
13085
13176
|
import { tmpdir as tmpdir8 } from "os";
|
|
13086
|
-
import { join as
|
|
13087
|
-
import { basename as
|
|
13177
|
+
import { join as join49 } from "path";
|
|
13178
|
+
import { basename as basename20 } from "path";
|
|
13088
13179
|
function classifyAssertDelta(inp) {
|
|
13089
|
-
const f =
|
|
13180
|
+
const f = basename20(inp.path);
|
|
13090
13181
|
if (!/^(test_.*|.*_test)\.py$/.test(f))
|
|
13091
13182
|
return WEAKENED;
|
|
13092
13183
|
if (inp.headCounts.run !== inp.baseCounts.run || inp.headCounts.skipped !== inp.baseCounts.skipped)
|
|
13093
13184
|
return WEAKENED;
|
|
13094
13185
|
let cwd = "";
|
|
13095
13186
|
try {
|
|
13096
|
-
cwd = mkdtempSync6(
|
|
13187
|
+
cwd = mkdtempSync6(join49(tmpdir8(), "loki-ad-"));
|
|
13097
13188
|
const raw2 = execFileSync4("python3", ["-I", "-c", PY], {
|
|
13098
13189
|
input: JSON.stringify({ path: inp.path, base: inp.base, head: inp.head, task: inp.task }),
|
|
13099
13190
|
cwd,
|
|
@@ -13124,7 +13215,7 @@ function assertDeltaNotes(repoDir, baseSha, headRef, path, task, baseCounts, hea
|
|
|
13124
13215
|
return null;
|
|
13125
13216
|
try {
|
|
13126
13217
|
const show = (ref) => safeGit(repoDir, ["show", `${ref}:${path}`]);
|
|
13127
|
-
const head = headRef ? show(headRef) :
|
|
13218
|
+
const head = headRef ? show(headRef) : readFileSync39(join49(repoDir, path), "utf8");
|
|
13128
13219
|
const r = classifyTestEdit(path, show(baseSha), head, task, baseCounts, headCounts);
|
|
13129
13220
|
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
13221
|
} catch {
|
|
@@ -13307,7 +13398,7 @@ var init_select = __esm(() => {
|
|
|
13307
13398
|
});
|
|
13308
13399
|
|
|
13309
13400
|
// ../../loki-ts/src/util/wall_owned.ts
|
|
13310
|
-
import { isAbsolute as isAbsolute7, join as
|
|
13401
|
+
import { isAbsolute as isAbsolute7, join as join50, relative as relative7 } from "path";
|
|
13311
13402
|
function failingLocations(raw2, cwd, repoDir) {
|
|
13312
13403
|
const out2 = raw2.replace(ANSI2, "").replace(/\r\n?/g, `
|
|
13313
13404
|
`), files = new Set;
|
|
@@ -13339,7 +13430,7 @@ function failingLocations(raw2, cwd, repoDir) {
|
|
|
13339
13430
|
}
|
|
13340
13431
|
if (errors2 === 0 || located !== errors2)
|
|
13341
13432
|
return null;
|
|
13342
|
-
return [...files].map((f) =>
|
|
13433
|
+
return [...files].map((f) => relative7(repoDir, isAbsolute7(f) ? f : join50(cwd, f)));
|
|
13343
13434
|
}
|
|
13344
13435
|
function wallOwnedFailure(raw2, cwd, repoDir, wall) {
|
|
13345
13436
|
const locs = failingLocations(raw2, cwd, repoDir);
|
|
@@ -13352,25 +13443,25 @@ var init_wall_owned = __esm(() => {
|
|
|
13352
13443
|
|
|
13353
13444
|
// ../../loki-ts/src/util/app_probe.ts
|
|
13354
13445
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
13355
|
-
import { existsSync as
|
|
13356
|
-
import { join as
|
|
13446
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync19, readFileSync as readFileSync40, renameSync as renameSync11, writeFileSync as writeFileSync22 } from "fs";
|
|
13447
|
+
import { join as join51 } from "path";
|
|
13357
13448
|
function readJson4(p) {
|
|
13358
13449
|
try {
|
|
13359
|
-
const v = JSON.parse(
|
|
13450
|
+
const v = JSON.parse(readFileSync40(p, "utf8"));
|
|
13360
13451
|
return v && typeof v === "object" ? v : null;
|
|
13361
13452
|
} catch {
|
|
13362
13453
|
return null;
|
|
13363
13454
|
}
|
|
13364
13455
|
}
|
|
13365
13456
|
function stopApp(repoDir, opts = {}) {
|
|
13366
|
-
const runner = opts.runnerPath ??
|
|
13367
|
-
if (!
|
|
13457
|
+
const runner = opts.runnerPath ?? join51(REPO_ROOT, "autonomy", "app-runner.sh");
|
|
13458
|
+
if (!existsSync31(runner) || !existsSync31(join51(repoDir, ".loki", "app-runner", "app.pid")))
|
|
13368
13459
|
return;
|
|
13369
13460
|
spawnSync6("bash", ["-c", STOP, "app-probe", repoDir, runner], { cwd: repoDir, env: plainTestEnv(), timeout: opts.timeoutMs ?? 60000, killSignal: "SIGKILL", stdio: "ignore" });
|
|
13370
13461
|
}
|
|
13371
13462
|
async function appProbe(repoDir, lokiDir2, opts = {}) {
|
|
13372
|
-
const timeoutMs = opts.timeoutMs ?? 60000, runner = opts.runnerPath ??
|
|
13373
|
-
const dir =
|
|
13463
|
+
const timeoutMs = opts.timeoutMs ?? 60000, runner = opts.runnerPath ?? join51(REPO_ROOT, "autonomy", "app-runner.sh");
|
|
13464
|
+
const dir = join51(repoDir, ".loki", "app-runner"), checks = [];
|
|
13374
13465
|
const t0 = Date.now();
|
|
13375
13466
|
const mk2 = (name, result, reason) => ({ name, cmd: "autonomy/app-runner.sh", result, duration_s: (Date.now() - t0) / 1000, reason });
|
|
13376
13467
|
const sh = (script) => {
|
|
@@ -13378,7 +13469,7 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
|
|
|
13378
13469
|
return { out: r.stdout ?? "", status: r.error ? null : r.status };
|
|
13379
13470
|
};
|
|
13380
13471
|
let pid = null, url = null;
|
|
13381
|
-
if (!
|
|
13472
|
+
if (!existsSync31(runner))
|
|
13382
13473
|
return { checks: [mk2("app boot", "not_run", "app-runner.sh not found"), mk2("http probe", "not_run", "app not booted")], pid, url };
|
|
13383
13474
|
try {
|
|
13384
13475
|
const b = sh(BOOT);
|
|
@@ -13388,9 +13479,9 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
|
|
|
13388
13479
|
return { checks, pid, url };
|
|
13389
13480
|
}
|
|
13390
13481
|
const ir = Number(m[1]), sr = Number(m[2]), hr = Number(m[3]);
|
|
13391
|
-
const pidTxt =
|
|
13482
|
+
const pidTxt = existsSync31(join51(dir, "app.pid")) ? readFileSync40(join51(dir, "app.pid"), "utf8").trim() : "";
|
|
13392
13483
|
pid = /^\d+$/.test(pidTxt) && sr >= 0 ? Number(pidTxt) : null;
|
|
13393
|
-
const st = readJson4(
|
|
13484
|
+
const st = readJson4(join51(dir, "state.json"));
|
|
13394
13485
|
url = typeof st?.["url"] === "string" ? st["url"] : null;
|
|
13395
13486
|
if (sr < 0) {
|
|
13396
13487
|
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 +13492,7 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
|
|
|
13401
13492
|
return { checks, pid, url };
|
|
13402
13493
|
}
|
|
13403
13494
|
checks.push(mk2("app boot", "pass", "app process started"));
|
|
13404
|
-
const health = readJson4(
|
|
13495
|
+
const health = readJson4(join51(dir, "health.json"));
|
|
13405
13496
|
checks.push(hr === 0 && health?.["ok"] === true ? mk2("http probe", "pass", "health.json ok") : mk2("http probe", "fail", "app-runner health check failed"));
|
|
13406
13497
|
if (opts.specText !== undefined && checks[1]?.result === "pass" && url)
|
|
13407
13498
|
checks.push(await functionalVerify(opts, url, dir, lokiDir2, timeoutMs));
|
|
@@ -13414,10 +13505,10 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
|
|
|
13414
13505
|
async function functionalVerify(opts, url, dir, lokiDir2, timeoutMs) {
|
|
13415
13506
|
const t0 = Date.now();
|
|
13416
13507
|
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 || !
|
|
13508
|
+
const py = await findPython3(), script = opts.verifyPath ?? join51(REPO_ROOT, "autonomy", "lib", "functional-verify.py");
|
|
13509
|
+
if (!py || !existsSync31(script))
|
|
13419
13510
|
return res("not_run", "python3 or functional-verify.py unavailable");
|
|
13420
|
-
const specFile =
|
|
13511
|
+
const specFile = join51(dir, "spec.txt");
|
|
13421
13512
|
writeFileSync22(specFile, opts.specText ?? "");
|
|
13422
13513
|
const r = spawnSync6(py, ["-I", script, specFile, url], { env: plainTestEnv(), encoding: "utf8", timeout: timeoutMs, killSignal: "SIGKILL", stdio: ["ignore", "pipe", "ignore"] });
|
|
13423
13514
|
let out2 = null;
|
|
@@ -13429,11 +13520,11 @@ async function functionalVerify(opts, url, dir, lokiDir2, timeoutMs) {
|
|
|
13429
13520
|
}
|
|
13430
13521
|
if (!out2 || r.status !== 0)
|
|
13431
13522
|
return res("not_run", "functional harness produced no result");
|
|
13432
|
-
const q =
|
|
13523
|
+
const q = join51(lokiDir2, "quality");
|
|
13433
13524
|
mkdirSync19(q, { recursive: true });
|
|
13434
|
-
const tmp =
|
|
13525
|
+
const tmp = join51(q, `functional-results.json.tmp.${process.pid}`);
|
|
13435
13526
|
writeFileSync22(tmp, JSON.stringify(out2, null, 2));
|
|
13436
|
-
renameSync11(tmp,
|
|
13527
|
+
renameSync11(tmp, join51(q, "functional-results.json"));
|
|
13437
13528
|
const s = String(out2["functional_status"] ?? "inconclusive");
|
|
13438
13529
|
return res(s === "verified" ? "pass" : s === "failed" ? "fail" : "not_run", `functional_status ${s}`);
|
|
13439
13530
|
}
|
|
@@ -13463,16 +13554,16 @@ app_runner_stop >/dev/null 2>&1
|
|
|
13463
13554
|
});
|
|
13464
13555
|
|
|
13465
13556
|
// ../../loki-ts/src/util/secure_scan.ts
|
|
13466
|
-
import { existsSync as
|
|
13557
|
+
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
13558
|
import { randomBytes as randomBytes5 } from "crypto";
|
|
13468
13559
|
import { tmpdir as tmpdir9 } from "os";
|
|
13469
|
-
import { basename as
|
|
13560
|
+
import { basename as basename21, dirname as dirname18, join as join52, resolve as resolve16, sep as sep12 } from "path";
|
|
13470
13561
|
function fail(error) {
|
|
13471
13562
|
return { ok: false, findings: [], error };
|
|
13472
13563
|
}
|
|
13473
13564
|
async function runSecureScan(targetDir, opts = {}) {
|
|
13474
|
-
const script = opts.scriptPath ??
|
|
13475
|
-
if (!
|
|
13565
|
+
const script = opts.scriptPath ?? join52(REPO_ROOT, "autonomy", "lib", "secure-scan.py");
|
|
13566
|
+
if (!existsSync32(script))
|
|
13476
13567
|
return fail(`secure-scan script not found: ${script}`);
|
|
13477
13568
|
const py = await findPython3();
|
|
13478
13569
|
if (!py)
|
|
@@ -13523,7 +13614,7 @@ function isWorkTreeRoot(dir) {
|
|
|
13523
13614
|
if (top === null)
|
|
13524
13615
|
return false;
|
|
13525
13616
|
try {
|
|
13526
|
-
return
|
|
13617
|
+
return realpathSync21(top.trim()) === realpathSync21(dir);
|
|
13527
13618
|
} catch {
|
|
13528
13619
|
return false;
|
|
13529
13620
|
}
|
|
@@ -13641,7 +13732,7 @@ async function scanAddedLines(repoDir, opts = {}) {
|
|
|
13641
13732
|
const skipped2 = [];
|
|
13642
13733
|
for (const p of untracked.split("\x00").filter(Boolean)) {
|
|
13643
13734
|
try {
|
|
13644
|
-
const st = statSync19(
|
|
13735
|
+
const st = statSync19(join52(repoDir, p));
|
|
13645
13736
|
if (!st.isFile())
|
|
13646
13737
|
continue;
|
|
13647
13738
|
if (st.size > MAX_ADDED_FILE_BYTES) {
|
|
@@ -13656,23 +13747,23 @@ async function scanAddedLines(repoDir, opts = {}) {
|
|
|
13656
13747
|
continue;
|
|
13657
13748
|
}
|
|
13658
13749
|
const lines2 = new Map;
|
|
13659
|
-
|
|
13750
|
+
readFileSync41(join52(repoDir, p), "utf8").split(`
|
|
13660
13751
|
`).forEach((t, i) => lines2.set(i + 1, t));
|
|
13661
13752
|
added.set(p, lines2);
|
|
13662
13753
|
} catch {}
|
|
13663
13754
|
}
|
|
13664
13755
|
if (added.size === 0)
|
|
13665
13756
|
return { ok: true, findings: skipped2 };
|
|
13666
|
-
const mirror = mkdtempSync7(
|
|
13757
|
+
const mirror = mkdtempSync7(join52(tmpdir9(), "loki-secure-added-"));
|
|
13667
13758
|
try {
|
|
13668
|
-
const root =
|
|
13759
|
+
const root = resolve16(mirror) + sep12;
|
|
13669
13760
|
const chunkMap = new Map;
|
|
13670
13761
|
const chunkRoot = `.loki-chunks-${randomBytes5(6).toString("hex")}`;
|
|
13671
13762
|
let chunkSeq = 0;
|
|
13672
13763
|
for (const [p, lines2] of added) {
|
|
13673
13764
|
if (lines2.size === 0)
|
|
13674
13765
|
continue;
|
|
13675
|
-
const dest =
|
|
13766
|
+
const dest = resolve16(mirror, p);
|
|
13676
13767
|
if (!dest.startsWith(root))
|
|
13677
13768
|
continue;
|
|
13678
13769
|
let max = 0;
|
|
@@ -13709,8 +13800,8 @@ async function scanAddedLines(repoDir, opts = {}) {
|
|
|
13709
13800
|
chunks.push(cur);
|
|
13710
13801
|
const whole = chunks.length === 1;
|
|
13711
13802
|
for (const c of chunks) {
|
|
13712
|
-
const rel = whole ? p :
|
|
13713
|
-
const out2 = whole ? dest :
|
|
13803
|
+
const rel = whole ? p : join52(chunkRoot, String(chunkSeq++), basename21(p));
|
|
13804
|
+
const out2 = whole ? dest : resolve16(mirror, rel);
|
|
13714
13805
|
if (!out2.startsWith(root))
|
|
13715
13806
|
break;
|
|
13716
13807
|
chunkMap.set(rel, { file: p, lines: c.orig });
|
|
@@ -13727,7 +13818,7 @@ async function scanAddedLines(repoDir, opts = {}) {
|
|
|
13727
13818
|
for (let f of r.findings) {
|
|
13728
13819
|
if (f.rule !== "secret-in-client-file")
|
|
13729
13820
|
continue;
|
|
13730
|
-
const c = chunkMap.get(f.file.split(
|
|
13821
|
+
const c = chunkMap.get(f.file.split(sep12).join("/"));
|
|
13731
13822
|
if (c)
|
|
13732
13823
|
f = { ...f, file: c.file, line: c.lines[f.line - 1] ?? f.line };
|
|
13733
13824
|
const kind = /A live (\S+)/.exec(f.message)?.[1] ?? "provider key";
|
|
@@ -13859,9 +13950,9 @@ var init_route_block = __esm(() => {
|
|
|
13859
13950
|
// ../../loki-ts/src/features/visual_evidence.ts
|
|
13860
13951
|
import { spawn as spawn8 } from "child_process";
|
|
13861
13952
|
import { createHash as createHash14, randomBytes as randomBytes6 } from "crypto";
|
|
13862
|
-
import { existsSync as
|
|
13953
|
+
import { existsSync as existsSync33, lstatSync as lstatSync12, mkdirSync as mkdirSync21, readdirSync as readdirSync19, readFileSync as readFileSync42, writeFileSync as writeFileSync24 } from "fs";
|
|
13863
13954
|
import { createServer } from "net";
|
|
13864
|
-
import { dirname as dirname19, isAbsolute as isAbsolute8, join as
|
|
13955
|
+
import { dirname as dirname19, isAbsolute as isAbsolute8, join as join53, normalize as normalize3, relative as relative8, sep as sep13 } from "path";
|
|
13865
13956
|
function routeFor(file) {
|
|
13866
13957
|
let r = file.replace(/^(?:.*?\/)?(?:app|pages|src|public)\//, "").replace(/^(?:routes|pages)\//, "");
|
|
13867
13958
|
r = r.replace(/\.(?:html|jsx|tsx|vue|svelte)$/, "").replace(/\/?(?:page|index|\+page)$/, "");
|
|
@@ -13871,7 +13962,7 @@ function hashScreens(runDir, rels) {
|
|
|
13871
13962
|
const out2 = [];
|
|
13872
13963
|
for (const rel of rels) {
|
|
13873
13964
|
try {
|
|
13874
|
-
out2.push({ path: rel, sha256: sha256File(
|
|
13965
|
+
out2.push({ path: rel, sha256: sha256File(join53(runDir, rel)) });
|
|
13875
13966
|
} catch {}
|
|
13876
13967
|
}
|
|
13877
13968
|
return out2;
|
|
@@ -13884,14 +13975,14 @@ function checkScreens(runDir, screens) {
|
|
|
13884
13975
|
return "evidence_screens entry is malformed";
|
|
13885
13976
|
if (isAbsolute8(s.path) || normalize3(s.path).startsWith(".."))
|
|
13886
13977
|
return `evidence screenshot path escapes the evidence dir: ${s.path}`;
|
|
13887
|
-
const file =
|
|
13978
|
+
const file = join53(runDir, s.path);
|
|
13888
13979
|
let cur = runDir;
|
|
13889
|
-
for (const seg of normalize3(s.path).split(
|
|
13890
|
-
cur =
|
|
13980
|
+
for (const seg of normalize3(s.path).split(sep13)) {
|
|
13981
|
+
cur = join53(cur, seg);
|
|
13891
13982
|
if (isSymlink(cur))
|
|
13892
13983
|
return `evidence screenshot path is a symlink: ${s.path}`;
|
|
13893
13984
|
}
|
|
13894
|
-
if (!
|
|
13985
|
+
if (!existsSync33(file))
|
|
13895
13986
|
return `evidence screenshot is missing: ${s.path}`;
|
|
13896
13987
|
if (!isRegularFile(file))
|
|
13897
13988
|
return `evidence screenshot is not a regular file: ${s.path}`;
|
|
@@ -13934,11 +14025,11 @@ async function waitUp(url, ms, signal) {
|
|
|
13934
14025
|
}
|
|
13935
14026
|
function openapiPaths(repoDir) {
|
|
13936
14027
|
for (const f of ["openapi.json", "openapi.yaml", "openapi.yml", "swagger.json"]) {
|
|
13937
|
-
const p =
|
|
13938
|
-
if (!
|
|
14028
|
+
const p = join53(repoDir, f);
|
|
14029
|
+
if (!existsSync33(p))
|
|
13939
14030
|
continue;
|
|
13940
14031
|
try {
|
|
13941
|
-
const txt =
|
|
14032
|
+
const txt = readFileSync42(p, "utf8");
|
|
13942
14033
|
const paths = f.endsWith(".json") ? Object.keys(JSON.parse(txt).paths ?? {}) : [...txt.matchAll(/^ {2}(\/[^\s:]*):\s*$/gm)].map((m) => m[1]);
|
|
13943
14034
|
return paths.filter((x) => !x.includes("{")).slice(0, 10);
|
|
13944
14035
|
} catch {
|
|
@@ -13952,24 +14043,24 @@ async function recordE2eMedia(repoDir, runDir, relDir, base, routes, ms, signal)
|
|
|
13952
14043
|
if (!pw || !pkg)
|
|
13953
14044
|
return { rels: [], skipped: "playwright e2e video and trace skipped: @playwright/test is not installed in the repo" };
|
|
13954
14045
|
try {
|
|
13955
|
-
const dir =
|
|
14046
|
+
const dir = join53(runDir, relDir, "e2e");
|
|
13956
14047
|
mkdirSync21(dir, { recursive: true });
|
|
13957
|
-
writeFileSync24(
|
|
13958
|
-
writeFileSync24(
|
|
14048
|
+
writeFileSync24(join53(dir, "walk.spec.cjs"), e2eSpecSource(pkg, base, routes));
|
|
14049
|
+
writeFileSync24(join53(dir, "playwright.config.cjs"), `module.exports = { testDir: ".", testMatch: "walk.spec.cjs", outputDir: "./out", reporter: "null", use: { video: "on", trace: "on" } };
|
|
13959
14050
|
`);
|
|
13960
|
-
if (!await shoot(pw, ["test", "--config",
|
|
14051
|
+
if (!await shoot(pw, ["test", "--config", join53(dir, "playwright.config.cjs")], repoDir, ms, signal))
|
|
13961
14052
|
return { rels: [], skipped: "playwright e2e video and trace skipped: the run failed or timed out" };
|
|
13962
14053
|
const rels = [];
|
|
13963
14054
|
const walk = (d) => {
|
|
13964
|
-
for (const e of
|
|
13965
|
-
const full =
|
|
14055
|
+
for (const e of readdirSync19(d, { withFileTypes: true })) {
|
|
14056
|
+
const full = join53(d, e.name);
|
|
13966
14057
|
if (e.isDirectory())
|
|
13967
14058
|
walk(full);
|
|
13968
14059
|
else if (e.isFile() && /\.(webm|zip)$/.test(e.name))
|
|
13969
|
-
rels.push(
|
|
14060
|
+
rels.push(join53(relDir, "e2e", relative8(dir, full)));
|
|
13970
14061
|
}
|
|
13971
14062
|
};
|
|
13972
|
-
walk(
|
|
14063
|
+
walk(join53(dir, "out"));
|
|
13973
14064
|
return rels.length > 0 ? { rels, skipped: null } : { rels, skipped: "playwright e2e video and trace skipped: no video or trace was produced" };
|
|
13974
14065
|
} catch (e) {
|
|
13975
14066
|
return { rels: [], skipped: `playwright e2e video and trace skipped: ${String(e?.message ?? e).slice(0, 120)}` };
|
|
@@ -14048,22 +14139,22 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
14048
14139
|
if (!visualEvidenceEnabled(opts.env))
|
|
14049
14140
|
return skip("LOKI_VISUAL_EVIDENCE is 0");
|
|
14050
14141
|
const api = loadProjectApi(repoDir), boot = isMultiRoot(api) ? api.uiBoot() : null;
|
|
14051
|
-
const appDir = boot ?
|
|
14052
|
-
const pkgPath =
|
|
14142
|
+
const appDir = boot ? join53(repoDir, boot.boot.cwd) : repoDir;
|
|
14143
|
+
const pkgPath = join53(appDir, "package.json");
|
|
14053
14144
|
let script = null;
|
|
14054
14145
|
if (!boot) {
|
|
14055
|
-
if (!
|
|
14056
|
-
const subs = ["backend", "frontend"].filter((d) =>
|
|
14146
|
+
if (!existsSync33(pkgPath)) {
|
|
14147
|
+
const subs = ["backend", "frontend"].filter((d) => existsSync33(join53(repoDir, d, "package.json")));
|
|
14057
14148
|
const has = (d) => {
|
|
14058
14149
|
try {
|
|
14059
|
-
return pickScript(JSON.parse(
|
|
14150
|
+
return pickScript(JSON.parse(readFileSync42(join53(repoDir, d, "package.json"), "utf8"))) !== null;
|
|
14060
14151
|
} catch {
|
|
14061
14152
|
return false;
|
|
14062
14153
|
}
|
|
14063
14154
|
};
|
|
14064
14155
|
return skip(noRootReason(subs, subs.filter((d) => !has(d))));
|
|
14065
14156
|
}
|
|
14066
|
-
script = pickScript(JSON.parse(
|
|
14157
|
+
script = pickScript(JSON.parse(readFileSync42(pkgPath, "utf8")));
|
|
14067
14158
|
if (!script)
|
|
14068
14159
|
return skip("no dev, preview or start script");
|
|
14069
14160
|
}
|
|
@@ -14090,20 +14181,20 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
14090
14181
|
}
|
|
14091
14182
|
if (!await waitUp(base, left(), signal))
|
|
14092
14183
|
return skip(aborted() ? "aborted" : `${script} server did not answer within ${Math.round(budget / 1000)}s`);
|
|
14093
|
-
const evRoot =
|
|
14184
|
+
const evRoot = join53(runDir, "evidence");
|
|
14094
14185
|
if (isSymlink(evRoot))
|
|
14095
14186
|
return skip("evidence dir is a symlink");
|
|
14096
14187
|
mkdirSync21(evRoot, { recursive: true });
|
|
14097
14188
|
if (pages.length > 0) {
|
|
14098
|
-
const rel0 =
|
|
14099
|
-
mkdirSync21(
|
|
14189
|
+
const rel0 = join53("evidence", randomBytes6(6).toString("hex"));
|
|
14190
|
+
mkdirSync21(join53(runDir, rel0));
|
|
14100
14191
|
const rels = [];
|
|
14101
14192
|
for (const route of [...new Set(pages.map(routeFor))].slice(0, opts.maxRoutes ?? MAX_ROUTES)) {
|
|
14102
14193
|
if (aborted() || left() <= 0)
|
|
14103
14194
|
break;
|
|
14104
|
-
const rel =
|
|
14105
|
-
const ok = await shoot(pw, ["screenshot", `${base}${route}`,
|
|
14106
|
-
if (ok && !aborted() && !isSymlink(
|
|
14195
|
+
const rel = join53(rel0, `${screenName(route)}.png`);
|
|
14196
|
+
const ok = await shoot(pw, ["screenshot", `${base}${route}`, join53(runDir, rel)], appDir, left(), signal);
|
|
14197
|
+
if (ok && !aborted() && !isSymlink(join53(runDir, rel)) && existsSync33(join53(runDir, rel)))
|
|
14107
14198
|
rels.push(rel);
|
|
14108
14199
|
}
|
|
14109
14200
|
if (aborted())
|
|
@@ -14128,9 +14219,9 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
14128
14219
|
}
|
|
14129
14220
|
if (aborted())
|
|
14130
14221
|
return skip("aborted");
|
|
14131
|
-
const hdir =
|
|
14222
|
+
const hdir = join53(evRoot, randomBytes6(6).toString("hex"));
|
|
14132
14223
|
mkdirSync21(hdir);
|
|
14133
|
-
writeFileSync24(
|
|
14224
|
+
writeFileSync24(join53(hdir, "http.json"), JSON.stringify(rows, null, 2) + `
|
|
14134
14225
|
`);
|
|
14135
14226
|
return { screens: [], http: true, skipped: null };
|
|
14136
14227
|
} catch (e) {
|
|
@@ -14159,12 +14250,12 @@ function receiptScreensProblem(receiptPath, receipt) {
|
|
|
14159
14250
|
return `visual evidence failed (LOKI_VISUAL_GATE=1): ${receipt["evidence_failed"]}`;
|
|
14160
14251
|
return receipt["evidence_screens"] === undefined ? null : checkScreens(dirname19(receiptPath), receipt["evidence_screens"]);
|
|
14161
14252
|
}
|
|
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
|
|
14253
|
+
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) => {
|
|
14254
|
+
const bin = join53(repoDir, "node_modules", ".bin", "playwright");
|
|
14255
|
+
return existsSync33(bin) ? bin : null;
|
|
14165
14256
|
}, playwrightTestPkg = (repoDir) => {
|
|
14166
|
-
const d =
|
|
14167
|
-
return
|
|
14257
|
+
const d = join53(repoDir, "node_modules", "@playwright", "test");
|
|
14258
|
+
return existsSync33(join53(d, "package.json")) ? d : null;
|
|
14168
14259
|
}, e2eSpecSource = (pkgDir, base, routes) => `const { test } = require(${JSON.stringify(pkgDir)});
|
|
14169
14260
|
test("loki e2e walkthrough", async ({ page }) => {
|
|
14170
14261
|
for (const r of ${JSON.stringify(routes)}) { await page.goto(${JSON.stringify(base)} + r); await page.waitForLoadState("load"); }
|
|
@@ -14210,7 +14301,7 @@ var init_outbox = __esm(() => {
|
|
|
14210
14301
|
});
|
|
14211
14302
|
|
|
14212
14303
|
// ../../loki-ts/src/engine10/stages/pr.ts
|
|
14213
|
-
import { join as
|
|
14304
|
+
import { join as join54 } from "path";
|
|
14214
14305
|
var DEFAULT_PUSH_SH, DEFAULT_PUSH_GITLAB_SH;
|
|
14215
14306
|
var init_pr = __esm(() => {
|
|
14216
14307
|
init_types();
|
|
@@ -14229,20 +14320,20 @@ var init_pr = __esm(() => {
|
|
|
14229
14320
|
init_receipt_surface();
|
|
14230
14321
|
init_yaml_key();
|
|
14231
14322
|
init_outbox();
|
|
14232
|
-
DEFAULT_PUSH_SH =
|
|
14233
|
-
DEFAULT_PUSH_GITLAB_SH =
|
|
14323
|
+
DEFAULT_PUSH_SH = join54(REPO_ROOT, "autonomy/lib/engine10-push.sh");
|
|
14324
|
+
DEFAULT_PUSH_GITLAB_SH = join54(REPO_ROOT, "autonomy/lib/engine10-push-gitlab.sh");
|
|
14234
14325
|
});
|
|
14235
14326
|
|
|
14236
14327
|
// ../../loki-ts/src/util/pr_lessons.ts
|
|
14237
|
-
import { existsSync as
|
|
14238
|
-
import { dirname as dirname20, join as
|
|
14328
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync8, readFileSync as readFileSync43, rmSync as rmSync16, writeFileSync as writeFileSync25 } from "fs";
|
|
14329
|
+
import { dirname as dirname20, join as join55 } from "path";
|
|
14239
14330
|
import { createHash as createHash15 } from "crypto";
|
|
14240
14331
|
function loadLessons(repoDir) {
|
|
14241
14332
|
const p = lessonsPath(repoDir);
|
|
14242
|
-
if (!
|
|
14333
|
+
if (!existsSync34(p))
|
|
14243
14334
|
return [];
|
|
14244
14335
|
try {
|
|
14245
|
-
const j = JSON.parse(
|
|
14336
|
+
const j = JSON.parse(readFileSync43(p, "utf-8"));
|
|
14246
14337
|
return Array.isArray(j.lessons) ? j.lessons : [];
|
|
14247
14338
|
} catch {
|
|
14248
14339
|
return [];
|
|
@@ -14284,7 +14375,7 @@ function recordRunVerdict(repoDir, runId2, verdict) {
|
|
|
14284
14375
|
if (dirty)
|
|
14285
14376
|
save(repoDir, lessons);
|
|
14286
14377
|
}
|
|
14287
|
-
var lessonsPath = (repoDir) =>
|
|
14378
|
+
var lessonsPath = (repoDir) => join55(repoDir, ".loki", "memory", "semantic", "pr-lessons.json"), KINDS;
|
|
14288
14379
|
var init_pr_lessons = __esm(() => {
|
|
14289
14380
|
init_atomic();
|
|
14290
14381
|
init_safe_git();
|
|
@@ -14310,9 +14401,9 @@ var init_attempts = __esm(() => {
|
|
|
14310
14401
|
var init_mcp_config = () => {};
|
|
14311
14402
|
|
|
14312
14403
|
// ../../loki-ts/src/providers/claude_flags.ts
|
|
14313
|
-
import { existsSync as
|
|
14404
|
+
import { existsSync as existsSync35, readFileSync as readFileSync44 } from "fs";
|
|
14314
14405
|
import { resolve as resolvePath, dirname as dirname21 } from "path";
|
|
14315
|
-
import { fileURLToPath as
|
|
14406
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
14316
14407
|
function claudeFlagSupported(flag, helpText) {
|
|
14317
14408
|
const txt = helpText ?? _claudeHelpCache;
|
|
14318
14409
|
if (txt === null || txt === undefined) {
|
|
@@ -14358,14 +14449,14 @@ function leanReviewerFlags(opts = {}) {
|
|
|
14358
14449
|
}
|
|
14359
14450
|
function designArchetypesText() {
|
|
14360
14451
|
try {
|
|
14361
|
-
const moduleDir = dirname21(
|
|
14452
|
+
const moduleDir = dirname21(fileURLToPath5(import.meta.url));
|
|
14362
14453
|
for (const rel of [
|
|
14363
14454
|
["..", "..", "..", "references", "design-archetypes.md"],
|
|
14364
14455
|
["..", "..", "references", "design-archetypes.md"]
|
|
14365
14456
|
]) {
|
|
14366
14457
|
const p = resolvePath(moduleDir, ...rel);
|
|
14367
|
-
if (
|
|
14368
|
-
return
|
|
14458
|
+
if (existsSync35(p))
|
|
14459
|
+
return readFileSync44(p, "utf8");
|
|
14369
14460
|
}
|
|
14370
14461
|
} catch {}
|
|
14371
14462
|
return "";
|
|
@@ -14450,14 +14541,14 @@ var init_providers = __esm(() => {
|
|
|
14450
14541
|
});
|
|
14451
14542
|
|
|
14452
14543
|
// ../../loki-ts/src/runner/router/route_record.ts
|
|
14453
|
-
import { existsSync as
|
|
14454
|
-
import { join as
|
|
14544
|
+
import { existsSync as existsSync36, lstatSync as lstatSync13, mkdirSync as mkdirSync23, readFileSync as readFileSync45, writeFileSync as writeFileSync26 } from "fs";
|
|
14545
|
+
import { join as join56 } from "path";
|
|
14455
14546
|
function loadRouteRecord(runDir) {
|
|
14456
14547
|
try {
|
|
14457
|
-
const p =
|
|
14458
|
-
if (!
|
|
14548
|
+
const p = join56(runDir, ROUTE_RECORD_FILE);
|
|
14549
|
+
if (!existsSync36(p) || !lstatSync13(p).isFile())
|
|
14459
14550
|
return;
|
|
14460
|
-
const v = JSON.parse(
|
|
14551
|
+
const v = JSON.parse(readFileSync45(p, "utf8"));
|
|
14461
14552
|
return typeof v === "object" && v !== null && !Array.isArray(v) ? v : undefined;
|
|
14462
14553
|
} catch {
|
|
14463
14554
|
return;
|
|
@@ -14605,14 +14696,14 @@ __export(exports_deep, {
|
|
|
14605
14696
|
DEFAULT_SECRET_SCAN_SH: () => DEFAULT_SECRET_SCAN_SH,
|
|
14606
14697
|
DEFAULT_PUSH_SH: () => DEFAULT_PUSH_SH2
|
|
14607
14698
|
});
|
|
14608
|
-
import { copyFileSync as copyFileSync3, existsSync as
|
|
14699
|
+
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
14700
|
import { tmpdir as tmpdir10 } from "os";
|
|
14610
|
-
import { dirname as dirname22, join as
|
|
14701
|
+
import { dirname as dirname22, join as join57 } from "path";
|
|
14611
14702
|
function sessionCouncil(sessions) {
|
|
14612
14703
|
return { async run(input, signal) {
|
|
14613
|
-
const cwd = mkdtempSync9(
|
|
14704
|
+
const cwd = mkdtempSync9(join57(tmpdir10(), "loki-deep-council-"));
|
|
14614
14705
|
try {
|
|
14615
|
-
writeFileSync27(
|
|
14706
|
+
writeFileSync27(join57(cwd, "diff.patch"), input.diff, "utf8");
|
|
14616
14707
|
const r = await sessions.run({
|
|
14617
14708
|
stage: "deep",
|
|
14618
14709
|
tier: "development",
|
|
@@ -14682,7 +14773,7 @@ ${r.stderr}`, lr = r.exitCode === 0 ? undefined : await harnessLoadReason({ repo
|
|
|
14682
14773
|
async function runAppBoot(ctx, opts, checks, notProven) {
|
|
14683
14774
|
let r;
|
|
14684
14775
|
try {
|
|
14685
|
-
r = await (opts.appProbe ?? appProbe)(ctx.repoDir,
|
|
14776
|
+
r = await (opts.appProbe ?? appProbe)(ctx.repoDir, join57(ctx.repoDir, ".loki"));
|
|
14686
14777
|
} catch (err) {
|
|
14687
14778
|
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
14779
|
}
|
|
@@ -14724,12 +14815,12 @@ async function runCouncilCheck(ctx, changed, baseSha, signal, opts, checks, notP
|
|
|
14724
14815
|
}
|
|
14725
14816
|
}
|
|
14726
14817
|
async function secureScanChanged(repoDir, changed, opts) {
|
|
14727
|
-
const dir = mkdtempSync9(
|
|
14818
|
+
const dir = mkdtempSync9(join57(tmpdir10(), "loki-deep-secure-"));
|
|
14728
14819
|
try {
|
|
14729
14820
|
for (const f of changed)
|
|
14730
|
-
if (
|
|
14731
|
-
mkdirSync24(dirname22(
|
|
14732
|
-
copyFileSync3(
|
|
14821
|
+
if (existsSync37(join57(repoDir, f)) && lstatSync14(join57(repoDir, f)).isFile()) {
|
|
14822
|
+
mkdirSync24(dirname22(join57(dir, f)), { recursive: true });
|
|
14823
|
+
copyFileSync3(join57(repoDir, f), join57(dir, f));
|
|
14733
14824
|
}
|
|
14734
14825
|
return await runSecureScan(dir, { ...opts.secureScanPath ? { scriptPath: opts.secureScanPath } : {}, timeoutMs: 60000 });
|
|
14735
14826
|
} finally {
|
|
@@ -14738,7 +14829,7 @@ async function secureScanChanged(repoDir, changed, opts) {
|
|
|
14738
14829
|
}
|
|
14739
14830
|
async function runSecretScan(ctx, changed, opts, checks, notProven) {
|
|
14740
14831
|
const scriptPath = opts.secretScanShPath ?? DEFAULT_SECRET_SCAN_SH, name = "security scan", cmd2 = "secret-scan.sh + secure-scan.py";
|
|
14741
|
-
if (!
|
|
14832
|
+
if (!existsSync37(scriptPath)) {
|
|
14742
14833
|
checks.push({ name, cmd: cmd2, result: "not_run", duration_s: 0 });
|
|
14743
14834
|
notProven.add(`not run: ${name} (secret-scan.sh not found)`);
|
|
14744
14835
|
return;
|
|
@@ -14749,7 +14840,7 @@ async function runSecretScan(ctx, changed, opts, checks, notProven) {
|
|
|
14749
14840
|
}
|
|
14750
14841
|
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
14842
|
const started = Date.now();
|
|
14752
|
-
const r = await run(["bash", "-c", inline, "_", scriptPath, ...changed.map((f) =>
|
|
14843
|
+
const r = await run(["bash", "-c", inline, "_", scriptPath, ...changed.map((f) => join57(ctx.repoDir, f))], { cwd: ctx.repoDir, timeoutMs: 30000 });
|
|
14753
14844
|
const sec = await secureScanChanged(ctx.repoDir, changed, opts), gaps = [], reasons = [];
|
|
14754
14845
|
const hits = r.exitCode === 3 ? [] : r.stdout.split(`
|
|
14755
14846
|
`).map((l) => l.trim()).filter(Boolean), high = sec.findings.filter((f) => String(f.severity).toUpperCase() === "HIGH");
|
|
@@ -14790,7 +14881,7 @@ async function postResults(ctx, opts, checks, notProven, statusState) {
|
|
|
14790
14881
|
const prNumber = prUrl ? PR_NUMBER_RE.exec(prUrl)?.[1] : undefined;
|
|
14791
14882
|
if (prNumber) {
|
|
14792
14883
|
mkdirSync24(ctx.runDir, { recursive: true });
|
|
14793
|
-
const bodyFile =
|
|
14884
|
+
const bodyFile = join57(ctx.runDir, "deep-comment.md");
|
|
14794
14885
|
writeFileSync27(bodyFile, buildCommentBody(checks, notProven, statusState), "utf8");
|
|
14795
14886
|
const commentResult = await run(["bash", scriptPath, ...commentArgv(prNumber, bodyFile)], { cwd: ctx.repoDir, env, timeoutMs: 30000 });
|
|
14796
14887
|
if (commentResult.exitCode !== 0)
|
|
@@ -14844,7 +14935,7 @@ async function runDeep(ctx, signal, opts = {}) {
|
|
|
14844
14935
|
const sig = signReceipt(`${ctx.runId}-deep`, addendumSha256);
|
|
14845
14936
|
const addendum = { ...addendumBody, addendum_sha256: addendumSha256, verification: { jwt: sig.jwt, kid: sig.kid } };
|
|
14846
14937
|
mkdirSync24(ctx.runDir, { recursive: true });
|
|
14847
|
-
writeFileSync27(
|
|
14938
|
+
writeFileSync27(join57(ctx.runDir, "receipt-addendum-1.json"), JSON.stringify(addendum, null, 2) + `
|
|
14848
14939
|
`);
|
|
14849
14940
|
const pushNotProven = await postResults(ctx, opts, checks, notProvenList, statusState);
|
|
14850
14941
|
const allNotProven = [...notProvenList, ...pushNotProven];
|
|
@@ -14880,9 +14971,9 @@ var init_deep = __esm(() => {
|
|
|
14880
14971
|
});
|
|
14881
14972
|
|
|
14882
14973
|
// ../../loki-ts/src/engine10/stages/verify.ts
|
|
14883
|
-
import { existsSync as
|
|
14974
|
+
import { existsSync as existsSync38, mkdtempSync as mkdtempSync10, rmSync as rmSync18 } from "fs";
|
|
14884
14975
|
import { tmpdir as tmpdir11 } from "os";
|
|
14885
|
-
import { isAbsolute as isAbsolute9, join as
|
|
14976
|
+
import { isAbsolute as isAbsolute9, join as join58, relative as relative9 } from "path";
|
|
14886
14977
|
async function runOnce2(cmd2, args, cwd, signal, opts) {
|
|
14887
14978
|
if (!Bun.which(cmd2, { PATH: opts.path ?? process.env["PATH"] ?? "" }))
|
|
14888
14979
|
return { ok: false, missing: true, cut: false, out: "" };
|
|
@@ -14945,17 +15036,18 @@ async function runCheck(ctx, name, cmd2, args, signal, checks, opts = {}) {
|
|
|
14945
15036
|
ctx.emit("test.result", "verify", opts.opaque ? { ...pubHold(check) } : { ...check });
|
|
14946
15037
|
return check;
|
|
14947
15038
|
}
|
|
14948
|
-
async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal) {
|
|
14949
|
-
const out2 = { ids: [], names: [], weak: [], cnt: {} };
|
|
15039
|
+
async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal, zeroOk = true) {
|
|
15040
|
+
const out2 = { ids: [], names: [], weak: [], zero: [], cnt: {} };
|
|
14950
15041
|
const pairs = checks.flatMap((c) => {
|
|
14951
15042
|
const t = tests.find((x) => testCheckName(x) === c.name);
|
|
14952
15043
|
return t ? [{ c, t }] : [];
|
|
14953
15044
|
});
|
|
14954
15045
|
const un = pairs.filter(({ t }) => !changed.includes(t.path));
|
|
14955
15046
|
const sus = pairs.filter(({ c }) => rel.has(c.name) && c.result === "pass");
|
|
14956
|
-
|
|
15047
|
+
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)) : [];
|
|
15048
|
+
if (!(un.some(({ c }) => c.result === "fail" && c.ids?.length) || sus.length || zc.length) || signal.aborted)
|
|
14957
15049
|
return out2;
|
|
14958
|
-
const dir = mkdtempSync10(
|
|
15050
|
+
const dir = mkdtempSync10(join58(tmpdir11(), "e10-base-"));
|
|
14959
15051
|
const git4 = (args) => {
|
|
14960
15052
|
safeGit(ctx.repoDir, args, { stdio: "ignore", repoDrivers: true });
|
|
14961
15053
|
};
|
|
@@ -14968,6 +15060,7 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal)
|
|
|
14968
15060
|
const red = !b.ok && !b.cut ? failIds(b.out) : [];
|
|
14969
15061
|
base.set(c, { red, n: ran(b.out) ?? summaryPassFailCount(b.out), sk: skipped(b.out) });
|
|
14970
15062
|
}
|
|
15063
|
+
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
15064
|
out2.weak = sus.filter(({ c }) => (c.sk ?? 0) > base.get(c).sk || (c.n ?? 0) < base.get(c).n).map(({ c }) => c.name);
|
|
14972
15065
|
for (const { c } of sus) {
|
|
14973
15066
|
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 +15086,7 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal)
|
|
|
14993
15086
|
return out2;
|
|
14994
15087
|
}
|
|
14995
15088
|
function isLokiModeRepo(repoDir) {
|
|
14996
|
-
return
|
|
15089
|
+
return existsSync38(join58(repoDir, "scripts", "select-tests.sh"));
|
|
14997
15090
|
}
|
|
14998
15091
|
async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
|
|
14999
15092
|
const { api, ...runOpts } = opts;
|
|
@@ -15015,9 +15108,9 @@ async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
|
|
|
15015
15108
|
}
|
|
15016
15109
|
for (const g of groupByPackage(api, ctx.repoDir, changed.filter((f) => /\.(ts|tsx|js|jsx)$/.test(f)))) {
|
|
15017
15110
|
const sfx = g.root === "." ? "" : `:${g.root}`, co = g.root === "." ? opts : { ...opts, cwd: g.cwd };
|
|
15018
|
-
if (
|
|
15111
|
+
if (existsSync38(join58(g.cwd, "tsconfig.json")))
|
|
15019
15112
|
await runCheck(ctx, `lint:tsc${sfx}`, "npx", ["--no-install", "tsc", "--noEmit", "-p", "."], signal, checks, { ...co, kind: "static" });
|
|
15020
|
-
if (ESLINT_CONFIGS.some((f) =>
|
|
15113
|
+
if (ESLINT_CONFIGS.some((f) => existsSync38(join58(g.cwd, f)))) {
|
|
15021
15114
|
const c = await runCheck(ctx, `lint:eslint${sfx}`, "npx", ["--no-install", "eslint", ...g.rel], signal, checks, { ...co, kind: "static" });
|
|
15022
15115
|
if (await excuseLint(ctx, signal, c, "eslint", "npx", ["--no-install", "eslint"], g.cwd, g.rel, co))
|
|
15023
15116
|
pre.push(c.name);
|
|
@@ -15032,7 +15125,7 @@ var CHECK_TIMEOUT_MS = 60000, excerpts, isHold = (c) => isHoldoutCheck(c.name),
|
|
|
15032
15125
|
return r.missing || r.cut ? null : r;
|
|
15033
15126
|
}, base: (f) => {
|
|
15034
15127
|
try {
|
|
15035
|
-
return safeGit(ctx.repoDir, ["show", `${ctx.baseSha}:${
|
|
15128
|
+
return safeGit(ctx.repoDir, ["show", `${ctx.baseSha}:${relative9(ctx.repoDir, join58(cwd, f))}`], { stdio: ["ignore", "pipe", "ignore"] });
|
|
15036
15129
|
} catch {
|
|
15037
15130
|
return null;
|
|
15038
15131
|
}
|
|
@@ -15053,6 +15146,7 @@ var init_verify = __esm(() => {
|
|
|
15053
15146
|
init_types();
|
|
15054
15147
|
init_resolve();
|
|
15055
15148
|
init_safe_git();
|
|
15149
|
+
init_base_guard();
|
|
15056
15150
|
init_repo_profile();
|
|
15057
15151
|
init_check_result();
|
|
15058
15152
|
init_check_result();
|
|
@@ -15095,7 +15189,7 @@ var init_verify = __esm(() => {
|
|
|
15095
15189
|
const impacted = ctx.tests.impacted(map, changed);
|
|
15096
15190
|
const changedTestFiles = map.tests.filter((t) => changed.includes(t.path));
|
|
15097
15191
|
const wall = ctx.outputs().wall ?? {};
|
|
15098
|
-
const wallPaths = new Set((wall.files ?? []).map((f) => isAbsolute9(f.path) ?
|
|
15192
|
+
const wallPaths = new Set((wall.files ?? []).map((f) => isAbsolute9(f.path) ? relative9(ctx.repoDir, f.path) : f.path));
|
|
15099
15193
|
const intake = ctx.outputs().intake, repoMap = loadRepoMap(intake?.repomap_ref), relevant2 = ctx.tests.impacted(map, namedFiles(intake?.task ?? "", repoMap));
|
|
15100
15194
|
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
15195
|
const tests = failedFirst(dedupeTests([...impacted, ...changedTestFiles, ...wallTests, ...relevant2]), ctx.outputs().verify?.checks);
|
|
@@ -15126,7 +15220,8 @@ var init_verify = __esm(() => {
|
|
|
15126
15220
|
ctx.emit("test.result", "verify", { ...pubHold(k) });
|
|
15127
15221
|
}
|
|
15128
15222
|
const targetNames = new Set([...[...wallTests, ...relevant2].map(testCheckName), ...checks.filter(isHold).map((c) => c.name)]);
|
|
15129
|
-
const
|
|
15223
|
+
const cfgChanged = testConfigChanged(ctx.repoDir, ctx.baseSha, changed);
|
|
15224
|
+
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
15225
|
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
15226
|
attr.introducedChecks = [...new Set(attr.introducedChecks.map((n2) => isHoldoutCheck(n2) ? "holdout" : n2))];
|
|
15132
15227
|
preRed.names.push(...attr.preExistingChecks);
|
|
@@ -15165,7 +15260,6 @@ var init_verify = __esm(() => {
|
|
|
15165
15260
|
recordRisk(ctx.repoDir, risk);
|
|
15166
15261
|
}
|
|
15167
15262
|
}
|
|
15168
|
-
const cfgChanged = testConfigChanged(ctx.repoDir, ctx.baseSha, changed);
|
|
15169
15263
|
const covered = (f) => ctx.tests.impacted(map, [f]).some((t) => checks.some((c) => c.name === testCheckName(t) && hasExecutedProof([c])));
|
|
15170
15264
|
const uncoveredChanged = changed.filter((f) => CODE_EXT.test(f) && !isTestFile(f) && !wallPaths.has(f) && !cfgChanged.includes(f) && !covered(f));
|
|
15171
15265
|
const flaky = checks.filter((c) => c.result === "flaky").map((c) => isHold(c) ? "holdout" : c.name);
|
|
@@ -15195,14 +15289,14 @@ ${x}` : c.cmd };
|
|
|
15195
15289
|
const weakened = [...modifiedRel, ...cfgChanged.map((f) => `test configuration changed: ${f}`), ...preRed.weak.map((n2) => `skipped or fewer tests than base: ${n2}`)];
|
|
15196
15290
|
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
15291
|
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 } };
|
|
15292
|
+
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
15293
|
}
|
|
15200
15294
|
};
|
|
15201
15295
|
});
|
|
15202
15296
|
|
|
15203
15297
|
// ../../loki-ts/src/project_model/conventions.ts
|
|
15204
|
-
import { existsSync as
|
|
15205
|
-
import { dirname as dirname23, join as
|
|
15298
|
+
import { existsSync as existsSync39, readdirSync as readdirSync20, readFileSync as readFileSync46 } from "fs";
|
|
15299
|
+
import { dirname as dirname23, join as join59 } from "path";
|
|
15206
15300
|
function parseJsonc(text2) {
|
|
15207
15301
|
let out2 = "", i = 0;
|
|
15208
15302
|
while (i < text2.length) {
|
|
@@ -15237,25 +15331,25 @@ function moduleOf(file, depth = 0) {
|
|
|
15237
15331
|
const ext = typeof j.extends === "string" ? j.extends : null;
|
|
15238
15332
|
if (!ext || !ext.startsWith("."))
|
|
15239
15333
|
return null;
|
|
15240
|
-
const next =
|
|
15241
|
-
return
|
|
15334
|
+
const next = join59(dirname23(file), ext.endsWith(".json") ? ext : `${ext}.json`);
|
|
15335
|
+
return existsSync39(next) ? moduleOf(next, depth + 1) : null;
|
|
15242
15336
|
}
|
|
15243
15337
|
function readPackageConventions(pkgDir, runner = null) {
|
|
15244
15338
|
let names = [];
|
|
15245
15339
|
try {
|
|
15246
|
-
names =
|
|
15340
|
+
names = readdirSync20(pkgDir).filter((f) => f.endsWith(".json")).sort((x, y) => x.length - y.length || x.localeCompare(y));
|
|
15247
15341
|
} catch {
|
|
15248
15342
|
return null;
|
|
15249
15343
|
}
|
|
15250
15344
|
let packageType = null, tsModule = null;
|
|
15251
15345
|
for (const n2 of names) {
|
|
15252
|
-
const j = readJson5(
|
|
15346
|
+
const j = readJson5(join59(pkgDir, n2));
|
|
15253
15347
|
if (!j)
|
|
15254
15348
|
continue;
|
|
15255
15349
|
if (packageType === null && typeof j.type === "string" && typeof j.name === "string")
|
|
15256
15350
|
packageType = j.type;
|
|
15257
15351
|
if (tsModule === null && j.compilerOptions !== undefined)
|
|
15258
|
-
tsModule = moduleOf(
|
|
15352
|
+
tsModule = moduleOf(join59(pkgDir, n2));
|
|
15259
15353
|
}
|
|
15260
15354
|
if (packageType === null && tsModule === null)
|
|
15261
15355
|
return null;
|
|
@@ -15277,7 +15371,7 @@ function conventionViolation(c, fileName, content) {
|
|
|
15277
15371
|
}
|
|
15278
15372
|
var readJson5 = (p) => {
|
|
15279
15373
|
try {
|
|
15280
|
-
const v = parseJsonc(
|
|
15374
|
+
const v = parseJsonc(readFileSync46(p, "utf8"));
|
|
15281
15375
|
return v && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
15282
15376
|
} catch {
|
|
15283
15377
|
return null;
|
|
@@ -15287,9 +15381,9 @@ var init_conventions = () => {};
|
|
|
15287
15381
|
|
|
15288
15382
|
// ../../loki-ts/src/engine10/stages/wall.ts
|
|
15289
15383
|
import { spawnSync as spawnSync7 } from "child_process";
|
|
15290
|
-
import { existsSync as
|
|
15384
|
+
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
15385
|
import { tmpdir as tmpdir12 } from "os";
|
|
15292
|
-
import { dirname as dirname24, join as
|
|
15386
|
+
import { dirname as dirname24, join as join60, relative as relative10 } from "path";
|
|
15293
15387
|
|
|
15294
15388
|
class RealBaseTestRunner {
|
|
15295
15389
|
api;
|
|
@@ -15352,10 +15446,10 @@ ${acceptance.map((a) => `Acceptance: ${a}`).join(`
|
|
|
15352
15446
|
function loadTaskText(ctx, fromPrior) {
|
|
15353
15447
|
if (fromPrior)
|
|
15354
15448
|
return fromPrior;
|
|
15355
|
-
const issueJsonPath = process.env.LOKI_E10_ISSUE_JSON ??
|
|
15356
|
-
if (
|
|
15449
|
+
const issueJsonPath = process.env.LOKI_E10_ISSUE_JSON ?? join60(ctx.runDir, "issue.json");
|
|
15450
|
+
if (existsSync40(issueJsonPath)) {
|
|
15357
15451
|
try {
|
|
15358
|
-
const issue = JSON.parse(
|
|
15452
|
+
const issue = JSON.parse(readFileSync47(issueJsonPath, "utf8"));
|
|
15359
15453
|
const text2 = [issue.title, issue.body].filter((s) => typeof s === "string" && s.length > 0).join(`
|
|
15360
15454
|
|
|
15361
15455
|
`);
|
|
@@ -15367,7 +15461,7 @@ function loadTaskText(ctx, fromPrior) {
|
|
|
15367
15461
|
}
|
|
15368
15462
|
function wallTargetDir(repoDir, existingTests) {
|
|
15369
15463
|
const first = existingTests[0];
|
|
15370
|
-
return first ?
|
|
15464
|
+
return first ? join60(repoDir, dirname24(first.path)) : join60(repoDir, "tests");
|
|
15371
15465
|
}
|
|
15372
15466
|
function guessRunner(fileName, runners) {
|
|
15373
15467
|
if (fileName.endsWith(".py"))
|
|
@@ -15399,12 +15493,12 @@ async function wallAuthor(ctx, signal, retry) {
|
|
|
15399
15493
|
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
15494
|
const tree = prior.intake?.tree;
|
|
15401
15495
|
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(
|
|
15496
|
+
const targetDir = wallTargetDir(ctx.repoDir, existingTests), pkg = loadProjectApi(ctx.repoDir)?.packageOf(`${relative10(ctx.repoDir, targetDir)}/x`);
|
|
15497
|
+
const conv2 = readPackageConventions(join60(ctx.repoDir, pkg?.root ?? "."), pkg?.runner ?? null);
|
|
15498
|
+
const cwd = mkdtempSync11(join60(tmpdir12(), "loki-e15-wall-"));
|
|
15405
15499
|
const wm = wallManifestFor(ctx.repoDir, tree, task);
|
|
15406
15500
|
for (const [n2, c] of [["task.md", task], ["repomap.txt", repomapText], ...wm ? [["wall_manifest.txt", wm.text]] : []])
|
|
15407
|
-
writeFileSync28(
|
|
15501
|
+
writeFileSync28(join60(cwd, n2), c, "utf8");
|
|
15408
15502
|
const model = retry?.model ?? wallFirstModel(sz.size), iterationId = `${ctx.runId}-wall${retry?.suffix ?? ""}`;
|
|
15409
15503
|
const session = await ctx.sessions.run({
|
|
15410
15504
|
stage: "wall",
|
|
@@ -15420,15 +15514,15 @@ async function wallAuthor(ctx, signal, retry) {
|
|
|
15420
15514
|
rmSync19(cwd, { recursive: true, force: true });
|
|
15421
15515
|
return done({ status: "failed", data: { iteration_ids: [iterationId], model }, reason: "wall session aborted, killed, or timed out", killed: true });
|
|
15422
15516
|
}
|
|
15423
|
-
const all =
|
|
15424
|
-
const sealedDir =
|
|
15517
|
+
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));
|
|
15518
|
+
const sealedDir = join60(ctx.runDir, "wall");
|
|
15425
15519
|
if (generated.length > 0)
|
|
15426
15520
|
mkdirSync25(sealedDir, { recursive: true });
|
|
15427
15521
|
const contents = new Map;
|
|
15428
15522
|
const discarded = [];
|
|
15429
15523
|
for (const name of generated) {
|
|
15430
|
-
const content =
|
|
15431
|
-
writeFileSync28(
|
|
15524
|
+
const content = readFileSync47(join60(cwd, name), "utf8"), bad = conventionViolation(conv2, name, content);
|
|
15525
|
+
writeFileSync28(join60(sealedDir, name), content, "utf8");
|
|
15432
15526
|
if (bad)
|
|
15433
15527
|
discarded.push({ file: name, reason: `${bad}; wall test did not compile under the package config` });
|
|
15434
15528
|
else
|
|
@@ -15455,19 +15549,19 @@ function* installCore(ctx, a, baseDir, opts) {
|
|
|
15455
15549
|
const content = contents.get(name);
|
|
15456
15550
|
if (content === undefined)
|
|
15457
15551
|
continue;
|
|
15458
|
-
const dest =
|
|
15552
|
+
const dest = join60(targetDir, name), runner = guessRunner(name, runners);
|
|
15459
15553
|
writeFileSync28(dest, content, "utf8");
|
|
15460
15554
|
sealedFiles.push({ path: dest, sha256: sha2562(content) });
|
|
15461
15555
|
readOnlyFiles.push({ path: dest, content });
|
|
15462
15556
|
if (runner)
|
|
15463
|
-
wallTests.push({ runner, path:
|
|
15557
|
+
wallTests.push({ runner, path: relative10(ctx.repoDir, dest) });
|
|
15464
15558
|
}
|
|
15465
15559
|
ctx.wallSealed = true;
|
|
15466
15560
|
ctx.emit("wall.sealed", "wall", { files: sealedFiles, ...a.manifestSha256 ? { manifest_sha256: a.manifestSha256 } : {} });
|
|
15467
15561
|
const baseRunner = opts.baseRunner ?? new RealBaseTestRunner, baseRun = { pass: 0, fail: 0, not_run: discarded.length }, notRunFiles = [];
|
|
15468
15562
|
const each = yield { runner: baseRunner, tests: wallTests };
|
|
15469
15563
|
for (const [i, t] of wallTests.entries()) {
|
|
15470
|
-
const e = each?.[i], r = e ?? baseRunner.run(baseDir, [t]), abs =
|
|
15564
|
+
const e = each?.[i], r = e ?? baseRunner.run(baseDir, [t]), abs = join60(ctx.repoDir, t.path);
|
|
15471
15565
|
baseRun.pass += r.pass;
|
|
15472
15566
|
baseRun.fail += r.fail;
|
|
15473
15567
|
baseRun.not_run += r.not_run ?? 0;
|
|
@@ -15508,7 +15602,7 @@ async function runWall(ctx, signal, opts = {}) {
|
|
|
15508
15602
|
if (a.kind === "authored") {
|
|
15509
15603
|
for (const f of first.data.files ?? [])
|
|
15510
15604
|
rmSync19(f.path, { force: true });
|
|
15511
|
-
rmSync19(
|
|
15605
|
+
rmSync19(join60(ctx.runDir, "wall"), { recursive: true, force: true });
|
|
15512
15606
|
ctx.wallSealed = false;
|
|
15513
15607
|
}
|
|
15514
15608
|
removeHoldout(ctx.runId, ctx.repoDir);
|
|
@@ -15544,15 +15638,15 @@ var init_wall = __esm(() => {
|
|
|
15544
15638
|
});
|
|
15545
15639
|
|
|
15546
15640
|
// ../../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
|
|
15641
|
+
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";
|
|
15642
|
+
import { dirname as dirname25, join as join61, relative as relative11, sep as sep14 } from "path";
|
|
15549
15643
|
function safeRestore(repoDir, f, want, mode) {
|
|
15550
|
-
const root =
|
|
15644
|
+
const root = realpathSync23(repoDir), fp = join61(root, f), rel = relative11(root, dirname25(fp));
|
|
15551
15645
|
if (rel.startsWith(".."))
|
|
15552
15646
|
throw new Error("outside repo");
|
|
15553
15647
|
let cur = root;
|
|
15554
|
-
for (const part of rel === "" ? [] : rel.split(
|
|
15555
|
-
cur =
|
|
15648
|
+
for (const part of rel === "" ? [] : rel.split(sep14)) {
|
|
15649
|
+
cur = join61(cur, part);
|
|
15556
15650
|
let st2;
|
|
15557
15651
|
try {
|
|
15558
15652
|
st2 = lstatSync15(cur);
|
|
@@ -15569,7 +15663,7 @@ function safeRestore(repoDir, f, want, mode) {
|
|
|
15569
15663
|
} catch {
|
|
15570
15664
|
st = null;
|
|
15571
15665
|
}
|
|
15572
|
-
if (st?.isFile() &&
|
|
15666
|
+
if (st?.isFile() && readFileSync48(fp).equals(want)) {
|
|
15573
15667
|
chmodSync5(fp, mode);
|
|
15574
15668
|
return;
|
|
15575
15669
|
}
|
|
@@ -15606,7 +15700,7 @@ async function discardIfSatisfied(git4, base, o, staged, keep, repoDir) {
|
|
|
15606
15700
|
return { status: "failed", data: {}, reason: "already-satisfied discard failed" };
|
|
15607
15701
|
const notProven = [];
|
|
15608
15702
|
for (const [f, v] of Object.entries(o.intake?.preexisting_untracked_blobs ?? {})) {
|
|
15609
|
-
const fp =
|
|
15703
|
+
const fp = join61(repoDir, f);
|
|
15610
15704
|
try {
|
|
15611
15705
|
if (v.startsWith("!")) {
|
|
15612
15706
|
const st = lstatSync15(fp);
|
|
@@ -15625,7 +15719,7 @@ async function discardIfSatisfied(git4, base, o, staged, keep, repoDir) {
|
|
|
15625
15719
|
try {
|
|
15626
15720
|
let m = 420;
|
|
15627
15721
|
try {
|
|
15628
|
-
const l = lstatSync15(
|
|
15722
|
+
const l = lstatSync15(join61(repoDir, f));
|
|
15629
15723
|
if (l.isFile())
|
|
15630
15724
|
m = l.mode & 511;
|
|
15631
15725
|
} catch {}
|
|
@@ -15672,7 +15766,7 @@ var init_commit_filter = __esm(() => {
|
|
|
15672
15766
|
});
|
|
15673
15767
|
|
|
15674
15768
|
// ../../loki-ts/src/e10ext/scope.ts
|
|
15675
|
-
import { basename as
|
|
15769
|
+
import { basename as basename23, dirname as dirname27 } from "path";
|
|
15676
15770
|
function contractText(o) {
|
|
15677
15771
|
const c = o.intake?.contract_snapshot?.contract;
|
|
15678
15772
|
return Array.isArray(c?.criteria) ? c.criteria.map((x) => typeof x?.text === "string" ? x.text : "").join(`
|
|
@@ -15687,7 +15781,7 @@ function outsideScope(o, staged) {
|
|
|
15687
15781
|
${typeof o.intake?.task === "string" ? o.intake.task : ""}
|
|
15688
15782
|
${contractText(o)}`, pre = o.intake?.preexisting_dirty ?? {};
|
|
15689
15783
|
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,
|
|
15784
|
+
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
15785
|
}
|
|
15692
15786
|
function flagOutsideScope(o, staged) {
|
|
15693
15787
|
const unit = unitFlags(staged, process.env, o.intake?.preexisting_dirty ?? {});
|
|
@@ -15702,14 +15796,14 @@ var init_scope2 = __esm(() => {
|
|
|
15702
15796
|
});
|
|
15703
15797
|
|
|
15704
15798
|
// ../../loki-ts/src/council/role_agents.ts
|
|
15705
|
-
import { existsSync as
|
|
15799
|
+
import { existsSync as existsSync41, readdirSync as readdirSync22, readFileSync as readFileSync49 } from "fs";
|
|
15706
15800
|
import { homedir as homedir9 } from "os";
|
|
15707
|
-
import { join as
|
|
15801
|
+
import { join as join62 } from "path";
|
|
15708
15802
|
function agentDirs(repoDir, env = process.env) {
|
|
15709
|
-
return [env["LOKI_AGENTS_PROJECT_DIR"] ||
|
|
15803
|
+
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
15804
|
}
|
|
15711
15805
|
function parseAgent(file, stem2) {
|
|
15712
|
-
const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(
|
|
15806
|
+
const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(readFileSync49(file, "utf8"));
|
|
15713
15807
|
if (!m)
|
|
15714
15808
|
return null;
|
|
15715
15809
|
const body = m[2].trim();
|
|
@@ -15723,18 +15817,18 @@ function parseAgent(file, stem2) {
|
|
|
15723
15817
|
}
|
|
15724
15818
|
function loadRoleAgent(repoDir, role, env = process.env) {
|
|
15725
15819
|
for (const d of agentDirs(repoDir, env)) {
|
|
15726
|
-
if (!
|
|
15820
|
+
if (!existsSync41(d))
|
|
15727
15821
|
continue;
|
|
15728
15822
|
let names;
|
|
15729
15823
|
try {
|
|
15730
|
-
names =
|
|
15824
|
+
names = readdirSync22(d).filter((n2) => n2.endsWith(".md") && !n2.startsWith(".")).sort();
|
|
15731
15825
|
} catch {
|
|
15732
15826
|
continue;
|
|
15733
15827
|
}
|
|
15734
15828
|
const ordered = [...names.filter((n2) => n2 === `${role}.md`), ...names.filter((n2) => n2 !== `${role}.md`)];
|
|
15735
15829
|
for (const n2 of ordered) {
|
|
15736
15830
|
try {
|
|
15737
|
-
const a = parseAgent(
|
|
15831
|
+
const a = parseAgent(join62(d, n2), n2.slice(0, -3));
|
|
15738
15832
|
if (a && a.role === role)
|
|
15739
15833
|
return a;
|
|
15740
15834
|
} catch {}
|
|
@@ -15752,7 +15846,7 @@ var init_role_agents = __esm(() => {
|
|
|
15752
15846
|
|
|
15753
15847
|
// ../../loki-ts/src/util/child_ledger.ts
|
|
15754
15848
|
import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync27 } from "fs";
|
|
15755
|
-
import { join as
|
|
15849
|
+
import { join as join63 } from "path";
|
|
15756
15850
|
function unmeasuredRecord(phase, model, source) {
|
|
15757
15851
|
return { phase, model, input_tokens: 0, output_tokens: 0, cache_creation_tokens: 0, cache_read_tokens: 0, source, cost_status: "unmeasured" };
|
|
15758
15852
|
}
|
|
@@ -15777,9 +15871,9 @@ function recordFromClaudeResult(phase, payload, source = "claude-json") {
|
|
|
15777
15871
|
}
|
|
15778
15872
|
function appendChildLedger(lokiDir2, rec2) {
|
|
15779
15873
|
try {
|
|
15780
|
-
const dir =
|
|
15874
|
+
const dir = join63(lokiDir2, "metrics");
|
|
15781
15875
|
mkdirSync27(dir, { recursive: true });
|
|
15782
|
-
appendFileSync4(
|
|
15876
|
+
appendFileSync4(join63(dir, "child-sessions.jsonl"), `${JSON.stringify(rec2)}
|
|
15783
15877
|
`);
|
|
15784
15878
|
return true;
|
|
15785
15879
|
} catch {
|
|
@@ -15829,14 +15923,14 @@ var init_colors = __esm(() => {
|
|
|
15829
15923
|
});
|
|
15830
15924
|
|
|
15831
15925
|
// ../../loki-ts/src/util/run_summary.ts
|
|
15832
|
-
import { existsSync as
|
|
15833
|
-
import { join as
|
|
15926
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync28, readFileSync as readFileSync50, renameSync as renameSync12, statSync as statSync20, writeFileSync as writeFileSync30 } from "fs";
|
|
15927
|
+
import { join as join64 } from "path";
|
|
15834
15928
|
function readRiskRecord(repoDir, sinceMs = 0) {
|
|
15835
15929
|
try {
|
|
15836
|
-
const p =
|
|
15930
|
+
const p = join64(repoDir, ".loki", "state", "risk-tier.json");
|
|
15837
15931
|
if (statSync20(p).mtimeMs < sinceMs)
|
|
15838
15932
|
return null;
|
|
15839
|
-
const r = JSON.parse(
|
|
15933
|
+
const r = JSON.parse(readFileSync50(p, "utf8"));
|
|
15840
15934
|
return r && typeof r === "object" ? r : null;
|
|
15841
15935
|
} catch {
|
|
15842
15936
|
return null;
|
|
@@ -15851,8 +15945,8 @@ var init_run_summary = __esm(() => {
|
|
|
15851
15945
|
});
|
|
15852
15946
|
|
|
15853
15947
|
// ../../loki-ts/src/engine10/stages/xreview.ts
|
|
15854
|
-
import { existsSync as
|
|
15855
|
-
import { join as
|
|
15948
|
+
import { existsSync as existsSync43, readFileSync as readFileSync51 } from "fs";
|
|
15949
|
+
import { join as join65 } from "path";
|
|
15856
15950
|
function minVerdict(verdict, review) {
|
|
15857
15951
|
const ceiling = review?.level === "block" ? "PARTIAL" : verdict;
|
|
15858
15952
|
return RANK3[ceiling] < RANK3[verdict] ? ceiling : verdict;
|
|
@@ -15865,11 +15959,11 @@ function explicitReview(repoDir, env) {
|
|
|
15865
15959
|
if (flag && isOff(ev))
|
|
15866
15960
|
return "off";
|
|
15867
15961
|
for (const f of ["loki.yaml", "loki.yml"]) {
|
|
15868
|
-
const p =
|
|
15869
|
-
if (!
|
|
15962
|
+
const p = join65(repoDir, f);
|
|
15963
|
+
if (!existsSync43(p))
|
|
15870
15964
|
continue;
|
|
15871
15965
|
try {
|
|
15872
|
-
const m = /^review:[ \t]*["']?([A-Za-z]+)["']?[ \t]*(?:#.*)?$/m.exec(
|
|
15966
|
+
const m = /^review:[ \t]*["']?([A-Za-z]+)["']?[ \t]*(?:#.*)?$/m.exec(readFileSync51(p, "utf8"));
|
|
15873
15967
|
const v = asProvider(m?.[1]);
|
|
15874
15968
|
if (v)
|
|
15875
15969
|
return v;
|
|
@@ -15952,7 +16046,7 @@ Review ONLY the diff below. Do not modify files.` : "You are an independent code
|
|
|
15952
16046
|
try {
|
|
15953
16047
|
if (p === "claude")
|
|
15954
16048
|
await ensureClaudeHelpCache();
|
|
15955
|
-
const r = await withChildLedger(run,
|
|
16049
|
+
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
16050
|
if (r.exitCode !== 0)
|
|
15957
16051
|
return { provider: p, level: "not_run", notes: [`cross-review not run: ${p} exited ${r.exitCode}`] };
|
|
15958
16052
|
return parseReview(p, r.stdout);
|
|
@@ -16048,8 +16142,8 @@ See also: loki cost --detail (what a run ALREADY spent)
|
|
|
16048
16142
|
});
|
|
16049
16143
|
|
|
16050
16144
|
// ../../loki-ts/src/features/contract.ts
|
|
16051
|
-
import { existsSync as
|
|
16052
|
-
import { dirname as dirname28, join as
|
|
16145
|
+
import { existsSync as existsSync44, lstatSync as lstatSync16, mkdirSync as mkdirSync29, readFileSync as readFileSync52, rmSync as rmSync20, writeFileSync as writeFileSync31 } from "fs";
|
|
16146
|
+
import { dirname as dirname28, join as join66 } from "path";
|
|
16053
16147
|
import { createHash as createHash16 } from "crypto";
|
|
16054
16148
|
function contractEnabled(env = process.env) {
|
|
16055
16149
|
return env["LOKI_CONTRACT"] !== "0";
|
|
@@ -16081,7 +16175,7 @@ function untracedLines(trace) {
|
|
|
16081
16175
|
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
16176
|
}
|
|
16083
16177
|
function contractPath(repoDir) {
|
|
16084
|
-
return
|
|
16178
|
+
return join66(repoDir, ".loki", "contract.json");
|
|
16085
16179
|
}
|
|
16086
16180
|
function readContract(repoDir) {
|
|
16087
16181
|
const p = contractPath(repoDir);
|
|
@@ -16097,7 +16191,7 @@ function readContract(repoDir) {
|
|
|
16097
16191
|
return { contract: null, notes: ["contract unreadable: too large"], sha256: null };
|
|
16098
16192
|
let raw2;
|
|
16099
16193
|
try {
|
|
16100
|
-
raw2 =
|
|
16194
|
+
raw2 = readFileSync52(p);
|
|
16101
16195
|
} catch {
|
|
16102
16196
|
return { contract: null, notes: ["contract unreadable: read failed"], sha256: null };
|
|
16103
16197
|
}
|
|
@@ -16166,17 +16260,17 @@ var init_contract = __esm(() => {
|
|
|
16166
16260
|
init_safe_git();
|
|
16167
16261
|
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
16262
|
MAX_CONTRACT_BYTES = 1024 * 1024;
|
|
16169
|
-
REQ_MAP_REL =
|
|
16263
|
+
REQ_MAP_REL = join66(".loki", "state", "requirements-map.json");
|
|
16170
16264
|
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
16265
|
});
|
|
16172
16266
|
|
|
16173
16267
|
// ../../loki-ts/src/features/speed/seal_group.ts
|
|
16174
16268
|
import { createHash as createHash17 } from "crypto";
|
|
16175
|
-
import { existsSync as
|
|
16176
|
-
import { dirname as dirname29, join as
|
|
16269
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync30, readdirSync as readdirSync23, readFileSync as readFileSync53, renameSync as renameSync13, statSync as statSync21, writeFileSync as writeFileSync32 } from "fs";
|
|
16270
|
+
import { dirname as dirname29, join as join67 } from "path";
|
|
16177
16271
|
function sealGroup(runDir, rh) {
|
|
16178
|
-
const manifestPath =
|
|
16179
|
-
if (!
|
|
16272
|
+
const manifestPath = join67(runDir, "group", "manifest.json");
|
|
16273
|
+
if (!existsSync45(manifestPath))
|
|
16180
16274
|
return { section: undefined, notProven: [], problems: 0, allUnitsPass: true };
|
|
16181
16275
|
const notProven = [];
|
|
16182
16276
|
let problems = 0;
|
|
@@ -16200,10 +16294,10 @@ function sealGroup(runDir, rh) {
|
|
|
16200
16294
|
return fail2(`unit ${index2} has an invalid, duplicate or case-colliding id`);
|
|
16201
16295
|
seen.add(id);
|
|
16202
16296
|
seenLower.add(id.toLowerCase());
|
|
16203
|
-
const dir =
|
|
16297
|
+
const dir = join67(unitsDir(runDir), id), rp = join67(dir, "receipt.json"), ep = join67(dir, "events.jsonl");
|
|
16204
16298
|
let bytes;
|
|
16205
16299
|
try {
|
|
16206
|
-
bytes =
|
|
16300
|
+
bytes = readFileSync53(rp);
|
|
16207
16301
|
} catch {
|
|
16208
16302
|
return fail2(`unit ${id} sub-receipt missing`);
|
|
16209
16303
|
}
|
|
@@ -16220,7 +16314,7 @@ function sealGroup(runDir, rh) {
|
|
|
16220
16314
|
unit_id: id,
|
|
16221
16315
|
sub_receipt_sha256: sha3(bytes),
|
|
16222
16316
|
receipt_sha256: sub2["receipt_sha256"],
|
|
16223
|
-
events_file_sha256:
|
|
16317
|
+
events_file_sha256: existsSync45(ep) ? sha3(readFileSync53(ep)) : null,
|
|
16224
16318
|
verdict,
|
|
16225
16319
|
goal: text2(u["goal"], 200),
|
|
16226
16320
|
files: (Array.isArray(u["files"]) ? u["files"] : []).map((f) => text2(f, 200)).filter(Boolean).slice(0, 50),
|
|
@@ -16245,7 +16339,7 @@ async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
|
|
|
16245
16339
|
const bad = (reason) => ({ verdict: "TAMPERED", reason: `group: ${reason}` });
|
|
16246
16340
|
const g = receipt["group"];
|
|
16247
16341
|
if (g === undefined)
|
|
16248
|
-
return
|
|
16342
|
+
return existsSync45(join67(runDir, "group", "manifest.json")) ? bad("group directory present but the receipt has no group section") : null;
|
|
16249
16343
|
if (!isObj10(g) || !ID_RE.test(String(g["group_id"] ?? "")) || !Array.isArray(g["units"]) || g["units"].length === 0)
|
|
16250
16344
|
return bad("group section malformed");
|
|
16251
16345
|
const entries = g["units"];
|
|
@@ -16257,20 +16351,20 @@ async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
|
|
|
16257
16351
|
return bad("unit directories do not match the receipt (missing or extra unit)");
|
|
16258
16352
|
let unchecked = null;
|
|
16259
16353
|
for (let i = 0;i < entries.length; i++) {
|
|
16260
|
-
const e = entries[i], id = ids[i], dir =
|
|
16354
|
+
const e = entries[i], id = ids[i], dir = join67(unitsDir(runDir), id), rp = join67(dir, "receipt.json"), ep = join67(dir, "events.jsonl");
|
|
16261
16355
|
if (e["index"] !== i)
|
|
16262
16356
|
return bad(`unit ${id} is out of order (index ${String(e["index"])} at position ${i})`);
|
|
16263
16357
|
let bytes;
|
|
16264
16358
|
try {
|
|
16265
16359
|
if (!statSync21(dir).isDirectory())
|
|
16266
16360
|
return bad(`unit ${id} is not a directory`);
|
|
16267
|
-
bytes =
|
|
16361
|
+
bytes = readFileSync53(rp);
|
|
16268
16362
|
} catch {
|
|
16269
16363
|
return bad(`unit ${id} sub-receipt missing`);
|
|
16270
16364
|
}
|
|
16271
16365
|
if (sha3(bytes) !== e["sub_receipt_sha256"])
|
|
16272
16366
|
return bad(`unit ${id} sub-receipt does not match its recorded hash`);
|
|
16273
|
-
const evSha =
|
|
16367
|
+
const evSha = existsSync45(ep) ? sha3(readFileSync53(ep)) : null;
|
|
16274
16368
|
if (evSha !== (e["events_file_sha256"] ?? null))
|
|
16275
16369
|
return bad(`unit ${id} events.jsonl does not match its recorded hash`);
|
|
16276
16370
|
const sub2 = readJson6(rp);
|
|
@@ -16293,15 +16387,15 @@ function compositeVerdict(childVerdicts) {
|
|
|
16293
16387
|
const failed2 = childVerdicts.filter((v) => v === "FAILED" || !["VERIFIED", "ALREADY_SATISFIED", "PARTIAL", "SPEC_CONFLICT"].includes(v)).length;
|
|
16294
16388
|
return capGroupVerdict(base, { section: undefined, notProven: [], problems: failed2, allUnitsPass: childVerdicts.every((v) => PASSING.has(v)) });
|
|
16295
16389
|
}
|
|
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) =>
|
|
16390
|
+
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
16391
|
try {
|
|
16298
|
-
return JSON.parse(
|
|
16392
|
+
return JSON.parse(readFileSync53(p, "utf8"));
|
|
16299
16393
|
} catch {
|
|
16300
16394
|
return;
|
|
16301
16395
|
}
|
|
16302
16396
|
}, dirNames = (d) => {
|
|
16303
16397
|
try {
|
|
16304
|
-
return
|
|
16398
|
+
return readdirSync23(d).filter((n3) => !n3.startsWith(".")).sort();
|
|
16305
16399
|
} catch {
|
|
16306
16400
|
return null;
|
|
16307
16401
|
}
|
|
@@ -16313,8 +16407,8 @@ var init_seal_group = __esm(() => {
|
|
|
16313
16407
|
});
|
|
16314
16408
|
|
|
16315
16409
|
// ../../loki-ts/src/supply/supply_guard.ts
|
|
16316
|
-
import { existsSync as
|
|
16317
|
-
import { basename as
|
|
16410
|
+
import { existsSync as existsSync46, readFileSync as readFileSync54, statSync as statSync22 } from "fs";
|
|
16411
|
+
import { basename as basename24, join as join68 } from "path";
|
|
16318
16412
|
function supplyEnabled(env) {
|
|
16319
16413
|
return env["LOKI_SUPPLY_GUARD"] !== "0";
|
|
16320
16414
|
}
|
|
@@ -16326,16 +16420,16 @@ function supplyVerdict(verdict, r) {
|
|
|
16326
16420
|
return r.blocked && verdict === "VERIFIED" ? "FAILED" : verdict;
|
|
16327
16421
|
}
|
|
16328
16422
|
function isManifestPath(path) {
|
|
16329
|
-
return MANIFESTS.test(
|
|
16423
|
+
return MANIFESTS.test(basename24(path));
|
|
16330
16424
|
}
|
|
16331
16425
|
function readDeclared(repoDir) {
|
|
16332
|
-
const p =
|
|
16333
|
-
if (!
|
|
16426
|
+
const p = join68(repoDir, ".loki", DECLARED_FILE);
|
|
16427
|
+
if (!existsSync46(p))
|
|
16334
16428
|
return { deps: [], problem: null };
|
|
16335
16429
|
try {
|
|
16336
16430
|
if (statSync22(p).size > MAX_FILE_BYTES)
|
|
16337
16431
|
return { deps: [], problem: "declaration file too large" };
|
|
16338
|
-
const j = JSON.parse(
|
|
16432
|
+
const j = JSON.parse(readFileSync54(p, "utf8"));
|
|
16339
16433
|
if (!Array.isArray(j))
|
|
16340
16434
|
return { deps: [], problem: "declaration is not a JSON array" };
|
|
16341
16435
|
const deps = [];
|
|
@@ -16355,11 +16449,11 @@ function readDeclared(repoDir) {
|
|
|
16355
16449
|
}
|
|
16356
16450
|
}
|
|
16357
16451
|
function readAllowlist(repoDir) {
|
|
16358
|
-
const p =
|
|
16359
|
-
if (!
|
|
16452
|
+
const p = join68(repoDir, ".loki", "supply-allowlist");
|
|
16453
|
+
if (!existsSync46(p))
|
|
16360
16454
|
return new Set;
|
|
16361
16455
|
try {
|
|
16362
|
-
return new Set(
|
|
16456
|
+
return new Set(readFileSync54(p, "utf8").split(`
|
|
16363
16457
|
`).map((l) => l.replace(/#.*$/, "").trim()).filter(Boolean));
|
|
16364
16458
|
} catch {
|
|
16365
16459
|
return new Set;
|
|
@@ -16400,7 +16494,7 @@ function userConfigPrivate(eco, repoDir, env, goEnv = {}, name = "") {
|
|
|
16400
16494
|
if (eco === "npm") {
|
|
16401
16495
|
if (privateUrlList([env["npm_config_registry"] ?? "", env["NPM_CONFIG_REGISTRY"] ?? ""]))
|
|
16402
16496
|
return true;
|
|
16403
|
-
return files(
|
|
16497
|
+
return files(join68(repoDir, ".npmrc"), home ? join68(home, ".npmrc") : "").some((t) => t.split(`
|
|
16404
16498
|
`).some((l) => {
|
|
16405
16499
|
const m = /^\s*(?:(@[^:\s]+):)?registry\s*=\s*(\S+)/.exec(l);
|
|
16406
16500
|
return !!m && privateUrl(m[2]) && (m[1] === undefined || name.startsWith(`${m[1]}/`));
|
|
@@ -16409,7 +16503,7 @@ function userConfigPrivate(eco, repoDir, env, goEnv = {}, name = "") {
|
|
|
16409
16503
|
if (eco === "pypi") {
|
|
16410
16504
|
if (privateUrlList([env["PIP_INDEX_URL"] ?? "", env["PIP_EXTRA_INDEX_URL"] ?? ""]))
|
|
16411
16505
|
return true;
|
|
16412
|
-
const cfg = [env["PIP_CONFIG_FILE"] ?? "", home ?
|
|
16506
|
+
const cfg = [env["PIP_CONFIG_FILE"] ?? "", home ? join68(home, ".config", "pip", "pip.conf") : "", home ? join68(home, ".pip", "pip.conf") : "", join68(repoDir, "pip.conf")];
|
|
16413
16507
|
return files(...cfg).some((t) => t.split(`
|
|
16414
16508
|
`).some((l) => {
|
|
16415
16509
|
const m = /^\s*(?:extra-)?index-url\s*[=:]\s*(.+)$/.exec(l);
|
|
@@ -16419,7 +16513,7 @@ function userConfigPrivate(eco, repoDir, env, goEnv = {}, name = "") {
|
|
|
16419
16513
|
if (eco === "cargo") {
|
|
16420
16514
|
if (Object.keys(env).some((k) => /^CARGO_REGISTRIES_.+_INDEX$/.test(k) || /^CARGO_SOURCE_/.test(k)))
|
|
16421
16515
|
return true;
|
|
16422
|
-
return files(
|
|
16516
|
+
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
16517
|
}
|
|
16424
16518
|
if (eco === "go") {
|
|
16425
16519
|
const gp = goEnv["GOPROXY"] ?? env["GOPROXY"] ?? "";
|
|
@@ -16542,7 +16636,7 @@ var MIN_AGE_DAYS = 7, DECLARED_FILE = "supply-declared.json", MAX_CHECKED = 50,
|
|
|
16542
16636
|
}
|
|
16543
16637
|
}, 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
16638
|
try {
|
|
16545
|
-
return statSync22(p).size <= MAX_FILE_BYTES ?
|
|
16639
|
+
return statSync22(p).size <= MAX_FILE_BYTES ? readFileSync54(p, "utf8") : "";
|
|
16546
16640
|
} catch {
|
|
16547
16641
|
return "";
|
|
16548
16642
|
}
|
|
@@ -16558,8 +16652,8 @@ var init_supply_guard = __esm(() => {
|
|
|
16558
16652
|
|
|
16559
16653
|
// ../../loki-ts/src/engine10/stages/seal.ts
|
|
16560
16654
|
import { createHash as createHash18 } from "crypto";
|
|
16561
|
-
import { existsSync as
|
|
16562
|
-
import { basename as
|
|
16655
|
+
import { existsSync as existsSync47, readdirSync as readdirSync24, mkdirSync as mkdirSync31, readFileSync as readFileSync55 } from "fs";
|
|
16656
|
+
import { basename as basename25, isAbsolute as isAbsolute11, join as join69, relative as relative12 } from "path";
|
|
16563
16657
|
function receiptSha256(r) {
|
|
16564
16658
|
const { verification: _v, receipt_sha256: _h, ...body } = r;
|
|
16565
16659
|
return sha2562(canonicalJson(body));
|
|
@@ -16630,7 +16724,7 @@ function renderReceiptMd(r) {
|
|
|
16630
16724
|
`);
|
|
16631
16725
|
}
|
|
16632
16726
|
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 =
|
|
16727
|
+
const r = relative12(ctx.repoDir, join69(ctx.runDir, "receipt.json"));
|
|
16634
16728
|
return r.startsWith("..") || isAbsolute11(r) ? `.loki/runs/${ctx.runId}/receipt.json` : r;
|
|
16635
16729
|
}, commitStage, wallGreenOnBaseOf = (o) => {
|
|
16636
16730
|
const b = o.wall?.base_run ?? {};
|
|
@@ -16750,8 +16844,8 @@ var init_seal = __esm(() => {
|
|
|
16750
16844
|
notProven.add(`Wall test not executed: ${wallNotRun} file(s), no reason recorded`);
|
|
16751
16845
|
if (wallNotRun > 0) {
|
|
16752
16846
|
try {
|
|
16753
|
-
const kept = new Set((Array.isArray(o.wall?.files) ? o.wall.files : []).map((f) =>
|
|
16754
|
-
for (const n3 of
|
|
16847
|
+
const kept = new Set((Array.isArray(o.wall?.files) ? o.wall.files : []).map((f) => basename25(String(f.path))));
|
|
16848
|
+
for (const n3 of readdirSync24(join69(ctx.runDir, "wall")).sort())
|
|
16755
16849
|
if (!kept.has(n3))
|
|
16756
16850
|
notProven.add(`wall test discarded: ${n3} (not_run)`);
|
|
16757
16851
|
} catch {}
|
|
@@ -16779,8 +16873,10 @@ var init_seal = __esm(() => {
|
|
|
16779
16873
|
for (const f of uncoveredAfterLimit)
|
|
16780
16874
|
notProven.add(`changed, untested after limit: ${f}`);
|
|
16781
16875
|
for (const c of checks)
|
|
16782
|
-
if (c.result === "not_run")
|
|
16876
|
+
if (c.result === "not_run" && !strs2(o.verify?.skipped_on_base).includes(c.name))
|
|
16783
16877
|
notProven.add(`not run: ${c.name}`);
|
|
16878
|
+
for (const n3 of strs2(o.verify?.skipped_on_base))
|
|
16879
|
+
notProven.add(`skipped on base (excused): ${n3}`);
|
|
16784
16880
|
for (const f of strs2(o.verify?.flaky))
|
|
16785
16881
|
notProven.add(`flaky test: ${f}`);
|
|
16786
16882
|
for (const n3 of verifyNotProven)
|
|
@@ -16814,19 +16910,19 @@ var init_seal = __esm(() => {
|
|
|
16814
16910
|
for (const [s, d] of Object.entries(o))
|
|
16815
16911
|
if (typeof d?.duration_s === "number")
|
|
16816
16912
|
stages[s] = d.duration_s;
|
|
16817
|
-
const T = hooks.time, time = T ? T.build(ctx, stages, T.firstEventMs(
|
|
16913
|
+
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
16914
|
const iterIds = [...new Set([...Object.values(o).flatMap((d) => [...strs2(d?.iteration_ids), ...strs2([d?.iteration_id])]), ...ctx.sessionIds?.() ?? []])];
|
|
16819
16915
|
if (iterIds.length === 0)
|
|
16820
16916
|
notProven.add("cost not measured (no iteration ids recorded)");
|
|
16821
16917
|
const cost = ctx.cost.read(ctx.repoDir, iterIds);
|
|
16822
16918
|
if (cost.unmetered)
|
|
16823
16919
|
notProven.add("cost unmetered (CLI invoker; recorded as 0)");
|
|
16824
|
-
const eventsPath =
|
|
16920
|
+
const eventsPath = join69(ctx.runDir, "events.jsonl");
|
|
16825
16921
|
const wallFiles = Array.isArray(o.wall?.files) ? o.wall.files : [];
|
|
16826
16922
|
const wallPassed = typeof o.verify?.wall_passed === "boolean" ? o.verify.wall_passed : null;
|
|
16827
16923
|
if (wallFiles.length > 0 && wallPassed === null)
|
|
16828
16924
|
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(
|
|
16925
|
+
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
16926
|
if (routeBlock)
|
|
16831
16927
|
for (const l of routeNotProven(routeBlock))
|
|
16832
16928
|
notProven.add(l);
|
|
@@ -16868,7 +16964,7 @@ var init_seal = __esm(() => {
|
|
|
16868
16964
|
provider: ctx.provider,
|
|
16869
16965
|
model: ctx.model,
|
|
16870
16966
|
resumed: o.intake?.resumed === true,
|
|
16871
|
-
events_sha256: sha2562(
|
|
16967
|
+
events_sha256: sha2562(existsSync47(eventsPath) ? readFileSync55(eventsPath) : ""),
|
|
16872
16968
|
...await sealEvidence(ctx.repoDir, ctx.runDir, o, notProven, signal, ctx.emit),
|
|
16873
16969
|
log_seal: true,
|
|
16874
16970
|
toolchain: collectToolchain(),
|
|
@@ -16892,10 +16988,10 @@ var init_seal = __esm(() => {
|
|
|
16892
16988
|
}
|
|
16893
16989
|
const receipt = { ...body, receipt_sha256: hash, verification: { jwt: sig.jwt, kid: sig.kid } };
|
|
16894
16990
|
mkdirSync31(ctx.runDir, { recursive: true });
|
|
16895
|
-
const path =
|
|
16991
|
+
const path = join69(ctx.runDir, "receipt.json");
|
|
16896
16992
|
atomicWriteText(path, JSON.stringify(receipt, null, 2) + `
|
|
16897
16993
|
`);
|
|
16898
|
-
atomicWriteText(
|
|
16994
|
+
atomicWriteText(join69(ctx.runDir, "receipt.md"), renderReceiptMd(receipt));
|
|
16899
16995
|
recordRun(process.env, ctx.repoDir, ranModel(o.implement, ctx.model, o.fix), verdict, cost.usd, cost.unmetered === true, totalS);
|
|
16900
16996
|
try {
|
|
16901
16997
|
hooks.sealed?.(ctx.runDir, JSON.parse(JSON.stringify(receipt), (_k, v) => v && typeof v === "object" ? Object.freeze(v) : v));
|
|
@@ -16920,14 +17016,14 @@ var init_seal = __esm(() => {
|
|
|
16920
17016
|
});
|
|
16921
17017
|
|
|
16922
17018
|
// ../../loki-ts/src/util/composite_seal.ts
|
|
16923
|
-
import { existsSync as
|
|
16924
|
-
import { basename as
|
|
17019
|
+
import { existsSync as existsSync48, readFileSync as readFileSync56 } from "fs";
|
|
17020
|
+
import { basename as basename26, dirname as dirname31, join as join70 } from "path";
|
|
16925
17021
|
function logProblem(runDir, integ) {
|
|
16926
17022
|
if (typeof integ["log_sha256"] !== "string")
|
|
16927
17023
|
return null;
|
|
16928
17024
|
let b;
|
|
16929
17025
|
try {
|
|
16930
|
-
b =
|
|
17026
|
+
b = readFileSync56(join70(runDir, "integration.log"));
|
|
16931
17027
|
} catch {
|
|
16932
17028
|
return "integration.log is missing but integration.json records its hash";
|
|
16933
17029
|
}
|
|
@@ -16950,13 +17046,13 @@ async function verifyComposite(receiptPath, receipt, rh, verifyOne, deps = {}) {
|
|
|
16950
17046
|
return bad("body malformed");
|
|
16951
17047
|
let ibytes;
|
|
16952
17048
|
try {
|
|
16953
|
-
ibytes =
|
|
17049
|
+
ibytes = readFileSync56(join70(runDir, "integration.json"));
|
|
16954
17050
|
} catch {
|
|
16955
17051
|
return bad("integration.json missing");
|
|
16956
17052
|
}
|
|
16957
17053
|
if (sha3(ibytes) !== receipt["integration_sha256"])
|
|
16958
17054
|
return bad("integration.json does not match its recorded hash");
|
|
16959
|
-
const integ = readJson6(
|
|
17055
|
+
const integ = readJson6(join70(runDir, "integration.json"));
|
|
16960
17056
|
if (!isObj10(integ) || !isObj10(integ["outcomes"]))
|
|
16961
17057
|
return bad("integration.json has no outcomes");
|
|
16962
17058
|
const iprob = integrationProblem(integ);
|
|
@@ -16991,10 +17087,10 @@ async function verifyComposite(receiptPath, receipt, rh, verifyOne, deps = {}) {
|
|
|
16991
17087
|
return bad(`child ${text2(repo, 80) || "?"} has an invalid receipt path`);
|
|
16992
17088
|
if (outcomes[repo] !== "ok")
|
|
16993
17089
|
return bad(`child ${text2(repo, 80)} did not finish ok in integration.json`);
|
|
16994
|
-
const rp =
|
|
17090
|
+
const rp = join70(runDir, rel);
|
|
16995
17091
|
let bytes;
|
|
16996
17092
|
try {
|
|
16997
|
-
bytes =
|
|
17093
|
+
bytes = readFileSync56(rp);
|
|
16998
17094
|
} catch {
|
|
16999
17095
|
return bad(`child ${repo} receipt missing`);
|
|
17000
17096
|
}
|
|
@@ -17043,8 +17139,8 @@ var init_keys_cmd = __esm(() => {
|
|
|
17043
17139
|
});
|
|
17044
17140
|
|
|
17045
17141
|
// ../../loki-ts/src/engine10/verify_cmd.ts
|
|
17046
|
-
import { existsSync as
|
|
17047
|
-
import { basename as
|
|
17142
|
+
import { existsSync as existsSync49, readFileSync as readFileSync57, renameSync as renameSync14, statSync as statSync24, writeFileSync as writeFileSync33 } from "fs";
|
|
17143
|
+
import { basename as basename27, dirname as dirname32, join as join71 } from "path";
|
|
17048
17144
|
import { createHash as createHash19, createPublicKey as createPublicKey4, verify as verify4 } from "crypto";
|
|
17049
17145
|
function pubFor(kid, given) {
|
|
17050
17146
|
if (given)
|
|
@@ -17052,7 +17148,7 @@ function pubFor(kid, given) {
|
|
|
17052
17148
|
const active = loadSigningKey(false);
|
|
17053
17149
|
const pubs = (process.env["LOKI_RECEIPT_RETIRED_PUBKEYS"] ?? "").split(":").map((f) => f.trim()).filter(Boolean).flatMap((f) => {
|
|
17054
17150
|
try {
|
|
17055
|
-
return [createPublicKey4(
|
|
17151
|
+
return [createPublicKey4(readFileSync57(f))];
|
|
17056
17152
|
} catch {
|
|
17057
17153
|
return [];
|
|
17058
17154
|
}
|
|
@@ -17096,10 +17192,10 @@ function checkEventLog(receiptPath, receipt) {
|
|
|
17096
17192
|
const claims = st !== null && typeof st === "object" && Object.keys(st).length > 0;
|
|
17097
17193
|
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
17194
|
}
|
|
17099
|
-
const path =
|
|
17100
|
-
if (!
|
|
17195
|
+
const path = join71(dirname32(receiptPath), "events.jsonl");
|
|
17196
|
+
if (!existsSync49(path))
|
|
17101
17197
|
return "events.jsonl is missing";
|
|
17102
|
-
const raw2 =
|
|
17198
|
+
const raw2 = readFileSync57(path, "utf8"), events2 = readEvents(path), lines2 = raw2.split(`
|
|
17103
17199
|
`).filter((l) => l.trim() !== "");
|
|
17104
17200
|
if (events2.length !== lines2.length || events2.some((e, i) => e.seq !== i))
|
|
17105
17201
|
return "events.jsonl has a forged, edited or missing line";
|
|
@@ -17115,7 +17211,7 @@ function checkEventLog(receiptPath, receipt) {
|
|
|
17115
17211
|
return h.digest("hex") === bound ? null : "events.jsonl does not match the hash recorded at seal";
|
|
17116
17212
|
}
|
|
17117
17213
|
function checkLogSeal(receiptPath, hash, kid, given) {
|
|
17118
|
-
const path =
|
|
17214
|
+
const path = join71(dirname32(receiptPath), "events.jsonl"), events2 = readEvents(path), done = events2.findIndex((e) => e.type === "run.completed");
|
|
17119
17215
|
if (!events2.some((e) => e.type === "receipt.sealed" && e.data["receipt_sha256"] === hash))
|
|
17120
17216
|
return { verdict: "TAMPERED", reason: "events.jsonl has no receipt.sealed event for this receipt" };
|
|
17121
17217
|
if (done < 0)
|
|
@@ -17123,7 +17219,7 @@ function checkLogSeal(receiptPath, hash, kid, given) {
|
|
|
17123
17219
|
const seal = events2[done + 1], d = seal?.type === "log.sealed" ? seal.data : null;
|
|
17124
17220
|
if (!d)
|
|
17125
17221
|
return { verdict: "TAMPERED", reason: "events.jsonl has no signed log.sealed line after run.completed" };
|
|
17126
|
-
const lines2 =
|
|
17222
|
+
const lines2 = readFileSync57(path, "utf8").split(`
|
|
17127
17223
|
`).filter((l) => l.trim() !== ""), sha4 = createHash19("sha256").update(lines2.slice(0, done + 1).join(`
|
|
17128
17224
|
`) + `
|
|
17129
17225
|
`).digest("hex");
|
|
@@ -17133,11 +17229,11 @@ function checkLogSeal(receiptPath, hash, kid, given) {
|
|
|
17133
17229
|
return null;
|
|
17134
17230
|
}
|
|
17135
17231
|
async function verifyReceipt(receiptPath, deps = {}) {
|
|
17136
|
-
if (!
|
|
17232
|
+
if (!existsSync49(receiptPath))
|
|
17137
17233
|
return { verdict: "UNCHECKED", reasons: [`receipt not found: ${receiptPath}`] };
|
|
17138
17234
|
let receipt;
|
|
17139
17235
|
try {
|
|
17140
|
-
receipt = JSON.parse((deps.read ?? ((p) =>
|
|
17236
|
+
receipt = JSON.parse((deps.read ?? ((p) => readFileSync57(p, "utf8")))(receiptPath));
|
|
17141
17237
|
} catch {
|
|
17142
17238
|
return { verdict: "UNCHECKED", reasons: ["receipt.json is not valid JSON"] };
|
|
17143
17239
|
}
|
|
@@ -17226,8 +17322,8 @@ var init_verify_cmd = __esm(() => {
|
|
|
17226
17322
|
});
|
|
17227
17323
|
|
|
17228
17324
|
// src/server/app.ts
|
|
17229
|
-
import { existsSync as
|
|
17230
|
-
import { join as
|
|
17325
|
+
import { existsSync as existsSync51, readFileSync as readFileSync60, statSync as statSync25 } from "fs";
|
|
17326
|
+
import { join as join74, resolve as resolve17, sep as sep16 } from "path";
|
|
17231
17327
|
|
|
17232
17328
|
// node_modules/hono/dist/request/constants.js
|
|
17233
17329
|
var GET_MATCH_RESULT = Symbol();
|
|
@@ -27499,9 +27595,9 @@ function mount20(ctx) {
|
|
|
27499
27595
|
}
|
|
27500
27596
|
|
|
27501
27597
|
// src/server/routes/verify.ts
|
|
27502
|
-
import { readFileSync as
|
|
27598
|
+
import { readFileSync as readFileSync58, realpathSync as realpathSync24 } from "fs";
|
|
27503
27599
|
import { createPublicKey as createPublicKey5 } from "crypto";
|
|
27504
|
-
import { join as
|
|
27600
|
+
import { join as join72, sep as sep15 } from "path";
|
|
27505
27601
|
init_verify_cmd();
|
|
27506
27602
|
init_seal();
|
|
27507
27603
|
init_receipt_dsse();
|
|
@@ -27528,15 +27624,15 @@ function mount21(ctx) {
|
|
|
27528
27624
|
return done(404, "receipt not available", "not_found");
|
|
27529
27625
|
let runDir, file;
|
|
27530
27626
|
try {
|
|
27531
|
-
const root =
|
|
27532
|
-
runDir =
|
|
27533
|
-
if (runDir !==
|
|
27627
|
+
const root = realpathSync24(join72(repo.p, ".loki", "runs"));
|
|
27628
|
+
runDir = realpathSync24(join72(root, run2));
|
|
27629
|
+
if (runDir !== join72(root, run2))
|
|
27534
27630
|
return done(404, "receipt not found", "not_found");
|
|
27535
|
-
file =
|
|
27631
|
+
file = realpathSync24(join72(runDir, "receipt.json"));
|
|
27536
27632
|
} catch {
|
|
27537
27633
|
return done(404, "receipt not found", "not_found");
|
|
27538
27634
|
}
|
|
27539
|
-
if (!file.startsWith(runDir +
|
|
27635
|
+
if (!file.startsWith(runDir + sep15))
|
|
27540
27636
|
return done(404, "receipt not found", "not_found");
|
|
27541
27637
|
let integrity, reasons, sha4 = null, outcome = "UNREADABLE";
|
|
27542
27638
|
try {
|
|
@@ -27551,7 +27647,7 @@ function mount21(ctx) {
|
|
|
27551
27647
|
sha4 = r.receiptSha256 ?? null;
|
|
27552
27648
|
}
|
|
27553
27649
|
try {
|
|
27554
|
-
outcome = outcomeOf(JSON.parse(
|
|
27650
|
+
outcome = outcomeOf(JSON.parse(readFileSync58(file, "utf8")));
|
|
27555
27651
|
} catch {
|
|
27556
27652
|
outcome = "UNREADABLE";
|
|
27557
27653
|
}
|
|
@@ -27613,8 +27709,8 @@ function ttlCache(ttlMs = PROBE_CACHE_MS, now2 = Date.now) {
|
|
|
27613
27709
|
}
|
|
27614
27710
|
|
|
27615
27711
|
// src/server/legacy/shim.ts
|
|
27616
|
-
import { existsSync as
|
|
27617
|
-
import { join as
|
|
27712
|
+
import { existsSync as existsSync50, readFileSync as readFileSync59 } from "fs";
|
|
27713
|
+
import { join as join73 } from "path";
|
|
27618
27714
|
|
|
27619
27715
|
// src/server/legacy/routes.ts
|
|
27620
27716
|
var LEGACY_ROUTES = [
|
|
@@ -27992,10 +28088,10 @@ var logged = new Set;
|
|
|
27992
28088
|
var toHono = (p) => p.replace(/\{([A-Za-z_]+):path\}/g, ":$1{.+}").replace(/\{([A-Za-z_]+)\}/g, ":$1");
|
|
27993
28089
|
var NOT_SUPPORTED = "not yet supported by the Control Plane";
|
|
27994
28090
|
var repoVersion = () => {
|
|
27995
|
-
for (const f of [
|
|
28091
|
+
for (const f of [join73(import.meta.dir, "../../../../../VERSION")]) {
|
|
27996
28092
|
try {
|
|
27997
|
-
if (
|
|
27998
|
-
return
|
|
28093
|
+
if (existsSync50(f))
|
|
28094
|
+
return readFileSync59(f, "utf8").trim();
|
|
27999
28095
|
} catch {}
|
|
28000
28096
|
}
|
|
28001
28097
|
return "unknown";
|
|
@@ -28177,7 +28273,7 @@ function legacyShim(opts) {
|
|
|
28177
28273
|
|
|
28178
28274
|
// src/server/app.ts
|
|
28179
28275
|
var MAX_BODY2 = 1e6;
|
|
28180
|
-
var defaultUiDir = () => [
|
|
28276
|
+
var defaultUiDir = () => [join74(import.meta.dir, "../../ui/dist"), join74(import.meta.dir, "../ui/dist")].find((d) => existsSync51(join74(d, "index.html")));
|
|
28181
28277
|
function createApp(opts) {
|
|
28182
28278
|
const uiDir = opts.uiDir ?? defaultUiDir();
|
|
28183
28279
|
const { db, sqlite } = openDb(opts.dbPath);
|
|
@@ -28206,10 +28302,10 @@ function createApp(opts) {
|
|
|
28206
28302
|
await next();
|
|
28207
28303
|
});
|
|
28208
28304
|
const readInstalled = () => {
|
|
28209
|
-
for (const f of [process.env.LOKI_VERSION_FILE,
|
|
28305
|
+
for (const f of [process.env.LOKI_VERSION_FILE, join74(import.meta.dir, "../../../../VERSION")]) {
|
|
28210
28306
|
try {
|
|
28211
28307
|
if (f)
|
|
28212
|
-
return
|
|
28308
|
+
return readFileSync60(f, "utf8").trim() || "unknown";
|
|
28213
28309
|
} catch {}
|
|
28214
28310
|
}
|
|
28215
28311
|
return "unknown";
|
|
@@ -28318,13 +28414,13 @@ function createApp(opts) {
|
|
|
28318
28414
|
}
|
|
28319
28415
|
if (!uiDir || p.startsWith("/v1/"))
|
|
28320
28416
|
return c.json({ error: "not found" }, 404);
|
|
28321
|
-
const root =
|
|
28322
|
-
const f =
|
|
28323
|
-
if (f.startsWith(root +
|
|
28417
|
+
const root = resolve17(uiDir);
|
|
28418
|
+
const f = resolve17(root, `.${p}`);
|
|
28419
|
+
if (f.startsWith(root + sep16) && existsSync51(f) && statSync25(f).isFile())
|
|
28324
28420
|
return new Response(Bun.file(f));
|
|
28325
28421
|
if (/\.[a-z0-9]+$/i.test(p))
|
|
28326
28422
|
return c.json({ error: "not found" }, 404);
|
|
28327
|
-
return new Response(Bun.file(
|
|
28423
|
+
return new Response(Bun.file(join74(root, "index.html")));
|
|
28328
28424
|
});
|
|
28329
28425
|
return { app, db, close: () => {
|
|
28330
28426
|
clearInterval(reconciler);
|