loki-mode 11.17.82 → 11.17.84

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