loki-mode 11.17.37 → 11.17.39

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 (77) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/lib/chat.sh +3 -2
  4. package/autonomy/lib/config-map.sh +11 -4
  5. package/autonomy/lib/secret-scan.sh +1 -0
  6. package/autonomy/loki +172 -8
  7. package/autonomy/verify.sh +1 -0
  8. package/completions/_loki +5 -0
  9. package/completions/loki.bash +2 -2
  10. package/dashboard/__init__.py +1 -1
  11. package/docs/CLI-REFERENCE.md +1 -1
  12. package/docs/DEPLOYMENT.md +22 -0
  13. package/docs/INSTALLATION.md +1 -1
  14. package/docs/v10/BOARD.md +52 -19
  15. package/docs/v10/PROGRESS.md +6 -0
  16. package/loki-ts/dist/loki.js +1274 -1257
  17. package/mcp/__init__.py +1 -1
  18. package/package.json +2 -2
  19. package/packages/control-plane/dist/server.js +512 -318
  20. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  21. package/web-app/dist/assets/{AdminPage-8Ms4e7v3.js → AdminPage-sMRXVp8V.js} +1 -1
  22. package/web-app/dist/assets/{Avatar-D-_RMtAF.js → Avatar-sqshsKDj.js} +1 -1
  23. package/web-app/dist/assets/{Badge-BiTryACM.js → Badge-DVLT6AZl.js} +1 -1
  24. package/web-app/dist/assets/{Button-D5J90sJA.js → Button-CUGOx2F-.js} +1 -1
  25. package/web-app/dist/assets/{CockpitPage-CBsCLHsX.js → CockpitPage-_5XpWSyB.js} +1 -1
  26. package/web-app/dist/assets/{ComparePage-ZU4NYIxk.js → ComparePage-CHybAwF6.js} +1 -1
  27. package/web-app/dist/assets/{ErrorBoundary-kRsIDD2c.js → ErrorBoundary-yws0dvvJ.js} +1 -1
  28. package/web-app/dist/assets/{EvidenceReceiptPanel-DV6ZxN0r.js → EvidenceReceiptPanel-DQPXKaYq.js} +1 -1
  29. package/web-app/dist/assets/{GitHubIssuesPanel-B0uPt2Uy.js → GitHubIssuesPanel-CDnklfFn.js} +1 -1
  30. package/web-app/dist/assets/{GitHubPRsPanel-DnrIz7Qh.js → GitHubPRsPanel-F1H3q6Mg.js} +1 -1
  31. package/web-app/dist/assets/{HomePage-SjkWXTYO.js → HomePage-Donxu3UG.js} +2 -2
  32. package/web-app/dist/assets/{LoginPage-D1XU1UOK.js → LoginPage-vabZaQ4T.js} +1 -1
  33. package/web-app/dist/assets/{MagicPage-Cg6MzSOR.js → MagicPage-zJiSFKm6.js} +1 -1
  34. package/web-app/dist/assets/{MetricsPage-Bs4xxEL4.js → MetricsPage-tW1d9Pc4.js} +1 -1
  35. package/web-app/dist/assets/{NotFoundPage-xoIjTbo3.js → NotFoundPage-DfL2kcAp.js} +1 -1
  36. package/web-app/dist/assets/{ProjectPage-DtX7g5N3.js → ProjectPage-Bnx3Slii.js} +3 -3
  37. package/web-app/dist/assets/{ProjectsPage-BZiUAYq4.js → ProjectsPage-C74jNljb.js} +1 -1
  38. package/web-app/dist/assets/{SettingsPage-BGWiG3O9.js → SettingsPage-FA9_6XvR.js} +1 -1
  39. package/web-app/dist/assets/{ShowcasePage-DgrnwUsK.js → ShowcasePage-CUYKoPB0.js} +1 -1
  40. package/web-app/dist/assets/{SystemSettingsPage-cHvinh4M.js → SystemSettingsPage-ClEk_OL-.js} +1 -1
  41. package/web-app/dist/assets/{TeamsPage-BVCDcah9.js → TeamsPage-CZod1nxw.js} +1 -1
  42. package/web-app/dist/assets/{TemplatesPage-BVZWaHmc.js → TemplatesPage-ftxcEJ5S.js} +1 -1
  43. package/web-app/dist/assets/{TerminalOutput-DXipqPhV.js → TerminalOutput-C-ztoDne.js} +1 -1
  44. package/web-app/dist/assets/{activity-CshhOoCC.js → activity-ClWb6nuh.js} +1 -1
  45. package/web-app/dist/assets/{bell-C2aVKCgl.js → bell-DSdTj9Kf.js} +1 -1
  46. package/web-app/dist/assets/{bot-CS4hsHcl.js → bot-DX8ebhTj.js} +1 -1
  47. package/web-app/dist/assets/{check-C9BOGqR2.js → check-6OAuuO_W.js} +1 -1
  48. package/web-app/dist/assets/{chevron-left-BBTdOAuW.js → chevron-left-DTdjxSL_.js} +1 -1
  49. package/web-app/dist/assets/{circle-alert-D7SSuEIf.js → circle-alert-B40DtHik.js} +1 -1
  50. package/web-app/dist/assets/{clock-CHFYgPU3.js → clock-cVEP2obv.js} +1 -1
  51. package/web-app/dist/assets/{cloud-cEefzPuf.js → cloud-CmG80ODy.js} +1 -1
  52. package/web-app/dist/assets/{code-xml-B7St2q5i.js → code-xml-uDISZWZx.js} +1 -1
  53. package/web-app/dist/assets/{database-irsYoPwy.js → database-BBjrBzZH.js} +1 -1
  54. package/web-app/dist/assets/{dollar-sign-ChdZBjDE.js → dollar-sign-QuSiEBvi.js} +1 -1
  55. package/web-app/dist/assets/{file-code-corner-CdnsaqHY.js → file-code-corner-DaYWw_54.js} +1 -1
  56. package/web-app/dist/assets/{file-plus-Cm5WJLtA.js → file-plus-DBrjgfG0.js} +1 -1
  57. package/web-app/dist/assets/{globe-itCMNb3u.js → globe-yLg95rUG.js} +1 -1
  58. package/web-app/dist/assets/{hammer-DpZbHRqZ.js → hammer-Cm_tQ3f7.js} +1 -1
  59. package/web-app/dist/assets/{index-BY6H3gcR.js → index-WwgJyEgR.js} +3 -3
  60. package/web-app/dist/assets/{layers-Pja4FEia.js → layers-CVu0QAr_.js} +1 -1
  61. package/web-app/dist/assets/{loader-circle-CeRQm3kJ.js → loader-circle-C1ByA4HR.js} +1 -1
  62. package/web-app/dist/assets/{lock-DN-Y7N_K.js → lock-COFCj4kU.js} +1 -1
  63. package/web-app/dist/assets/{package-xmriszo-.js → package-DPdWCR4l.js} +1 -1
  64. package/web-app/dist/assets/{plus-_Uj6A6jB.js → plus-CP2Oh8yP.js} +1 -1
  65. package/web-app/dist/assets/{refresh-cw-BsssvIIM.js → refresh-cw-CR9Wf9cI.js} +1 -1
  66. package/web-app/dist/assets/{rotate-ccw-BuGEgNBP.js → rotate-ccw-jJugFDir.js} +1 -1
  67. package/web-app/dist/assets/{scroll-text-D3I5iPxb.js → scroll-text-BiJUO5k9.js} +1 -1
  68. package/web-app/dist/assets/{server-CmqFqyr6.js → server-US70f4RI.js} +1 -1
  69. package/web-app/dist/assets/{shield-alert-BDfXzBqa.js → shield-alert-C7ig1ziQ.js} +1 -1
  70. package/web-app/dist/assets/{thumbs-up-_tO386xs.js → thumbs-up-D3SDwx7o.js} +1 -1
  71. package/web-app/dist/assets/{trash-2-BY17xDYh.js → trash-2-CikJqAs_.js} +1 -1
  72. package/web-app/dist/assets/{trending-down-2q53wyOn.js → trending-down-Bcyok37Q.js} +1 -1
  73. package/web-app/dist/assets/{trending-up-k3BMoWKv.js → trending-up-CFJbw392.js} +1 -1
  74. package/web-app/dist/assets/{upload-BchR2Xs4.js → upload-BvhLwHkC.js} +1 -1
  75. package/web-app/dist/assets/{usePolling-DO8v6wKt.js → usePolling-Bck_ydy1.js} +1 -1
  76. package/web-app/dist/assets/{user-ThJCW69N.js → user-BpuwYFeB.js} +1 -1
  77. package/web-app/dist/index.html +1 -1
