loki-mode 11.17.82 → 11.17.84
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 +11 -2
- package/docs/v10/PROGRESS.md +6 -0
- package/loki-ts/dist/loki.js +1236 -1235
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/packages/control-plane/dist/server.js +368 -205
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/web-app/dist/assets/{AdminPage-BRdwyMOz.js → AdminPage-K5ByrLR9.js} +1 -1
- package/web-app/dist/assets/{Avatar-BgBez5kw.js → Avatar-YgkUcdSY.js} +1 -1
- package/web-app/dist/assets/{Badge-DI1obeQL.js → Badge-BPSEuhap.js} +1 -1
- package/web-app/dist/assets/{Button-K12ksdPS.js → Button-B9U75GxN.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-CcdJJz6Y.js → CockpitPage-DsfWn1by.js} +1 -1
- package/web-app/dist/assets/{ComparePage-BjQE-BcT.js → ComparePage-Bw5ksH0K.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-CSeWwyja.js → ErrorBoundary-CO95MTCp.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-BG3DhGvM.js → EvidenceReceiptPanel-QOtNfGPr.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-DNzidZZs.js → GitHubIssuesPanel-Czdh0zJD.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-B5NcUHit.js → GitHubPRsPanel-DyxFGyfo.js} +1 -1
- package/web-app/dist/assets/{HomePage-CDojDo58.js → HomePage-DlyIQtiu.js} +2 -2
- package/web-app/dist/assets/{LoginPage-3BFNzUcW.js → LoginPage-BCugtLMp.js} +1 -1
- package/web-app/dist/assets/{MagicPage-NY1Zawdf.js → MagicPage-BNfWXXtj.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-CfxGwjFC.js → MetricsPage-aBjuM4A_.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-i3_qnVi1.js → NotFoundPage-BCOPrXwc.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-CqGmrK1T.js → ProjectPage-CQckLxB6.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-C36P0Irr.js → ProjectsPage-xgEbC4Gz.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-DTzb0uKT.js → SettingsPage-UVrDGxdY.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-CfY4ALt_.js → ShowcasePage-B2Xoipg-.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-CDjjQUIO.js → SystemSettingsPage-CgLRefdv.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-DEvPeYoV.js → TeamsPage-Cw8Hj66k.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-C2pvQh6p.js → TemplatesPage-CaCBUUO5.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-DSt6ijzO.js → TerminalOutput-B7m2HRNn.js} +1 -1
- package/web-app/dist/assets/{activity-cQKc7Qz3.js → activity-CkeOgiXm.js} +1 -1
- package/web-app/dist/assets/{bell-DvuiCdXA.js → bell-DKaU63My.js} +1 -1
- package/web-app/dist/assets/{bot-xQfFCnf-.js → bot-CraPUnae.js} +1 -1
- package/web-app/dist/assets/{check-0by_ASuL.js → check-BjJbXEmH.js} +1 -1
- package/web-app/dist/assets/{chevron-left-FwfCMqen.js → chevron-left-_x9ovbIV.js} +1 -1
- package/web-app/dist/assets/{circle-alert-1tiUDoUg.js → circle-alert-DYrIIc9A.js} +1 -1
- package/web-app/dist/assets/{clock-DVN3Nu7G.js → clock-07ChPrGQ.js} +1 -1
- package/web-app/dist/assets/{cloud-hIv4Jsym.js → cloud-UZrr1T4k.js} +1 -1
- package/web-app/dist/assets/{code-xml-D-71nPRE.js → code-xml-jmlsXp32.js} +1 -1
- package/web-app/dist/assets/{database-Da0-3m0h.js → database-Cw9NK9yy.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-BXSYlXLl.js → dollar-sign-C_gtNZU_.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-BoLea73g.js → file-code-corner-PMk7fRz9.js} +1 -1
- package/web-app/dist/assets/{file-plus-BW3QvU13.js → file-plus-DlZs6Btl.js} +1 -1
- package/web-app/dist/assets/{globe-B7VuWP4E.js → globe-C9cpOvdr.js} +1 -1
- package/web-app/dist/assets/{hammer-KlXonR5y.js → hammer-DEk8bLDy.js} +1 -1
- package/web-app/dist/assets/{index-UfHXAUkp.js → index-Km0ikbi_.js} +3 -3
- package/web-app/dist/assets/{layers-CiiwhXq6.js → layers-4RjPXic5.js} +1 -1
- package/web-app/dist/assets/{loader-circle-Ddov0Hjc.js → loader-circle-DlUucLsL.js} +1 -1
- package/web-app/dist/assets/{lock-Bf_LkHux.js → lock-Cul5JgtK.js} +1 -1
- package/web-app/dist/assets/{package-DaF0Dad-.js → package-Vbp2mPNL.js} +1 -1
- package/web-app/dist/assets/{plus-nPhC7bJ0.js → plus-DSMqkDx2.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-BDtpGNOs.js → refresh-cw-Dzcn5O_r.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-B3YXhasa.js → rotate-ccw-DRuS-hw1.js} +1 -1
- package/web-app/dist/assets/{scroll-text-CCf8dMB0.js → scroll-text-DSzR2Oet.js} +1 -1
- package/web-app/dist/assets/{server-BkKkvfJb.js → server-CaA-i_3H.js} +1 -1
- package/web-app/dist/assets/{shield-alert-Bx-2t6AA.js → shield-alert-4whQzr0p.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-AjAA5tox.js → thumbs-up-CUCPAMhF.js} +1 -1
- package/web-app/dist/assets/{trash-2-YSiRb9MG.js → trash-2-CJiX03EE.js} +1 -1
- package/web-app/dist/assets/{trending-down-dZxc5O7C.js → trending-down-ROoZX4P4.js} +1 -1
- package/web-app/dist/assets/{trending-up-Dl-LwOqo.js → trending-up-Gi3o5rCK.js} +1 -1
- package/web-app/dist/assets/{upload-Csn6khaL.js → upload-C5s98AFw.js} +1 -1
- package/web-app/dist/assets/{usePolling-qReatY5K.js → usePolling-DaEWx5La.js} +1 -1
- package/web-app/dist/assets/{user-5eHbCeDU.js → user-D4yDWC5X.js} +1 -1
- package/web-app/dist/index.html +1 -1
|
@@ -10002,6 +10002,18 @@ async function zeroOnBase(cands, baseDir, repoDir, run, note) {
|
|
|
10002
10002
|
}
|
|
10003
10003
|
return zero;
|
|
10004
10004
|
}
|
|
10005
|
+
function addedSymlinkNotes(rawDiff, planText) {
|
|
10006
|
+
const asks = (w) => [...(planText ?? "").matchAll(new RegExp(`\\b${w}s?\\b`, "gi"))].some((m) => !/\b(?:no|not|never|without|avoid|don'?t|cannot|can'?t)\b[^.\n]{0,40}$/i.test(planText.slice(Math.max(0, m.index - 45), m.index)));
|
|
10007
|
+
const out2 = [];
|
|
10008
|
+
for (let i = 0;i + 1 < rawDiff.length; i += 2) {
|
|
10009
|
+
const f = rawDiff[i].trim().split(" "), oldMode = f[0].replace(/^:/, ""), st = f[f.length - 1], p = rawDiff[i + 1];
|
|
10010
|
+
if (f[1] === "120000" && (st === "A" || st === "T" && oldMode !== "120000") && !asks("symlink"))
|
|
10011
|
+
out2.push(`symlink added by the change (a link can stand in for missing work; the plan did not ask for one): ${p}`);
|
|
10012
|
+
else if (f[1] === "160000" && (st === "A" || st === "T") && !asks("submodule"))
|
|
10013
|
+
out2.push(`submodule pointer added by the change (it can stand in for missing work; the plan did not ask for one): ${p}`);
|
|
10014
|
+
}
|
|
10015
|
+
return out2;
|
|
10016
|
+
}
|
|
10005
10017
|
var WALK_BOUND = 50000, REPO_LINK_FILE;
|
|
10006
10018
|
var init_base_guard = __esm(() => {
|
|
10007
10019
|
init_check_result();
|
|
@@ -13890,6 +13902,258 @@ var init_secure_scan = __esm(() => {
|
|
|
13890
13902
|
// ../../loki-ts/src/runner/retry_class.ts
|
|
13891
13903
|
var init_retry_class = () => {};
|
|
13892
13904
|
|
|
13905
|
+
// ../../loki-ts/src/project_model/conventions.ts
|
|
13906
|
+
import { existsSync as existsSync33, readdirSync as readdirSync19, readFileSync as readFileSync42 } from "fs";
|
|
13907
|
+
import { basename as basename22, dirname as dirname19, isAbsolute as isAbsolute8, join as join53, relative as relative8, resolve as resolve17 } from "path";
|
|
13908
|
+
function parseJsonc(text2) {
|
|
13909
|
+
let out2 = "", i = 0;
|
|
13910
|
+
while (i < text2.length) {
|
|
13911
|
+
const c = text2[i], n2 = text2[i + 1];
|
|
13912
|
+
if (c === '"') {
|
|
13913
|
+
let j = i + 1;
|
|
13914
|
+
while (j < text2.length && text2[j] !== '"')
|
|
13915
|
+
j += text2[j] === "\\" ? 2 : 1;
|
|
13916
|
+
out2 += text2.slice(i, j + 1);
|
|
13917
|
+
i = j + 1;
|
|
13918
|
+
} else if (c === "/" && n2 === "/") {
|
|
13919
|
+
while (i < text2.length && text2[i] !== `
|
|
13920
|
+
`)
|
|
13921
|
+
i++;
|
|
13922
|
+
} else if (c === "/" && n2 === "*") {
|
|
13923
|
+
const e = text2.indexOf("*/", i + 2);
|
|
13924
|
+
i = e < 0 ? text2.length : e + 2;
|
|
13925
|
+
} else {
|
|
13926
|
+
out2 += c;
|
|
13927
|
+
i++;
|
|
13928
|
+
}
|
|
13929
|
+
}
|
|
13930
|
+
return JSON.parse(out2.replace(/,(\s*[}\]])/g, "$1"));
|
|
13931
|
+
}
|
|
13932
|
+
function moduleOf(file, depth = 0) {
|
|
13933
|
+
const j = readJson5(file);
|
|
13934
|
+
if (!j || depth > 4)
|
|
13935
|
+
return null;
|
|
13936
|
+
const m = j.compilerOptions?.module;
|
|
13937
|
+
if (typeof m === "string")
|
|
13938
|
+
return m.toLowerCase();
|
|
13939
|
+
const ext = typeof j.extends === "string" ? j.extends : null;
|
|
13940
|
+
if (!ext || !ext.startsWith("."))
|
|
13941
|
+
return null;
|
|
13942
|
+
const next = join53(dirname19(file), ext.endsWith(".json") ? ext : `${ext}.json`);
|
|
13943
|
+
return existsSync33(next) ? moduleOf(next, depth + 1) : null;
|
|
13944
|
+
}
|
|
13945
|
+
function readPackageConventions(pkgDir, runner = null) {
|
|
13946
|
+
let names = [];
|
|
13947
|
+
try {
|
|
13948
|
+
names = readdirSync19(pkgDir).filter((f) => f.endsWith(".json")).sort((x, y) => x.length - y.length || x.localeCompare(y));
|
|
13949
|
+
} catch {
|
|
13950
|
+
return null;
|
|
13951
|
+
}
|
|
13952
|
+
let packageType = null, tsModule = null;
|
|
13953
|
+
for (const n2 of names) {
|
|
13954
|
+
const j = readJson5(join53(pkgDir, n2));
|
|
13955
|
+
if (!j)
|
|
13956
|
+
continue;
|
|
13957
|
+
if (packageType === null && typeof j.type === "string" && typeof j.name === "string")
|
|
13958
|
+
packageType = j.type;
|
|
13959
|
+
if (tsModule === null && j.compilerOptions !== undefined)
|
|
13960
|
+
tsModule = moduleOf(join53(pkgDir, n2));
|
|
13961
|
+
}
|
|
13962
|
+
if (packageType === null && tsModule === null)
|
|
13963
|
+
return null;
|
|
13964
|
+
const esmType = packageType === "module";
|
|
13965
|
+
const moduleSystem = tsModule === null || tsModule === "node16" || tsModule === "nodenext" ? esmType ? "esm" : "commonjs" : /^(commonjs|amd|umd|system)$/.test(tsModule) ? "commonjs" : "esm";
|
|
13966
|
+
return { moduleSystem, packageType, tsModule, runner };
|
|
13967
|
+
}
|
|
13968
|
+
function conventionsBrief(c) {
|
|
13969
|
+
if (!c)
|
|
13970
|
+
return "";
|
|
13971
|
+
const decl = `manifest type: ${c.packageType ?? "(unset)"}, compiler module: ${c.tsModule ?? "(unset)"}${c.runner ? `, test runner: ${c.runner}` : ""}`;
|
|
13972
|
+
return c.moduleSystem === "commonjs" ? `Package conventions (${decl}): this package compiles as CommonJS. Never use import.meta or top-level await (TS1470, the package's own tsc rejects them); use __dirname and __filename for paths. In files the package's own compiler processes write import statements (they compile to CommonJS) and never require(): a package lint config commonly forbids require() and runs over your file; use require() only in plain .js or .cjs files.` : `Package conventions (${decl}): this package is ES modules. Use import syntax; use import.meta.url for file locations; never use require(), __dirname or __filename.`;
|
|
13973
|
+
}
|
|
13974
|
+
function conventionViolation(c, fileName, content) {
|
|
13975
|
+
if (!c || c.moduleSystem !== "commonjs" || !/\.[cm]?[jt]sx?$/.test(fileName) || /\.m[jt]s$/.test(fileName))
|
|
13976
|
+
return null;
|
|
13977
|
+
const code = content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1").replace(/(["'`])(?:\\.|(?!\1)[^\\\n])*\1/g, '""');
|
|
13978
|
+
return /\bimport\.meta\b/.test(code) ? "import.meta is not allowed in a CommonJS package (TS1470)" : null;
|
|
13979
|
+
}
|
|
13980
|
+
function outOfRepoTarget(content) {
|
|
13981
|
+
const code = content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1").replace(/(^|\s)#.*$/gm, "$1");
|
|
13982
|
+
const lines2 = code.split(`
|
|
13983
|
+
`), at = lines2.findIndex((l) => /\bprocess\.env\.(HOME|USERPROFILE)\s*=(?!=)|\benv\[\s*["'](HOME|USERPROFILE)["']\s*\]\s*=(?!=)|^\s*(export\s+)?(HOME|USERPROFILE)=|\bexport\s+(HOME|USERPROFILE)\b|\bsetenv\(\s*["'](HOME|USERPROFILE)["']|\benv\s*:\s*\{[^}]*\b(HOME|USERPROFILE)\s*:|\bpatch\.dict\([^)]*["'](HOME|USERPROFILE)["']/.test(l));
|
|
13984
|
+
const home = /\bhomedir\s*\(|\bPath\.home\s*\(|\bexpanduser\s*\(|\$\{?HOME\b|\$\{?USERPROFILE\b|\bprocess\.env\.(HOME|USERPROFILE)\b|["'`]~\//;
|
|
13985
|
+
const HOMELIT = String.raw`(?:file:\/\/)?(?:\/(?:Users|home|root)\/|[A-Za-z]:\\+Users\\)`;
|
|
13986
|
+
const literalTarget = new RegExp(String.raw`\b(?:from|import|require)\s*\(?\s*["'` + "`" + String.raw`]${HOMELIT}|^\s*(?:source|\.)\s+["']?${HOMELIT}`);
|
|
13987
|
+
const locates = /["'`\/]\.[A-Za-z][\w-]*(?:[\/"'`]|$)|\b(?:import|require|source|spawn\w*|exec\w*|pathToFileURL|readFile\w*)\b/;
|
|
13988
|
+
for (const line2 of lines2.slice(0, at < 0 ? lines2.length : at)) {
|
|
13989
|
+
if (/^\s*(?:await\s+)?(?:expect|assert\w*)\b/.test(line2))
|
|
13990
|
+
continue;
|
|
13991
|
+
if (home.test(line2) && locates.test(line2) || literalTarget.test(line2))
|
|
13992
|
+
return "resolves the code under test outside the repo via a home-directory path; target repo-relative paths (relative to this test file or the repo root) so the check exercises the change";
|
|
13993
|
+
}
|
|
13994
|
+
return null;
|
|
13995
|
+
}
|
|
13996
|
+
function phantomRepoPaths(content, fileName, testDir, repoDir, planText) {
|
|
13997
|
+
if (!/\.[cm]?[jt]sx?$/.test(fileName))
|
|
13998
|
+
return [];
|
|
13999
|
+
const code = content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1").replace(/\(\s+/g, "(").replace(/\s+\)/g, ")").replace(/,\s*\n\s*/g, ", ").replace(/=\s*\n\s*/g, "= ");
|
|
14000
|
+
let pkg = testDir;
|
|
14001
|
+
while (pkg !== repoDir && pkg !== dirname19(pkg) && !MANIFESTS.some((m) => existsSync33(join53(pkg, m))))
|
|
14002
|
+
pkg = dirname19(pkg);
|
|
14003
|
+
const split2 = (s) => {
|
|
14004
|
+
const out2 = [];
|
|
14005
|
+
let d = 0, q = "", cur = "";
|
|
14006
|
+
for (let i = 0;i < s.length; i++) {
|
|
14007
|
+
const c = s[i];
|
|
14008
|
+
if (q) {
|
|
14009
|
+
cur += c;
|
|
14010
|
+
if (c === "\\")
|
|
14011
|
+
cur += s[++i] ?? "";
|
|
14012
|
+
else if (c === q)
|
|
14013
|
+
q = "";
|
|
14014
|
+
} else if (c === '"' || c === "'" || c === "`") {
|
|
14015
|
+
q = c;
|
|
14016
|
+
cur += c;
|
|
14017
|
+
} else if ("([{".includes(c)) {
|
|
14018
|
+
d++;
|
|
14019
|
+
cur += c;
|
|
14020
|
+
} else if (")]}".includes(c)) {
|
|
14021
|
+
d--;
|
|
14022
|
+
cur += c;
|
|
14023
|
+
} else if (c === "," && d === 0) {
|
|
14024
|
+
out2.push(cur);
|
|
14025
|
+
cur = "";
|
|
14026
|
+
} else
|
|
14027
|
+
cur += c;
|
|
14028
|
+
}
|
|
14029
|
+
if (cur.trim())
|
|
14030
|
+
out2.push(cur);
|
|
14031
|
+
return out2;
|
|
14032
|
+
};
|
|
14033
|
+
const close = (line2, at) => {
|
|
14034
|
+
let d = 0;
|
|
14035
|
+
for (let j = at;j < line2.length; j++) {
|
|
14036
|
+
if (line2[j] === "(")
|
|
14037
|
+
d++;
|
|
14038
|
+
else if (line2[j] === ")" && --d === 0)
|
|
14039
|
+
return j;
|
|
14040
|
+
}
|
|
14041
|
+
return -1;
|
|
14042
|
+
};
|
|
14043
|
+
const scan = (cwd) => {
|
|
14044
|
+
const vars = new Map, reports = new Map, created = [];
|
|
14045
|
+
let ln = 0;
|
|
14046
|
+
const ev = (raw2, report) => {
|
|
14047
|
+
const e = raw2.trim().replace(/^await\s+/, "").replace(/\s+as\s+\w+$/, "").replace(/!$/, "");
|
|
14048
|
+
if (/^import\.meta\.(dir|dirname)$|^__dirname$/.test(e))
|
|
14049
|
+
return testDir;
|
|
14050
|
+
if (e === "process.cwd()")
|
|
14051
|
+
return cwd;
|
|
14052
|
+
const env = /^process\.env(?:\.[\w$]+|\[[^\]]+\])\s*(?:\?\?|\|\|)\s*([\s\S]+)$/.exec(e);
|
|
14053
|
+
if (env)
|
|
14054
|
+
return ev(env[1], report);
|
|
14055
|
+
if (e === "fileURLToPath(import.meta.url)" || e === "__filename")
|
|
14056
|
+
return join53(testDir, "__self__");
|
|
14057
|
+
const url = /^fileURLToPath\(new URL\((["'])([^"']*)\1\s*,\s*import\.meta\.url\)\)$/.exec(e);
|
|
14058
|
+
if (url)
|
|
14059
|
+
return resolve17(testDir, url[2]);
|
|
14060
|
+
const lit = /^(["'`])((?:\\.|(?!\1)[^\\])*)\1$/.exec(e);
|
|
14061
|
+
if (lit)
|
|
14062
|
+
return lit[2].includes("${") ? null : lit[2];
|
|
14063
|
+
if (/^[A-Za-z_$][\w$]*$/.test(e))
|
|
14064
|
+
return vars.get(e) ?? null;
|
|
14065
|
+
const call = /^(?:path\.)?(join|resolve|dirname)\(([\s\S]*)\)$/.exec(e);
|
|
14066
|
+
if (!call)
|
|
14067
|
+
return null;
|
|
14068
|
+
const parts = split2(call[2]), args = parts.map((a) => ev(a, report));
|
|
14069
|
+
if (args.some((a) => a === null))
|
|
14070
|
+
return null;
|
|
14071
|
+
if (call[1] === "dirname")
|
|
14072
|
+
return dirname19(args[0]);
|
|
14073
|
+
const out2 = resolve17(...args);
|
|
14074
|
+
if (report && relative8(testDir, out2).startsWith("..") && parts.some((a) => /^\s*["'`]/.test(a)))
|
|
14075
|
+
reports.set(`${ln}|${e}`, { out: out2, rel: relative8(repoDir, out2) });
|
|
14076
|
+
return out2;
|
|
14077
|
+
};
|
|
14078
|
+
for (const line2 of code.split(`
|
|
14079
|
+
`)) {
|
|
14080
|
+
ln++;
|
|
14081
|
+
for (const m of line2.matchAll(CREATORS)) {
|
|
14082
|
+
const j = close(line2, m.index + m[0].length - 1);
|
|
14083
|
+
if (j > 0)
|
|
14084
|
+
for (const a of split2(line2.slice(m.index + m[0].length, j))) {
|
|
14085
|
+
const v = ev(a, false);
|
|
14086
|
+
if (v)
|
|
14087
|
+
created.push(v);
|
|
14088
|
+
}
|
|
14089
|
+
}
|
|
14090
|
+
const skip = /^\s*(?:await\s+)?(?:expect|assert\w*)\b|\b(?:write\w*|mkdir\w*|rm\w*|cp\w*|copy\w*|rename\w*|symlink\w*|mkdtemp\w*|tmpdir|outputFile|touch)\b/.test(line2);
|
|
14091
|
+
const asg = /^\s*(?:export\s+)?(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*(?::[^=]+)?=\s*(.+?);?\s*$/.exec(line2);
|
|
14092
|
+
if (asg) {
|
|
14093
|
+
const v = ev(asg[2], !skip);
|
|
14094
|
+
if (v !== null)
|
|
14095
|
+
vars.set(asg[1], v);
|
|
14096
|
+
continue;
|
|
14097
|
+
}
|
|
14098
|
+
if (skip)
|
|
14099
|
+
continue;
|
|
14100
|
+
for (const m of line2.matchAll(/(?:path\.)?(?:join|resolve)\(/g)) {
|
|
14101
|
+
const j = close(line2, m.index + m[0].length - 1);
|
|
14102
|
+
if (j > 0)
|
|
14103
|
+
ev(line2.slice(m.index, j + 1), true);
|
|
14104
|
+
}
|
|
14105
|
+
}
|
|
14106
|
+
return { reports, created };
|
|
14107
|
+
};
|
|
14108
|
+
const runs2 = [...new Set([pkg, repoDir])].map(scan);
|
|
14109
|
+
const planned = (rel) => !!planText && rel.split("/").some((_, i, a) => {
|
|
14110
|
+
const pre = a.slice(0, i + 1).join("/");
|
|
14111
|
+
return (i > 0 || a.length === 1) && !existsSync33(join53(repoDir, pre)) && new RegExp(`(?<![\\w-])${pre.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w-])`).test(planText);
|
|
14112
|
+
});
|
|
14113
|
+
const phantom = (r, created) => {
|
|
14114
|
+
const rel = r.rel;
|
|
14115
|
+
if (!rel || rel.startsWith("..") || isAbsolute8(rel) || /(^|\/)(node_modules|\.git|\.loki|dist|build|coverage|tmp)(\/|$)/.test(rel) || existsSync33(r.out) || planned(rel))
|
|
14116
|
+
return false;
|
|
14117
|
+
if (created.some((c) => c === r.out || c.startsWith(r.out + "/") || r.out.startsWith(c + "/")))
|
|
14118
|
+
return false;
|
|
14119
|
+
return safeGitSpawn(repoDir, ["check-ignore", "-q", "--", rel], { timeout: 5000 }).status !== 0;
|
|
14120
|
+
};
|
|
14121
|
+
const missing = [];
|
|
14122
|
+
for (const [k, r] of runs2[0].reports)
|
|
14123
|
+
if (runs2.every((x) => x.reports.has(k) && phantom(x.reports.get(k), x.created)) && !missing.includes(r.rel))
|
|
14124
|
+
missing.push(r.rel);
|
|
14125
|
+
return missing.slice(0, 3);
|
|
14126
|
+
}
|
|
14127
|
+
function phantomReason(miss, repoFiles) {
|
|
14128
|
+
if (miss.length === 0)
|
|
14129
|
+
return null;
|
|
14130
|
+
const hint = (m) => {
|
|
14131
|
+
const n2 = basename22(m), near = [...new Set(repoFiles.flatMap((f) => {
|
|
14132
|
+
const s = f.split("/"), k = s.indexOf(n2);
|
|
14133
|
+
return k >= 0 && s.slice(0, k + 1).join("/") !== m ? [s.slice(0, k + 1).join("/")] : [];
|
|
14134
|
+
}))].slice(0, 3);
|
|
14135
|
+
return near.length ? `${m} (a path named ${n2} exists at ${near.join(", ")})` : m;
|
|
14136
|
+
};
|
|
14137
|
+
return `references repo path(s) that do not exist in the repository and that the plan does not create: ${miss.map(hint).join("; ")}. Locate the real code by searching the repository; do not copy a name from the task text as a path`;
|
|
14138
|
+
}
|
|
14139
|
+
var readJson5 = (p) => {
|
|
14140
|
+
try {
|
|
14141
|
+
const v = parseJsonc(readFileSync42(p, "utf8"));
|
|
14142
|
+
return v && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
14143
|
+
} catch {
|
|
14144
|
+
return null;
|
|
14145
|
+
}
|
|
14146
|
+
}, outOfRepoReask = (lead, bad) => [`${lead} Each was rejected:
|
|
14147
|
+
${bad.map((b) => `- ${b.name}: ${b.why}`).join(`
|
|
14148
|
+
`)}`, `Point every reference at the repository code with repo-relative paths (for example join(import.meta.dir, "..", "<repo path>") or the equivalent for this runner). Do not read the home directory, $HOME or an environment variable that falls back to one. Write nothing else.`].join(`
|
|
14149
|
+
|
|
14150
|
+
`), MANIFESTS, CREATORS;
|
|
14151
|
+
var init_conventions = __esm(() => {
|
|
14152
|
+
init_safe_git();
|
|
14153
|
+
MANIFESTS = ["package.json", "pyproject.toml", "go.mod", "Cargo.toml"];
|
|
14154
|
+
CREATORS = /\b(?:mkdirSync|writeFileSync|appendFileSync|cpSync|copyFileSync|renameSync|symlinkSync|mkdir|writeFile|appendFile|cp|copyFile|rename|outputFile|ensureDir|mkdirp)\(/g;
|
|
14155
|
+
});
|
|
14156
|
+
|
|
13893
14157
|
// ../../loki-ts/src/version.ts
|
|
13894
14158
|
var init_version = __esm(() => {
|
|
13895
14159
|
init_paths();
|
|
@@ -13986,9 +14250,9 @@ var init_route_block = __esm(() => {
|
|
|
13986
14250
|
// ../../loki-ts/src/features/visual_evidence.ts
|
|
13987
14251
|
import { spawn as spawn8 } from "child_process";
|
|
13988
14252
|
import { createHash as createHash14, randomBytes as randomBytes6 } from "crypto";
|
|
13989
|
-
import { existsSync as
|
|
14253
|
+
import { existsSync as existsSync34, lstatSync as lstatSync12, mkdirSync as mkdirSync21, readdirSync as readdirSync20, readFileSync as readFileSync43, writeFileSync as writeFileSync24 } from "fs";
|
|
13990
14254
|
import { createServer } from "net";
|
|
13991
|
-
import { dirname as
|
|
14255
|
+
import { dirname as dirname20, isAbsolute as isAbsolute9, join as join54, normalize as normalize3, relative as relative9, sep as sep13 } from "path";
|
|
13992
14256
|
function routeFor(file) {
|
|
13993
14257
|
let r = file.replace(/^(?:.*?\/)?(?:app|pages|src|public)\//, "").replace(/^(?:routes|pages)\//, "");
|
|
13994
14258
|
r = r.replace(/\.(?:html|jsx|tsx|vue|svelte)$/, "").replace(/\/?(?:page|index|\+page)$/, "");
|
|
@@ -13998,7 +14262,7 @@ function hashScreens(runDir, rels) {
|
|
|
13998
14262
|
const out2 = [];
|
|
13999
14263
|
for (const rel of rels) {
|
|
14000
14264
|
try {
|
|
14001
|
-
out2.push({ path: rel, sha256: sha256File(
|
|
14265
|
+
out2.push({ path: rel, sha256: sha256File(join54(runDir, rel)) });
|
|
14002
14266
|
} catch {}
|
|
14003
14267
|
}
|
|
14004
14268
|
return out2;
|
|
@@ -14009,16 +14273,16 @@ function checkScreens(runDir, screens) {
|
|
|
14009
14273
|
for (const s of screens) {
|
|
14010
14274
|
if (typeof s?.path !== "string" || typeof s.sha256 !== "string")
|
|
14011
14275
|
return "evidence_screens entry is malformed";
|
|
14012
|
-
if (
|
|
14276
|
+
if (isAbsolute9(s.path) || normalize3(s.path).startsWith(".."))
|
|
14013
14277
|
return `evidence screenshot path escapes the evidence dir: ${s.path}`;
|
|
14014
|
-
const file =
|
|
14278
|
+
const file = join54(runDir, s.path);
|
|
14015
14279
|
let cur = runDir;
|
|
14016
14280
|
for (const seg of normalize3(s.path).split(sep13)) {
|
|
14017
|
-
cur =
|
|
14281
|
+
cur = join54(cur, seg);
|
|
14018
14282
|
if (isSymlink(cur))
|
|
14019
14283
|
return `evidence screenshot path is a symlink: ${s.path}`;
|
|
14020
14284
|
}
|
|
14021
|
-
if (!
|
|
14285
|
+
if (!existsSync34(file))
|
|
14022
14286
|
return `evidence screenshot is missing: ${s.path}`;
|
|
14023
14287
|
if (!isRegularFile(file))
|
|
14024
14288
|
return `evidence screenshot is not a regular file: ${s.path}`;
|
|
@@ -14061,11 +14325,11 @@ async function waitUp(url, ms, signal) {
|
|
|
14061
14325
|
}
|
|
14062
14326
|
function openapiPaths(repoDir) {
|
|
14063
14327
|
for (const f of ["openapi.json", "openapi.yaml", "openapi.yml", "swagger.json"]) {
|
|
14064
|
-
const p =
|
|
14065
|
-
if (!
|
|
14328
|
+
const p = join54(repoDir, f);
|
|
14329
|
+
if (!existsSync34(p))
|
|
14066
14330
|
continue;
|
|
14067
14331
|
try {
|
|
14068
|
-
const txt =
|
|
14332
|
+
const txt = readFileSync43(p, "utf8");
|
|
14069
14333
|
const paths = f.endsWith(".json") ? Object.keys(JSON.parse(txt).paths ?? {}) : [...txt.matchAll(/^ {2}(\/[^\s:]*):\s*$/gm)].map((m) => m[1]);
|
|
14070
14334
|
return paths.filter((x) => !x.includes("{")).slice(0, 10);
|
|
14071
14335
|
} catch {
|
|
@@ -14079,24 +14343,24 @@ async function recordE2eMedia(repoDir, runDir, relDir, base, routes, ms, signal)
|
|
|
14079
14343
|
if (!pw || !pkg)
|
|
14080
14344
|
return { rels: [], skipped: "playwright e2e video and trace skipped: @playwright/test is not installed in the repo" };
|
|
14081
14345
|
try {
|
|
14082
|
-
const dir =
|
|
14346
|
+
const dir = join54(runDir, relDir, "e2e");
|
|
14083
14347
|
mkdirSync21(dir, { recursive: true });
|
|
14084
|
-
writeFileSync24(
|
|
14085
|
-
writeFileSync24(
|
|
14348
|
+
writeFileSync24(join54(dir, "walk.spec.cjs"), e2eSpecSource(pkg, base, routes));
|
|
14349
|
+
writeFileSync24(join54(dir, "playwright.config.cjs"), `module.exports = { testDir: ".", testMatch: "walk.spec.cjs", outputDir: "./out", reporter: "null", use: { video: "on", trace: "on" } };
|
|
14086
14350
|
`);
|
|
14087
|
-
if (!await shoot(pw, ["test", "--config",
|
|
14351
|
+
if (!await shoot(pw, ["test", "--config", join54(dir, "playwright.config.cjs")], repoDir, ms, signal))
|
|
14088
14352
|
return { rels: [], skipped: "playwright e2e video and trace skipped: the run failed or timed out" };
|
|
14089
14353
|
const rels = [];
|
|
14090
14354
|
const walk = (d) => {
|
|
14091
|
-
for (const e of
|
|
14092
|
-
const full =
|
|
14355
|
+
for (const e of readdirSync20(d, { withFileTypes: true })) {
|
|
14356
|
+
const full = join54(d, e.name);
|
|
14093
14357
|
if (e.isDirectory())
|
|
14094
14358
|
walk(full);
|
|
14095
14359
|
else if (e.isFile() && /\.(webm|zip)$/.test(e.name))
|
|
14096
|
-
rels.push(
|
|
14360
|
+
rels.push(join54(relDir, "e2e", relative9(dir, full)));
|
|
14097
14361
|
}
|
|
14098
14362
|
};
|
|
14099
|
-
walk(
|
|
14363
|
+
walk(join54(dir, "out"));
|
|
14100
14364
|
return rels.length > 0 ? { rels, skipped: null } : { rels, skipped: "playwright e2e video and trace skipped: no video or trace was produced" };
|
|
14101
14365
|
} catch (e) {
|
|
14102
14366
|
return { rels: [], skipped: `playwright e2e video and trace skipped: ${String(e?.message ?? e).slice(0, 120)}` };
|
|
@@ -14175,22 +14439,22 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
14175
14439
|
if (!visualEvidenceEnabled(opts.env))
|
|
14176
14440
|
return skip("LOKI_VISUAL_EVIDENCE is 0");
|
|
14177
14441
|
const api = loadProjectApi(repoDir), boot = isMultiRoot(api) ? api.uiBoot() : null;
|
|
14178
|
-
const appDir = boot ?
|
|
14179
|
-
const pkgPath =
|
|
14442
|
+
const appDir = boot ? join54(repoDir, boot.boot.cwd) : repoDir;
|
|
14443
|
+
const pkgPath = join54(appDir, "package.json");
|
|
14180
14444
|
let script = null;
|
|
14181
14445
|
if (!boot) {
|
|
14182
|
-
if (!
|
|
14183
|
-
const subs = ["backend", "frontend"].filter((d) =>
|
|
14446
|
+
if (!existsSync34(pkgPath)) {
|
|
14447
|
+
const subs = ["backend", "frontend"].filter((d) => existsSync34(join54(repoDir, d, "package.json")));
|
|
14184
14448
|
const has2 = (d) => {
|
|
14185
14449
|
try {
|
|
14186
|
-
return pickScript(JSON.parse(
|
|
14450
|
+
return pickScript(JSON.parse(readFileSync43(join54(repoDir, d, "package.json"), "utf8"))) !== null;
|
|
14187
14451
|
} catch {
|
|
14188
14452
|
return false;
|
|
14189
14453
|
}
|
|
14190
14454
|
};
|
|
14191
14455
|
return skip(noRootReason(subs, subs.filter((d) => !has2(d))));
|
|
14192
14456
|
}
|
|
14193
|
-
script = pickScript(JSON.parse(
|
|
14457
|
+
script = pickScript(JSON.parse(readFileSync43(pkgPath, "utf8")));
|
|
14194
14458
|
if (!script)
|
|
14195
14459
|
return skip("no dev, preview or start script");
|
|
14196
14460
|
}
|
|
@@ -14217,20 +14481,20 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
14217
14481
|
}
|
|
14218
14482
|
if (!await waitUp(base, left(), signal))
|
|
14219
14483
|
return skip(aborted() ? "aborted" : `${script} server did not answer within ${Math.round(budget / 1000)}s`);
|
|
14220
|
-
const evRoot =
|
|
14484
|
+
const evRoot = join54(runDir, "evidence");
|
|
14221
14485
|
if (isSymlink(evRoot))
|
|
14222
14486
|
return skip("evidence dir is a symlink");
|
|
14223
14487
|
mkdirSync21(evRoot, { recursive: true });
|
|
14224
14488
|
if (pages.length > 0) {
|
|
14225
|
-
const rel0 =
|
|
14226
|
-
mkdirSync21(
|
|
14489
|
+
const rel0 = join54("evidence", randomBytes6(6).toString("hex"));
|
|
14490
|
+
mkdirSync21(join54(runDir, rel0));
|
|
14227
14491
|
const rels = [];
|
|
14228
14492
|
for (const route of [...new Set(pages.map(routeFor))].slice(0, opts.maxRoutes ?? MAX_ROUTES)) {
|
|
14229
14493
|
if (aborted() || left() <= 0)
|
|
14230
14494
|
break;
|
|
14231
|
-
const rel =
|
|
14232
|
-
const ok = await shoot(pw, ["screenshot", `${base}${route}`,
|
|
14233
|
-
if (ok && !aborted() && !isSymlink(
|
|
14495
|
+
const rel = join54(rel0, `${screenName(route)}.png`);
|
|
14496
|
+
const ok = await shoot(pw, ["screenshot", `${base}${route}`, join54(runDir, rel)], appDir, left(), signal);
|
|
14497
|
+
if (ok && !aborted() && !isSymlink(join54(runDir, rel)) && existsSync34(join54(runDir, rel)))
|
|
14234
14498
|
rels.push(rel);
|
|
14235
14499
|
}
|
|
14236
14500
|
if (aborted())
|
|
@@ -14255,9 +14519,9 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
14255
14519
|
}
|
|
14256
14520
|
if (aborted())
|
|
14257
14521
|
return skip("aborted");
|
|
14258
|
-
const hdir =
|
|
14522
|
+
const hdir = join54(evRoot, randomBytes6(6).toString("hex"));
|
|
14259
14523
|
mkdirSync21(hdir);
|
|
14260
|
-
writeFileSync24(
|
|
14524
|
+
writeFileSync24(join54(hdir, "http.json"), JSON.stringify(rows, null, 2) + `
|
|
14261
14525
|
`);
|
|
14262
14526
|
return { screens: [], http: true, skipped: null };
|
|
14263
14527
|
} catch (e) {
|
|
@@ -14284,14 +14548,14 @@ async function sealEvidence(repoDir, runDir, o, notProven, signal, emit) {
|
|
|
14284
14548
|
function receiptScreensProblem(receiptPath, receipt) {
|
|
14285
14549
|
if (visualGateEnabled() && typeof receipt["evidence_failed"] === "string")
|
|
14286
14550
|
return `visual evidence failed (LOKI_VISUAL_GATE=1): ${receipt["evidence_failed"]}`;
|
|
14287
|
-
return receipt["evidence_screens"] === undefined ? null : checkScreens(
|
|
14551
|
+
return receipt["evidence_screens"] === undefined ? null : checkScreens(dirname20(receiptPath), receipt["evidence_screens"]);
|
|
14288
14552
|
}
|
|
14289
|
-
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(
|
|
14290
|
-
const bin =
|
|
14291
|
-
return
|
|
14553
|
+
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(readFileSync43(p)).digest("hex"), playwrightBin = (repoDir) => {
|
|
14554
|
+
const bin = join54(repoDir, "node_modules", ".bin", "playwright");
|
|
14555
|
+
return existsSync34(bin) ? bin : null;
|
|
14292
14556
|
}, playwrightTestPkg = (repoDir) => {
|
|
14293
|
-
const d =
|
|
14294
|
-
return
|
|
14557
|
+
const d = join54(repoDir, "node_modules", "@playwright", "test");
|
|
14558
|
+
return existsSync34(join54(d, "package.json")) ? d : null;
|
|
14295
14559
|
}, e2eSpecSource = (pkgDir, base, routes) => `const { test } = require(${JSON.stringify(pkgDir)});
|
|
14296
14560
|
test("loki e2e walkthrough", async ({ page }) => {
|
|
14297
14561
|
for (const r of ${JSON.stringify(routes)}) { await page.goto(${JSON.stringify(base)} + r); await page.waitForLoadState("load"); }
|
|
@@ -14337,7 +14601,7 @@ var init_outbox = __esm(() => {
|
|
|
14337
14601
|
});
|
|
14338
14602
|
|
|
14339
14603
|
// ../../loki-ts/src/engine10/stages/pr.ts
|
|
14340
|
-
import { join as
|
|
14604
|
+
import { join as join55 } from "path";
|
|
14341
14605
|
var DEFAULT_PUSH_SH, DEFAULT_PUSH_GITLAB_SH;
|
|
14342
14606
|
var init_pr = __esm(() => {
|
|
14343
14607
|
init_types();
|
|
@@ -14356,20 +14620,20 @@ var init_pr = __esm(() => {
|
|
|
14356
14620
|
init_receipt_surface();
|
|
14357
14621
|
init_yaml_key();
|
|
14358
14622
|
init_outbox();
|
|
14359
|
-
DEFAULT_PUSH_SH =
|
|
14360
|
-
DEFAULT_PUSH_GITLAB_SH =
|
|
14623
|
+
DEFAULT_PUSH_SH = join55(REPO_ROOT, "autonomy/lib/engine10-push.sh");
|
|
14624
|
+
DEFAULT_PUSH_GITLAB_SH = join55(REPO_ROOT, "autonomy/lib/engine10-push-gitlab.sh");
|
|
14361
14625
|
});
|
|
14362
14626
|
|
|
14363
14627
|
// ../../loki-ts/src/util/pr_lessons.ts
|
|
14364
|
-
import { existsSync as
|
|
14365
|
-
import { dirname as
|
|
14628
|
+
import { existsSync as existsSync35, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync8, readFileSync as readFileSync44, rmSync as rmSync16, writeFileSync as writeFileSync25 } from "fs";
|
|
14629
|
+
import { dirname as dirname21, join as join56 } from "path";
|
|
14366
14630
|
import { createHash as createHash15 } from "crypto";
|
|
14367
14631
|
function loadLessons(repoDir) {
|
|
14368
14632
|
const p = lessonsPath(repoDir);
|
|
14369
|
-
if (!
|
|
14633
|
+
if (!existsSync35(p))
|
|
14370
14634
|
return [];
|
|
14371
14635
|
try {
|
|
14372
|
-
const j = JSON.parse(
|
|
14636
|
+
const j = JSON.parse(readFileSync44(p, "utf-8"));
|
|
14373
14637
|
return Array.isArray(j.lessons) ? j.lessons : [];
|
|
14374
14638
|
} catch {
|
|
14375
14639
|
return [];
|
|
@@ -14377,7 +14641,7 @@ function loadLessons(repoDir) {
|
|
|
14377
14641
|
}
|
|
14378
14642
|
function save(repoDir, lessons) {
|
|
14379
14643
|
const p = lessonsPath(repoDir);
|
|
14380
|
-
mkdirSync22(
|
|
14644
|
+
mkdirSync22(dirname21(p), { recursive: true });
|
|
14381
14645
|
atomicWriteJson(p, { version: 2, lessons });
|
|
14382
14646
|
}
|
|
14383
14647
|
function appendReceiptFact(repoDir, f, now2 = () => new Date) {
|
|
@@ -14411,7 +14675,7 @@ function recordRunVerdict(repoDir, runId2, verdict) {
|
|
|
14411
14675
|
if (dirty)
|
|
14412
14676
|
save(repoDir, lessons);
|
|
14413
14677
|
}
|
|
14414
|
-
var lessonsPath = (repoDir) =>
|
|
14678
|
+
var lessonsPath = (repoDir) => join56(repoDir, ".loki", "memory", "semantic", "pr-lessons.json"), KINDS;
|
|
14415
14679
|
var init_pr_lessons = __esm(() => {
|
|
14416
14680
|
init_atomic();
|
|
14417
14681
|
init_safe_git();
|
|
@@ -14437,8 +14701,8 @@ var init_attempts = __esm(() => {
|
|
|
14437
14701
|
var init_mcp_config = () => {};
|
|
14438
14702
|
|
|
14439
14703
|
// ../../loki-ts/src/providers/claude_flags.ts
|
|
14440
|
-
import { existsSync as
|
|
14441
|
-
import { resolve as resolvePath, dirname as
|
|
14704
|
+
import { existsSync as existsSync36, readFileSync as readFileSync45 } from "fs";
|
|
14705
|
+
import { resolve as resolvePath, dirname as dirname22 } from "path";
|
|
14442
14706
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
14443
14707
|
function claudeFlagSupported(flag, helpText) {
|
|
14444
14708
|
const txt = helpText ?? _claudeHelpCache;
|
|
@@ -14485,14 +14749,14 @@ function leanReviewerFlags(opts = {}) {
|
|
|
14485
14749
|
}
|
|
14486
14750
|
function designArchetypesText() {
|
|
14487
14751
|
try {
|
|
14488
|
-
const moduleDir =
|
|
14752
|
+
const moduleDir = dirname22(fileURLToPath5(import.meta.url));
|
|
14489
14753
|
for (const rel of [
|
|
14490
14754
|
["..", "..", "..", "references", "design-archetypes.md"],
|
|
14491
14755
|
["..", "..", "references", "design-archetypes.md"]
|
|
14492
14756
|
]) {
|
|
14493
14757
|
const p = resolvePath(moduleDir, ...rel);
|
|
14494
|
-
if (
|
|
14495
|
-
return
|
|
14758
|
+
if (existsSync36(p))
|
|
14759
|
+
return readFileSync45(p, "utf8");
|
|
14496
14760
|
}
|
|
14497
14761
|
} catch {}
|
|
14498
14762
|
return "";
|
|
@@ -14577,14 +14841,14 @@ var init_providers = __esm(() => {
|
|
|
14577
14841
|
});
|
|
14578
14842
|
|
|
14579
14843
|
// ../../loki-ts/src/runner/router/route_record.ts
|
|
14580
|
-
import { existsSync as
|
|
14581
|
-
import { join as
|
|
14844
|
+
import { existsSync as existsSync37, lstatSync as lstatSync13, mkdirSync as mkdirSync23, readFileSync as readFileSync46, writeFileSync as writeFileSync26 } from "fs";
|
|
14845
|
+
import { join as join57 } from "path";
|
|
14582
14846
|
function loadRouteRecord(runDir) {
|
|
14583
14847
|
try {
|
|
14584
|
-
const p =
|
|
14585
|
-
if (!
|
|
14848
|
+
const p = join57(runDir, ROUTE_RECORD_FILE);
|
|
14849
|
+
if (!existsSync37(p) || !lstatSync13(p).isFile())
|
|
14586
14850
|
return;
|
|
14587
|
-
const v = JSON.parse(
|
|
14851
|
+
const v = JSON.parse(readFileSync46(p, "utf8"));
|
|
14588
14852
|
return typeof v === "object" && v !== null && !Array.isArray(v) ? v : undefined;
|
|
14589
14853
|
} catch {
|
|
14590
14854
|
return;
|
|
@@ -14645,6 +14909,7 @@ var init_implement_route = __esm(() => {
|
|
|
14645
14909
|
var init_implement = __esm(() => {
|
|
14646
14910
|
init_install();
|
|
14647
14911
|
init_lean_prefix();
|
|
14912
|
+
init_conventions();
|
|
14648
14913
|
init_pr_lessons();
|
|
14649
14914
|
init_context();
|
|
14650
14915
|
init_model_downgrades();
|
|
@@ -14732,14 +14997,14 @@ __export(exports_deep, {
|
|
|
14732
14997
|
DEFAULT_SECRET_SCAN_SH: () => DEFAULT_SECRET_SCAN_SH,
|
|
14733
14998
|
DEFAULT_PUSH_SH: () => DEFAULT_PUSH_SH2
|
|
14734
14999
|
});
|
|
14735
|
-
import { copyFileSync as copyFileSync3, existsSync as
|
|
15000
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync38, lstatSync as lstatSync14, mkdirSync as mkdirSync24, mkdtempSync as mkdtempSync9, rmSync as rmSync17, writeFileSync as writeFileSync27 } from "fs";
|
|
14736
15001
|
import { tmpdir as tmpdir10 } from "os";
|
|
14737
|
-
import { dirname as
|
|
15002
|
+
import { dirname as dirname23, join as join58 } from "path";
|
|
14738
15003
|
function sessionCouncil(sessions) {
|
|
14739
15004
|
return { async run(input, signal) {
|
|
14740
|
-
const cwd = mkdtempSync9(
|
|
15005
|
+
const cwd = mkdtempSync9(join58(tmpdir10(), "loki-deep-council-"));
|
|
14741
15006
|
try {
|
|
14742
|
-
writeFileSync27(
|
|
15007
|
+
writeFileSync27(join58(cwd, "diff.patch"), input.diff, "utf8");
|
|
14743
15008
|
const r = await sessions.run({
|
|
14744
15009
|
stage: "deep",
|
|
14745
15010
|
tier: "development",
|
|
@@ -14809,7 +15074,7 @@ ${r.stderr}`), lr = r.exitCode === 0 ? undefined : await harnessLoadReason({ rep
|
|
|
14809
15074
|
async function runAppBoot(ctx, opts, checks, notProven) {
|
|
14810
15075
|
let r;
|
|
14811
15076
|
try {
|
|
14812
|
-
r = await (opts.appProbe ?? appProbe)(ctx.repoDir,
|
|
15077
|
+
r = await (opts.appProbe ?? appProbe)(ctx.repoDir, join58(ctx.repoDir, ".loki"));
|
|
14813
15078
|
} catch (err) {
|
|
14814
15079
|
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 };
|
|
14815
15080
|
}
|
|
@@ -14855,12 +15120,12 @@ async function runCouncilCheck(ctx, changed, baseSha, signal, opts, checks, notP
|
|
|
14855
15120
|
}
|
|
14856
15121
|
}
|
|
14857
15122
|
async function secureScanChanged(repoDir, changed, opts) {
|
|
14858
|
-
const dir = mkdtempSync9(
|
|
15123
|
+
const dir = mkdtempSync9(join58(tmpdir10(), "loki-deep-secure-"));
|
|
14859
15124
|
try {
|
|
14860
15125
|
for (const f of changed)
|
|
14861
|
-
if (
|
|
14862
|
-
mkdirSync24(
|
|
14863
|
-
copyFileSync3(
|
|
15126
|
+
if (existsSync38(join58(repoDir, f)) && lstatSync14(join58(repoDir, f)).isFile()) {
|
|
15127
|
+
mkdirSync24(dirname23(join58(dir, f)), { recursive: true });
|
|
15128
|
+
copyFileSync3(join58(repoDir, f), join58(dir, f));
|
|
14864
15129
|
}
|
|
14865
15130
|
return await runSecureScan(dir, { ...opts.secureScanPath ? { scriptPath: opts.secureScanPath } : {}, timeoutMs: 60000 });
|
|
14866
15131
|
} finally {
|
|
@@ -14869,7 +15134,7 @@ async function secureScanChanged(repoDir, changed, opts) {
|
|
|
14869
15134
|
}
|
|
14870
15135
|
async function runSecretScan(ctx, changed, opts, checks, notProven) {
|
|
14871
15136
|
const scriptPath = opts.secretScanShPath ?? DEFAULT_SECRET_SCAN_SH, name = "security scan", cmd2 = "secret-scan.sh + secure-scan.py";
|
|
14872
|
-
if (!
|
|
15137
|
+
if (!existsSync38(scriptPath)) {
|
|
14873
15138
|
checks.push({ name, cmd: cmd2, result: "not_run", duration_s: 0 });
|
|
14874
15139
|
notProven.add(`not run: ${name} (secret-scan.sh not found)`);
|
|
14875
15140
|
return;
|
|
@@ -14880,7 +15145,7 @@ async function runSecretScan(ctx, changed, opts, checks, notProven) {
|
|
|
14880
15145
|
}
|
|
14881
15146
|
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"';
|
|
14882
15147
|
const started = Date.now();
|
|
14883
|
-
const r = await run(["bash", "-c", inline, "_", scriptPath, ...changed.map((f) =>
|
|
15148
|
+
const r = await run(["bash", "-c", inline, "_", scriptPath, ...changed.map((f) => join58(ctx.repoDir, f))], { cwd: ctx.repoDir, timeoutMs: 30000 });
|
|
14884
15149
|
const sec = await secureScanChanged(ctx.repoDir, changed, opts), gaps = [], reasons = [];
|
|
14885
15150
|
const hits = r.exitCode === 3 ? [] : r.stdout.split(`
|
|
14886
15151
|
`).map((l) => l.trim()).filter(Boolean), high = sec.findings.filter((f) => String(f.severity).toUpperCase() === "HIGH");
|
|
@@ -14921,7 +15186,7 @@ async function postResults(ctx, opts, checks, notProven, statusState) {
|
|
|
14921
15186
|
const prNumber = prUrl ? PR_NUMBER_RE.exec(prUrl)?.[1] : undefined;
|
|
14922
15187
|
if (prNumber) {
|
|
14923
15188
|
mkdirSync24(ctx.runDir, { recursive: true });
|
|
14924
|
-
const bodyFile =
|
|
15189
|
+
const bodyFile = join58(ctx.runDir, "deep-comment.md");
|
|
14925
15190
|
writeFileSync27(bodyFile, buildCommentBody(checks, notProven, statusState), "utf8");
|
|
14926
15191
|
const commentResult = await run(["bash", scriptPath, ...commentArgv(prNumber, bodyFile)], { cwd: ctx.repoDir, env, timeoutMs: 30000 });
|
|
14927
15192
|
if (commentResult.exitCode !== 0)
|
|
@@ -14976,7 +15241,7 @@ async function runDeep(ctx, signal, opts = {}) {
|
|
|
14976
15241
|
const sig = signReceipt(`${ctx.runId}-deep`, addendumSha256);
|
|
14977
15242
|
const addendum = { ...addendumBody, addendum_sha256: addendumSha256, verification: { jwt: sig.jwt, kid: sig.kid } };
|
|
14978
15243
|
mkdirSync24(ctx.runDir, { recursive: true });
|
|
14979
|
-
writeFileSync27(
|
|
15244
|
+
writeFileSync27(join58(ctx.runDir, "receipt-addendum-1.json"), JSON.stringify(addendum, null, 2) + `
|
|
14980
15245
|
`);
|
|
14981
15246
|
const pushNotProven = await postResults(ctx, opts, checks, notProvenList, statusState);
|
|
14982
15247
|
const allNotProven = [...notProvenList, ...pushNotProven];
|
|
@@ -15012,9 +15277,9 @@ var init_deep = __esm(() => {
|
|
|
15012
15277
|
});
|
|
15013
15278
|
|
|
15014
15279
|
// ../../loki-ts/src/engine10/stages/verify.ts
|
|
15015
|
-
import { existsSync as
|
|
15280
|
+
import { existsSync as existsSync39, mkdtempSync as mkdtempSync10, rmSync as rmSync18 } from "fs";
|
|
15016
15281
|
import { tmpdir as tmpdir11 } from "os";
|
|
15017
|
-
import { isAbsolute as
|
|
15282
|
+
import { isAbsolute as isAbsolute10, join as join59, relative as relative10 } from "path";
|
|
15018
15283
|
async function runOnce2(cmd2, args, cwd, signal, opts) {
|
|
15019
15284
|
if (!Bun.which(cmd2, { PATH: opts.path ?? process.env["PATH"] ?? "" }))
|
|
15020
15285
|
return { ok: false, missing: true, cut: false, out: "" };
|
|
@@ -15088,7 +15353,7 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal,
|
|
|
15088
15353
|
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)) : [];
|
|
15089
15354
|
if (!(un.some(({ c }) => c.result === "fail" && c.ids?.length) || sus.length || zc.length) || signal.aborted)
|
|
15090
15355
|
return out2;
|
|
15091
|
-
const dir = mkdtempSync10(
|
|
15356
|
+
const dir = mkdtempSync10(join59(tmpdir11(), "e10-base-"));
|
|
15092
15357
|
const git4 = (args) => {
|
|
15093
15358
|
safeGit(ctx.repoDir, args, { stdio: "ignore", repoDrivers: true });
|
|
15094
15359
|
};
|
|
@@ -15127,7 +15392,7 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal,
|
|
|
15127
15392
|
return out2;
|
|
15128
15393
|
}
|
|
15129
15394
|
function isLokiModeRepo(repoDir) {
|
|
15130
|
-
return
|
|
15395
|
+
return existsSync39(join59(repoDir, "scripts", "select-tests.sh"));
|
|
15131
15396
|
}
|
|
15132
15397
|
async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
|
|
15133
15398
|
const { api, ...runOpts } = opts;
|
|
@@ -15149,9 +15414,9 @@ async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
|
|
|
15149
15414
|
}
|
|
15150
15415
|
for (const g of groupByPackage(api, ctx.repoDir, changed.filter((f) => /\.(ts|tsx|js|jsx)$/.test(f)))) {
|
|
15151
15416
|
const sfx = g.root === "." ? "" : `:${g.root}`, co = g.root === "." ? opts : { ...opts, cwd: g.cwd };
|
|
15152
|
-
if (
|
|
15417
|
+
if (existsSync39(join59(g.cwd, "tsconfig.json")))
|
|
15153
15418
|
await runCheck(ctx, `lint:tsc${sfx}`, "npx", ["--no-install", "tsc", "--noEmit", "-p", "."], signal, checks, { ...co, kind: "static" });
|
|
15154
|
-
if (ESLINT_CONFIGS.some((f) =>
|
|
15419
|
+
if (ESLINT_CONFIGS.some((f) => existsSync39(join59(g.cwd, f)))) {
|
|
15155
15420
|
const c = await runCheck(ctx, `lint:eslint${sfx}`, "npx", ["--no-install", "eslint", ...g.rel], signal, checks, { ...co, kind: "static" });
|
|
15156
15421
|
if (await excuseLint(ctx, signal, c, "eslint", "npx", ["--no-install", "eslint"], g.cwd, g.rel, co))
|
|
15157
15422
|
pre.push(c.name);
|
|
@@ -15166,7 +15431,7 @@ var CHECK_TIMEOUT_MS = 60000, excerpts, isHold = (c) => isHoldoutCheck(c.name),
|
|
|
15166
15431
|
return r.missing || r.cut ? null : r;
|
|
15167
15432
|
}, base: (f) => {
|
|
15168
15433
|
try {
|
|
15169
|
-
return safeGit(ctx.repoDir, ["show", `${ctx.baseSha}:${
|
|
15434
|
+
return safeGit(ctx.repoDir, ["show", `${ctx.baseSha}:${relative10(ctx.repoDir, join59(cwd, f))}`], { stdio: ["ignore", "pipe", "ignore"] });
|
|
15170
15435
|
} catch {
|
|
15171
15436
|
return null;
|
|
15172
15437
|
}
|
|
@@ -15231,7 +15496,7 @@ var init_verify = __esm(() => {
|
|
|
15231
15496
|
const impacted = ctx.tests.impacted(map, changed);
|
|
15232
15497
|
const changedTestFiles = map.tests.filter((t) => changed.includes(t.path));
|
|
15233
15498
|
const wall = ctx.outputs().wall ?? {};
|
|
15234
|
-
const wallPaths = new Set((wall.files ?? []).map((f) =>
|
|
15499
|
+
const wallPaths = new Set((wall.files ?? []).map((f) => isAbsolute10(f.path) ? relative10(ctx.repoDir, f.path) : f.path));
|
|
15235
15500
|
const intake = ctx.outputs().intake, repoMap = loadRepoMap(intake?.repomap_ref), relevant2 = ctx.tests.impacted(map, namedFiles(intake?.task ?? "", repoMap));
|
|
15236
15501
|
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 })) : []];
|
|
15237
15502
|
const tests = failedFirst(dedupeTests([...impacted, ...changedTestFiles, ...wallTests, ...relevant2]), ctx.outputs().verify?.checks);
|
|
@@ -15338,111 +15603,11 @@ ${x}` : c.cmd };
|
|
|
15338
15603
|
};
|
|
15339
15604
|
});
|
|
15340
15605
|
|
|
15341
|
-
// ../../loki-ts/src/project_model/conventions.ts
|
|
15342
|
-
import { existsSync as existsSync39, readdirSync as readdirSync20, readFileSync as readFileSync46 } from "fs";
|
|
15343
|
-
import { dirname as dirname23, join as join59 } from "path";
|
|
15344
|
-
function parseJsonc(text2) {
|
|
15345
|
-
let out2 = "", i = 0;
|
|
15346
|
-
while (i < text2.length) {
|
|
15347
|
-
const c = text2[i], n2 = text2[i + 1];
|
|
15348
|
-
if (c === '"') {
|
|
15349
|
-
let j = i + 1;
|
|
15350
|
-
while (j < text2.length && text2[j] !== '"')
|
|
15351
|
-
j += text2[j] === "\\" ? 2 : 1;
|
|
15352
|
-
out2 += text2.slice(i, j + 1);
|
|
15353
|
-
i = j + 1;
|
|
15354
|
-
} else if (c === "/" && n2 === "/") {
|
|
15355
|
-
while (i < text2.length && text2[i] !== `
|
|
15356
|
-
`)
|
|
15357
|
-
i++;
|
|
15358
|
-
} else if (c === "/" && n2 === "*") {
|
|
15359
|
-
const e = text2.indexOf("*/", i + 2);
|
|
15360
|
-
i = e < 0 ? text2.length : e + 2;
|
|
15361
|
-
} else {
|
|
15362
|
-
out2 += c;
|
|
15363
|
-
i++;
|
|
15364
|
-
}
|
|
15365
|
-
}
|
|
15366
|
-
return JSON.parse(out2.replace(/,(\s*[}\]])/g, "$1"));
|
|
15367
|
-
}
|
|
15368
|
-
function moduleOf(file, depth = 0) {
|
|
15369
|
-
const j = readJson5(file);
|
|
15370
|
-
if (!j || depth > 4)
|
|
15371
|
-
return null;
|
|
15372
|
-
const m = j.compilerOptions?.module;
|
|
15373
|
-
if (typeof m === "string")
|
|
15374
|
-
return m.toLowerCase();
|
|
15375
|
-
const ext = typeof j.extends === "string" ? j.extends : null;
|
|
15376
|
-
if (!ext || !ext.startsWith("."))
|
|
15377
|
-
return null;
|
|
15378
|
-
const next = join59(dirname23(file), ext.endsWith(".json") ? ext : `${ext}.json`);
|
|
15379
|
-
return existsSync39(next) ? moduleOf(next, depth + 1) : null;
|
|
15380
|
-
}
|
|
15381
|
-
function readPackageConventions(pkgDir, runner = null) {
|
|
15382
|
-
let names = [];
|
|
15383
|
-
try {
|
|
15384
|
-
names = readdirSync20(pkgDir).filter((f) => f.endsWith(".json")).sort((x, y) => x.length - y.length || x.localeCompare(y));
|
|
15385
|
-
} catch {
|
|
15386
|
-
return null;
|
|
15387
|
-
}
|
|
15388
|
-
let packageType = null, tsModule = null;
|
|
15389
|
-
for (const n2 of names) {
|
|
15390
|
-
const j = readJson5(join59(pkgDir, n2));
|
|
15391
|
-
if (!j)
|
|
15392
|
-
continue;
|
|
15393
|
-
if (packageType === null && typeof j.type === "string" && typeof j.name === "string")
|
|
15394
|
-
packageType = j.type;
|
|
15395
|
-
if (tsModule === null && j.compilerOptions !== undefined)
|
|
15396
|
-
tsModule = moduleOf(join59(pkgDir, n2));
|
|
15397
|
-
}
|
|
15398
|
-
if (packageType === null && tsModule === null)
|
|
15399
|
-
return null;
|
|
15400
|
-
const esmType = packageType === "module";
|
|
15401
|
-
const moduleSystem = tsModule === null || tsModule === "node16" || tsModule === "nodenext" ? esmType ? "esm" : "commonjs" : /^(commonjs|amd|umd|system)$/.test(tsModule) ? "commonjs" : "esm";
|
|
15402
|
-
return { moduleSystem, packageType, tsModule, runner };
|
|
15403
|
-
}
|
|
15404
|
-
function conventionsBrief(c) {
|
|
15405
|
-
if (!c)
|
|
15406
|
-
return "";
|
|
15407
|
-
const decl = `manifest type: ${c.packageType ?? "(unset)"}, compiler module: ${c.tsModule ?? "(unset)"}${c.runner ? `, test runner: ${c.runner}` : ""}`;
|
|
15408
|
-
return c.moduleSystem === "commonjs" ? `Package conventions (${decl}): this package compiles as CommonJS. Never use import.meta or top-level await (TS1470, the package's own tsc rejects them); use __dirname and __filename for paths. In files the package's own compiler processes write import statements (they compile to CommonJS) and never require(): a package lint config commonly forbids require() and runs over your file; use require() only in plain .js or .cjs files.` : `Package conventions (${decl}): this package is ES modules. Use import syntax; use import.meta.url for file locations; never use require(), __dirname or __filename.`;
|
|
15409
|
-
}
|
|
15410
|
-
function conventionViolation(c, fileName, content) {
|
|
15411
|
-
if (!c || c.moduleSystem !== "commonjs" || !/\.[cm]?[jt]sx?$/.test(fileName) || /\.m[jt]s$/.test(fileName))
|
|
15412
|
-
return null;
|
|
15413
|
-
const code = content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1").replace(/(["'`])(?:\\.|(?!\1)[^\\\n])*\1/g, '""');
|
|
15414
|
-
return /\bimport\.meta\b/.test(code) ? "import.meta is not allowed in a CommonJS package (TS1470)" : null;
|
|
15415
|
-
}
|
|
15416
|
-
function outOfRepoTarget(content) {
|
|
15417
|
-
const code = content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1").replace(/(^|\s)#.*$/gm, "$1");
|
|
15418
|
-
if (/\bprocess\.env\.(HOME|USERPROFILE)\s*=(?!=)|\benv\[\s*["'](HOME|USERPROFILE)["']\s*\]\s*=(?!=)|^\s*(export\s+)?(HOME|USERPROFILE)=|\bexport\s+(HOME|USERPROFILE)\b|\bsetenv\(\s*["'](HOME|USERPROFILE)["']|\benv\s*:\s*\{[^}]*\b(HOME|USERPROFILE)\s*:|\bpatch\.dict\([^)]*["'](HOME|USERPROFILE)["']/m.test(code))
|
|
15419
|
-
return null;
|
|
15420
|
-
const home = /\bhomedir\s*\(|\bPath\.home\s*\(|\bexpanduser\s*\(|\$\{?HOME\b|\$\{?USERPROFILE\b|\bprocess\.env\.(HOME|USERPROFILE)\b|["'`]~\/|["'`](?:file:\/\/)?\/(?:Users|home|root)\//;
|
|
15421
|
-
const locates = /["'`\/]\.[A-Za-z][\w-]*(?:[\/"'`]|$)|\b(?:import|require|source|spawn\w*|exec\w*|pathToFileURL|readFile\w*)\b/;
|
|
15422
|
-
for (const line2 of code.split(`
|
|
15423
|
-
`)) {
|
|
15424
|
-
if (/^\s*(?:await\s+)?(?:expect|assert\w*)\b/.test(line2))
|
|
15425
|
-
continue;
|
|
15426
|
-
if (home.test(line2) && locates.test(line2))
|
|
15427
|
-
return "resolves the code under test outside the repo via a home-directory path; target repo-relative paths (relative to this test file or the repo root) so the check exercises the change";
|
|
15428
|
-
}
|
|
15429
|
-
return null;
|
|
15430
|
-
}
|
|
15431
|
-
var readJson5 = (p) => {
|
|
15432
|
-
try {
|
|
15433
|
-
const v = parseJsonc(readFileSync46(p, "utf8"));
|
|
15434
|
-
return v && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
15435
|
-
} catch {
|
|
15436
|
-
return null;
|
|
15437
|
-
}
|
|
15438
|
-
};
|
|
15439
|
-
var init_conventions = () => {};
|
|
15440
|
-
|
|
15441
15606
|
// ../../loki-ts/src/engine10/stages/wall.ts
|
|
15442
15607
|
import { spawnSync as spawnSync7 } from "child_process";
|
|
15443
15608
|
import { existsSync as existsSync40, mkdirSync as mkdirSync25, mkdtempSync as mkdtempSync11, readFileSync as readFileSync47, readdirSync as readdirSync21, rmSync as rmSync19, writeFileSync as writeFileSync28 } from "fs";
|
|
15444
15609
|
import { tmpdir as tmpdir12 } from "os";
|
|
15445
|
-
import { dirname as dirname24, join as join60, relative as
|
|
15610
|
+
import { dirname as dirname24, join as join60, relative as relative11 } from "path";
|
|
15446
15611
|
|
|
15447
15612
|
class RealBaseTestRunner {
|
|
15448
15613
|
api;
|
|
@@ -15553,7 +15718,7 @@ async function wallAuthor(ctx, signal, retry) {
|
|
|
15553
15718
|
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" });
|
|
15554
15719
|
const tree = prior.intake?.tree;
|
|
15555
15720
|
const repomapText = repoMapText(ctx.repoDir, tree, repomapRef, WALL_MAP_MAX_LINES);
|
|
15556
|
-
const targetDir = wallTargetDir(ctx.repoDir, existingTests), pkg = loadProjectApi(ctx.repoDir)?.packageOf(`${
|
|
15721
|
+
const targetDir = wallTargetDir(ctx.repoDir, existingTests), pkg = loadProjectApi(ctx.repoDir)?.packageOf(`${relative11(ctx.repoDir, targetDir)}/x`);
|
|
15557
15722
|
const conv2 = readPackageConventions(join60(ctx.repoDir, pkg?.root ?? "."), pkg?.runner ?? null);
|
|
15558
15723
|
const cwd = mkdtempSync11(join60(tmpdir12(), "loki-e15-wall-"));
|
|
15559
15724
|
const wm = wallManifestFor(ctx.repoDir, tree, task);
|
|
@@ -15574,17 +15739,14 @@ async function wallAuthor(ctx, signal, retry) {
|
|
|
15574
15739
|
rmSync19(cwd, { recursive: true, force: true });
|
|
15575
15740
|
return done({ status: "failed", data: { iteration_ids: [iterationId], model }, reason: "wall session aborted, killed, or timed out", killed: true });
|
|
15576
15741
|
}
|
|
15742
|
+
const planText = typeof prior.plan?.plan === "string" ? prior.plan.plan : null, repoFiles = repoMap?.files ?? [];
|
|
15577
15743
|
const oor = () => readdirSync21(cwd).filter((f) => f.startsWith(WALL_PREFIX)).flatMap((name) => {
|
|
15578
|
-
const
|
|
15744
|
+
const text2 = readFileSync47(join60(cwd, name), "utf8"), why = outOfRepoTarget(text2) ?? phantomReason(phantomRepoPaths(text2, name, targetDir, ctx.repoDir, planText), repoFiles);
|
|
15579
15745
|
return why ? [{ name, why }] : [];
|
|
15580
15746
|
});
|
|
15581
15747
|
const bad1 = oor();
|
|
15582
15748
|
if (bad1.length > 0 && !signal.aborted)
|
|
15583
|
-
await ctx.sessions.run({ stage: "wall", brief: withStagePrefix(
|
|
15584
|
-
${bad1.map((b) => `- ${b.name}: ${b.why}`).join(`
|
|
15585
|
-
`)}`, `Point every reference at the repository code with repo-relative paths (for example join(import.meta.dir, "..", "<repo path>") or the equivalent for this runner). Do not read the home directory, $HOME or an environment variable that falls back to one. Write nothing else.`].join(`
|
|
15586
|
-
|
|
15587
|
-
`)), tier: "development", model, iterationId: `${iterationId}-oor`, limitS: wallLimitS(sz.size), signal, cwd });
|
|
15749
|
+
await ctx.sessions.run({ stage: "wall", brief: withStagePrefix(outOfRepoReask("Rewrite these Wall files in place, keeping the same names and acceptance coverage.", bad1)), tier: "development", model, iterationId: `${iterationId}-oor`, limitS: wallLimitS(sz.size), signal, cwd });
|
|
15588
15750
|
const oorBad = new Map(oor().map((b) => [b.name, b.why])), all = readdirSync21(cwd).filter((f) => f.startsWith(WALL_PREFIX)), held = stashHoldout({ runId: ctx.runId, repoDir: ctx.repoDir, srcDir: cwd, targetDir, names: all.filter((n2) => !oorBad.has(n2) && !conventionViolation(conv2, n2, readFileSync47(join60(cwd, n2), "utf8"))), runnerOf: (n2) => guessRunner(n2, runners) }), generated = all.filter((n2) => !held?.names.has(n2));
|
|
15589
15751
|
const sealedDir = join60(ctx.runDir, "wall");
|
|
15590
15752
|
if (generated.length > 0)
|
|
@@ -15627,7 +15789,7 @@ function* installCore(ctx, a, baseDir, opts) {
|
|
|
15627
15789
|
sealedFiles.push({ path: dest, sha256: sha2562(content) });
|
|
15628
15790
|
readOnlyFiles.push({ path: dest, content });
|
|
15629
15791
|
if (runner)
|
|
15630
|
-
wallTests.push({ runner, path:
|
|
15792
|
+
wallTests.push({ runner, path: relative11(ctx.repoDir, dest) });
|
|
15631
15793
|
}
|
|
15632
15794
|
ctx.wallSealed = true;
|
|
15633
15795
|
ctx.emit("wall.sealed", "wall", { files: sealedFiles, ...a.manifestSha256 ? { manifest_sha256: a.manifestSha256 } : {} });
|
|
@@ -15712,9 +15874,9 @@ var init_wall = __esm(() => {
|
|
|
15712
15874
|
|
|
15713
15875
|
// ../../loki-ts/src/e10ext/discard.ts
|
|
15714
15876
|
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";
|
|
15715
|
-
import { dirname as dirname25, join as join61, relative as
|
|
15877
|
+
import { dirname as dirname25, join as join61, relative as relative12, sep as sep14 } from "path";
|
|
15716
15878
|
function safeRestore(repoDir, f, want, mode) {
|
|
15717
|
-
const root = realpathSync23(repoDir), fp = join61(root, f), rel =
|
|
15879
|
+
const root = realpathSync23(repoDir), fp = join61(root, f), rel = relative12(root, dirname25(fp));
|
|
15718
15880
|
if (rel.startsWith(".."))
|
|
15719
15881
|
throw new Error("outside repo");
|
|
15720
15882
|
let cur = root;
|
|
@@ -15839,7 +16001,7 @@ var init_commit_filter = __esm(() => {
|
|
|
15839
16001
|
});
|
|
15840
16002
|
|
|
15841
16003
|
// ../../loki-ts/src/e10ext/scope.ts
|
|
15842
|
-
import { basename as
|
|
16004
|
+
import { basename as basename24, dirname as dirname27 } from "path";
|
|
15843
16005
|
function contractText(o) {
|
|
15844
16006
|
const c = o.intake?.contract_snapshot?.contract;
|
|
15845
16007
|
return Array.isArray(c?.criteria) ? c.criteria.map((x) => typeof x?.text === "string" ? x.text : "").join(`
|
|
@@ -15854,7 +16016,7 @@ function outsideScope(o, staged) {
|
|
|
15854
16016
|
${typeof o.intake?.task === "string" ? o.intake.task : ""}
|
|
15855
16017
|
${contractText(o)}`, pre = o.intake?.preexisting_dirty ?? {};
|
|
15856
16018
|
const toks = surfaceTokens(text2), plannedDirs = new Set(rel.map((r) => dirname27(r)).filter((d) => d !== "."));
|
|
15857
|
-
return staged.filter(({ st, f }) => st !== "A" && !isTestFile(f) && !Object.hasOwn(pre, f) && !rel.includes(f) && !mentions(text2, f) && !mentions(text2,
|
|
16019
|
+
return staged.filter(({ st, f }) => st !== "A" && !isTestFile(f) && !Object.hasOwn(pre, f) && !rel.includes(f) && !mentions(text2, f) && !mentions(text2, basename24(f)) && !plannedDirs.has(dirname27(f)) && !dirSegs(f).some((d) => toks.has(d))).map(({ f }) => f);
|
|
15858
16020
|
}
|
|
15859
16021
|
function flagOutsideScope(o, staged) {
|
|
15860
16022
|
const unit = unitFlags(staged, process.env, o.intake?.preexisting_dirty ?? {});
|
|
@@ -16481,7 +16643,7 @@ var init_seal_group = __esm(() => {
|
|
|
16481
16643
|
|
|
16482
16644
|
// ../../loki-ts/src/supply/supply_guard.ts
|
|
16483
16645
|
import { existsSync as existsSync46, readFileSync as readFileSync54, statSync as statSync22 } from "fs";
|
|
16484
|
-
import { basename as
|
|
16646
|
+
import { basename as basename25, join as join68 } from "path";
|
|
16485
16647
|
function supplyEnabled(env) {
|
|
16486
16648
|
return env["LOKI_SUPPLY_GUARD"] !== "0";
|
|
16487
16649
|
}
|
|
@@ -16493,7 +16655,7 @@ function supplyVerdict(verdict, r) {
|
|
|
16493
16655
|
return r.blocked && verdict === "VERIFIED" ? "FAILED" : verdict;
|
|
16494
16656
|
}
|
|
16495
16657
|
function isManifestPath(path) {
|
|
16496
|
-
return
|
|
16658
|
+
return MANIFESTS2.test(basename25(path));
|
|
16497
16659
|
}
|
|
16498
16660
|
function readDeclared(repoDir) {
|
|
16499
16661
|
const p = join68(repoDir, ".loki", DECLARED_FILE);
|
|
@@ -16691,7 +16853,7 @@ async function supplyGuard(repoDir, changedFiles2, declared, env, opts = {}) {
|
|
|
16691
16853
|
}
|
|
16692
16854
|
return { block: { guard: "v2", warn_age_days: MIN_AGE_DAYS, fail_age_days: failAge, declared: declared.deps.length, entries }, notProven, blocked };
|
|
16693
16855
|
}
|
|
16694
|
-
var MIN_AGE_DAYS = 7, DECLARED_FILE = "supply-declared.json", MAX_CHECKED = 50, MAX_DECLARED = 200, MAX_FILE_BYTES, DAY_MS = 86400000,
|
|
16856
|
+
var MIN_AGE_DAYS = 7, DECLARED_FILE = "supply-declared.json", MAX_CHECKED = 50, MAX_DECLARED = 200, MAX_FILE_BYTES, DAY_MS = 86400000, MANIFESTS2, ECO, NAME2, defaultResolver = async (dep, cwd) => {
|
|
16695
16857
|
const argv = {
|
|
16696
16858
|
npm: ["npm", "view", dep.name, "time.created", "--json"],
|
|
16697
16859
|
pypi: ["pip", "index", "versions", "--pre", "--ignore-requires-python", dep.name],
|
|
@@ -16717,7 +16879,7 @@ var MIN_AGE_DAYS = 7, DECLARED_FILE = "supply-declared.json", MAX_CHECKED = 50,
|
|
|
16717
16879
|
var init_supply_guard = __esm(() => {
|
|
16718
16880
|
init_shell();
|
|
16719
16881
|
MAX_FILE_BYTES = 64 * 1024;
|
|
16720
|
-
|
|
16882
|
+
MANIFESTS2 = /^(package\.json|package-lock\.json|npm-shrinkwrap\.json|yarn\.lock|pnpm-lock\.yaml|bun\.lockb?|requirements.*\.txt|pyproject\.toml|poetry\.lock|uv\.lock|Pipfile|Pipfile\.lock|go\.mod|go\.sum|Cargo\.toml|Cargo\.lock|Gemfile|Gemfile\.lock|composer\.json|composer\.lock|pom\.xml|build\.gradle(\.kts)?)$/;
|
|
16721
16883
|
ECO = { npm: "npm", node: "npm", pypi: "pypi", pip: "pypi", python: "pypi", cargo: "cargo", crates: "cargo", go: "go", golang: "go" };
|
|
16722
16884
|
NAME2 = /^[A-Za-z0-9@][A-Za-z0-9@._/~+-]{0,213}$/;
|
|
16723
16885
|
PUBLIC_HOSTS = new Set(["registry.npmjs.org", "registry.npmjs.com", "registry.yarnpkg.com", "npmjs.com", "npmjs.org", "pypi.org", "pypi.python.org", "files.pythonhosted.org", "crates.io", "index.crates.io", "static.crates.io", "proxy.golang.org", "golang.org", "pkg.go.dev"]);
|
|
@@ -16726,7 +16888,7 @@ var init_supply_guard = __esm(() => {
|
|
|
16726
16888
|
// ../../loki-ts/src/engine10/stages/seal.ts
|
|
16727
16889
|
import { createHash as createHash18 } from "crypto";
|
|
16728
16890
|
import { existsSync as existsSync47, readdirSync as readdirSync24, mkdirSync as mkdirSync31, readFileSync as readFileSync55 } from "fs";
|
|
16729
|
-
import { basename as
|
|
16891
|
+
import { basename as basename26, isAbsolute as isAbsolute12, join as join69, relative as relative13 } from "path";
|
|
16730
16892
|
function receiptSha256(r) {
|
|
16731
16893
|
const { verification: _v, receipt_sha256: _h, ...body } = r;
|
|
16732
16894
|
return sha2562(canonicalJson(body));
|
|
@@ -16798,8 +16960,8 @@ function renderReceiptMd(r) {
|
|
|
16798
16960
|
`);
|
|
16799
16961
|
}
|
|
16800
16962
|
var 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) => {
|
|
16801
|
-
const r =
|
|
16802
|
-
return r.startsWith("..") ||
|
|
16963
|
+
const r = relative13(ctx.repoDir, join69(ctx.runDir, "receipt.json"));
|
|
16964
|
+
return r.startsWith("..") || isAbsolute12(r) ? `.loki/runs/${ctx.runId}/receipt.json` : r;
|
|
16803
16965
|
}, commitStage, wallGreenOnBaseOf = (o) => {
|
|
16804
16966
|
const b = o.wall?.base_run ?? {};
|
|
16805
16967
|
return typeof b.pass === "number" && b.pass > 0 && b.fail === 0 && (typeof b.not_run === "number" ? b.not_run : 0) === 0;
|
|
@@ -16834,6 +16996,7 @@ var init_seal = __esm(() => {
|
|
|
16834
16996
|
init_hooks();
|
|
16835
16997
|
init_atomic();
|
|
16836
16998
|
init_safe_git();
|
|
16999
|
+
init_base_guard();
|
|
16837
17000
|
commitStage = {
|
|
16838
17001
|
name: "commit",
|
|
16839
17002
|
...STAGE_BUDGETS.commit,
|
|
@@ -16888,7 +17051,7 @@ var init_seal = __esm(() => {
|
|
|
16888
17051
|
for (let i = 0;i + 1 < rawDiff.length; i += 2)
|
|
16889
17052
|
if ((rawDiff[i].trim().split(" ").pop() ?? "") !== "A" && isTestFile(rawDiff[i + 1]))
|
|
16890
17053
|
weakTests.push(rawDiff[i + 1]);
|
|
16891
|
-
const rcNotes = diffOk ? runnerConfigNotes(ctx.repoDir, ctx.baseSha, head, rawDiff.filter((_, i) => i % 2 === 1), signal) : [];
|
|
17054
|
+
const rcNotes = diffOk ? [...runnerConfigNotes(ctx.repoDir, ctx.baseSha, head, rawDiff.filter((_, i) => i % 2 === 1), signal), ...addedSymlinkNotes(rawDiff, str4(o.plan?.plan))] : [];
|
|
16892
17055
|
const grp = sealGroup(ctx.runDir, receiptSha256);
|
|
16893
17056
|
const vraw = Array.isArray(o.verify?.checks) ? o.verify.checks : [], executed = hasExecutedProof(vraw), proof = process.env["LOKI_EXOGENOUS_PROOF"] === "0" ? executed : hasExogenousProof(vraw, pctx);
|
|
16894
17057
|
const uncoveredAfterLimit = o.implement?.exit === "killed" ? strs2(o.verify?.uncovered_changed) : [];
|
|
@@ -16917,7 +17080,7 @@ var init_seal = __esm(() => {
|
|
|
16917
17080
|
notProven.add(`Wall test not executed: ${wallNotRun} file(s), no reason recorded`);
|
|
16918
17081
|
if (wallNotRun > 0) {
|
|
16919
17082
|
try {
|
|
16920
|
-
const kept = new Set((Array.isArray(o.wall?.files) ? o.wall.files : []).map((f) =>
|
|
17083
|
+
const kept = new Set((Array.isArray(o.wall?.files) ? o.wall.files : []).map((f) => basename26(String(f.path))));
|
|
16921
17084
|
for (const n3 of readdirSync24(join69(ctx.runDir, "wall")).sort())
|
|
16922
17085
|
if (!kept.has(n3))
|
|
16923
17086
|
notProven.add(`wall test discarded: ${n3} (not_run)`);
|
|
@@ -17093,7 +17256,7 @@ var init_seal = __esm(() => {
|
|
|
17093
17256
|
|
|
17094
17257
|
// ../../loki-ts/src/util/composite_seal.ts
|
|
17095
17258
|
import { existsSync as existsSync48, readFileSync as readFileSync56 } from "fs";
|
|
17096
|
-
import { basename as
|
|
17259
|
+
import { basename as basename27, dirname as dirname31, join as join70 } from "path";
|
|
17097
17260
|
function logProblem(runDir, integ) {
|
|
17098
17261
|
if (typeof integ["log_sha256"] !== "string")
|
|
17099
17262
|
return null;
|
|
@@ -17216,7 +17379,7 @@ var init_keys_cmd = __esm(() => {
|
|
|
17216
17379
|
|
|
17217
17380
|
// ../../loki-ts/src/engine10/verify_cmd.ts
|
|
17218
17381
|
import { existsSync as existsSync49, readFileSync as readFileSync57, renameSync as renameSync14, statSync as statSync24, writeFileSync as writeFileSync33 } from "fs";
|
|
17219
|
-
import { basename as
|
|
17382
|
+
import { basename as basename28, dirname as dirname32, join as join71 } from "path";
|
|
17220
17383
|
import { createHash as createHash19, createPublicKey as createPublicKey4, verify as verify4 } from "crypto";
|
|
17221
17384
|
function pubFor(kid, given) {
|
|
17222
17385
|
if (given)
|
|
@@ -17399,7 +17562,7 @@ var init_verify_cmd = __esm(() => {
|
|
|
17399
17562
|
|
|
17400
17563
|
// src/server/app.ts
|
|
17401
17564
|
import { existsSync as existsSync51, readFileSync as readFileSync60, statSync as statSync25 } from "fs";
|
|
17402
|
-
import { join as join74, resolve as
|
|
17565
|
+
import { join as join74, resolve as resolve18, sep as sep16 } from "path";
|
|
17403
17566
|
|
|
17404
17567
|
// node_modules/hono/dist/request/constants.js
|
|
17405
17568
|
var GET_MATCH_RESULT = Symbol();
|
|
@@ -28490,8 +28653,8 @@ function createApp(opts) {
|
|
|
28490
28653
|
}
|
|
28491
28654
|
if (!uiDir || p.startsWith("/v1/"))
|
|
28492
28655
|
return c.json({ error: "not found" }, 404);
|
|
28493
|
-
const root =
|
|
28494
|
-
const f =
|
|
28656
|
+
const root = resolve18(uiDir);
|
|
28657
|
+
const f = resolve18(root, `.${p}`);
|
|
28495
28658
|
if (f.startsWith(root + sep16) && existsSync51(f) && statSync25(f).isFile())
|
|
28496
28659
|
return new Response(Bun.file(f));
|
|
28497
28660
|
if (/\.[a-z0-9]+$/i.test(p))
|