loki-mode 11.17.83 → 11.17.85
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 +6 -0
- package/loki-ts/dist/loki.js +1097 -1097
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/packages/control-plane/dist/server.js +354 -333
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/web-app/dist/assets/{AdminPage-CrFXPtYq.js → AdminPage-CQvIDW-E.js} +1 -1
- package/web-app/dist/assets/{Avatar-ByHPLzy-.js → Avatar-DkFJwRUj.js} +1 -1
- package/web-app/dist/assets/{Badge-Cv86Tg1z.js → Badge-Bvma4aph.js} +1 -1
- package/web-app/dist/assets/{Button-Cmt4rAI6.js → Button-BwBKoWqj.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-C5oGG7HK.js → CockpitPage-8pGnRSzZ.js} +1 -1
- package/web-app/dist/assets/{ComparePage-BLHQkb2H.js → ComparePage-BDwuIaxb.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-CFYb0Cvs.js → ErrorBoundary-CKU4Vwp6.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-f7UV0iq8.js → EvidenceReceiptPanel-BMjrOryM.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-B9naEGop.js → GitHubIssuesPanel-DczOvL20.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-D_Sdx1xa.js → GitHubPRsPanel-0N9ak3AJ.js} +1 -1
- package/web-app/dist/assets/{HomePage-fgOLpLKO.js → HomePage-mdnAjF-J.js} +2 -2
- package/web-app/dist/assets/{LoginPage-5GbmfJoR.js → LoginPage-BaeNhqD9.js} +1 -1
- package/web-app/dist/assets/{MagicPage-CuBB-UdE.js → MagicPage-DH0tE5_L.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-CcDxBoQB.js → MetricsPage-DaYA5uZR.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-BRay4BL5.js → NotFoundPage-X8vHBuQ8.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-Du8YJlry.js → ProjectPage-95TRezL4.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage--psgDFsh.js → ProjectsPage-DOMomOSF.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-C4D9Jar9.js → SettingsPage-BfSpdpCc.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-BHTTqg8U.js → ShowcasePage-C0qPGJkC.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-BPVW2bM6.js → SystemSettingsPage-BpThrDER.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-D2XZA8JP.js → TeamsPage-clGzSU5q.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-BT5ReLll.js → TemplatesPage-BXEbxAHC.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-CG-tEIma.js → TerminalOutput-ClTPqtqi.js} +1 -1
- package/web-app/dist/assets/{activity-D4VfYw_h.js → activity-m15BYeZE.js} +1 -1
- package/web-app/dist/assets/{bell-AnG3l9wT.js → bell-BuwP2GDL.js} +1 -1
- package/web-app/dist/assets/{bot-CxMiwdYy.js → bot-CDjGLCgr.js} +1 -1
- package/web-app/dist/assets/{check-BrO9f5gl.js → check-BFDr2EjD.js} +1 -1
- package/web-app/dist/assets/{chevron-left-HpEtIo4e.js → chevron-left-BvabdS2G.js} +1 -1
- package/web-app/dist/assets/{circle-alert-S__4Lj5Y.js → circle-alert-D99GRyhd.js} +1 -1
- package/web-app/dist/assets/{clock-87ZkFFKd.js → clock-DpeqNd9u.js} +1 -1
- package/web-app/dist/assets/{cloud-CaoiXqrq.js → cloud-DT_Fkaaq.js} +1 -1
- package/web-app/dist/assets/{code-xml-Djv6HpN2.js → code-xml-CumY0v5M.js} +1 -1
- package/web-app/dist/assets/{database-QSkMsaL0.js → database-kSSVbdSM.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-DsIbt7E9.js → dollar-sign-DutghDzd.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-DQY_EKG0.js → file-code-corner-C-NqIxgV.js} +1 -1
- package/web-app/dist/assets/{file-plus-CeFRVlCc.js → file-plus-DxaP7cJb.js} +1 -1
- package/web-app/dist/assets/{globe-CYIZDx5y.js → globe-B1-ppFGm.js} +1 -1
- package/web-app/dist/assets/{hammer-QPHdCfpp.js → hammer-Dbv-mPGT.js} +1 -1
- package/web-app/dist/assets/{index-QoGQRWyx.js → index-dsPbt07e.js} +3 -3
- package/web-app/dist/assets/{layers-CtcDx8kr.js → layers-rknU7Tbd.js} +1 -1
- package/web-app/dist/assets/{loader-circle-CRP0ymla.js → loader-circle-B_OkT5zh.js} +1 -1
- package/web-app/dist/assets/{lock-DC_-r7Nn.js → lock-CJBwCwIB.js} +1 -1
- package/web-app/dist/assets/{package-C0utKSsc.js → package-BX33XiJh.js} +1 -1
- package/web-app/dist/assets/{plus-DN-1ptdd.js → plus-DHRl-agm.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-ClVo1weu.js → refresh-cw-Dd05dLci.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-buy6n4Dj.js → rotate-ccw-cRD-P0-J.js} +1 -1
- package/web-app/dist/assets/{scroll-text-fNFIg342.js → scroll-text-CxsDJg3c.js} +1 -1
- package/web-app/dist/assets/{server-JcjFhb66.js → server-DynZEwnf.js} +1 -1
- package/web-app/dist/assets/{shield-alert-DGjhsZZQ.js → shield-alert-4FfGW8Wb.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-Cu9bXhPK.js → thumbs-up-BfLden4A.js} +1 -1
- package/web-app/dist/assets/{trash-2-DQh5erCE.js → trash-2-oVADXZmH.js} +1 -1
- package/web-app/dist/assets/{trending-down-DCQoOPWu.js → trending-down-CFNSKYP7.js} +1 -1
- package/web-app/dist/assets/{trending-up-Dj30VoUY.js → trending-up-BoP8pQ87.js} +1 -1
- package/web-app/dist/assets/{upload-f7HNT6Li.js → upload-xTAtKIud.js} +1 -1
- package/web-app/dist/assets/{usePolling-T-0o6PGt.js → usePolling-rplsJRTX.js} +1 -1
- package/web-app/dist/assets/{user-9GLVvJkd.js → user-CXoaIq7w.js} +1 -1
- package/web-app/dist/index.html +1 -1
|
@@ -13902,6 +13902,277 @@ 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 nearestPackageRoot(testDir, repoDir, fileName) {
|
|
13997
|
+
const site = siteFor(loadProjectApi(repoDir), repoDir, relative8(repoDir, join53(testDir, fileName)));
|
|
13998
|
+
if (site)
|
|
13999
|
+
return site.cwd;
|
|
14000
|
+
const shaped = (d) => {
|
|
14001
|
+
try {
|
|
14002
|
+
return readdirSync19(d).some((f) => {
|
|
14003
|
+
if (!f.endsWith(".json"))
|
|
14004
|
+
return false;
|
|
14005
|
+
const j = readJson5(join53(d, f));
|
|
14006
|
+
return !!j && typeof j.name === "string" && Object.keys(j).length > 1;
|
|
14007
|
+
});
|
|
14008
|
+
} catch {
|
|
14009
|
+
return false;
|
|
14010
|
+
}
|
|
14011
|
+
};
|
|
14012
|
+
let pkg = testDir;
|
|
14013
|
+
while (pkg !== repoDir && pkg !== dirname19(pkg) && !shaped(pkg))
|
|
14014
|
+
pkg = dirname19(pkg);
|
|
14015
|
+
return pkg;
|
|
14016
|
+
}
|
|
14017
|
+
function phantomRepoPaths(content, fileName, testDir, repoDir, planText) {
|
|
14018
|
+
if (!/\.[cm]?[jt]sx?$/.test(fileName))
|
|
14019
|
+
return [];
|
|
14020
|
+
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, "= ");
|
|
14021
|
+
const pkg = nearestPackageRoot(testDir, repoDir, fileName);
|
|
14022
|
+
const split2 = (s) => {
|
|
14023
|
+
const out2 = [];
|
|
14024
|
+
let d = 0, q = "", cur = "";
|
|
14025
|
+
for (let i = 0;i < s.length; i++) {
|
|
14026
|
+
const c = s[i];
|
|
14027
|
+
if (q) {
|
|
14028
|
+
cur += c;
|
|
14029
|
+
if (c === "\\")
|
|
14030
|
+
cur += s[++i] ?? "";
|
|
14031
|
+
else if (c === q)
|
|
14032
|
+
q = "";
|
|
14033
|
+
} else if (c === '"' || c === "'" || c === "`") {
|
|
14034
|
+
q = c;
|
|
14035
|
+
cur += c;
|
|
14036
|
+
} else if ("([{".includes(c)) {
|
|
14037
|
+
d++;
|
|
14038
|
+
cur += c;
|
|
14039
|
+
} else if (")]}".includes(c)) {
|
|
14040
|
+
d--;
|
|
14041
|
+
cur += c;
|
|
14042
|
+
} else if (c === "," && d === 0) {
|
|
14043
|
+
out2.push(cur);
|
|
14044
|
+
cur = "";
|
|
14045
|
+
} else
|
|
14046
|
+
cur += c;
|
|
14047
|
+
}
|
|
14048
|
+
if (cur.trim())
|
|
14049
|
+
out2.push(cur);
|
|
14050
|
+
return out2;
|
|
14051
|
+
};
|
|
14052
|
+
const close = (line2, at) => {
|
|
14053
|
+
let d = 0;
|
|
14054
|
+
for (let j = at;j < line2.length; j++) {
|
|
14055
|
+
if (line2[j] === "(")
|
|
14056
|
+
d++;
|
|
14057
|
+
else if (line2[j] === ")" && --d === 0)
|
|
14058
|
+
return j;
|
|
14059
|
+
}
|
|
14060
|
+
return -1;
|
|
14061
|
+
};
|
|
14062
|
+
const scan = (cwd) => {
|
|
14063
|
+
const vars = new Map, reports = new Map, created = [];
|
|
14064
|
+
let ln = 0;
|
|
14065
|
+
const ev = (raw2, report) => {
|
|
14066
|
+
const e = raw2.trim().replace(/^await\s+/, "").replace(/\s+as\s+\w+$/, "").replace(/!$/, "");
|
|
14067
|
+
if (/^import\.meta\.(dir|dirname)$|^__dirname$/.test(e))
|
|
14068
|
+
return testDir;
|
|
14069
|
+
if (e === "process.cwd()")
|
|
14070
|
+
return cwd;
|
|
14071
|
+
const env = /^process\.env(?:\.[\w$]+|\[[^\]]+\])\s*(?:\?\?|\|\|)\s*([\s\S]+)$/.exec(e);
|
|
14072
|
+
if (env)
|
|
14073
|
+
return ev(env[1], report);
|
|
14074
|
+
if (e === "fileURLToPath(import.meta.url)" || e === "__filename")
|
|
14075
|
+
return join53(testDir, "__self__");
|
|
14076
|
+
const url = /^fileURLToPath\(new URL\((["'])([^"']*)\1\s*,\s*import\.meta\.url\)\)$/.exec(e);
|
|
14077
|
+
if (url)
|
|
14078
|
+
return resolve17(testDir, url[2]);
|
|
14079
|
+
const lit = /^(["'`])((?:\\.|(?!\1)[^\\])*)\1$/.exec(e);
|
|
14080
|
+
if (lit)
|
|
14081
|
+
return lit[2].includes("${") ? null : lit[2];
|
|
14082
|
+
if (/^[A-Za-z_$][\w$]*$/.test(e))
|
|
14083
|
+
return vars.get(e) ?? null;
|
|
14084
|
+
const call = /^(?:path\.)?(join|resolve|dirname)\(([\s\S]*)\)$/.exec(e);
|
|
14085
|
+
if (!call)
|
|
14086
|
+
return null;
|
|
14087
|
+
const parts = split2(call[2]), args = parts.map((a) => ev(a, report));
|
|
14088
|
+
if (args.some((a) => a === null))
|
|
14089
|
+
return null;
|
|
14090
|
+
if (call[1] === "dirname")
|
|
14091
|
+
return dirname19(args[0]);
|
|
14092
|
+
const out2 = resolve17(...args);
|
|
14093
|
+
if (report && relative8(testDir, out2).startsWith("..") && parts.some((a) => /^\s*["'`]/.test(a)))
|
|
14094
|
+
reports.set(`${ln}|${e}`, { out: out2, rel: relative8(repoDir, out2) });
|
|
14095
|
+
return out2;
|
|
14096
|
+
};
|
|
14097
|
+
for (const line2 of code.split(`
|
|
14098
|
+
`)) {
|
|
14099
|
+
ln++;
|
|
14100
|
+
for (const m of line2.matchAll(CREATORS)) {
|
|
14101
|
+
const j = close(line2, m.index + m[0].length - 1);
|
|
14102
|
+
if (j > 0)
|
|
14103
|
+
for (const a of split2(line2.slice(m.index + m[0].length, j))) {
|
|
14104
|
+
const v = ev(a, false);
|
|
14105
|
+
if (v)
|
|
14106
|
+
created.push(v);
|
|
14107
|
+
}
|
|
14108
|
+
}
|
|
14109
|
+
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);
|
|
14110
|
+
const asg = /^\s*(?:export\s+)?(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*(?::[^=]+)?=\s*(.+?);?\s*$/.exec(line2);
|
|
14111
|
+
if (asg) {
|
|
14112
|
+
const v = ev(asg[2], !skip);
|
|
14113
|
+
if (v !== null)
|
|
14114
|
+
vars.set(asg[1], v);
|
|
14115
|
+
continue;
|
|
14116
|
+
}
|
|
14117
|
+
if (skip)
|
|
14118
|
+
continue;
|
|
14119
|
+
for (const m of line2.matchAll(/(?:path\.)?(?:join|resolve)\(/g)) {
|
|
14120
|
+
const j = close(line2, m.index + m[0].length - 1);
|
|
14121
|
+
if (j > 0)
|
|
14122
|
+
ev(line2.slice(m.index, j + 1), true);
|
|
14123
|
+
}
|
|
14124
|
+
}
|
|
14125
|
+
return { reports, created };
|
|
14126
|
+
};
|
|
14127
|
+
const runs2 = [...new Set([pkg, repoDir])].map(scan);
|
|
14128
|
+
const planned = (rel) => !!planText && rel.split("/").some((_, i, a) => {
|
|
14129
|
+
const pre = a.slice(0, i + 1).join("/");
|
|
14130
|
+
return (i > 0 || a.length === 1) && !existsSync33(join53(repoDir, pre)) && new RegExp(`(?<![\\w-])${pre.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w-])`).test(planText);
|
|
14131
|
+
});
|
|
14132
|
+
const phantom = (r, created) => {
|
|
14133
|
+
const rel = r.rel;
|
|
14134
|
+
if (!rel || rel.startsWith("..") || isAbsolute8(rel) || /(^|\/)(\w*_modules|\.git|\.loki|dist|build|coverage|tmp)(\/|$)/.test(rel) || existsSync33(r.out) || planned(rel))
|
|
14135
|
+
return false;
|
|
14136
|
+
if (created.some((c) => c === r.out || c.startsWith(r.out + "/") || r.out.startsWith(c + "/")))
|
|
14137
|
+
return false;
|
|
14138
|
+
return safeGitSpawn(repoDir, ["check-ignore", "-q", "--", rel], { timeout: 5000 }).status !== 0;
|
|
14139
|
+
};
|
|
14140
|
+
const missing = [];
|
|
14141
|
+
for (const [k, r] of runs2[0].reports)
|
|
14142
|
+
if (runs2.every((x) => x.reports.has(k) && phantom(x.reports.get(k), x.created)) && !missing.includes(r.rel))
|
|
14143
|
+
missing.push(r.rel);
|
|
14144
|
+
return missing.slice(0, 3);
|
|
14145
|
+
}
|
|
14146
|
+
function phantomReason(miss, repoFiles) {
|
|
14147
|
+
if (miss.length === 0)
|
|
14148
|
+
return null;
|
|
14149
|
+
const hint = (m) => {
|
|
14150
|
+
const n2 = basename22(m), near = [...new Set(repoFiles.flatMap((f) => {
|
|
14151
|
+
const s = f.split("/"), k = s.indexOf(n2);
|
|
14152
|
+
return k >= 0 && s.slice(0, k + 1).join("/") !== m ? [s.slice(0, k + 1).join("/")] : [];
|
|
14153
|
+
}))].slice(0, 3);
|
|
14154
|
+
return near.length ? `${m} (a path named ${n2} exists at ${near.join(", ")})` : m;
|
|
14155
|
+
};
|
|
14156
|
+
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`;
|
|
14157
|
+
}
|
|
14158
|
+
var readJson5 = (p) => {
|
|
14159
|
+
try {
|
|
14160
|
+
const v = parseJsonc(readFileSync42(p, "utf8"));
|
|
14161
|
+
return v && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
14162
|
+
} catch {
|
|
14163
|
+
return null;
|
|
14164
|
+
}
|
|
14165
|
+
}, outOfRepoReask = (lead, bad) => [`${lead} Each was rejected:
|
|
14166
|
+
${bad.map((b) => `- ${b.name}: ${b.why}`).join(`
|
|
14167
|
+
`)}`, `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(`
|
|
14168
|
+
|
|
14169
|
+
`), CREATORS;
|
|
14170
|
+
var init_conventions = __esm(() => {
|
|
14171
|
+
init_safe_git();
|
|
14172
|
+
init_resolve();
|
|
14173
|
+
CREATORS = /\b(?:mkdirSync|writeFileSync|appendFileSync|cpSync|copyFileSync|renameSync|symlinkSync|mkdir|writeFile|appendFile|cp|copyFile|rename|outputFile|ensureDir|mkdirp)\(/g;
|
|
14174
|
+
});
|
|
14175
|
+
|
|
13905
14176
|
// ../../loki-ts/src/version.ts
|
|
13906
14177
|
var init_version = __esm(() => {
|
|
13907
14178
|
init_paths();
|
|
@@ -13998,9 +14269,9 @@ var init_route_block = __esm(() => {
|
|
|
13998
14269
|
// ../../loki-ts/src/features/visual_evidence.ts
|
|
13999
14270
|
import { spawn as spawn8 } from "child_process";
|
|
14000
14271
|
import { createHash as createHash14, randomBytes as randomBytes6 } from "crypto";
|
|
14001
|
-
import { existsSync as
|
|
14272
|
+
import { existsSync as existsSync34, lstatSync as lstatSync12, mkdirSync as mkdirSync21, readdirSync as readdirSync20, readFileSync as readFileSync43, writeFileSync as writeFileSync24 } from "fs";
|
|
14002
14273
|
import { createServer } from "net";
|
|
14003
|
-
import { dirname as
|
|
14274
|
+
import { dirname as dirname20, isAbsolute as isAbsolute9, join as join54, normalize as normalize3, relative as relative9, sep as sep13 } from "path";
|
|
14004
14275
|
function routeFor(file) {
|
|
14005
14276
|
let r = file.replace(/^(?:.*?\/)?(?:app|pages|src|public)\//, "").replace(/^(?:routes|pages)\//, "");
|
|
14006
14277
|
r = r.replace(/\.(?:html|jsx|tsx|vue|svelte)$/, "").replace(/\/?(?:page|index|\+page)$/, "");
|
|
@@ -14010,7 +14281,7 @@ function hashScreens(runDir, rels) {
|
|
|
14010
14281
|
const out2 = [];
|
|
14011
14282
|
for (const rel of rels) {
|
|
14012
14283
|
try {
|
|
14013
|
-
out2.push({ path: rel, sha256: sha256File(
|
|
14284
|
+
out2.push({ path: rel, sha256: sha256File(join54(runDir, rel)) });
|
|
14014
14285
|
} catch {}
|
|
14015
14286
|
}
|
|
14016
14287
|
return out2;
|
|
@@ -14021,16 +14292,16 @@ function checkScreens(runDir, screens) {
|
|
|
14021
14292
|
for (const s of screens) {
|
|
14022
14293
|
if (typeof s?.path !== "string" || typeof s.sha256 !== "string")
|
|
14023
14294
|
return "evidence_screens entry is malformed";
|
|
14024
|
-
if (
|
|
14295
|
+
if (isAbsolute9(s.path) || normalize3(s.path).startsWith(".."))
|
|
14025
14296
|
return `evidence screenshot path escapes the evidence dir: ${s.path}`;
|
|
14026
|
-
const file =
|
|
14297
|
+
const file = join54(runDir, s.path);
|
|
14027
14298
|
let cur = runDir;
|
|
14028
14299
|
for (const seg of normalize3(s.path).split(sep13)) {
|
|
14029
|
-
cur =
|
|
14300
|
+
cur = join54(cur, seg);
|
|
14030
14301
|
if (isSymlink(cur))
|
|
14031
14302
|
return `evidence screenshot path is a symlink: ${s.path}`;
|
|
14032
14303
|
}
|
|
14033
|
-
if (!
|
|
14304
|
+
if (!existsSync34(file))
|
|
14034
14305
|
return `evidence screenshot is missing: ${s.path}`;
|
|
14035
14306
|
if (!isRegularFile(file))
|
|
14036
14307
|
return `evidence screenshot is not a regular file: ${s.path}`;
|
|
@@ -14073,11 +14344,11 @@ async function waitUp(url, ms, signal) {
|
|
|
14073
14344
|
}
|
|
14074
14345
|
function openapiPaths(repoDir) {
|
|
14075
14346
|
for (const f of ["openapi.json", "openapi.yaml", "openapi.yml", "swagger.json"]) {
|
|
14076
|
-
const p =
|
|
14077
|
-
if (!
|
|
14347
|
+
const p = join54(repoDir, f);
|
|
14348
|
+
if (!existsSync34(p))
|
|
14078
14349
|
continue;
|
|
14079
14350
|
try {
|
|
14080
|
-
const txt =
|
|
14351
|
+
const txt = readFileSync43(p, "utf8");
|
|
14081
14352
|
const paths = f.endsWith(".json") ? Object.keys(JSON.parse(txt).paths ?? {}) : [...txt.matchAll(/^ {2}(\/[^\s:]*):\s*$/gm)].map((m) => m[1]);
|
|
14082
14353
|
return paths.filter((x) => !x.includes("{")).slice(0, 10);
|
|
14083
14354
|
} catch {
|
|
@@ -14091,24 +14362,24 @@ async function recordE2eMedia(repoDir, runDir, relDir, base, routes, ms, signal)
|
|
|
14091
14362
|
if (!pw || !pkg)
|
|
14092
14363
|
return { rels: [], skipped: "playwright e2e video and trace skipped: @playwright/test is not installed in the repo" };
|
|
14093
14364
|
try {
|
|
14094
|
-
const dir =
|
|
14365
|
+
const dir = join54(runDir, relDir, "e2e");
|
|
14095
14366
|
mkdirSync21(dir, { recursive: true });
|
|
14096
|
-
writeFileSync24(
|
|
14097
|
-
writeFileSync24(
|
|
14367
|
+
writeFileSync24(join54(dir, "walk.spec.cjs"), e2eSpecSource(pkg, base, routes));
|
|
14368
|
+
writeFileSync24(join54(dir, "playwright.config.cjs"), `module.exports = { testDir: ".", testMatch: "walk.spec.cjs", outputDir: "./out", reporter: "null", use: { video: "on", trace: "on" } };
|
|
14098
14369
|
`);
|
|
14099
|
-
if (!await shoot(pw, ["test", "--config",
|
|
14370
|
+
if (!await shoot(pw, ["test", "--config", join54(dir, "playwright.config.cjs")], repoDir, ms, signal))
|
|
14100
14371
|
return { rels: [], skipped: "playwright e2e video and trace skipped: the run failed or timed out" };
|
|
14101
14372
|
const rels = [];
|
|
14102
14373
|
const walk = (d) => {
|
|
14103
|
-
for (const e of
|
|
14104
|
-
const full =
|
|
14374
|
+
for (const e of readdirSync20(d, { withFileTypes: true })) {
|
|
14375
|
+
const full = join54(d, e.name);
|
|
14105
14376
|
if (e.isDirectory())
|
|
14106
14377
|
walk(full);
|
|
14107
14378
|
else if (e.isFile() && /\.(webm|zip)$/.test(e.name))
|
|
14108
|
-
rels.push(
|
|
14379
|
+
rels.push(join54(relDir, "e2e", relative9(dir, full)));
|
|
14109
14380
|
}
|
|
14110
14381
|
};
|
|
14111
|
-
walk(
|
|
14382
|
+
walk(join54(dir, "out"));
|
|
14112
14383
|
return rels.length > 0 ? { rels, skipped: null } : { rels, skipped: "playwright e2e video and trace skipped: no video or trace was produced" };
|
|
14113
14384
|
} catch (e) {
|
|
14114
14385
|
return { rels: [], skipped: `playwright e2e video and trace skipped: ${String(e?.message ?? e).slice(0, 120)}` };
|
|
@@ -14187,22 +14458,22 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
14187
14458
|
if (!visualEvidenceEnabled(opts.env))
|
|
14188
14459
|
return skip("LOKI_VISUAL_EVIDENCE is 0");
|
|
14189
14460
|
const api = loadProjectApi(repoDir), boot = isMultiRoot(api) ? api.uiBoot() : null;
|
|
14190
|
-
const appDir = boot ?
|
|
14191
|
-
const pkgPath =
|
|
14461
|
+
const appDir = boot ? join54(repoDir, boot.boot.cwd) : repoDir;
|
|
14462
|
+
const pkgPath = join54(appDir, "package.json");
|
|
14192
14463
|
let script = null;
|
|
14193
14464
|
if (!boot) {
|
|
14194
|
-
if (!
|
|
14195
|
-
const subs = ["backend", "frontend"].filter((d) =>
|
|
14465
|
+
if (!existsSync34(pkgPath)) {
|
|
14466
|
+
const subs = ["backend", "frontend"].filter((d) => existsSync34(join54(repoDir, d, "package.json")));
|
|
14196
14467
|
const has2 = (d) => {
|
|
14197
14468
|
try {
|
|
14198
|
-
return pickScript(JSON.parse(
|
|
14469
|
+
return pickScript(JSON.parse(readFileSync43(join54(repoDir, d, "package.json"), "utf8"))) !== null;
|
|
14199
14470
|
} catch {
|
|
14200
14471
|
return false;
|
|
14201
14472
|
}
|
|
14202
14473
|
};
|
|
14203
14474
|
return skip(noRootReason(subs, subs.filter((d) => !has2(d))));
|
|
14204
14475
|
}
|
|
14205
|
-
script = pickScript(JSON.parse(
|
|
14476
|
+
script = pickScript(JSON.parse(readFileSync43(pkgPath, "utf8")));
|
|
14206
14477
|
if (!script)
|
|
14207
14478
|
return skip("no dev, preview or start script");
|
|
14208
14479
|
}
|
|
@@ -14229,20 +14500,20 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
14229
14500
|
}
|
|
14230
14501
|
if (!await waitUp(base, left(), signal))
|
|
14231
14502
|
return skip(aborted() ? "aborted" : `${script} server did not answer within ${Math.round(budget / 1000)}s`);
|
|
14232
|
-
const evRoot =
|
|
14503
|
+
const evRoot = join54(runDir, "evidence");
|
|
14233
14504
|
if (isSymlink(evRoot))
|
|
14234
14505
|
return skip("evidence dir is a symlink");
|
|
14235
14506
|
mkdirSync21(evRoot, { recursive: true });
|
|
14236
14507
|
if (pages.length > 0) {
|
|
14237
|
-
const rel0 =
|
|
14238
|
-
mkdirSync21(
|
|
14508
|
+
const rel0 = join54("evidence", randomBytes6(6).toString("hex"));
|
|
14509
|
+
mkdirSync21(join54(runDir, rel0));
|
|
14239
14510
|
const rels = [];
|
|
14240
14511
|
for (const route of [...new Set(pages.map(routeFor))].slice(0, opts.maxRoutes ?? MAX_ROUTES)) {
|
|
14241
14512
|
if (aborted() || left() <= 0)
|
|
14242
14513
|
break;
|
|
14243
|
-
const rel =
|
|
14244
|
-
const ok = await shoot(pw, ["screenshot", `${base}${route}`,
|
|
14245
|
-
if (ok && !aborted() && !isSymlink(
|
|
14514
|
+
const rel = join54(rel0, `${screenName(route)}.png`);
|
|
14515
|
+
const ok = await shoot(pw, ["screenshot", `${base}${route}`, join54(runDir, rel)], appDir, left(), signal);
|
|
14516
|
+
if (ok && !aborted() && !isSymlink(join54(runDir, rel)) && existsSync34(join54(runDir, rel)))
|
|
14246
14517
|
rels.push(rel);
|
|
14247
14518
|
}
|
|
14248
14519
|
if (aborted())
|
|
@@ -14267,9 +14538,9 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
14267
14538
|
}
|
|
14268
14539
|
if (aborted())
|
|
14269
14540
|
return skip("aborted");
|
|
14270
|
-
const hdir =
|
|
14541
|
+
const hdir = join54(evRoot, randomBytes6(6).toString("hex"));
|
|
14271
14542
|
mkdirSync21(hdir);
|
|
14272
|
-
writeFileSync24(
|
|
14543
|
+
writeFileSync24(join54(hdir, "http.json"), JSON.stringify(rows, null, 2) + `
|
|
14273
14544
|
`);
|
|
14274
14545
|
return { screens: [], http: true, skipped: null };
|
|
14275
14546
|
} catch (e) {
|
|
@@ -14296,14 +14567,14 @@ async function sealEvidence(repoDir, runDir, o, notProven, signal, emit) {
|
|
|
14296
14567
|
function receiptScreensProblem(receiptPath, receipt) {
|
|
14297
14568
|
if (visualGateEnabled() && typeof receipt["evidence_failed"] === "string")
|
|
14298
14569
|
return `visual evidence failed (LOKI_VISUAL_GATE=1): ${receipt["evidence_failed"]}`;
|
|
14299
|
-
return receipt["evidence_screens"] === undefined ? null : checkScreens(
|
|
14570
|
+
return receipt["evidence_screens"] === undefined ? null : checkScreens(dirname20(receiptPath), receipt["evidence_screens"]);
|
|
14300
14571
|
}
|
|
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
|
|
14572
|
+
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) => {
|
|
14573
|
+
const bin = join54(repoDir, "node_modules", ".bin", "playwright");
|
|
14574
|
+
return existsSync34(bin) ? bin : null;
|
|
14304
14575
|
}, playwrightTestPkg = (repoDir) => {
|
|
14305
|
-
const d =
|
|
14306
|
-
return
|
|
14576
|
+
const d = join54(repoDir, "node_modules", "@playwright", "test");
|
|
14577
|
+
return existsSync34(join54(d, "package.json")) ? d : null;
|
|
14307
14578
|
}, e2eSpecSource = (pkgDir, base, routes) => `const { test } = require(${JSON.stringify(pkgDir)});
|
|
14308
14579
|
test("loki e2e walkthrough", async ({ page }) => {
|
|
14309
14580
|
for (const r of ${JSON.stringify(routes)}) { await page.goto(${JSON.stringify(base)} + r); await page.waitForLoadState("load"); }
|
|
@@ -14349,7 +14620,7 @@ var init_outbox = __esm(() => {
|
|
|
14349
14620
|
});
|
|
14350
14621
|
|
|
14351
14622
|
// ../../loki-ts/src/engine10/stages/pr.ts
|
|
14352
|
-
import { join as
|
|
14623
|
+
import { join as join55 } from "path";
|
|
14353
14624
|
var DEFAULT_PUSH_SH, DEFAULT_PUSH_GITLAB_SH;
|
|
14354
14625
|
var init_pr = __esm(() => {
|
|
14355
14626
|
init_types();
|
|
@@ -14368,20 +14639,20 @@ var init_pr = __esm(() => {
|
|
|
14368
14639
|
init_receipt_surface();
|
|
14369
14640
|
init_yaml_key();
|
|
14370
14641
|
init_outbox();
|
|
14371
|
-
DEFAULT_PUSH_SH =
|
|
14372
|
-
DEFAULT_PUSH_GITLAB_SH =
|
|
14642
|
+
DEFAULT_PUSH_SH = join55(REPO_ROOT, "autonomy/lib/engine10-push.sh");
|
|
14643
|
+
DEFAULT_PUSH_GITLAB_SH = join55(REPO_ROOT, "autonomy/lib/engine10-push-gitlab.sh");
|
|
14373
14644
|
});
|
|
14374
14645
|
|
|
14375
14646
|
// ../../loki-ts/src/util/pr_lessons.ts
|
|
14376
|
-
import { existsSync as
|
|
14377
|
-
import { dirname as
|
|
14647
|
+
import { existsSync as existsSync35, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync8, readFileSync as readFileSync44, rmSync as rmSync16, writeFileSync as writeFileSync25 } from "fs";
|
|
14648
|
+
import { dirname as dirname21, join as join56 } from "path";
|
|
14378
14649
|
import { createHash as createHash15 } from "crypto";
|
|
14379
14650
|
function loadLessons(repoDir) {
|
|
14380
14651
|
const p = lessonsPath(repoDir);
|
|
14381
|
-
if (!
|
|
14652
|
+
if (!existsSync35(p))
|
|
14382
14653
|
return [];
|
|
14383
14654
|
try {
|
|
14384
|
-
const j = JSON.parse(
|
|
14655
|
+
const j = JSON.parse(readFileSync44(p, "utf-8"));
|
|
14385
14656
|
return Array.isArray(j.lessons) ? j.lessons : [];
|
|
14386
14657
|
} catch {
|
|
14387
14658
|
return [];
|
|
@@ -14389,7 +14660,7 @@ function loadLessons(repoDir) {
|
|
|
14389
14660
|
}
|
|
14390
14661
|
function save(repoDir, lessons) {
|
|
14391
14662
|
const p = lessonsPath(repoDir);
|
|
14392
|
-
mkdirSync22(
|
|
14663
|
+
mkdirSync22(dirname21(p), { recursive: true });
|
|
14393
14664
|
atomicWriteJson(p, { version: 2, lessons });
|
|
14394
14665
|
}
|
|
14395
14666
|
function appendReceiptFact(repoDir, f, now2 = () => new Date) {
|
|
@@ -14423,7 +14694,7 @@ function recordRunVerdict(repoDir, runId2, verdict) {
|
|
|
14423
14694
|
if (dirty)
|
|
14424
14695
|
save(repoDir, lessons);
|
|
14425
14696
|
}
|
|
14426
|
-
var lessonsPath = (repoDir) =>
|
|
14697
|
+
var lessonsPath = (repoDir) => join56(repoDir, ".loki", "memory", "semantic", "pr-lessons.json"), KINDS;
|
|
14427
14698
|
var init_pr_lessons = __esm(() => {
|
|
14428
14699
|
init_atomic();
|
|
14429
14700
|
init_safe_git();
|
|
@@ -14449,8 +14720,8 @@ var init_attempts = __esm(() => {
|
|
|
14449
14720
|
var init_mcp_config = () => {};
|
|
14450
14721
|
|
|
14451
14722
|
// ../../loki-ts/src/providers/claude_flags.ts
|
|
14452
|
-
import { existsSync as
|
|
14453
|
-
import { resolve as resolvePath, dirname as
|
|
14723
|
+
import { existsSync as existsSync36, readFileSync as readFileSync45 } from "fs";
|
|
14724
|
+
import { resolve as resolvePath, dirname as dirname22 } from "path";
|
|
14454
14725
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
14455
14726
|
function claudeFlagSupported(flag, helpText) {
|
|
14456
14727
|
const txt = helpText ?? _claudeHelpCache;
|
|
@@ -14497,14 +14768,14 @@ function leanReviewerFlags(opts = {}) {
|
|
|
14497
14768
|
}
|
|
14498
14769
|
function designArchetypesText() {
|
|
14499
14770
|
try {
|
|
14500
|
-
const moduleDir =
|
|
14771
|
+
const moduleDir = dirname22(fileURLToPath5(import.meta.url));
|
|
14501
14772
|
for (const rel of [
|
|
14502
14773
|
["..", "..", "..", "references", "design-archetypes.md"],
|
|
14503
14774
|
["..", "..", "references", "design-archetypes.md"]
|
|
14504
14775
|
]) {
|
|
14505
14776
|
const p = resolvePath(moduleDir, ...rel);
|
|
14506
|
-
if (
|
|
14507
|
-
return
|
|
14777
|
+
if (existsSync36(p))
|
|
14778
|
+
return readFileSync45(p, "utf8");
|
|
14508
14779
|
}
|
|
14509
14780
|
} catch {}
|
|
14510
14781
|
return "";
|
|
@@ -14589,14 +14860,14 @@ var init_providers = __esm(() => {
|
|
|
14589
14860
|
});
|
|
14590
14861
|
|
|
14591
14862
|
// ../../loki-ts/src/runner/router/route_record.ts
|
|
14592
|
-
import { existsSync as
|
|
14593
|
-
import { join as
|
|
14863
|
+
import { existsSync as existsSync37, lstatSync as lstatSync13, mkdirSync as mkdirSync23, readFileSync as readFileSync46, writeFileSync as writeFileSync26 } from "fs";
|
|
14864
|
+
import { join as join57 } from "path";
|
|
14594
14865
|
function loadRouteRecord(runDir) {
|
|
14595
14866
|
try {
|
|
14596
|
-
const p =
|
|
14597
|
-
if (!
|
|
14867
|
+
const p = join57(runDir, ROUTE_RECORD_FILE);
|
|
14868
|
+
if (!existsSync37(p) || !lstatSync13(p).isFile())
|
|
14598
14869
|
return;
|
|
14599
|
-
const v = JSON.parse(
|
|
14870
|
+
const v = JSON.parse(readFileSync46(p, "utf8"));
|
|
14600
14871
|
return typeof v === "object" && v !== null && !Array.isArray(v) ? v : undefined;
|
|
14601
14872
|
} catch {
|
|
14602
14873
|
return;
|
|
@@ -14657,6 +14928,7 @@ var init_implement_route = __esm(() => {
|
|
|
14657
14928
|
var init_implement = __esm(() => {
|
|
14658
14929
|
init_install();
|
|
14659
14930
|
init_lean_prefix();
|
|
14931
|
+
init_conventions();
|
|
14660
14932
|
init_pr_lessons();
|
|
14661
14933
|
init_context();
|
|
14662
14934
|
init_model_downgrades();
|
|
@@ -14744,14 +15016,14 @@ __export(exports_deep, {
|
|
|
14744
15016
|
DEFAULT_SECRET_SCAN_SH: () => DEFAULT_SECRET_SCAN_SH,
|
|
14745
15017
|
DEFAULT_PUSH_SH: () => DEFAULT_PUSH_SH2
|
|
14746
15018
|
});
|
|
14747
|
-
import { copyFileSync as copyFileSync3, existsSync as
|
|
15019
|
+
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
15020
|
import { tmpdir as tmpdir10 } from "os";
|
|
14749
|
-
import { dirname as
|
|
15021
|
+
import { dirname as dirname23, join as join58 } from "path";
|
|
14750
15022
|
function sessionCouncil(sessions) {
|
|
14751
15023
|
return { async run(input, signal) {
|
|
14752
|
-
const cwd = mkdtempSync9(
|
|
15024
|
+
const cwd = mkdtempSync9(join58(tmpdir10(), "loki-deep-council-"));
|
|
14753
15025
|
try {
|
|
14754
|
-
writeFileSync27(
|
|
15026
|
+
writeFileSync27(join58(cwd, "diff.patch"), input.diff, "utf8");
|
|
14755
15027
|
const r = await sessions.run({
|
|
14756
15028
|
stage: "deep",
|
|
14757
15029
|
tier: "development",
|
|
@@ -14821,7 +15093,7 @@ ${r.stderr}`), lr = r.exitCode === 0 ? undefined : await harnessLoadReason({ rep
|
|
|
14821
15093
|
async function runAppBoot(ctx, opts, checks, notProven) {
|
|
14822
15094
|
let r;
|
|
14823
15095
|
try {
|
|
14824
|
-
r = await (opts.appProbe ?? appProbe)(ctx.repoDir,
|
|
15096
|
+
r = await (opts.appProbe ?? appProbe)(ctx.repoDir, join58(ctx.repoDir, ".loki"));
|
|
14825
15097
|
} catch (err) {
|
|
14826
15098
|
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
15099
|
}
|
|
@@ -14867,12 +15139,12 @@ async function runCouncilCheck(ctx, changed, baseSha, signal, opts, checks, notP
|
|
|
14867
15139
|
}
|
|
14868
15140
|
}
|
|
14869
15141
|
async function secureScanChanged(repoDir, changed, opts) {
|
|
14870
|
-
const dir = mkdtempSync9(
|
|
15142
|
+
const dir = mkdtempSync9(join58(tmpdir10(), "loki-deep-secure-"));
|
|
14871
15143
|
try {
|
|
14872
15144
|
for (const f of changed)
|
|
14873
|
-
if (
|
|
14874
|
-
mkdirSync24(
|
|
14875
|
-
copyFileSync3(
|
|
15145
|
+
if (existsSync38(join58(repoDir, f)) && lstatSync14(join58(repoDir, f)).isFile()) {
|
|
15146
|
+
mkdirSync24(dirname23(join58(dir, f)), { recursive: true });
|
|
15147
|
+
copyFileSync3(join58(repoDir, f), join58(dir, f));
|
|
14876
15148
|
}
|
|
14877
15149
|
return await runSecureScan(dir, { ...opts.secureScanPath ? { scriptPath: opts.secureScanPath } : {}, timeoutMs: 60000 });
|
|
14878
15150
|
} finally {
|
|
@@ -14881,7 +15153,7 @@ async function secureScanChanged(repoDir, changed, opts) {
|
|
|
14881
15153
|
}
|
|
14882
15154
|
async function runSecretScan(ctx, changed, opts, checks, notProven) {
|
|
14883
15155
|
const scriptPath = opts.secretScanShPath ?? DEFAULT_SECRET_SCAN_SH, name = "security scan", cmd2 = "secret-scan.sh + secure-scan.py";
|
|
14884
|
-
if (!
|
|
15156
|
+
if (!existsSync38(scriptPath)) {
|
|
14885
15157
|
checks.push({ name, cmd: cmd2, result: "not_run", duration_s: 0 });
|
|
14886
15158
|
notProven.add(`not run: ${name} (secret-scan.sh not found)`);
|
|
14887
15159
|
return;
|
|
@@ -14892,7 +15164,7 @@ async function runSecretScan(ctx, changed, opts, checks, notProven) {
|
|
|
14892
15164
|
}
|
|
14893
15165
|
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
15166
|
const started = Date.now();
|
|
14895
|
-
const r = await run(["bash", "-c", inline, "_", scriptPath, ...changed.map((f) =>
|
|
15167
|
+
const r = await run(["bash", "-c", inline, "_", scriptPath, ...changed.map((f) => join58(ctx.repoDir, f))], { cwd: ctx.repoDir, timeoutMs: 30000 });
|
|
14896
15168
|
const sec = await secureScanChanged(ctx.repoDir, changed, opts), gaps = [], reasons = [];
|
|
14897
15169
|
const hits = r.exitCode === 3 ? [] : r.stdout.split(`
|
|
14898
15170
|
`).map((l) => l.trim()).filter(Boolean), high = sec.findings.filter((f) => String(f.severity).toUpperCase() === "HIGH");
|
|
@@ -14933,7 +15205,7 @@ async function postResults(ctx, opts, checks, notProven, statusState) {
|
|
|
14933
15205
|
const prNumber = prUrl ? PR_NUMBER_RE.exec(prUrl)?.[1] : undefined;
|
|
14934
15206
|
if (prNumber) {
|
|
14935
15207
|
mkdirSync24(ctx.runDir, { recursive: true });
|
|
14936
|
-
const bodyFile =
|
|
15208
|
+
const bodyFile = join58(ctx.runDir, "deep-comment.md");
|
|
14937
15209
|
writeFileSync27(bodyFile, buildCommentBody(checks, notProven, statusState), "utf8");
|
|
14938
15210
|
const commentResult = await run(["bash", scriptPath, ...commentArgv(prNumber, bodyFile)], { cwd: ctx.repoDir, env, timeoutMs: 30000 });
|
|
14939
15211
|
if (commentResult.exitCode !== 0)
|
|
@@ -14988,7 +15260,7 @@ async function runDeep(ctx, signal, opts = {}) {
|
|
|
14988
15260
|
const sig = signReceipt(`${ctx.runId}-deep`, addendumSha256);
|
|
14989
15261
|
const addendum = { ...addendumBody, addendum_sha256: addendumSha256, verification: { jwt: sig.jwt, kid: sig.kid } };
|
|
14990
15262
|
mkdirSync24(ctx.runDir, { recursive: true });
|
|
14991
|
-
writeFileSync27(
|
|
15263
|
+
writeFileSync27(join58(ctx.runDir, "receipt-addendum-1.json"), JSON.stringify(addendum, null, 2) + `
|
|
14992
15264
|
`);
|
|
14993
15265
|
const pushNotProven = await postResults(ctx, opts, checks, notProvenList, statusState);
|
|
14994
15266
|
const allNotProven = [...notProvenList, ...pushNotProven];
|
|
@@ -15024,9 +15296,9 @@ var init_deep = __esm(() => {
|
|
|
15024
15296
|
});
|
|
15025
15297
|
|
|
15026
15298
|
// ../../loki-ts/src/engine10/stages/verify.ts
|
|
15027
|
-
import { existsSync as
|
|
15299
|
+
import { existsSync as existsSync39, mkdtempSync as mkdtempSync10, rmSync as rmSync18 } from "fs";
|
|
15028
15300
|
import { tmpdir as tmpdir11 } from "os";
|
|
15029
|
-
import { isAbsolute as
|
|
15301
|
+
import { isAbsolute as isAbsolute10, join as join59, relative as relative10 } from "path";
|
|
15030
15302
|
async function runOnce2(cmd2, args, cwd, signal, opts) {
|
|
15031
15303
|
if (!Bun.which(cmd2, { PATH: opts.path ?? process.env["PATH"] ?? "" }))
|
|
15032
15304
|
return { ok: false, missing: true, cut: false, out: "" };
|
|
@@ -15100,7 +15372,7 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal,
|
|
|
15100
15372
|
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
15373
|
if (!(un.some(({ c }) => c.result === "fail" && c.ids?.length) || sus.length || zc.length) || signal.aborted)
|
|
15102
15374
|
return out2;
|
|
15103
|
-
const dir = mkdtempSync10(
|
|
15375
|
+
const dir = mkdtempSync10(join59(tmpdir11(), "e10-base-"));
|
|
15104
15376
|
const git4 = (args) => {
|
|
15105
15377
|
safeGit(ctx.repoDir, args, { stdio: "ignore", repoDrivers: true });
|
|
15106
15378
|
};
|
|
@@ -15139,7 +15411,7 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal,
|
|
|
15139
15411
|
return out2;
|
|
15140
15412
|
}
|
|
15141
15413
|
function isLokiModeRepo(repoDir) {
|
|
15142
|
-
return
|
|
15414
|
+
return existsSync39(join59(repoDir, "scripts", "select-tests.sh"));
|
|
15143
15415
|
}
|
|
15144
15416
|
async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
|
|
15145
15417
|
const { api, ...runOpts } = opts;
|
|
@@ -15161,9 +15433,9 @@ async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
|
|
|
15161
15433
|
}
|
|
15162
15434
|
for (const g of groupByPackage(api, ctx.repoDir, changed.filter((f) => /\.(ts|tsx|js|jsx)$/.test(f)))) {
|
|
15163
15435
|
const sfx = g.root === "." ? "" : `:${g.root}`, co = g.root === "." ? opts : { ...opts, cwd: g.cwd };
|
|
15164
|
-
if (
|
|
15436
|
+
if (existsSync39(join59(g.cwd, "tsconfig.json")))
|
|
15165
15437
|
await runCheck(ctx, `lint:tsc${sfx}`, "npx", ["--no-install", "tsc", "--noEmit", "-p", "."], signal, checks, { ...co, kind: "static" });
|
|
15166
|
-
if (ESLINT_CONFIGS.some((f) =>
|
|
15438
|
+
if (ESLINT_CONFIGS.some((f) => existsSync39(join59(g.cwd, f)))) {
|
|
15167
15439
|
const c = await runCheck(ctx, `lint:eslint${sfx}`, "npx", ["--no-install", "eslint", ...g.rel], signal, checks, { ...co, kind: "static" });
|
|
15168
15440
|
if (await excuseLint(ctx, signal, c, "eslint", "npx", ["--no-install", "eslint"], g.cwd, g.rel, co))
|
|
15169
15441
|
pre.push(c.name);
|
|
@@ -15178,7 +15450,7 @@ var CHECK_TIMEOUT_MS = 60000, excerpts, isHold = (c) => isHoldoutCheck(c.name),
|
|
|
15178
15450
|
return r.missing || r.cut ? null : r;
|
|
15179
15451
|
}, base: (f) => {
|
|
15180
15452
|
try {
|
|
15181
|
-
return safeGit(ctx.repoDir, ["show", `${ctx.baseSha}:${
|
|
15453
|
+
return safeGit(ctx.repoDir, ["show", `${ctx.baseSha}:${relative10(ctx.repoDir, join59(cwd, f))}`], { stdio: ["ignore", "pipe", "ignore"] });
|
|
15182
15454
|
} catch {
|
|
15183
15455
|
return null;
|
|
15184
15456
|
}
|
|
@@ -15243,7 +15515,7 @@ var init_verify = __esm(() => {
|
|
|
15243
15515
|
const impacted = ctx.tests.impacted(map, changed);
|
|
15244
15516
|
const changedTestFiles = map.tests.filter((t) => changed.includes(t.path));
|
|
15245
15517
|
const wall = ctx.outputs().wall ?? {};
|
|
15246
|
-
const wallPaths = new Set((wall.files ?? []).map((f) =>
|
|
15518
|
+
const wallPaths = new Set((wall.files ?? []).map((f) => isAbsolute10(f.path) ? relative10(ctx.repoDir, f.path) : f.path));
|
|
15247
15519
|
const intake = ctx.outputs().intake, repoMap = loadRepoMap(intake?.repomap_ref), relevant2 = ctx.tests.impacted(map, namedFiles(intake?.task ?? "", repoMap));
|
|
15248
15520
|
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
15521
|
const tests = failedFirst(dedupeTests([...impacted, ...changedTestFiles, ...wallTests, ...relevant2]), ctx.outputs().verify?.checks);
|
|
@@ -15350,253 +15622,6 @@ ${x}` : c.cmd };
|
|
|
15350
15622
|
};
|
|
15351
15623
|
});
|
|
15352
15624
|
|
|
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
15625
|
// ../../loki-ts/src/engine10/stages/wall.ts
|
|
15601
15626
|
import { spawnSync as spawnSync7 } from "child_process";
|
|
15602
15627
|
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 +15765,7 @@ async function wallAuthor(ctx, signal, retry) {
|
|
|
15740
15765
|
});
|
|
15741
15766
|
const bad1 = oor();
|
|
15742
15767
|
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 });
|
|
15768
|
+
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
15769
|
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
15770
|
const sealedDir = join60(ctx.runDir, "wall");
|
|
15750
15771
|
if (generated.length > 0)
|
|
@@ -16653,7 +16674,7 @@ function supplyVerdict(verdict, r) {
|
|
|
16653
16674
|
return r.blocked && verdict === "VERIFIED" ? "FAILED" : verdict;
|
|
16654
16675
|
}
|
|
16655
16676
|
function isManifestPath(path) {
|
|
16656
|
-
return
|
|
16677
|
+
return MANIFESTS.test(basename25(path));
|
|
16657
16678
|
}
|
|
16658
16679
|
function readDeclared(repoDir) {
|
|
16659
16680
|
const p = join68(repoDir, ".loki", DECLARED_FILE);
|
|
@@ -16851,7 +16872,7 @@ async function supplyGuard(repoDir, changedFiles2, declared, env, opts = {}) {
|
|
|
16851
16872
|
}
|
|
16852
16873
|
return { block: { guard: "v2", warn_age_days: MIN_AGE_DAYS, fail_age_days: failAge, declared: declared.deps.length, entries }, notProven, blocked };
|
|
16853
16874
|
}
|
|
16854
|
-
var MIN_AGE_DAYS = 7, DECLARED_FILE = "supply-declared.json", MAX_CHECKED = 50, MAX_DECLARED = 200, MAX_FILE_BYTES, DAY_MS = 86400000,
|
|
16875
|
+
var MIN_AGE_DAYS = 7, DECLARED_FILE = "supply-declared.json", MAX_CHECKED = 50, MAX_DECLARED = 200, MAX_FILE_BYTES, DAY_MS = 86400000, MANIFESTS, ECO, NAME2, defaultResolver = async (dep, cwd) => {
|
|
16855
16876
|
const argv = {
|
|
16856
16877
|
npm: ["npm", "view", dep.name, "time.created", "--json"],
|
|
16857
16878
|
pypi: ["pip", "index", "versions", "--pre", "--ignore-requires-python", dep.name],
|
|
@@ -16877,7 +16898,7 @@ var MIN_AGE_DAYS = 7, DECLARED_FILE = "supply-declared.json", MAX_CHECKED = 50,
|
|
|
16877
16898
|
var init_supply_guard = __esm(() => {
|
|
16878
16899
|
init_shell();
|
|
16879
16900
|
MAX_FILE_BYTES = 64 * 1024;
|
|
16880
|
-
|
|
16901
|
+
MANIFESTS = /^(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)?)$/;
|
|
16881
16902
|
ECO = { npm: "npm", node: "npm", pypi: "pypi", pip: "pypi", python: "pypi", cargo: "cargo", crates: "cargo", go: "go", golang: "go" };
|
|
16882
16903
|
NAME2 = /^[A-Za-z0-9@][A-Za-z0-9@._/~+-]{0,213}$/;
|
|
16883
16904
|
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"]);
|