@@ -146,7 +146,9 @@ var init_redact = __esm(() => {
146
146
  [/eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g, "[REDACTED:JWT]"],
147
147
  [/AI[a-zA-Z0-9_-]{30,}/g, "[REDACTED:GOOGLE_KEY]"],
148
148
  [/sk-[A-Za-z0-9_-]{20,}/g, "[REDACTED:OPENAI_KEY]"],
149
- [/(Bearer\s+)[A-Za-z0-9._~+/=-]{20,}/g, "$1[REDACTED]"]
149
+ [/(Bearer\s+)[A-Za-z0-9._~+/=-]{20,}/g, "$1[REDACTED]"],
150
+ [/(\b[a-z][a-z0-9+.-]*:\/\/)[^\s/?#@]+@/gi, "$1[REDACTED]@"],
151
+ [/(\bAuthorization\s*[:=]\s*)(?:Basic|Bearer|Token|Digest)?\s*[^\s,;"']+/gi, "$1[REDACTED]"]
150
152
  ];
151
153
  });
152
154
 
@@ -7795,9 +7797,7 @@ function readJson3(path, isValid = (_v) => true) {
7795
7797
  function isRepoMap(v) {
7796
7798
  return typeof v === "object" && v !== null && Array.isArray(v.files) && Array.isArray(v.entries);
7797
7799
  }
7798
- function readRepoMapCache(dir, tree) {
7799
- return readJson3(resolve8(dir, `repomap2-${tree}.json`), isRepoMap);
7800
- }
7800
+ var readRepoMapCache = (dir, tree) => readJson3(resolve8(dir, `repomap2-${tree}.json`), isRepoMap);
7801
7801
  var init_cache = __esm(() => {
7802
7802
  init_paths();
7803
7803
  });
@@ -9791,8 +9791,8 @@ var init_testmap = __esm(() => {
9791
9791
  });
9792
9792
 
9793
9793
  // ../../loki-ts/src/util/check_result.ts
9794
- import { mkdirSync as mkdirSync13, readFileSync as readFileSync29, renameSync as renameSync8, writeFileSync as writeFileSync16 } from "fs";
9795
- import { basename as basename11, join as join38 } from "path";
9794
+ import { existsSync as existsSync23, mkdirSync as mkdirSync13, readFileSync as readFileSync29, realpathSync as realpathSync17, renameSync as renameSync8, writeFileSync as writeFileSync16 } from "fs";
9795
+ import { basename as basename11, isAbsolute as isAbsolute3, join as join38 } from "path";
9796
9796
  function plainTestEnv(base = process.env) {
9797
9797
  const e = {};
9798
9798
  for (const [k, v] of Object.entries(tokenFreeEnv(base)))
@@ -10006,6 +10006,8 @@ function checkProvenance(name, ctx) {
10006
10006
  return "independent";
10007
10007
  if (ctx.addedFiles.some((a) => normPath(a) === p))
10008
10008
  return "agent_authored";
10009
+ if (ctx.modifiedFiles?.some((m) => normPath(m) === p))
10010
+ return "agent_authored";
10009
10011
  }
10010
10012
  return "exogenous";
10011
10013
  }
@@ -10161,6 +10163,92 @@ function failureExcerpt(out2, repoDir = "", cap = EXCERPT_GROUP_CAP) {
10161
10163
  body = redactSecrets(body);
10162
10164
  return truncateBytes(body, cap);
10163
10165
  }
10166
+ function pytestCollectionIsRed(output, repoDir) {
10167
+ if (/ModuleNotFoundError/.test(output))
10168
+ return false;
10169
+ const real2 = (p) => {
10170
+ try {
10171
+ return realpathSync17(isAbsolute3(p) ? p : join38(repoDir, p));
10172
+ } catch {
10173
+ return null;
10174
+ }
10175
+ };
10176
+ const repoReal = real2(repoDir);
10177
+ const under = (p) => {
10178
+ const r = real2(p);
10179
+ return !!repoReal && !!r && (r === repoReal || r.startsWith(`${repoReal}/`));
10180
+ };
10181
+ const imp = /ImportError: cannot import name .* from ['"][\w.]+['"] \(([^)]+)\)/.exec(output);
10182
+ if (imp)
10183
+ return under(imp[1]);
10184
+ const hdr = [...output.matchAll(/^=+ short test summary info =+$/gm)].pop();
10185
+ if (!hdr)
10186
+ return false;
10187
+ const cls = [...output.slice(hdr.index).matchAll(/^ERROR \S+ - (\w+Error): /gm)].pop()?.[1];
10188
+ if (cls !== "AttributeError" && cls !== "NameError")
10189
+ return false;
10190
+ const start = output.search(/^_+ ERROR collecting /m);
10191
+ if (start < 0 || start > hdr.index)
10192
+ return false;
10193
+ const block = output.slice(start, hdr.index).split(/^-+ Captured .*$/m)[0];
10194
+ const eLines = [...block.matchAll(new RegExp(`^E {3}${cls}: (.*)$`, "gm"))];
10195
+ const eLine = eLines[eLines.length - 1];
10196
+ if (!eLine)
10197
+ return false;
10198
+ if (cls === "AttributeError") {
10199
+ const m = /^module ['"]([\w.]+)['"] has no attribute/.exec(eLine[1]);
10200
+ return !!m && moduleUnderRepo(repoDir, m[1]);
10201
+ }
10202
+ const frames = [...block.slice(0, eLine.index).matchAll(/^(.+?):\d+: in \S+\n\s*(.*)$/gm)];
10203
+ const last = frames[frames.length - 1];
10204
+ return !!last && under(last[1]) && !/^\s*(import\s|from\s\S+\s+import\b)/.test(last[2] ?? "");
10205
+ }
10206
+ function moduleUnderRepo(repoDir, name) {
10207
+ const rel = name.replace(/\./g, "/");
10208
+ return existsSync23(join38(repoDir, `${rel}.py`)) || existsSync23(join38(repoDir, rel, "__init__.py"));
10209
+ }
10210
+ function pytestExit1IsRed(output) {
10211
+ if (/^!+ _pytest\.outcomes\.Exit\b/m.test(output))
10212
+ return false;
10213
+ if (/^=*\s*(\d+ \w+(, )?)*\d+ failed\b.* in [\d.]+s/.test(output.trimEnd().split(`
10214
+ `).pop() ?? ""))
10215
+ return true;
10216
+ const hdr = [...output.matchAll(/^=+ short test summary info =+$/gm)].pop();
10217
+ return !!hdr && /^FAILED \S+/m.test(output.slice(hdr.index));
10218
+ }
10219
+ function parsedFailCount(runner, output) {
10220
+ const m = runner === "bun" ? /^\s*(\d+)\s+fail\s*$/m.exec(output) : runner === "jest" ? /Tests:\s*(\d+)\s+failed/i.exec(output) : runner === "vitest" ? /Tests\s+(\d+)\s+failed/i.exec(output) : null;
10221
+ return m ? Number(m[1]) : 0;
10222
+ }
10223
+ function nodeIsRed(f, raw2) {
10224
+ const o = raw2.replace(/^# (?!(?:tests|suites|pass|fail|cancelled|skipped|todo|duration_ms|Subtest)\b)/gm, "");
10225
+ const mod = /^Error(?: \[\w+\])?: Cannot find (?:module|package) '([^']+)'(?:(?!\u2716)[\s\S])*?\nNode\.js v/m.exec(o), top = /^(\S+):\d+\n.*\n.*\n\n?(?:ReferenceError|SyntaxError)\b/m.exec(o);
10226
+ const named = [...o.matchAll(/^(?:\u2716|\s*not ok \d+ -) (?!failing tests:)(.+?)(?: \(|$)/gm)].some((m) => !f.path.endsWith(m[1]) && !m[1].endsWith(f.path)), blk = o.split("failing tests:")[1] ?? "", esm = /^SyntaxError: The requested module '([^']+)' does not provide an export named/m.exec(o), errs = [...blk.matchAll(/^ {2}(\w+Error): .*\n\s+at (?:.*\()?([^\s()]+?):\d+:\d+/gm), ...o.matchAll(/^ +name: '(\w+Error)'\n(?:.*\n)*? +stack: \|-\n\s+(?:.*\()?([^\s()]+?):\d+:\d+/gm)];
10227
+ return /^(?:#|\u2139) fail [1-9]/m.test(raw2) && (/^ {2}AssertionError\b/m.test(blk) || /^ +name: 'AssertionError'/m.test(o) || (mod && !named ? /^[./]/.test(mod[1]) : esm ? /^[./]/.test(esm[1]) : top ? !top[1].endsWith(f.path) : !errs.length || errs.some((e) => !/^(?:Reference|Syntax)Error$/.test(e[1]) || !(e[2].startsWith("node:") || e[2].endsWith(f.path)))));
10228
+ }
10229
+ function notRunReason(status, interpreter) {
10230
+ if (interpreter === "system")
10231
+ return "ran under the system interpreter, not the project's, so the result proves nothing";
10232
+ if (status === null)
10233
+ return "the test runner did not start or timed out";
10234
+ if (status === 126 || status === 127)
10235
+ return `the test runner command was not found or not executable (exit ${status})`;
10236
+ return status === 0 ? "exit 0 but no executed test count could be confirmed" : `exit ${status} but the runner output showed no readable failing test`;
10237
+ }
10238
+ function classify(f, status, output, repoDir, interpreter) {
10239
+ if (interpreter === "system")
10240
+ return "not_run";
10241
+ output = stripAnsi(output);
10242
+ if (status === null || status === 126 || status === 127)
10243
+ return "not_run";
10244
+ if (status === 0)
10245
+ return classifyCheck({ kind: "test", ok: true, out: output, path: f.path, ...f.runner === "go" ? { runner: "go" } : {} }).result === "pass" ? "pass" : "not_run";
10246
+ if (f.runner === "pytest")
10247
+ return status === 1 ? pytestExit1IsRed(output) ? "fail" : "not_run" : status === 2 ? pytestCollectionIsRed(output, repoDir) ? "fail" : "not_run" : "not_run";
10248
+ if (f.runner === "jest" || f.runner === "vitest" || f.runner === "bun")
10249
+ return parsedFailCount(f.runner, output) > 0 ? "fail" : "not_run";
10250
+ return f.runner === "node" && nodeIsRed(f, output) ? "fail" : "not_run";
10251
+ }
10164
10252
  var NO_TESTS_REASON = "no tests executed", GO_EXIT0_REASON = "test count could not be confirmed: go test output is produced by the code under test and cannot confirm execution (a Go exit 0 is never a pass)", UNCONFIRMED_REASON = "test count could not be confirmed", FAIL_EVIDENCE, GO_FAIL_EVIDENCE, UNMEASURED_REASON = "executed count unmeasured (Loki could not parse the runner summary, harness-owned)", stripAnsi = (s) => s.replace(/\u001b\][^\u0007\u001b]*(?:\u0007|\u001b\\)/g, "").replace(/(?:\u001b\[|\u009b)[0-9;?]*[ -\/]*[@-~]/g, "").replace(/\r\n?/g, `
10165
10253
  `), tailLines = (out2) => out2.split(`
10166
10254
  `).filter((x) => x.trim()).slice(-12), GO_PKG_RE, isExecutedProof = (c) => c.result === "pass" && typeof c.n === "number" && c.n > 0, hasExecutedProof = (checks) => checks.some(isExecutedProof), LLM_JUDGES, NON_RUNNER, normPath = (p) => p.replace(/^(?:\.\/)+/, ""), hasExogenousProof = (checks, ctx) => checks.some((c) => isExecutedProof(c) && ((p) => p !== "agent_authored" && p !== "llm_judge")(checkProvenance(c.name ?? "", ctx))), SENSITIVE, API, TEST_CFG, RANK2, FILES_MEDIUM = 4, FILES_HIGH = 15, LINES_MEDIUM = 100, LINES_HIGH = 500, RAN_ALWAYS, PLAN, LOW_SKIPPED, deferredOf = (tier, selected, executed) => (tier === "low" ? LOW_SKIPPED : selected).filter((c) => !RAN_ALWAYS.includes(c) && !executed.includes(c)), EXCERPT_GROUP_CAP = 1500, EXCERPT_TOTAL_CAP = 6144;
@@ -10213,8 +10301,8 @@ var init_state = __esm(() => {
10213
10301
  });
10214
10302
 
10215
10303
  // ../../loki-ts/src/runner/repo_profile.ts
10216
- import { existsSync as existsSync23, readFileSync as readFileSync30, mkdirSync as mkdirSync14, readdirSync as readdirSync14, renameSync as renameSync9, rmSync as rmSync8, writeFileSync as writeFileSync17 } from "fs";
10217
- import { basename as basename12, join as join39, resolve as resolve13, isAbsolute as isAbsolute3 } from "path";
10304
+ import { existsSync as existsSync24, readFileSync as readFileSync30, mkdirSync as mkdirSync14, readdirSync as readdirSync14, renameSync as renameSync9, rmSync as rmSync8, writeFileSync as writeFileSync17 } from "fs";
10305
+ import { basename as basename12, join as join39, resolve as resolve13, isAbsolute as isAbsolute4 } from "path";
10218
10306
  function loadProfile(repoDir) {
10219
10307
  try {
10220
10308
  const p = JSON.parse(readFileSync30(commandProfilePath(repoDir), "utf8"));
@@ -10350,7 +10438,7 @@ var init_context = __esm(() => {
10350
10438
  });
10351
10439
 
10352
10440
  // ../../loki-ts/src/util/steer.ts
10353
- import { appendFileSync as appendFileSync2, closeSync as closeSync8, constants as constants2, fstatSync as fstatSync6, readdirSync as readdirSync15, lstatSync as lstatSync9, mkdirSync as mkdirSync15, linkSync as linkSync2, openSync as openSync8, readFileSync as readFileSync31, readSync as readSync7, renameSync as renameSync10, statSync as statSync15, lutimesSync, rmSync as rmSync9, unlinkSync as unlinkSync5, writeFileSync as writeFileSync18, existsSync as existsSync24 } from "fs";
10441
+ import { appendFileSync as appendFileSync2, closeSync as closeSync8, constants as constants2, fstatSync as fstatSync6, readdirSync as readdirSync15, lstatSync as lstatSync9, mkdirSync as mkdirSync15, linkSync as linkSync2, openSync as openSync8, readFileSync as readFileSync31, readSync as readSync7, renameSync as renameSync10, statSync as statSync15, lutimesSync, rmSync as rmSync9, unlinkSync as unlinkSync5, writeFileSync as writeFileSync18, existsSync as existsSync25 } from "fs";
10354
10442
  import { createHash as createHash9, randomBytes as randomBytes4 } from "crypto";
10355
10443
  import { basename as basename13, join as join40 } from "path";
10356
10444
  function archiveTo(logs, prefix, src, link = linkSync2, onLinked) {
@@ -10387,7 +10475,7 @@ function orphanAlreadyArchived(logs, claim) {
10387
10475
  const s = statSync15(join40(logs, a));
10388
10476
  if (s.ino !== c.ino || s.dev !== c.dev)
10389
10477
  continue;
10390
- if (/^human-input-(ORPHAN|REJECTED)-/.test(a) || existsSync24(appliedMarker(logs, a)))
10478
+ if (/^human-input-(ORPHAN|REJECTED)-/.test(a) || existsSync25(appliedMarker(logs, a)))
10391
10479
  return true;
10392
10480
  } catch {}
10393
10481
  }
@@ -10689,12 +10777,12 @@ var init_seal_drift = __esm(() => {
10689
10777
  });
10690
10778
 
10691
10779
  // ../../loki-ts/src/util/spec_file.ts
10692
- import { isAbsolute as isAbsolute4, join as join41, relative as relative2 } from "path";
10780
+ import { isAbsolute as isAbsolute5, join as join41, relative as relative2 } from "path";
10693
10781
  function specReceiptBlock(env) {
10694
10782
  const { LOKI_E10_SPEC_PATH: p, LOKI_E10_SPEC_SHA256: sha2 } = env;
10695
10783
  if (!p || !sha2)
10696
10784
  return {};
10697
- const rel = isAbsolute4(p) && env.LOKI_E10_REPO_DIR ? relative2(env.LOKI_E10_REPO_DIR, p) : p;
10785
+ const rel = isAbsolute5(p) && env.LOKI_E10_REPO_DIR ? relative2(env.LOKI_E10_REPO_DIR, p) : p;
10698
10786
  return { spec: { path: rel, sha256: sha2 } };
10699
10787
  }
10700
10788
  var SPEC_DIR;
@@ -10720,11 +10808,11 @@ var init_run_cap = __esm(() => {
10720
10808
  });
10721
10809
 
10722
10810
  // ../../loki-ts/src/util/mutation_proof.ts
10723
- import { existsSync as existsSync25, mkdirSync as mkdirSync16, mkdtempSync as mkdtempSync3, readFileSync as readFileSync32, rmSync as rmSync10, symlinkSync, writeFileSync as writeFileSync19 } from "fs";
10811
+ import { existsSync as existsSync26, mkdirSync as mkdirSync16, mkdtempSync as mkdtempSync3, readFileSync as readFileSync32, rmSync as rmSync10, symlinkSync, writeFileSync as writeFileSync19 } from "fs";
10724
10812
  import { tmpdir as tmpdir4 } from "os";
10725
- import { basename as basename14, dirname as dirname13, isAbsolute as isAbsolute5, join as join42, relative as relative3 } from "path";
10813
+ import { basename as basename14, dirname as dirname13, isAbsolute as isAbsolute6, join as join42, relative as relative3 } from "path";
10726
10814
  function mutationProof(i) {
10727
- const rels = i.wallFiles.map((f) => isAbsolute5(f.path) ? relative3(i.repoDir, f.path) : f.path);
10815
+ const rels = i.wallFiles.map((f) => isAbsolute6(f.path) ? relative3(i.repoDir, f.path) : f.path);
10728
10816
  if (rels.length === 0)
10729
10817
  return np("no Wall tests");
10730
10818
  const tests = rels.flatMap((rel) => {
@@ -10743,12 +10831,12 @@ function mutationProof(i) {
10743
10831
  parent = mkdtempSync3(join42(tmpdir4(), "loki-mutproof-"));
10744
10832
  wt = join42(parent, "wt");
10745
10833
  const add3 = git(i.repoDir, ["worktree", "add", "--detach", wt, i.baseSha], Math.max(1000, Math.min(30000, remaining())));
10746
- added = existsSync25(wt) || add3.status === 0;
10834
+ added = existsSync26(wt) || add3.status === 0;
10747
10835
  if (add3.status !== 0)
10748
10836
  return np("could not create the base worktree");
10749
10837
  for (const rel of rels) {
10750
- const sealed = join42(i.runDir, "wall", basename14(rel)), src = existsSync25(sealed) ? sealed : join42(i.repoDir, rel);
10751
- if (!existsSync25(src))
10838
+ const sealed = join42(i.runDir, "wall", basename14(rel)), src = existsSync26(sealed) ? sealed : join42(i.repoDir, rel);
10839
+ if (!existsSync26(src))
10752
10840
  return np(`Wall file missing: ${rel}`);
10753
10841
  mkdirSync16(dirname13(join42(wt, rel)), { recursive: true });
10754
10842
  writeFileSync19(join42(wt, rel), readFileSync32(src));
@@ -10759,7 +10847,7 @@ function mutationProof(i) {
10759
10847
  const anc = parts.slice(0, n2).join("/");
10760
10848
  for (const d of DEP_DIRS) {
10761
10849
  const src = join42(i.repoDir, anc, d), dst = join42(wt, anc, d);
10762
- if (existsSync25(src) && !existsSync25(dst)) {
10850
+ if (existsSync26(src) && !existsSync26(dst)) {
10763
10851
  try {
10764
10852
  symlinkSync(src, dst);
10765
10853
  } catch {}
@@ -10902,14 +10990,14 @@ var init_shell = __esm(() => {
10902
10990
  });
10903
10991
 
10904
10992
  // ../../loki-ts/src/util/python.ts
10905
- import { accessSync, constants as constants3, existsSync as existsSync26, mkdtempSync as mkdtempSync4, readFileSync as readFileSync33, realpathSync as realpathSync17, rmSync as rmSync11, statSync as statSync16 } from "fs";
10993
+ import { accessSync, constants as constants3, existsSync as existsSync27, mkdtempSync as mkdtempSync4, readFileSync as readFileSync33, realpathSync as realpathSync18, rmSync as rmSync11, statSync as statSync16 } from "fs";
10906
10994
  import { spawnSync as spawnSync2 } from "child_process";
10907
10995
  import { tmpdir as tmpdir5 } from "os";
10908
10996
  async function findPython3() {
10909
10997
  if (_pythonCache !== undefined)
10910
10998
  return _pythonCache;
10911
10999
  const homebrew = "/opt/homebrew/bin/python3.12";
10912
- if (existsSync26(homebrew)) {
11000
+ if (existsSync27(homebrew)) {
10913
11001
  _pythonCache = homebrew;
10914
11002
  return homebrew;
10915
11003
  }
@@ -11352,7 +11440,7 @@ Example: test('name', () => { assert.strictEqual(fn(1), 2); }); Run: node --tes
11352
11440
 
11353
11441
  // ../../loki-ts/src/util/holdout.ts
11354
11442
  import { createHash as createHash12 } from "crypto";
11355
- import { appendFileSync as appendFileSync3, copyFileSync as copyFileSync2, existsSync as existsSync27, mkdirSync as mkdirSync17, readFileSync as readFileSync34, rmSync as rmSync12, writeFileSync as writeFileSync20 } from "fs";
11443
+ import { appendFileSync as appendFileSync3, copyFileSync as copyFileSync2, existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as readFileSync34, rmSync as rmSync12, writeFileSync as writeFileSync20 } from "fs";
11356
11444
  import { tmpdir as tmpdir6 } from "os";
11357
11445
  import { basename as basename16, join as join43, relative as relative4 } from "path";
11358
11446
  function wallHoldoutRatio(env = process.env) {
@@ -11403,7 +11491,7 @@ function stageHoldout(dir, repoDir) {
11403
11491
  mkdirSync17(man.targetDir, { recursive: true });
11404
11492
  man.files.forEach((f, i) => {
11405
11493
  const src = join43(dir, f.name);
11406
- if (!existsSync27(src) || sha2(readFileSync34(src, "utf8")) !== f.sha256) {
11494
+ if (!existsSync28(src) || sha2(readFileSync34(src, "utf8")) !== f.sha256) {
11407
11495
  missing.push(`holdout ${i + 1} missing or altered`);
11408
11496
  return;
11409
11497
  }
@@ -12077,7 +12165,7 @@ var init_runner_errors = __esm(() => {
12077
12165
 
12078
12166
  // ../../loki-ts/src/runner/load_owner.ts
12079
12167
  import { spawnSync as spawnSync3 } from "child_process";
12080
- import { mkdtempSync as mkdtempSync6, realpathSync as realpathSync18, rmSync as rmSync14 } from "fs";
12168
+ import { mkdtempSync as mkdtempSync6, realpathSync as realpathSync19, rmSync as rmSync14 } from "fs";
12081
12169
  import { tmpdir as tmpdir8 } from "os";
12082
12170
  import { basename as basename18, extname as extname2, join as join46 } from "path";
12083
12171
  function changedFilesNamed(out2, repoDir, changed) {
@@ -12099,7 +12187,7 @@ function loadSignature(out2, roots) {
12099
12187
  let o = out2;
12100
12188
  for (const r of roots.flatMap((x) => {
12101
12189
  try {
12102
- return [x, realpathSync18(x)];
12190
+ return [x, realpathSync19(x)];
12103
12191
  } catch {
12104
12192
  return [x];
12105
12193
  }
@@ -12225,7 +12313,7 @@ var init_load_owner = __esm(() => {
12225
12313
  });
12226
12314
 
12227
12315
  // ../../loki-ts/src/util/wall_owned.ts
12228
- import { isAbsolute as isAbsolute6, join as join47, relative as relative5 } from "path";
12316
+ import { isAbsolute as isAbsolute7, join as join47, relative as relative5 } from "path";
12229
12317
  function failingLocations(raw2, cwd, repoDir) {
12230
12318
  const out2 = raw2.replace(ANSI2, "").replace(/\r\n?/g, `
12231
12319
  `), files = new Set;
@@ -12257,7 +12345,7 @@ function failingLocations(raw2, cwd, repoDir) {
12257
12345
  }
12258
12346
  if (errors2 === 0 || located !== errors2)
12259
12347
  return null;
12260
- return [...files].map((f) => relative5(repoDir, isAbsolute6(f) ? f : join47(cwd, f)));
12348
+ return [...files].map((f) => relative5(repoDir, isAbsolute7(f) ? f : join47(cwd, f)));
12261
12349
  }
12262
12350
  function wallOwnedFailure(raw2, cwd, repoDir, wall) {
12263
12351
  const locs = failingLocations(raw2, cwd, repoDir);
@@ -12270,7 +12358,7 @@ var init_wall_owned = __esm(() => {
12270
12358
 
12271
12359
  // ../../loki-ts/src/util/app_probe.ts
12272
12360
  import { spawnSync as spawnSync4 } from "child_process";
12273
- import { existsSync as existsSync28, mkdirSync as mkdirSync18, readFileSync as readFileSync37, renameSync as renameSync11, writeFileSync as writeFileSync21 } from "fs";
12361
+ import { existsSync as existsSync29, mkdirSync as mkdirSync18, readFileSync as readFileSync37, renameSync as renameSync11, writeFileSync as writeFileSync21 } from "fs";
12274
12362
  import { join as join48 } from "path";
12275
12363
  function readJson4(p) {
12276
12364
  try {
@@ -12282,7 +12370,7 @@ function readJson4(p) {
12282
12370
  }
12283
12371
  function stopApp(repoDir, opts = {}) {
12284
12372
  const runner = opts.runnerPath ?? join48(REPO_ROOT, "autonomy", "app-runner.sh");
12285
- if (!existsSync28(runner) || !existsSync28(join48(repoDir, ".loki", "app-runner", "app.pid")))
12373
+ if (!existsSync29(runner) || !existsSync29(join48(repoDir, ".loki", "app-runner", "app.pid")))
12286
12374
  return;
12287
12375
  spawnSync4("bash", ["-c", STOP, "app-probe", repoDir, runner], { cwd: repoDir, env: plainTestEnv(), timeout: opts.timeoutMs ?? 60000, killSignal: "SIGKILL", stdio: "ignore" });
12288
12376
  }
@@ -12296,7 +12384,7 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
12296
12384
  return { out: r.stdout ?? "", status: r.error ? null : r.status };
12297
12385
  };
12298
12386
  let pid = null, url = null;
12299
- if (!existsSync28(runner))
12387
+ if (!existsSync29(runner))
12300
12388
  return { checks: [mk2("app boot", "not_run", "app-runner.sh not found"), mk2("http probe", "not_run", "app not booted")], pid, url };
12301
12389
  try {
12302
12390
  const b = sh(BOOT);
@@ -12306,7 +12394,7 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
12306
12394
  return { checks, pid, url };
12307
12395
  }
12308
12396
  const ir = Number(m[1]), sr = Number(m[2]), hr = Number(m[3]);
12309
- const pidTxt = existsSync28(join48(dir, "app.pid")) ? readFileSync37(join48(dir, "app.pid"), "utf8").trim() : "";
12397
+ const pidTxt = existsSync29(join48(dir, "app.pid")) ? readFileSync37(join48(dir, "app.pid"), "utf8").trim() : "";
12310
12398
  pid = /^\d+$/.test(pidTxt) && sr >= 0 ? Number(pidTxt) : null;
12311
12399
  const st = readJson4(join48(dir, "state.json"));
12312
12400
  url = typeof st?.["url"] === "string" ? st["url"] : null;
@@ -12333,7 +12421,7 @@ async function functionalVerify(opts, url, dir, lokiDir2, timeoutMs) {
12333
12421
  const t0 = Date.now();
12334
12422
  const res = (result, reason) => ({ name: "functional verify", cmd: "autonomy/lib/functional-verify.py", result, duration_s: (Date.now() - t0) / 1000, reason });
12335
12423
  const py = await findPython3(), script = opts.verifyPath ?? join48(REPO_ROOT, "autonomy", "lib", "functional-verify.py");
12336
- if (!py || !existsSync28(script))
12424
+ if (!py || !existsSync29(script))
12337
12425
  return res("not_run", "python3 or functional-verify.py unavailable");
12338
12426
  const specFile = join48(dir, "spec.txt");
12339
12427
  writeFileSync21(specFile, opts.specText ?? "");
@@ -12381,14 +12469,15 @@ app_runner_stop >/dev/null 2>&1
12381
12469
  });
12382
12470
 
12383
12471
  // ../../loki-ts/src/util/secure_scan.ts
12384
- import { existsSync as existsSync29 } from "fs";
12385
- import { join as join49 } from "path";
12472
+ import { existsSync as existsSync30, mkdirSync as mkdirSync19, mkdtempSync as mkdtempSync7, readFileSync as readFileSync38, realpathSync as realpathSync20, rmSync as rmSync15, statSync as statSync17, writeFileSync as writeFileSync22 } from "fs";
12473
+ import { tmpdir as tmpdir9 } from "os";
12474
+ import { dirname as dirname16, join as join49, resolve as resolve14, sep as sep11 } from "path";
12386
12475
  function fail(error) {
12387
12476
  return { ok: false, findings: [], error };
12388
12477
  }
12389
12478
  async function runSecureScan(targetDir, opts = {}) {
12390
12479
  const script = opts.scriptPath ?? join49(REPO_ROOT, "autonomy", "lib", "secure-scan.py");
12391
- if (!existsSync29(script))
12480
+ if (!existsSync30(script))
12392
12481
  return fail(`secure-scan script not found: ${script}`);
12393
12482
  const py = await findPython3();
12394
12483
  if (!py)
@@ -12406,9 +12495,15 @@ async function runSecureScan(targetDir, opts = {}) {
12406
12495
  const obj = parsed && typeof parsed === "object" ? parsed : undefined;
12407
12496
  if ((res.exitCode === 0 || res.exitCode === 1) && obj && Array.isArray(obj.findings)) {
12408
12497
  const findings = obj.findings;
12409
- if (res.exitCode === 1 === findings.length > 0)
12498
+ if (res.exitCode === 1 !== findings.length > 0)
12499
+ return fail(`secure-scan exit ${res.exitCode} disagrees with ${findings.length} findings`);
12500
+ if (opts.secretsEverywhere || opts.diffBase === false)
12410
12501
  return { ok: true, findings };
12411
- return fail(`secure-scan exit ${res.exitCode} disagrees with ${findings.length} findings`);
12502
+ const added = await scanAddedLines(targetDir, { ...opts, scriptPath: script, timeoutMs });
12503
+ if (!added.ok)
12504
+ return added;
12505
+ const seen = new Set(findings.map((f) => `${f.file}|${f.line}`));
12506
+ return { ok: true, findings: [...findings, ...added.findings.filter((f) => !seen.has(`${f.file}|${f.line}`))] };
12412
12507
  }
12413
12508
  if (res.exitCode !== 0 && res.exitCode !== 1 && res.exitCode !== 2 && elapsed >= timeoutMs) {
12414
12509
  return fail(`secure-scan timed out after ${timeoutMs}ms`);
@@ -12419,10 +12514,194 @@ async function runSecureScan(targetDir, opts = {}) {
12419
12514
  `).slice(-3).join(" | ");
12420
12515
  return fail(`secure-scan failed (exit ${res.exitCode}): ${tail}`);
12421
12516
  }
12422
- var DEFAULT_SECURE_SCAN_TIMEOUT_MS = 120000;
12517
+ function git3(repoDir, args) {
12518
+ const r = safeGitSpawn(repoDir, args, { encoding: "utf8", maxBuffer: 64 * 1024 * 1024 });
12519
+ return r.status === 0 && typeof r.stdout === "string" ? r.stdout : null;
12520
+ }
12521
+ function isWorkTreeRoot(dir) {
12522
+ const top = git3(dir, ["rev-parse", "--show-toplevel"]);
12523
+ if (top === null)
12524
+ return false;
12525
+ try {
12526
+ return realpathSync20(top.trim()) === realpathSync20(dir);
12527
+ } catch {
12528
+ return false;
12529
+ }
12530
+ }
12531
+ function resolveDiffBase(repoDir, explicit) {
12532
+ const want = explicit ?? process.env["LOKI_SECURE_SCAN_BASE"];
12533
+ if (want)
12534
+ return git3(repoDir, ["rev-parse", "--verify", "--quiet", `${want}^{commit}`])?.trim() || null;
12535
+ for (const ref of ["refs/remotes/origin/HEAD", "@{upstream}"]) {
12536
+ const mb = git3(repoDir, ["merge-base", "HEAD", ref])?.trim();
12537
+ if (mb)
12538
+ return mb;
12539
+ }
12540
+ return git3(repoDir, ["rev-parse", "--verify", "--quiet", "HEAD^{commit}"])?.trim() || null;
12541
+ }
12542
+ function parseDiffHeaderPath(header) {
12543
+ let p = header;
12544
+ if (p.startsWith('"')) {
12545
+ const bytes = [];
12546
+ let i = 1;
12547
+ let closed = false;
12548
+ while (i < p.length) {
12549
+ const c = String.fromCodePoint(p.codePointAt(i));
12550
+ if (c === '"') {
12551
+ closed = true;
12552
+ break;
12553
+ }
12554
+ if (c !== "\\") {
12555
+ for (const b of Buffer.from(c, "utf8"))
12556
+ bytes.push(b);
12557
+ i += c.length;
12558
+ continue;
12559
+ }
12560
+ const e = p[i + 1] ?? "";
12561
+ const oct = /^[0-7]{3}/.exec(p.slice(i + 1, i + 4));
12562
+ if (oct) {
12563
+ bytes.push(parseInt(oct[0], 8));
12564
+ i += 4;
12565
+ continue;
12566
+ }
12567
+ const esc2 = { a: 7, b: 8, t: 9, n: 10, v: 11, f: 12, r: 13, '"': 34, "\\": 92 };
12568
+ if (!(e in esc2))
12569
+ return null;
12570
+ bytes.push(esc2[e]);
12571
+ i += 2;
12572
+ }
12573
+ if (!closed)
12574
+ return null;
12575
+ p = Buffer.from(bytes).toString("utf8");
12576
+ } else if (p.endsWith("\t")) {
12577
+ p = p.slice(0, -1);
12578
+ }
12579
+ return p.startsWith("b/") && p.length > 2 ? p.slice(2) : null;
12580
+ }
12581
+ function parseAddedLines(diff) {
12582
+ const out2 = new Map;
12583
+ let cur = null;
12584
+ let next = 0;
12585
+ let oldLeft = 0;
12586
+ let newLeft = 0;
12587
+ for (const line2 of diff.split(`
12588
+ `)) {
12589
+ if (oldLeft > 0 || newLeft > 0) {
12590
+ if (line2.startsWith("\\"))
12591
+ continue;
12592
+ if (line2.startsWith("+")) {
12593
+ if (cur)
12594
+ cur.set(next, line2.slice(1));
12595
+ next++;
12596
+ newLeft--;
12597
+ } else if (line2.startsWith("-")) {
12598
+ oldLeft--;
12599
+ } else {
12600
+ next++;
12601
+ oldLeft--;
12602
+ newLeft--;
12603
+ }
12604
+ continue;
12605
+ }
12606
+ if (line2.startsWith("diff --git ")) {
12607
+ cur = null;
12608
+ continue;
12609
+ }
12610
+ if (line2.startsWith("+++ ")) {
12611
+ const p = parseDiffHeaderPath(line2.slice(4));
12612
+ cur = p === null ? null : out2.get(p) ?? new Map;
12613
+ if (p !== null && cur)
12614
+ out2.set(p, cur);
12615
+ continue;
12616
+ }
12617
+ const m = /^@@ -\d+(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/.exec(line2);
12618
+ if (m) {
12619
+ oldLeft = m[1] === undefined ? 1 : Number(m[1]);
12620
+ next = Number(m[2]);
12621
+ newLeft = m[3] === undefined ? 1 : Number(m[3]);
12622
+ }
12623
+ }
12624
+ return out2;
12625
+ }
12626
+ async function scanAddedLines(repoDir, opts = {}) {
12627
+ if (opts.diffBase === false || !isWorkTreeRoot(repoDir))
12628
+ return { ok: true, findings: [] };
12629
+ const base = resolveDiffBase(repoDir, opts.diffBase);
12630
+ const added = new Map;
12631
+ if (base) {
12632
+ const diff = git3(repoDir, ["-c", "core.quotePath=false", "diff", "--src-prefix=a/", "--dst-prefix=b/", "-U0", "--no-color", "--no-ext-diff", "--no-renames", base, "--"]);
12633
+ if (diff === null)
12634
+ return fail(`secure-scan: git diff against ${base.slice(0, 12)} failed`);
12635
+ for (const [p, lines2] of parseAddedLines(diff))
12636
+ added.set(p, lines2);
12637
+ }
12638
+ const untracked = git3(repoDir, ["ls-files", "--others", "--exclude-standard", "-z"]);
12639
+ if (untracked === null)
12640
+ return fail("secure-scan: git ls-files failed");
12641
+ for (const p of untracked.split("\x00").filter(Boolean)) {
12642
+ try {
12643
+ const st = statSync17(join49(repoDir, p));
12644
+ if (!st.isFile() || st.size > MAX_ADDED_FILE_BYTES)
12645
+ continue;
12646
+ const lines2 = new Map;
12647
+ readFileSync38(join49(repoDir, p), "utf8").split(`
12648
+ `).forEach((t, i) => lines2.set(i + 1, t));
12649
+ added.set(p, lines2);
12650
+ } catch {}
12651
+ }
12652
+ if (added.size === 0)
12653
+ return { ok: true, findings: [] };
12654
+ const mirror = mkdtempSync7(join49(tmpdir9(), "loki-secure-added-"));
12655
+ try {
12656
+ const root = resolve14(mirror) + sep11;
12657
+ for (const [p, lines2] of added) {
12658
+ if (lines2.size === 0)
12659
+ continue;
12660
+ const dest = resolve14(mirror, p);
12661
+ if (!dest.startsWith(root))
12662
+ continue;
12663
+ const max = Math.max(...lines2.keys());
12664
+ const body = [];
12665
+ for (let i = 1;i <= max; i++)
12666
+ body.push(lines2.get(i) ?? "");
12667
+ mkdirSync19(dirname16(dest), { recursive: true });
12668
+ writeFileSync22(dest, body.join(`
12669
+ `) + `
12670
+ `);
12671
+ }
12672
+ const r = await runSecureScan(mirror, { scriptPath: opts.scriptPath, timeoutMs: opts.timeoutMs, secretsEverywhere: true });
12673
+ if (!r.ok)
12674
+ return r;
12675
+ const byLine = new Map;
12676
+ for (const f of r.findings) {
12677
+ if (f.rule !== "secret-in-client-file")
12678
+ continue;
12679
+ const kind = /A live (\S+)/.exec(f.message)?.[1] ?? "provider key";
12680
+ const k = `${f.file}|${f.line}`;
12681
+ const prev = byLine.get(k);
12682
+ if (!prev || prev.kind === "openai-key" && kind !== "openai-key")
12683
+ byLine.set(k, { f, kind });
12684
+ }
12685
+ const findings = [...byLine.values()].map(({ f, kind }) => {
12686
+ return {
12687
+ rule: ADDED_LINE_RULE,
12688
+ file: f.file,
12689
+ line: f.line,
12690
+ severity: "HIGH",
12691
+ message: `A ${kind} was added at ${f.file}:${f.line}; the value is withheld here.`,
12692
+ fix: "Remove the key from the change, rotate it (assume it is compromised), and read it at runtime from an environment variable or secret manager."
12693
+ };
12694
+ });
12695
+ return { ok: true, findings };
12696
+ } finally {
12697
+ rmSync15(mirror, { recursive: true, force: true });
12698
+ }
12699
+ }
12700
+ var ADDED_LINE_RULE = "provider-key-in-added-line", MAX_ADDED_FILE_BYTES = 1e6, DEFAULT_SECURE_SCAN_TIMEOUT_MS = 120000;
12423
12701
  var init_secure_scan = __esm(() => {
12424
12702
  init_paths();
12425
12703
  init_python();
12704
+ init_safe_git();
12426
12705
  init_shell();
12427
12706
  });
12428
12707
 
@@ -12532,9 +12811,9 @@ var init_route_block = __esm(() => {
12532
12811
  // ../../loki-ts/src/features/visual_evidence.ts
12533
12812
  import { spawn as spawn7 } from "child_process";
12534
12813
  import { createHash as createHash13, randomBytes as randomBytes5 } from "crypto";
12535
- import { existsSync as existsSync30, lstatSync as lstatSync10, mkdirSync as mkdirSync19, readdirSync as readdirSync16, readFileSync as readFileSync38, writeFileSync as writeFileSync22 } from "fs";
12814
+ import { existsSync as existsSync31, lstatSync as lstatSync10, mkdirSync as mkdirSync20, readdirSync as readdirSync16, readFileSync as readFileSync39, writeFileSync as writeFileSync23 } from "fs";
12536
12815
  import { createServer } from "net";
12537
- import { dirname as dirname16, isAbsolute as isAbsolute7, join as join50, normalize as normalize3, relative as relative6, sep as sep11 } from "path";
12816
+ import { dirname as dirname17, isAbsolute as isAbsolute8, join as join50, normalize as normalize3, relative as relative6, sep as sep12 } from "path";
12538
12817
  function routeFor(file) {
12539
12818
  let r = file.replace(/^(?:.*?\/)?(?:app|pages|src|public)\//, "").replace(/^(?:routes|pages)\//, "");
12540
12819
  r = r.replace(/\.(?:html|jsx|tsx|vue|svelte)$/, "").replace(/\/?(?:page|index|\+page)$/, "");
@@ -12555,16 +12834,16 @@ function checkScreens(runDir, screens) {
12555
12834
  for (const s of screens) {
12556
12835
  if (typeof s?.path !== "string" || typeof s.sha256 !== "string")
12557
12836
  return "evidence_screens entry is malformed";
12558
- if (isAbsolute7(s.path) || normalize3(s.path).startsWith(".."))
12837
+ if (isAbsolute8(s.path) || normalize3(s.path).startsWith(".."))
12559
12838
  return `evidence screenshot path escapes the evidence dir: ${s.path}`;
12560
12839
  const file = join50(runDir, s.path);
12561
12840
  let cur = runDir;
12562
- for (const seg of normalize3(s.path).split(sep11)) {
12841
+ for (const seg of normalize3(s.path).split(sep12)) {
12563
12842
  cur = join50(cur, seg);
12564
12843
  if (isSymlink(cur))
12565
12844
  return `evidence screenshot path is a symlink: ${s.path}`;
12566
12845
  }
12567
- if (!existsSync30(file))
12846
+ if (!existsSync31(file))
12568
12847
  return `evidence screenshot is missing: ${s.path}`;
12569
12848
  if (!isRegularFile(file))
12570
12849
  return `evidence screenshot is not a regular file: ${s.path}`;
@@ -12608,10 +12887,10 @@ async function waitUp(url, ms, signal) {
12608
12887
  function openapiPaths(repoDir) {
12609
12888
  for (const f of ["openapi.json", "openapi.yaml", "openapi.yml", "swagger.json"]) {
12610
12889
  const p = join50(repoDir, f);
12611
- if (!existsSync30(p))
12890
+ if (!existsSync31(p))
12612
12891
  continue;
12613
12892
  try {
12614
- const txt = readFileSync38(p, "utf8");
12893
+ const txt = readFileSync39(p, "utf8");
12615
12894
  const paths = f.endsWith(".json") ? Object.keys(JSON.parse(txt).paths ?? {}) : [...txt.matchAll(/^ {2}(\/[^\s:]*):\s*$/gm)].map((m) => m[1]);
12616
12895
  return paths.filter((x) => !x.includes("{")).slice(0, 10);
12617
12896
  } catch {
@@ -12626,9 +12905,9 @@ async function recordE2eMedia(repoDir, runDir, relDir, base, routes, ms, signal)
12626
12905
  return { rels: [], skipped: "playwright e2e video and trace skipped: @playwright/test is not installed in the repo" };
12627
12906
  try {
12628
12907
  const dir = join50(runDir, relDir, "e2e");
12629
- mkdirSync19(dir, { recursive: true });
12630
- writeFileSync22(join50(dir, "walk.spec.cjs"), e2eSpecSource(pkg, base, routes));
12631
- writeFileSync22(join50(dir, "playwright.config.cjs"), `module.exports = { testDir: ".", testMatch: "walk.spec.cjs", outputDir: "./out", reporter: "null", use: { video: "on", trace: "on" } };
12908
+ mkdirSync20(dir, { recursive: true });
12909
+ writeFileSync23(join50(dir, "walk.spec.cjs"), e2eSpecSource(pkg, base, routes));
12910
+ writeFileSync23(join50(dir, "playwright.config.cjs"), `module.exports = { testDir: ".", testMatch: "walk.spec.cjs", outputDir: "./out", reporter: "null", use: { video: "on", trace: "on" } };
12632
12911
  `);
12633
12912
  if (!await shoot(pw, ["test", "--config", join50(dir, "playwright.config.cjs")], repoDir, ms, signal))
12634
12913
  return { rels: [], skipped: "playwright e2e video and trace skipped: the run failed or timed out" };
@@ -12725,18 +13004,18 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
12725
13004
  const pkgPath = join50(appDir, "package.json");
12726
13005
  let script = null;
12727
13006
  if (!boot) {
12728
- if (!existsSync30(pkgPath)) {
12729
- const subs = ["backend", "frontend"].filter((d) => existsSync30(join50(repoDir, d, "package.json")));
13007
+ if (!existsSync31(pkgPath)) {
13008
+ const subs = ["backend", "frontend"].filter((d) => existsSync31(join50(repoDir, d, "package.json")));
12730
13009
  const has = (d) => {
12731
13010
  try {
12732
- return pickScript(JSON.parse(readFileSync38(join50(repoDir, d, "package.json"), "utf8"))) !== null;
13011
+ return pickScript(JSON.parse(readFileSync39(join50(repoDir, d, "package.json"), "utf8"))) !== null;
12733
13012
  } catch {
12734
13013
  return false;
12735
13014
  }
12736
13015
  };
12737
13016
  return skip(noRootReason(subs, subs.filter((d) => !has(d))));
12738
13017
  }
12739
- script = pickScript(JSON.parse(readFileSync38(pkgPath, "utf8")));
13018
+ script = pickScript(JSON.parse(readFileSync39(pkgPath, "utf8")));
12740
13019
  if (!script)
12741
13020
  return skip("no dev, preview or start script");
12742
13021
  }
@@ -12766,17 +13045,17 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
12766
13045
  const evRoot = join50(runDir, "evidence");
12767
13046
  if (isSymlink(evRoot))
12768
13047
  return skip("evidence dir is a symlink");
12769
- mkdirSync19(evRoot, { recursive: true });
13048
+ mkdirSync20(evRoot, { recursive: true });
12770
13049
  if (pages.length > 0) {
12771
13050
  const rel0 = join50("evidence", randomBytes5(6).toString("hex"));
12772
- mkdirSync19(join50(runDir, rel0));
13051
+ mkdirSync20(join50(runDir, rel0));
12773
13052
  const rels = [];
12774
13053
  for (const route of [...new Set(pages.map(routeFor))].slice(0, opts.maxRoutes ?? MAX_ROUTES)) {
12775
13054
  if (aborted() || left() <= 0)
12776
13055
  break;
12777
13056
  const rel = join50(rel0, `${screenName(route)}.png`);
12778
13057
  const ok = await shoot(pw, ["screenshot", `${base}${route}`, join50(runDir, rel)], appDir, left(), signal);
12779
- if (ok && !aborted() && !isSymlink(join50(runDir, rel)) && existsSync30(join50(runDir, rel)))
13058
+ if (ok && !aborted() && !isSymlink(join50(runDir, rel)) && existsSync31(join50(runDir, rel)))
12780
13059
  rels.push(rel);
12781
13060
  }
12782
13061
  if (aborted())
@@ -12802,8 +13081,8 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
12802
13081
  if (aborted())
12803
13082
  return skip("aborted");
12804
13083
  const hdir = join50(evRoot, randomBytes5(6).toString("hex"));
12805
- mkdirSync19(hdir);
12806
- writeFileSync22(join50(hdir, "http.json"), JSON.stringify(rows, null, 2) + `
13084
+ mkdirSync20(hdir);
13085
+ writeFileSync23(join50(hdir, "http.json"), JSON.stringify(rows, null, 2) + `
12807
13086
  `);
12808
13087
  return { screens: [], http: true, skipped: null };
12809
13088
  } catch (e) {
@@ -12830,14 +13109,14 @@ async function sealEvidence(repoDir, runDir, o, notProven, signal, emit) {
12830
13109
  function receiptScreensProblem(receiptPath, receipt) {
12831
13110
  if (visualGateEnabled() && typeof receipt["evidence_failed"] === "string")
12832
13111
  return `visual evidence failed (LOKI_VISUAL_GATE=1): ${receipt["evidence_failed"]}`;
12833
- return receipt["evidence_screens"] === undefined ? null : checkScreens(dirname16(receiptPath), receipt["evidence_screens"]);
13112
+ return receipt["evidence_screens"] === undefined ? null : checkScreens(dirname17(receiptPath), receipt["evidence_screens"]);
12834
13113
  }
12835
- 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) => createHash13("sha256").update(readFileSync38(p)).digest("hex"), playwrightBin = (repoDir) => {
13114
+ 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) => createHash13("sha256").update(readFileSync39(p)).digest("hex"), playwrightBin = (repoDir) => {
12836
13115
  const bin = join50(repoDir, "node_modules", ".bin", "playwright");
12837
- return existsSync30(bin) ? bin : null;
13116
+ return existsSync31(bin) ? bin : null;
12838
13117
  }, playwrightTestPkg = (repoDir) => {
12839
13118
  const d = join50(repoDir, "node_modules", "@playwright", "test");
12840
- return existsSync30(join50(d, "package.json")) ? d : null;
13119
+ return existsSync31(join50(d, "package.json")) ? d : null;
12841
13120
  }, e2eSpecSource = (pkgDir, base, routes) => `const { test } = require(${JSON.stringify(pkgDir)});
12842
13121
  test("loki e2e walkthrough", async ({ page }) => {
12843
13122
  for (const r of ${JSON.stringify(routes)}) { await page.goto(${JSON.stringify(base)} + r); await page.waitForLoadState("load"); }
@@ -12902,15 +13181,15 @@ var init_pr = __esm(() => {
12902
13181
  });
12903
13182
 
12904
13183
  // ../../loki-ts/src/util/pr_lessons.ts
12905
- import { existsSync as existsSync31, mkdirSync as mkdirSync20, mkdtempSync as mkdtempSync7, readFileSync as readFileSync39, rmSync as rmSync15, writeFileSync as writeFileSync23 } from "fs";
12906
- import { dirname as dirname17, join as join52 } from "path";
13184
+ import { existsSync as existsSync32, mkdirSync as mkdirSync21, mkdtempSync as mkdtempSync8, readFileSync as readFileSync40, rmSync as rmSync16, writeFileSync as writeFileSync24 } from "fs";
13185
+ import { dirname as dirname18, join as join52 } from "path";
12907
13186
  import { createHash as createHash14 } from "crypto";
12908
13187
  function loadLessons(repoDir) {
12909
13188
  const p = lessonsPath(repoDir);
12910
- if (!existsSync31(p))
13189
+ if (!existsSync32(p))
12911
13190
  return [];
12912
13191
  try {
12913
- const j = JSON.parse(readFileSync39(p, "utf-8"));
13192
+ const j = JSON.parse(readFileSync40(p, "utf-8"));
12914
13193
  return Array.isArray(j.lessons) ? j.lessons : [];
12915
13194
  } catch {
12916
13195
  return [];
@@ -12918,7 +13197,7 @@ function loadLessons(repoDir) {
12918
13197
  }
12919
13198
  function save(repoDir, lessons) {
12920
13199
  const p = lessonsPath(repoDir);
12921
- mkdirSync20(dirname17(p), { recursive: true });
13200
+ mkdirSync21(dirname18(p), { recursive: true });
12922
13201
  atomicWriteJson(p, { version: 2, lessons });
12923
13202
  }
12924
13203
  function appendReceiptFact(repoDir, f, now2 = () => new Date) {
@@ -12984,8 +13263,8 @@ var init_attempts = __esm(() => {
12984
13263
  var init_mcp_config = () => {};
12985
13264
 
12986
13265
  // ../../loki-ts/src/providers/claude_flags.ts
12987
- import { existsSync as existsSync32, readFileSync as readFileSync40 } from "fs";
12988
- import { resolve as resolvePath, dirname as dirname18 } from "path";
13266
+ import { existsSync as existsSync33, readFileSync as readFileSync41 } from "fs";
13267
+ import { resolve as resolvePath, dirname as dirname19 } from "path";
12989
13268
  import { fileURLToPath as fileURLToPath4 } from "url";
12990
13269
  function claudeFlagSupported(flag, helpText) {
12991
13270
  const txt = helpText ?? _claudeHelpCache;
@@ -13032,14 +13311,14 @@ function leanReviewerFlags(opts = {}) {
13032
13311
  }
13033
13312
  function designArchetypesText() {
13034
13313
  try {
13035
- const moduleDir = dirname18(fileURLToPath4(import.meta.url));
13314
+ const moduleDir = dirname19(fileURLToPath4(import.meta.url));
13036
13315
  for (const rel of [
13037
13316
  ["..", "..", "..", "references", "design-archetypes.md"],
13038
13317
  ["..", "..", "references", "design-archetypes.md"]
13039
13318
  ]) {
13040
13319
  const p = resolvePath(moduleDir, ...rel);
13041
- if (existsSync32(p))
13042
- return readFileSync40(p, "utf8");
13320
+ if (existsSync33(p))
13321
+ return readFileSync41(p, "utf8");
13043
13322
  }
13044
13323
  } catch {}
13045
13324
  return "";
@@ -13123,14 +13402,14 @@ var init_providers = __esm(() => {
13123
13402
  });
13124
13403
 
13125
13404
  // ../../loki-ts/src/runner/router/route_record.ts
13126
- import { existsSync as existsSync33, lstatSync as lstatSync11, mkdirSync as mkdirSync21, readFileSync as readFileSync41, writeFileSync as writeFileSync24 } from "fs";
13405
+ import { existsSync as existsSync34, lstatSync as lstatSync11, mkdirSync as mkdirSync22, readFileSync as readFileSync42, writeFileSync as writeFileSync25 } from "fs";
13127
13406
  import { join as join53 } from "path";
13128
13407
  function loadRouteRecord(runDir) {
13129
13408
  try {
13130
13409
  const p = join53(runDir, ROUTE_RECORD_FILE);
13131
- if (!existsSync33(p) || !lstatSync11(p).isFile())
13410
+ if (!existsSync34(p) || !lstatSync11(p).isFile())
13132
13411
  return;
13133
- const v = JSON.parse(readFileSync41(p, "utf8"));
13412
+ const v = JSON.parse(readFileSync42(p, "utf8"));
13134
13413
  return typeof v === "object" && v !== null && !Array.isArray(v) ? v : undefined;
13135
13414
  } catch {
13136
13415
  return;
@@ -13313,14 +13592,14 @@ __export(exports_deep, {
13313
13592
  DEFAULT_SECRET_SCAN_SH: () => DEFAULT_SECRET_SCAN_SH,
13314
13593
  DEFAULT_PUSH_SH: () => DEFAULT_PUSH_SH2
13315
13594
  });
13316
- import { copyFileSync as copyFileSync3, existsSync as existsSync34, lstatSync as lstatSync12, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync8, rmSync as rmSync16, writeFileSync as writeFileSync25 } from "fs";
13317
- import { tmpdir as tmpdir9 } from "os";
13318
- import { dirname as dirname19, join as join55 } from "path";
13595
+ import { copyFileSync as copyFileSync3, existsSync as existsSync35, lstatSync as lstatSync12, mkdirSync as mkdirSync23, mkdtempSync as mkdtempSync9, rmSync as rmSync17, writeFileSync as writeFileSync26 } from "fs";
13596
+ import { tmpdir as tmpdir10 } from "os";
13597
+ import { dirname as dirname20, join as join55 } from "path";
13319
13598
  function sessionCouncil(sessions) {
13320
13599
  return { async run(input, signal) {
13321
- const cwd = mkdtempSync8(join55(tmpdir9(), "loki-deep-council-"));
13600
+ const cwd = mkdtempSync9(join55(tmpdir10(), "loki-deep-council-"));
13322
13601
  try {
13323
- writeFileSync25(join55(cwd, "diff.patch"), input.diff, "utf8");
13602
+ writeFileSync26(join55(cwd, "diff.patch"), input.diff, "utf8");
13324
13603
  const r = await sessions.run({
13325
13604
  stage: "deep",
13326
13605
  tier: "development",
@@ -13342,7 +13621,7 @@ function sessionCouncil(sessions) {
13342
13621
  throw new Error("reviewer reply has no LGTM or FINDING: line");
13343
13622
  return { findings };
13344
13623
  } finally {
13345
- rmSync16(cwd, { recursive: true, force: true });
13624
+ rmSync17(cwd, { recursive: true, force: true });
13346
13625
  }
13347
13626
  } };
13348
13627
  }
@@ -13432,21 +13711,21 @@ async function runCouncilCheck(ctx, changed, baseSha, signal, opts, checks, notP
13432
13711
  }
13433
13712
  }
13434
13713
  async function secureScanChanged(repoDir, changed, opts) {
13435
- const dir = mkdtempSync8(join55(tmpdir9(), "loki-deep-secure-"));
13714
+ const dir = mkdtempSync9(join55(tmpdir10(), "loki-deep-secure-"));
13436
13715
  try {
13437
13716
  for (const f of changed)
13438
- if (existsSync34(join55(repoDir, f)) && lstatSync12(join55(repoDir, f)).isFile()) {
13439
- mkdirSync22(dirname19(join55(dir, f)), { recursive: true });
13717
+ if (existsSync35(join55(repoDir, f)) && lstatSync12(join55(repoDir, f)).isFile()) {
13718
+ mkdirSync23(dirname20(join55(dir, f)), { recursive: true });
13440
13719
  copyFileSync3(join55(repoDir, f), join55(dir, f));
13441
13720
  }
13442
13721
  return await runSecureScan(dir, { ...opts.secureScanPath ? { scriptPath: opts.secureScanPath } : {}, timeoutMs: 60000 });
13443
13722
  } finally {
13444
- rmSync16(dir, { recursive: true, force: true });
13723
+ rmSync17(dir, { recursive: true, force: true });
13445
13724
  }
13446
13725
  }
13447
13726
  async function runSecretScan(ctx, changed, opts, checks, notProven) {
13448
13727
  const scriptPath = opts.secretScanShPath ?? DEFAULT_SECRET_SCAN_SH, name = "security scan", cmd = "secret-scan.sh + secure-scan.py";
13449
- if (!existsSync34(scriptPath)) {
13728
+ if (!existsSync35(scriptPath)) {
13450
13729
  checks.push({ name, cmd, result: "not_run", duration_s: 0 });
13451
13730
  notProven.add(`not run: ${name} (secret-scan.sh not found)`);
13452
13731
  return;
@@ -13497,9 +13776,9 @@ async function postResults(ctx, opts, checks, notProven, statusState) {
13497
13776
  const prUrl = ctx.outputs().pr?.pr_url;
13498
13777
  const prNumber = prUrl ? PR_NUMBER_RE.exec(prUrl)?.[1] : undefined;
13499
13778
  if (prNumber) {
13500
- mkdirSync22(ctx.runDir, { recursive: true });
13779
+ mkdirSync23(ctx.runDir, { recursive: true });
13501
13780
  const bodyFile = join55(ctx.runDir, "deep-comment.md");
13502
- writeFileSync25(bodyFile, buildCommentBody(checks, notProven, statusState), "utf8");
13781
+ writeFileSync26(bodyFile, buildCommentBody(checks, notProven, statusState), "utf8");
13503
13782
  const commentResult = await run(["bash", scriptPath, ...commentArgv(prNumber, bodyFile)], { cwd: ctx.repoDir, env, timeoutMs: 30000 });
13504
13783
  if (commentResult.exitCode !== 0)
13505
13784
  out2.push(`deep comment not posted (engine10-push.sh exit ${commentResult.exitCode})`);
@@ -13551,8 +13830,8 @@ async function runDeep(ctx, signal, opts = {}) {
13551
13830
  const addendumSha256 = sha2562(canonicalJson(addendumBody));
13552
13831
  const sig = signReceipt(`${ctx.runId}-deep`, addendumSha256);
13553
13832
  const addendum = { ...addendumBody, addendum_sha256: addendumSha256, verification: { jwt: sig.jwt, kid: sig.kid } };
13554
- mkdirSync22(ctx.runDir, { recursive: true });
13555
- writeFileSync25(join55(ctx.runDir, "receipt-addendum-1.json"), JSON.stringify(addendum, null, 2) + `
13833
+ mkdirSync23(ctx.runDir, { recursive: true });
13834
+ writeFileSync26(join55(ctx.runDir, "receipt-addendum-1.json"), JSON.stringify(addendum, null, 2) + `
13556
13835
  `);
13557
13836
  const pushNotProven = await postResults(ctx, opts, checks, notProvenList, statusState);
13558
13837
  const allNotProven = [...notProvenList, ...pushNotProven];
@@ -13597,21 +13876,21 @@ var init_deep = __esm(() => {
13597
13876
  });
13598
13877
 
13599
13878
  // ../../loki-ts/src/engine10/stages/verify.ts
13600
- import { existsSync as existsSync35, mkdtempSync as mkdtempSync9, realpathSync as realpathSync19, rmSync as rmSync17 } from "fs";
13601
- import { tmpdir as tmpdir10 } from "os";
13602
- import { dirname as dirname20, isAbsolute as isAbsolute8, join as join56, relative as relative7 } from "path";
13879
+ import { existsSync as existsSync36, mkdtempSync as mkdtempSync10, realpathSync as realpathSync21, rmSync as rmSync18 } from "fs";
13880
+ import { tmpdir as tmpdir11 } from "os";
13881
+ import { dirname as dirname21, isAbsolute as isAbsolute9, join as join56, relative as relative7 } from "path";
13603
13882
  function resolveTool(repoDir, bin, fallback, lastResort = fallback) {
13604
13883
  const inRepo = (p) => {
13605
13884
  try {
13606
- const r = relative7(realpathSync19(repoDir), realpathSync19(p));
13607
- return r !== "" && !r.startsWith("..") && !isAbsolute8(r);
13885
+ const r = relative7(realpathSync21(repoDir), realpathSync21(p));
13886
+ return r !== "" && !r.startsWith("..") && !isAbsolute9(r);
13608
13887
  } catch {
13609
13888
  return false;
13610
13889
  }
13611
13890
  };
13612
13891
  const venvEnv = process.env["VIRTUAL_ENV"];
13613
- const project = [join56(repoDir, ".venv", "bin", bin), join56(repoDir, "venv", "bin", bin), ...venvEnv && inRepo(venvEnv) ? [join56(venvEnv, "bin", bin)] : []].find(existsSync35);
13614
- return project ? [project, "project", []] : existsSync35(join56(repoDir, "uv.lock")) && Bun.which("uv") ? ["uv", "project", ["run", "--", bin]] : [Bun.which(fallback) ? fallback : lastResort, "system", []];
13892
+ const project = [join56(repoDir, ".venv", "bin", bin), join56(repoDir, "venv", "bin", bin), ...venvEnv && inRepo(venvEnv) ? [join56(venvEnv, "bin", bin)] : []].find(existsSync36);
13893
+ return project ? [project, "project", []] : existsSync36(join56(repoDir, "uv.lock")) && Bun.which("uv") ? ["uv", "project", ["run", "--", bin]] : [Bun.which(fallback) ? fallback : lastResort, "system", []];
13615
13894
  }
13616
13895
  function runnerCmd(t, repoDir) {
13617
13896
  switch (t.runner) {
@@ -13630,7 +13909,7 @@ function runnerCmd(t, repoDir) {
13630
13909
  case "npm":
13631
13910
  return ["npm", ["test", "--silent"]];
13632
13911
  case "go":
13633
- return ["go", ["test", "-json", `./${dirname20(t.path)}`]];
13912
+ return ["go", ["test", "-json", `./${dirname21(t.path)}`]];
13634
13913
  case "cargo":
13635
13914
  return ["cargo", ["test"]];
13636
13915
  }
@@ -13725,12 +14004,12 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal)
13725
14004
  const sus = pairs.filter(({ c }) => rel.has(c.name) && c.result === "pass");
13726
14005
  if (!(un.some(({ c }) => c.result === "fail" && c.ids?.length) || sus.length) || signal.aborted)
13727
14006
  return out2;
13728
- const dir = mkdtempSync9(join56(tmpdir10(), "e10-base-"));
13729
- const git3 = (args) => {
14007
+ const dir = mkdtempSync10(join56(tmpdir11(), "e10-base-"));
14008
+ const git4 = (args) => {
13730
14009
  safeGit(ctx.repoDir, args, { stdio: "ignore", repoDrivers: true });
13731
14010
  };
13732
14011
  try {
13733
- git3(["-c", "core.hooksPath=/dev/null", "worktree", "add", "--detach", dir, ctx.baseSha]);
14012
+ git4(["-c", "core.hooksPath=/dev/null", "worktree", "add", "--detach", dir, ctx.baseSha]);
13734
14013
  const base = new Map;
13735
14014
  for (const { c, t } of new Set([...un, ...sus])) {
13736
14015
  const bc = commandFor(t, dir, api);
@@ -13753,17 +14032,17 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal)
13753
14032
  }
13754
14033
  } catch {} finally {
13755
14034
  try {
13756
- git3(["worktree", "remove", "--force", dir]);
14035
+ git4(["worktree", "remove", "--force", dir]);
13757
14036
  } catch {}
13758
- rmSync17(dir, { recursive: true, force: true });
14037
+ rmSync18(dir, { recursive: true, force: true });
13759
14038
  try {
13760
- git3(["worktree", "prune"]);
14039
+ git4(["worktree", "prune"]);
13761
14040
  } catch {}
13762
14041
  }
13763
14042
  return out2;
13764
14043
  }
13765
14044
  function isLokiModeRepo(repoDir) {
13766
- return existsSync35(join56(repoDir, "scripts", "select-tests.sh"));
14045
+ return existsSync36(join56(repoDir, "scripts", "select-tests.sh"));
13767
14046
  }
13768
14047
  async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
13769
14048
  const { api, ...runOpts } = opts;
@@ -13785,9 +14064,9 @@ async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
13785
14064
  }
13786
14065
  for (const g of groupByPackage(api, ctx.repoDir, changed.filter((f) => /\.(ts|tsx|js|jsx)$/.test(f)))) {
13787
14066
  const sfx = g.root === "." ? "" : `:${g.root}`, co = g.root === "." ? opts : { ...opts, cwd: g.cwd };
13788
- if (existsSync35(join56(g.cwd, "tsconfig.json")))
14067
+ if (existsSync36(join56(g.cwd, "tsconfig.json")))
13789
14068
  await runCheck(ctx, `lint:tsc${sfx}`, "npx", ["tsc", "--noEmit", "-p", "."], signal, checks, { ...co, kind: "static" });
13790
- if (ESLINT_CONFIGS.some((f) => existsSync35(join56(g.cwd, f)))) {
14069
+ if (ESLINT_CONFIGS.some((f) => existsSync36(join56(g.cwd, f)))) {
13791
14070
  const c = await runCheck(ctx, `lint:eslint${sfx}`, "npx", ["eslint", ...g.rel], signal, checks, { ...co, kind: "static" });
13792
14071
  if (await excuseLint(ctx, signal, c, "eslint", "npx", ["eslint"], g.cwd, g.rel, co))
13793
14072
  pre.push(c.name);
@@ -13861,7 +14140,7 @@ var init_verify = __esm(() => {
13861
14140
  const impacted = ctx.tests.impacted(map, changed);
13862
14141
  const changedTestFiles = map.tests.filter((t) => changed.includes(t.path));
13863
14142
  const wall = ctx.outputs().wall ?? {};
13864
- const wallPaths = new Set((wall.files ?? []).map((f) => isAbsolute8(f.path) ? relative7(ctx.repoDir, f.path) : f.path));
14143
+ const wallPaths = new Set((wall.files ?? []).map((f) => isAbsolute9(f.path) ? relative7(ctx.repoDir, f.path) : f.path));
13865
14144
  const wallTests = map.tests.filter((t) => wallPaths.has(t.path));
13866
14145
  const intake = ctx.outputs().intake, relevant2 = ctx.tests.impacted(map, namedFiles(intake?.task ?? "", loadRepoMap(intake?.repomap_ref)));
13867
14146
  const tests = dedupeTests([...impacted, ...changedTestFiles, ...wallTests, ...relevant2]);
@@ -13967,8 +14246,8 @@ ${x}` : c.cmd };
13967
14246
  });
13968
14247
 
13969
14248
  // ../../loki-ts/src/project_model/conventions.ts
13970
- import { existsSync as existsSync36, readdirSync as readdirSync17, readFileSync as readFileSync42 } from "fs";
13971
- import { dirname as dirname21, join as join57 } from "path";
14249
+ import { existsSync as existsSync37, readdirSync as readdirSync17, readFileSync as readFileSync43 } from "fs";
14250
+ import { dirname as dirname22, join as join57 } from "path";
13972
14251
  function parseJsonc(text2) {
13973
14252
  let out2 = "", i = 0;
13974
14253
  while (i < text2.length) {
@@ -14003,8 +14282,8 @@ function moduleOf(file, depth = 0) {
14003
14282
  const ext = typeof j.extends === "string" ? j.extends : null;
14004
14283
  if (!ext || !ext.startsWith("."))
14005
14284
  return null;
14006
- const next = join57(dirname21(file), ext.endsWith(".json") ? ext : `${ext}.json`);
14007
- return existsSync36(next) ? moduleOf(next, depth + 1) : null;
14285
+ const next = join57(dirname22(file), ext.endsWith(".json") ? ext : `${ext}.json`);
14286
+ return existsSync37(next) ? moduleOf(next, depth + 1) : null;
14008
14287
  }
14009
14288
  function readPackageConventions(pkgDir, runner = null) {
14010
14289
  let names = [];
@@ -14043,7 +14322,7 @@ function conventionViolation(c, fileName, content) {
14043
14322
  }
14044
14323
  var readJson5 = (p) => {
14045
14324
  try {
14046
- const v = parseJsonc(readFileSync42(p, "utf8"));
14325
+ const v = parseJsonc(readFileSync43(p, "utf8"));
14047
14326
  return v && typeof v === "object" && !Array.isArray(v) ? v : null;
14048
14327
  } catch {
14049
14328
  return null;
@@ -14053,95 +14332,9 @@ var init_conventions = () => {};
14053
14332
 
14054
14333
  // ../../loki-ts/src/engine10/stages/wall.ts
14055
14334
  import { spawnSync as spawnSync5 } from "child_process";
14056
- import { existsSync as existsSync37, mkdirSync as mkdirSync23, mkdtempSync as mkdtempSync10, readFileSync as readFileSync43, readdirSync as readdirSync18, realpathSync as realpathSync20, rmSync as rmSync18, writeFileSync as writeFileSync26 } from "fs";
14057
- import { tmpdir as tmpdir11 } from "os";
14058
- import { dirname as dirname22, isAbsolute as isAbsolute9, join as join58, relative as relative8 } from "path";
14059
- function pytestCollectionIsRed(output, repoDir) {
14060
- if (/ModuleNotFoundError/.test(output))
14061
- return false;
14062
- const real2 = (p) => {
14063
- try {
14064
- return realpathSync20(isAbsolute9(p) ? p : join58(repoDir, p));
14065
- } catch {
14066
- return null;
14067
- }
14068
- };
14069
- const repoReal = real2(repoDir);
14070
- const under = (p) => {
14071
- const r = real2(p);
14072
- return !!repoReal && !!r && (r === repoReal || r.startsWith(`${repoReal}/`));
14073
- };
14074
- const imp = /ImportError: cannot import name .* from ['"][\w.]+['"] \(([^)]+)\)/.exec(output);
14075
- if (imp)
14076
- return under(imp[1]);
14077
- const hdr = [...output.matchAll(/^=+ short test summary info =+$/gm)].pop();
14078
- if (!hdr)
14079
- return false;
14080
- const cls = [...output.slice(hdr.index).matchAll(/^ERROR \S+ - (\w+Error): /gm)].pop()?.[1];
14081
- if (cls !== "AttributeError" && cls !== "NameError")
14082
- return false;
14083
- const start = output.search(/^_+ ERROR collecting /m);
14084
- if (start < 0 || start > hdr.index)
14085
- return false;
14086
- const block = output.slice(start, hdr.index).split(/^-+ Captured .*$/m)[0];
14087
- const eLines = [...block.matchAll(new RegExp(`^E {3}${cls}: (.*)$`, "gm"))];
14088
- const eLine = eLines[eLines.length - 1];
14089
- if (!eLine)
14090
- return false;
14091
- if (cls === "AttributeError") {
14092
- const m = /^module ['"]([\w.]+)['"] has no attribute/.exec(eLine[1]);
14093
- return !!m && moduleUnderRepo(repoDir, m[1]);
14094
- }
14095
- const frames = [...block.slice(0, eLine.index).matchAll(/^(.+?):\d+: in \S+\n\s*(.*)$/gm)];
14096
- const last = frames[frames.length - 1];
14097
- return !!last && under(last[1]) && !/^\s*(import\s|from\s\S+\s+import\b)/.test(last[2] ?? "");
14098
- }
14099
- function moduleUnderRepo(repoDir, name) {
14100
- const rel = name.replace(/\./g, "/");
14101
- return existsSync37(join58(repoDir, `${rel}.py`)) || existsSync37(join58(repoDir, rel, "__init__.py"));
14102
- }
14103
- function pytestExit1IsRed(output) {
14104
- if (/^!+ _pytest\.outcomes\.Exit\b/m.test(output))
14105
- return false;
14106
- if (/^=*\s*(\d+ \w+(, )?)*\d+ failed\b.* in [\d.]+s/.test(output.trimEnd().split(`
14107
- `).pop() ?? ""))
14108
- return true;
14109
- const hdr = [...output.matchAll(/^=+ short test summary info =+$/gm)].pop();
14110
- return !!hdr && /^FAILED \S+/m.test(output.slice(hdr.index));
14111
- }
14112
- function parsedFailCount(runner, output) {
14113
- const m = runner === "bun" ? /^\s*(\d+)\s+fail\s*$/m.exec(output) : runner === "jest" ? /Tests:\s*(\d+)\s+failed/i.exec(output) : runner === "vitest" ? /Tests\s+(\d+)\s+failed/i.exec(output) : null;
14114
- return m ? Number(m[1]) : 0;
14115
- }
14116
- function nodeIsRed(f, raw2) {
14117
- const o = raw2.replace(/^# (?!(?:tests|suites|pass|fail|cancelled|skipped|todo|duration_ms|Subtest)\b)/gm, "");
14118
- const mod = /^Error(?: \[\w+\])?: Cannot find (?:module|package) '([^']+)'(?:(?!\u2716)[\s\S])*?\nNode\.js v/m.exec(o), top = /^(\S+):\d+\n.*\n.*\n\n?(?:ReferenceError|SyntaxError)\b/m.exec(o);
14119
- const named = [...o.matchAll(/^(?:\u2716|\s*not ok \d+ -) (?!failing tests:)(.+?)(?: \(|$)/gm)].some((m) => !f.path.endsWith(m[1]) && !m[1].endsWith(f.path)), blk = o.split("failing tests:")[1] ?? "", esm = /^SyntaxError: The requested module '([^']+)' does not provide an export named/m.exec(o), errs = [...blk.matchAll(/^ {2}(\w+Error): .*\n\s+at (?:.*\()?([^\s()]+?):\d+:\d+/gm), ...o.matchAll(/^ +name: '(\w+Error)'\n(?:.*\n)*? +stack: \|-\n\s+(?:.*\()?([^\s()]+?):\d+:\d+/gm)];
14120
- return /^(?:#|\u2139) fail [1-9]/m.test(raw2) && (/^ {2}AssertionError\b/m.test(blk) || /^ +name: 'AssertionError'/m.test(o) || (mod && !named ? /^[./]/.test(mod[1]) : esm ? /^[./]/.test(esm[1]) : top ? !top[1].endsWith(f.path) : !errs.length || errs.some((e) => !/^(?:Reference|Syntax)Error$/.test(e[1]) || !(e[2].startsWith("node:") || e[2].endsWith(f.path)))));
14121
- }
14122
- function notRunReason(status, interpreter) {
14123
- if (interpreter === "system")
14124
- return "ran under the system interpreter, not the project's, so the result proves nothing";
14125
- if (status === null)
14126
- return "the test runner did not start or timed out";
14127
- if (status === 126 || status === 127)
14128
- return `the test runner command was not found or not executable (exit ${status})`;
14129
- return status === 0 ? "exit 0 but no executed test count could be confirmed" : `exit ${status} but the runner output showed no readable failing test`;
14130
- }
14131
- function classify(f, status, output, repoDir, interpreter) {
14132
- if (interpreter === "system")
14133
- return "not_run";
14134
- output = stripAnsi(output);
14135
- if (status === null || status === 126 || status === 127)
14136
- return "not_run";
14137
- if (status === 0)
14138
- return classifyCheck({ kind: "test", ok: true, out: output, path: f.path, ...f.runner === "go" ? { runner: "go" } : {} }).result === "pass" ? "pass" : "not_run";
14139
- if (f.runner === "pytest")
14140
- return status === 1 ? pytestExit1IsRed(output) ? "fail" : "not_run" : status === 2 ? pytestCollectionIsRed(output, repoDir) ? "fail" : "not_run" : "not_run";
14141
- if (f.runner === "jest" || f.runner === "vitest" || f.runner === "bun")
14142
- return parsedFailCount(f.runner, output) > 0 ? "fail" : "not_run";
14143
- return f.runner === "node" && nodeIsRed(f, output) ? "fail" : "not_run";
14144
- }
14335
+ import { existsSync as existsSync38, mkdirSync as mkdirSync24, mkdtempSync as mkdtempSync11, readFileSync as readFileSync44, readdirSync as readdirSync18, rmSync as rmSync19, writeFileSync as writeFileSync27 } from "fs";
14336
+ import { tmpdir as tmpdir12 } from "os";
14337
+ import { dirname as dirname23, join as join58, relative as relative8 } from "path";
14145
14338
 
14146
14339
  class RealBaseTestRunner {
14147
14340
  api;
@@ -14186,7 +14379,7 @@ ${repomapText}`] : [],
14186
14379
  ...acceptance.length ? [`Acceptance criteria frozen for this unit (each must be covered by a test):
14187
14380
  ${acceptance.map((a) => `Acceptance: ${a}`).join(`
14188
14381
  `)}`] : [],
14189
- "Write behavioral acceptance tests that prove the task is done. A test that errors on import, uses another framework's globals, or fails for a reason unrelated to the task is discarded.",
14382
+ "Write behavioral acceptance tests that prove the task is done. A test that errors on import, uses another framework's globals, or fails for a reason unrelated to the task is discarded. Negative case: for each acceptance line include one assertion that rejects bad input or would fail before the fix.",
14190
14383
  `Test runner: ${runners.map((r) => RUNNER_HINT[r]).find(Boolean) ?? "the framework named in repomap.txt"}`,
14191
14384
  ...conventions ? [conventions] : [],
14192
14385
  `Name every file you write starting with "${WALL_PREFIX}". Write nothing else.`
@@ -14198,9 +14391,9 @@ function loadTaskText(ctx, fromPrior) {
14198
14391
  if (fromPrior)
14199
14392
  return fromPrior;
14200
14393
  const issueJsonPath = process.env.LOKI_E10_ISSUE_JSON ?? join58(ctx.runDir, "issue.json");
14201
- if (existsSync37(issueJsonPath)) {
14394
+ if (existsSync38(issueJsonPath)) {
14202
14395
  try {
14203
- const issue = JSON.parse(readFileSync43(issueJsonPath, "utf8"));
14396
+ const issue = JSON.parse(readFileSync44(issueJsonPath, "utf8"));
14204
14397
  const text2 = [issue.title, issue.body].filter((s) => typeof s === "string" && s.length > 0).join(`
14205
14398
 
14206
14399
  `);
@@ -14212,7 +14405,7 @@ function loadTaskText(ctx, fromPrior) {
14212
14405
  }
14213
14406
  function wallTargetDir(repoDir, existingTests) {
14214
14407
  const first = existingTests[0];
14215
- return first ? join58(repoDir, dirname22(first.path)) : join58(repoDir, "tests");
14408
+ return first ? join58(repoDir, dirname23(first.path)) : join58(repoDir, "tests");
14216
14409
  }
14217
14410
  function guessRunner(fileName, runners) {
14218
14411
  if (fileName.endsWith(".py"))
@@ -14246,10 +14439,10 @@ async function wallAuthor(ctx, signal, retry) {
14246
14439
  const repomapText = repoMapText(ctx.repoDir, tree, repomapRef, WALL_MAP_MAX_LINES);
14247
14440
  const targetDir = wallTargetDir(ctx.repoDir, existingTests), pkg = loadProjectApi(ctx.repoDir)?.packageOf(`${relative8(ctx.repoDir, targetDir)}/x`);
14248
14441
  const conv2 = readPackageConventions(join58(ctx.repoDir, pkg?.root ?? "."), pkg?.runner ?? null);
14249
- const cwd = mkdtempSync10(join58(tmpdir11(), "loki-e15-wall-"));
14442
+ const cwd = mkdtempSync11(join58(tmpdir12(), "loki-e15-wall-"));
14250
14443
  const wm = wallManifestFor(ctx.repoDir, tree, task);
14251
14444
  for (const [n2, c] of [["task.md", task], ["repomap.txt", repomapText], ...wm ? [["wall_manifest.txt", wm.text]] : []])
14252
- writeFileSync26(join58(cwd, n2), c, "utf8");
14445
+ writeFileSync27(join58(cwd, n2), c, "utf8");
14253
14446
  const model = retry?.model ?? wallFirstModel(sz.size), iterationId = `${ctx.runId}-wall${retry?.suffix ?? ""}`;
14254
14447
  const session = await ctx.sessions.run({
14255
14448
  stage: "wall",
@@ -14262,30 +14455,30 @@ async function wallAuthor(ctx, signal, retry) {
14262
14455
  cwd
14263
14456
  });
14264
14457
  if (session.killed || session.exit === null) {
14265
- rmSync18(cwd, { recursive: true, force: true });
14458
+ rmSync19(cwd, { recursive: true, force: true });
14266
14459
  return done({ status: "failed", data: { iteration_ids: [iterationId], model }, reason: "wall session aborted, killed, or timed out", killed: true });
14267
14460
  }
14268
- const all = readdirSync18(cwd).filter((f) => f.startsWith(WALL_PREFIX)), held = stashHoldout({ runId: ctx.runId, repoDir: ctx.repoDir, srcDir: cwd, targetDir, names: all.filter((n2) => !conventionViolation(conv2, n2, readFileSync43(join58(cwd, n2), "utf8"))), runnerOf: (n2) => guessRunner(n2, runners) }), generated = all.filter((n2) => !held?.names.has(n2));
14461
+ const all = readdirSync18(cwd).filter((f) => f.startsWith(WALL_PREFIX)), held = stashHoldout({ runId: ctx.runId, repoDir: ctx.repoDir, srcDir: cwd, targetDir, names: all.filter((n2) => !conventionViolation(conv2, n2, readFileSync44(join58(cwd, n2), "utf8"))), runnerOf: (n2) => guessRunner(n2, runners) }), generated = all.filter((n2) => !held?.names.has(n2));
14269
14462
  const sealedDir = join58(ctx.runDir, "wall");
14270
14463
  if (generated.length > 0)
14271
- mkdirSync23(sealedDir, { recursive: true });
14464
+ mkdirSync24(sealedDir, { recursive: true });
14272
14465
  const contents = new Map;
14273
14466
  const discarded = [];
14274
14467
  for (const name of generated) {
14275
- const content = readFileSync43(join58(cwd, name), "utf8"), bad = conventionViolation(conv2, name, content);
14276
- writeFileSync26(join58(sealedDir, name), content, "utf8");
14468
+ const content = readFileSync44(join58(cwd, name), "utf8"), bad = conventionViolation(conv2, name, content);
14469
+ writeFileSync27(join58(sealedDir, name), content, "utf8");
14277
14470
  if (bad)
14278
14471
  discarded.push({ file: name, reason: `${bad}; wall test did not compile under the package config` });
14279
14472
  else
14280
14473
  contents.set(name, content);
14281
14474
  }
14282
- rmSync18(cwd, { recursive: true, force: true });
14475
+ rmSync19(cwd, { recursive: true, force: true });
14283
14476
  return { kind: "authored", model, iterationId, task, sizeName: sz.size, runners, targetDir, generated, contents, discarded, ...wm ? { manifestSha256: wm.sha256 } : {}, ...held ? { holdoutDir: held.dir } : {} };
14284
14477
  }
14285
14478
  function installWall(ctx, a, baseDir, opts = {}) {
14286
14479
  const { generated, contents, discarded, targetDir, runners } = a;
14287
14480
  if (generated.length > 0)
14288
- mkdirSync23(targetDir, { recursive: true });
14481
+ mkdirSync24(targetDir, { recursive: true });
14289
14482
  const sealedFiles = [];
14290
14483
  const readOnlyFiles = [];
14291
14484
  const wallTests = [];
@@ -14294,7 +14487,7 @@ function installWall(ctx, a, baseDir, opts = {}) {
14294
14487
  if (content === undefined)
14295
14488
  continue;
14296
14489
  const dest = join58(targetDir, name), runner = guessRunner(name, runners);
14297
- writeFileSync26(dest, content, "utf8");
14490
+ writeFileSync27(dest, content, "utf8");
14298
14491
  sealedFiles.push({ path: dest, sha256: sha2562(content) });
14299
14492
  readOnlyFiles.push({ path: dest, content });
14300
14493
  if (runner)
@@ -14310,7 +14503,7 @@ function installWall(ctx, a, baseDir, opts = {}) {
14310
14503
  baseRun.not_run += r.not_run ?? 0;
14311
14504
  notRunFiles.push(...baseRunner.lastNotRunFiles ?? []);
14312
14505
  if (r.pass + r.fail === 0) {
14313
- rmSync18(abs, { force: true });
14506
+ rmSync19(abs, { force: true });
14314
14507
  for (const l of [sealedFiles, readOnlyFiles])
14315
14508
  l.splice(0, l.length, ...l.filter((f) => f.path !== abs));
14316
14509
  }
@@ -14343,8 +14536,8 @@ async function runWall(ctx, signal, opts = {}) {
14343
14536
  return green ? { ...first, data: distrustGreenBase(first.data) } : first;
14344
14537
  if (a.kind === "authored") {
14345
14538
  for (const f of first.data.files ?? [])
14346
- rmSync18(f.path, { force: true });
14347
- rmSync18(join58(ctx.runDir, "wall"), { recursive: true, force: true });
14539
+ rmSync19(f.path, { force: true });
14540
+ rmSync19(join58(ctx.runDir, "wall"), { recursive: true, force: true });
14348
14541
  ctx.wallSealed = false;
14349
14542
  }
14350
14543
  removeHoldout(ctx.runId, ctx.repoDir);
@@ -14367,6 +14560,7 @@ var init_wall = __esm(() => {
14367
14560
  init_resolve();
14368
14561
  init_check_result();
14369
14562
  init_conventions();
14563
+ init_check_result();
14370
14564
  WALL_RUNG_S = WALL_SESSION_MAX_S + WALL_BASE_FILES * (BASE_RUN_TIMEOUT_MS / 1000);
14371
14565
  WALL_STAGE_LIMIT_S = 2 * WALL_RUNG_S;
14372
14566
  wallStage = {
@@ -14379,20 +14573,20 @@ var init_wall = __esm(() => {
14379
14573
  });
14380
14574
 
14381
14575
  // ../../loki-ts/src/e10ext/discard.ts
14382
- import { chmodSync as chmodSync5, closeSync as closeSync9, lstatSync as lstatSync13, mkdirSync as mkdirSync24, openSync as openSync9, readFileSync as readFileSync44, realpathSync as realpathSync21, rmdirSync, unlinkSync as unlinkSync6, writeFileSync as writeFileSync27 } from "fs";
14383
- import { dirname as dirname23, join as join59, relative as relative9, sep as sep12 } from "path";
14576
+ import { chmodSync as chmodSync5, closeSync as closeSync9, lstatSync as lstatSync13, mkdirSync as mkdirSync25, openSync as openSync9, readFileSync as readFileSync45, realpathSync as realpathSync23, rmdirSync, unlinkSync as unlinkSync6, writeFileSync as writeFileSync28 } from "fs";
14577
+ import { dirname as dirname24, join as join59, relative as relative9, sep as sep13 } from "path";
14384
14578
  function safeRestore(repoDir, f, want, mode) {
14385
- const root = realpathSync21(repoDir), fp = join59(root, f), rel = relative9(root, dirname23(fp));
14579
+ const root = realpathSync23(repoDir), fp = join59(root, f), rel = relative9(root, dirname24(fp));
14386
14580
  if (rel.startsWith(".."))
14387
14581
  throw new Error("outside repo");
14388
14582
  let cur = root;
14389
- for (const part of rel === "" ? [] : rel.split(sep12)) {
14583
+ for (const part of rel === "" ? [] : rel.split(sep13)) {
14390
14584
  cur = join59(cur, part);
14391
14585
  let st2;
14392
14586
  try {
14393
14587
  st2 = lstatSync13(cur);
14394
14588
  } catch {
14395
- mkdirSync24(cur);
14589
+ mkdirSync25(cur);
14396
14590
  continue;
14397
14591
  }
14398
14592
  if (!st2.isDirectory())
@@ -14404,7 +14598,7 @@ function safeRestore(repoDir, f, want, mode) {
14404
14598
  } catch {
14405
14599
  st = null;
14406
14600
  }
14407
- if (st?.isFile() && readFileSync44(fp).equals(want)) {
14601
+ if (st?.isFile() && readFileSync45(fp).equals(want)) {
14408
14602
  chmodSync5(fp, mode);
14409
14603
  return;
14410
14604
  }
@@ -14416,7 +14610,7 @@ function safeRestore(repoDir, f, want, mode) {
14416
14610
  }
14417
14611
  const fd = openSync9(fp, "wx", mode);
14418
14612
  try {
14419
- writeFileSync27(fd, want);
14613
+ writeFileSync28(fd, want);
14420
14614
  } finally {
14421
14615
  closeSync9(fd);
14422
14616
  }
@@ -14432,13 +14626,13 @@ function catBlob(repoDir, sha3) {
14432
14626
  throw r.error ?? new Error(`git cat-file blob ${sha3} failed`);
14433
14627
  return r.stdout;
14434
14628
  }
14435
- async function discardIfSatisfied(git3, base, o, staged, keep, repoDir) {
14629
+ async function discardIfSatisfied(git4, base, o, staged, keep, repoDir) {
14436
14630
  if (!alreadySatisfied(o))
14437
14631
  return null;
14438
14632
  const pre = Object.assign(Object.create(null), o.intake?.preexisting_dirty ?? {}), own = new Set([...Array.isArray(o.intake?.preexisting_untracked) ? o.intake.preexisting_untracked : [], ...Object.keys(o.intake?.preexisting_untracked_blobs ?? {})]);
14439
14633
  const gone = staged.filter(({ f }) => !keep.has(f) && !own.has(f) && !Object.hasOwn(pre, f) && !f.startsWith(".loki/")), lit = ["--literal-pathspecs"];
14440
14634
  const del = gone.filter(({ st }) => st === "A").map(({ f }) => f), back = gone.filter(({ st }) => st !== "A").map(({ f }) => f);
14441
- if (del.length > 0 && (await git3([...lit, "rm", "-q", "-f", "--", ...del])).code !== 0 || back.length > 0 && (await git3([...lit, "restore", `--source=${base}`, "--staged", "--worktree", "--", ...back])).code !== 0 || (await git3(["reset", "-q", base])).code !== 0)
14635
+ if (del.length > 0 && (await git4([...lit, "rm", "-q", "-f", "--", ...del])).code !== 0 || back.length > 0 && (await git4([...lit, "restore", `--source=${base}`, "--staged", "--worktree", "--", ...back])).code !== 0 || (await git4(["reset", "-q", base])).code !== 0)
14442
14636
  return { status: "failed", data: {}, reason: "already-satisfied discard failed" };
14443
14637
  const notProven = [];
14444
14638
  for (const [f, v] of Object.entries(o.intake?.preexisting_untracked_blobs ?? {})) {
@@ -14494,9 +14688,9 @@ var init_preexisting_dirty = __esm(() => {
14494
14688
  });
14495
14689
 
14496
14690
  // ../../loki-ts/src/e10ext/commit_filter.ts
14497
- import { dirname as dirname24 } from "path";
14691
+ import { dirname as dirname25 } from "path";
14498
14692
  function dropSet(repoDir, staged, preexistingDirty, env = process.env) {
14499
- return staged.concat(untouchedSinceIntake(repoDir, preexistingDirty, env).map((f) => ({ st: "L", f }))).filter(({ st, f }) => f.startsWith(".loki/") || st === "L" || /(^|\/)loki_wall_[^/]*$/.test(f) || st === "A" && !staged.some(({ f: m }) => /(^|\/)(package\.json|pyproject\.toml|requirements\.txt|Cargo\.toml|go\.mod)$/.test(m) && dirname24(m) === dirname24(f)) && /(^|\/)(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|bun\.lockb?|poetry\.lock|Cargo\.lock|go\.sum)$/.test(f));
14693
+ return staged.concat(untouchedSinceIntake(repoDir, preexistingDirty, env).map((f) => ({ st: "L", f }))).filter(({ st, f }) => f.startsWith(".loki/") || st === "L" || /(^|\/)loki_wall_[^/]*$/.test(f) || st === "A" && !staged.some(({ f: m }) => /(^|\/)(package\.json|pyproject\.toml|requirements\.txt|Cargo\.toml|go\.mod)$/.test(m) && dirname25(m) === dirname25(f)) && /(^|\/)(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|bun\.lockb?|poetry\.lock|Cargo\.lock|go\.sum)$/.test(f));
14500
14694
  }
14501
14695
  var parseStaged = (out2) => out2.split("\x00").reduce((a, t, i, all) => i % 2 === 0 && t ? [...a, { st: t, f: all[i + 1] }] : a, []);
14502
14696
  var init_commit_filter = __esm(() => {
@@ -14505,7 +14699,7 @@ var init_commit_filter = __esm(() => {
14505
14699
  });
14506
14700
 
14507
14701
  // ../../loki-ts/src/e10ext/scope.ts
14508
- import { basename as basename20, dirname as dirname25 } from "path";
14702
+ import { basename as basename20, dirname as dirname26 } from "path";
14509
14703
  function contractText(o) {
14510
14704
  const c = o.intake?.contract_snapshot?.contract;
14511
14705
  return Array.isArray(c?.criteria) ? c.criteria.map((x) => typeof x?.text === "string" ? x.text : "").join(`
@@ -14519,8 +14713,8 @@ function outsideScope(o, staged) {
14519
14713
  const text2 = `${plan}
14520
14714
  ${typeof o.intake?.task === "string" ? o.intake.task : ""}
14521
14715
  ${contractText(o)}`, pre = o.intake?.preexisting_dirty ?? {};
14522
- const toks = surfaceTokens(text2), plannedDirs = new Set(rel.map((r) => dirname25(r)).filter((d) => d !== "."));
14523
- return staged.filter(({ st, f }) => st !== "A" && !isTestFile(f) && !Object.hasOwn(pre, f) && !rel.includes(f) && !mentions(text2, f) && !mentions(text2, basename20(f)) && !plannedDirs.has(dirname25(f)) && !dirSegs(f).some((d) => toks.has(d))).map(({ f }) => f);
14716
+ const toks = surfaceTokens(text2), plannedDirs = new Set(rel.map((r) => dirname26(r)).filter((d) => d !== "."));
14717
+ return staged.filter(({ st, f }) => st !== "A" && !isTestFile(f) && !Object.hasOwn(pre, f) && !rel.includes(f) && !mentions(text2, f) && !mentions(text2, basename20(f)) && !plannedDirs.has(dirname26(f)) && !dirSegs(f).some((d) => toks.has(d))).map(({ f }) => f);
14524
14718
  }
14525
14719
  function flagOutsideScope(o, staged) {
14526
14720
  const unit = unitFlags(staged, process.env, o.intake?.preexisting_dirty ?? {});
@@ -14535,14 +14729,14 @@ var init_scope2 = __esm(() => {
14535
14729
  });
14536
14730
 
14537
14731
  // ../../loki-ts/src/council/role_agents.ts
14538
- import { existsSync as existsSync38, readdirSync as readdirSync19, readFileSync as readFileSync45 } from "fs";
14732
+ import { existsSync as existsSync39, readdirSync as readdirSync19, readFileSync as readFileSync46 } from "fs";
14539
14733
  import { homedir as homedir9 } from "os";
14540
14734
  import { join as join60 } from "path";
14541
14735
  function agentDirs(repoDir, env = process.env) {
14542
14736
  return [env["LOKI_AGENTS_PROJECT_DIR"] || join60(repoDir, ".loki", "agents"), env["LOKI_AGENTS_USER_DIR"] || join60(env["XDG_CONFIG_HOME"] || join60(homedir9(), ".config"), "loki", "agents")];
14543
14737
  }
14544
14738
  function parseAgent(file, stem2) {
14545
- const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(readFileSync45(file, "utf8"));
14739
+ const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(readFileSync46(file, "utf8"));
14546
14740
  if (!m)
14547
14741
  return null;
14548
14742
  const body = m[2].trim();
@@ -14556,7 +14750,7 @@ function parseAgent(file, stem2) {
14556
14750
  }
14557
14751
  function loadRoleAgent(repoDir, role, env = process.env) {
14558
14752
  for (const d of agentDirs(repoDir, env)) {
14559
- if (!existsSync38(d))
14753
+ if (!existsSync39(d))
14560
14754
  continue;
14561
14755
  let names;
14562
14756
  try {
@@ -14584,7 +14778,7 @@ var init_role_agents = __esm(() => {
14584
14778
  });
14585
14779
 
14586
14780
  // ../../loki-ts/src/util/child_ledger.ts
14587
- import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync25 } from "fs";
14781
+ import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync26 } from "fs";
14588
14782
  import { join as join61 } from "path";
14589
14783
  function unmeasuredRecord(phase, model, source) {
14590
14784
  return { phase, model, input_tokens: 0, output_tokens: 0, cache_creation_tokens: 0, cache_read_tokens: 0, source, cost_status: "unmeasured" };
@@ -14611,7 +14805,7 @@ function recordFromClaudeResult(phase, payload, source = "claude-json") {
14611
14805
  function appendChildLedger(lokiDir2, rec2) {
14612
14806
  try {
14613
14807
  const dir = join61(lokiDir2, "metrics");
14614
- mkdirSync25(dir, { recursive: true });
14808
+ mkdirSync26(dir, { recursive: true });
14615
14809
  appendFileSync4(join61(dir, "child-sessions.jsonl"), `${JSON.stringify(rec2)}
14616
14810
  `);
14617
14811
  return true;
@@ -14642,14 +14836,14 @@ var init_child_ledger = __esm(() => {
14642
14836
  });
14643
14837
 
14644
14838
  // ../../loki-ts/src/util/run_summary.ts
14645
- import { existsSync as existsSync39, mkdirSync as mkdirSync26, readFileSync as readFileSync46, renameSync as renameSync12, statSync as statSync17, writeFileSync as writeFileSync28 } from "fs";
14839
+ import { existsSync as existsSync40, mkdirSync as mkdirSync27, readFileSync as readFileSync47, renameSync as renameSync12, statSync as statSync18, writeFileSync as writeFileSync29 } from "fs";
14646
14840
  import { join as join62 } from "path";
14647
14841
  function readRiskRecord(repoDir, sinceMs = 0) {
14648
14842
  try {
14649
14843
  const p = join62(repoDir, ".loki", "state", "risk-tier.json");
14650
- if (statSync17(p).mtimeMs < sinceMs)
14844
+ if (statSync18(p).mtimeMs < sinceMs)
14651
14845
  return null;
14652
- const r = JSON.parse(readFileSync46(p, "utf8"));
14846
+ const r = JSON.parse(readFileSync47(p, "utf8"));
14653
14847
  return r && typeof r === "object" ? r : null;
14654
14848
  } catch {
14655
14849
  return null;
@@ -14663,7 +14857,7 @@ var init_run_summary = __esm(() => {
14663
14857
  });
14664
14858
 
14665
14859
  // ../../loki-ts/src/engine10/stages/xreview.ts
14666
- import { existsSync as existsSync40, readFileSync as readFileSync47 } from "fs";
14860
+ import { existsSync as existsSync41, readFileSync as readFileSync48 } from "fs";
14667
14861
  import { join as join63 } from "path";
14668
14862
  function minVerdict(verdict, review) {
14669
14863
  const ceiling = review?.level === "block" ? "PARTIAL" : verdict;
@@ -14678,10 +14872,10 @@ function explicitReview(repoDir, env) {
14678
14872
  return "off";
14679
14873
  for (const f of ["loki.yaml", "loki.yml"]) {
14680
14874
  const p = join63(repoDir, f);
14681
- if (!existsSync40(p))
14875
+ if (!existsSync41(p))
14682
14876
  continue;
14683
14877
  try {
14684
- const m = /^review:[ \t]*["']?([A-Za-z]+)["']?[ \t]*(?:#.*)?$/m.exec(readFileSync47(p, "utf8"));
14878
+ const m = /^review:[ \t]*["']?([A-Za-z]+)["']?[ \t]*(?:#.*)?$/m.exec(readFileSync48(p, "utf8"));
14685
14879
  const v = asProvider(m?.[1]);
14686
14880
  if (v)
14687
14881
  return v;
@@ -14859,8 +15053,8 @@ See also: loki cost --detail (what a run ALREADY spent)
14859
15053
  });
14860
15054
 
14861
15055
  // ../../loki-ts/src/features/contract.ts
14862
- import { existsSync as existsSync41, lstatSync as lstatSync14, mkdirSync as mkdirSync27, readFileSync as readFileSync48, rmSync as rmSync19, writeFileSync as writeFileSync29 } from "fs";
14863
- import { dirname as dirname26, join as join64 } from "path";
15056
+ import { existsSync as existsSync42, lstatSync as lstatSync14, mkdirSync as mkdirSync28, readFileSync as readFileSync49, rmSync as rmSync20, writeFileSync as writeFileSync30 } from "fs";
15057
+ import { dirname as dirname27, join as join64 } from "path";
14864
15058
  import { createHash as createHash15 } from "crypto";
14865
15059
  function contractEnabled(env = process.env) {
14866
15060
  return env["LOKI_CONTRACT"] !== "0";
@@ -14908,7 +15102,7 @@ function readContract(repoDir) {
14908
15102
  return { contract: null, notes: ["contract unreadable: too large"], sha256: null };
14909
15103
  let raw2;
14910
15104
  try {
14911
- raw2 = readFileSync48(p);
15105
+ raw2 = readFileSync49(p);
14912
15106
  } catch {
14913
15107
  return { contract: null, notes: ["contract unreadable: read failed"], sha256: null };
14914
15108
  }
@@ -14983,11 +15177,11 @@ var init_contract = __esm(() => {
14983
15177
 
14984
15178
  // ../../loki-ts/src/features/speed/seal_group.ts
14985
15179
  import { createHash as createHash16 } from "crypto";
14986
- import { existsSync as existsSync42, mkdirSync as mkdirSync28, readdirSync as readdirSync20, readFileSync as readFileSync49, renameSync as renameSync13, statSync as statSync18, writeFileSync as writeFileSync30 } from "fs";
14987
- import { dirname as dirname27, join as join65 } from "path";
15180
+ import { existsSync as existsSync43, mkdirSync as mkdirSync29, readdirSync as readdirSync20, readFileSync as readFileSync50, renameSync as renameSync13, statSync as statSync19, writeFileSync as writeFileSync31 } from "fs";
15181
+ import { dirname as dirname28, join as join65 } from "path";
14988
15182
  function sealGroup(runDir, rh) {
14989
15183
  const manifestPath = join65(runDir, "group", "manifest.json");
14990
- if (!existsSync42(manifestPath))
15184
+ if (!existsSync43(manifestPath))
14991
15185
  return { section: undefined, notProven: [], problems: 0, allUnitsPass: true };
14992
15186
  const notProven = [];
14993
15187
  let problems = 0;
@@ -15014,7 +15208,7 @@ function sealGroup(runDir, rh) {
15014
15208
  const dir = join65(unitsDir(runDir), id), rp = join65(dir, "receipt.json"), ep = join65(dir, "events.jsonl");
15015
15209
  let bytes;
15016
15210
  try {
15017
- bytes = readFileSync49(rp);
15211
+ bytes = readFileSync50(rp);
15018
15212
  } catch {
15019
15213
  return fail2(`unit ${id} sub-receipt missing`);
15020
15214
  }
@@ -15031,7 +15225,7 @@ function sealGroup(runDir, rh) {
15031
15225
  unit_id: id,
15032
15226
  sub_receipt_sha256: sha3(bytes),
15033
15227
  receipt_sha256: sub["receipt_sha256"],
15034
- events_file_sha256: existsSync42(ep) ? sha3(readFileSync49(ep)) : null,
15228
+ events_file_sha256: existsSync43(ep) ? sha3(readFileSync50(ep)) : null,
15035
15229
  verdict,
15036
15230
  goal: text2(u["goal"], 200),
15037
15231
  files: (Array.isArray(u["files"]) ? u["files"] : []).map((f) => text2(f, 200)).filter(Boolean).slice(0, 50),
@@ -15051,12 +15245,12 @@ function capGroupVerdict(v, g) {
15051
15245
  return !g.allUnitsPass && (v === "VERIFIED" || v === "ALREADY_SATISFIED") ? "PARTIAL" : v;
15052
15246
  }
15053
15247
  async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
15054
- const runDir = dirname27(receiptPath);
15248
+ const runDir = dirname28(receiptPath);
15055
15249
  const signed = isObj10(receipt["verification"]) && typeof receipt["verification"]["jwt"] === "string";
15056
15250
  const bad = (reason) => ({ verdict: "TAMPERED", reason: `group: ${reason}` });
15057
15251
  const g = receipt["group"];
15058
15252
  if (g === undefined)
15059
- return existsSync42(join65(runDir, "group", "manifest.json")) ? bad("group directory present but the receipt has no group section") : null;
15253
+ return existsSync43(join65(runDir, "group", "manifest.json")) ? bad("group directory present but the receipt has no group section") : null;
15060
15254
  if (!isObj10(g) || !ID_RE.test(String(g["group_id"] ?? "")) || !Array.isArray(g["units"]) || g["units"].length === 0)
15061
15255
  return bad("group section malformed");
15062
15256
  const entries = g["units"];
@@ -15073,15 +15267,15 @@ async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
15073
15267
  return bad(`unit ${id} is out of order (index ${String(e["index"])} at position ${i})`);
15074
15268
  let bytes;
15075
15269
  try {
15076
- if (!statSync18(dir).isDirectory())
15270
+ if (!statSync19(dir).isDirectory())
15077
15271
  return bad(`unit ${id} is not a directory`);
15078
- bytes = readFileSync49(rp);
15272
+ bytes = readFileSync50(rp);
15079
15273
  } catch {
15080
15274
  return bad(`unit ${id} sub-receipt missing`);
15081
15275
  }
15082
15276
  if (sha3(bytes) !== e["sub_receipt_sha256"])
15083
15277
  return bad(`unit ${id} sub-receipt does not match its recorded hash`);
15084
- const evSha = existsSync42(ep) ? sha3(readFileSync49(ep)) : null;
15278
+ const evSha = existsSync43(ep) ? sha3(readFileSync50(ep)) : null;
15085
15279
  if (evSha !== (e["events_file_sha256"] ?? null))
15086
15280
  return bad(`unit ${id} events.jsonl does not match its recorded hash`);
15087
15281
  const sub = readJson6(rp);
@@ -15106,7 +15300,7 @@ function compositeVerdict(childVerdicts) {
15106
15300
  }
15107
15301
  var ID_RE, PASSING, sha3 = (b) => createHash16("sha256").update(b).digest("hex"), isObj10 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), text2 = (v, cap) => typeof v === "string" ? v.replace(/[\x00-\x1f\x7f]+/g, " ").trim().slice(0, cap) : "", num4 = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : 0, unitsDir = (runDir) => join65(runDir, "group", "units"), readJson6 = (p) => {
15108
15302
  try {
15109
- return JSON.parse(readFileSync49(p, "utf8"));
15303
+ return JSON.parse(readFileSync50(p, "utf8"));
15110
15304
  } catch {
15111
15305
  return;
15112
15306
  }
@@ -15124,7 +15318,7 @@ var init_seal_group = __esm(() => {
15124
15318
  });
15125
15319
 
15126
15320
  // ../../loki-ts/src/supply/supply_guard.ts
15127
- import { existsSync as existsSync43, readFileSync as readFileSync50, statSync as statSync19 } from "fs";
15321
+ import { existsSync as existsSync44, readFileSync as readFileSync51, statSync as statSync20 } from "fs";
15128
15322
  import { basename as basename21, join as join66 } from "path";
15129
15323
  function supplyEnabled(env) {
15130
15324
  return env["LOKI_SUPPLY_GUARD"] !== "0";
@@ -15141,12 +15335,12 @@ function isManifestPath(path) {
15141
15335
  }
15142
15336
  function readDeclared(repoDir) {
15143
15337
  const p = join66(repoDir, ".loki", DECLARED_FILE);
15144
- if (!existsSync43(p))
15338
+ if (!existsSync44(p))
15145
15339
  return { deps: [], problem: null };
15146
15340
  try {
15147
- if (statSync19(p).size > MAX_FILE_BYTES)
15341
+ if (statSync20(p).size > MAX_FILE_BYTES)
15148
15342
  return { deps: [], problem: "declaration file too large" };
15149
- const j = JSON.parse(readFileSync50(p, "utf8"));
15343
+ const j = JSON.parse(readFileSync51(p, "utf8"));
15150
15344
  if (!Array.isArray(j))
15151
15345
  return { deps: [], problem: "declaration is not a JSON array" };
15152
15346
  const deps = [];
@@ -15167,10 +15361,10 @@ function readDeclared(repoDir) {
15167
15361
  }
15168
15362
  function readAllowlist(repoDir) {
15169
15363
  const p = join66(repoDir, ".loki", "supply-allowlist");
15170
- if (!existsSync43(p))
15364
+ if (!existsSync44(p))
15171
15365
  return new Set;
15172
15366
  try {
15173
- return new Set(readFileSync50(p, "utf8").split(`
15367
+ return new Set(readFileSync51(p, "utf8").split(`
15174
15368
  `).map((l) => l.replace(/#.*$/, "").trim()).filter(Boolean));
15175
15369
  } catch {
15176
15370
  return new Set;
@@ -15353,7 +15547,7 @@ var MIN_AGE_DAYS = 7, DECLARED_FILE = "supply-declared.json", MAX_CHECKED = 50,
15353
15547
  }
15354
15548
  }, PUBLIC_HOSTS, hostOf = (u) => u.trim().toLowerCase().replace(/^[a-z][a-z0-9+.-]*:\/\//, "").replace(/^www\./, "").split(/[/?#\s]/)[0].replace(/^[^@]*@/, "").replace(/:\d+$/, ""), privateUrl = (u) => /[a-z0-9]/i.test(u) && !PUBLIC_HOSTS.has(hostOf(u)), readSmall = (p) => {
15355
15549
  try {
15356
- return statSync19(p).size <= MAX_FILE_BYTES ? readFileSync50(p, "utf8") : "";
15550
+ return statSync20(p).size <= MAX_FILE_BYTES ? readFileSync51(p, "utf8") : "";
15357
15551
  } catch {
15358
15552
  return "";
15359
15553
  }
@@ -15369,8 +15563,8 @@ var init_supply_guard = __esm(() => {
15369
15563
 
15370
15564
  // ../../loki-ts/src/engine10/stages/seal.ts
15371
15565
  import { createHash as createHash17 } from "crypto";
15372
- import { existsSync as existsSync44, readdirSync as readdirSync21, mkdirSync as mkdirSync29, readFileSync as readFileSync51, writeFileSync as writeFileSync31 } from "fs";
15373
- import { basename as basename22, isAbsolute as isAbsolute10, join as join67, relative as relative10 } from "path";
15566
+ import { existsSync as existsSync45, readdirSync as readdirSync21, mkdirSync as mkdirSync30, readFileSync as readFileSync52, writeFileSync as writeFileSync32 } from "fs";
15567
+ import { basename as basename22, isAbsolute as isAbsolute11, join as join67, relative as relative10 } from "path";
15374
15568
  function sanitizeReason(s) {
15375
15569
  const collapsed = s.replace(/[\x00-\x1f\x7f]+/g, " ").trim();
15376
15570
  const capped = collapsed.length > 500 ? `${collapsed.slice(0, 500)}...` : collapsed;
@@ -15380,7 +15574,7 @@ function receiptSha256(r) {
15380
15574
  const { verification: _v, receipt_sha256: _h, ...body } = r;
15381
15575
  return sha2562(canonicalJson(body));
15382
15576
  }
15383
- async function git3(ctx, args, keep = {}) {
15577
+ async function git4(ctx, args, keep = {}) {
15384
15578
  const r = await safeGitRun(ctx.repoDir, args, { timeoutMs: 20000, ...keep });
15385
15579
  return { out: r.stdout, code: r.exitCode };
15386
15580
  }
@@ -15447,7 +15641,7 @@ function renderReceiptMd(r) {
15447
15641
  }
15448
15642
  var DEEP_NOT_PROVEN, SIGNING_UNAVAILABLE = "receipt signing unavailable (no usable signing key: invalid key or unwritable ~/.loki/keys)", AGENT_ONLY_REASON = "only agent-authored tests executed (no agent-independent proof)", EXCLUDE_LOKI = ":(exclude).loki", sha2562 = (s) => createHash17("sha256").update(s).digest("hex"), str3 = (v) => typeof v === "string" && v !== "" ? v : null, strs2 = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string" && x !== "") : [], receiptRel = (ctx) => {
15449
15643
  const r = relative10(ctx.repoDir, join67(ctx.runDir, "receipt.json"));
15450
- return r.startsWith("..") || isAbsolute10(r) ? `.loki/runs/${ctx.runId}/receipt.json` : r;
15644
+ return r.startsWith("..") || isAbsolute11(r) ? `.loki/runs/${ctx.runId}/receipt.json` : r;
15451
15645
  }, commitStage, wallGreenOnBaseOf = (o) => {
15452
15646
  const b = o.wall?.base_run ?? {};
15453
15647
  return typeof b.pass === "number" && b.pass > 0 && b.fail === 0 && (typeof b.not_run === "number" ? b.not_run : 0) === 0;
@@ -15484,30 +15678,30 @@ var init_seal = __esm(() => {
15484
15678
  name: "commit",
15485
15679
  ...STAGE_BUDGETS.commit,
15486
15680
  async run(ctx) {
15487
- if (!ctx.baseSha || (await git3(ctx, ["rev-parse", "--verify", "-q", `${ctx.baseSha}^{commit}`])).code !== 0)
15681
+ if (!ctx.baseSha || (await git4(ctx, ["rev-parse", "--verify", "-q", `${ctx.baseSha}^{commit}`])).code !== 0)
15488
15682
  return { status: "failed", data: {}, reason: "base commit not resolvable" };
15489
- if ((await git3(ctx, ["add", "-A", "--", "."], { repoDrivers: true })).code !== 0)
15683
+ if ((await git4(ctx, ["add", "-A", "--", "."], { repoDrivers: true })).code !== 0)
15490
15684
  return { status: "failed", data: {}, reason: "git add failed" };
15491
- const sd = await git3(ctx, ["diff", "--cached", "--name-status", "--no-renames", "-z", ctx.baseSha]);
15685
+ const sd = await git4(ctx, ["diff", "--cached", "--name-status", "--no-renames", "-z", ctx.baseSha]);
15492
15686
  if (sd.code !== 0)
15493
15687
  return { status: "failed", data: {}, reason: "git diff against base failed" };
15494
15688
  const staged = parseStaged(sd.out);
15495
15689
  const drop = dropSet(ctx.repoDir, staged, ctx.outputs().intake?.preexisting_dirty);
15496
- const sat = await discardIfSatisfied((a) => git3(ctx, a), ctx.baseSha, ctx.outputs(), staged, new Set(drop.filter(({ st }) => st === "L").map(({ f }) => f)), ctx.repoDir);
15690
+ const sat = await discardIfSatisfied((a) => git4(ctx, a), ctx.baseSha, ctx.outputs(), staged, new Set(drop.filter(({ st }) => st === "L").map(({ f }) => f)), ctx.repoDir);
15497
15691
  if (sat)
15498
15692
  return sat;
15499
- if (drop.length > 0 && (await git3(ctx, ["--literal-pathspecs", "reset", "-q", ctx.baseSha, "--", ...drop.map(({ f }) => f)])).code !== 0)
15693
+ if (drop.length > 0 && (await git4(ctx, ["--literal-pathspecs", "reset", "-q", ctx.baseSha, "--", ...drop.map(({ f }) => f)])).code !== 0)
15500
15694
  return { status: "failed", data: {}, reason: "git reset failed" };
15501
15695
  const dropped2 = new Set(drop.map(({ f }) => f)), notes = flagOutsideScope(ctx.outputs(), staged.filter(({ f }) => !dropped2.has(f)));
15502
- if ((await git3(ctx, ["diff", "--cached", "--quiet"])).code === 0)
15696
+ if ((await git4(ctx, ["diff", "--cached", "--quiet"])).code === 0)
15503
15697
  return { status: "completed", data: { committed: false, scope_notes: notes } };
15504
15698
  const title = (str3(ctx.outputs().intake?.title) ?? `run ${ctx.runId}`).split(`
15505
15699
  `)[0].slice(0, 72);
15506
- const c = await git3(ctx, ["commit", "-q", "-m", `loki: ${title}`, "-m", [`Loki-Run: ${ctx.runId}`, ...aiTrailers({ runId: ctx.runId, provider: ctx.provider, model: ctx.model, receiptRel: receiptRel(ctx) })].join(`
15700
+ const c = await git4(ctx, ["commit", "-q", "-m", `loki: ${title}`, "-m", [`Loki-Run: ${ctx.runId}`, ...aiTrailers({ runId: ctx.runId, provider: ctx.provider, model: ctx.model, receiptRel: receiptRel(ctx) })].join(`
15507
15701
  `)], { repoDrivers: true, userHooks: true });
15508
15702
  if (c.code !== 0)
15509
15703
  return { status: "failed", data: {}, reason: "git commit failed" };
15510
- return { status: "completed", data: { committed: true, head_sha: (await git3(ctx, ["rev-parse", "HEAD"])).out.trim(), scope_notes: notes } };
15704
+ return { status: "completed", data: { committed: true, head_sha: (await git4(ctx, ["rev-parse", "HEAD"])).out.trim(), scope_notes: notes } };
15511
15705
  }
15512
15706
  };
15513
15707
  sealStage = {
@@ -15517,8 +15711,8 @@ var init_seal = __esm(() => {
15517
15711
  const o = ctx.outputs(), stale = staleAtSeal(ctx.repoDir, ctx);
15518
15712
  if (stale.length)
15519
15713
  return { status: "failed", data: { stale_wall_revisions: stale.map((r) => r.rev) }, reason: staleReason(stale) };
15520
- const head = (await git3(ctx, ["rev-parse", "HEAD"])).out.trim();
15521
- const tree = (await git3(ctx, ["rev-parse", "HEAD^{tree}"])).out.trim();
15714
+ const head = (await git4(ctx, ["rev-parse", "HEAD"])).out.trim();
15715
+ const tree = (await git4(ctx, ["rev-parse", "HEAD^{tree}"])).out.trim();
15522
15716
  const diff = await safeGitRun(ctx.repoDir, ["diff-tree", "-r", "-z", "--raw", "--no-renames", "--no-abbrev", "-O/dev/null", ctx.baseSha, head, "--", ".", EXCLUDE_LOKI], { timeoutMs: 20000 });
15523
15717
  const diffOk = diff.exitCode === 0 && /^[0-9a-f]{40,64}$/.test(head);
15524
15718
  const verifyNotProven = strs2(o.verify?.not_proven);
@@ -15526,7 +15720,7 @@ var init_seal = __esm(() => {
15526
15720
  const wallNotRun = typeof base.not_run === "number" ? base.not_run : 0;
15527
15721
  const wallGreenOnBase = wallGreenOnBaseOf(o);
15528
15722
  const preRedChecks = strs2(o.verify?.pre_red_checks);
15529
- const rawDiff = diffOk ? diff.stdout.split("\x00").filter(Boolean) : [], pctx = { addedFiles: rawDiff.flatMap((m, i) => i % 2 === 0 && m.trim().split(" ").pop() === "A" && rawDiff[i + 1] ? [rawDiff[i + 1]] : []), wallFiles: Array.isArray(o.wall?.files) ? o.wall.files.map((f) => String(f.path)) : [] }, checks = checksOf(o.verify?.checks, pctx);
15723
+ const rawDiff = diffOk ? diff.stdout.split("\x00").filter(Boolean) : [], pctx = { addedFiles: rawDiff.flatMap((m, i) => i % 2 === 0 && m.trim().split(" ").pop() === "A" && rawDiff[i + 1] ? [rawDiff[i + 1]] : []), wallFiles: Array.isArray(o.wall?.files) ? o.wall.files.map((f) => String(f.path)) : [], modifiedFiles: rawDiff.flatMap((m, i) => i % 2 === 0 && m.trim().split(" ").pop() !== "A" && rawDiff[i + 1] && isTestFile(rawDiff[i + 1]) ? [rawDiff[i + 1]] : []) }, checks = checksOf(o.verify?.checks, pctx);
15530
15724
  const weakTests = [];
15531
15725
  for (let i = 0;i + 1 < rawDiff.length; i += 2)
15532
15726
  if ((rawDiff[i].trim().split(" ").pop() ?? "") !== "A" && isTestFile(rawDiff[i + 1]))
@@ -15676,7 +15870,7 @@ var init_seal = __esm(() => {
15676
15870
  provider: ctx.provider,
15677
15871
  model: ctx.model,
15678
15872
  resumed: o.intake?.resumed === true,
15679
- events_sha256: sha2562(existsSync44(eventsPath) ? readFileSync51(eventsPath) : ""),
15873
+ events_sha256: sha2562(existsSync45(eventsPath) ? readFileSync52(eventsPath) : ""),
15680
15874
  ...await sealEvidence(ctx.repoDir, ctx.runDir, o, notProven, signal, ctx.emit),
15681
15875
  log_seal: true,
15682
15876
  ...receiptBlock(process.env, cost.usd, cost.unmetered === true, totalS),
@@ -15697,11 +15891,11 @@ var init_seal = __esm(() => {
15697
15891
  hash = receiptSha256(body);
15698
15892
  }
15699
15893
  const receipt = { ...body, receipt_sha256: hash, verification: { jwt: sig.jwt, kid: sig.kid } };
15700
- mkdirSync29(ctx.runDir, { recursive: true });
15894
+ mkdirSync30(ctx.runDir, { recursive: true });
15701
15895
  const path = join67(ctx.runDir, "receipt.json");
15702
- writeFileSync31(path, JSON.stringify(receipt, null, 2) + `
15896
+ writeFileSync32(path, JSON.stringify(receipt, null, 2) + `
15703
15897
  `);
15704
- writeFileSync31(join67(ctx.runDir, "receipt.md"), renderReceiptMd(receipt));
15898
+ writeFileSync32(join67(ctx.runDir, "receipt.md"), renderReceiptMd(receipt));
15705
15899
  recordRun(process.env, ctx.repoDir, ranModel(o.implement, ctx.model, o.fix), verdict, cost.usd, cost.unmetered === true, totalS);
15706
15900
  try {
15707
15901
  hooks.sealed?.(ctx.runDir, JSON.parse(JSON.stringify(receipt), (_k, v) => v && typeof v === "object" ? Object.freeze(v) : v));
@@ -15727,7 +15921,7 @@ var init_seal = __esm(() => {
15727
15921
 
15728
15922
  // ../../loki-ts/src/features/receipt_dsse.ts
15729
15923
  import { createPublicKey as createPublicKey3, sign as sign2, verify as verify3 } from "crypto";
15730
- import { readFileSync as readFileSync52 } from "fs";
15924
+ import { readFileSync as readFileSync53 } from "fs";
15731
15925
  function pae(payloadType, body) {
15732
15926
  const t = Buffer.from(payloadType, "utf8");
15733
15927
  return Buffer.concat([Buffer.from(`DSSEv1 ${t.length} `), t, Buffer.from(` ${body.length} `), body]);
@@ -15804,7 +15998,7 @@ function verifyDsseReceipt(env, d) {
15804
15998
  }
15805
15999
  function runIdGuard(receiptPath, runId) {
15806
16000
  try {
15807
- return envelopeRunIdProblem(JSON.parse(readFileSync52(receiptPath, "utf8")), runId);
16001
+ return envelopeRunIdProblem(JSON.parse(readFileSync53(receiptPath, "utf8")), runId);
15808
16002
  } catch {
15809
16003
  return null;
15810
16004
  }
@@ -15813,14 +16007,14 @@ var DSSE_PAYLOAD_TYPE = "application/vnd.in-toto+json", STATEMENT_TYPE = "https:
15813
16007
  var init_receipt_dsse = () => {};
15814
16008
 
15815
16009
  // ../../loki-ts/src/util/composite_seal.ts
15816
- import { existsSync as existsSync45, readFileSync as readFileSync53 } from "fs";
15817
- import { basename as basename23, dirname as dirname29, join as join68 } from "path";
16010
+ import { existsSync as existsSync46, readFileSync as readFileSync54 } from "fs";
16011
+ import { basename as basename23, dirname as dirname30, join as join68 } from "path";
15818
16012
  function logProblem(runDir, integ) {
15819
16013
  if (typeof integ["log_sha256"] !== "string")
15820
16014
  return null;
15821
16015
  let b;
15822
16016
  try {
15823
- b = readFileSync53(join68(runDir, "integration.log"));
16017
+ b = readFileSync54(join68(runDir, "integration.log"));
15824
16018
  } catch {
15825
16019
  return "integration.log is missing but integration.json records its hash";
15826
16020
  }
@@ -15835,7 +16029,7 @@ function integrationProblem(integ) {
15835
16029
  return null;
15836
16030
  }
15837
16031
  async function verifyComposite(receiptPath, receipt, rh, verifyOne, deps = {}) {
15838
- const runDir = dirname29(receiptPath);
16032
+ const runDir = dirname30(receiptPath);
15839
16033
  const signed = isObj10(receipt["verification"]) && typeof receipt["verification"]["jwt"] === "string";
15840
16034
  const bad = (reason) => ({ problem: { verdict: "TAMPERED", reason: `composite: ${reason}` }, verdict: "FAILED" });
15841
16035
  const kids = receipt["children"];
@@ -15843,7 +16037,7 @@ async function verifyComposite(receiptPath, receipt, rh, verifyOne, deps = {}) {
15843
16037
  return bad("body malformed");
15844
16038
  let ibytes;
15845
16039
  try {
15846
- ibytes = readFileSync53(join68(runDir, "integration.json"));
16040
+ ibytes = readFileSync54(join68(runDir, "integration.json"));
15847
16041
  } catch {
15848
16042
  return bad("integration.json missing");
15849
16043
  }
@@ -15882,7 +16076,7 @@ async function verifyComposite(receiptPath, receipt, rh, verifyOne, deps = {}) {
15882
16076
  const rp = join68(runDir, rel);
15883
16077
  let bytes;
15884
16078
  try {
15885
- bytes = readFileSync53(rp);
16079
+ bytes = readFileSync54(rp);
15886
16080
  } catch {
15887
16081
  return bad(`child ${repo} receipt missing`);
15888
16082
  }
@@ -15931,8 +16125,8 @@ var init_keys_cmd = __esm(() => {
15931
16125
  });
15932
16126
 
15933
16127
  // ../../loki-ts/src/engine10/verify_cmd.ts
15934
- import { existsSync as existsSync46, readFileSync as readFileSync54, renameSync as renameSync14, statSync as statSync21, writeFileSync as writeFileSync32 } from "fs";
15935
- import { basename as basename24, dirname as dirname30, join as join69 } from "path";
16128
+ import { existsSync as existsSync47, readFileSync as readFileSync55, renameSync as renameSync14, statSync as statSync22, writeFileSync as writeFileSync33 } from "fs";
16129
+ import { basename as basename24, dirname as dirname31, join as join69 } from "path";
15936
16130
  import { createHash as createHash18, createPublicKey as createPublicKey4, verify as verify4 } from "crypto";
15937
16131
  function pubFor(kid, given) {
15938
16132
  if (given)
@@ -15940,7 +16134,7 @@ function pubFor(kid, given) {
15940
16134
  const active = loadSigningKey(false);
15941
16135
  const pubs = (process.env["LOKI_RECEIPT_RETIRED_PUBKEYS"] ?? "").split(":").map((f) => f.trim()).filter(Boolean).flatMap((f) => {
15942
16136
  try {
15943
- return [createPublicKey4(readFileSync54(f))];
16137
+ return [createPublicKey4(readFileSync55(f))];
15944
16138
  } catch {
15945
16139
  return [];
15946
16140
  }
@@ -15984,10 +16178,10 @@ function checkEventLog(receiptPath, receipt) {
15984
16178
  const claims = st !== null && typeof st === "object" && Object.keys(st).length > 0;
15985
16179
  return claims ? "the receipt records stages but binds the empty-log hash, so no events.jsonl can back it (missing, empty or non-empty); the receipt is forged or was sealed without a log. Re-run the task to produce a fresh receipt" : null;
15986
16180
  }
15987
- const path = join69(dirname30(receiptPath), "events.jsonl");
15988
- if (!existsSync46(path))
16181
+ const path = join69(dirname31(receiptPath), "events.jsonl");
16182
+ if (!existsSync47(path))
15989
16183
  return "events.jsonl is missing";
15990
- const raw2 = readFileSync54(path, "utf8"), events2 = readEvents(path), lines2 = raw2.split(`
16184
+ const raw2 = readFileSync55(path, "utf8"), events2 = readEvents(path), lines2 = raw2.split(`
15991
16185
  `).filter((l) => l.trim() !== "");
15992
16186
  if (events2.length !== lines2.length || events2.some((e, i) => e.seq !== i))
15993
16187
  return "events.jsonl has a forged, edited or missing line";
@@ -16003,7 +16197,7 @@ function checkEventLog(receiptPath, receipt) {
16003
16197
  return h.digest("hex") === bound ? null : "events.jsonl does not match the hash recorded at seal";
16004
16198
  }
16005
16199
  function checkLogSeal(receiptPath, hash, kid, given) {
16006
- const path = join69(dirname30(receiptPath), "events.jsonl"), events2 = readEvents(path), done = events2.findIndex((e) => e.type === "run.completed");
16200
+ const path = join69(dirname31(receiptPath), "events.jsonl"), events2 = readEvents(path), done = events2.findIndex((e) => e.type === "run.completed");
16007
16201
  if (!events2.some((e) => e.type === "receipt.sealed" && e.data["receipt_sha256"] === hash))
16008
16202
  return { verdict: "TAMPERED", reason: "events.jsonl has no receipt.sealed event for this receipt" };
16009
16203
  if (done < 0)
@@ -16011,7 +16205,7 @@ function checkLogSeal(receiptPath, hash, kid, given) {
16011
16205
  const seal = events2[done + 1], d = seal?.type === "log.sealed" ? seal.data : null;
16012
16206
  if (!d)
16013
16207
  return { verdict: "TAMPERED", reason: "events.jsonl has no signed log.sealed line after run.completed" };
16014
- const lines2 = readFileSync54(path, "utf8").split(`
16208
+ const lines2 = readFileSync55(path, "utf8").split(`
16015
16209
  `).filter((l) => l.trim() !== ""), sha4 = createHash18("sha256").update(lines2.slice(0, done + 1).join(`
16016
16210
  `) + `
16017
16211
  `).digest("hex");
@@ -16021,11 +16215,11 @@ function checkLogSeal(receiptPath, hash, kid, given) {
16021
16215
  return null;
16022
16216
  }
16023
16217
  async function verifyReceipt(receiptPath, deps = {}) {
16024
- if (!existsSync46(receiptPath))
16218
+ if (!existsSync47(receiptPath))
16025
16219
  return { verdict: "UNCHECKED", reasons: [`receipt not found: ${receiptPath}`] };
16026
16220
  let receipt;
16027
16221
  try {
16028
- receipt = JSON.parse((deps.read ?? ((p) => readFileSync54(p, "utf8")))(receiptPath));
16222
+ receipt = JSON.parse((deps.read ?? ((p) => readFileSync55(p, "utf8")))(receiptPath));
16029
16223
  } catch {
16030
16224
  return { verdict: "UNCHECKED", reasons: ["receipt.json is not valid JSON"] };
16031
16225
  }
@@ -16114,8 +16308,8 @@ var init_verify_cmd = __esm(() => {
16114
16308
  });
16115
16309
 
16116
16310
  // src/server/app.ts
16117
- import { existsSync as existsSync48, readFileSync as readFileSync57, statSync as statSync22 } from "fs";
16118
- import { join as join72, resolve as resolve14, sep as sep14 } from "path";
16311
+ import { existsSync as existsSync49, readFileSync as readFileSync58, statSync as statSync23 } from "fs";
16312
+ import { join as join72, resolve as resolve15, sep as sep15 } from "path";
16119
16313
 
16120
16314
  // node_modules/hono/dist/request/constants.js
16121
16315
  var GET_MATCH_RESULT = Symbol();
@@ -26397,9 +26591,9 @@ function mount20(ctx) {
26397
26591
  }
26398
26592
 
26399
26593
  // src/server/routes/verify.ts
26400
- import { readFileSync as readFileSync55, realpathSync as realpathSync22 } from "fs";
26594
+ import { readFileSync as readFileSync56, realpathSync as realpathSync24 } from "fs";
26401
26595
  import { createPublicKey as createPublicKey5 } from "crypto";
26402
- import { join as join70, sep as sep13 } from "path";
26596
+ import { join as join70, sep as sep14 } from "path";
26403
26597
  init_verify_cmd();
26404
26598
  init_seal();
26405
26599
  init_receipt_dsse();
@@ -26426,15 +26620,15 @@ function mount21(ctx) {
26426
26620
  return done(404, "receipt not available", "not_found");
26427
26621
  let runDir, file;
26428
26622
  try {
26429
- const root = realpathSync22(join70(repo.p, ".loki", "runs"));
26430
- runDir = realpathSync22(join70(root, run2));
26623
+ const root = realpathSync24(join70(repo.p, ".loki", "runs"));
26624
+ runDir = realpathSync24(join70(root, run2));
26431
26625
  if (runDir !== join70(root, run2))
26432
26626
  return done(404, "receipt not found", "not_found");
26433
- file = realpathSync22(join70(runDir, "receipt.json"));
26627
+ file = realpathSync24(join70(runDir, "receipt.json"));
26434
26628
  } catch {
26435
26629
  return done(404, "receipt not found", "not_found");
26436
26630
  }
26437
- if (!file.startsWith(runDir + sep13))
26631
+ if (!file.startsWith(runDir + sep14))
26438
26632
  return done(404, "receipt not found", "not_found");
26439
26633
  let integrity, reasons, sha4 = null, outcome = "UNREADABLE";
26440
26634
  try {
@@ -26449,7 +26643,7 @@ function mount21(ctx) {
26449
26643
  sha4 = r.receiptSha256 ?? null;
26450
26644
  }
26451
26645
  try {
26452
- outcome = outcomeOf(JSON.parse(readFileSync55(file, "utf8")));
26646
+ outcome = outcomeOf(JSON.parse(readFileSync56(file, "utf8")));
26453
26647
  } catch {
26454
26648
  outcome = "UNREADABLE";
26455
26649
  }
@@ -26511,7 +26705,7 @@ function ttlCache(ttlMs = PROBE_CACHE_MS, now2 = Date.now) {
26511
26705
  }
26512
26706
 
26513
26707
  // src/server/legacy/shim.ts
26514
- import { existsSync as existsSync47, readFileSync as readFileSync56 } from "fs";
26708
+ import { existsSync as existsSync48, readFileSync as readFileSync57 } from "fs";
26515
26709
  import { join as join71 } from "path";
26516
26710
 
26517
26711
  // src/server/legacy/routes.ts
@@ -26892,8 +27086,8 @@ var NOT_SUPPORTED = "not yet supported by the Control Plane";
26892
27086
  var repoVersion = () => {
26893
27087
  for (const f of [join71(import.meta.dir, "../../../../../VERSION")]) {
26894
27088
  try {
26895
- if (existsSync47(f))
26896
- return readFileSync56(f, "utf8").trim();
27089
+ if (existsSync48(f))
27090
+ return readFileSync57(f, "utf8").trim();
26897
27091
  } catch {}
26898
27092
  }
26899
27093
  return "unknown";
@@ -27075,7 +27269,7 @@ function legacyShim(opts) {
27075
27269
 
27076
27270
  // src/server/app.ts
27077
27271
  var MAX_BODY2 = 1e6;
27078
- var defaultUiDir = () => [join72(import.meta.dir, "../../ui/dist"), join72(import.meta.dir, "../ui/dist")].find((d) => existsSync48(join72(d, "index.html")));
27272
+ var defaultUiDir = () => [join72(import.meta.dir, "../../ui/dist"), join72(import.meta.dir, "../ui/dist")].find((d) => existsSync49(join72(d, "index.html")));
27079
27273
  function createApp(opts) {
27080
27274
  const uiDir = opts.uiDir ?? defaultUiDir();
27081
27275
  const { db, sqlite } = openDb(opts.dbPath);
@@ -27107,7 +27301,7 @@ function createApp(opts) {
27107
27301
  for (const f of [process.env.LOKI_VERSION_FILE, join72(import.meta.dir, "../../../../VERSION")]) {
27108
27302
  try {
27109
27303
  if (f)
27110
- return readFileSync57(f, "utf8").trim() || "unknown";
27304
+ return readFileSync58(f, "utf8").trim() || "unknown";
27111
27305
  } catch {}
27112
27306
  }
27113
27307
  return "unknown";
@@ -27216,9 +27410,9 @@ function createApp(opts) {
27216
27410
  }
27217
27411
  if (!uiDir || p.startsWith("/v1/"))
27218
27412
  return c.json({ error: "not found" }, 404);
27219
- const root = resolve14(uiDir);
27220
- const f = resolve14(root, `.${p}`);
27221
- if (f.startsWith(root + sep14) && existsSync48(f) && statSync22(f).isFile())
27413
+ const root = resolve15(uiDir);
27414
+ const f = resolve15(root, `.${p}`);
27415
+ if (f.startsWith(root + sep15) && existsSync49(f) && statSync23(f).isFile())
27222
27416
  return new Response(Bun.file(f));
27223
27417
  if (/\.[a-z0-9]+$/i.test(p))
27224
27418
  return c.json({ error: "not found" }, 404);