loki-mode 11.17.83 → 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 +3 -2
- package/docs/v10/PROGRESS.md +3 -0
- package/loki-ts/dist/loki.js +1079 -1079
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/packages/control-plane/dist/server.js +332 -330
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/web-app/dist/assets/{AdminPage-CrFXPtYq.js → AdminPage-K5ByrLR9.js} +1 -1
- package/web-app/dist/assets/{Avatar-ByHPLzy-.js → Avatar-YgkUcdSY.js} +1 -1
- package/web-app/dist/assets/{Badge-Cv86Tg1z.js → Badge-BPSEuhap.js} +1 -1
- package/web-app/dist/assets/{Button-Cmt4rAI6.js → Button-B9U75GxN.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-C5oGG7HK.js → CockpitPage-DsfWn1by.js} +1 -1
- package/web-app/dist/assets/{ComparePage-BLHQkb2H.js → ComparePage-Bw5ksH0K.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-CFYb0Cvs.js → ErrorBoundary-CO95MTCp.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-f7UV0iq8.js → EvidenceReceiptPanel-QOtNfGPr.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-B9naEGop.js → GitHubIssuesPanel-Czdh0zJD.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-D_Sdx1xa.js → GitHubPRsPanel-DyxFGyfo.js} +1 -1
- package/web-app/dist/assets/{HomePage-fgOLpLKO.js → HomePage-DlyIQtiu.js} +2 -2
- package/web-app/dist/assets/{LoginPage-5GbmfJoR.js → LoginPage-BCugtLMp.js} +1 -1
- package/web-app/dist/assets/{MagicPage-CuBB-UdE.js → MagicPage-BNfWXXtj.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-CcDxBoQB.js → MetricsPage-aBjuM4A_.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-BRay4BL5.js → NotFoundPage-BCOPrXwc.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-Du8YJlry.js → ProjectPage-CQckLxB6.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage--psgDFsh.js → ProjectsPage-xgEbC4Gz.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-C4D9Jar9.js → SettingsPage-UVrDGxdY.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-BHTTqg8U.js → ShowcasePage-B2Xoipg-.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-BPVW2bM6.js → SystemSettingsPage-CgLRefdv.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-D2XZA8JP.js → TeamsPage-Cw8Hj66k.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-BT5ReLll.js → TemplatesPage-CaCBUUO5.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-CG-tEIma.js → TerminalOutput-B7m2HRNn.js} +1 -1
- package/web-app/dist/assets/{activity-D4VfYw_h.js → activity-CkeOgiXm.js} +1 -1
- package/web-app/dist/assets/{bell-AnG3l9wT.js → bell-DKaU63My.js} +1 -1
- package/web-app/dist/assets/{bot-CxMiwdYy.js → bot-CraPUnae.js} +1 -1
- package/web-app/dist/assets/{check-BrO9f5gl.js → check-BjJbXEmH.js} +1 -1
- package/web-app/dist/assets/{chevron-left-HpEtIo4e.js → chevron-left-_x9ovbIV.js} +1 -1
- package/web-app/dist/assets/{circle-alert-S__4Lj5Y.js → circle-alert-DYrIIc9A.js} +1 -1
- package/web-app/dist/assets/{clock-87ZkFFKd.js → clock-07ChPrGQ.js} +1 -1
- package/web-app/dist/assets/{cloud-CaoiXqrq.js → cloud-UZrr1T4k.js} +1 -1
- package/web-app/dist/assets/{code-xml-Djv6HpN2.js → code-xml-jmlsXp32.js} +1 -1
- package/web-app/dist/assets/{database-QSkMsaL0.js → database-Cw9NK9yy.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-DsIbt7E9.js → dollar-sign-C_gtNZU_.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-DQY_EKG0.js → file-code-corner-PMk7fRz9.js} +1 -1
- package/web-app/dist/assets/{file-plus-CeFRVlCc.js → file-plus-DlZs6Btl.js} +1 -1
- package/web-app/dist/assets/{globe-CYIZDx5y.js → globe-C9cpOvdr.js} +1 -1
- package/web-app/dist/assets/{hammer-QPHdCfpp.js → hammer-DEk8bLDy.js} +1 -1
- package/web-app/dist/assets/{index-QoGQRWyx.js → index-Km0ikbi_.js} +3 -3
- package/web-app/dist/assets/{layers-CtcDx8kr.js → layers-4RjPXic5.js} +1 -1
- package/web-app/dist/assets/{loader-circle-CRP0ymla.js → loader-circle-DlUucLsL.js} +1 -1
- package/web-app/dist/assets/{lock-DC_-r7Nn.js → lock-Cul5JgtK.js} +1 -1
- package/web-app/dist/assets/{package-C0utKSsc.js → package-Vbp2mPNL.js} +1 -1
- package/web-app/dist/assets/{plus-DN-1ptdd.js → plus-DSMqkDx2.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-ClVo1weu.js → refresh-cw-Dzcn5O_r.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-buy6n4Dj.js → rotate-ccw-DRuS-hw1.js} +1 -1
- package/web-app/dist/assets/{scroll-text-fNFIg342.js → scroll-text-DSzR2Oet.js} +1 -1
- package/web-app/dist/assets/{server-JcjFhb66.js → server-CaA-i_3H.js} +1 -1
- package/web-app/dist/assets/{shield-alert-DGjhsZZQ.js → shield-alert-4whQzr0p.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-Cu9bXhPK.js → thumbs-up-CUCPAMhF.js} +1 -1
- package/web-app/dist/assets/{trash-2-DQh5erCE.js → trash-2-CJiX03EE.js} +1 -1
- package/web-app/dist/assets/{trending-down-DCQoOPWu.js → trending-down-ROoZX4P4.js} +1 -1
- package/web-app/dist/assets/{trending-up-Dj30VoUY.js → trending-up-Gi3o5rCK.js} +1 -1
- package/web-app/dist/assets/{upload-f7HNT6Li.js → upload-C5s98AFw.js} +1 -1
- package/web-app/dist/assets/{usePolling-T-0o6PGt.js → usePolling-DaEWx5La.js} +1 -1
- package/web-app/dist/assets/{user-9GLVvJkd.js → user-D4yDWC5X.js} +1 -1
- package/web-app/dist/index.html +1 -1
|
@@ -13902,6 +13902,258 @@ var init_secure_scan = __esm(() => {
|
|
|
13902
13902
|
// ../../loki-ts/src/runner/retry_class.ts
|
|
13903
13903
|
var init_retry_class = () => {};
|
|
13904
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
|
+
|
|
13905
14157
|
// ../../loki-ts/src/version.ts
|
|
13906
14158
|
var init_version = __esm(() => {
|
|
13907
14159
|
init_paths();
|
|
@@ -13998,9 +14250,9 @@ var init_route_block = __esm(() => {
|
|
|
13998
14250
|
// ../../loki-ts/src/features/visual_evidence.ts
|
|
13999
14251
|
import { spawn as spawn8 } from "child_process";
|
|
14000
14252
|
import { createHash as createHash14, randomBytes as randomBytes6 } from "crypto";
|
|
14001
|
-
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";
|
|
14002
14254
|
import { createServer } from "net";
|
|
14003
|
-
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";
|
|
14004
14256
|
function routeFor(file) {
|
|
14005
14257
|
let r = file.replace(/^(?:.*?\/)?(?:app|pages|src|public)\//, "").replace(/^(?:routes|pages)\//, "");
|
|
14006
14258
|
r = r.replace(/\.(?:html|jsx|tsx|vue|svelte)$/, "").replace(/\/?(?:page|index|\+page)$/, "");
|
|
@@ -14010,7 +14262,7 @@ function hashScreens(runDir, rels) {
|
|
|
14010
14262
|
const out2 = [];
|
|
14011
14263
|
for (const rel of rels) {
|
|
14012
14264
|
try {
|
|
14013
|
-
out2.push({ path: rel, sha256: sha256File(
|
|
14265
|
+
out2.push({ path: rel, sha256: sha256File(join54(runDir, rel)) });
|
|
14014
14266
|
} catch {}
|
|
14015
14267
|
}
|
|
14016
14268
|
return out2;
|
|
@@ -14021,16 +14273,16 @@ function checkScreens(runDir, screens) {
|
|
|
14021
14273
|
for (const s of screens) {
|
|
14022
14274
|
if (typeof s?.path !== "string" || typeof s.sha256 !== "string")
|
|
14023
14275
|
return "evidence_screens entry is malformed";
|
|
14024
|
-
if (
|
|
14276
|
+
if (isAbsolute9(s.path) || normalize3(s.path).startsWith(".."))
|
|
14025
14277
|
return `evidence screenshot path escapes the evidence dir: ${s.path}`;
|
|
14026
|
-
const file =
|
|
14278
|
+
const file = join54(runDir, s.path);
|
|
14027
14279
|
let cur = runDir;
|
|
14028
14280
|
for (const seg of normalize3(s.path).split(sep13)) {
|
|
14029
|
-
cur =
|
|
14281
|
+
cur = join54(cur, seg);
|
|
14030
14282
|
if (isSymlink(cur))
|
|
14031
14283
|
return `evidence screenshot path is a symlink: ${s.path}`;
|
|
14032
14284
|
}
|
|
14033
|
-
if (!
|
|
14285
|
+
if (!existsSync34(file))
|
|
14034
14286
|
return `evidence screenshot is missing: ${s.path}`;
|
|
14035
14287
|
if (!isRegularFile(file))
|
|
14036
14288
|
return `evidence screenshot is not a regular file: ${s.path}`;
|
|
@@ -14073,11 +14325,11 @@ async function waitUp(url, ms, signal) {
|
|
|
14073
14325
|
}
|
|
14074
14326
|
function openapiPaths(repoDir) {
|
|
14075
14327
|
for (const f of ["openapi.json", "openapi.yaml", "openapi.yml", "swagger.json"]) {
|
|
14076
|
-
const p =
|
|
14077
|
-
if (!
|
|
14328
|
+
const p = join54(repoDir, f);
|
|
14329
|
+
if (!existsSync34(p))
|
|
14078
14330
|
continue;
|
|
14079
14331
|
try {
|
|
14080
|
-
const txt =
|
|
14332
|
+
const txt = readFileSync43(p, "utf8");
|
|
14081
14333
|
const paths = f.endsWith(".json") ? Object.keys(JSON.parse(txt).paths ?? {}) : [...txt.matchAll(/^ {2}(\/[^\s:]*):\s*$/gm)].map((m) => m[1]);
|
|
14082
14334
|
return paths.filter((x) => !x.includes("{")).slice(0, 10);
|
|
14083
14335
|
} catch {
|
|
@@ -14091,24 +14343,24 @@ async function recordE2eMedia(repoDir, runDir, relDir, base, routes, ms, signal)
|
|
|
14091
14343
|
if (!pw || !pkg)
|
|
14092
14344
|
return { rels: [], skipped: "playwright e2e video and trace skipped: @playwright/test is not installed in the repo" };
|
|
14093
14345
|
try {
|
|
14094
|
-
const dir =
|
|
14346
|
+
const dir = join54(runDir, relDir, "e2e");
|
|
14095
14347
|
mkdirSync21(dir, { recursive: true });
|
|
14096
|
-
writeFileSync24(
|
|
14097
|
-
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" } };
|
|
14098
14350
|
`);
|
|
14099
|
-
if (!await shoot(pw, ["test", "--config",
|
|
14351
|
+
if (!await shoot(pw, ["test", "--config", join54(dir, "playwright.config.cjs")], repoDir, ms, signal))
|
|
14100
14352
|
return { rels: [], skipped: "playwright e2e video and trace skipped: the run failed or timed out" };
|
|
14101
14353
|
const rels = [];
|
|
14102
14354
|
const walk = (d) => {
|
|
14103
|
-
for (const e of
|
|
14104
|
-
const full =
|
|
14355
|
+
for (const e of readdirSync20(d, { withFileTypes: true })) {
|
|
14356
|
+
const full = join54(d, e.name);
|
|
14105
14357
|
if (e.isDirectory())
|
|
14106
14358
|
walk(full);
|
|
14107
14359
|
else if (e.isFile() && /\.(webm|zip)$/.test(e.name))
|
|
14108
|
-
rels.push(
|
|
14360
|
+
rels.push(join54(relDir, "e2e", relative9(dir, full)));
|
|
14109
14361
|
}
|
|
14110
14362
|
};
|
|
14111
|
-
walk(
|
|
14363
|
+
walk(join54(dir, "out"));
|
|
14112
14364
|
return rels.length > 0 ? { rels, skipped: null } : { rels, skipped: "playwright e2e video and trace skipped: no video or trace was produced" };
|
|
14113
14365
|
} catch (e) {
|
|
14114
14366
|
return { rels: [], skipped: `playwright e2e video and trace skipped: ${String(e?.message ?? e).slice(0, 120)}` };
|
|
@@ -14187,22 +14439,22 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
14187
14439
|
if (!visualEvidenceEnabled(opts.env))
|
|
14188
14440
|
return skip("LOKI_VISUAL_EVIDENCE is 0");
|
|
14189
14441
|
const api = loadProjectApi(repoDir), boot = isMultiRoot(api) ? api.uiBoot() : null;
|
|
14190
|
-
const appDir = boot ?
|
|
14191
|
-
const pkgPath =
|
|
14442
|
+
const appDir = boot ? join54(repoDir, boot.boot.cwd) : repoDir;
|
|
14443
|
+
const pkgPath = join54(appDir, "package.json");
|
|
14192
14444
|
let script = null;
|
|
14193
14445
|
if (!boot) {
|
|
14194
|
-
if (!
|
|
14195
|
-
const subs = ["backend", "frontend"].filter((d) =>
|
|
14446
|
+
if (!existsSync34(pkgPath)) {
|
|
14447
|
+
const subs = ["backend", "frontend"].filter((d) => existsSync34(join54(repoDir, d, "package.json")));
|
|
14196
14448
|
const has2 = (d) => {
|
|
14197
14449
|
try {
|
|
14198
|
-
return pickScript(JSON.parse(
|
|
14450
|
+
return pickScript(JSON.parse(readFileSync43(join54(repoDir, d, "package.json"), "utf8"))) !== null;
|
|
14199
14451
|
} catch {
|
|
14200
14452
|
return false;
|
|
14201
14453
|
}
|
|
14202
14454
|
};
|
|
14203
14455
|
return skip(noRootReason(subs, subs.filter((d) => !has2(d))));
|
|
14204
14456
|
}
|
|
14205
|
-
script = pickScript(JSON.parse(
|
|
14457
|
+
script = pickScript(JSON.parse(readFileSync43(pkgPath, "utf8")));
|
|
14206
14458
|
if (!script)
|
|
14207
14459
|
return skip("no dev, preview or start script");
|
|
14208
14460
|
}
|
|
@@ -14229,20 +14481,20 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
14229
14481
|
}
|
|
14230
14482
|
if (!await waitUp(base, left(), signal))
|
|
14231
14483
|
return skip(aborted() ? "aborted" : `${script} server did not answer within ${Math.round(budget / 1000)}s`);
|
|
14232
|
-
const evRoot =
|
|
14484
|
+
const evRoot = join54(runDir, "evidence");
|
|
14233
14485
|
if (isSymlink(evRoot))
|
|
14234
14486
|
return skip("evidence dir is a symlink");
|
|
14235
14487
|
mkdirSync21(evRoot, { recursive: true });
|
|
14236
14488
|
if (pages.length > 0) {
|
|
14237
|
-
const rel0 =
|
|
14238
|
-
mkdirSync21(
|
|
14489
|
+
const rel0 = join54("evidence", randomBytes6(6).toString("hex"));
|
|
14490
|
+
mkdirSync21(join54(runDir, rel0));
|
|
14239
14491
|
const rels = [];
|
|
14240
14492
|
for (const route of [...new Set(pages.map(routeFor))].slice(0, opts.maxRoutes ?? MAX_ROUTES)) {
|
|
14241
14493
|
if (aborted() || left() <= 0)
|
|
14242
14494
|
break;
|
|
14243
|
-
const rel =
|
|
14244
|
-
const ok = await shoot(pw, ["screenshot", `${base}${route}`,
|
|
14245
|
-
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)))
|
|
14246
14498
|
rels.push(rel);
|
|
14247
14499
|
}
|
|
14248
14500
|
if (aborted())
|
|
@@ -14267,9 +14519,9 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
14267
14519
|
}
|
|
14268
14520
|
if (aborted())
|
|
14269
14521
|
return skip("aborted");
|
|
14270
|
-
const hdir =
|
|
14522
|
+
const hdir = join54(evRoot, randomBytes6(6).toString("hex"));
|
|
14271
14523
|
mkdirSync21(hdir);
|
|
14272
|
-
writeFileSync24(
|
|
14524
|
+
writeFileSync24(join54(hdir, "http.json"), JSON.stringify(rows, null, 2) + `
|
|
14273
14525
|
`);
|
|
14274
14526
|
return { screens: [], http: true, skipped: null };
|
|
14275
14527
|
} catch (e) {
|
|
@@ -14296,14 +14548,14 @@ async function sealEvidence(repoDir, runDir, o, notProven, signal, emit) {
|
|
|
14296
14548
|
function receiptScreensProblem(receiptPath, receipt) {
|
|
14297
14549
|
if (visualGateEnabled() && typeof receipt["evidence_failed"] === "string")
|
|
14298
14550
|
return `visual evidence failed (LOKI_VISUAL_GATE=1): ${receipt["evidence_failed"]}`;
|
|
14299
|
-
return receipt["evidence_screens"] === undefined ? null : checkScreens(
|
|
14551
|
+
return receipt["evidence_screens"] === undefined ? null : checkScreens(dirname20(receiptPath), receipt["evidence_screens"]);
|
|
14300
14552
|
}
|
|
14301
|
-
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(
|
|
14302
|
-
const bin =
|
|
14303
|
-
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;
|
|
14304
14556
|
}, playwrightTestPkg = (repoDir) => {
|
|
14305
|
-
const d =
|
|
14306
|
-
return
|
|
14557
|
+
const d = join54(repoDir, "node_modules", "@playwright", "test");
|
|
14558
|
+
return existsSync34(join54(d, "package.json")) ? d : null;
|
|
14307
14559
|
}, e2eSpecSource = (pkgDir, base, routes) => `const { test } = require(${JSON.stringify(pkgDir)});
|
|
14308
14560
|
test("loki e2e walkthrough", async ({ page }) => {
|
|
14309
14561
|
for (const r of ${JSON.stringify(routes)}) { await page.goto(${JSON.stringify(base)} + r); await page.waitForLoadState("load"); }
|
|
@@ -14349,7 +14601,7 @@ var init_outbox = __esm(() => {
|
|
|
14349
14601
|
});
|
|
14350
14602
|
|
|
14351
14603
|
// ../../loki-ts/src/engine10/stages/pr.ts
|
|
14352
|
-
import { join as
|
|
14604
|
+
import { join as join55 } from "path";
|
|
14353
14605
|
var DEFAULT_PUSH_SH, DEFAULT_PUSH_GITLAB_SH;
|
|
14354
14606
|
var init_pr = __esm(() => {
|
|
14355
14607
|
init_types();
|
|
@@ -14368,20 +14620,20 @@ var init_pr = __esm(() => {
|
|
|
14368
14620
|
init_receipt_surface();
|
|
14369
14621
|
init_yaml_key();
|
|
14370
14622
|
init_outbox();
|
|
14371
|
-
DEFAULT_PUSH_SH =
|
|
14372
|
-
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");
|
|
14373
14625
|
});
|
|
14374
14626
|
|
|
14375
14627
|
// ../../loki-ts/src/util/pr_lessons.ts
|
|
14376
|
-
import { existsSync as
|
|
14377
|
-
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";
|
|
14378
14630
|
import { createHash as createHash15 } from "crypto";
|
|
14379
14631
|
function loadLessons(repoDir) {
|
|
14380
14632
|
const p = lessonsPath(repoDir);
|
|
14381
|
-
if (!
|
|
14633
|
+
if (!existsSync35(p))
|
|
14382
14634
|
return [];
|
|
14383
14635
|
try {
|
|
14384
|
-
const j = JSON.parse(
|
|
14636
|
+
const j = JSON.parse(readFileSync44(p, "utf-8"));
|
|
14385
14637
|
return Array.isArray(j.lessons) ? j.lessons : [];
|
|
14386
14638
|
} catch {
|
|
14387
14639
|
return [];
|
|
@@ -14389,7 +14641,7 @@ function loadLessons(repoDir) {
|
|
|
14389
14641
|
}
|
|
14390
14642
|
function save(repoDir, lessons) {
|
|
14391
14643
|
const p = lessonsPath(repoDir);
|
|
14392
|
-
mkdirSync22(
|
|
14644
|
+
mkdirSync22(dirname21(p), { recursive: true });
|
|
14393
14645
|
atomicWriteJson(p, { version: 2, lessons });
|
|
14394
14646
|
}
|
|
14395
14647
|
function appendReceiptFact(repoDir, f, now2 = () => new Date) {
|
|
@@ -14423,7 +14675,7 @@ function recordRunVerdict(repoDir, runId2, verdict) {
|
|
|
14423
14675
|
if (dirty)
|
|
14424
14676
|
save(repoDir, lessons);
|
|
14425
14677
|
}
|
|
14426
|
-
var lessonsPath = (repoDir) =>
|
|
14678
|
+
var lessonsPath = (repoDir) => join56(repoDir, ".loki", "memory", "semantic", "pr-lessons.json"), KINDS;
|
|
14427
14679
|
var init_pr_lessons = __esm(() => {
|
|
14428
14680
|
init_atomic();
|
|
14429
14681
|
init_safe_git();
|
|
@@ -14449,8 +14701,8 @@ var init_attempts = __esm(() => {
|
|
|
14449
14701
|
var init_mcp_config = () => {};
|
|
14450
14702
|
|
|
14451
14703
|
// ../../loki-ts/src/providers/claude_flags.ts
|
|
14452
|
-
import { existsSync as
|
|
14453
|
-
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";
|
|
14454
14706
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
14455
14707
|
function claudeFlagSupported(flag, helpText) {
|
|
14456
14708
|
const txt = helpText ?? _claudeHelpCache;
|
|
@@ -14497,14 +14749,14 @@ function leanReviewerFlags(opts = {}) {
|
|
|
14497
14749
|
}
|
|
14498
14750
|
function designArchetypesText() {
|
|
14499
14751
|
try {
|
|
14500
|
-
const moduleDir =
|
|
14752
|
+
const moduleDir = dirname22(fileURLToPath5(import.meta.url));
|
|
14501
14753
|
for (const rel of [
|
|
14502
14754
|
["..", "..", "..", "references", "design-archetypes.md"],
|
|
14503
14755
|
["..", "..", "references", "design-archetypes.md"]
|
|
14504
14756
|
]) {
|
|
14505
14757
|
const p = resolvePath(moduleDir, ...rel);
|
|
14506
|
-
if (
|
|
14507
|
-
return
|
|
14758
|
+
if (existsSync36(p))
|
|
14759
|
+
return readFileSync45(p, "utf8");
|
|
14508
14760
|
}
|
|
14509
14761
|
} catch {}
|
|
14510
14762
|
return "";
|
|
@@ -14589,14 +14841,14 @@ var init_providers = __esm(() => {
|
|
|
14589
14841
|
});
|
|
14590
14842
|
|
|
14591
14843
|
// ../../loki-ts/src/runner/router/route_record.ts
|
|
14592
|
-
import { existsSync as
|
|
14593
|
-
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";
|
|
14594
14846
|
function loadRouteRecord(runDir) {
|
|
14595
14847
|
try {
|
|
14596
|
-
const p =
|
|
14597
|
-
if (!
|
|
14848
|
+
const p = join57(runDir, ROUTE_RECORD_FILE);
|
|
14849
|
+
if (!existsSync37(p) || !lstatSync13(p).isFile())
|
|
14598
14850
|
return;
|
|
14599
|
-
const v = JSON.parse(
|
|
14851
|
+
const v = JSON.parse(readFileSync46(p, "utf8"));
|
|
14600
14852
|
return typeof v === "object" && v !== null && !Array.isArray(v) ? v : undefined;
|
|
14601
14853
|
} catch {
|
|
14602
14854
|
return;
|
|
@@ -14657,6 +14909,7 @@ var init_implement_route = __esm(() => {
|
|
|
14657
14909
|
var init_implement = __esm(() => {
|
|
14658
14910
|
init_install();
|
|
14659
14911
|
init_lean_prefix();
|
|
14912
|
+
init_conventions();
|
|
14660
14913
|
init_pr_lessons();
|
|
14661
14914
|
init_context();
|
|
14662
14915
|
init_model_downgrades();
|
|
@@ -14744,14 +14997,14 @@ __export(exports_deep, {
|
|
|
14744
14997
|
DEFAULT_SECRET_SCAN_SH: () => DEFAULT_SECRET_SCAN_SH,
|
|
14745
14998
|
DEFAULT_PUSH_SH: () => DEFAULT_PUSH_SH2
|
|
14746
14999
|
});
|
|
14747
|
-
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";
|
|
14748
15001
|
import { tmpdir as tmpdir10 } from "os";
|
|
14749
|
-
import { dirname as
|
|
15002
|
+
import { dirname as dirname23, join as join58 } from "path";
|
|
14750
15003
|
function sessionCouncil(sessions) {
|
|
14751
15004
|
return { async run(input, signal) {
|
|
14752
|
-
const cwd = mkdtempSync9(
|
|
15005
|
+
const cwd = mkdtempSync9(join58(tmpdir10(), "loki-deep-council-"));
|
|
14753
15006
|
try {
|
|
14754
|
-
writeFileSync27(
|
|
15007
|
+
writeFileSync27(join58(cwd, "diff.patch"), input.diff, "utf8");
|
|
14755
15008
|
const r = await sessions.run({
|
|
14756
15009
|
stage: "deep",
|
|
14757
15010
|
tier: "development",
|
|
@@ -14821,7 +15074,7 @@ ${r.stderr}`), lr = r.exitCode === 0 ? undefined : await harnessLoadReason({ rep
|
|
|
14821
15074
|
async function runAppBoot(ctx, opts, checks, notProven) {
|
|
14822
15075
|
let r;
|
|
14823
15076
|
try {
|
|
14824
|
-
r = await (opts.appProbe ?? appProbe)(ctx.repoDir,
|
|
15077
|
+
r = await (opts.appProbe ?? appProbe)(ctx.repoDir, join58(ctx.repoDir, ".loki"));
|
|
14825
15078
|
} catch (err) {
|
|
14826
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 };
|
|
14827
15080
|
}
|
|
@@ -14867,12 +15120,12 @@ async function runCouncilCheck(ctx, changed, baseSha, signal, opts, checks, notP
|
|
|
14867
15120
|
}
|
|
14868
15121
|
}
|
|
14869
15122
|
async function secureScanChanged(repoDir, changed, opts) {
|
|
14870
|
-
const dir = mkdtempSync9(
|
|
15123
|
+
const dir = mkdtempSync9(join58(tmpdir10(), "loki-deep-secure-"));
|
|
14871
15124
|
try {
|
|
14872
15125
|
for (const f of changed)
|
|
14873
|
-
if (
|
|
14874
|
-
mkdirSync24(
|
|
14875
|
-
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));
|
|
14876
15129
|
}
|
|
14877
15130
|
return await runSecureScan(dir, { ...opts.secureScanPath ? { scriptPath: opts.secureScanPath } : {}, timeoutMs: 60000 });
|
|
14878
15131
|
} finally {
|
|
@@ -14881,7 +15134,7 @@ async function secureScanChanged(repoDir, changed, opts) {
|
|
|
14881
15134
|
}
|
|
14882
15135
|
async function runSecretScan(ctx, changed, opts, checks, notProven) {
|
|
14883
15136
|
const scriptPath = opts.secretScanShPath ?? DEFAULT_SECRET_SCAN_SH, name = "security scan", cmd2 = "secret-scan.sh + secure-scan.py";
|
|
14884
|
-
if (!
|
|
15137
|
+
if (!existsSync38(scriptPath)) {
|
|
14885
15138
|
checks.push({ name, cmd: cmd2, result: "not_run", duration_s: 0 });
|
|
14886
15139
|
notProven.add(`not run: ${name} (secret-scan.sh not found)`);
|
|
14887
15140
|
return;
|
|
@@ -14892,7 +15145,7 @@ async function runSecretScan(ctx, changed, opts, checks, notProven) {
|
|
|
14892
15145
|
}
|
|
14893
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"';
|
|
14894
15147
|
const started = Date.now();
|
|
14895
|
-
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 });
|
|
14896
15149
|
const sec = await secureScanChanged(ctx.repoDir, changed, opts), gaps = [], reasons = [];
|
|
14897
15150
|
const hits = r.exitCode === 3 ? [] : r.stdout.split(`
|
|
14898
15151
|
`).map((l) => l.trim()).filter(Boolean), high = sec.findings.filter((f) => String(f.severity).toUpperCase() === "HIGH");
|
|
@@ -14933,7 +15186,7 @@ async function postResults(ctx, opts, checks, notProven, statusState) {
|
|
|
14933
15186
|
const prNumber = prUrl ? PR_NUMBER_RE.exec(prUrl)?.[1] : undefined;
|
|
14934
15187
|
if (prNumber) {
|
|
14935
15188
|
mkdirSync24(ctx.runDir, { recursive: true });
|
|
14936
|
-
const bodyFile =
|
|
15189
|
+
const bodyFile = join58(ctx.runDir, "deep-comment.md");
|
|
14937
15190
|
writeFileSync27(bodyFile, buildCommentBody(checks, notProven, statusState), "utf8");
|
|
14938
15191
|
const commentResult = await run(["bash", scriptPath, ...commentArgv(prNumber, bodyFile)], { cwd: ctx.repoDir, env, timeoutMs: 30000 });
|
|
14939
15192
|
if (commentResult.exitCode !== 0)
|
|
@@ -14988,7 +15241,7 @@ async function runDeep(ctx, signal, opts = {}) {
|
|
|
14988
15241
|
const sig = signReceipt(`${ctx.runId}-deep`, addendumSha256);
|
|
14989
15242
|
const addendum = { ...addendumBody, addendum_sha256: addendumSha256, verification: { jwt: sig.jwt, kid: sig.kid } };
|
|
14990
15243
|
mkdirSync24(ctx.runDir, { recursive: true });
|
|
14991
|
-
writeFileSync27(
|
|
15244
|
+
writeFileSync27(join58(ctx.runDir, "receipt-addendum-1.json"), JSON.stringify(addendum, null, 2) + `
|
|
14992
15245
|
`);
|
|
14993
15246
|
const pushNotProven = await postResults(ctx, opts, checks, notProvenList, statusState);
|
|
14994
15247
|
const allNotProven = [...notProvenList, ...pushNotProven];
|
|
@@ -15024,9 +15277,9 @@ var init_deep = __esm(() => {
|
|
|
15024
15277
|
});
|
|
15025
15278
|
|
|
15026
15279
|
// ../../loki-ts/src/engine10/stages/verify.ts
|
|
15027
|
-
import { existsSync as
|
|
15280
|
+
import { existsSync as existsSync39, mkdtempSync as mkdtempSync10, rmSync as rmSync18 } from "fs";
|
|
15028
15281
|
import { tmpdir as tmpdir11 } from "os";
|
|
15029
|
-
import { isAbsolute as
|
|
15282
|
+
import { isAbsolute as isAbsolute10, join as join59, relative as relative10 } from "path";
|
|
15030
15283
|
async function runOnce2(cmd2, args, cwd, signal, opts) {
|
|
15031
15284
|
if (!Bun.which(cmd2, { PATH: opts.path ?? process.env["PATH"] ?? "" }))
|
|
15032
15285
|
return { ok: false, missing: true, cut: false, out: "" };
|
|
@@ -15100,7 +15353,7 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal,
|
|
|
15100
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)) : [];
|
|
15101
15354
|
if (!(un.some(({ c }) => c.result === "fail" && c.ids?.length) || sus.length || zc.length) || signal.aborted)
|
|
15102
15355
|
return out2;
|
|
15103
|
-
const dir = mkdtempSync10(
|
|
15356
|
+
const dir = mkdtempSync10(join59(tmpdir11(), "e10-base-"));
|
|
15104
15357
|
const git4 = (args) => {
|
|
15105
15358
|
safeGit(ctx.repoDir, args, { stdio: "ignore", repoDrivers: true });
|
|
15106
15359
|
};
|
|
@@ -15139,7 +15392,7 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal,
|
|
|
15139
15392
|
return out2;
|
|
15140
15393
|
}
|
|
15141
15394
|
function isLokiModeRepo(repoDir) {
|
|
15142
|
-
return
|
|
15395
|
+
return existsSync39(join59(repoDir, "scripts", "select-tests.sh"));
|
|
15143
15396
|
}
|
|
15144
15397
|
async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
|
|
15145
15398
|
const { api, ...runOpts } = opts;
|
|
@@ -15161,9 +15414,9 @@ async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
|
|
|
15161
15414
|
}
|
|
15162
15415
|
for (const g of groupByPackage(api, ctx.repoDir, changed.filter((f) => /\.(ts|tsx|js|jsx)$/.test(f)))) {
|
|
15163
15416
|
const sfx = g.root === "." ? "" : `:${g.root}`, co = g.root === "." ? opts : { ...opts, cwd: g.cwd };
|
|
15164
|
-
if (
|
|
15417
|
+
if (existsSync39(join59(g.cwd, "tsconfig.json")))
|
|
15165
15418
|
await runCheck(ctx, `lint:tsc${sfx}`, "npx", ["--no-install", "tsc", "--noEmit", "-p", "."], signal, checks, { ...co, kind: "static" });
|
|
15166
|
-
if (ESLINT_CONFIGS.some((f) =>
|
|
15419
|
+
if (ESLINT_CONFIGS.some((f) => existsSync39(join59(g.cwd, f)))) {
|
|
15167
15420
|
const c = await runCheck(ctx, `lint:eslint${sfx}`, "npx", ["--no-install", "eslint", ...g.rel], signal, checks, { ...co, kind: "static" });
|
|
15168
15421
|
if (await excuseLint(ctx, signal, c, "eslint", "npx", ["--no-install", "eslint"], g.cwd, g.rel, co))
|
|
15169
15422
|
pre.push(c.name);
|
|
@@ -15178,7 +15431,7 @@ var CHECK_TIMEOUT_MS = 60000, excerpts, isHold = (c) => isHoldoutCheck(c.name),
|
|
|
15178
15431
|
return r.missing || r.cut ? null : r;
|
|
15179
15432
|
}, base: (f) => {
|
|
15180
15433
|
try {
|
|
15181
|
-
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"] });
|
|
15182
15435
|
} catch {
|
|
15183
15436
|
return null;
|
|
15184
15437
|
}
|
|
@@ -15243,7 +15496,7 @@ var init_verify = __esm(() => {
|
|
|
15243
15496
|
const impacted = ctx.tests.impacted(map, changed);
|
|
15244
15497
|
const changedTestFiles = map.tests.filter((t) => changed.includes(t.path));
|
|
15245
15498
|
const wall = ctx.outputs().wall ?? {};
|
|
15246
|
-
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));
|
|
15247
15500
|
const intake = ctx.outputs().intake, repoMap = loadRepoMap(intake?.repomap_ref), relevant2 = ctx.tests.impacted(map, namedFiles(intake?.task ?? "", repoMap));
|
|
15248
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 })) : []];
|
|
15249
15502
|
const tests = failedFirst(dedupeTests([...impacted, ...changedTestFiles, ...wallTests, ...relevant2]), ctx.outputs().verify?.checks);
|
|
@@ -15350,253 +15603,6 @@ ${x}` : c.cmd };
|
|
|
15350
15603
|
};
|
|
15351
15604
|
});
|
|
15352
15605
|
|
|
15353
|
-
// ../../loki-ts/src/project_model/conventions.ts
|
|
15354
|
-
import { existsSync as existsSync39, readdirSync as readdirSync20, readFileSync as readFileSync46 } from "fs";
|
|
15355
|
-
import { basename as basename23, dirname as dirname23, isAbsolute as isAbsolute10, join as join59, relative as relative10, resolve as resolve17 } from "path";
|
|
15356
|
-
function parseJsonc(text2) {
|
|
15357
|
-
let out2 = "", i = 0;
|
|
15358
|
-
while (i < text2.length) {
|
|
15359
|
-
const c = text2[i], n2 = text2[i + 1];
|
|
15360
|
-
if (c === '"') {
|
|
15361
|
-
let j = i + 1;
|
|
15362
|
-
while (j < text2.length && text2[j] !== '"')
|
|
15363
|
-
j += text2[j] === "\\" ? 2 : 1;
|
|
15364
|
-
out2 += text2.slice(i, j + 1);
|
|
15365
|
-
i = j + 1;
|
|
15366
|
-
} else if (c === "/" && n2 === "/") {
|
|
15367
|
-
while (i < text2.length && text2[i] !== `
|
|
15368
|
-
`)
|
|
15369
|
-
i++;
|
|
15370
|
-
} else if (c === "/" && n2 === "*") {
|
|
15371
|
-
const e = text2.indexOf("*/", i + 2);
|
|
15372
|
-
i = e < 0 ? text2.length : e + 2;
|
|
15373
|
-
} else {
|
|
15374
|
-
out2 += c;
|
|
15375
|
-
i++;
|
|
15376
|
-
}
|
|
15377
|
-
}
|
|
15378
|
-
return JSON.parse(out2.replace(/,(\s*[}\]])/g, "$1"));
|
|
15379
|
-
}
|
|
15380
|
-
function moduleOf(file, depth = 0) {
|
|
15381
|
-
const j = readJson5(file);
|
|
15382
|
-
if (!j || depth > 4)
|
|
15383
|
-
return null;
|
|
15384
|
-
const m = j.compilerOptions?.module;
|
|
15385
|
-
if (typeof m === "string")
|
|
15386
|
-
return m.toLowerCase();
|
|
15387
|
-
const ext = typeof j.extends === "string" ? j.extends : null;
|
|
15388
|
-
if (!ext || !ext.startsWith("."))
|
|
15389
|
-
return null;
|
|
15390
|
-
const next = join59(dirname23(file), ext.endsWith(".json") ? ext : `${ext}.json`);
|
|
15391
|
-
return existsSync39(next) ? moduleOf(next, depth + 1) : null;
|
|
15392
|
-
}
|
|
15393
|
-
function readPackageConventions(pkgDir, runner = null) {
|
|
15394
|
-
let names = [];
|
|
15395
|
-
try {
|
|
15396
|
-
names = readdirSync20(pkgDir).filter((f) => f.endsWith(".json")).sort((x, y) => x.length - y.length || x.localeCompare(y));
|
|
15397
|
-
} catch {
|
|
15398
|
-
return null;
|
|
15399
|
-
}
|
|
15400
|
-
let packageType = null, tsModule = null;
|
|
15401
|
-
for (const n2 of names) {
|
|
15402
|
-
const j = readJson5(join59(pkgDir, n2));
|
|
15403
|
-
if (!j)
|
|
15404
|
-
continue;
|
|
15405
|
-
if (packageType === null && typeof j.type === "string" && typeof j.name === "string")
|
|
15406
|
-
packageType = j.type;
|
|
15407
|
-
if (tsModule === null && j.compilerOptions !== undefined)
|
|
15408
|
-
tsModule = moduleOf(join59(pkgDir, n2));
|
|
15409
|
-
}
|
|
15410
|
-
if (packageType === null && tsModule === null)
|
|
15411
|
-
return null;
|
|
15412
|
-
const esmType = packageType === "module";
|
|
15413
|
-
const moduleSystem = tsModule === null || tsModule === "node16" || tsModule === "nodenext" ? esmType ? "esm" : "commonjs" : /^(commonjs|amd|umd|system)$/.test(tsModule) ? "commonjs" : "esm";
|
|
15414
|
-
return { moduleSystem, packageType, tsModule, runner };
|
|
15415
|
-
}
|
|
15416
|
-
function conventionsBrief(c) {
|
|
15417
|
-
if (!c)
|
|
15418
|
-
return "";
|
|
15419
|
-
const decl = `manifest type: ${c.packageType ?? "(unset)"}, compiler module: ${c.tsModule ?? "(unset)"}${c.runner ? `, test runner: ${c.runner}` : ""}`;
|
|
15420
|
-
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.`;
|
|
15421
|
-
}
|
|
15422
|
-
function conventionViolation(c, fileName, content) {
|
|
15423
|
-
if (!c || c.moduleSystem !== "commonjs" || !/\.[cm]?[jt]sx?$/.test(fileName) || /\.m[jt]s$/.test(fileName))
|
|
15424
|
-
return null;
|
|
15425
|
-
const code = content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1").replace(/(["'`])(?:\\.|(?!\1)[^\\\n])*\1/g, '""');
|
|
15426
|
-
return /\bimport\.meta\b/.test(code) ? "import.meta is not allowed in a CommonJS package (TS1470)" : null;
|
|
15427
|
-
}
|
|
15428
|
-
function outOfRepoTarget(content) {
|
|
15429
|
-
const code = content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1").replace(/(^|\s)#.*$/gm, "$1");
|
|
15430
|
-
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))
|
|
15431
|
-
return null;
|
|
15432
|
-
const home = /\bhomedir\s*\(|\bPath\.home\s*\(|\bexpanduser\s*\(|\$\{?HOME\b|\$\{?USERPROFILE\b|\bprocess\.env\.(HOME|USERPROFILE)\b|["'`]~\/|["'`](?:file:\/\/)?\/(?:Users|home|root)\//;
|
|
15433
|
-
const locates = /["'`\/]\.[A-Za-z][\w-]*(?:[\/"'`]|$)|\b(?:import|require|source|spawn\w*|exec\w*|pathToFileURL|readFile\w*)\b/;
|
|
15434
|
-
for (const line2 of code.split(`
|
|
15435
|
-
`)) {
|
|
15436
|
-
if (/^\s*(?:await\s+)?(?:expect|assert\w*)\b/.test(line2))
|
|
15437
|
-
continue;
|
|
15438
|
-
if (home.test(line2) && locates.test(line2))
|
|
15439
|
-
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";
|
|
15440
|
-
}
|
|
15441
|
-
return null;
|
|
15442
|
-
}
|
|
15443
|
-
function phantomRepoPaths(content, fileName, testDir, repoDir, planText) {
|
|
15444
|
-
if (!/\.[cm]?[jt]sx?$/.test(fileName))
|
|
15445
|
-
return [];
|
|
15446
|
-
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, "= ");
|
|
15447
|
-
let pkg = testDir;
|
|
15448
|
-
while (pkg !== repoDir && pkg !== dirname23(pkg) && !MANIFESTS.some((m) => existsSync39(join59(pkg, m))))
|
|
15449
|
-
pkg = dirname23(pkg);
|
|
15450
|
-
const split2 = (s) => {
|
|
15451
|
-
const out2 = [];
|
|
15452
|
-
let d = 0, q = "", cur = "";
|
|
15453
|
-
for (let i = 0;i < s.length; i++) {
|
|
15454
|
-
const c = s[i];
|
|
15455
|
-
if (q) {
|
|
15456
|
-
cur += c;
|
|
15457
|
-
if (c === "\\")
|
|
15458
|
-
cur += s[++i] ?? "";
|
|
15459
|
-
else if (c === q)
|
|
15460
|
-
q = "";
|
|
15461
|
-
} else if (c === '"' || c === "'" || c === "`") {
|
|
15462
|
-
q = c;
|
|
15463
|
-
cur += c;
|
|
15464
|
-
} else if ("([{".includes(c)) {
|
|
15465
|
-
d++;
|
|
15466
|
-
cur += c;
|
|
15467
|
-
} else if (")]}".includes(c)) {
|
|
15468
|
-
d--;
|
|
15469
|
-
cur += c;
|
|
15470
|
-
} else if (c === "," && d === 0) {
|
|
15471
|
-
out2.push(cur);
|
|
15472
|
-
cur = "";
|
|
15473
|
-
} else
|
|
15474
|
-
cur += c;
|
|
15475
|
-
}
|
|
15476
|
-
if (cur.trim())
|
|
15477
|
-
out2.push(cur);
|
|
15478
|
-
return out2;
|
|
15479
|
-
};
|
|
15480
|
-
const close = (line2, at) => {
|
|
15481
|
-
let d = 0;
|
|
15482
|
-
for (let j = at;j < line2.length; j++) {
|
|
15483
|
-
if (line2[j] === "(")
|
|
15484
|
-
d++;
|
|
15485
|
-
else if (line2[j] === ")" && --d === 0)
|
|
15486
|
-
return j;
|
|
15487
|
-
}
|
|
15488
|
-
return -1;
|
|
15489
|
-
};
|
|
15490
|
-
const scan = (cwd) => {
|
|
15491
|
-
const vars = new Map, reports = new Map, created = [];
|
|
15492
|
-
let ln = 0;
|
|
15493
|
-
const ev = (raw2, report) => {
|
|
15494
|
-
const e = raw2.trim().replace(/^await\s+/, "").replace(/\s+as\s+\w+$/, "").replace(/!$/, "");
|
|
15495
|
-
if (/^import\.meta\.(dir|dirname)$|^__dirname$/.test(e))
|
|
15496
|
-
return testDir;
|
|
15497
|
-
if (e === "process.cwd()")
|
|
15498
|
-
return cwd;
|
|
15499
|
-
const env = /^process\.env(?:\.[\w$]+|\[[^\]]+\])\s*(?:\?\?|\|\|)\s*([\s\S]+)$/.exec(e);
|
|
15500
|
-
if (env)
|
|
15501
|
-
return ev(env[1], report);
|
|
15502
|
-
if (e === "fileURLToPath(import.meta.url)" || e === "__filename")
|
|
15503
|
-
return join59(testDir, "__self__");
|
|
15504
|
-
const url = /^fileURLToPath\(new URL\((["'])([^"']*)\1\s*,\s*import\.meta\.url\)\)$/.exec(e);
|
|
15505
|
-
if (url)
|
|
15506
|
-
return resolve17(testDir, url[2]);
|
|
15507
|
-
const lit = /^(["'`])((?:\\.|(?!\1)[^\\])*)\1$/.exec(e);
|
|
15508
|
-
if (lit)
|
|
15509
|
-
return lit[2].includes("${") ? null : lit[2];
|
|
15510
|
-
if (/^[A-Za-z_$][\w$]*$/.test(e))
|
|
15511
|
-
return vars.get(e) ?? null;
|
|
15512
|
-
const call = /^(?:path\.)?(join|resolve|dirname)\(([\s\S]*)\)$/.exec(e);
|
|
15513
|
-
if (!call)
|
|
15514
|
-
return null;
|
|
15515
|
-
const parts = split2(call[2]), args = parts.map((a) => ev(a, report));
|
|
15516
|
-
if (args.some((a) => a === null))
|
|
15517
|
-
return null;
|
|
15518
|
-
if (call[1] === "dirname")
|
|
15519
|
-
return dirname23(args[0]);
|
|
15520
|
-
const out2 = resolve17(...args);
|
|
15521
|
-
if (report && relative10(testDir, out2).startsWith("..") && parts.some((a) => /^\s*["'`]/.test(a)))
|
|
15522
|
-
reports.set(`${ln}|${e}`, { out: out2, rel: relative10(repoDir, out2) });
|
|
15523
|
-
return out2;
|
|
15524
|
-
};
|
|
15525
|
-
for (const line2 of code.split(`
|
|
15526
|
-
`)) {
|
|
15527
|
-
ln++;
|
|
15528
|
-
for (const m of line2.matchAll(CREATORS)) {
|
|
15529
|
-
const j = close(line2, m.index + m[0].length - 1);
|
|
15530
|
-
if (j > 0)
|
|
15531
|
-
for (const a of split2(line2.slice(m.index + m[0].length, j))) {
|
|
15532
|
-
const v = ev(a, false);
|
|
15533
|
-
if (v)
|
|
15534
|
-
created.push(v);
|
|
15535
|
-
}
|
|
15536
|
-
}
|
|
15537
|
-
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);
|
|
15538
|
-
const asg = /^\s*(?:export\s+)?(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*(?::[^=]+)?=\s*(.+?);?\s*$/.exec(line2);
|
|
15539
|
-
if (asg) {
|
|
15540
|
-
const v = ev(asg[2], !skip);
|
|
15541
|
-
if (v !== null)
|
|
15542
|
-
vars.set(asg[1], v);
|
|
15543
|
-
continue;
|
|
15544
|
-
}
|
|
15545
|
-
if (skip)
|
|
15546
|
-
continue;
|
|
15547
|
-
for (const m of line2.matchAll(/(?:path\.)?(?:join|resolve)\(/g)) {
|
|
15548
|
-
const j = close(line2, m.index + m[0].length - 1);
|
|
15549
|
-
if (j > 0)
|
|
15550
|
-
ev(line2.slice(m.index, j + 1), true);
|
|
15551
|
-
}
|
|
15552
|
-
}
|
|
15553
|
-
return { reports, created };
|
|
15554
|
-
};
|
|
15555
|
-
const runs2 = [...new Set([pkg, repoDir])].map(scan);
|
|
15556
|
-
const planned = (rel) => !!planText && rel.split("/").some((_, i, a) => {
|
|
15557
|
-
const pre = a.slice(0, i + 1).join("/");
|
|
15558
|
-
return (i > 0 || a.length === 1) && !existsSync39(join59(repoDir, pre)) && new RegExp(`(?<![\\w-])${pre.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w-])`).test(planText);
|
|
15559
|
-
});
|
|
15560
|
-
const phantom = (r, created) => {
|
|
15561
|
-
const rel = r.rel;
|
|
15562
|
-
if (!rel || rel.startsWith("..") || isAbsolute10(rel) || /(^|\/)(node_modules|\.git|\.loki|dist|build|coverage|tmp)(\/|$)/.test(rel) || existsSync39(r.out) || planned(rel))
|
|
15563
|
-
return false;
|
|
15564
|
-
if (created.some((c) => c === r.out || c.startsWith(r.out + "/") || r.out.startsWith(c + "/")))
|
|
15565
|
-
return false;
|
|
15566
|
-
return safeGitSpawn(repoDir, ["check-ignore", "-q", "--", rel], { timeout: 5000 }).status !== 0;
|
|
15567
|
-
};
|
|
15568
|
-
const missing = [];
|
|
15569
|
-
for (const [k, r] of runs2[0].reports)
|
|
15570
|
-
if (runs2.every((x) => x.reports.has(k) && phantom(x.reports.get(k), x.created)) && !missing.includes(r.rel))
|
|
15571
|
-
missing.push(r.rel);
|
|
15572
|
-
return missing.slice(0, 3);
|
|
15573
|
-
}
|
|
15574
|
-
function phantomReason(miss, repoFiles) {
|
|
15575
|
-
if (miss.length === 0)
|
|
15576
|
-
return null;
|
|
15577
|
-
const hint = (m) => {
|
|
15578
|
-
const n2 = basename23(m), near = [...new Set(repoFiles.flatMap((f) => {
|
|
15579
|
-
const s = f.split("/"), k = s.indexOf(n2);
|
|
15580
|
-
return k >= 0 && s.slice(0, k + 1).join("/") !== m ? [s.slice(0, k + 1).join("/")] : [];
|
|
15581
|
-
}))].slice(0, 3);
|
|
15582
|
-
return near.length ? `${m} (a path named ${n2} exists at ${near.join(", ")})` : m;
|
|
15583
|
-
};
|
|
15584
|
-
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`;
|
|
15585
|
-
}
|
|
15586
|
-
var readJson5 = (p) => {
|
|
15587
|
-
try {
|
|
15588
|
-
const v = parseJsonc(readFileSync46(p, "utf8"));
|
|
15589
|
-
return v && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
15590
|
-
} catch {
|
|
15591
|
-
return null;
|
|
15592
|
-
}
|
|
15593
|
-
}, MANIFESTS, CREATORS;
|
|
15594
|
-
var init_conventions = __esm(() => {
|
|
15595
|
-
init_safe_git();
|
|
15596
|
-
MANIFESTS = ["package.json", "pyproject.toml", "go.mod", "Cargo.toml"];
|
|
15597
|
-
CREATORS = /\b(?:mkdirSync|writeFileSync|appendFileSync|cpSync|copyFileSync|renameSync|symlinkSync|mkdir|writeFile|appendFile|cp|copyFile|rename|outputFile|ensureDir|mkdirp)\(/g;
|
|
15598
|
-
});
|
|
15599
|
-
|
|
15600
15606
|
// ../../loki-ts/src/engine10/stages/wall.ts
|
|
15601
15607
|
import { spawnSync as spawnSync7 } from "child_process";
|
|
15602
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";
|
|
@@ -15740,11 +15746,7 @@ async function wallAuthor(ctx, signal, retry) {
|
|
|
15740
15746
|
});
|
|
15741
15747
|
const bad1 = oor();
|
|
15742
15748
|
if (bad1.length > 0 && !signal.aborted)
|
|
15743
|
-
await ctx.sessions.run({ stage: "wall", brief: withStagePrefix(
|
|
15744
|
-
${bad1.map((b) => `- ${b.name}: ${b.why}`).join(`
|
|
15745
|
-
`)}`, `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(`
|
|
15746
|
-
|
|
15747
|
-
`)), 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 });
|
|
15748
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));
|
|
15749
15751
|
const sealedDir = join60(ctx.runDir, "wall");
|
|
15750
15752
|
if (generated.length > 0)
|