loki-mode 11.81.1 → 11.83.0

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 (70) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/lib/telemetry-schema.json +1 -1
  4. package/autonomy/telemetry.sh +1 -1
  5. package/dashboard/__init__.py +1 -1
  6. package/docs/CLI-REFERENCE.md +1 -1
  7. package/docs/INSTALLATION.md +1 -1
  8. package/loki-ts/dist/loki.js +1397 -1380
  9. package/loki-ts/package.json +1 -1
  10. package/mcp/__init__.py +1 -1
  11. package/package.json +2 -2
  12. package/packages/control-plane/dist/server.js +818 -566
  13. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  14. package/web-app/dist/assets/{AdminPage-Vc1xmG5S.js → AdminPage-DpWNKWhs.js} +1 -1
  15. package/web-app/dist/assets/{Avatar-DpDwMCRf.js → Avatar-BjGfE5Z2.js} +1 -1
  16. package/web-app/dist/assets/{Badge-Db74zT9q.js → Badge-BZzQgc5L.js} +1 -1
  17. package/web-app/dist/assets/{Button-GehhhJSq.js → Button-B4UFBoKo.js} +1 -1
  18. package/web-app/dist/assets/{CockpitPage-BGdBtPaF.js → CockpitPage-HrjOxPcp.js} +1 -1
  19. package/web-app/dist/assets/{ComparePage-DpnZuvk5.js → ComparePage-rDB52mbC.js} +1 -1
  20. package/web-app/dist/assets/{ErrorBoundary-DzEqEovi.js → ErrorBoundary-BnGTHBD5.js} +1 -1
  21. package/web-app/dist/assets/{EvidenceReceiptPanel-Cw7HQjzr.js → EvidenceReceiptPanel-EWQ-AUvr.js} +1 -1
  22. package/web-app/dist/assets/{GitHubIssuesPanel-Cxpn_s6S.js → GitHubIssuesPanel-COCm9cnv.js} +1 -1
  23. package/web-app/dist/assets/{GitHubPRsPanel-DCdf7lvR.js → GitHubPRsPanel-ZYNmFQAR.js} +1 -1
  24. package/web-app/dist/assets/{HomePage-DnVetpJ_.js → HomePage-CJXtxNhl.js} +2 -2
  25. package/web-app/dist/assets/{LoginPage-8VjdvfM3.js → LoginPage-CXG5HrnH.js} +1 -1
  26. package/web-app/dist/assets/{MagicPage-CP5dgazx.js → MagicPage-D_1k-qFR.js} +1 -1
  27. package/web-app/dist/assets/{MetricsPage-DOpoS7e3.js → MetricsPage-Bh2OOgQW.js} +1 -1
  28. package/web-app/dist/assets/{NotFoundPage-COzCrnS6.js → NotFoundPage-DYtJqd7q.js} +1 -1
  29. package/web-app/dist/assets/{ProjectPage-DO4l10Ay.js → ProjectPage-C0_lqGnI.js} +3 -3
  30. package/web-app/dist/assets/{ProjectsPage-C0tYUwpA.js → ProjectsPage-C3ZDOF-i.js} +1 -1
  31. package/web-app/dist/assets/{SettingsPage-CocOl0Br.js → SettingsPage-DNLBBiFb.js} +1 -1
  32. package/web-app/dist/assets/{ShowcasePage-D1JXy7Uh.js → ShowcasePage-jxMrHvDJ.js} +1 -1
  33. package/web-app/dist/assets/{SystemSettingsPage-J2oNgHg2.js → SystemSettingsPage-C2ZPx8uP.js} +1 -1
  34. package/web-app/dist/assets/{TeamsPage-CcE2AFtg.js → TeamsPage-CmSWv2WS.js} +1 -1
  35. package/web-app/dist/assets/{TemplatesPage-DYXxELhl.js → TemplatesPage-Cqcz3jC1.js} +1 -1
  36. package/web-app/dist/assets/{TerminalOutput-DNQJnu5M.js → TerminalOutput-Cfy74R8E.js} +1 -1
  37. package/web-app/dist/assets/{activity-BZxgQZSK.js → activity-DvB2Cewz.js} +1 -1
  38. package/web-app/dist/assets/{bell-BgmfzWCz.js → bell-DFPKTgoZ.js} +1 -1
  39. package/web-app/dist/assets/{bot-BGir-bWC.js → bot-Bf5xNfiN.js} +1 -1
  40. package/web-app/dist/assets/{check-CveMRLRE.js → check-BdqIiGKJ.js} +1 -1
  41. package/web-app/dist/assets/{chevron-left-Dxd2H6to.js → chevron-left-Q2RMHGjD.js} +1 -1
  42. package/web-app/dist/assets/{circle-alert-CBmik7wR.js → circle-alert-CSsLxjNX.js} +1 -1
  43. package/web-app/dist/assets/{clock-BOKNTHCd.js → clock-SUq-A-Pc.js} +1 -1
  44. package/web-app/dist/assets/{cloud-CQy11uYO.js → cloud-1Qu-bH4o.js} +1 -1
  45. package/web-app/dist/assets/{code-xml-G-3Gc_8h.js → code-xml-B8tVFMMA.js} +1 -1
  46. package/web-app/dist/assets/{database-DgDzuYJ_.js → database-BqqcDq2C.js} +1 -1
  47. package/web-app/dist/assets/{dollar-sign-Lp9JyaRP.js → dollar-sign-D3Q2UCG0.js} +1 -1
  48. package/web-app/dist/assets/{file-code-corner-BO2cQzOV.js → file-code-corner-CRIBFOW5.js} +1 -1
  49. package/web-app/dist/assets/{file-plus-DH7lzils.js → file-plus-Bv-fZPBA.js} +1 -1
  50. package/web-app/dist/assets/{globe-BfSvGNE3.js → globe-C4B7SAB9.js} +1 -1
  51. package/web-app/dist/assets/{hammer-DnCBfcc3.js → hammer-y0Ikysax.js} +1 -1
  52. package/web-app/dist/assets/{index-BQo5YwJS.js → index-dNruR__0.js} +3 -3
  53. package/web-app/dist/assets/{layers-BrW-wRnL.js → layers-EgGWmhHw.js} +1 -1
  54. package/web-app/dist/assets/{loader-circle-BMGt1Kfa.js → loader-circle-Bt5dIF0I.js} +1 -1
  55. package/web-app/dist/assets/{lock-65KUUGOn.js → lock-BGuyekU7.js} +1 -1
  56. package/web-app/dist/assets/{package-BuhQfrbf.js → package-BkYbeAX3.js} +1 -1
  57. package/web-app/dist/assets/{plus-CCqniqNu.js → plus-BzcgCbLN.js} +1 -1
  58. package/web-app/dist/assets/{refresh-cw-CaTVoaT8.js → refresh-cw-Dm5Jp3fH.js} +1 -1
  59. package/web-app/dist/assets/{rotate-ccw-G73Ulpkj.js → rotate-ccw-BwCcLLQd.js} +1 -1
  60. package/web-app/dist/assets/{scroll-text-Bl6ByvVU.js → scroll-text-ZdYcnYoT.js} +1 -1
  61. package/web-app/dist/assets/{server-UW4cgj8y.js → server-BKLLV1vh.js} +1 -1
  62. package/web-app/dist/assets/{shield-alert-C0FwCrI5.js → shield-alert-BmdJ5RUP.js} +1 -1
  63. package/web-app/dist/assets/{thumbs-up-ApOqvOwV.js → thumbs-up-BkgThloL.js} +1 -1
  64. package/web-app/dist/assets/{trash-2-BsQzJxqd.js → trash-2-CEGx8Si2.js} +1 -1
  65. package/web-app/dist/assets/{trending-down-mfvmwkOt.js → trending-down-bDEP2c-J.js} +1 -1
  66. package/web-app/dist/assets/{trending-up-DAE5_Gqc.js → trending-up-BTZtHq6z.js} +1 -1
  67. package/web-app/dist/assets/{upload-Ci5-pITX.js → upload-CU4BNteU.js} +1 -1
  68. package/web-app/dist/assets/{usePolling-DdLg3S71.js → usePolling-uzQ6JTcy.js} +1 -1
  69. package/web-app/dist/assets/{user-vdRHG5fO.js → user-Bz1t2qnf.js} +1 -1
  70. package/web-app/dist/index.html +1 -1
@@ -258,7 +258,7 @@ var ASSIGNMENT, RULES, QUERY_SEGMENT, SECRET_PARAM, redactQuery = (s) => s.repla
258
258
  if (!keep || !data || typeof data !== "object" || Array.isArray(data))
259
259
  return redactDeep(data);
260
260
  return Object.fromEntries(Object.entries(data).map(([k, v]) => typeof v === "string" && keep.get(k)?.test(v) ? [k, v] : [redactSecrets(k), redactDeep(v)]));
261
- }, redactEnvelope = (e) => Object.fromEntries(Object.entries(e).map(([k, v]) => [redactSecrets(k), k === "data" ? redactEventData(e.type, v) : redactDeep(v)]));
261
+ }, redactEnvelope = (e) => Object.fromEntries(Object.entries(e).map(([k, v]) => [redactSecrets(k), k === "data" ? redactEventData(e.type, v) : redactDeep(v)])), UNSAFE_TERMINAL_CHARS_RE;
262
262
  var init_redact = __esm(() => {
263
263
  ASSIGNMENT = /((?<![A-Za-z0-9_.-])[_.-]*(?:[A-Za-z0-9]+[_.-]+)*(?:password|passwd|secret|token|api[_-]?key|apikey)["']?\s*[:=]\s*)((?:"(?!\[REDACTED)(?:\\.|[^"\\\n])+")|(?:'(?!\[REDACTED)(?:\\.|[^'\\\n])+')|(?!["']|\[REDACTED)[^\s"',;&]+)/gi;
264
264
  RULES = [
@@ -300,6 +300,7 @@ var init_redact = __esm(() => {
300
300
  ["log.sealed", new Map([["kid", B64(43)], ["sig", B64(86)], ["events_sha256", HEX64]])],
301
301
  ["receipt.sealed", new Map([["kid", B64(43)], ["receipt_sha256", HEX64], ["events_sha256", HEX64]])]
302
302
  ]);
303
+ UNSAFE_TERMINAL_CHARS_RE = /[\x00-\x1f\x7f-\x9f\u00ad\u061c\u200b-\u200f\u2028-\u202e\u2060-\u2064\u2066-\u2069\ufeff]/g;
303
304
  });
304
305
 
305
306
  // ../../loki-ts/src/util/credential_env.ts
@@ -55777,6 +55778,7 @@ var init_test_file_text = __esm(() => {
55777
55778
  var exports_testmap = {};
55778
55779
  __export(exports_testmap, {
55779
55780
  projectInterpreter: () => projectInterpreter,
55781
+ missingJavaTool: () => missingJavaTool,
55780
55782
  isTestFile: () => isTestFile,
55781
55783
  impactedRefs: () => impactedRefs,
55782
55784
  harnessRunners: () => harnessRunners,
@@ -55796,6 +55798,10 @@ function pytestPython(root) {
55796
55798
  }
55797
55799
  return "python";
55798
55800
  }
55801
+ function missingJavaTool(files, env = process.env, root) {
55802
+ const want = files.some((f) => /(?:^|\/)pom\.xml$/.test(f)) ? "maven" : files.some((f) => /(?:^|\/)(?:build|settings)\.gradle(?:\.kts)?$|(?:^|\/)gradlew$/.test(f)) ? "gradle" : files.some((f) => /\.java$/.test(f)) ? "javac" : null;
55803
+ return want && !javaToolOk(want, env, root) ? JAVA_TOOLS[want].tool : null;
55804
+ }
55799
55805
  function guessRunner(fileName, runners, relPath) {
55800
55806
  if (fileName.endsWith(".py"))
55801
55807
  return runners.includes("unittest") && !runners.includes("pytest") ? "unittest" : "pytest";
@@ -55803,6 +55809,8 @@ function guessRunner(fileName, runners, relPath) {
55803
55809
  return "go";
55804
55810
  if (fileName.endsWith(".rs"))
55805
55811
  return runners.includes("cargo") && relPath !== undefined && CARGO_TEST_FILE_RE.test(relPath) ? "cargo" : null;
55812
+ if (fileName.endsWith(".java"))
55813
+ return ["maven", "gradle", "javac"].find((r) => runners.includes(r)) ?? null;
55806
55814
  return /\.[cm]?[jt]sx?$/.test(fileName) ? ["vitest", "jest", "bun", "node"].find((r) => runners.includes(r)) ?? null : null;
55807
55815
  }
55808
55816
  function projectInterpreter(root) {
@@ -55851,6 +55859,10 @@ function buildTestMap(root) {
55851
55859
  mark("go", rel);
55852
55860
  else if (name === "Cargo.toml")
55853
55861
  mark("cargo", rel);
55862
+ else if (name === "pom.xml")
55863
+ mark("maven", rel);
55864
+ else if (/^(?:build|settings)\.gradle(?:\.kts)?$/.test(name) || name === "gradlew")
55865
+ mark("gradle", rel);
55854
55866
  }
55855
55867
  const jsRunner = evidence["vitest"] ? "vitest" : evidence["jest"] ? "jest" : evidence["bun"] ? "bun" : evidence["node"] ? "node" : null;
55856
55868
  const tests = [];
@@ -55919,7 +55931,10 @@ class RealTestMapProvider {
55919
55931
  return impactedRefs(map, changedFiles);
55920
55932
  }
55921
55933
  }
55922
- var RUNNER_ORDER, COMMANDS, STDLIB_RUNNERS, FOREIGN_SOURCE_RE, harnessRunners = (runners, files = [], env = process.env, root, focus2 = []) => {
55934
+ var RUNNER_ORDER, COMMANDS, STDLIB_RUNNERS, FOREIGN_SOURCE_RE, JAVA_TOOLS, javaToolOk = (r, env, root) => {
55935
+ const t = JAVA_TOOLS[r];
55936
+ return !t || !!Bun.which(t.tool, { PATH: env.PATH ?? "" }) || !!t.wrapper && !!root && existsSync36(join53(root, t.wrapper));
55937
+ }, harnessRunners = (runners, files = [], env = process.env, root, focus2 = []) => pickHarnessRunners(runners, files, env, root, focus2).filter((r) => javaToolOk(r, env, root)), pickHarnessRunners = (runners, files, env, root, focus2) => {
55923
55938
  const onPath = (tool) => !!Bun.which(tool, { PATH: env.PATH ?? "" }), w = languageBytes(root, files, (f) => STDLIB_RUNNERS.find((r) => r.ext.test(f))?.runner ?? (/\.[cm]?[jt]sx?$/i.test(f) ? "js" : FOREIGN_SOURCE_RE.test(f) ? "other" : null)), at2 = (k3) => w.get(k3) ?? 0, js = at2("js"), top = STDLIB_RUNNERS.reduce((a, r) => at2(r.runner) > at2(a.runner) ? r : a), bun = env.LOKI_WALL_HARNESS_RUNNER !== "0" && onPath("bun") ? ["bun"] : toolchainRunner(files, focus2);
55924
55939
  const t = at2(top.runner), o = at2("other");
55925
55940
  return runners.length > 0 ? runners : js >= t && js >= o ? js === 0 && w.size > 0 ? [] : bun : t > o ? onPath(top.tool) ? [top.runner] : toolchainRunner(files, focus2) : [];
@@ -55939,7 +55954,7 @@ var init_testmap = __esm(() => {
55939
55954
  init_linguist();
55940
55955
  init_scope();
55941
55956
  init_test_file_text();
55942
- RUNNER_ORDER = ["pytest", "vitest", "jest", "bun", "node", "npm", "go", "cargo"];
55957
+ RUNNER_ORDER = ["pytest", "vitest", "jest", "bun", "node", "npm", "go", "cargo", "maven", "gradle", "javac"];
55943
55958
  COMMANDS = {
55944
55959
  pytest: { cmd: "python -m pytest -q <files>", coarse: false },
55945
55960
  unittest: { cmd: "python3 -m unittest <files>", coarse: false },
@@ -55949,11 +55964,15 @@ var init_testmap = __esm(() => {
55949
55964
  node: { cmd: "node --test <files>", coarse: false },
55950
55965
  npm: { cmd: "npm test --silent", coarse: true },
55951
55966
  go: { cmd: "go test ./<pkg dirs>", coarse: false },
55952
- cargo: { cmd: "cargo test", coarse: true }
55967
+ cargo: { cmd: "cargo test", coarse: true },
55968
+ maven: { cmd: "mvn test -Dtest=<class>", coarse: false },
55969
+ gradle: { cmd: "gradle cleanTest test --tests <class>", coarse: false },
55970
+ javac: { cmd: "javac + java <test class>", coarse: false }
55953
55971
  };
55954
- STDLIB_RUNNERS = [{ ext: /\.py$/, runner: "unittest", tool: "python3" }, { ext: /\.go$/, runner: "go", tool: "go" }, { ext: /\.rs$/, runner: "cargo", tool: "cargo" }];
55972
+ STDLIB_RUNNERS = [{ ext: /\.py$/, runner: "unittest", tool: "python3" }, { ext: /\.go$/, runner: "go", tool: "go" }, { ext: /\.rs$/, runner: "cargo", tool: "cargo" }, { ext: /\.java$/, runner: "javac", tool: "javac" }];
55955
55973
  FOREIGN_SOURCE_RE = /\.(?:py|go|rs|java|kt|kts|scala|rb|php|cs|c|cc|cpp|cxx|h|hpp|swift|m|mm|ex|exs|erl|hs|clj|lua|pl|dart|r|jl|zig)$/i;
55956
- TOOLCHAINS = [[/(?:^|\/)package\.json$/, "node", /\.[cm]?[jt]sx?$/], [/(?:^|\/)go\.mod$/, "go", /\.go$/], [/(?:^|\/)Cargo\.toml$/, "cargo", /\.rs$/], [/(?:^|\/)(?:pyproject\.toml|setup\.py|setup\.cfg|requirements(?:[-_.][\w.-]+)?\.txt|tox\.ini|pytest\.ini)$/, "pytest", /\.py$/]];
55974
+ JAVA_TOOLS = { maven: { tool: "mvn", wrapper: "mvnw" }, gradle: { tool: "gradle", wrapper: "gradlew" }, javac: { tool: "javac" } };
55975
+ TOOLCHAINS = [[/(?:^|\/)package\.json$/, "node", /\.[cm]?[jt]sx?$/], [/(?:^|\/)go\.mod$/, "go", /\.go$/], [/(?:^|\/)Cargo\.toml$/, "cargo", /\.rs$/], [/(?:^|\/)pom\.xml$/, "maven", /\.java$/], [/(?:^|\/)(?:build|settings)\.gradle(?:\.kts)?$|(?:^|\/)gradlew$/, "gradle", /\.java$/], [/(?:^|\/)(?:pyproject\.toml|setup\.py|setup\.cfg|requirements(?:[-_.][\w.-]+)?\.txt|tox\.ini|pytest\.ini)$/, "pytest", /\.py$/]];
55957
55976
  CARGO_TEST_FILE_RE = /(?:^|\/)tests\/[^/]+\.rs$/;
55958
55977
  });
55959
55978
 
@@ -56129,6 +56148,50 @@ function skipped(raw2) {
56129
56148
  return stripAnsi(raw2).split(`
56130
56149
  `).filter((l) => /^(?:=+ )?\d+ \w+.* in [\d.]+s|^\s*Tests?:?\s+\d|^(?:#|\u2139) skipped \d/.test(l.trim())).reduce((t, l) => t + [...l.matchAll(/(\d+) (?:skipped|deselected|xfailed)|skipped (\d+)/g)].reduce((u10, m) => u10 + +(m[1] ?? m[2]), 0), 0);
56131
56150
  }
56151
+ function javaSummary(raw2) {
56152
+ const ls2 = stripAnsi(raw2).split(`
56153
+ `).map((l) => l.trimEnd()), tail2 = ls2.filter((l) => l.trim()).slice(-40), ok2 = (re2) => {
56154
+ const m = tail2.map((l) => re2.exec(l)).filter(Boolean).pop();
56155
+ return m ? m[1] === "SUCCESS" || m[1] === "SUCCESSFUL" : null;
56156
+ };
56157
+ const wrap = ls2.filter((l) => l.trim()).slice(-1)[0]?.match(/^LOKI_JAVA_TESTS: (\d+) run, (\d+) failed$/);
56158
+ if (wrap) {
56159
+ const ids = ls2.flatMap((l) => l.match(/^FAIL (.+)$/)?.[1] ?? []), failed2 = +wrap[2];
56160
+ return +wrap[1] > 0 && ids.length === failed2 && ls2.filter((l) => /^(?:PASS|FAIL) /.test(l)).length === +wrap[1] ? { executed: +wrap[1], failed: failed2, ids } : null;
56161
+ }
56162
+ const mv2 = ok2(/^\[(?:INFO|ERROR)\] BUILD (SUCCESS|FAILURE)$/), gr2 = ok2(/^BUILD (SUCCESSFUL|FAILED)\b/);
56163
+ if (mv2 !== null) {
56164
+ let executed = 0, failed2 = 0, seen = false;
56165
+ ls2.forEach((l, i) => {
56166
+ if (/^\[(?:INFO|ERROR)\] Results:$/.test(l)) {
56167
+ const m = ls2.slice(i + 1, i + 40).map((x3) => /^\[(?:INFO|WARNING|ERROR)\] Tests run: (\d+), Failures: (\d+), Errors: (\d+), Skipped: (\d+)$/.exec(x3)).find(Boolean);
56168
+ if (m) {
56169
+ seen = true;
56170
+ executed += +m[1] - +m[4];
56171
+ failed2 += +m[2] + +m[3];
56172
+ }
56173
+ }
56174
+ });
56175
+ const ids = [...new Set(ls2.flatMap((l) => {
56176
+ const m = /^\[ERROR\] (?:(\S+)\(([\w.$]+)\)|([\w.$]+\.[\w$]+)(?:\[[^\]]*\])?) .*<<< (?:FAILURE|ERROR)!$/.exec(l);
56177
+ return m ? [m[3] ?? `${m[2]}.${m[1]}`] : [];
56178
+ }))];
56179
+ return seen && executed > 0 && (mv2 ? failed2 === 0 : failed2 > 0) ? { executed, failed: failed2, ids } : null;
56180
+ }
56181
+ if (gr2 !== null) {
56182
+ const ev2 = ls2.flatMap((l) => {
56183
+ const m = /^\s*(\S.*?) > (\S.*?) (PASSED|FAILED|SKIPPED)$/.exec(l);
56184
+ return m ? [{ id: `${m[1]}.${m[2]}`, s: m[3] }] : [];
56185
+ }), bad = ev2.filter((e10) => e10.s === "FAILED");
56186
+ const executed = ev2.filter((e10) => e10.s !== "SKIPPED").length;
56187
+ return executed > 0 && (gr2 ? bad.length === 0 : bad.length > 0) ? { executed, failed: bad.length, ids: [...new Set(bad.map((e10) => e10.id))] } : null;
56188
+ }
56189
+ return null;
56190
+ }
56191
+ function javaTestClass(path) {
56192
+ const m = /^(.*?)\/?src\/test\/java\/(.+)\.java$/.exec(path), cls = (m ? m[2] : basename12(path, ".java")).split("/").join(".");
56193
+ return { root: m?.[1] || ".", cls, rel: m ? `src/test/java/${m[2]}.java` : path };
56194
+ }
56132
56195
  function testCount(raw2, path, ok2) {
56133
56196
  const out3 = stripAnsi(raw2);
56134
56197
  const bu2 = bunCount(out3), ut = unittestCount(out3, ok2);
@@ -56136,6 +56199,9 @@ function testCount(raw2, path, ok2) {
56136
56199
  return bu2;
56137
56200
  if (ut !== null)
56138
56201
  return ut;
56202
+ const jv = javaSummary(out3);
56203
+ if (jv)
56204
+ return jv.executed;
56139
56205
  if (/^\s*(?:Test Files\s+0\b|No test files found)/m.test(out3) && !/^\s*Tests?\s+\d/m.test(out3))
56140
56206
  return 0;
56141
56207
  const r = ran(out3, path, ok2);
@@ -56202,6 +56268,9 @@ function classifyCheck(i) {
56202
56268
  return { result: "fail", ...n10 !== null ? { n: n10 } : {} };
56203
56269
  if (n10 === null)
56204
56270
  return { result: "not_run", reason: UNMEASURED_REASON };
56271
+ const jv = javaSummary(text3);
56272
+ if (jv && jv.failed > 0)
56273
+ return { result: "fail", n: n10 };
56205
56274
  return { result: "pass", n: n10 };
56206
56275
  }
56207
56276
  function checkProvenance(name, ctx) {
@@ -56715,6 +56784,10 @@ function classify(f, status, output, repoDir, interpreter) {
56715
56784
  return status === 1 ? pytestExit1IsRed(output) ? "fail" : "not_run" : status === 2 ? pytestCollectionIsRed(output, repoDir) ? "fail" : "not_run" : "not_run";
56716
56785
  if (f.runner === "jest" || f.runner === "vitest" || f.runner === "bun")
56717
56786
  return parsedFailCount(f.runner, output) > 0 ? "fail" : "not_run";
56787
+ if (f.runner === "maven" || f.runner === "gradle" || f.runner === "javac") {
56788
+ const j10 = javaSummary(output);
56789
+ return j10 && j10.failed > 0 ? "fail" : "not_run";
56790
+ }
56718
56791
  return f.runner === "node" && nodeIsRed(f, output) ? "fail" : "not_run";
56719
56792
  }
56720
56793
  function baseJobs() {
@@ -56809,11 +56882,27 @@ function runnerCmd(t, repoDir) {
56809
56882
  const names = goTestNames(join54(repoDir, t.path));
56810
56883
  return ["go", ["test", "-json", ...names.length ? ["-run", `^(${names.join("|")})$`] : [], `./${dirname23(t.path)}`]];
56811
56884
  }
56885
+ case "maven": {
56886
+ const j10 = javaTestClass(t.path);
56887
+ return [wrapperOr(repoDir, "mvnw", "mvn"), ["-B", "test", `-Dtest=${j10.cls.split(".").pop()}`, "-Dsurefire.failIfNoSpecifiedTests=false", "-DfailIfNoTests=false"]];
56888
+ }
56889
+ case "gradle": {
56890
+ const j10 = javaTestClass(t.path);
56891
+ return [wrapperOr(repoDir, "gradlew", "gradle"), ["cleanTest", "test", "--tests", j10.cls, "-i", "--console=plain"]];
56892
+ }
56893
+ case "javac": {
56894
+ const j10 = javaTestClass(t.path);
56895
+ return ["bash", ["-c", JAVAC_WRAPPER, "loki-javac", j10.root, j10.cls, j10.rel]];
56896
+ }
56812
56897
  case "cargo":
56813
56898
  return CARGO_TEST_FILE_RE.test(t.path) ? ["cargo", ["test", "--test", basename12(t.path, ".rs")]] : ["cargo", ["test"]];
56814
56899
  }
56815
56900
  }
56816
56901
  function fullSuiteCmd(runner, repoDir) {
56902
+ if (runner === "maven" || runner === "gradle") {
56903
+ const s = FULL_SUITE_STATIC[runner];
56904
+ return { ...s, cmd: wrapperOr(repoDir, runner === "maven" ? "mvnw" : "gradlew", s.cmd) };
56905
+ }
56817
56906
  if (runner !== "pytest" && runner !== "unittest")
56818
56907
  return FULL_SUITE_STATIC[runner];
56819
56908
  const [cmd, interpreter, pre2] = resolveTool(repoDir, "python", "python3", "python");
@@ -56896,7 +56985,23 @@ function firstFileLineAnchor(desc2) {
56896
56985
  }
56897
56986
  var NO_TESTS_REASON = "no tests executed", NO_RUNNER_REASON = "no runner of this repo runs this file", harnessSkipCode = (env = process.env) => env.LOKI_WALL_HARNESS_RUNNER === "0" ? "harness_runner_disabled" : Bun.which("bun", { PATH: env.PATH ?? "" }) ? "no_toolchain" : "bun_not_on_path", 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, `
56898
56987
  `), tailLines = (out3) => out3.split(`
56899
- `).filter((x3) => x3.trim()).slice(-12), GO_PKG_RE, EXIT_CODED_COUNT = "n/a (exit-coded check, not a test runner)", FRAMEWORK_RE, SCRIPT_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))), CODE_FILE_EXT, DECL_RE, VAR_DECL_RE, stripComments = (src) => src.replace(/\/\*[\s\S]*?\*\//g, " ").split(`
56988
+ `).filter((x3) => x3.trim()).slice(-12), GO_PKG_RE, JAVAC_WRAPPER = `set -u
56989
+ root="$1"; cls="$2"; shift 2; cd "$root" || exit 70
56990
+ if [ "$cls" = "-" ]; then
56991
+ set -- $(find src/test/java -name '*Test.java' 2>/dev/null | sort); cls=""
56992
+ for f in "$@"; do c="\${f#src/test/java/}"; c="\${c%.java}"; cls="$cls \${c//\\//.}"; done
56993
+ fi
56994
+ out="$(mktemp -d "\${TMPDIR:-/tmp}/loki-javac.XXXXXX")" || exit 70
56995
+ trap 'rm -rf -- "\${out:?}"' EXIT
56996
+ find src/main/java -name '*.java' 2>/dev/null > "$out/srcs"
56997
+ javac -nowarn -d "$out" @"$out/srcs" "$@" || exit 1
56998
+ st=0; : > "$out/run.log"
56999
+ for c in $cls; do java -cp "$out" "$c" >> "$out/run.log" 2>&1 || st=$?; done
57000
+ cat "$out/run.log"
57001
+ p=$(grep -c '^PASS ' "$out/run.log"); f=$(grep -c '^FAIL ' "$out/run.log")
57002
+ echo "LOKI_JAVA_TESTS: $((p + f)) run, $f failed"
57003
+ [ "$f" -gt 0 ] && st=1
57004
+ exit $st`, wrapperOr = (repoDir, w, bare) => existsSync37(join54(repoDir, w)) ? `./${w}` : bare, EXIT_CODED_COUNT = "n/a (exit-coded check, not a test runner)", FRAMEWORK_RE, SCRIPT_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))), CODE_FILE_EXT, DECL_RE, VAR_DECL_RE, stripComments = (src) => src.replace(/\/\*[\s\S]*?\*\//g, " ").split(`
56900
57005
  `).map((l) => /^\s*\*/.test(l) ? "" : l.replace(/\/\/.*$/, "").replace(/(^|\s)#.*$/, "$1")).join(`
56901
57006
  `), GO_METHOD_RE, METHOD_RE, NOT_A_NAME, declNames = (line2) => {
56902
57007
  const out3 = [];
@@ -56911,7 +57016,7 @@ var NO_TESTS_REASON = "no tests executed", NO_RUNNER_REASON = "no runner of this
56911
57016
  if (m)
56912
57017
  out3.push(m[1]);
56913
57018
  return out3.filter((n10) => !NOT_A_NAME.has(n10));
56914
- }, printable = (s) => s.replace(/[\x00-\x1f\x7f]/g, "?"), SENSITIVE, API, TEST_CFG, RANK3, FILES_MEDIUM = 4, FILES_HIGH = 15, LINES_MEDIUM = 100, LINES_HIGH = 500, RAN_ALWAYS, REVIEWER_ITEM = "one reviewer", PLAN, LOW_SKIPPED, deferredOf = (tier, selected, executed) => (tier === "low" ? LOW_SKIPPED : selected).filter((c) => !RAN_ALWAYS.includes(c) && !executed.includes(c)), DEEP_ITEMS, NOT_SELECTED = "not selected by risk tier: ", MANIFEST_LOCKS, dirOf = (p) => p.includes("/") ? p.slice(0, p.lastIndexOf("/")) : "", PKG_DEP_KEYS, PYPROJECT_NONDEP, SEM_RULES, DOC_FILE, readOr = (p) => {
57019
+ }, printable = (s) => s.replace(UNSAFE_TERMINAL_CHARS_RE, "?"), SENSITIVE, API, TEST_CFG, RANK3, FILES_MEDIUM = 4, FILES_HIGH = 15, LINES_MEDIUM = 100, LINES_HIGH = 500, RAN_ALWAYS, REVIEWER_ITEM = "one reviewer", PLAN, LOW_SKIPPED, deferredOf = (tier, selected, executed) => (tier === "low" ? LOW_SKIPPED : selected).filter((c) => !RAN_ALWAYS.includes(c) && !executed.includes(c)), DEEP_ITEMS, NOT_SELECTED = "not selected by risk tier: ", MANIFEST_LOCKS, dirOf = (p) => p.includes("/") ? p.slice(0, p.lastIndexOf("/")) : "", PKG_DEP_KEYS, PYPROJECT_NONDEP, SEM_RULES, DOC_FILE, readOr = (p) => {
56915
57020
  try {
56916
57021
  return readFileSync49(p, "utf8");
56917
57022
  } catch {
@@ -56990,7 +57095,10 @@ var init_check_result = __esm(() => {
56990
57095
  node: { cmd: "node", args: ["--test"] },
56991
57096
  npm: { cmd: "npm", args: ["test", "--silent"] },
56992
57097
  go: { cmd: "go", args: ["test", "-json", "./..."] },
56993
- cargo: { cmd: "cargo", args: ["test"] }
57098
+ cargo: { cmd: "cargo", args: ["test"] },
57099
+ maven: { cmd: "mvn", args: ["-B", "test"] },
57100
+ gradle: { cmd: "gradle", args: ["cleanTest", "test", "-i", "--console=plain"] },
57101
+ javac: { cmd: "bash", args: ["-c", JAVAC_WRAPPER, "loki-javac", ".", "-"] }
56994
57102
  };
56995
57103
  URL_RE = /\b[a-z][a-z0-9+.-]{0,63}:\/\/\S+/gi;
56996
57104
  ANCHOR_RE = /(?<![\w./@-])([\w./@-]{1,512})[`'"]?(?::L?|#L|\s*\(line\s+)([1-9]\d*)(?!\d)/g;
@@ -59186,6 +59294,9 @@ function failIds(raw2) {
59186
59294
  const output = stripAnsi(raw2), gc2 = goCargoIds(output);
59187
59295
  if (gc2)
59188
59296
  return gc2;
59297
+ const jv = javaSummary(output);
59298
+ if (jv)
59299
+ return jv.failed > 0 && jv.ids.length >= jv.failed ? jv.ids : [];
59189
59300
  const ids = [...new Set(output.split(`
59190
59301
  `).map((l) => ID_LINE.exec(l.trim())).flatMap((m) => m ? [(m.slice(1).find(Boolean) ?? "").trim()] : []).filter(Boolean))];
59191
59302
  const c = failCount(output);
@@ -64503,7 +64614,10 @@ class TestName(unittest.TestCase):
64503
64614
  def test_it(self): self.assertEqual(fn(1), 2)
64504
64615
  Run: python3 -m unittest <file>.`,
64505
64616
  go: `${COMMANDS.go.cmd.replace(" ./<pkg dirs>", "")}. Write a _test.go file in the package under test. Example: func TestName(t *testing.T) { if got := Fn(1); got != 2 { t.Fatalf("got %v", got) } } Run: ${COMMANDS.go.cmd.replace("<pkg dirs>", "<dir>")}.`,
64506
- cargo: `${COMMANDS.cargo.cmd}. Write an integration test file directly under tests/ that calls the crate's public API. Example: #[test] fn name() { assert_eq!(my_crate::f(1), 2); } Run: ${COMMANDS.cargo.cmd} --test <stem>.`
64617
+ cargo: `${COMMANDS.cargo.cmd}. Write an integration test file directly under tests/ that calls the crate's public API. Example: #[test] fn name() { assert_eq!(my_crate::f(1), 2); } Run: ${COMMANDS.cargo.cmd} --test <stem>.`,
64618
+ maven: `Maven + JUnit (use the JUnit version already declared in the build file). Put the file in src/test/java/ (add a package line only if the code under test is in a package). The file name must end in Test.java and the public class name must equal the file name without .java, so surefire picks it up. Example: import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; public class loki_wall_LeapTest { @Test void leap() { assertTrue(Leap.is(2000)); } } Run: ${COMMANDS.maven.cmd.replace("<class>", "<ClassName>")}.`,
64619
+ gradle: `Gradle + JUnit (use the JUnit version already declared in the build file). Put the file in src/test/java/. The public class name must equal the file name without .java and the file name must end in Test.java. Example: import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; public class loki_wall_LeapTest { @Test void leap() { assertTrue(Leap.is(2000)); } } Run: ${COMMANDS.gradle.cmd.replace("<class>", "<ClassName>")}.`,
64620
+ javac: 'Plain Java 8+ with NO test framework and NO build tool (do not import org.junit). Put the file in src/test/java/. The file name must end in Test.java and the public class name must equal the file name without .java. The class has public static void main. For every check print exactly one line, `PASS <name>` or `FAIL <name>` (name on the same line), and at the end System.exit(1) if any check failed. Catch exceptions per check so one failure does not hide the rest. Example: static void check(String n, boolean ok) { System.out.println((ok ? "PASS " : "FAIL ") + n); if (!ok) failed = true; } Run: javac the sources under src/main/java plus the file, then java <ClassName>.'
64507
64621
  };
64508
64622
  });
64509
64623
 
@@ -65318,27 +65432,102 @@ var init_select = __esm(() => {
65318
65432
  RANK_LABELS = ["wallPasses", "deterministicFails", "passesInS", "flakyInS", "lintFails", "diffLines", "index"];
65319
65433
  });
65320
65434
 
65435
+ // ../../loki-ts/src/features/dependents.ts
65436
+ import { readFileSync as readFileSync73 } from "fs";
65437
+ import { dirname as dirname33, join as join82, normalize as normalize5 } from "path";
65438
+ function importTargets(rel, text3) {
65439
+ const out3 = [], dir = dirname33(rel);
65440
+ if (JS2.test(rel))
65441
+ for (const m of text3.matchAll(JS_SPEC_RE)) {
65442
+ const spec = m[1] ?? "";
65443
+ if (!spec.startsWith("."))
65444
+ continue;
65445
+ const p = posix3(join82(dir, spec)), stem = p.replace(/\.[cm]?[jt]sx?$/, "");
65446
+ out3.push(p, ...JS_EXT2.flatMap((e10) => [stem + e10, `${p}/index${e10}`]));
65447
+ }
65448
+ else if (PY3.test(rel)) {
65449
+ const add3 = (dots, mod, names) => {
65450
+ const up2 = dots > 0 ? join82(dir, ...Array(dots - 1).fill("..")) : "", roots = dots > 0 ? [up2] : [".", dir], path = mod.split(".").filter(Boolean).join("/");
65451
+ for (const r of roots) {
65452
+ const b = join82(r, path);
65453
+ if (path)
65454
+ out3.push(...pyMod(posix3(b)).map(posix3));
65455
+ for (const n10 of names)
65456
+ out3.push(...pyMod(posix3(join82(b, n10))));
65457
+ }
65458
+ };
65459
+ for (const m of text3.matchAll(PY_FROM)) {
65460
+ const dots = /^\.*/.exec(m[1])[0].length;
65461
+ add3(dots, m[1].slice(dots), m[2].replace(/[()]/g, "").split(",").map((s) => s.trim().split(/\s+as\s+/)[0]).filter((s) => /^\w+$/.test(s)));
65462
+ }
65463
+ for (const m of text3.matchAll(PY_IMP))
65464
+ for (const part of m[1].split(","))
65465
+ add3(0, part.trim().split(/\s+as\s+/)[0], []);
65466
+ }
65467
+ return out3;
65468
+ }
65469
+ function dependentTests(repoDir, map, changed, already) {
65470
+ const chg = new Set(changed.map(posix3).filter((f) => JS2.test(f) || PY3.test(f))), none = { tests: [], dropped: 0, truncated: false };
65471
+ if (chg.size === 0)
65472
+ return none;
65473
+ const isTest = new Set(map.tests.map((t) => t.path)), have = new Set(already.map((t) => t.path)), t02 = Date.now();
65474
+ let bytes = 0, truncated = false;
65475
+ const deps = new Set;
65476
+ for (const rel of listProjectFiles(repoDir)) {
65477
+ if (!(JS2.test(rel) || PY3.test(rel)) || isTest.has(rel) || chg.has(rel))
65478
+ continue;
65479
+ if (bytes > SCAN_MAX_BYTES || Date.now() - t02 > SCAN_MAX_MS) {
65480
+ truncated = true;
65481
+ break;
65482
+ }
65483
+ const text3 = read2(repoDir, rel);
65484
+ bytes += text3.length;
65485
+ if (importsAny(text3, rel, chg))
65486
+ deps.add(rel);
65487
+ }
65488
+ if (deps.size === 0)
65489
+ return { ...none, truncated };
65490
+ const all = map.tests.filter((t) => !have.has(t.path) && importsAny(read2(repoDir, t.path), t.path, deps)).sort((a, b) => a.path.localeCompare(b.path));
65491
+ return { tests: all.slice(0, MAX_DEPENDENT_TESTS), dropped: Math.max(0, all.length - MAX_DEPENDENT_TESTS), truncated };
65492
+ }
65493
+ var MAX_DEPENDENT_TESTS = 20, SCAN_MAX_BYTES = 48000000, SCAN_MAX_MS = 4000, FILE_MAX_BYTES = 256000, JS2, PY3, JS_EXT2, PY_FROM, PY_IMP, posix3 = (p) => normalize5(p).split("\\").join("/").replace(/^\.\//, ""), pyMod = (base) => [`${base}.py`, `${base}/__init__.py`], read2 = (repoDir, rel) => {
65494
+ try {
65495
+ return readFileSync73(join82(repoDir, rel), "utf8").slice(0, FILE_MAX_BYTES);
65496
+ } catch {
65497
+ return "";
65498
+ }
65499
+ }, importsAny = (text3, rel, set) => importTargets(rel, text3).some((t) => set.has(t)), dependentNotes = (d) => [...d.truncated ? ["reverse-dependent scan hit its byte or time bound: some importers of changed files may not have been tested"] : [], ...d.dropped ? [`reverse-dependent tests dropped by the ${MAX_DEPENDENT_TESTS}-file cap: ${d.dropped}`] : []];
65500
+ var init_dependents = __esm(() => {
65501
+ init_safe_git();
65502
+ init_test_file_text();
65503
+ JS2 = /\.(?:[cm]?[jt]sx?)$/;
65504
+ PY3 = /\.py$/;
65505
+ JS_EXT2 = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
65506
+ PY_FROM = /^[ \t]*from[ \t]+(\.*[\w.]*)[ \t]+import[ \t]+(\([^)]*\)|[^\n#]+)/gm;
65507
+ PY_IMP = /^[ \t]*import[ \t]+([\w., \t]+)/gm;
65508
+ });
65509
+
65321
65510
  // ../../loki-ts/src/util/app_probe.ts
65322
65511
  import { spawnSync as spawnSync9 } from "child_process";
65323
- import { existsSync as existsSync56, mkdirSync as mkdirSync40, readFileSync as readFileSync73, renameSync as renameSync18, writeFileSync as writeFileSync38 } from "fs";
65324
- import { join as join82 } from "path";
65512
+ import { existsSync as existsSync56, mkdirSync as mkdirSync40, readFileSync as readFileSync74, renameSync as renameSync18, writeFileSync as writeFileSync38 } from "fs";
65513
+ import { join as join83 } from "path";
65325
65514
  function readJson5(p) {
65326
65515
  try {
65327
- const v3 = JSON.parse(readFileSync73(p, "utf8"));
65516
+ const v3 = JSON.parse(readFileSync74(p, "utf8"));
65328
65517
  return v3 && typeof v3 === "object" ? v3 : null;
65329
65518
  } catch {
65330
65519
  return null;
65331
65520
  }
65332
65521
  }
65333
65522
  function stopApp(repoDir, opts = {}) {
65334
- const runner = opts.runnerPath ?? join82(REPO_ROOT, "autonomy", "app-runner.sh");
65335
- if (!existsSync56(runner) || !existsSync56(join82(repoDir, ".loki", "app-runner", "app.pid")))
65523
+ const runner = opts.runnerPath ?? join83(REPO_ROOT, "autonomy", "app-runner.sh");
65524
+ if (!existsSync56(runner) || !existsSync56(join83(repoDir, ".loki", "app-runner", "app.pid")))
65336
65525
  return;
65337
65526
  spawnSync9("bash", ["-c", STOP, "app-probe", repoDir, runner], { cwd: repoDir, env: plainTestEnv(), timeout: opts.timeoutMs ?? 60000, killSignal: "SIGKILL", stdio: "ignore" });
65338
65527
  }
65339
65528
  async function appProbe(repoDir, lokiDir2, opts = {}) {
65340
- const timeoutMs = opts.timeoutMs ?? 60000, runner = opts.runnerPath ?? join82(REPO_ROOT, "autonomy", "app-runner.sh");
65341
- const dir = join82(repoDir, ".loki", "app-runner"), checks = [];
65529
+ const timeoutMs = opts.timeoutMs ?? 60000, runner = opts.runnerPath ?? join83(REPO_ROOT, "autonomy", "app-runner.sh");
65530
+ const dir = join83(repoDir, ".loki", "app-runner"), checks = [];
65342
65531
  const t02 = Date.now();
65343
65532
  const mk3 = (name, result, reason) => ({ name, cmd: "autonomy/app-runner.sh", result, duration_s: (Date.now() - t02) / 1000, reason });
65344
65533
  const sh3 = (script) => {
@@ -65356,9 +65545,9 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
65356
65545
  return { checks, pid, url };
65357
65546
  }
65358
65547
  const ir2 = Number(m[1]), sr2 = Number(m[2]), hr = Number(m[3]), noApp = m[4] === "1";
65359
- const pidTxt = existsSync56(join82(dir, "app.pid")) ? readFileSync73(join82(dir, "app.pid"), "utf8").trim() : "";
65548
+ const pidTxt = existsSync56(join83(dir, "app.pid")) ? readFileSync74(join83(dir, "app.pid"), "utf8").trim() : "";
65360
65549
  pid = /^\d+$/.test(pidTxt) && sr2 >= 0 ? Number(pidTxt) : null;
65361
- const st2 = readJson5(join82(dir, "state.json"));
65550
+ const st2 = readJson5(join83(dir, "state.json"));
65362
65551
  url = typeof st2?.["url"] === "string" ? st2["url"] : null;
65363
65552
  if (sr2 < 0) {
65364
65553
  checks.push(noApp ? mk3("app boot", "n/a", "app-runner detected no app") : mk3("app boot", "not_run", ir2 === 0 ? "app-runner detected no app" : "no runnable app detected or runtime missing"), mk3("http probe", noApp ? "n/a" : "not_run", "app not booted"));
@@ -65369,7 +65558,7 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
65369
65558
  return { checks, pid, url };
65370
65559
  }
65371
65560
  checks.push(mk3("app boot", "pass", "app process started"));
65372
- const health = readJson5(join82(dir, "health.json"));
65561
+ const health = readJson5(join83(dir, "health.json"));
65373
65562
  checks.push(hr === 0 && health?.["ok"] === true ? mk3("http probe", "pass", "health.json ok") : mk3("http probe", "fail", "app-runner health check failed"));
65374
65563
  if (opts.specText !== undefined && checks[1]?.result === "pass" && url)
65375
65564
  checks.push(await functionalVerify(opts, url, dir, lokiDir2, timeoutMs));
@@ -65382,10 +65571,10 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
65382
65571
  async function functionalVerify(opts, url, dir, lokiDir2, timeoutMs) {
65383
65572
  const t02 = Date.now();
65384
65573
  const res = (result, reason) => ({ name: "functional verify", cmd: "autonomy/lib/functional-verify.py", result, duration_s: (Date.now() - t02) / 1000, reason });
65385
- const py2 = await findPython3(), script = opts.verifyPath ?? join82(REPO_ROOT, "autonomy", "lib", "functional-verify.py");
65574
+ const py2 = await findPython3(), script = opts.verifyPath ?? join83(REPO_ROOT, "autonomy", "lib", "functional-verify.py");
65386
65575
  if (!py2 || !existsSync56(script))
65387
65576
  return res("not_run", "python3 or functional-verify.py unavailable");
65388
- const specFile = join82(dir, "spec.txt");
65577
+ const specFile = join83(dir, "spec.txt");
65389
65578
  writeFileSync38(specFile, opts.specText ?? "");
65390
65579
  const r = spawnSync9(py2, ["-I", script, specFile, url], { env: plainTestEnv(), encoding: "utf8", timeout: timeoutMs, killSignal: "SIGKILL", stdio: ["ignore", "pipe", "ignore"] });
65391
65580
  let out3 = null;
@@ -65397,11 +65586,11 @@ async function functionalVerify(opts, url, dir, lokiDir2, timeoutMs) {
65397
65586
  }
65398
65587
  if (!out3 || r.status !== 0)
65399
65588
  return res("not_run", "functional harness produced no result");
65400
- const q10 = join82(lokiDir2, "quality");
65589
+ const q10 = join83(lokiDir2, "quality");
65401
65590
  mkdirSync40(q10, { recursive: true });
65402
- const tmp = join82(q10, `functional-results.json.tmp.${process.pid}`);
65591
+ const tmp = join83(q10, `functional-results.json.tmp.${process.pid}`);
65403
65592
  writeFileSync38(tmp, JSON.stringify(out3, null, 2));
65404
- renameSync18(tmp, join82(q10, "functional-results.json"));
65593
+ renameSync18(tmp, join83(q10, "functional-results.json"));
65405
65594
  const s = String(out3["functional_status"] ?? "inconclusive");
65406
65595
  return res(s === "verified" ? "pass" : s === "failed" ? "fail" : "not_run", `functional_status ${s}`);
65407
65596
  }
@@ -65433,15 +65622,15 @@ app_runner_stop >/dev/null 2>&1
65433
65622
  });
65434
65623
 
65435
65624
  // ../../loki-ts/src/util/secure_scan.ts
65436
- import { copyFileSync as copyFileSync5, existsSync as existsSync57, lstatSync as lstatSync23, mkdirSync as mkdirSync41, mkdtempSync as mkdtempSync9, readFileSync as readFileSync74, realpathSync as realpathSync26, rmSync as rmSync21, statSync as statSync25, writeFileSync as writeFileSync39 } from "fs";
65625
+ import { copyFileSync as copyFileSync5, existsSync as existsSync57, lstatSync as lstatSync23, mkdirSync as mkdirSync41, mkdtempSync as mkdtempSync9, readFileSync as readFileSync75, realpathSync as realpathSync26, rmSync as rmSync21, statSync as statSync25, writeFileSync as writeFileSync39 } from "fs";
65437
65626
  import { randomBytes as randomBytes6 } from "crypto";
65438
65627
  import { tmpdir as tmpdir12 } from "os";
65439
- import { basename as basename22, dirname as dirname33, join as join83, resolve as resolve28, sep as sep17 } from "path";
65628
+ import { basename as basename22, dirname as dirname34, join as join84, resolve as resolve28, sep as sep17 } from "path";
65440
65629
  function fail(error) {
65441
65630
  return { ok: false, findings: [], error };
65442
65631
  }
65443
65632
  async function runSecureScan(targetDir, opts = {}) {
65444
- const script = opts.scriptPath ?? join83(REPO_ROOT, "autonomy", "lib", "secure-scan.py");
65633
+ const script = opts.scriptPath ?? join84(REPO_ROOT, "autonomy", "lib", "secure-scan.py");
65445
65634
  if (!existsSync57(script))
65446
65635
  return fail(`secure-scan script not found: ${script}`);
65447
65636
  const py2 = await findPython3();
@@ -65485,12 +65674,12 @@ async function runSecureScan(targetDir, opts = {}) {
65485
65674
  return fail(`secure-scan failed (exit ${res.exitCode}): ${tail2}`);
65486
65675
  }
65487
65676
  async function secureScanChanged(repoDir, changed, scriptPath) {
65488
- const dir = mkdtempSync9(join83(tmpdir12(), "loki-deep-secure-"));
65677
+ const dir = mkdtempSync9(join84(tmpdir12(), "loki-deep-secure-"));
65489
65678
  try {
65490
65679
  for (const f of changed)
65491
- if (existsSync57(join83(repoDir, f)) && lstatSync23(join83(repoDir, f)).isFile()) {
65492
- mkdirSync41(dirname33(join83(dir, f)), { recursive: true });
65493
- copyFileSync5(join83(repoDir, f), join83(dir, f));
65680
+ if (existsSync57(join84(repoDir, f)) && lstatSync23(join84(repoDir, f)).isFile()) {
65681
+ mkdirSync41(dirname34(join84(dir, f)), { recursive: true });
65682
+ copyFileSync5(join84(repoDir, f), join84(dir, f));
65494
65683
  }
65495
65684
  return await runSecureScan(dir, { ...scriptPath ? { scriptPath } : {}, timeoutMs: 60000 });
65496
65685
  } finally {
@@ -65624,7 +65813,7 @@ async function scanAddedLines(repoDir, opts = {}) {
65624
65813
  const skipped2 = [];
65625
65814
  for (const p of untracked2.split("\x00").filter(Boolean)) {
65626
65815
  try {
65627
- const st2 = statSync25(join83(repoDir, p));
65816
+ const st2 = statSync25(join84(repoDir, p));
65628
65817
  if (!st2.isFile())
65629
65818
  continue;
65630
65819
  if (st2.size > MAX_ADDED_FILE_BYTES) {
@@ -65639,14 +65828,14 @@ async function scanAddedLines(repoDir, opts = {}) {
65639
65828
  continue;
65640
65829
  }
65641
65830
  const lines2 = new Map;
65642
- readFileSync74(join83(repoDir, p), "utf8").split(`
65831
+ readFileSync75(join84(repoDir, p), "utf8").split(`
65643
65832
  `).forEach((t, i) => lines2.set(i + 1, t));
65644
65833
  added.set(p, lines2);
65645
65834
  } catch {}
65646
65835
  }
65647
65836
  if (added.size === 0)
65648
65837
  return { ok: true, findings: skipped2 };
65649
- const mirror = mkdtempSync9(join83(tmpdir12(), "loki-secure-added-"));
65838
+ const mirror = mkdtempSync9(join84(tmpdir12(), "loki-secure-added-"));
65650
65839
  try {
65651
65840
  const root = resolve28(mirror) + sep17;
65652
65841
  const chunkMap = new Map;
@@ -65692,12 +65881,12 @@ async function scanAddedLines(repoDir, opts = {}) {
65692
65881
  chunks.push(cur);
65693
65882
  const whole = chunks.length === 1;
65694
65883
  for (const c of chunks) {
65695
- const rel = whole ? p : join83(chunkRoot, String(chunkSeq++), basename22(p));
65884
+ const rel = whole ? p : join84(chunkRoot, String(chunkSeq++), basename22(p));
65696
65885
  const out3 = whole ? dest : resolve28(mirror, rel);
65697
65886
  if (!out3.startsWith(root))
65698
65887
  break;
65699
65888
  chunkMap.set(rel, { file: p, lines: c.orig });
65700
- mkdirSync41(dirname33(out3), { recursive: true });
65889
+ mkdirSync41(dirname34(out3), { recursive: true });
65701
65890
  writeFileSync39(out3, c.body.join(`
65702
65891
  `) + `
65703
65892
  `);
@@ -65744,14 +65933,14 @@ var init_secure_scan = __esm(() => {
65744
65933
  });
65745
65934
 
65746
65935
  // ../../loki-ts/src/util/run_control.ts
65747
- import { existsSync as existsSync58, readFileSync as readFileSync75, renameSync as renameSync19, writeFileSync as writeFileSync40 } from "fs";
65748
- import { join as join84 } from "path";
65936
+ import { existsSync as existsSync58, readFileSync as readFileSync76, renameSync as renameSync19, writeFileSync as writeFileSync40 } from "fs";
65937
+ import { join as join85 } from "path";
65749
65938
  function readRunControl(runDir) {
65750
- const p = join84(runDir, RUN_CONTROL_FILE);
65939
+ const p = join85(runDir, RUN_CONTROL_FILE);
65751
65940
  if (!existsSync58(p))
65752
65941
  return null;
65753
65942
  try {
65754
- const a = JSON.parse(readFileSync75(p, "utf8")).action;
65943
+ const a = JSON.parse(readFileSync76(p, "utf8")).action;
65755
65944
  return typeof a === "string" && ACTIONS2.has(a) ? a : null;
65756
65945
  } catch {
65757
65946
  return null;
@@ -65809,8 +65998,8 @@ var init_run_control = __esm(() => {
65809
65998
  });
65810
65999
 
65811
66000
  // ../../loki-ts/src/project_model/conventions.ts
65812
- import { existsSync as existsSync59, readdirSync as readdirSync27, readFileSync as readFileSync76 } from "fs";
65813
- import { basename as basename23, dirname as dirname34, isAbsolute as isAbsolute15, join as join85, relative as relative16, resolve as resolve29 } from "path";
66001
+ import { existsSync as existsSync59, readdirSync as readdirSync27, readFileSync as readFileSync77 } from "fs";
66002
+ import { basename as basename23, dirname as dirname35, isAbsolute as isAbsolute15, join as join86, relative as relative16, resolve as resolve29 } from "path";
65814
66003
  function parseJsonc(text3) {
65815
66004
  let out3 = "", i = 0;
65816
66005
  while (i < text3.length) {
@@ -65845,7 +66034,7 @@ function moduleOf(file, depth = 0) {
65845
66034
  const ext = typeof j10.extends === "string" ? j10.extends : null;
65846
66035
  if (!ext || !ext.startsWith("."))
65847
66036
  return null;
65848
- const next = join85(dirname34(file), ext.endsWith(".json") ? ext : `${ext}.json`);
66037
+ const next = join86(dirname35(file), ext.endsWith(".json") ? ext : `${ext}.json`);
65849
66038
  return existsSync59(next) ? moduleOf(next, depth + 1) : null;
65850
66039
  }
65851
66040
  function readPackageConventions(pkgDir, runner = null) {
@@ -65857,13 +66046,13 @@ function readPackageConventions(pkgDir, runner = null) {
65857
66046
  }
65858
66047
  let packageType = null, tsModule = null;
65859
66048
  for (const n10 of names) {
65860
- const j10 = readJson6(join85(pkgDir, n10));
66049
+ const j10 = readJson6(join86(pkgDir, n10));
65861
66050
  if (!j10)
65862
66051
  continue;
65863
66052
  if (packageType === null && typeof j10.type === "string" && typeof j10.name === "string")
65864
66053
  packageType = j10.type;
65865
66054
  if (tsModule === null && j10.compilerOptions !== undefined)
65866
- tsModule = moduleOf(join85(pkgDir, n10));
66055
+ tsModule = moduleOf(join86(pkgDir, n10));
65867
66056
  }
65868
66057
  if (packageType === null && tsModule === null)
65869
66058
  return null;
@@ -65969,13 +66158,13 @@ function vacuousCheck(fileName, content) {
65969
66158
  function nearestPackageRoot(testDir, repoDir, fileName) {
65970
66159
  const api = loadProjectApi(repoDir);
65971
66160
  if (api)
65972
- return siteFor(api, repoDir, relative16(repoDir, join85(testDir, fileName)))?.cwd ?? repoDir;
66161
+ return siteFor(api, repoDir, relative16(repoDir, join86(testDir, fileName)))?.cwd ?? repoDir;
65973
66162
  const shaped = (d) => {
65974
66163
  try {
65975
66164
  return readdirSync27(d).some((f) => {
65976
66165
  if (!f.endsWith(".json"))
65977
66166
  return false;
65978
- const j10 = readJson6(join85(d, f));
66167
+ const j10 = readJson6(join86(d, f));
65979
66168
  return !!j10 && typeof j10.name === "string" && Object.keys(j10).length > 1;
65980
66169
  });
65981
66170
  } catch {
@@ -65983,8 +66172,8 @@ function nearestPackageRoot(testDir, repoDir, fileName) {
65983
66172
  }
65984
66173
  };
65985
66174
  let pkg = testDir;
65986
- while (pkg !== repoDir && pkg !== dirname34(pkg) && !shaped(pkg))
65987
- pkg = dirname34(pkg);
66175
+ while (pkg !== repoDir && pkg !== dirname35(pkg) && !shaped(pkg))
66176
+ pkg = dirname35(pkg);
65988
66177
  return pkg;
65989
66178
  }
65990
66179
  function phantomRepoPaths(content, fileName, testDir, repoDir, planText) {
@@ -66036,7 +66225,7 @@ function phantomRepoPaths(content, fileName, testDir, repoDir, planText) {
66036
66225
  };
66037
66226
  const strayInTestDir = (out3) => {
66038
66227
  const first = relative16(testDir, out3).split("/")[0];
66039
- return !!first && first !== "__self__" && !existsSync59(join85(testDir, first)) && [pkg, repoDir].some((d) => d !== testDir && existsSync59(join85(d, first)));
66228
+ return !!first && first !== "__self__" && !existsSync59(join86(testDir, first)) && [pkg, repoDir].some((d) => d !== testDir && existsSync59(join86(d, first)));
66040
66229
  };
66041
66230
  const scan = (cwd) => {
66042
66231
  const vars = new Map, walk = new Set, taint = new Set, reports = new Map, created = [];
@@ -66051,7 +66240,7 @@ function phantomRepoPaths(content, fileName, testDir, repoDir, planText) {
66051
66240
  if (env)
66052
66241
  return ev2(env[1], report);
66053
66242
  if (e10 === "fileURLToPath(import.meta.url)" || e10 === "__filename")
66054
- return join85(testDir, "__self__");
66243
+ return join86(testDir, "__self__");
66055
66244
  const url = /^fileURLToPath\(new URL\((["'])([^"']*)\1\s*,\s*import\.meta\.url\)\)$/.exec(e10);
66056
66245
  if (url)
66057
66246
  return resolve29(testDir, url[2]);
@@ -66067,11 +66256,11 @@ function phantomRepoPaths(content, fileName, testDir, repoDir, planText) {
66067
66256
  if (args.some((a) => a === null))
66068
66257
  return null;
66069
66258
  if (call[1] === "dirname")
66070
- return dirname34(args[0]);
66259
+ return dirname35(args[0]);
66071
66260
  const out3 = resolve29(...args);
66072
- const first = parts.slice(1).map((a) => /^\s*["'`]([^"'`]*)["'`]\s*$/.exec(a)?.[1]).find((x3) => x3), viaWalk = !!first && walk.has(parts[0].trim()) && [pkg, repoDir].some((d) => existsSync59(join85(d, first.split("/").filter(Boolean)[0] ?? "\x00")));
66261
+ const first = parts.slice(1).map((a) => /^\s*["'`]([^"'`]*)["'`]\s*$/.exec(a)?.[1]).find((x3) => x3), viaWalk = !!first && walk.has(parts[0].trim()) && [pkg, repoDir].some((d) => existsSync59(join86(d, first.split("/").filter(Boolean)[0] ?? "\x00")));
66073
66262
  if (report && (viaWalk || !parts.some((a) => walk.has(a.trim()) || taint.has(a.trim())) && (relative16(testDir, out3).startsWith("..") || strayInTestDir(out3))) && parts.some((a) => /^\s*["'`]/.test(a)))
66074
- reports.set(`${ln2}|${e10}`, { out: out3, rel: relative16(repoDir, out3), tail: viaWalk ? join85(...args.slice(1)) : undefined });
66263
+ reports.set(`${ln2}|${e10}`, { out: out3, rel: relative16(repoDir, out3), tail: viaWalk ? join86(...args.slice(1)) : undefined });
66075
66264
  return out3;
66076
66265
  };
66077
66266
  for (const line2 of walkCode.split(`
@@ -66119,7 +66308,7 @@ function phantomRepoPaths(content, fileName, testDir, repoDir, planText) {
66119
66308
  const runs2 = [...new Set([pkg, repoDir])].map(scan);
66120
66309
  const planned = (rel) => !!planText && rel.split("/").some((_, i, a) => {
66121
66310
  const pre2 = a.slice(0, i + 1).join("/");
66122
- return (i > 0 || a.length === 1) && !existsSync59(join85(repoDir, pre2)) && new RegExp(`(?<![\\w-])${pre2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w-])`).test(planText);
66311
+ return (i > 0 || a.length === 1) && !existsSync59(join86(repoDir, pre2)) && new RegExp(`(?<![\\w-])${pre2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w-])`).test(planText);
66123
66312
  });
66124
66313
  const phantom = (r, created) => {
66125
66314
  const rel = r.rel;
@@ -66129,11 +66318,11 @@ function phantomRepoPaths(content, fileName, testDir, repoDir, planText) {
66129
66318
  const seen = (from) => {
66130
66319
  let d = from;
66131
66320
  for (let i = 0;i < 64; i++) {
66132
- if (existsSync59(join85(d, r.tail)))
66321
+ if (existsSync59(join86(d, r.tail)))
66133
66322
  return true;
66134
- if (d === repoDir || d === dirname34(d))
66323
+ if (d === repoDir || d === dirname35(d))
66135
66324
  return false;
66136
- d = dirname34(d);
66325
+ d = dirname35(d);
66137
66326
  }
66138
66327
  return false;
66139
66328
  };
@@ -66171,7 +66360,7 @@ function phantomReason(miss, repoFiles, testDir = "", pkgRoot = "") {
66171
66360
  }
66172
66361
  var readJson6 = (p) => {
66173
66362
  try {
66174
- const v3 = parseJsonc(readFileSync76(p, "utf8"));
66363
+ const v3 = parseJsonc(readFileSync77(p, "utf8"));
66175
66364
  return v3 && typeof v3 === "object" && !Array.isArray(v3) ? v3 : null;
66176
66365
  } catch {
66177
66366
  return null;
@@ -66180,8 +66369,8 @@ var readJson6 = (p) => {
66180
66369
  ${bad.map((b) => `- ${b.name}: ${b.why}`).join(`
66181
66370
  `)}`, `Point every reference at the repository code with repo-relative paths (for example join(import.meta.dir, "..", "<repo path>") or the equivalent for this runner). Do not read the home directory, $HOME or an environment variable that falls back to one. Write nothing else.`].join(`
66182
66371
 
66183
- `), outOfRepoTests = (repoDir, changed) => changed.filter((f) => /(^|[\/._-])(test|spec)s?[\/._-]|_test\./i.test(f) && existsSync59(join85(repoDir, f))).flatMap((name) => {
66184
- const why = outOfRepoTarget(readFileSync76(join85(repoDir, name), "utf8"));
66372
+ `), outOfRepoTests = (repoDir, changed) => changed.filter((f) => /(^|[\/._-])(test|spec)s?[\/._-]|_test\./i.test(f) && existsSync59(join86(repoDir, f))).flatMap((name) => {
66373
+ const why = outOfRepoTarget(readFileSync77(join86(repoDir, name), "utf8"));
66185
66374
  return why ? [{ name, why }] : [];
66186
66375
  }), CREATORS;
66187
66376
  var init_conventions = __esm(() => {
@@ -66191,16 +66380,16 @@ var init_conventions = __esm(() => {
66191
66380
  });
66192
66381
 
66193
66382
  // ../../loki-ts/src/util/pr_lessons.ts
66194
- import { existsSync as existsSync60, mkdirSync as mkdirSync42, mkdtempSync as mkdtempSync10, readFileSync as readFileSync77, rmSync as rmSync22, writeFileSync as writeFileSync41 } from "fs";
66383
+ import { existsSync as existsSync60, mkdirSync as mkdirSync42, mkdtempSync as mkdtempSync10, readFileSync as readFileSync78, rmSync as rmSync22, writeFileSync as writeFileSync41 } from "fs";
66195
66384
  import { homedir as homedir10, tmpdir as tmpdir13 } from "os";
66196
- import { dirname as dirname35, join as join86 } from "path";
66385
+ import { dirname as dirname36, join as join87 } from "path";
66197
66386
  import { createHash as createHash26 } from "crypto";
66198
66387
  function loadLessons(repoDir) {
66199
66388
  const p = lessonsPath(repoDir);
66200
66389
  if (!existsSync60(p))
66201
66390
  return [];
66202
66391
  try {
66203
- const j10 = JSON.parse(readFileSync77(p, "utf-8"));
66392
+ const j10 = JSON.parse(readFileSync78(p, "utf-8"));
66204
66393
  return Array.isArray(j10.lessons) ? j10.lessons : [];
66205
66394
  } catch {
66206
66395
  return [];
@@ -66208,12 +66397,12 @@ function loadLessons(repoDir) {
66208
66397
  }
66209
66398
  function save3(repoDir, lessons) {
66210
66399
  const p = lessonsPath(repoDir);
66211
- mkdirSync42(dirname35(p), { recursive: true });
66400
+ mkdirSync42(dirname36(p), { recursive: true });
66212
66401
  atomicWriteJson(p, { version: 2, lessons });
66213
66402
  }
66214
66403
  function loadPromoted() {
66215
66404
  try {
66216
- const j10 = JSON.parse(readFileSync77(promotedPath(), "utf-8"));
66405
+ const j10 = JSON.parse(readFileSync78(promotedPath(), "utf-8"));
66217
66406
  return Array.isArray(j10.lessons) ? j10.lessons : [];
66218
66407
  } catch {
66219
66408
  return [];
@@ -66324,7 +66513,7 @@ ${body}
66324
66513
  function learningsBlock(repoDir, limit = 5) {
66325
66514
  let items2 = [];
66326
66515
  try {
66327
- const parsed = JSON.parse(readFileSync77(join86(repoDir, ".loki", "state", "relevant-learnings.json"), "utf-8"));
66516
+ const parsed = JSON.parse(readFileSync78(join87(repoDir, ".loki", "state", "relevant-learnings.json"), "utf-8"));
66328
66517
  if (Array.isArray(parsed.learnings))
66329
66518
  items2 = parsed.learnings;
66330
66519
  } catch {
@@ -66354,7 +66543,7 @@ ${lines2.join(`
66354
66543
  </untrusted-learnings>
66355
66544
  `;
66356
66545
  }
66357
- var lessonsPath = (repoDir) => join86(repoDir, ".loki", "memory", "semantic", "pr-lessons.json"), promotedPath = () => join86(process.env["LOKI_PROMOTED_DIR"] || join86(homedir10(), ".loki"), "memory", "semantic", "promoted-lessons.json"), DEMOTE_AFTER = 3, demoteOn = () => process.env["LOKI_PR_LESSON_DEMOTE"] !== "0", HEX642, KINDS, VERDICT_BASE, words = (s) => new Set(s.toLowerCase().match(/[a-z0-9_]{4,}/g) ?? []), fence = (s) => s.replace(/[<>]/g, "");
66546
+ var lessonsPath = (repoDir) => join87(repoDir, ".loki", "memory", "semantic", "pr-lessons.json"), promotedPath = () => join87(process.env["LOKI_PROMOTED_DIR"] || join87(homedir10(), ".loki"), "memory", "semantic", "promoted-lessons.json"), DEMOTE_AFTER = 3, demoteOn = () => process.env["LOKI_PR_LESSON_DEMOTE"] !== "0", HEX642, KINDS, VERDICT_BASE, words = (s) => new Set(s.toLowerCase().match(/[a-z0-9_]{4,}/g) ?? []), fence = (s) => s.replace(/[<>]/g, "");
66358
66547
  var init_pr_lessons = __esm(() => {
66359
66548
  init_redact();
66360
66549
  init_atomic();
@@ -66374,7 +66563,7 @@ import {
66374
66563
  lstatSync as lstatSync24,
66375
66564
  mkdirSync as mkdirSync43,
66376
66565
  openSync as openSync13,
66377
- readFileSync as readFileSync78,
66566
+ readFileSync as readFileSync79,
66378
66567
  readlinkSync as readlinkSync5,
66379
66568
  realpathSync as realpathSync27,
66380
66569
  rmSync as rmSync23,
@@ -66382,7 +66571,7 @@ import {
66382
66571
  unlinkSync as unlinkSync8,
66383
66572
  writeFileSync as writeFileSync42
66384
66573
  } from "fs";
66385
- import { dirname as dirname36, isAbsolute as isAbsolute16, join as join87, relative as relative17, resolve as resolve30, sep as sep18 } from "path";
66574
+ import { dirname as dirname37, isAbsolute as isAbsolute16, join as join88, relative as relative17, resolve as resolve30, sep as sep18 } from "path";
66386
66575
  function git8(root, args) {
66387
66576
  return safeGit(root, args);
66388
66577
  }
@@ -66422,7 +66611,7 @@ function safeJoin(root, relPath) {
66422
66611
  const segment = segments[i];
66423
66612
  if (segment === undefined)
66424
66613
  continue;
66425
- cur = join87(cur, segment);
66614
+ cur = join88(cur, segment);
66426
66615
  if (i < segments.length - 1) {
66427
66616
  let st2;
66428
66617
  try {
@@ -66439,7 +66628,7 @@ function safeJoin(root, relPath) {
66439
66628
  function assertSymlinkWithinRoot(root, relPath, target) {
66440
66629
  if (isAbsolute16(target))
66441
66630
  throw new TreeSwapUnsafePathError(`symlink ${relPath} has an absolute target`);
66442
- const resolvedTarget = resolve30(dirname36(join87(resolve30(root), relPath)), target);
66631
+ const resolvedTarget = resolve30(dirname37(join88(resolve30(root), relPath)), target);
66443
66632
  const rel = relative17(resolve30(root), resolvedTarget);
66444
66633
  if (rel === ".." || rel.startsWith(`..${"/"}`) || isAbsolute16(rel)) {
66445
66634
  throw new TreeSwapUnsafePathError(`symlink ${relPath} escapes tree root`);
@@ -66458,7 +66647,7 @@ function readEntry(root, relPath) {
66458
66647
  }
66459
66648
  const fd2 = openSync13(abs, fsc.O_RDONLY | fsc.O_NOFOLLOW);
66460
66649
  try {
66461
- return { content: readFileSync78(fd2), mode: st2.mode & 511 };
66650
+ return { content: readFileSync79(fd2), mode: st2.mode & 511 };
66462
66651
  } finally {
66463
66652
  closeSync13(fd2);
66464
66653
  }
@@ -66477,7 +66666,7 @@ function writeEntry(root, relPath, entry2) {
66477
66666
  assertSymlinkWithinRoot(root, relPath, entry2.symlinkTarget);
66478
66667
  }
66479
66668
  const abs = safeJoin(root, relPath);
66480
- mkdirSync43(dirname36(abs), { recursive: true });
66669
+ mkdirSync43(dirname37(abs), { recursive: true });
66481
66670
  removeEntry(root, relPath);
66482
66671
  if (entry2.symlinkTarget !== undefined) {
66483
66672
  symlinkSync4(entry2.symlinkTarget, abs);
@@ -66600,7 +66789,7 @@ function swapLocked(opts, excludes) {
66600
66789
  pre2.push({ path, kind: "file", content: e10.content, mode: e10.mode, symlinkTarget: e10.symlinkTarget });
66601
66790
  }
66602
66791
  mkdirSync43(opts.runDir, { recursive: true });
66603
- const undoPath = join87(opts.runDir, UNDO_FILE);
66792
+ const undoPath = join88(opts.runDir, UNDO_FILE);
66604
66793
  const enc = (l) => l.map((e10) => ({ ...e10, content: e10.content?.toString("base64") }));
66605
66794
  let fd2;
66606
66795
  try {
@@ -66640,7 +66829,7 @@ function removeLenient(root, relPath) {
66640
66829
  }
66641
66830
  }
66642
66831
  function restoreFromUndo(primaryRoot, runDir, excludes = DEFAULT_EXCLUDES) {
66643
- const rec2 = JSON.parse(readFileSync78(join87(runDir, UNDO_FILE), "utf8"));
66832
+ const rec2 = JSON.parse(readFileSync79(join88(runDir, UNDO_FILE), "utf8"));
66644
66833
  const dec = (l) => l.map((e10) => ({ ...e10, content: e10.content === undefined ? undefined : Buffer.from(e10.content, "base64") }));
66645
66834
  const entries = dec(rec2.entries);
66646
66835
  const errors2 = [];
@@ -66660,7 +66849,7 @@ function restoreFromUndo(primaryRoot, runDir, excludes = DEFAULT_EXCLUDES) {
66660
66849
  throw new AggregateError(errors2, "treeswap: rollback incomplete");
66661
66850
  }
66662
66851
  function cleanupAttempt(primaryRoot, runDir, attemptDir) {
66663
- const attemptsRoot = join87(realpathSync27(resolve30(runDir)), "attempts");
66852
+ const attemptsRoot = join88(realpathSync27(resolve30(runDir)), "attempts");
66664
66853
  let attemptsLst;
66665
66854
  try {
66666
66855
  attemptsLst = lstatSync24(attemptsRoot);
@@ -66677,17 +66866,17 @@ function cleanupAttempt(primaryRoot, runDir, attemptDir) {
66677
66866
  if (isPrimaryOrAncestor(realpathSync27(attemptsRoot)))
66678
66867
  throw new TreeSwapUnsafePathError(`attempts dir ${attemptsRoot} resolves to the primary tree`);
66679
66868
  const lexical = resolve30(attemptDir);
66680
- const parent = dirname36(lexical);
66869
+ const parent = dirname37(lexical);
66681
66870
  let real3;
66682
66871
  try {
66683
- real3 = join87(realpathSync27(parent), lexical.slice(parent.length + 1));
66872
+ real3 = join88(realpathSync27(parent), lexical.slice(parent.length + 1));
66684
66873
  lstatSync24(real3);
66685
66874
  } catch (err) {
66686
66875
  if (err.code === "ENOENT")
66687
66876
  return;
66688
66877
  throw err;
66689
66878
  }
66690
- if (dirname36(real3) !== attemptsRoot)
66879
+ if (dirname37(real3) !== attemptsRoot)
66691
66880
  throw new TreeSwapUnsafePathError(`${attemptDir} is not a direct child of ${attemptsRoot}`);
66692
66881
  if (isPrimaryOrAncestor(real3))
66693
66882
  throw new TreeSwapUnsafePathError(`${attemptDir} is or contains the primary tree`);
@@ -66698,7 +66887,7 @@ function cleanupAttempt(primaryRoot, runDir, attemptDir) {
66698
66887
  throw new TreeSwapUnsafePathError(`${attemptDir} is not a directory`);
66699
66888
  if (process.getuid && lst.uid !== process.getuid())
66700
66889
  throw new TreeSwapUnsafePathError(`refusing to remove ${attemptDir}: not owned by the current user`);
66701
- const gitFile = join87(real3, ".git");
66890
+ const gitFile = join88(real3, ".git");
66702
66891
  let isLinkedWorktree = false;
66703
66892
  try {
66704
66893
  isLinkedWorktree = lstatSync24(gitFile).isFile();
@@ -66725,8 +66914,8 @@ var init_treeswap = __esm(() => {
66725
66914
  });
66726
66915
 
66727
66916
  // ../../loki-ts/src/features/attempts.ts
66728
- import { existsSync as existsSync61, mkdirSync as mkdirSync44, readFileSync as readFileSync79 } from "fs";
66729
- import { join as join88 } from "path";
66917
+ import { existsSync as existsSync61, mkdirSync as mkdirSync44, readFileSync as readFileSync80 } from "fs";
66918
+ import { join as join89 } from "path";
66730
66919
  function assertScrubbedEnv(env) {
66731
66920
  for (const v3 of GITHUB_TOKEN_VARS) {
66732
66921
  const val = env[v3] ?? "";
@@ -66777,19 +66966,19 @@ async function runTwoAttempts(ops, S, wall, signal, env = process.env) {
66777
66966
  }
66778
66967
  }
66779
66968
  function treeswapOps(a) {
66780
- const attemptsDir = join88(a.runDir, "attempts"), bDir = join88(attemptsDir, "B");
66969
+ const attemptsDir = join89(a.runDir, "attempts"), bDir = join89(attemptsDir, "B");
66781
66970
  mkdirSync44(attemptsDir, { recursive: true });
66782
66971
  safeGit(a.primary, ["worktree", "add", "--detach", bDir, a.base]);
66783
66972
  const pre2 = new Set(untracked2(a.primary));
66784
66973
  let snapA = null;
66785
66974
  const wallWeakened = (root, isPrimary, p, touched) => {
66786
- const sealed = a.wallContent?.get(p), f = join88(root, p);
66975
+ const sealed = a.wallContent?.get(p), f = join89(root, p);
66787
66976
  if (!existsSync61(f))
66788
66977
  return isPrimary ? sealed !== undefined || touched.has(p) : false;
66789
66978
  if (sealed === undefined)
66790
66979
  return touched.has(p);
66791
66980
  try {
66792
- return readFileSync79(f, "utf8") !== sealed;
66981
+ return readFileSync80(f, "utf8") !== sealed;
66793
66982
  } catch {
66794
66983
  return true;
66795
66984
  }
@@ -66867,8 +67056,8 @@ var init_attempts = __esm(() => {
66867
67056
  });
66868
67057
 
66869
67058
  // ../../loki-ts/src/runner/router/route_record.ts
66870
- import { existsSync as existsSync62, lstatSync as lstatSync25, mkdirSync as mkdirSync45, readFileSync as readFileSync80, writeFileSync as writeFileSync43 } from "fs";
66871
- import { join as join89 } from "path";
67059
+ import { existsSync as existsSync62, lstatSync as lstatSync25, mkdirSync as mkdirSync45, readFileSync as readFileSync81, writeFileSync as writeFileSync43 } from "fs";
67060
+ import { join as join90 } from "path";
66872
67061
  function buildRouteRecord(i) {
66873
67062
  const notProven = [...i.notProven, ...i.planModelNote ? [`plan model: NOT PROVEN (owner provider): ${i.planModelNote}`] : []];
66874
67063
  const base = { plan_model: i.planModel, shape_key: i.shapeKey, route_not_proven: notProven, applied: PER_UNIT_EXECUTORS_APPLIED };
@@ -66889,16 +67078,16 @@ function buildRouteRecord(i) {
66889
67078
  function writeRouteRecord(runDir, record) {
66890
67079
  try {
66891
67080
  mkdirSync45(runDir, { recursive: true });
66892
- writeFileSync43(join89(runDir, ROUTE_RECORD_FILE), `${JSON.stringify(record, null, 2)}
67081
+ writeFileSync43(join90(runDir, ROUTE_RECORD_FILE), `${JSON.stringify(record, null, 2)}
66893
67082
  `);
66894
67083
  } catch {}
66895
67084
  }
66896
67085
  function loadRouteRecord(runDir) {
66897
67086
  try {
66898
- const p = join89(runDir, ROUTE_RECORD_FILE);
67087
+ const p = join90(runDir, ROUTE_RECORD_FILE);
66899
67088
  if (!existsSync62(p) || !lstatSync25(p).isFile())
66900
67089
  return;
66901
- const v3 = JSON.parse(readFileSync80(p, "utf8"));
67090
+ const v3 = JSON.parse(readFileSync81(p, "utf8"));
66902
67091
  return typeof v3 === "object" && v3 !== null && !Array.isArray(v3) ? v3 : undefined;
66903
67092
  } catch {
66904
67093
  return;
@@ -66973,10 +67162,10 @@ __export(exports_plan, {
66973
67162
  planStage: () => planStage,
66974
67163
  buildPlanBrief: () => buildPlanBrief
66975
67164
  });
66976
- import { existsSync as existsSync63, mkdirSync as mkdirSync46, readFileSync as readFileSync81, writeFileSync as writeFileSync44 } from "fs";
66977
- import { join as join90 } from "path";
67165
+ import { existsSync as existsSync63, mkdirSync as mkdirSync46, readFileSync as readFileSync82, writeFileSync as writeFileSync44 } from "fs";
67166
+ import { join as join91 } from "path";
66978
67167
  function planOutputPath(runDir) {
66979
- return join90(runDir, PLAN_OUTPUT_FILENAME);
67168
+ return join91(runDir, PLAN_OUTPUT_FILENAME);
66980
67169
  }
66981
67170
  function truncatePlan(raw2, max = MAX_PLAN_LINES) {
66982
67171
  const lines2 = raw2.split(`
@@ -67046,7 +67235,7 @@ var init_plan = __esm(() => {
67046
67235
  const cardOn = intentCardEnabled(process.env);
67047
67236
  const runPlan = (onSonnet) => ctx.sessions.run({
67048
67237
  stage: "plan",
67049
- brief: buildPlanBrief(task, relevantFiles, outputPath, join90(ctx.runDir, PLAN_SCOPE_FILE), pr2.routed, cardOn, mutationStrict(), reviewerBriefEnabled()),
67238
+ brief: buildPlanBrief(task, relevantFiles, outputPath, join91(ctx.runDir, PLAN_SCOPE_FILE), pr2.routed, cardOn, mutationStrict(), reviewerBriefEnabled()),
67050
67239
  tier: "fast",
67051
67240
  iterationId,
67052
67241
  limitS: planStage.limitS,
@@ -67065,11 +67254,11 @@ var init_plan = __esm(() => {
67065
67254
  if (!session.killed && session.exit !== 0) {
67066
67255
  pr2.record({ planModel, planModelNote, skipReason: `plan session failed (exit ${session.exit})` });
67067
67256
  mkdirSync46(ctx.runDir, { recursive: true });
67068
- const stderrPath = join90(ctx.runDir, `${iterationId}.stderr.log`);
67257
+ const stderrPath = join91(ctx.runDir, `${iterationId}.stderr.log`);
67069
67258
  writeFileSync44(stderrPath, session.stderrTail ?? "", "utf8");
67070
67259
  return { status: "failed", reason: classifyExitCause(session.exit, false), data: { iteration_ids: [iterationId], duration_s: session.durationS, stderr_path: stderrPath } };
67071
67260
  }
67072
- const rawPlan = existsSync63(outputPath) ? readFileSync81(outputPath, "utf8") : "";
67261
+ const rawPlan = existsSync63(outputPath) ? readFileSync82(outputPath, "utf8") : "";
67073
67262
  const ic2 = await applyIntent(rawPlan, cardOn, ctx.runDir, (d) => ctx.emit("variant", "plan", d));
67074
67263
  const plan = truncatePlan(ic2.rest);
67075
67264
  const route_record = pr2.record({ planModel, planModelNote }), oor = planOutOfRepo(ctx.runDir);
@@ -67094,9 +67283,9 @@ var init_plan = __esm(() => {
67094
67283
 
67095
67284
  // ../../loki-ts/src/util/conflict_resume.ts
67096
67285
  import { createHash as createHash27 } from "crypto";
67097
- import { existsSync as existsSync64, mkdtempSync as mkdtempSync11, readFileSync as readFileSync82, rmSync as rmSync24, writeFileSync as writeFileSync45 } from "fs";
67286
+ import { existsSync as existsSync64, mkdtempSync as mkdtempSync11, readFileSync as readFileSync83, rmSync as rmSync24, writeFileSync as writeFileSync45 } from "fs";
67098
67287
  import { tmpdir as tmpdir14 } from "os";
67099
- import { basename as basename24, join as join91, relative as relative18 } from "path";
67288
+ import { basename as basename24, join as join92, relative as relative18 } from "path";
67100
67289
  async function resumeAfterConflict(ctx, first, firstSession) {
67101
67290
  if ((ctx.implementLeftS?.() ?? Infinity) < RESUME_MIN_LEFT_S)
67102
67291
  return { session: firstSession, iterationId: first.iterationId };
@@ -67120,9 +67309,9 @@ async function adjudicateWallConflict(ctx, first, firstSession, wall) {
67120
67309
  const reason = firstSession.markers.specConflict, rels = wall.map((f10) => relative18(ctx.repoDir, f10.path)), a = reason ? wallAnchor(reason, rels) : null;
67121
67310
  if (!reason || !a)
67122
67311
  return null;
67123
- const f = wall[rels.indexOf(a.file)], ids = [], o = ctx.outputs(), cwd = mkdtempSync11(join91(tmpdir14(), "loki-e15-wall-")), name = basename24(f.path);
67312
+ const f = wall[rels.indexOf(a.file)], ids = [], o = ctx.outputs(), cwd = mkdtempSync11(join92(tmpdir14(), "loki-e15-wall-")), name = basename24(f.path);
67124
67313
  try {
67125
- writeFileSync45(join91(cwd, name), f.content, "utf8");
67314
+ writeFileSync45(join92(cwd, name), f.content, "utf8");
67126
67315
  const id2 = `${first.iterationId}-wa`;
67127
67316
  ids.push(id2);
67128
67317
  const au2 = await ctx.sessions.run({
@@ -67142,7 +67331,7 @@ async function adjudicateWallConflict(ctx, first, firstSession, wall) {
67142
67331
 
67143
67332
  `)
67144
67333
  });
67145
- const next = !au2.killed && au2.exit === 0 && existsSync64(join91(cwd, name)) ? readFileSync82(join91(cwd, name), "utf8") : "";
67334
+ const next = !au2.killed && au2.exit === 0 && existsSync64(join92(cwd, name)) ? readFileSync83(join92(cwd, name), "utf8") : "";
67146
67335
  const rewritten = next.trim() !== "" && next !== f.content;
67147
67336
  if (rewritten) {
67148
67337
  f.content = next;
@@ -67237,8 +67426,8 @@ __export(exports_implement, {
67237
67426
  briefCtx: () => briefCtx,
67238
67427
  applyExternalPatch: () => applyExternalPatch
67239
67428
  });
67240
- import { existsSync as existsSync65, mkdirSync as mkdirSync47, readFileSync as readFileSync83, rmSync as rmSync25, writeFileSync as writeFileSync46 } from "fs";
67241
- import { join as join92, relative as relative19 } from "path";
67429
+ import { existsSync as existsSync65, mkdirSync as mkdirSync47, readFileSync as readFileSync84, rmSync as rmSync25, writeFileSync as writeFileSync46 } from "fs";
67430
+ import { join as join93, relative as relative19 } from "path";
67242
67431
  function impactedTests(ctx) {
67243
67432
  const o = ctx.outputs();
67244
67433
  const map = o.intake?.testmap;
@@ -67266,7 +67455,7 @@ ${plan}` : "No separate plan was made: plan the change yourself in this session,
67266
67455
  function restoreReadOnly(files) {
67267
67456
  const reverted = [];
67268
67457
  for (const f of files) {
67269
- const current = existsSync65(f.path) ? readFileSync83(f.path, "utf8") : null;
67458
+ const current = existsSync65(f.path) ? readFileSync84(f.path, "utf8") : null;
67270
67459
  if (current !== f.content) {
67271
67460
  writeFileSync46(f.path, f.content, "utf8");
67272
67461
  reverted.push(f.path);
@@ -67285,7 +67474,7 @@ function specFor(ctx) {
67285
67474
  if (!process.env.LOKI_E10_SPEC_SHA256)
67286
67475
  return null;
67287
67476
  try {
67288
- return loadSpecFile(join92(ctx.runDir, "spec.snapshot.md"));
67477
+ return loadSpecFile(join93(ctx.runDir, "spec.snapshot.md"));
67289
67478
  } catch {
67290
67479
  return null;
67291
67480
  }
@@ -67298,7 +67487,7 @@ function applyExternalPatch(ctx, patchPath) {
67298
67487
  `)[0]}` };
67299
67488
  }
67300
67489
  const testsReverted = restoreReadOnly(ctx.outputs().wall?.readOnlyFiles ?? []);
67301
- return { status: "completed", data: { exit: "external", external: true, patch_sha256: sha2562(readFileSync83(patchPath, "utf8")), tests_reverted: testsReverted, impacted_tests: impactedTests(ctx), iteration_ids: [] } };
67490
+ return { status: "completed", data: { exit: "external", external: true, patch_sha256: sha2562(readFileSync84(patchPath, "utf8")), tests_reverted: testsReverted, impacted_tests: impactedTests(ctx), iteration_ids: [] } };
67302
67491
  }
67303
67492
  var briefCtx = (ctx) => briefContext(ctx, { select: selectRelevantFiles, cmd: (t, repoDir) => {
67304
67493
  const c = commandFor(t, repoDir, loadProjectApi(repoDir));
@@ -67330,7 +67519,7 @@ var init_implement = __esm(() => {
67330
67519
  targetS: 180,
67331
67520
  limitS: 480,
67332
67521
  async run(ctx, signal) {
67333
- rmSync25(join92(ctx.repoDir, ".loki", "supply-declared.json"), { force: true });
67522
+ rmSync25(join93(ctx.repoDir, ".loki", "supply-declared.json"), { force: true });
67334
67523
  if (ctx.externalPatch)
67335
67524
  return applyExternalPatch(ctx, ctx.externalPatch);
67336
67525
  const prior = ctx.outputs();
@@ -67459,7 +67648,7 @@ var init_implement = __esm(() => {
67459
67648
  return { status: "completed", data };
67460
67649
  const stderrTail = session.stderrTail ?? "";
67461
67650
  mkdirSync47(ctx.runDir, { recursive: true });
67462
- const stderrPath = join92(ctx.runDir, `${iterationId}.stderr.log`);
67651
+ const stderrPath = join93(ctx.runDir, `${iterationId}.stderr.log`);
67463
67652
  writeFileSync46(stderrPath, stderrTail, "utf8");
67464
67653
  data.stderr_path = stderrPath;
67465
67654
  return { status: "failed", reason: classifyExitCause(session.exit, false), data };
@@ -67470,17 +67659,17 @@ var init_implement = __esm(() => {
67470
67659
 
67471
67660
  // ../../loki-ts/src/engine10/machine.ts
67472
67661
  import { existsSync as existsSync66, mkdirSync as mkdirSync48, rmSync as rmSync26, writeFileSync as writeFileSync47 } from "fs";
67473
- import { isAbsolute as isAbsolute17, join as join93, relative as relative20 } from "path";
67662
+ import { isAbsolute as isAbsolute17, join as join94, relative as relative20 } from "path";
67474
67663
  async function optional(path) {
67475
- const abs = isAbsolute17(path) ? path : join93(import.meta.dir, path);
67664
+ const abs = isAbsolute17(path) ? path : join94(import.meta.dir, path);
67476
67665
  if (!existsSync66(abs))
67477
67666
  return null;
67478
67667
  return await import(abs);
67479
67668
  }
67480
67669
  function defaultLoader(dir) {
67481
67670
  return async (name) => {
67482
- const reg = dir === join93(import.meta.dir, "stages") ? REGISTRY[`./stages/${name}.ts`] : undefined;
67483
- const mod = reg ? await reg() : await optional(join93(dir, `${name}.ts`));
67671
+ const reg = dir === join94(import.meta.dir, "stages") ? REGISTRY[`./stages/${name}.ts`] : undefined;
67672
+ const mod = reg ? await reg() : await optional(join94(dir, `${name}.ts`));
67484
67673
  return mod ? mod.stage ?? mod.default ?? null : null;
67485
67674
  };
67486
67675
  }
@@ -67489,7 +67678,7 @@ function softCapS(capS) {
67489
67678
  return Math.max(0, Math.min(plain2, budget));
67490
67679
  }
67491
67680
  async function runMachine(ctx, opts = {}) {
67492
- const load = opts.load ?? defaultLoader(opts.stagesDir ?? join93(import.meta.dir, "stages"));
67681
+ const load = opts.load ?? defaultLoader(opts.stagesDir ?? join94(import.meta.dir, "stages"));
67493
67682
  const outputs = {};
67494
67683
  let capHit = false, fatal = null;
67495
67684
  if (opts.restored)
@@ -67705,9 +67894,9 @@ ${timeBudgetNote(limitS)}`;
67705
67894
  else
67706
67895
  try {
67707
67896
  const w = a;
67708
- mkdirSync48(join93(base, relative20(ctx.repoDir, w.targetDir)), { recursive: true });
67897
+ mkdirSync48(join94(base, relative20(ctx.repoDir, w.targetDir)), { recursive: true });
67709
67898
  for (const [n10, c] of w.contents)
67710
- writeFileSync47(join93(base, relative20(ctx.repoDir, w.targetDir), n10), c, "utf8");
67899
+ writeFileSync47(join94(base, relative20(ctx.repoDir, w.targetDir), n10), c, "utf8");
67711
67900
  r = j10.split.install(sctx, a, base);
67712
67901
  const changed = hooks.wall.changedSinceBase(ctx.repoDir, ctx.baseSha);
67713
67902
  if (r.status === "completed") {
@@ -68014,8 +68203,8 @@ __export(exports_worker, {
68014
68203
  main: () => main2,
68015
68204
  assertWorkerEnv: () => assertWorkerEnv
68016
68205
  });
68017
- import { readFileSync as readFileSync84 } from "fs";
68018
- import { join as join94 } from "path";
68206
+ import { readFileSync as readFileSync85 } from "fs";
68207
+ import { join as join95 } from "path";
68019
68208
  function assertWorkerEnv(env = process.env) {
68020
68209
  if (env.LOKI_ALLOW_AGENT_GITHUB_TOKEN === "1")
68021
68210
  return;
@@ -68045,7 +68234,7 @@ async function main2(args) {
68045
68234
  return 2;
68046
68235
  }
68047
68236
  const repoDir = process.cwd();
68048
- const lokiRoot = join94(repoDir, ".loki");
68237
+ const lokiRoot = join95(repoDir, ".loki");
68049
68238
  const deep = mode === "deep";
68050
68239
  globalThis[Symbol.for("loki.ownsStopSignals")] = true;
68051
68240
  for (const sig of ["SIGTERM", "SIGINT"])
@@ -68073,7 +68262,7 @@ async function main2(args) {
68073
68262
  externalPatch,
68074
68263
  runId,
68075
68264
  repoDir,
68076
- runDir: join94(lokiRoot, "runs", runId),
68265
+ runDir: join95(lokiRoot, "runs", runId),
68077
68266
  branch: `loki/${runId}`,
68078
68267
  provider,
68079
68268
  model,
@@ -68087,7 +68276,7 @@ async function main2(args) {
68087
68276
  tests: new RealTestMapProvider,
68088
68277
  cost: {
68089
68278
  read(dir, ids) {
68090
- const c = sumResultCosts(join94(dir, ".loki"), liveArchivedCosts(join94(dir, ".loki"), ids, UNMETERED));
68279
+ const c = sumResultCosts(join95(dir, ".loki"), liveArchivedCosts(join95(dir, ".loki"), ids, UNMETERED));
68091
68280
  return costTotalsOf(c);
68092
68281
  }
68093
68282
  },
@@ -68097,7 +68286,7 @@ async function main2(args) {
68097
68286
  const resize = deep ? undefined : () => resizeCap(ctx.runDir, loadProjectApi(repoDir), !(Number(parseCapUsd(process.env.LOKI_E10_MAX_COST_USD)) > 0), Number(process.env.LOKI_E10_CAP_FIXED_S) || undefined);
68098
68287
  let flow = FLOW.filter((s) => s !== "pr"), restored;
68099
68288
  if (process.env.LOKI_E10_RESUME === "1") {
68100
- const p = join94(repoDir, eventsRelPath(runId)), r = (await Promise.resolve().then(() => (init_run_outputs(), exports_run_outputs))).resumeMachineOpts(ctx, readEvents(p), readFileSync84(p, "utf8"), flow);
68289
+ const p = join95(repoDir, eventsRelPath(runId)), r = (await Promise.resolve().then(() => (init_run_outputs(), exports_run_outputs))).resumeMachineOpts(ctx, readEvents(p), readFileSync85(p, "utf8"), flow);
68101
68290
  if (!r.ok) {
68102
68291
  emit("escalated", null, { stop: `resume refused: ${r.reason}` });
68103
68292
  return;
@@ -68145,12 +68334,12 @@ __export(exports_deep, {
68145
68334
  });
68146
68335
  import { existsSync as existsSync67, mkdirSync as mkdirSync49, mkdtempSync as mkdtempSync12, rmSync as rmSync27, writeFileSync as writeFileSync48 } from "fs";
68147
68336
  import { tmpdir as tmpdir15 } from "os";
68148
- import { join as join95 } from "path";
68337
+ import { join as join96 } from "path";
68149
68338
  function sessionCouncil(sessions) {
68150
68339
  return { async run(input, signal) {
68151
- const cwd = mkdtempSync12(join95(tmpdir15(), "loki-deep-council-"));
68340
+ const cwd = mkdtempSync12(join96(tmpdir15(), "loki-deep-council-"));
68152
68341
  try {
68153
- writeFileSync48(join95(cwd, "diff.patch"), input.diff, "utf8");
68342
+ writeFileSync48(join96(cwd, "diff.patch"), input.diff, "utf8");
68154
68343
  const r = await sessions.run({
68155
68344
  stage: "deep",
68156
68345
  tier: "development",
@@ -68220,7 +68409,7 @@ ${r.stderr}`), lr2 = r.exitCode === 0 ? undefined : await harnessLoadReason({ re
68220
68409
  async function runAppBoot(ctx, opts, checks, notProven) {
68221
68410
  let r;
68222
68411
  try {
68223
- r = await (opts.appProbe ?? appProbe)(ctx.repoDir, join95(ctx.repoDir, ".loki"));
68412
+ r = await (opts.appProbe ?? appProbe)(ctx.repoDir, join96(ctx.repoDir, ".loki"));
68224
68413
  } catch (err) {
68225
68414
  r = { checks: [{ name: "app boot", cmd: "autonomy/app-runner.sh", result: "not_run", duration_s: 0, reason: `app probe threw: ${err.message}` }], pid: null, url: null };
68226
68415
  }
@@ -68278,7 +68467,7 @@ async function runSecretScan(ctx, changed, opts, checks, notProven) {
68278
68467
  }
68279
68468
  const inline = 'script="$1"; shift; . "$script" || exit 3; hit=0; for f in "$@"; do if _commit_scan_secret_file "$f" || _commit_path_looks_secret "$f"; then printf "%s\\n" "$f"; hit=1; fi; done; exit "$hit"';
68280
68469
  const started = Date.now();
68281
- const r = await run(["bash", "-c", inline, "_", scriptPath, ...changed.map((f) => join95(ctx.repoDir, f))], { cwd: ctx.repoDir, timeoutMs: 30000 });
68470
+ const r = await run(["bash", "-c", inline, "_", scriptPath, ...changed.map((f) => join96(ctx.repoDir, f))], { cwd: ctx.repoDir, timeoutMs: 30000 });
68282
68471
  const sec = await secureScanChanged(ctx.repoDir, changed, opts.secureScanPath), gaps = [], reasons = [];
68283
68472
  const hits = r.exitCode === 3 ? [] : r.stdout.split(`
68284
68473
  `).map((l) => l.trim()).filter(Boolean), high = sec.findings.filter((f) => String(f.severity).toUpperCase() === "HIGH");
@@ -68331,7 +68520,7 @@ async function runDeep(ctx, signal, opts = {}) {
68331
68520
  const sig = signReceipt(`${ctx.runId}-deep`, addendumSha256);
68332
68521
  const addendum = { ...addendumBody, addendum_sha256: addendumSha256, verification: { jwt: sig.jwt, kid: sig.kid } };
68333
68522
  mkdirSync49(ctx.runDir, { recursive: true });
68334
- writeFileSync48(join95(ctx.runDir, "receipt-addendum-1.json"), JSON.stringify(addendum, null, 2) + `
68523
+ writeFileSync48(join96(ctx.runDir, "receipt-addendum-1.json"), JSON.stringify(addendum, null, 2) + `
68335
68524
  `);
68336
68525
  const headSha = (await safeGitRun(ctx.repoDir, ["rev-parse", "HEAD"], { timeoutMs: 1e4 })).stdout.trim();
68337
68526
  const pushNotProven = await postDeepResults({
@@ -68357,11 +68546,11 @@ async function deepWorker(args, deps = {}) {
68357
68546
  `);
68358
68547
  return 2;
68359
68548
  }
68360
- const repoDir = process.cwd(), lokiRoot = join95(repoDir, ".loki"), runDir = join95(lokiRoot, "runs", runId);
68549
+ const repoDir = process.cwd(), lokiRoot = join96(repoDir, ".loki"), runDir = join96(lokiRoot, "runs", runId);
68361
68550
  const { readEvents: readEvents2 } = await Promise.resolve().then(() => (init_events(), exports_events)), { eventsRelPath: eventsRelPath2 } = await Promise.resolve().then(() => (init_engine_origin(), exports_engine_origin)), { outputsFromEvents: outputsFromEvents2 } = await Promise.resolve().then(() => (init_run_outputs(), exports_run_outputs));
68362
68551
  let outputs;
68363
68552
  try {
68364
- outputs = outputsFromEvents2(readEvents2(join95(repoDir, eventsRelPath2(runId))));
68553
+ outputs = outputsFromEvents2(readEvents2(join96(repoDir, eventsRelPath2(runId))));
68365
68554
  } catch (err) {
68366
68555
  process.stderr.write(`engine10 deep-worker: cannot read run events: ${err.message}
68367
68556
  `);
@@ -68451,9 +68640,9 @@ __export(exports_verify, {
68451
68640
  commandFor: () => commandFor,
68452
68641
  changedFiles: () => changedFiles
68453
68642
  });
68454
- import { existsSync as existsSync68, mkdtempSync as mkdtempSync13, readFileSync as readFileSync85, rmSync as rmSync28 } from "fs";
68643
+ import { existsSync as existsSync68, mkdtempSync as mkdtempSync13, readFileSync as readFileSync86, rmSync as rmSync28 } from "fs";
68455
68644
  import { tmpdir as tmpdir16 } from "os";
68456
- import { basename as basename25, isAbsolute as isAbsolute18, join as join96, relative as relative21 } from "path";
68645
+ import { basename as basename25, isAbsolute as isAbsolute18, join as join97, relative as relative21 } from "path";
68457
68646
  async function runOnce3(cmd, args, cwd, signal, opts) {
68458
68647
  if (!Bun.which(cmd, { PATH: opts.path ?? process.env["PATH"] ?? "" }))
68459
68648
  return { ok: false, missing: true, cut: false, out: "" };
@@ -68535,7 +68724,7 @@ async function probeZeroChecks(repoDir, tests, signal, budgetS = 120, cap = 300)
68535
68724
  rmNewUntracked(repoDir, before);
68536
68725
  return { measured: measured.sort(), zero: zero.sort() };
68537
68726
  }
68538
- async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal, zeroOk = true, zeroIntake = new Set) {
68727
+ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal, zeroOk = true, zeroIntake = new Set, dep = new Set) {
68539
68728
  const out3 = { ids: [], names: [], weak: [], zero: [], cnt: {} };
68540
68729
  const pairs = checks.flatMap((c) => {
68541
68730
  const t = tests.find((x3) => testCheckName(x3) === c.name);
@@ -68546,7 +68735,7 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal,
68546
68735
  const zc2 = zeroOk ? un2.filter(({ c, t }) => c.result === "not_run" && !c.owner && (c.reason ?? "").startsWith(NO_TESTS_REASON) && !wall.has(c.name) && !isHoldoutCheck(c.name) && !changed.includes(t.path) && zeroIntake.has(c.name)) : [];
68547
68736
  if (!(un2.some(({ c }) => c.result === "fail" && c.ids?.length) || sus.length || zc2.length) || signal.aborted)
68548
68737
  return out3;
68549
- const dir = mkdtempSync13(join96(tmpdir16(), "e10-base-"));
68738
+ const dir = mkdtempSync13(join97(tmpdir16(), "e10-base-"));
68550
68739
  const git9 = (args) => {
68551
68740
  safeGit(ctx.repoDir, args, { stdio: "ignore", repoDrivers: true });
68552
68741
  };
@@ -68565,9 +68754,9 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal,
68565
68754
  out3.cnt[c.name] = { b: { run: base.get(c).n, skipped: base.get(c).sk }, h: { run: c.n ?? 0, skipped: c.sk ?? 0 } };
68566
68755
  }
68567
68756
  const progress = checks.some((c) => wall.has(c.name) && c.result === "pass") || sus.some(({ c }) => !out3.weak.includes(c.name) && base.get(c).red.length > 0 && (c.n ?? 0) >= base.get(c).n);
68568
- if (progress) {
68757
+ {
68569
68758
  for (const { c } of un2) {
68570
- if (!rel.has(c.name) && c.result === "fail" && c.ids?.length && c.ids.every((i) => base.get(c).red.includes(i))) {
68759
+ if ((progress || dep.has(c.name)) && !rel.has(c.name) && c.result === "fail" && c.ids?.length && c.ids.every((i) => base.get(c).red.includes(i))) {
68571
68760
  out3.names.push(c.name);
68572
68761
  out3.ids.push(...c.ids);
68573
68762
  }
@@ -68585,15 +68774,15 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal,
68585
68774
  return out3;
68586
68775
  }
68587
68776
  function isLokiModeRepo(repoDir) {
68588
- return existsSync68(join96(repoDir, "scripts", "select-tests.sh"));
68777
+ return existsSync68(join97(repoDir, "scripts", "select-tests.sh"));
68589
68778
  }
68590
68779
  function projectDeclaresRuff(repoDir) {
68591
- if (["ruff.toml", ".ruff.toml"].some((f) => existsSync68(join96(repoDir, f))))
68780
+ if (["ruff.toml", ".ruff.toml"].some((f) => existsSync68(join97(repoDir, f))))
68592
68781
  return true;
68593
68782
  const files = ["pyproject.toml", "setup.cfg", "tox.ini", ".pre-commit-config.yaml", "Pipfile", "requirements.txt", "requirements-dev.txt", "dev-requirements.txt"];
68594
68783
  return files.some((f) => {
68595
68784
  try {
68596
- return /\bruff\b/i.test(readFileSync85(join96(repoDir, f), "utf8"));
68785
+ return /\bruff\b/i.test(readFileSync86(join97(repoDir, f), "utf8"));
68597
68786
  } catch {
68598
68787
  return false;
68599
68788
  }
@@ -68619,9 +68808,9 @@ async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
68619
68808
  }
68620
68809
  for (const g of groupByPackage(api, ctx.repoDir, changed.filter((f) => /\.(ts|tsx|js|jsx)$/.test(f)))) {
68621
68810
  const sfx = g.root === "." ? "" : `:${g.root}`, co = g.root === "." ? opts : { ...opts, cwd: g.cwd };
68622
- if (existsSync68(join96(g.cwd, "tsconfig.json")))
68811
+ if (existsSync68(join97(g.cwd, "tsconfig.json")))
68623
68812
  await runCheck(ctx, `lint:tsc${sfx}`, "npx", ["--no-install", "tsc", "--noEmit", "-p", "."], signal, checks, { ...co, kind: "static" });
68624
- if (ESLINT_CONFIGS.some((f) => existsSync68(join96(g.cwd, f)))) {
68813
+ if (ESLINT_CONFIGS.some((f) => existsSync68(join97(g.cwd, f)))) {
68625
68814
  const c = await runCheck(ctx, `lint:eslint${sfx}`, "npx", ["--no-install", "eslint", ...g.rel], signal, checks, { ...co, kind: "static" });
68626
68815
  if (await excuseLint(ctx, signal, c, "eslint", "npx", ["--no-install", "eslint"], g.cwd, g.rel, co))
68627
68816
  pre2.push(c.name);
@@ -68636,7 +68825,7 @@ var CHECK_TIMEOUT_MS = 60000, excerpts, isHold = (c) => isHoldoutCheck(c.name),
68636
68825
  return r.missing || r.cut ? null : r;
68637
68826
  }, base: (f) => {
68638
68827
  try {
68639
- return safeGit(ctx.repoDir, ["show", `${ctx.baseSha}:${relative21(ctx.repoDir, join96(cwd, f))}`], { stdio: ["ignore", "pipe", "ignore"] });
68828
+ return safeGit(ctx.repoDir, ["show", `${ctx.baseSha}:${relative21(ctx.repoDir, join97(cwd, f))}`], { stdio: ["ignore", "pipe", "ignore"] });
68640
68829
  } catch {
68641
68830
  return null;
68642
68831
  }
@@ -68648,6 +68837,7 @@ var init_verify = __esm(() => {
68648
68837
  init_assert_delta();
68649
68838
  init_failures();
68650
68839
  init_select();
68840
+ init_dependents();
68651
68841
  init_load_owner();
68652
68842
  init_sizing();
68653
68843
  init_testmap();
@@ -68711,7 +68901,8 @@ var init_verify = __esm(() => {
68711
68901
  const runner = rec2 ?? guessRunner(basename25(p), map.runners, p);
68712
68902
  return runner && (runner !== "bun" || map.runners.includes("bun") || /[._](?:test|spec)\.[cm]?[jt]sx?$/.test(p)) ? [{ runner, path: p }] : [];
68713
68903
  });
68714
- const tests = failedFirst(dedupeTests([...impacted, ...changedTestFiles, ...wallTests, ...relevant2]), ctx.outputs().verify?.checks);
68904
+ const dep = dependentTests(ctx.repoDir, map, changed, [...impacted, ...changedTestFiles, ...wallTests, ...relevant2]), depNames = new Set(dep.tests.map(testCheckName));
68905
+ const tests = failedFirst(dedupeTests([...impacted, ...dep.tests, ...changedTestFiles, ...wallTests, ...relevant2]), ctx.outputs().verify?.checks);
68715
68906
  const scopedOut = scopedOutOf(map);
68716
68907
  if (scopedOut.length)
68717
68908
  ctx.emit("test.scoped_out", "verify", { tests: scopedOut });
@@ -68740,7 +68931,7 @@ var init_verify = __esm(() => {
68740
68931
  }
68741
68932
  const targetNames = new Set([...[...wallTests, ...relevant2].map(testCheckName), ...checks.filter(isHold).map((c) => c.name)]);
68742
68933
  const cfgChanged = testConfigChanged(ctx.repoDir, ctx.baseSha, changed);
68743
- const preRed = await subtractBase(ctx, api, checks, tests, changed, new Set(wallTests.map(testCheckName)), new Set(relevant2.map(testCheckName)), signal, cfgChanged.length === 0, new Set(ctx.outputs().intake?.zero_baseline?.zero ?? []));
68934
+ const preRed = await subtractBase(ctx, api, checks, tests, changed, new Set(wallTests.map(testCheckName)), new Set(relevant2.map(testCheckName)), signal, cfgChanged.length === 0, new Set(ctx.outputs().intake?.zero_baseline?.zero ?? []), depNames);
68744
68935
  const attr = attribute(ctx.repoDir, ctx.baseSha, checks.filter((c) => c.result === "fail" && !preRed.names.includes(c.name)).map((c) => ({ name: c.name, ids: c.ids, eligible: !targetNames.has(c.name) && !changed.includes(c.name.slice(c.name.indexOf(":") + 1)) })));
68745
68936
  attr.introducedChecks = [...new Set(attr.introducedChecks.map((n10) => isHoldoutCheck(n10) ? "holdout" : n10))];
68746
68937
  preRed.names.push(...attr.preExistingChecks);
@@ -68808,11 +68999,11 @@ ${x3}` : c.cmd };
68808
68999
  return [`weakened test: ${t.path}`, ...assertDeltaNotes(ctx.repoDir, ctx.baseSha, null, t.path, intake?.task ?? "", k3?.b, k3?.h) ?? []];
68809
69000
  });
68810
69001
  const weakened = [...modifiedRel, ...cfgChanged.map((f) => `test configuration changed: ${f}`), ...preRed.weak.map((n10) => `skipped or fewer tests than base: ${n10}`)];
68811
- const notProven = [...weakened, ...intake?.deps_not_proven ?? [], ...pub.filter((c) => c.name === "holdout" && c.result !== "pass").map((c) => c.result === "not_run" ? "holdout not executed" : "holdout check failed"), ...[...fullNotProven].filter((n10) => !naNote(n10)), ...pub.filter((c) => c.owner === "harness" && c.name !== "holdout").map((c) => `${c.reason} (${c.name}; harness-owned, no fix rounds)`), ...new Set(checks.filter((c) => c.interpreter === "system" && c.result !== "not_run").map((c) => c.name.startsWith("lint:") ? "lint ran on the system ruff" : "tests ran on the system interpreter"))];
69002
+ const notProven = [...weakened, ...dependentNotes(dep), ...intake?.deps_not_proven ?? [], ...pub.filter((c) => c.name === "holdout" && c.result !== "pass").map((c) => c.result === "not_run" ? "holdout not executed" : "holdout check failed"), ...[...fullNotProven].filter((n10) => !naNote(n10)), ...pub.filter((c) => c.owner === "harness" && c.name !== "holdout").map((c) => `${c.reason} (${c.name}; harness-owned, no fix rounds)`), ...new Set(checks.filter((c) => c.interpreter === "system" && c.result !== "not_run").map((c) => c.name.startsWith("lint:") ? "lint ran on the system ruff" : "tests ran on the system interpreter"))];
68812
69003
  const wallDropped2 = [...wallPaths].filter((p) => !wallTests.some((t) => t.path === p));
68813
69004
  notProven.push(...wallDropped2.map((p) => `Wall test not executed: ${p}: ${NO_RUNNER_REASON}`));
68814
69005
  const wallNames = new Set(wallTests.map(testCheckName)), wallRun = checks.filter((c) => wallNames.has(c.name) || isHold(c)), wallPassed = wallRun.some((c) => c.result === "fail") ? false : wallRun.length > 0 && wallDropped2.length === 0 && wallRun.every((c) => c.result === "pass") ? true : undefined;
68815
- return { status: "completed", data: { checks: pub, flaky, ...wallPassed === undefined ? {} : { wall_passed: wallPassed }, failures_grouped: failuresGrouped, holdout_failed: holdoutFailed, changed_files: changed, not_proven: notProven, ...fullNotProven.size ? { not_applicable: [...fullNotProven].filter(naNote).map(naText) } : {}, pre_red: preRed.ids, pre_red_checks: preRed.names, skipped_on_base: preRed.zero, ...attr.line ? { baseline_line: attr.line, introduced_checks: attr.introducedChecks } : {}, test_counts: testCounts, uncovered_changed: uncoveredChanged, target_checks: checks.filter((c) => c.result === "pass" && targetNames.has(c.name)).map((c) => isHold(c) ? "holdout" : c.name), risk } };
69006
+ return { status: "completed", data: { checks: pub, flaky, ...wallPassed === undefined ? {} : { wall_passed: wallPassed }, failures_grouped: failuresGrouped, holdout_failed: holdoutFailed, changed_files: changed, ...depNames.size ? { dependent_checks: [...depNames] } : {}, not_proven: notProven, ...fullNotProven.size ? { not_applicable: [...fullNotProven].filter(naNote).map(naText) } : {}, pre_red: preRed.ids, pre_red_checks: preRed.names, skipped_on_base: preRed.zero, ...attr.line ? { baseline_line: attr.line, introduced_checks: attr.introducedChecks } : {}, test_counts: testCounts, uncovered_changed: uncoveredChanged, target_checks: checks.filter((c) => c.result === "pass" && targetNames.has(c.name)).map((c) => isHold(c) ? "holdout" : c.name), risk } };
68816
69007
  }
68817
69008
  };
68818
69009
  stage5 = verifyStage;
@@ -68843,9 +69034,9 @@ __export(exports_wall, {
68843
69034
  BASE_RUN_TIMEOUT_MS: () => BASE_RUN_TIMEOUT_MS
68844
69035
  });
68845
69036
  import { spawnSync as spawnSync10 } from "child_process";
68846
- import { existsSync as existsSync69, mkdirSync as mkdirSync50, mkdtempSync as mkdtempSync14, readFileSync as readFileSync86, readdirSync as readdirSync28, rmSync as rmSync29, writeFileSync as writeFileSync49 } from "fs";
69037
+ import { existsSync as existsSync69, mkdirSync as mkdirSync50, mkdtempSync as mkdtempSync14, readFileSync as readFileSync87, readdirSync as readdirSync28, rmSync as rmSync29, writeFileSync as writeFileSync49 } from "fs";
68847
69038
  import { tmpdir as tmpdir17 } from "os";
68848
- import { dirname as dirname38, join as join97, relative as relative22 } from "path";
69039
+ import { dirname as dirname39, join as join98, relative as relative22 } from "path";
68849
69040
 
68850
69041
  class RealBaseTestRunner {
68851
69042
  api;
@@ -68911,10 +69102,10 @@ ${acceptance2.map((a) => `Acceptance: ${a}`).join(`
68911
69102
  function loadTaskText(ctx, fromPrior) {
68912
69103
  if (fromPrior)
68913
69104
  return fromPrior;
68914
- const issueJsonPath = process.env.LOKI_E10_ISSUE_JSON ?? join97(ctx.runDir, "issue.json");
69105
+ const issueJsonPath = process.env.LOKI_E10_ISSUE_JSON ?? join98(ctx.runDir, "issue.json");
68915
69106
  if (existsSync69(issueJsonPath)) {
68916
69107
  try {
68917
- const issue = JSON.parse(readFileSync86(issueJsonPath, "utf8"));
69108
+ const issue = JSON.parse(readFileSync87(issueJsonPath, "utf8"));
68918
69109
  const text3 = [issue.title, issue.body].filter((s) => typeof s === "string" && s.length > 0).join(`
68919
69110
 
68920
69111
  `);
@@ -68924,9 +69115,11 @@ function loadTaskText(ctx, fromPrior) {
68924
69115
  }
68925
69116
  return process.env.LOKI_E10_TASK_TEXT ?? "";
68926
69117
  }
68927
- function wallTargetDir(repoDir, existingTests) {
69118
+ function wallTargetDir(repoDir, existingTests, runners = []) {
68928
69119
  const first = existingTests[0];
68929
- return first ? join97(repoDir, dirname38(first.path)) : join97(repoDir, "tests");
69120
+ if (!first && runners.some((r) => r === "maven" || r === "gradle" || r === "javac"))
69121
+ return join98(repoDir, "src", "test", "java");
69122
+ return first ? join98(repoDir, dirname39(first.path)) : join98(repoDir, "tests");
68930
69123
  }
68931
69124
  async function wallAuthor(ctx, signal, retry) {
68932
69125
  const done = (result) => ({ kind: "done", result });
@@ -68945,18 +69138,20 @@ async function wallAuthor(ctx, signal, retry) {
68945
69138
  if (!ctx.externalPatch && planMode() !== "always" && smallTaskPath(sz2.size, hasRelevantTests(task, repoMap, testMap, ctx.tests.impacted)) === "lean") {
68946
69139
  return done({ status: "skipped", data: { size: sz2.size }, reason: "small task with a relevant test: cascade skips Wall" });
68947
69140
  }
68948
- if (testMap && runners.length === 0)
68949
- return done({ status: "skipped", data: { size: sz2.size, files: [], no_runner: true, skip_code: harnessSkipCode(), not_proven: ["Wall skipped: no runnable test command for this stack"] }, reason: "no runnable test command detected: the Wall cannot write a runnable check" });
69141
+ if (testMap && runners.length === 0) {
69142
+ const miss = missingJavaTool(repoMap?.files ?? [], process.env, ctx.repoDir);
69143
+ return done({ status: "skipped", data: { size: sz2.size, files: [], no_runner: true, skip_code: harnessSkipCode(), not_proven: [miss ? `Wall not run: ${miss} is not installed on this machine, so this Java repo could not be tested (harness-owned)` : "Wall skipped: no runnable test command for this stack"] }, reason: miss ? `${miss} is not installed: the Wall cannot run Java tests (harness-owned, not proven)` : "no runnable test command detected: the Wall cannot write a runnable check" });
69144
+ }
68950
69145
  if (testMap && runners.every((r) => r === "pytest") && projectInterpreter(ctx.repoDir) === "system" && wallHoldoutRatio() === 0)
68951
69146
  return done({ status: "skipped", data: { size: sz2.size, files: [], no_interpreter: true, not_proven: ["Wall skipped: no project test interpreter"] }, reason: "Wall skipped: no project test interpreter" });
68952
69147
  const tree = prior.intake?.tree;
68953
69148
  const repomapText = repoMapText(ctx.repoDir, tree, repomapRef, WALL_MAP_MAX_LINES);
68954
- const targetDir = wallTargetDir(ctx.repoDir, existingTests), pkg = loadProjectApi(ctx.repoDir)?.packageOf(`${relative22(ctx.repoDir, targetDir)}/x`);
68955
- const conv2 = readPackageConventions(join97(ctx.repoDir, pkg?.root ?? "."), pkg?.runner ?? null);
68956
- const cwd = mkdtempSync14(join97(tmpdir17(), "loki-e15-wall-"));
69149
+ const targetDir = wallTargetDir(ctx.repoDir, existingTests, runners), pkg = loadProjectApi(ctx.repoDir)?.packageOf(`${relative22(ctx.repoDir, targetDir)}/x`);
69150
+ const conv2 = readPackageConventions(join98(ctx.repoDir, pkg?.root ?? "."), pkg?.runner ?? null);
69151
+ const cwd = mkdtempSync14(join98(tmpdir17(), "loki-e15-wall-"));
68957
69152
  const wm2 = wallManifestFor(ctx.repoDir, tree, task);
68958
69153
  for (const [n10, c] of [["task.md", task], ["repomap.txt", repomapText], ...wm2 ? [["wall_manifest.txt", wm2.text]] : []])
68959
- writeFileSync49(join97(cwd, n10), c, "utf8");
69154
+ writeFileSync49(join98(cwd, n10), c, "utf8");
68960
69155
  const clauseSet = extractClauses(task);
68961
69156
  const model = retry?.model ?? wallFirstModel(sz2.size), iterationId = `${ctx.runId}-wall${retry?.suffix ?? ""}`;
68962
69157
  const session = await ctx.sessions.run({
@@ -68975,21 +69170,21 @@ async function wallAuthor(ctx, signal, retry) {
68975
69170
  }
68976
69171
  const planText = typeof prior.plan?.plan === "string" ? prior.plan.plan : null, repoFiles = repoMap?.files ?? [];
68977
69172
  const oor = () => readdirSync28(cwd).filter((f) => f.startsWith(WALL_PREFIX)).flatMap((name) => {
68978
- const text3 = readFileSync86(join97(cwd, name), "utf8"), why = outOfRepoTarget(text3) ?? vacuousCheck(name, text3) ?? phantomReason(phantomRepoPaths(text3, name, targetDir, ctx.repoDir, planText), repoFiles, relative22(ctx.repoDir, targetDir), pkg?.root ?? "");
69173
+ const text3 = readFileSync87(join98(cwd, name), "utf8"), why = outOfRepoTarget(text3) ?? vacuousCheck(name, text3) ?? phantomReason(phantomRepoPaths(text3, name, targetDir, ctx.repoDir, planText), repoFiles, relative22(ctx.repoDir, targetDir), pkg?.root ?? "");
68979
69174
  return why ? [{ name, why }] : [];
68980
69175
  });
68981
69176
  const bad1 = oor();
68982
69177
  if (bad1.length > 0 && !signal.aborted && !ctx.overCap?.())
68983
69178
  await ctx.sessions.run({ stage: "wall", brief: withStagePrefix(outOfRepoReask("Rewrite these Wall files in place, keeping the same names and acceptance coverage.", bad1)), tier: "development", model, iterationId: `${iterationId}-oor`, limitS: wallLimitS(sz2.size), signal, cwd });
68984
- const oorBad = new Map(oor().map((b) => [b.name, b.why])), all = readdirSync28(cwd).filter((f) => f.startsWith(WALL_PREFIX)), held = stashHoldout({ runId: ctx.runId, repoDir: ctx.repoDir, srcDir: cwd, targetDir, names: all.filter((n10) => !oorBad.has(n10) && !conventionViolation(conv2, n10, readFileSync86(join97(cwd, n10), "utf8"))), runnerOf: (n10) => guessRunner(n10, runners) }), generated = all.filter((n10) => !held?.names.has(n10));
68985
- const sealedDir = join97(ctx.runDir, "wall");
69179
+ const oorBad = new Map(oor().map((b) => [b.name, b.why])), all = readdirSync28(cwd).filter((f) => f.startsWith(WALL_PREFIX)), held = stashHoldout({ runId: ctx.runId, repoDir: ctx.repoDir, srcDir: cwd, targetDir, names: all.filter((n10) => !oorBad.has(n10) && !conventionViolation(conv2, n10, readFileSync87(join98(cwd, n10), "utf8"))), runnerOf: (n10) => guessRunner(n10, runners) }), generated = all.filter((n10) => !held?.names.has(n10));
69180
+ const sealedDir = join98(ctx.runDir, "wall");
68986
69181
  if (generated.length > 0)
68987
69182
  mkdirSync50(sealedDir, { recursive: true });
68988
69183
  const contents = new Map;
68989
69184
  const discarded = [];
68990
69185
  for (const name of generated) {
68991
- const content = readFileSync86(join97(cwd, name), "utf8"), oorWhy = oorBad.get(name), bad = oorWhy ?? conventionViolation(conv2, name, content);
68992
- writeFileSync49(join97(sealedDir, name), content, "utf8");
69186
+ const content = readFileSync87(join98(cwd, name), "utf8"), oorWhy = oorBad.get(name), bad = oorWhy ?? conventionViolation(conv2, name, content);
69187
+ writeFileSync49(join98(sealedDir, name), content, "utf8");
68993
69188
  if (oorWhy)
68994
69189
  discarded.push({ file: name, reason: `${oorWhy}; wall test discarded after one rewrite request` });
68995
69190
  else if (bad)
@@ -69018,7 +69213,7 @@ function* installCore(ctx, a, baseDir, opts) {
69018
69213
  const content = contents.get(name);
69019
69214
  if (content === undefined)
69020
69215
  continue;
69021
- const dest = join97(targetDir, name), runner = guessRunner(name, runners, relative22(ctx.repoDir, dest));
69216
+ const dest = join98(targetDir, name), runner = guessRunner(name, runners, relative22(ctx.repoDir, dest));
69022
69217
  writeFileSync49(dest, content, "utf8");
69023
69218
  sealedFiles.push({ path: dest, sha256: sha2562(content), ...runner ? { runner } : {} });
69024
69219
  readOnlyFiles.push({ path: dest, content });
@@ -69035,7 +69230,7 @@ function* installCore(ctx, a, baseDir, opts) {
69035
69230
  }
69036
69231
  const each = yield { runner: baseRunner, tests: wallTests };
69037
69232
  for (const [i, t] of wallTests.entries()) {
69038
- const e10 = each?.[i], r = e10 ?? baseRunner.run(baseDir, [t]), abs = join97(ctx.repoDir, t.path);
69233
+ const e10 = each?.[i], r = e10 ?? baseRunner.run(baseDir, [t]), abs = join98(ctx.repoDir, t.path);
69039
69234
  baseRun.pass += r.pass;
69040
69235
  baseRun.fail += r.fail;
69041
69236
  baseRun.not_run += r.not_run ?? 0;
@@ -69078,7 +69273,7 @@ async function runWall(ctx, signal, opts = {}) {
69078
69273
  if (a.kind === "authored") {
69079
69274
  for (const f of first.data.files ?? [])
69080
69275
  rmSync29(f.path, { force: true });
69081
- rmSync29(join97(ctx.runDir, "wall"), { recursive: true, force: true });
69276
+ rmSync29(join98(ctx.runDir, "wall"), { recursive: true, force: true });
69082
69277
  ctx.wallSealed = false;
69083
69278
  }
69084
69279
  removeHoldout(ctx.runId, ctx.repoDir);
@@ -69118,15 +69313,15 @@ var init_wall = __esm(() => {
69118
69313
  });
69119
69314
 
69120
69315
  // ../../loki-ts/src/e10ext/discard.ts
69121
- import { chmodSync as chmodSync6, closeSync as closeSync14, lstatSync as lstatSync26, mkdirSync as mkdirSync51, openSync as openSync14, readFileSync as readFileSync87, realpathSync as realpathSync29, rmdirSync, unlinkSync as unlinkSync9, writeFileSync as writeFileSync50 } from "fs";
69122
- import { dirname as dirname39, join as join98, relative as relative23, sep as sep19 } from "path";
69316
+ import { chmodSync as chmodSync6, closeSync as closeSync14, lstatSync as lstatSync26, mkdirSync as mkdirSync51, openSync as openSync14, readFileSync as readFileSync88, realpathSync as realpathSync29, rmdirSync, unlinkSync as unlinkSync9, writeFileSync as writeFileSync50 } from "fs";
69317
+ import { dirname as dirname40, join as join99, relative as relative23, sep as sep19 } from "path";
69123
69318
  function safeRestore(repoDir, f, want, mode) {
69124
- const root = realpathSync29(repoDir), fp2 = join98(root, f), rel = relative23(root, dirname39(fp2));
69319
+ const root = realpathSync29(repoDir), fp2 = join99(root, f), rel = relative23(root, dirname40(fp2));
69125
69320
  if (rel.startsWith(".."))
69126
69321
  throw new Error("outside repo");
69127
69322
  let cur = root;
69128
69323
  for (const part of rel === "" ? [] : rel.split(sep19)) {
69129
- cur = join98(cur, part);
69324
+ cur = join99(cur, part);
69130
69325
  let st3;
69131
69326
  try {
69132
69327
  st3 = lstatSync26(cur);
@@ -69143,7 +69338,7 @@ function safeRestore(repoDir, f, want, mode) {
69143
69338
  } catch {
69144
69339
  st2 = null;
69145
69340
  }
69146
- if (st2?.isFile() && readFileSync87(fp2).equals(want)) {
69341
+ if (st2?.isFile() && readFileSync88(fp2).equals(want)) {
69147
69342
  chmodSync6(fp2, mode);
69148
69343
  return;
69149
69344
  }
@@ -69180,7 +69375,7 @@ async function discardIfSatisfied(git9, base, o, staged, keep, repoDir) {
69180
69375
  return { status: "failed", data: {}, reason: "already-satisfied discard failed" };
69181
69376
  const notProven = [];
69182
69377
  for (const [f, v3] of Object.entries(o.intake?.preexisting_untracked_blobs ?? {})) {
69183
- const fp2 = join98(repoDir, f);
69378
+ const fp2 = join99(repoDir, f);
69184
69379
  try {
69185
69380
  if (v3.startsWith("!")) {
69186
69381
  const st2 = lstatSync26(fp2);
@@ -69199,7 +69394,7 @@ async function discardIfSatisfied(git9, base, o, staged, keep, repoDir) {
69199
69394
  try {
69200
69395
  let m = 420;
69201
69396
  try {
69202
- const l = lstatSync26(join98(repoDir, f));
69397
+ const l = lstatSync26(join99(repoDir, f));
69203
69398
  if (l.isFile())
69204
69399
  m = l.mode & 511;
69205
69400
  } catch {}
@@ -69215,7 +69410,7 @@ var init_discard = __esm(() => {
69215
69410
  });
69216
69411
 
69217
69412
  // ../../loki-ts/src/e10ext/scope.ts
69218
- import { basename as basename26, dirname as dirname40 } from "path";
69413
+ import { basename as basename26, dirname as dirname41 } from "path";
69219
69414
  function contractText(o) {
69220
69415
  const c = o.intake?.contract_snapshot?.contract;
69221
69416
  return Array.isArray(c?.criteria) ? c.criteria.map((x3) => typeof x3?.text === "string" ? x3.text : "").join(`
@@ -69229,8 +69424,8 @@ function outsideScope(o, staged) {
69229
69424
  const text3 = `${plan}
69230
69425
  ${typeof o.intake?.task === "string" ? o.intake.task : ""}
69231
69426
  ${contractText(o)}`, pre2 = o.intake?.preexisting_dirty ?? {};
69232
- const toks = surfaceTokens(text3), plannedDirs = new Set(rel.map((r) => dirname40(r)).filter((d) => d !== "."));
69233
- return staged.filter(({ st: st2, f }) => st2 !== "A" && !isTestFile(f) && !Object.hasOwn(pre2, f) && !rel.includes(f) && !mentions(text3, f) && !mentions(text3, basename26(f)) && !plannedDirs.has(dirname40(f)) && !dirSegs(f).some((d) => toks.has(d))).map(({ f }) => f);
69427
+ const toks = surfaceTokens(text3), plannedDirs = new Set(rel.map((r) => dirname41(r)).filter((d) => d !== "."));
69428
+ return staged.filter(({ st: st2, f }) => st2 !== "A" && !isTestFile(f) && !Object.hasOwn(pre2, f) && !rel.includes(f) && !mentions(text3, f) && !mentions(text3, basename26(f)) && !plannedDirs.has(dirname41(f)) && !dirSegs(f).some((d) => toks.has(d))).map(({ f }) => f);
69234
69429
  }
69235
69430
  function flagOutsideScope(o, staged) {
69236
69431
  const unit = unitFlags(staged, process.env, o.intake?.preexisting_dirty ?? {});
@@ -69245,14 +69440,14 @@ var init_scope2 = __esm(() => {
69245
69440
  });
69246
69441
 
69247
69442
  // ../../loki-ts/src/council/role_agents.ts
69248
- import { existsSync as existsSync70, readdirSync as readdirSync29, readFileSync as readFileSync88 } from "fs";
69443
+ import { existsSync as existsSync70, readdirSync as readdirSync29, readFileSync as readFileSync89 } from "fs";
69249
69444
  import { homedir as homedir11 } from "os";
69250
- import { join as join99 } from "path";
69445
+ import { join as join100 } from "path";
69251
69446
  function agentDirs(repoDir, env = process.env) {
69252
- return [env["LOKI_AGENTS_PROJECT_DIR"] || join99(repoDir, ".loki", "agents"), env["LOKI_AGENTS_USER_DIR"] || join99(env["XDG_CONFIG_HOME"] || join99(homedir11(), ".config"), "loki", "agents")];
69447
+ return [env["LOKI_AGENTS_PROJECT_DIR"] || join100(repoDir, ".loki", "agents"), env["LOKI_AGENTS_USER_DIR"] || join100(env["XDG_CONFIG_HOME"] || join100(homedir11(), ".config"), "loki", "agents")];
69253
69448
  }
69254
69449
  function parseAgent(file, stem2) {
69255
- const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(readFileSync88(file, "utf8"));
69450
+ const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(readFileSync89(file, "utf8"));
69256
69451
  if (!m)
69257
69452
  return null;
69258
69453
  const body = m[2].trim();
@@ -69277,7 +69472,7 @@ function loadRoleAgent(repoDir, role, env = process.env) {
69277
69472
  const ordered = [...names.filter((n10) => n10 === `${role}.md`), ...names.filter((n10) => n10 !== `${role}.md`)];
69278
69473
  for (const n10 of ordered) {
69279
69474
  try {
69280
- const a = parseAgent(join99(d, n10), n10.slice(0, -3));
69475
+ const a = parseAgent(join100(d, n10), n10.slice(0, -3));
69281
69476
  if (a && a.role === role)
69282
69477
  return a;
69283
69478
  } catch {}
@@ -69296,11 +69491,11 @@ function explicitReview(repoDir, env) {
69296
69491
  if (flag && isOff(ev2))
69297
69492
  return "off";
69298
69493
  for (const f of ["loki.yaml", "loki.yml"]) {
69299
- const p = join99(repoDir, f);
69494
+ const p = join100(repoDir, f);
69300
69495
  if (!existsSync70(p))
69301
69496
  continue;
69302
69497
  try {
69303
- const m = /^review:[ \t]*["']?([A-Za-z]+)["']?[ \t]*(?:#.*)?$/m.exec(readFileSync88(p, "utf8"));
69498
+ const m = /^review:[ \t]*["']?([A-Za-z]+)["']?[ \t]*(?:#.*)?$/m.exec(readFileSync89(p, "utf8"));
69304
69499
  const v3 = asProvider(m?.[1]);
69305
69500
  if (v3)
69306
69501
  return v3;
@@ -69333,7 +69528,7 @@ var init_role_agents = __esm(() => {
69333
69528
 
69334
69529
  // ../../loki-ts/src/util/child_ledger.ts
69335
69530
  import { appendFileSync as appendFileSync10, mkdirSync as mkdirSync52 } from "fs";
69336
- import { join as join100 } from "path";
69531
+ import { join as join101 } from "path";
69337
69532
  function unmeasuredRecord(phase, model, source) {
69338
69533
  return { phase, model, input_tokens: 0, output_tokens: 0, cache_creation_tokens: 0, cache_read_tokens: 0, source, cost_status: "unmeasured" };
69339
69534
  }
@@ -69358,9 +69553,9 @@ function recordFromClaudeResult(phase, payload, source = "claude-json") {
69358
69553
  }
69359
69554
  function appendChildLedger(lokiDir2, rec2) {
69360
69555
  try {
69361
- const dir = join100(lokiDir2, "metrics");
69556
+ const dir = join101(lokiDir2, "metrics");
69362
69557
  mkdirSync52(dir, { recursive: true });
69363
- appendFileSync10(join100(dir, "child-sessions.jsonl"), `${JSON.stringify(rec2)}
69558
+ appendFileSync10(join101(dir, "child-sessions.jsonl"), `${JSON.stringify(rec2)}
69364
69559
  `);
69365
69560
  return true;
69366
69561
  } catch {
@@ -69390,7 +69585,7 @@ var init_child_ledger = __esm(() => {
69390
69585
  });
69391
69586
 
69392
69587
  // ../../loki-ts/src/engine10/stages/xreview.ts
69393
- import { join as join101 } from "path";
69588
+ import { join as join102 } from "path";
69394
69589
  function minVerdict(verdict, review) {
69395
69590
  const ceiling = review?.level === "block" ? "PARTIAL" : verdict;
69396
69591
  return RANK4[ceiling] < RANK4[verdict] ? ceiling : verdict;
@@ -69488,9 +69683,9 @@ Review ONLY the diff below. Do not modify files.` : "You are an independent code
69488
69683
  try {
69489
69684
  if (p === "claude")
69490
69685
  await ensureClaudeHelpCache();
69491
- const r = await withChildLedger(run, join101(ctx.repoDir, ".loki"), "xreview")(reviewArgv(p, prompt, process.env, p === "claude" ? agent?.model || pin : undefined), { cwd: ctx.repoDir, timeoutMs: boxFor(ctx) * 1000, group: true, signal });
69686
+ const r = await withChildLedger(run, join102(ctx.repoDir, ".loki"), "xreview")(reviewArgv(p, prompt, process.env, p === "claude" ? agent?.model || pin : undefined), { cwd: ctx.repoDir, timeoutMs: boxFor(ctx) * 1000, group: true, signal });
69492
69687
  const costId = `${ctx.runId}-xreview-${p}`;
69493
- writeReviewerCost(join101(ctx.repoDir, ".loki"), costId, { reviewer: `xreview-${p}`, provider: p, model: p === "claude" ? agent?.model || pin : undefined, stdout: r.stdout, stderr: r.stderr });
69688
+ writeReviewerCost(join102(ctx.repoDir, ".loki"), costId, { reviewer: `xreview-${p}`, provider: p, model: p === "claude" ? agent?.model || pin : undefined, stdout: r.stdout, stderr: r.stderr });
69494
69689
  if (r.exitCode !== 0)
69495
69690
  return { ...tag({ provider: p, level: "not_run", notes: [`cross-review not run: ${p} exited ${r.exitCode}`] }), cost_iteration: costId };
69496
69691
  return { ...tag(parseReview(p, r.stdout)), cost_iteration: costId };
@@ -69671,9 +69866,9 @@ __export(exports_contract, {
69671
69866
  MAX_CONTRACT_BYTES: () => MAX_CONTRACT_BYTES,
69672
69867
  CONSTRAINT_KINDS: () => CONSTRAINT_KINDS
69673
69868
  });
69674
- import { existsSync as existsSync71, lstatSync as lstatSync27, mkdirSync as mkdirSync53, readFileSync as readFileSync89, rmSync as rmSync30, writeFileSync as writeFileSync51 } from "fs";
69869
+ import { existsSync as existsSync71, lstatSync as lstatSync27, mkdirSync as mkdirSync53, readFileSync as readFileSync90, rmSync as rmSync30, writeFileSync as writeFileSync51 } from "fs";
69675
69870
  import { spawnSync as spawnSync11 } from "child_process";
69676
- import { dirname as dirname41, join as join102 } from "path";
69871
+ import { dirname as dirname42, join as join103 } from "path";
69677
69872
  import { createHash as createHash28 } from "crypto";
69678
69873
  function contractEnabled(env = process.env) {
69679
69874
  return env["LOKI_CONTRACT"] !== "0";
@@ -69740,7 +69935,7 @@ function assignCriteria(units, criteria2) {
69740
69935
  return { units: out3, orphans: criteria2.filter((c) => !owned.has(c.id)) };
69741
69936
  }
69742
69937
  function groupContractPath(repoDir, groupId) {
69743
- return join102(repoDir, ".loki", "groups", groupId.replace(/[^A-Za-z0-9._-]/g, "_"), "contract.json");
69938
+ return join103(repoDir, ".loki", "groups", groupId.replace(/[^A-Za-z0-9._-]/g, "_"), "contract.json");
69744
69939
  }
69745
69940
  function freezeGroupContract(repoDir, groupId, units, contract) {
69746
69941
  const a = assignCriteria(units, contract.criteria);
@@ -69748,7 +69943,7 @@ function freezeGroupContract(repoDir, groupId, units, contract) {
69748
69943
  return { ok: false, reason: `NOT PROVEN: group contract has ${a.orphans.length} criterion owned by no unit: ${a.orphans.map((o) => `${sanitizeCriterion(o.id)} ${sanitizeCriterion(o.text)}`).join("; ")}`, orphans: a.orphans };
69749
69944
  const gc2 = { group: groupId, units: a.units, orphans: [] };
69750
69945
  const path = groupContractPath(repoDir, groupId);
69751
- mkdirSync53(dirname41(path), { recursive: true });
69946
+ mkdirSync53(dirname42(path), { recursive: true });
69752
69947
  atomicWriteJson(path, gc2);
69753
69948
  return { ok: true, path, contract: gc2 };
69754
69949
  }
@@ -69805,7 +70000,7 @@ function untracedLines(trace) {
69805
70000
  return trace.criteria.filter((c) => c.status === "no_match").map((c) => `contract ${sanitizeCriterion(c.id)} untraced (no keyword match in changed files): ${sanitizeCriterion(c.text)}`);
69806
70001
  }
69807
70002
  function contractPath(repoDir) {
69808
- return join102(repoDir, ".loki", "contract.json");
70003
+ return join103(repoDir, ".loki", "contract.json");
69809
70004
  }
69810
70005
  function readContract(repoDir) {
69811
70006
  const p = contractPath(repoDir);
@@ -69821,7 +70016,7 @@ function readContract(repoDir) {
69821
70016
  return { contract: null, notes: ["contract unreadable: too large"], sha256: null };
69822
70017
  let raw2;
69823
70018
  try {
69824
- raw2 = readFileSync89(p);
70019
+ raw2 = readFileSync90(p);
69825
70020
  } catch {
69826
70021
  return { contract: null, notes: ["contract unreadable: read failed"], sha256: null };
69827
70022
  }
@@ -69893,9 +70088,9 @@ function main3(args) {
69893
70088
  `);
69894
70089
  return 2;
69895
70090
  }
69896
- const contract = parseContract(readFileSync89(file, "utf8"), file);
70091
+ const contract = parseContract(readFileSync90(file, "utf8"), file);
69897
70092
  const out3 = contractPath(repoRoot(process.cwd()));
69898
- mkdirSync53(dirname41(out3), { recursive: true });
70093
+ mkdirSync53(dirname42(out3), { recursive: true });
69899
70094
  writeFileSync51(out3, JSON.stringify(contract, null, 2) + `
69900
70095
  `);
69901
70096
  process.stdout.write(renderContract(contract));
@@ -69952,7 +70147,7 @@ function fromSpecText(raw2) {
69952
70147
  }
69953
70148
  }
69954
70149
  function fromPrdText(text3, python = "python3") {
69955
- const script = join102(REPO_ROOT, "autonomy", "lib", "requirements_contract.py");
70150
+ const script = join103(REPO_ROOT, "autonomy", "lib", "requirements_contract.py");
69956
70151
  if (!existsSync71(script))
69957
70152
  return null;
69958
70153
  const code = `import sys,json,importlib.util as u
@@ -69995,12 +70190,12 @@ function mapRequirements(reqs, ran2, revision) {
69995
70190
  return { version: 1, revision, requirements: out3 };
69996
70191
  }
69997
70192
  function fromChecklist(lokiDir2) {
69998
- const p = join102(lokiDir2, "checklist", "checklist.json");
70193
+ const p = join103(lokiDir2, "checklist", "checklist.json");
69999
70194
  if (!existsSync71(p))
70000
70195
  return null;
70001
70196
  let doc;
70002
70197
  try {
70003
- doc = JSON.parse(readFileSync89(p, "utf8"));
70198
+ doc = JSON.parse(readFileSync90(p, "utf8"));
70004
70199
  } catch {
70005
70200
  return null;
70006
70201
  }
@@ -70032,7 +70227,7 @@ function writeRequirementsMap(repoDir, lokiDir2, reqs, ran2) {
70032
70227
  if (!reqs || reqs.length === 0)
70033
70228
  return null;
70034
70229
  const m = mapRequirements(reqs, ran2, currentRevision(repoDir));
70035
- atomicWriteJson(join102(lokiDir2, "state", "requirements-map.json"), m);
70230
+ atomicWriteJson(join103(lokiDir2, "state", "requirements-map.json"), m);
70036
70231
  return m;
70037
70232
  } catch {
70038
70233
  return null;
@@ -70044,17 +70239,17 @@ function writeFromChecklist(repoDir, lokiDir2) {
70044
70239
  }
70045
70240
  function writeFromEngine10(repoDir, lokiDir2, runDir, task, events2) {
70046
70241
  let reqs = null;
70047
- const snap = join102(runDir, "spec.snapshot.md");
70242
+ const snap = join103(runDir, "spec.snapshot.md");
70048
70243
  if (existsSync71(snap)) {
70049
70244
  try {
70050
- reqs = fromSpecText(readFileSync89(snap, "utf8"));
70245
+ reqs = fromSpecText(readFileSync90(snap, "utf8"));
70051
70246
  } catch {
70052
70247
  reqs = null;
70053
70248
  }
70054
70249
  }
70055
70250
  if (!reqs && task)
70056
70251
  reqs = fromPrdText(task);
70057
- const mapPath = join102(lokiDir2, "state", "requirements-map.json");
70252
+ const mapPath = join103(lokiDir2, "state", "requirements-map.json");
70058
70253
  if (!reqs || reqs.length === 0) {
70059
70254
  try {
70060
70255
  rmSync30(mapPath, { force: true });
@@ -70080,7 +70275,7 @@ function uncoveredCount(m) {
70080
70275
  }
70081
70276
  function readRequirementsMap(lokiDir2) {
70082
70277
  try {
70083
- const m = JSON.parse(readFileSync89(join102(lokiDir2, "state", "requirements-map.json"), "utf8"));
70278
+ const m = JSON.parse(readFileSync90(join103(lokiDir2, "state", "requirements-map.json"), "utf8"));
70084
70279
  return m.version === 1 && Array.isArray(m.requirements) ? m : null;
70085
70280
  } catch {
70086
70281
  return null;
@@ -70108,17 +70303,17 @@ var init_contract = __esm(() => {
70108
70303
  BULLET = /^\s*(?:[-*+]|\d+[.)])\s+(.+)$/;
70109
70304
  STOP3 = new Set(["the", "and", "for", "with", "that", "this", "must", "should", "shall", "when", "then", "are", "was", "all", "any", "can", "not", "has", "have", "from", "into", "each", "user", "users"]);
70110
70305
  MAX_CONTRACT_BYTES = 1024 * 1024;
70111
- REQ_MAP_REL = join102(".loki", "state", "requirements-map.json");
70306
+ REQ_MAP_REL = join103(".loki", "state", "requirements-map.json");
70112
70307
  REQ_STOP = new Set(["with", "that", "this", "from", "have", "will", "should", "must", "when", "then", "into", "each", "every", "user", "users", "page", "able", "allow", "support", "ensure", "using", "their", "there", "which", "shall"]);
70113
70308
  LINK_RE = /\s*\[checks?:\s*([^\]]+)\]\s*$/i;
70114
70309
  });
70115
70310
 
70116
70311
  // ../../loki-ts/src/features/speed/seal_group.ts
70117
70312
  import { createHash as createHash29 } from "crypto";
70118
- import { existsSync as existsSync72, mkdirSync as mkdirSync54, readdirSync as readdirSync30, readFileSync as readFileSync90, renameSync as renameSync20, statSync as statSync26, writeFileSync as writeFileSync52 } from "fs";
70119
- import { dirname as dirname42, join as join103 } from "path";
70313
+ import { existsSync as existsSync72, mkdirSync as mkdirSync54, readdirSync as readdirSync30, readFileSync as readFileSync91, renameSync as renameSync20, statSync as statSync26, writeFileSync as writeFileSync52 } from "fs";
70314
+ import { dirname as dirname43, join as join104 } from "path";
70120
70315
  function sealGroup(runDir, rh) {
70121
- const manifestPath = join103(runDir, "group", "manifest.json");
70316
+ const manifestPath = join104(runDir, "group", "manifest.json");
70122
70317
  if (!existsSync72(manifestPath))
70123
70318
  return { section: undefined, notProven: [], problems: 0, allUnitsPass: true };
70124
70319
  const notProven = [];
@@ -70143,10 +70338,10 @@ function sealGroup(runDir, rh) {
70143
70338
  return fail2(`unit ${index2} has an invalid, duplicate or case-colliding id`);
70144
70339
  seen.add(id2);
70145
70340
  seenLower.add(id2.toLowerCase());
70146
- const dir = join103(unitsDir(runDir), id2), rp = join103(dir, "receipt.json"), ep2 = join103(dir, "events.jsonl");
70341
+ const dir = join104(unitsDir(runDir), id2), rp = join104(dir, "receipt.json"), ep2 = join104(dir, "events.jsonl");
70147
70342
  let bytes;
70148
70343
  try {
70149
- bytes = readFileSync90(rp);
70344
+ bytes = readFileSync91(rp);
70150
70345
  } catch {
70151
70346
  return fail2(`unit ${id2} sub-receipt missing`);
70152
70347
  }
@@ -70165,7 +70360,7 @@ function sealGroup(runDir, rh) {
70165
70360
  unit_id: id2,
70166
70361
  sub_receipt_sha256: sha4(bytes),
70167
70362
  receipt_sha256: sub["receipt_sha256"],
70168
- events_file_sha256: existsSync72(ep2) ? sha4(readFileSync90(ep2)) : null,
70363
+ events_file_sha256: existsSync72(ep2) ? sha4(readFileSync91(ep2)) : null,
70169
70364
  verdict,
70170
70365
  goal: text3(u10["goal"], 200),
70171
70366
  files: (Array.isArray(u10["files"]) ? u10["files"] : []).map((f) => text3(f, 200)).filter(Boolean).slice(0, 50),
@@ -70185,12 +70380,12 @@ function capGroupVerdict(v3, g) {
70185
70380
  return !g.allUnitsPass && (v3 === "VERIFIED" || v3 === "ALREADY_SATISFIED") ? "PARTIAL" : v3;
70186
70381
  }
70187
70382
  async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
70188
- const runDir = dirname42(receiptPath);
70383
+ const runDir = dirname43(receiptPath);
70189
70384
  const signed = isObj10(receipt["verification"]) && typeof receipt["verification"]["jwt"] === "string";
70190
70385
  const bad = (reason) => ({ verdict: "TAMPERED", reason: `group: ${reason}` });
70191
70386
  const g = receipt["group"];
70192
70387
  if (g === undefined)
70193
- return existsSync72(join103(runDir, "group", "manifest.json")) ? bad("group directory present but the receipt has no group section") : null;
70388
+ return existsSync72(join104(runDir, "group", "manifest.json")) ? bad("group directory present but the receipt has no group section") : null;
70194
70389
  if (!isObj10(g) || !ID_RE.test(String(g["group_id"] ?? "")) || !Array.isArray(g["units"]) || g["units"].length === 0)
70195
70390
  return bad("group section malformed");
70196
70391
  const entries = g["units"];
@@ -70202,20 +70397,20 @@ async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
70202
70397
  return bad("unit directories do not match the receipt (missing or extra unit)");
70203
70398
  let unchecked = null;
70204
70399
  for (let i = 0;i < entries.length; i++) {
70205
- const e10 = entries[i], id2 = ids[i], dir = join103(unitsDir(runDir), id2), rp = join103(dir, "receipt.json"), ep2 = join103(dir, "events.jsonl");
70400
+ const e10 = entries[i], id2 = ids[i], dir = join104(unitsDir(runDir), id2), rp = join104(dir, "receipt.json"), ep2 = join104(dir, "events.jsonl");
70206
70401
  if (e10["index"] !== i)
70207
70402
  return bad(`unit ${id2} is out of order (index ${String(e10["index"])} at position ${i})`);
70208
70403
  let bytes;
70209
70404
  try {
70210
70405
  if (!statSync26(dir).isDirectory())
70211
70406
  return bad(`unit ${id2} is not a directory`);
70212
- bytes = readFileSync90(rp);
70407
+ bytes = readFileSync91(rp);
70213
70408
  } catch {
70214
70409
  return bad(`unit ${id2} sub-receipt missing`);
70215
70410
  }
70216
70411
  if (sha4(bytes) !== e10["sub_receipt_sha256"])
70217
70412
  return bad(`unit ${id2} sub-receipt does not match its recorded hash`);
70218
- const evSha = existsSync72(ep2) ? sha4(readFileSync90(ep2)) : null;
70413
+ const evSha = existsSync72(ep2) ? sha4(readFileSync91(ep2)) : null;
70219
70414
  if (evSha !== (e10["events_file_sha256"] ?? null))
70220
70415
  return bad(`unit ${id2} events.jsonl does not match its recorded hash`);
70221
70416
  const sub = readJson7(rp);
@@ -70244,7 +70439,7 @@ function composeGroupReceipt(groupDir, rh, o) {
70244
70439
  const body = { schema: GROUP_SCHEMA, run_id: gid, verdict, base_sha: o.baseRef, head_sha: o.head, not_proven: seal.notProven, group: seal.section };
70245
70440
  const hash = rh(body), sig = signReceipt(gid, hash);
70246
70441
  const receipt = { ...body, receipt_sha256: hash, verification: { jwt: sig.jwt, kid: sig.kid } };
70247
- const path = join103(groupDir, "receipt.json"), tmp = `${path}.${process.pid}.tmp`;
70442
+ const path = join104(groupDir, "receipt.json"), tmp = `${path}.${process.pid}.tmp`;
70248
70443
  mkdirSync54(groupDir, { recursive: true });
70249
70444
  writeFileSync52(tmp, JSON.stringify(receipt, null, 2) + `
70250
70445
  `);
@@ -70256,9 +70451,9 @@ function compositeVerdict(childVerdicts) {
70256
70451
  const failed2 = childVerdicts.filter((v3) => v3 === "FAILED" || !["VERIFIED", "ALREADY_SATISFIED", "PARTIAL", "SPEC_CONFLICT"].includes(v3)).length;
70257
70452
  return capGroupVerdict(base, { section: undefined, notProven: [], problems: failed2, allUnitsPass: childVerdicts.every((v3) => PASSING.has(v3)) });
70258
70453
  }
70259
- var ID_RE, PASSING, sha4 = (b) => createHash29("sha256").update(b).digest("hex"), isObj10 = (v3) => v3 !== null && typeof v3 === "object" && !Array.isArray(v3), text3 = (v3, cap) => typeof v3 === "string" ? v3.replace(/[\x00-\x1f\x7f]+/g, " ").trim().slice(0, cap) : "", num4 = (v3) => typeof v3 === "number" && Number.isFinite(v3) && v3 >= 0 ? v3 : 0, unitsDir = (runDir) => join103(runDir, "group", "units"), readJson7 = (p) => {
70454
+ var ID_RE, PASSING, sha4 = (b) => createHash29("sha256").update(b).digest("hex"), isObj10 = (v3) => v3 !== null && typeof v3 === "object" && !Array.isArray(v3), text3 = (v3, cap) => typeof v3 === "string" ? v3.replace(/[\x00-\x1f\x7f]+/g, " ").trim().slice(0, cap) : "", num4 = (v3) => typeof v3 === "number" && Number.isFinite(v3) && v3 >= 0 ? v3 : 0, unitsDir = (runDir) => join104(runDir, "group", "units"), readJson7 = (p) => {
70260
70455
  try {
70261
- return JSON.parse(readFileSync90(p, "utf8"));
70456
+ return JSON.parse(readFileSync91(p, "utf8"));
70262
70457
  } catch {
70263
70458
  return;
70264
70459
  }
@@ -70276,8 +70471,8 @@ var init_seal_group = __esm(() => {
70276
70471
  });
70277
70472
 
70278
70473
  // ../../loki-ts/src/supply/supply_guard.ts
70279
- import { existsSync as existsSync73, readFileSync as readFileSync91, statSync as statSync27 } from "fs";
70280
- import { basename as basename27, join as join104 } from "path";
70474
+ import { existsSync as existsSync73, readFileSync as readFileSync92, statSync as statSync27 } from "fs";
70475
+ import { basename as basename27, join as join105 } from "path";
70281
70476
  function supplyEnabled(env) {
70282
70477
  return env["LOKI_SUPPLY_GUARD"] !== "0";
70283
70478
  }
@@ -70292,13 +70487,13 @@ function isManifestPath(path) {
70292
70487
  return MANIFESTS2.test(basename27(path));
70293
70488
  }
70294
70489
  function readDeclared(repoDir) {
70295
- const p = join104(repoDir, ".loki", DECLARED_FILE);
70490
+ const p = join105(repoDir, ".loki", DECLARED_FILE);
70296
70491
  if (!existsSync73(p))
70297
70492
  return { deps: [], problem: null };
70298
70493
  try {
70299
70494
  if (statSync27(p).size > MAX_FILE_BYTES)
70300
70495
  return { deps: [], problem: "declaration file too large" };
70301
- const j10 = JSON.parse(readFileSync91(p, "utf8"));
70496
+ const j10 = JSON.parse(readFileSync92(p, "utf8"));
70302
70497
  if (!Array.isArray(j10))
70303
70498
  return { deps: [], problem: "declaration is not a JSON array" };
70304
70499
  const deps = [];
@@ -70318,11 +70513,11 @@ function readDeclared(repoDir) {
70318
70513
  }
70319
70514
  }
70320
70515
  function readAllowlist(repoDir) {
70321
- const p = join104(repoDir, ".loki", "supply-allowlist");
70516
+ const p = join105(repoDir, ".loki", "supply-allowlist");
70322
70517
  if (!existsSync73(p))
70323
70518
  return new Set;
70324
70519
  try {
70325
- return new Set(readFileSync91(p, "utf8").split(`
70520
+ return new Set(readFileSync92(p, "utf8").split(`
70326
70521
  `).map((l) => l.replace(/#.*$/, "").trim()).filter(Boolean));
70327
70522
  } catch {
70328
70523
  return new Set;
@@ -70363,7 +70558,7 @@ function userConfigPrivate(eco, repoDir, env, goEnv = {}, name = "") {
70363
70558
  if (eco === "npm") {
70364
70559
  if (privateUrlList([env["npm_config_registry"] ?? "", env["NPM_CONFIG_REGISTRY"] ?? ""]))
70365
70560
  return true;
70366
- return files(join104(repoDir, ".npmrc"), home ? join104(home, ".npmrc") : "").some((t) => t.split(`
70561
+ return files(join105(repoDir, ".npmrc"), home ? join105(home, ".npmrc") : "").some((t) => t.split(`
70367
70562
  `).some((l) => {
70368
70563
  const m = /^\s*(?:(@[^:\s]+):)?registry\s*=\s*(\S+)/.exec(l);
70369
70564
  return !!m && privateUrl(m[2]) && (m[1] === undefined || name.startsWith(`${m[1]}/`));
@@ -70372,7 +70567,7 @@ function userConfigPrivate(eco, repoDir, env, goEnv = {}, name = "") {
70372
70567
  if (eco === "pypi") {
70373
70568
  if (privateUrlList([env["PIP_INDEX_URL"] ?? "", env["PIP_EXTRA_INDEX_URL"] ?? ""]))
70374
70569
  return true;
70375
- const cfg = [env["PIP_CONFIG_FILE"] ?? "", home ? join104(home, ".config", "pip", "pip.conf") : "", home ? join104(home, ".pip", "pip.conf") : "", join104(repoDir, "pip.conf")];
70570
+ const cfg = [env["PIP_CONFIG_FILE"] ?? "", home ? join105(home, ".config", "pip", "pip.conf") : "", home ? join105(home, ".pip", "pip.conf") : "", join105(repoDir, "pip.conf")];
70376
70571
  return files(...cfg).some((t) => t.split(`
70377
70572
  `).some((l) => {
70378
70573
  const m = /^\s*(?:extra-)?index-url\s*[=:]\s*(.+)$/.exec(l);
@@ -70382,7 +70577,7 @@ function userConfigPrivate(eco, repoDir, env, goEnv = {}, name = "") {
70382
70577
  if (eco === "cargo") {
70383
70578
  if (Object.keys(env).some((k3) => /^CARGO_REGISTRIES_.+_INDEX$/.test(k3) || /^CARGO_SOURCE_/.test(k3)))
70384
70579
  return true;
70385
- return files(join104(repoDir, ".cargo", "config.toml"), join104(repoDir, ".cargo", "config"), home ? join104(home, ".cargo", "config.toml") : "", home ? join104(home, ".cargo", "config") : "").some((t) => /^\s*\[(registries\.|source\.)/m.test(t) || /replace-with\s*=/.test(t));
70580
+ return files(join105(repoDir, ".cargo", "config.toml"), join105(repoDir, ".cargo", "config"), home ? join105(home, ".cargo", "config.toml") : "", home ? join105(home, ".cargo", "config") : "").some((t) => /^\s*\[(registries\.|source\.)/m.test(t) || /replace-with\s*=/.test(t));
70386
70581
  }
70387
70582
  if (eco === "go") {
70388
70583
  const gp2 = goEnv["GOPROXY"] ?? env["GOPROXY"] ?? "";
@@ -70505,7 +70700,7 @@ var MIN_AGE_DAYS = 7, DECLARED_FILE = "supply-declared.json", MAX_CHECKED = 50,
70505
70700
  }
70506
70701
  }, PUBLIC_HOSTS, hostOf = (u10) => u10.trim().toLowerCase().replace(/^[a-z][a-z0-9+.-]*:\/\//, "").replace(/^www\./, "").split(/[/?#\s]/)[0].replace(/^[^@]*@/, "").replace(/:\d+$/, ""), privateUrl = (u10) => /[a-z0-9]/i.test(u10) && !PUBLIC_HOSTS.has(hostOf(u10)), readSmall = (p) => {
70507
70702
  try {
70508
- return statSync27(p).size <= MAX_FILE_BYTES ? readFileSync91(p, "utf8") : "";
70703
+ return statSync27(p).size <= MAX_FILE_BYTES ? readFileSync92(p, "utf8") : "";
70509
70704
  } catch {
70510
70705
  return "";
70511
70706
  }
@@ -70544,8 +70739,8 @@ __export(exports_seal, {
70544
70739
  AGENT_ONLY_REASON: () => AGENT_ONLY_REASON
70545
70740
  });
70546
70741
  import { createHash as createHash30 } from "crypto";
70547
- import { existsSync as existsSync74, readdirSync as readdirSync31, mkdirSync as mkdirSync55, readFileSync as readFileSync92 } from "fs";
70548
- import { basename as basename28, isAbsolute as isAbsolute20, join as join105, relative as relative24 } from "path";
70742
+ import { existsSync as existsSync74, readdirSync as readdirSync31, mkdirSync as mkdirSync55, readFileSync as readFileSync93 } from "fs";
70743
+ import { basename as basename28, isAbsolute as isAbsolute20, join as join106, relative as relative24 } from "path";
70549
70744
  async function leanSymbolGap(ctx, o, rawDiff, head, vraw) {
70550
70745
  if (externalRun(o) || Array.isArray(o.wall?.files) && o.wall.files.length > 0 || o.intake?.already_satisfied === true || o.implement?.exit === "already_done")
70551
70746
  return [];
@@ -70566,7 +70761,7 @@ async function leanSymbolGap(ctx, o, rawDiff, head, vraw) {
70566
70761
  const n11 = String(c.name ?? ""), p = n11.slice(n11.indexOf(":") + 1);
70567
70762
  if (n11.includes(":") && isTestFile(p))
70568
70763
  try {
70569
- sources2.push(readFileSync92(join105(ctx.repoDir, p), "utf8"));
70764
+ sources2.push(readFileSync93(join106(ctx.repoDir, p), "utf8"));
70570
70765
  } catch {}
70571
70766
  }
70572
70767
  return symbolGap(changedSymbols(d.stdout), sources2);
@@ -70649,7 +70844,7 @@ function renderReceiptMd(r) {
70649
70844
  `);
70650
70845
  }
70651
70846
  var SIGNING_UNAVAILABLE = "receipt signing unavailable (no usable signing key: invalid key or unwritable ~/.loki/keys)", AGENT_ONLY_REASON = "only agent-authored tests executed (no agent-independent proof)", WALL_GREEN_ON_BASE_REASON = "Wall green on base: no Wall test discriminates the change", EXCLUDE_LOKI = ":(exclude).loki", sha2562 = (s) => createHash30("sha256").update(s).digest("hex"), str3 = (v3) => typeof v3 === "string" && v3 !== "" ? v3 : null, EXTERNAL_MODEL_LABEL = "external (no Loki implement session)", EXTERNAL_DIFF_NOT_ISOLATED = "Wall author not filesystem-isolated from the external diff", EXTERNAL_NO_WALL = "external diff sealed with no Wall file that ran; the only checks are the repo's existing tests", externalRun = (o) => o.implement?.exit === "external", LEAN_NO_SYMBOL = "no passing check references a changed symbol and no Wall file ran", strs2 = (v3) => Array.isArray(v3) ? v3.filter((x3) => typeof x3 === "string" && x3 !== "") : [], g = (ctx) => (a) => git9(ctx, a), receiptRel = (ctx) => {
70652
- const r = relative24(ctx.repoDir, join105(ctx.runDir, "receipt.json"));
70847
+ const r = relative24(ctx.repoDir, join106(ctx.runDir, "receipt.json"));
70653
70848
  return r.startsWith("..") || isAbsolute20(r) ? `.loki/runs/${ctx.runId}/receipt.json` : r;
70654
70849
  }, commitStage, wallGreenOnBaseOf = (o) => {
70655
70850
  const b = o.wall?.base_run ?? {};
@@ -70791,7 +70986,7 @@ var init_seal = __esm(() => {
70791
70986
  if (wallNotRun > 0) {
70792
70987
  try {
70793
70988
  const kept = new Set((Array.isArray(o.wall?.files) ? o.wall.files : []).map((f) => basename28(String(f.path))));
70794
- for (const n11 of readdirSync31(join105(ctx.runDir, "wall")).sort())
70989
+ for (const n11 of readdirSync31(join106(ctx.runDir, "wall")).sort())
70795
70990
  if (!kept.has(n11))
70796
70991
  notProven.add(`wall test discarded: ${n11} (not_run)`);
70797
70992
  } catch {}
@@ -70862,19 +71057,19 @@ var init_seal = __esm(() => {
70862
71057
  for (const [s, d] of Object.entries(o))
70863
71058
  if (typeof d?.duration_s === "number")
70864
71059
  stages[s] = d.duration_s;
70865
- const T = hooks.time, time = T ? T.build(ctx, stages, T.firstEventMs(join105(ctx.runDir, "events.jsonl"))) : { wall_s: Object.values(stages).reduce((a, b) => a + (b ?? 0), 0), stages }, totalS = T?.reconciled(time) ?? null;
71060
+ const T = hooks.time, time = T ? T.build(ctx, stages, T.firstEventMs(join106(ctx.runDir, "events.jsonl"))) : { wall_s: Object.values(stages).reduce((a, b) => a + (b ?? 0), 0), stages }, totalS = T?.reconciled(time) ?? null;
70866
71061
  const iterIds = [...new Set([...Object.values(o).flatMap((d) => [...strs2(d?.iteration_ids), ...strs2([d?.iteration_id])]), ...ctx.sessionIds?.() ?? [], ...xr2?.cost_iteration ? [xr2.cost_iteration] : []])];
70867
71062
  if (iterIds.length === 0)
70868
71063
  notProven.add("cost not measured (no iteration ids recorded)");
70869
71064
  const cost = ctx.cost.read(ctx.repoDir, iterIds);
70870
71065
  if (cost.unmetered)
70871
71066
  notProven.add("cost unmetered (CLI invoker; recorded as 0)");
70872
- const eventsPath = join105(ctx.runDir, "events.jsonl");
71067
+ const eventsPath = join106(ctx.runDir, "events.jsonl");
70873
71068
  const wallFiles = Array.isArray(o.wall?.files) ? o.wall.files : [];
70874
71069
  const wallPassed = typeof o.verify?.wall_passed === "boolean" ? o.verify.wall_passed : null;
70875
71070
  if (wallFiles.length > 0 && wallPassed === null)
70876
71071
  notProven.add("wall result not recorded by verify");
70877
- const routeBlock = buildRouteBlock(process.env, ctx.provider, o.implement?.route ?? o.plan?.route_record ?? (routerEnabled(process.env) ? loadRouteRecord(ctx.runDir) : undefined), cost.router ?? (routerEnabled(process.env) ? sumResultCosts(join105(ctx.repoDir, ".loki"), liveArchivedCosts(join105(ctx.repoDir, ".loki"), iterIds, UNMETERED)).router : undefined), ctx.model);
71072
+ const routeBlock = buildRouteBlock(process.env, ctx.provider, o.implement?.route ?? o.plan?.route_record ?? (routerEnabled(process.env) ? loadRouteRecord(ctx.runDir) : undefined), cost.router ?? (routerEnabled(process.env) ? sumResultCosts(join106(ctx.repoDir, ".loki"), liveArchivedCosts(join106(ctx.repoDir, ".loki"), iterIds, UNMETERED)).router : undefined), ctx.model);
70878
71073
  if (routeBlock)
70879
71074
  for (const l of routeNotProven(routeBlock))
70880
71075
  notProven.add(l);
@@ -70917,7 +71112,7 @@ var init_seal = __esm(() => {
70917
71112
  model: externalRun(o) ? EXTERNAL_MODEL_LABEL : ctx.model,
70918
71113
  ...externalRun(o) ? { implement: { exit: "external", patch_sha256: str3(o.implement?.patch_sha256) ?? "" } } : {},
70919
71114
  resumed: o.intake?.resumed === true,
70920
- events_sha256: sha2562(existsSync74(eventsPath) ? readFileSync92(eventsPath) : ""),
71115
+ events_sha256: sha2562(existsSync74(eventsPath) ? readFileSync93(eventsPath) : ""),
70921
71116
  ...await sealEvidence(ctx.repoDir, ctx.runDir, o, notProven, signal, ctx.emit),
70922
71117
  log_seal: true,
70923
71118
  toolchain: collectToolchain(),
@@ -70945,10 +71140,10 @@ var init_seal = __esm(() => {
70945
71140
  }
70946
71141
  const receipt = { ...body, receipt_sha256: hash, verification: { jwt: sig.jwt, kid: sig.kid } };
70947
71142
  mkdirSync55(ctx.runDir, { recursive: true });
70948
- const path = join105(ctx.runDir, "receipt.json");
71143
+ const path = join106(ctx.runDir, "receipt.json");
70949
71144
  atomicWriteText(path, JSON.stringify(receipt, null, 2) + `
70950
71145
  `);
70951
- atomicWriteText(join105(ctx.runDir, "receipt.md"), renderReceiptMd(receipt));
71146
+ atomicWriteText(join106(ctx.runDir, "receipt.md"), renderReceiptMd(receipt));
70952
71147
  recordRun(process.env, ctx.repoDir, ranModel(o.implement, ctx.model, o.fix), verdict, cost.usd, cost.unmetered === true, totalS);
70953
71148
  try {
70954
71149
  hooks.sealed?.(ctx.runDir, JSON.parse(JSON.stringify(receipt), (_k2, v3) => v3 && typeof v3 === "object" ? Object.freeze(v3) : v3));
@@ -71022,7 +71217,7 @@ var init_github_token = __esm(() => {
71022
71217
  // ../../loki-ts/src/engine10/fetch_issue.ts
71023
71218
  import { execFileSync as execFileSync7 } from "child_process";
71024
71219
  import { writeFileSync as writeFileSync54 } from "fs";
71025
- import { join as join106 } from "path";
71220
+ import { join as join107 } from "path";
71026
71221
  function defaultExec(cmd, args) {
71027
71222
  const ms = Number(process.env.LOKI_FETCH_ISSUE_TIMEOUT_MS) || 60000;
71028
71223
  return execFileSync7(cmd, args, { encoding: "utf8", env: process.env, timeout: ms, killSignal: "SIGKILL" });
@@ -71049,7 +71244,7 @@ function fetchIssueToFile(ref, outFile, exec = defaultExec) {
71049
71244
  var ISSUE_PROVIDERS_SH;
71050
71245
  var init_fetch_issue = __esm(() => {
71051
71246
  init_paths();
71052
- ISSUE_PROVIDERS_SH = join106(REPO_ROOT, "autonomy/issue-providers.sh");
71247
+ ISSUE_PROVIDERS_SH = join107(REPO_ROOT, "autonomy/issue-providers.sh");
71053
71248
  if (false) {}
71054
71249
  });
71055
71250
 
@@ -71582,9 +71777,21 @@ var init_provider = __esm(() => {
71582
71777
  });
71583
71778
 
71584
71779
  // ../../loki-ts/src/util/funnel.ts
71780
+ function blockerOf(v3) {
71781
+ return typeof v3 === "string" && PREFLIGHT_BLOCKERS.includes(v3) ? v3 : null;
71782
+ }
71783
+ function noteRefusal(b) {
71784
+ if (b)
71785
+ refusal = b;
71786
+ }
71787
+ function noteRefusalFromEvents(events2) {
71788
+ noteRefusal(blockerOf(events2.find((e10) => e10.type === "stage.failed" && e10.stage === "intake")?.data["blocker"]));
71789
+ }
71790
+ var PREFLIGHT_BLOCKERS, refusal = null;
71585
71791
  var init_funnel = __esm(() => {
71586
71792
  init_paths();
71587
71793
  init_safe_git();
71794
+ PREFLIGHT_BLOCKERS = ["not_a_repo", "git_identity", "dirty_tracked_tree", "no_provider", "not_logged_in", "prd_missing", "unsupported_flag", "disk", "other"];
71588
71795
  });
71589
71796
 
71590
71797
  // ../../loki-ts/src/cockpit/capability.ts
@@ -71597,14 +71804,14 @@ var init_capability = __esm(() => {
71597
71804
  var init_raster = () => {};
71598
71805
 
71599
71806
  // ../../loki-ts/src/commands/doctor.ts
71600
- import { appendFileSync as appendFileSync11, writeFileSync as writeFileSync56, mkdirSync as mkdirSync56, accessSync as accessSync2, constants as fsConstants2, existsSync as existsSync75, lstatSync as lstatSync28, readdirSync as readdirSync32, readFileSync as readFileSync93, readlinkSync as readlinkSync6, realpathSync as realpathSync31, statSync as statSync29, statfsSync } from "fs";
71807
+ import { appendFileSync as appendFileSync11, writeFileSync as writeFileSync56, mkdirSync as mkdirSync56, accessSync as accessSync2, constants as fsConstants2, existsSync as existsSync75, lstatSync as lstatSync28, readdirSync as readdirSync32, readFileSync as readFileSync94, readlinkSync as readlinkSync6, realpathSync as realpathSync31, statSync as statSync29, statfsSync } from "fs";
71601
71808
  import { spawnSync as spawnSync12 } from "child_process";
71602
71809
  import { homedir as homedir12, tmpdir as tmpdir18 } from "os";
71603
- import { join as join107, resolve as resolve31 } from "path";
71810
+ import { join as join108, resolve as resolve31 } from "path";
71604
71811
  function loadRequirements(file = REQUIREMENTS_FILE) {
71605
71812
  if (file === REQUIREMENTS_FILE && cached)
71606
71813
  return cached;
71607
- const t = JSON.parse(readFileSync93(file, "utf8"));
71814
+ const t = JSON.parse(readFileSync94(file, "utf8"));
71608
71815
  if (file === REQUIREMENTS_FILE)
71609
71816
  cached = t;
71610
71817
  return t;
@@ -71635,7 +71842,7 @@ function providerLoginIssue(provider, cli, env) {
71635
71842
  const said = `${r.stdout}${r.stderr}`;
71636
71843
  return /not logged in/i.test(said) || classifyFailure(said).reason === "auth" ? { fatal: "codex is not logged in; run: codex login (or set OPENAI_API_KEY)" } : { warn: "could not confirm the Codex login (codex login status gave no answer); continuing" };
71637
71844
  }
71638
- if (PROVIDER_API_KEY_VARS.some(key) || provider === "opencode" && existsSync75(join107(env.XDG_DATA_HOME || join107(home, ".local", "share"), "opencode", "auth.json")) || provider === "cline" && existsSync75(join107(home, ".cline")))
71845
+ if (PROVIDER_API_KEY_VARS.some(key) || provider === "opencode" && existsSync75(join108(env.XDG_DATA_HOME || join108(home, ".local", "share"), "opencode", "auth.json")) || provider === "cline" && existsSync75(join108(home, ".cline")))
71639
71846
  return null;
71640
71847
  return provider === "aider" || provider === "opencode" || provider === "cline" ? { warn: `no ${provider} login or API key found (set a provider API key such as ANTHROPIC_API_KEY or OPENAI_API_KEY${provider === "opencode" ? ", or run: opencode auth login" : ""}); continuing` } : null;
71641
71848
  }
@@ -71646,9 +71853,9 @@ function providerAuthPath(provider, env) {
71646
71853
  const v3 = own.find(set);
71647
71854
  if (v3)
71648
71855
  return `${v3 === "CLAUDE_CODE_OAUTH_TOKEN" ? "oauth_token" : "api_key"}:${v3}`;
71649
- if (provider === "opencode" && existsSync75(join107(env.XDG_DATA_HOME || join107(home, ".local", "share"), "opencode", "auth.json")))
71856
+ if (provider === "opencode" && existsSync75(join108(env.XDG_DATA_HOME || join108(home, ".local", "share"), "opencode", "auth.json")))
71650
71857
  return "cli_login:opencode";
71651
- if (provider === "cline" && existsSync75(join107(home, ".cline")))
71858
+ if (provider === "cline" && existsSync75(join108(home, ".cline")))
71652
71859
  return "cli_login:cline";
71653
71860
  return provider === "claude" || provider === "codex" ? `cli_login:${provider}` : "none";
71654
71861
  }
@@ -71673,9 +71880,9 @@ function claudeAuthStatusLoggedIn(cli = "claude", env = process.env) {
71673
71880
  }
71674
71881
  }
71675
71882
  function claudeLoginProbeCached(cli, env = process.env, now2 = Date.now()) {
71676
- const file = join107(env.HOME || homedir12(), ".loki", "claude-login-ok.json");
71883
+ const file = join108(env.HOME || homedir12(), ".loki", "claude-login-ok.json");
71677
71884
  try {
71678
- const c = JSON.parse(readFileSync93(file, "utf8"));
71885
+ const c = JSON.parse(readFileSync94(file, "utf8"));
71679
71886
  if (c?.cli === cli && typeof c.at === "number" && now2 - c.at >= 0 && now2 - c.at < CLAUDE_LOGIN_TTL_MS)
71680
71887
  return "yes";
71681
71888
  } catch {}
@@ -71684,7 +71891,7 @@ function claudeLoginProbeCached(cli, env = process.env, now2 = Date.now()) {
71684
71891
  li2 = claudeAuthStatusLoggedIn(cli, env);
71685
71892
  if (li2 === "yes") {
71686
71893
  try {
71687
- mkdirSync56(join107(file, ".."), { recursive: true });
71894
+ mkdirSync56(join108(file, ".."), { recursive: true });
71688
71895
  writeFileSync56(file, JSON.stringify({ cli, at: now2 }));
71689
71896
  } catch {}
71690
71897
  }
@@ -71693,16 +71900,16 @@ function claudeLoginProbeCached(cli, env = process.env, now2 = Date.now()) {
71693
71900
  async function ghAuthProbeCached(env, probe, now2 = Date.now()) {
71694
71901
  const bin = "gh";
71695
71902
  const gh = Bun.which(bin, { PATH: env.PATH ?? process.env.PATH ?? "" }) ?? bin;
71696
- const file = join107(env.HOME || homedir12(), ".loki", "gh-auth-ok.json");
71903
+ const file = join108(env.HOME || homedir12(), ".loki", "gh-auth-ok.json");
71697
71904
  try {
71698
- const c = JSON.parse(readFileSync93(file, "utf8"));
71905
+ const c = JSON.parse(readFileSync94(file, "utf8"));
71699
71906
  if (c?.gh === gh && typeof c.at === "number" && now2 - c.at >= 0 && now2 - c.at < CLAUDE_LOGIN_TTL_MS)
71700
71907
  return true;
71701
71908
  } catch {}
71702
71909
  const ok3 = await probe();
71703
71910
  if (ok3) {
71704
71911
  try {
71705
- mkdirSync56(join107(file, ".."), { recursive: true });
71912
+ mkdirSync56(join108(file, ".."), { recursive: true });
71706
71913
  writeFileSync56(file, JSON.stringify({ gh, at: now2 }));
71707
71914
  } catch {}
71708
71915
  }
@@ -71777,7 +71984,7 @@ var init_first_run_repo = __esm(() => {
71777
71984
 
71778
71985
  // ../../loki-ts/src/engine10/preflight.ts
71779
71986
  import { accessSync as accessSync3, constants as fsc2, mkdirSync as mkdirSync57, statfsSync as statfsSync2, writeFileSync as writeFileSync57 } from "fs";
71780
- import { join as join108 } from "path";
71987
+ import { join as join109 } from "path";
71781
71988
  async function sh3(argv, opts) {
71782
71989
  try {
71783
71990
  return await run(argv, opts);
@@ -71819,18 +72026,19 @@ async function checkPreflight(o) {
71819
72026
  pinErr = `${e10.message}; set a valid value or unset it (the run would otherwise drop the pin and use the provider default model)`;
71820
72027
  }
71821
72028
  }
71822
- const fatal = wt.exitCode !== 0 || wt.stdout.trim() !== "true" ? initFatal ?? NOT_A_REPO(o.repoDir) : !name.stdout.trim() || !email.stdout.trim() ? `git identity is not set; run: git config user.name "you" && git config user.email "you@example.com"` : !envVar ? `the v10 engine has no ${o.provider} invoker yet` : o.provider !== "claude" && truthy(env["LOKI_HOST_GUARD"]) ? `LOKI_HOST_GUARD=1 is set but provider '${o.provider}' has no enforced PreToolUse hook; unset LOKI_HOST_GUARD or use --provider claude` : pinErr ? pinErr : !cliOk ? `provider CLI '${cli}' is not on PATH; install it or set ${envVar} to its path${requirementFix(o.provider) ? `. Fix: ${requirementFix(o.provider)}` : ""}` : head.exitCode !== 0 ? "repository has no commits; run: git add . && git commit -m init" : null;
71823
- if (fatal)
71824
- return { fatal, warnings };
72029
+ const refuse = (b, f) => [b, f];
72030
+ const hit = wt.exitCode !== 0 || wt.stdout.trim() !== "true" ? refuse("not_a_repo", initFatal ?? NOT_A_REPO(o.repoDir)) : !name.stdout.trim() || !email.stdout.trim() ? refuse("git_identity", `git identity is not set; run: git config user.name "you" && git config user.email "you@example.com"`) : !envVar ? refuse("unsupported_flag", `the v10 engine has no ${o.provider} invoker yet`) : o.provider !== "claude" && truthy(env["LOKI_HOST_GUARD"]) ? refuse("other", `LOKI_HOST_GUARD=1 is set but provider '${o.provider}' has no enforced PreToolUse hook; unset LOKI_HOST_GUARD or use --provider claude`) : pinErr ? refuse("other", pinErr) : !cliOk ? refuse("no_provider", `provider CLI '${cli}' is not on PATH; install it or set ${envVar} to its path${requirementFix(o.provider) ? `. Fix: ${requirementFix(o.provider)}` : ""}`) : head.exitCode !== 0 ? refuse("other", "repository has no commits; run: git add . && git commit -m init") : null;
72031
+ if (hit)
72032
+ return { fatal: hit[1], warnings, blocker: hit[0] };
71825
72033
  try {
71826
72034
  accessSync3(o.repoDir, fsc2.W_OK);
71827
72035
  } catch {
71828
- return { fatal: `${o.repoDir} is not writable; run: chmod u+w "${o.repoDir}" (or run loki from a writable checkout)`, warnings };
72036
+ return { fatal: `${o.repoDir} is not writable; run: chmod u+w "${o.repoDir}" (or run loki from a writable checkout)`, warnings, blocker: "other" };
71829
72037
  }
71830
72038
  const free = freeMb(o.repoDir, o.statfs ?? statfsSync2);
71831
72039
  const minMb = Number(env["LOKI_MIN_FREE_MB"]) > 0 ? Number(env["LOKI_MIN_FREE_MB"]) : 200;
71832
72040
  if (free !== null && free < minMb)
71833
- return { fatal: `only ${Math.floor(free)} MB free on the volume holding ${o.repoDir} (need ${minMb} MB); free disk space, or lower LOKI_MIN_FREE_MB`, warnings };
72041
+ return { fatal: `only ${Math.floor(free)} MB free on the volume holding ${o.repoDir} (need ${minMb} MB); free disk space, or lower LOKI_MIN_FREE_MB`, warnings, blocker: "disk" };
71834
72042
  if (free !== null && free < Math.max(2048, minMb))
71835
72043
  warnings.push(`low disk: ${Math.floor(free)} MB free on the volume holding ${o.repoDir}; a long run may fail mid-way (warns under 2 GB)`);
71836
72044
  const auth_path = providerAuthPath(o.provider, env);
@@ -71861,16 +72069,16 @@ async function checkPreflight(o) {
71861
72069
  if (o.runDir) {
71862
72070
  try {
71863
72071
  mkdirSync57(o.runDir, { recursive: true });
71864
- writeFileSync57(join108(o.runDir, "preflight.json"), JSON.stringify({ provider: o.provider, auth_path, probe }) + `
72072
+ writeFileSync57(join109(o.runDir, "preflight.json"), JSON.stringify({ provider: o.provider, auth_path, probe }) + `
71865
72073
  `);
71866
72074
  } catch {}
71867
72075
  }
71868
72076
  if (authFatal)
71869
- return { fatal: authFatal, warnings };
72077
+ return { fatal: authFatal, warnings, blocker: "not_logged_in" };
71870
72078
  if (o.pr && GITHUB_ORIGIN_RE.test((await git10(["config", "--get", "remote.origin.url"])).stdout.trim())) {
71871
72079
  const ghOk = await ghAuthProbeCached(env, async () => (await sh3(["gh", "--version"], { env, timeoutMs: 5000 })).exitCode === 0 && (await sh3(["gh", "auth", "status"], { env, timeoutMs: 1e4 })).exitCode === 0);
71872
72080
  if (!ghOk)
71873
- return { fatal: `gh (GitHub CLI) is missing or not authenticated; run gh auth login, or pass --no-pr`, warnings };
72081
+ return { fatal: `gh (GitHub CLI) is missing or not authenticated; run gh auth login, or pass --no-pr`, warnings, blocker: "other" };
71874
72082
  const plan = await probePublish((await git10(["config", "--get", "remote.origin.url"])).stdout.trim(), env);
71875
72083
  if (plan) {
71876
72084
  if (plan.warning)
@@ -71887,7 +72095,7 @@ async function assertPreflight(o) {
71887
72095
  process.stderr.write(`${w}
71888
72096
  `);
71889
72097
  if (r.fatal)
71890
- throw new PreflightError(r.fatal);
72098
+ throw new PreflightError(r.fatal, r.blocker);
71891
72099
  }
71892
72100
  var CLI_ENV_VAR, GITHUB_ORIGIN_RE, PreflightError;
71893
72101
  var init_preflight = __esm(() => {
@@ -71898,9 +72106,15 @@ var init_preflight = __esm(() => {
71898
72106
  init_first_run_repo();
71899
72107
  init_engine_origin();
71900
72108
  init_shell();
72109
+ init_funnel();
71901
72110
  CLI_ENV_VAR = { claude: "LOKI_CLAUDE_CLI", codex: "LOKI_CODEX_CLI", cline: "LOKI_CLINE_CLI", aider: "LOKI_AIDER_CLI", opencode: "LOKI_OPENCODE_CLI" };
71902
72111
  GITHUB_ORIGIN_RE = /^(?:https:\/\/(?:[^@/]+@)?github\.com\/|git@github\.com:|ssh:\/\/git@github\.com\/)/;
71903
72112
  PreflightError = class PreflightError extends Error {
72113
+ blocker;
72114
+ constructor(message, blocker = "other") {
72115
+ super(message);
72116
+ this.blocker = blocker;
72117
+ }
71904
72118
  };
71905
72119
  });
71906
72120
 
@@ -71909,7 +72123,7 @@ var exports_ship_hook = {};
71909
72123
  __export(exports_ship_hook, {
71910
72124
  startShip: () => startShip
71911
72125
  });
71912
- import { dirname as dirname44 } from "path";
72126
+ import { dirname as dirname45 } from "path";
71913
72127
  async function startShip(repoDir, eventsPath, env) {
71914
72128
  let url = shipEnabled(env);
71915
72129
  if (!url) {
@@ -71919,7 +72133,7 @@ async function startShip(repoDir, eventsPath, env) {
71919
72133
  }
71920
72134
  if (!url)
71921
72135
  return;
71922
- startShipLoop({ runDir: dirname44(eventsPath), url, source: sourceId(repoDir), token: env.LOKI_CONTROL_TOKEN });
72136
+ startShipLoop({ runDir: dirname45(eventsPath), url, source: sourceId(repoDir), token: env.LOKI_CONTROL_TOKEN });
71923
72137
  }
71924
72138
  var init_ship_hook = __esm(() => {
71925
72139
  init_discover();
@@ -72526,10 +72740,10 @@ __export(exports_run_group, {
72526
72740
  groupCostLine: () => groupCostLine,
72527
72741
  NOT_PROVEN: () => NOT_PROVEN
72528
72742
  });
72529
- import { cpSync as cpSync2, existsSync as existsSync76, mkdirSync as mkdirSync58, readdirSync as readdirSync34, readFileSync as readFileSync94, rmSync as rmSync32, statSync as statSync30 } from "fs";
72743
+ import { cpSync as cpSync2, existsSync as existsSync76, mkdirSync as mkdirSync58, readdirSync as readdirSync34, readFileSync as readFileSync95, rmSync as rmSync32, statSync as statSync30 } from "fs";
72530
72744
  import { createHash as createHash31 } from "crypto";
72531
72745
  import { spawn as spawn12 } from "child_process";
72532
- import { join as join109, resolve as resolve32 } from "path";
72746
+ import { join as join110, resolve as resolve32 } from "path";
72533
72747
  function scopedEnv(env) {
72534
72748
  const out3 = {};
72535
72749
  for (const [k3, v3] of Object.entries(env))
@@ -72566,7 +72780,7 @@ function groupCostLine(costs, provider = "claude") {
72566
72780
  `;
72567
72781
  }
72568
72782
  function writeGroupCostRecord(repoDir, name, costs, provider) {
72569
- const dir = join109(repoDir, ".loki", "metrics", "efficiency");
72783
+ const dir = join110(repoDir, ".loki", "metrics", "efficiency");
72570
72784
  const timestamp = new Date().toISOString();
72571
72785
  try {
72572
72786
  const base = { phase: "implement", provider, status: "group", kind: "group_cost", timestamp };
@@ -72580,7 +72794,7 @@ function writeGroupCostRecord(repoDir, name, costs, provider) {
72580
72794
  if (recs.length === 0)
72581
72795
  return;
72582
72796
  mkdirSync58(dir, { recursive: true });
72583
- recs.forEach((r, k3) => atomicWriteJson(join109(dir, `iteration-group-${name}-${String(k3).padStart(3, "0")}.json`), r));
72797
+ recs.forEach((r, k3) => atomicWriteJson(join110(dir, `iteration-group-${name}-${String(k3).padStart(3, "0")}.json`), r));
72584
72798
  } catch {}
72585
72799
  }
72586
72800
  function testCommand(repoDir, env) {
@@ -72593,7 +72807,7 @@ function testCommand(repoDir, env) {
72593
72807
  return [];
72594
72808
  }
72595
72809
  function findResumable(repoDir, specSha, unitIds) {
72596
- const root = join109(repoDir, ".loki", "groups");
72810
+ const root = join110(repoDir, ".loki", "groups");
72597
72811
  let names = [];
72598
72812
  try {
72599
72813
  names = readdirSync34(root);
@@ -72604,7 +72818,7 @@ function findResumable(repoDir, specSha, unitIds) {
72604
72818
  for (const gid of names) {
72605
72819
  if (!GID_RE.test(gid))
72606
72820
  continue;
72607
- const p = join109(root, gid, "dag.json"), d = readJson8(p);
72821
+ const p = join110(root, gid, "dag.json"), d = readJson8(p);
72608
72822
  if (!d || (unitIds ? JSON.stringify((Array.isArray(d["units"]) ? d["units"] : []).filter((u10) => !u10.fixKind).map((u10) => u10.id)) !== JSON.stringify(unitIds) : d["spec_sha256"] !== specSha) || typeof d["base_ref"] !== "string" || !Array.isArray(d["units"]))
72609
72823
  continue;
72610
72824
  let at2 = 0;
@@ -72621,7 +72835,7 @@ function findResumable(repoDir, specSha, unitIds) {
72621
72835
  async function unitDone(verifyReceipt, repoDir, gid, n11, id2) {
72622
72836
  if (!UNIT_ID_RE.test(id2))
72623
72837
  return false;
72624
- const rp = join109(repoDir, ".loki", "groups", gid, "group", "units", id2, "receipt.json");
72838
+ const rp = join110(repoDir, ".loki", "groups", gid, "group", "units", id2, "receipt.json");
72625
72839
  const rec2 = readJson8(rp);
72626
72840
  if (!rec2 || rec2["verdict"] !== "VERIFIED")
72627
72841
  return false;
@@ -72636,7 +72850,7 @@ async function adoptJournaled(verifyReceipt, repoDir, dir, key, gid, n11, id2, t
72636
72850
  return false;
72637
72851
  if (!await unitDone(verifyReceipt, repoDir, e10.gid, e10.n, id2))
72638
72852
  return false;
72639
- const signed = readJson8(join109(repoDir, ".loki", "groups", e10.gid, "group", "units", id2, "receipt.json"));
72853
+ const signed = readJson8(join110(repoDir, ".loki", "groups", e10.gid, "group", "units", id2, "receipt.json"));
72640
72854
  const signedTask = (signed?.["task"] ?? {}).sha256;
72641
72855
  const signedSpec = (signed?.["unit_spec"] ?? {}).sha256;
72642
72856
  if (typeof signedSpec !== "string" || signedSpec === "" || signedSpec !== specSha)
@@ -72646,9 +72860,9 @@ async function adoptJournaled(verifyReceipt, repoDir, dir, key, gid, n11, id2, t
72646
72860
  const tip = git11(repoDir, ["rev-parse", "--verify", "--quiet", `refs/heads/loki/unit-${e10.gid}-${e10.n}`]);
72647
72861
  if (tip === "" || tip !== e10.head)
72648
72862
  return false;
72649
- const dst = join109(repoDir, ".loki", "groups", gid, "group", "units", id2);
72863
+ const dst = join110(repoDir, ".loki", "groups", gid, "group", "units", id2);
72650
72864
  rmSync32(dst, { recursive: true, force: true });
72651
- cpSync2(join109(repoDir, ".loki", "groups", e10.gid, "group", "units", id2), dst, { recursive: true });
72865
+ cpSync2(join110(repoDir, ".loki", "groups", e10.gid, "group", "units", id2), dst, { recursive: true });
72652
72866
  if (safeGitSpawn(repoDir, ["update-ref", `refs/heads/loki/unit-${gid}-${n11}`, tip], { encoding: "utf8" }).status !== 0)
72653
72867
  return false;
72654
72868
  if (!await unitDone(verifyReceipt, repoDir, gid, n11, id2))
@@ -72683,8 +72897,8 @@ async function runGroup(launcher, dag, ctx) {
72683
72897
  const revised = resumable !== null && exact === null;
72684
72898
  const changed = new Set;
72685
72899
  const groupId = resumable?.gid ?? `g${Date.now().toString(36)}`;
72686
- const groupDir = join109(repoDir, ".loki", "groups", groupId);
72687
- const receiptPath = join109(groupDir, "receipt.json");
72900
+ const groupDir = join110(repoDir, ".loki", "groups", groupId);
72901
+ const receiptPath = join110(groupDir, "receipt.json");
72688
72902
  const slugOf = () => originSlug(repoDir);
72689
72903
  let baseRef;
72690
72904
  let startBranch = "";
@@ -72776,10 +72990,10 @@ async function runGroup(launcher, dag, ctx) {
72776
72990
  const accOf = new Map;
72777
72991
  for (const cu2 of Array.isArray(gc2?.["units"]) ? gc2["units"] : [])
72778
72992
  accOf.set(cu2.id, cu2.criteria.map((c) => c.text));
72779
- const specDir = join109(groupDir, "unit_specs");
72993
+ const specDir = join110(groupDir, "unit_specs");
72780
72994
  mkdirSync58(specDir, { recursive: true });
72781
72995
  for (const u10 of units) {
72782
- const spec = join109(specDir, `${u10.id}.json`);
72996
+ const spec = join110(specDir, `${u10.id}.json`);
72783
72997
  const isFix = !!u10.fixKind;
72784
72998
  if (!isFix)
72785
72999
  u10.base = baseRef;
@@ -72805,19 +73019,19 @@ async function runGroup(launcher, dag, ctx) {
72805
73019
  say(`loki: unit ${u10.id} skipped-unchanged
72806
73020
  `);
72807
73021
  } else if (resumable && UNIT_ID_RE.test(u10.id))
72808
- rmSync32(join109(groupDir, "group", "units", u10.id), { recursive: true, force: true });
73022
+ rmSync32(join110(groupDir, "group", "units", u10.id), { recursive: true, force: true });
72809
73023
  }
72810
73024
  const cut2 = units.findIndex((u10) => u10.fixKind && !u10.done);
72811
73025
  if (cut2 >= 0)
72812
73026
  for (const u10 of units.splice(cut2)) {
72813
73027
  if (u10.done)
72814
73028
  doneCount--;
72815
- rmSync32(join109(groupDir, "group", "units", u10.id), { recursive: true, force: true });
73029
+ rmSync32(join110(groupDir, "group", "units", u10.id), { recursive: true, force: true });
72816
73030
  }
72817
73031
  if (resumable)
72818
73032
  say(`loki: resuming group ${groupId}: ${doneCount} of ${units.length} units already VERIFIED
72819
73033
  `);
72820
- const dagPath = join109(groupDir, "dag.json");
73034
+ const dagPath = join110(groupDir, "dag.json");
72821
73035
  atomicWriteJson(dagPath, { group: groupId, spec_sha256: specSha, base_ref: baseRef, start_branch: startBranch, ...full, units });
72822
73036
  try {
72823
73037
  const chk = await checkDecomposable(full, { map: (() => {
@@ -72847,7 +73061,7 @@ async function runGroup(launcher, dag, ctx) {
72847
73061
  const n11 = Math.min(slots, pending);
72848
73062
  say(`loki: group ${groupId}: ${units.length} units, ${n11} parallel slot(s) (provider ${provider})
72849
73063
  `);
72850
- const backlog = join109(REPO_ROOT, "autonomy", "lib", "backlog.py");
73064
+ const backlog = join110(REPO_ROOT, "autonomy", "lib", "backlog.py");
72851
73065
  const feed = createGroupFeed(groupId, units, createGroupRenderer({ write: say, isTTY: false }));
72852
73066
  const res = await run2([backlog, slug, "--dag", dagPath, "--group", groupId, "--slots", String(n11), "--provider", provider], scopedEnv({ ...env, LOKI_PROVIDER: provider }), repoDir, (c) => feed.feed(c));
72853
73067
  launchCode = res.code;
@@ -72887,7 +73101,7 @@ async function runGroup(launcher, dag, ctx) {
72887
73101
  const testCmd = testCommand(repoDir, env), fixes = units.filter((u10) => u10.fixKind);
72888
73102
  const putDag = (us2) => atomicWriteJson(dagPath, { group: groupId, spec_sha256: specSha, base_ref: baseRef, start_branch: startBranch, ...full, units: us2 });
72889
73103
  const launchFix = async (fix) => {
72890
- const key = `unit-${groupId}-${units.length + 1}`, spec = join109(specDir, `${fix.id}.json`), slug = slugOf();
73104
+ const key = `unit-${groupId}-${units.length + 1}`, spec = join110(specDir, `${fix.id}.json`), slug = slugOf();
72891
73105
  if (!slug)
72892
73106
  return null;
72893
73107
  atomicWriteJson(spec, { id: fix.id, writeSet: fix.writeSet, pack: fix.writeSet, tokenBudget: 1e9, acceptance: fix.acceptance });
@@ -72896,7 +73110,7 @@ async function runGroup(launcher, dag, ctx) {
72896
73110
  fix.base = git11(repoDir, ["rev-parse", "HEAD"]);
72897
73111
  units.push(fix);
72898
73112
  putDag(units.map((u10) => u10 === fix ? u10 : { ...u10, done: true }));
72899
- const res = await run2([join109(REPO_ROOT, "autonomy", "lib", "backlog.py"), slug, "--dag", dagPath, "--group", groupId, "--slots", "1", "--provider", provider], scopedEnv({ ...env, LOKI_PROVIDER: provider }), repoDir);
73113
+ const res = await run2([join110(REPO_ROOT, "autonomy", "lib", "backlog.py"), slug, "--dag", dagPath, "--group", groupId, "--slots", "1", "--provider", provider], scopedEnv({ ...env, LOKI_PROVIDER: provider }), repoDir);
72900
73114
  costs.push(parseGroupCost(res.stdout));
72901
73115
  if (res.code !== 0 || !new RegExp(`^backlog: ${key} (VERIFIED|PR \\S+)$`, "m").test(res.stdout)) {
72902
73116
  units.pop();
@@ -72930,7 +73144,7 @@ async function runGroup(launcher, dag, ctx) {
72930
73144
  return 1;
72931
73145
  }
72932
73146
  const order2 = units.map((u10) => ({ unit_id: u10.id, goal: u10.items.join("; "), files: u10.writeSet }));
72933
- atomicWriteJson(join109(groupDir, "group", "manifest.json"), { group_id: groupId, units: order2 });
73147
+ atomicWriteJson(join110(groupDir, "group", "manifest.json"), { group_id: groupId, units: order2 });
72934
73148
  const head = git11(repoDir, ["rev-parse", "--verify", `refs/heads/${r.branch}`]);
72935
73149
  let verdict = "", unitVerdicts = [], why = "";
72936
73150
  try {
@@ -72976,7 +73190,7 @@ var NOT_PROVEN = 4, ENV_KEEP, defaultLauncher = (argv, env, cwd, onOut) => new P
72976
73190
  return r.status === 0 ? String(r.stdout).trim() : "";
72977
73191
  }, SLUG_RE, originSlug = (repoDir) => SLUG_RE.exec(git11(repoDir, ["remote", "get-url", "origin"]))?.[1], sha2563 = (s) => createHash31("sha256").update(s).digest("hex"), UNIT_ID_RE, GID_RE, readJson8 = (p) => {
72978
73192
  try {
72979
- const v3 = JSON.parse(readFileSync94(p, "utf8"));
73193
+ const v3 = JSON.parse(readFileSync95(p, "utf8"));
72980
73194
  return v3 !== null && typeof v3 === "object" && !Array.isArray(v3) ? v3 : null;
72981
73195
  } catch {
72982
73196
  return null;
@@ -73011,7 +73225,7 @@ __export(exports_route, {
73011
73225
  MAX_SPEC_BYTES: () => MAX_SPEC_BYTES2,
73012
73226
  MAX_SEQ_TASK_BYTES: () => MAX_SEQ_TASK_BYTES
73013
73227
  });
73014
- import { closeSync as closeSync15, constants as constants5, fstatSync as fstatSync8, openSync as openSync15, readFileSync as readFileSync95, realpathSync as realpathSync32 } from "fs";
73228
+ import { closeSync as closeSync15, constants as constants5, fstatSync as fstatSync8, openSync as openSync15, readFileSync as readFileSync96, realpathSync as realpathSync32 } from "fs";
73015
73229
  import { isAbsolute as isAbsolute21, relative as relative25, resolve as resolve33 } from "path";
73016
73230
  function providerSlots(env, provider) {
73017
73231
  provider = (provider || env.LOKI_PROVIDER || "claude").toLowerCase();
@@ -73038,7 +73252,7 @@ function readSpec(task, repoDir, cwd) {
73038
73252
  return { kind: "text" };
73039
73253
  if (st2.size > MAX_SPEC_BYTES2)
73040
73254
  return { kind: "reject", reason: `spec file over ${MAX_SPEC_BYTES2} bytes` };
73041
- const buf = readFileSync95(fd2);
73255
+ const buf = readFileSync96(fd2);
73042
73256
  if (buf.length > MAX_SPEC_BYTES2)
73043
73257
  return { kind: "reject", reason: `spec file over ${MAX_SPEC_BYTES2} bytes` };
73044
73258
  if (buf.includes(0))
@@ -73157,15 +73371,15 @@ var init_route = __esm(() => {
73157
73371
  });
73158
73372
 
73159
73373
  // ../../loki-ts/src/contrib/forecast.ts
73160
- import { appendFileSync as appendFileSync12, existsSync as existsSync77, mkdirSync as mkdirSync59, readFileSync as readFileSync96 } from "fs";
73161
- import { join as join110 } from "path";
73374
+ import { appendFileSync as appendFileSync12, existsSync as existsSync77, mkdirSync as mkdirSync59, readFileSync as readFileSync97 } from "fs";
73375
+ import { join as join111 } from "path";
73162
73376
  function readWindowDeltas(lokiDir2) {
73163
73377
  const p = historyPath2(lokiDir2);
73164
73378
  if (!existsSync77(p))
73165
73379
  return [];
73166
73380
  const out3 = [];
73167
73381
  try {
73168
- for (const line2 of readFileSync96(p, "utf8").split(`
73382
+ for (const line2 of readFileSync97(p, "utf8").split(`
73169
73383
  `)) {
73170
73384
  if (!line2.trim())
73171
73385
  continue;
@@ -73216,17 +73430,17 @@ function forecastLine(reading, history, opts = {}) {
73216
73430
  const w = range(history.map((h10) => h10.week));
73217
73431
  return fit(`forecast: ~${s}% of session window, ~${w}% of week (basis: ${history.length} past runs; ${used})`, width);
73218
73432
  }
73219
- async function printForecast(lokiDir2, read2, write, env = process.env) {
73433
+ async function printForecast(lokiDir2, read3, write, env = process.env) {
73220
73434
  if (!forecastOn(env))
73221
73435
  return;
73222
73436
  try {
73223
- const line2 = forecastLine(await read2(), readWindowDeltas(lokiDir2), { env });
73437
+ const line2 = forecastLine(await read3(), readWindowDeltas(lokiDir2), { env });
73224
73438
  if (line2)
73225
73439
  write(line2 + `
73226
73440
  `);
73227
73441
  } catch {}
73228
73442
  }
73229
- var MIN_FORECAST_RUNS = 3, KEEP_RUNS = 20, forecastOn = (env = process.env) => env["LOKI_FORECAST"] !== "0", finite = (v3) => typeof v3 === "number" && Number.isFinite(v3), historyPath2 = (lokiDir2) => join110(lokiDir2, "quota-runs.jsonl"), range = (xs2) => {
73443
+ var MIN_FORECAST_RUNS = 3, KEEP_RUNS = 20, forecastOn = (env = process.env) => env["LOKI_FORECAST"] !== "0", finite = (v3) => typeof v3 === "number" && Number.isFinite(v3), historyPath2 = (lokiDir2) => join111(lokiDir2, "quota-runs.jsonl"), range = (xs2) => {
73230
73444
  const lo = Math.floor(Math.min(...xs2)), hi2 = Math.ceil(Math.max(...xs2));
73231
73445
  return lo === hi2 ? `${hi2}` : `${lo}-${hi2}`;
73232
73446
  };
@@ -73235,8 +73449,8 @@ var init_forecast = __esm(() => {
73235
73449
  });
73236
73450
 
73237
73451
  // ../../loki-ts/src/commands/queue.ts
73238
- import { existsSync as existsSync78, mkdirSync as mkdirSync60, readFileSync as readFileSync97, readdirSync as readdirSync35, renameSync as renameSync21, statSync as statSync31, writeFileSync as writeFileSync58 } from "fs";
73239
- import { join as join111, resolve as resolve34 } from "path";
73452
+ import { existsSync as existsSync78, mkdirSync as mkdirSync60, readFileSync as readFileSync98, readdirSync as readdirSync35, renameSync as renameSync21, statSync as statSync31, writeFileSync as writeFileSync58 } from "fs";
73453
+ import { join as join112, resolve as resolve34 } from "path";
73240
73454
  function normalizeRef(raw2) {
73241
73455
  const m = URL_RE2.exec(raw2);
73242
73456
  if (m)
@@ -73246,11 +73460,11 @@ function normalizeRef(raw2) {
73246
73460
  return /^0+$/.test(raw2.replace(/^.*#/, "")) ? null : raw2;
73247
73461
  }
73248
73462
  function queuePath(lokiDir2) {
73249
- return join111(lokiDir2, "issue-queue.json");
73463
+ return join112(lokiDir2, "issue-queue.json");
73250
73464
  }
73251
73465
  function readQueue(lokiDir2) {
73252
73466
  try {
73253
- const d = JSON.parse(readFileSync97(queuePath(lokiDir2), "utf8"));
73467
+ const d = JSON.parse(readFileSync98(queuePath(lokiDir2), "utf8"));
73254
73468
  return Array.isArray(d.items) ? d.items.filter((i) => typeof i?.ref === "string") : [];
73255
73469
  } catch {
73256
73470
  return [];
@@ -73261,7 +73475,7 @@ function quarantineCorruptQueue(lokiDir2, now2, warn) {
73261
73475
  if (!existsSync78(p))
73262
73476
  return;
73263
73477
  try {
73264
- const d = JSON.parse(readFileSync97(p, "utf8"));
73478
+ const d = JSON.parse(readFileSync98(p, "utf8"));
73265
73479
  if (d !== null && typeof d === "object" && Array.isArray(d.items))
73266
73480
  return;
73267
73481
  } catch {}
@@ -73463,8 +73677,8 @@ ${QUEUE_USAGE}`);
73463
73677
  try {
73464
73678
  mkdirSync60(d.lokiDir, { recursive: true });
73465
73679
  const stamp2 = finished.toISOString().replace(/[:.]/g, "-");
73466
- writeFileSync58(join111(d.lokiDir, `queue-digest-${stamp2}.txt`), text4);
73467
- writeFileSync58(join111(d.lokiDir, "queue-digest-latest.txt"), text4);
73680
+ writeFileSync58(join112(d.lokiDir, `queue-digest-${stamp2}.txt`), text4);
73681
+ writeFileSync58(join112(d.lokiDir, "queue-digest-latest.txt"), text4);
73468
73682
  } catch (e10) {
73469
73683
  d.err(`loki queue: could not write digest: ${e10 instanceof Error ? e10.message : String(e10)}
73470
73684
  `);
@@ -73474,11 +73688,11 @@ ${QUEUE_USAGE}`);
73474
73688
  }
73475
73689
  function newestRecord(lokiDir2, since) {
73476
73690
  for (const [sub2, file] of [["runs", "receipt.json"], ["proofs", "proof.json"]]) {
73477
- const dir = join111(lokiDir2, sub2);
73691
+ const dir = join112(lokiDir2, sub2);
73478
73692
  let best = null;
73479
73693
  try {
73480
73694
  for (const name of readdirSync35(dir)) {
73481
- const p = join111(dir, name, file);
73695
+ const p = join112(dir, name, file);
73482
73696
  if (!existsSync78(p))
73483
73697
  continue;
73484
73698
  const t = statSync31(p).mtimeMs;
@@ -73487,7 +73701,7 @@ function newestRecord(lokiDir2, since) {
73487
73701
  }
73488
73702
  if (!best)
73489
73703
  continue;
73490
- const d = JSON.parse(readFileSync97(best.p, "utf8"));
73704
+ const d = JSON.parse(readFileSync98(best.p, "utf8"));
73491
73705
  const usd = d.cost?.usd;
73492
73706
  const unmetered = d.cost?.source === "cli-invoker-unmetered";
73493
73707
  return {
@@ -73521,7 +73735,7 @@ function makeDefaultRunner(lokiDir2) {
73521
73735
  return async (ref, opts) => {
73522
73736
  const since = Date.now();
73523
73737
  const argv = [resolve34(REPO_ROOT, "bin", "loki"), ...queueStartArgs(ref, !!opts.pr)];
73524
- const runLoki = opts.cwd ? join111(opts.cwd, ".loki") : lokiDir2;
73738
+ const runLoki = opts.cwd ? join112(opts.cwd, ".loki") : lokiDir2;
73525
73739
  const env = runnerEnv(opts, runLoki);
73526
73740
  const proc = Bun.spawn(argv, { stdout: "pipe", stderr: "pipe", stdin: "ignore", env, ...opts.cwd ? { cwd: opts.cwd } : {} });
73527
73741
  const mins2 = itemTimeoutMin(process.env["LOKI_QUEUE_ITEM_TIMEOUT_MIN"]);
@@ -73531,9 +73745,9 @@ function makeDefaultRunner(lokiDir2) {
73531
73745
  clearTimeout(timer);
73532
73746
  const output = so + se2;
73533
73747
  try {
73534
- const logDir = join111(lokiDir2, "queue-logs");
73748
+ const logDir = join112(lokiDir2, "queue-logs");
73535
73749
  mkdirSync60(logDir, { recursive: true });
73536
- writeFileSync58(join111(logDir, `${(opts.logName ?? ref).replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 120)}.log`), output);
73750
+ writeFileSync58(join112(logDir, `${(opts.logName ?? ref).replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 120)}.log`), output);
73537
73751
  } catch {}
73538
73752
  const proof = newestRecord(runLoki, since);
73539
73753
  return { rc: rc2, output, verdict: proof.verdict, costUsd: proof.costUsd, runId: proof.runId ?? null };
@@ -73713,13 +73927,13 @@ function renderEpicTree(n11, title, rows) {
73713
73927
  }
73714
73928
  function makeSessionDecompose(repoDir, lokiDir2, provider) {
73715
73929
  return async (slug, issue, triageReason) => {
73716
- const { mkdirSync: mkdirSync61, readFileSync: readFileSync98, existsSync: existsSync79 } = await import("fs");
73717
- const { join: join112 } = await import("path");
73930
+ const { mkdirSync: mkdirSync61, readFileSync: readFileSync99, existsSync: existsSync79 } = await import("fs");
73931
+ const { join: join113 } = await import("path");
73718
73932
  const { createSessionRunner: createSessionRunner2 } = await Promise.resolve().then(() => (init_session(), exports_session));
73719
73933
  const { envOverride: envOverride2 } = await Promise.resolve().then(() => (init_decision(), exports_decision));
73720
- const dir = join112(lokiDir2, "issues-run", "decompose");
73934
+ const dir = join113(lokiDir2, "issues-run", "decompose");
73721
73935
  mkdirSync61(dir, { recursive: true });
73722
- const outPath = join112(dir, `issue-${issue.number}-${Date.now()}.json`);
73936
+ const outPath = join113(dir, `issue-${issue.number}-${Date.now()}.json`);
73723
73937
  const runner = createSessionRunner2({ provider, lokiRoot: lokiDir2 });
73724
73938
  const r = await runner.run({
73725
73939
  stage: "plan",
@@ -73732,7 +73946,7 @@ function makeSessionDecompose(repoDir, lokiDir2, provider) {
73732
73946
  ...provider === "claude" && envOverride2(process.env) === null ? { model: "opus" } : {}
73733
73947
  });
73734
73948
  if (existsSync79(outPath))
73735
- return readFileSync98(outPath, "utf8");
73949
+ return readFileSync99(outPath, "utf8");
73736
73950
  return r.summary ?? "";
73737
73951
  };
73738
73952
  }
@@ -73759,7 +73973,7 @@ __export(exports_issues_run, {
73759
73973
  import { spawnSync as spawnSync15 } from "child_process";
73760
73974
  import { cpSync as cpSync3, existsSync as existsSync79, mkdirSync as mkdirSync61, mkdtempSync as mkdtempSync15, rmSync as rmSync33, writeFileSync as writeFileSync59 } from "fs";
73761
73975
  import { tmpdir as tmpdir19 } from "os";
73762
- import { join as join112, resolve as resolve35 } from "path";
73976
+ import { join as join113, resolve as resolve35 } from "path";
73763
73977
  import { createInterface as createInterface3 } from "readline";
73764
73978
  function parseIssuesArgs(args) {
73765
73979
  const a = { slug: null, label: null, milestone: null, limit: DEFAULT_LIMIT, parallel: 1, draft: false, dryRun: false, yes: false, comment: false, split: true, json: false };
@@ -74015,7 +74229,7 @@ ${USAGE}`);
74015
74229
  }
74016
74230
  }
74017
74231
  const stamp2 = started.toISOString().replace(/[:.]/g, "-");
74018
- const runDir = join112(d.lokiDir, "issues-run", stamp2);
74232
+ const runDir = join113(d.lokiDir, "issues-run", stamp2);
74019
74233
  mkdirSync61(runDir, { recursive: true });
74020
74234
  const byRef = new Map(actionable.map((i) => [`${slug}#${i.number}`, i]));
74021
74235
  const sink = () => {};
@@ -74105,14 +74319,14 @@ ${USAGE}`);
74105
74319
  ${trees.join(`
74106
74320
  `)}` : "");
74107
74321
  try {
74108
- writeFileSync59(join112(runDir, "digest.md"), text4);
74322
+ writeFileSync59(join113(runDir, "digest.md"), text4);
74109
74323
  } catch (e10) {
74110
74324
  d.err(`loki issues run: could not write digest: ${e10 instanceof Error ? e10.message : String(e10)}
74111
74325
  `);
74112
74326
  }
74113
74327
  d.out(`
74114
74328
  ${text4}
74115
- digest: ${join112(runDir, "digest.md")}
74329
+ digest: ${join113(runDir, "digest.md")}
74116
74330
  `);
74117
74331
  return 0;
74118
74332
  }
@@ -74122,11 +74336,11 @@ function perRun(est) {
74122
74336
  return est.prior ? { usd: est.prior.usd, tilde: "~", label: " (rough prior)" } : null;
74123
74337
  }
74124
74338
  function keepReceipt(wt, runId2, runDir, err) {
74125
- const src = join112(wt, ".loki", "runs", runId2);
74339
+ const src = join113(wt, ".loki", "runs", runId2);
74126
74340
  if (!/^[A-Za-z0-9_.-]+$/.test(runId2) || !existsSync79(src))
74127
74341
  return;
74128
74342
  try {
74129
- cpSync3(src, join112(runDir, "receipts", runId2), { recursive: true });
74343
+ cpSync3(src, join113(runDir, "receipts", runId2), { recursive: true });
74130
74344
  } catch (e10) {
74131
74345
  err(`loki issues run: could not keep the receipt of ${runId2}: ${e10 instanceof Error ? e10.message : String(e10)}
74132
74346
  `);
@@ -74173,8 +74387,8 @@ function makeWorktrees(repoDir) {
74173
74387
  let root = null;
74174
74388
  return {
74175
74389
  create: (name, base) => {
74176
- root ??= mkdtempSync15(join112(tmpdir19(), "loki-issues-"));
74177
- const p = join112(root, name);
74390
+ root ??= mkdtempSync15(join113(tmpdir19(), "loki-issues-"));
74391
+ const p = join113(root, name);
74178
74392
  safeGit(repoDir, ["worktree", "add", "-B", `loki/${name}`, p, base]);
74179
74393
  return p;
74180
74394
  },
@@ -74267,7 +74481,7 @@ __export(exports_satisfaction, {
74267
74481
  });
74268
74482
  import { appendFileSync as appendFileSync13, mkdirSync as mkdirSync62 } from "fs";
74269
74483
  import { homedir as homedir13 } from "os";
74270
- import { join as join113 } from "path";
74484
+ import { join as join114 } from "path";
74271
74485
  import { createInterface as createInterface4 } from "readline";
74272
74486
  function satisfactionEnabled(env, tty) {
74273
74487
  if (!tty)
@@ -74287,9 +74501,9 @@ function parseScore(line2) {
74287
74501
  return { score: Number(m[1]), again: m[2] ? m[2].toLowerCase() === "y" : null };
74288
74502
  }
74289
74503
  function recordSatisfaction(home, row) {
74290
- const dir = join113(home, ".loki");
74504
+ const dir = join114(home, ".loki");
74291
74505
  mkdirSync62(dir, { recursive: true, mode: 448 });
74292
- appendFileSync13(join113(dir, "satisfaction.jsonl"), `${JSON.stringify(row)}
74506
+ appendFileSync13(join114(dir, "satisfaction.jsonl"), `${JSON.stringify(row)}
74293
74507
  `, { mode: 384 });
74294
74508
  }
74295
74509
  async function maybeAsk(o) {
@@ -74360,8 +74574,8 @@ __export(exports_supervisor, {
74360
74574
  });
74361
74575
  import { spawn as spawn13, spawnSync as spawnSync16 } from "child_process";
74362
74576
  import { createHash as createHash32, createPublicKey as createPublicKey3, sign as sign2 } from "crypto";
74363
- import { existsSync as existsSync80, mkdirSync as mkdirSync63, readFileSync as readFileSync98, writeFileSync as writeFileSync60 } from "fs";
74364
- import { join as join114, relative as relative26, resolve as resolve36 } from "path";
74577
+ import { existsSync as existsSync80, mkdirSync as mkdirSync63, readFileSync as readFileSync99, writeFileSync as writeFileSync60 } from "fs";
74578
+ import { join as join115, relative as relative26, resolve as resolve36 } from "path";
74365
74579
  async function slackEvent(...a) {
74366
74580
  try {
74367
74581
  await (await Promise.resolve().then(() => (init_slack_events(), exports_slack_events))).notifyEvent(...a);
@@ -74390,7 +74604,7 @@ class SupervisorLog {
74390
74604
  this.log = new EventLog(path, runId2);
74391
74605
  this.hash = createHash32("sha256");
74392
74606
  try {
74393
- this.hash.update(readFileSync98(path));
74607
+ this.hash.update(readFileSync99(path));
74394
74608
  } catch {}
74395
74609
  }
74396
74610
  implementOpen = false;
@@ -74445,7 +74659,7 @@ class SupervisorLog {
74445
74659
  const expected = this.hash.copy().digest("hex");
74446
74660
  let actual = "";
74447
74661
  try {
74448
- actual = createHash32("sha256").update(readFileSync98(this.path)).digest("hex");
74662
+ actual = createHash32("sha256").update(readFileSync99(this.path)).digest("hex");
74449
74663
  } catch {}
74450
74664
  if (actual === expected)
74451
74665
  return true;
@@ -74467,15 +74681,15 @@ async function runSupervisor(opts) {
74467
74681
  const t02 = Date.now();
74468
74682
  const startedProvider = opts.started?.["provider"];
74469
74683
  const env = opts.env ?? process.env;
74470
- await assertPreflight({ repoDir: opts.repoDir, provider: typeof startedProvider === "string" ? startedProvider : "claude", pr: opts.pr !== undefined, env, runDir: join114(opts.repoDir, ".loki", "runs", opts.runId) });
74684
+ await assertPreflight({ repoDir: opts.repoDir, provider: typeof startedProvider === "string" ? startedProvider : "claude", pr: opts.pr !== undefined, env, runDir: join115(opts.repoDir, ".loki", "runs", opts.runId) });
74471
74685
  writeEngineMarker(opts.repoDir, opts.runId);
74472
74686
  const origin = readOriginUrl(opts.repoDir);
74473
- const rmRunPid = writeRunPid(join114(opts.repoDir, ".loki", "runs", opts.runId), opts.runId);
74687
+ const rmRunPid = writeRunPid(join115(opts.repoDir, ".loki", "runs", opts.runId), opts.runId);
74474
74688
  process.once("exit", rmRunPid);
74475
- const log = new SupervisorLog(join114(opts.repoDir, eventsRelPath(opts.runId)), opts.runId);
74689
+ const log = new SupervisorLog(join115(opts.repoDir, eventsRelPath(opts.runId)), opts.runId);
74476
74690
  if ((env.LOKI_CONTROL ?? process.env.LOKI_CONTROL) !== "0")
74477
74691
  Promise.resolve().then(() => (init_ship_hook(), exports_ship_hook)).then((m) => m.startShip(opts.repoDir, log.path, env)).catch(() => {});
74478
- const aliveDir = join114(opts.repoDir, ".loki", "runs", opts.runId), lastAlive = opts.resume ? readAliveBeat(aliveDir) : null;
74692
+ const aliveDir = join115(opts.repoDir, ".loki", "runs", opts.runId), lastAlive = opts.resume ? readAliveBeat(aliveDir) : null;
74479
74693
  log.append(opts.resume ? "run.resumed" : "run.started", null, { ...opts.started, ...opts.resume ? { phase: "stage", ...lastAlive ? { last_alive_ts: new Date(lastAlive).toISOString() } : {} } : {}, origin_repo: githubRepoFromUrl(origin) });
74480
74694
  if (!opts.resume)
74481
74695
  Promise.resolve().then(() => (init_writeback(), exports_writeback)).then((m) => m.writeBack({ phase: "started", verdict: "", prUrl: null, receiptSha256: null, task: "" }, env));
@@ -74510,7 +74724,7 @@ async function runSupervisor(opts) {
74510
74724
  if (e10?.type === "receipt.sealed")
74511
74725
  sealed = e10.data;
74512
74726
  if (e10?.type === "variant" && e10.data.intent_confirm === true && workerEnv.LOKI_INTENT_TTY === "1") {
74513
- askIntent(String(e10.data.card ?? ""), join114(opts.repoDir, ".loki", "runs", opts.runId));
74727
+ askIntent(String(e10.data.card ?? ""), join115(opts.repoDir, ".loki", "runs", opts.runId));
74514
74728
  }
74515
74729
  }, (stopped) => {
74516
74730
  for (const g10 of sessionGroups)
@@ -74609,8 +74823,8 @@ async function runSupervisor(opts) {
74609
74823
  }
74610
74824
  log.append("run.completed", null, { verdict, ...cancelled2 ? { cancelled: true, signal: cancelled2, outcome: "CANCELLED" } : {}, pr_url: prUrl, not_proven: notProven, cost_usd: costUsd, wall_s: wallS, pre_model: preModelTiming(allEvents, t02) });
74611
74825
  log.sealLog();
74612
- recordFingerprints(join114(opts.repoDir, ".loki", "state"), opts.runId, "failed", failedCheckNames(folded.stages["verify"]?.data.checks, folded.stages["verify"]?.data.pre_red_checks), cleanTreeId(opts.repoDir));
74613
- const stages = allEvents.filter((e10) => e10.type === "stage.completed" && typeof e10.data.duration_s === "number").map((e10) => ({ label: String(e10.stage), seconds: e10.data.duration_s })), pc2 = partialCost(allEvents, log.tampered), summary = { pr: prUrl ? { url: prUrl, draft: verdict !== "VERIFIED" } : null, verdict, outcome, notProven, flaky: recordFingerprints(join114(opts.repoDir, ".loki", "state"), opts.runId, "flaky", folded.stages["verify"]?.data.flaky, cleanTreeId(opts.repoDir)), wallS, stages, cost: { usd: costUsd, provider: String(opts.started?.provider ?? ""), tokens: summaryTokens(folded, allEvents.some((e10) => e10.type === "cost")), ...summaryCache(allEvents, log.tampered), partialUsd: pc2.usd, measuredSessions: pc2.measured, totalSessions: pc2.total, stageShares: log.tampered ? null : stageShareText(allEvents), capUsd: Number(opts.started?.["max_cost_usd"]) > 0 ? Number(opts.started?.["max_cost_usd"]) : undefined } };
74826
+ recordFingerprints(join115(opts.repoDir, ".loki", "state"), opts.runId, "failed", failedCheckNames(folded.stages["verify"]?.data.checks, folded.stages["verify"]?.data.pre_red_checks), cleanTreeId(opts.repoDir));
74827
+ const stages = allEvents.filter((e10) => e10.type === "stage.completed" && typeof e10.data.duration_s === "number").map((e10) => ({ label: String(e10.stage), seconds: e10.data.duration_s })), pc2 = partialCost(allEvents, log.tampered), summary = { pr: prUrl ? { url: prUrl, draft: verdict !== "VERIFIED" } : null, verdict, outcome, notProven, flaky: recordFingerprints(join115(opts.repoDir, ".loki", "state"), opts.runId, "flaky", folded.stages["verify"]?.data.flaky, cleanTreeId(opts.repoDir)), wallS, stages, cost: { usd: costUsd, provider: String(opts.started?.provider ?? ""), tokens: summaryTokens(folded, allEvents.some((e10) => e10.type === "cost")), ...summaryCache(allEvents, log.tampered), partialUsd: pc2.usd, measuredSessions: pc2.measured, totalSessions: pc2.total, stageShares: log.tampered ? null : stageShareText(allEvents), capUsd: Number(opts.started?.["max_cost_usd"]) > 0 ? Number(opts.started?.["max_cost_usd"]) : undefined } };
74614
74828
  await slackEvent(env, "finished", { summary: formatSummary(summary), outcome: String(outcome), cost: summary.cost.usd != null ? `$${summary.cost.usd.toFixed(2)}` : "not measured", time: `${Math.round(wallS)}s`, receipt: log.tampered ? "TAMPERED" : receiptVerdict ? verdict : undefined });
74615
74829
  rmRunPid();
74616
74830
  process.off("exit", rmRunPid);
@@ -74636,6 +74850,7 @@ async function main4(args) {
74636
74850
  if (v3 === undefined || v3 === "" || v3.startsWith("-")) {
74637
74851
  process.stderr.write(`engine10: --max-cost needs a value
74638
74852
  `);
74853
+ noteRefusal("unsupported_flag");
74639
74854
  return 2;
74640
74855
  }
74641
74856
  maxCost = v3;
@@ -74647,6 +74862,7 @@ async function main4(args) {
74647
74862
  if (v3 === undefined || v3 === "" || v3.startsWith("-")) {
74648
74863
  process.stderr.write(`engine10: --provider needs a value
74649
74864
  `);
74865
+ noteRefusal("unsupported_flag");
74650
74866
  return 2;
74651
74867
  }
74652
74868
  provider = v3;
@@ -74656,6 +74872,7 @@ async function main4(args) {
74656
74872
  if (v3 === undefined || v3 === "" || v3.startsWith("-")) {
74657
74873
  process.stderr.write(`engine10: --spec needs a value
74658
74874
  `);
74875
+ noteRefusal("unsupported_flag");
74659
74876
  return 2;
74660
74877
  }
74661
74878
  specFile = v3;
@@ -74671,6 +74888,7 @@ async function main4(args) {
74671
74888
  if (v3 === undefined || v3 === "" || v3.startsWith("-")) {
74672
74889
  process.stderr.write(`engine10: --seal-existing needs a patch file
74673
74890
  `);
74891
+ noteRefusal("unsupported_flag");
74674
74892
  return 2;
74675
74893
  }
74676
74894
  sealPatch = resolve36(v3);
@@ -74682,6 +74900,7 @@ async function main4(args) {
74682
74900
  process.stderr.write(`engine10: unknown flag ${a}
74683
74901
  usage: loki "<task>" [--no-pr] [--deep] [--json] [--verbose] [--quiet] [--max-cost N] [--provider P] [--spec F] [--seal-existing PATCH] [--resume] [--fresh] [-- <task>]
74684
74902
  `);
74903
+ noteRefusal("unsupported_flag");
74685
74904
  return 2;
74686
74905
  } else
74687
74906
  words3.push(a);
@@ -74696,6 +74915,7 @@ usage: loki "<task>" [--no-pr] [--deep] [--json] [--verbose] [--quiet] [--max-co
74696
74915
  } catch (e10) {
74697
74916
  process.stderr.write(`engine10: ${e10.message}
74698
74917
  `);
74918
+ noteRefusal("prd_missing");
74699
74919
  return 2;
74700
74920
  }
74701
74921
  if (!task)
@@ -74712,6 +74932,7 @@ usage: loki "<task>" [--no-pr] [--deep] [--json] [--verbose] [--quiet] [--max-co
74712
74932
  if (!task) {
74713
74933
  process.stderr.write(`engine10: no task given
74714
74934
  `);
74935
+ noteRefusal("prd_missing");
74715
74936
  return 2;
74716
74937
  }
74717
74938
  let repoDir;
@@ -74722,6 +74943,7 @@ usage: loki "<task>" [--no-pr] [--deep] [--json] [--verbose] [--quiet] [--max-co
74722
74943
  if (!i.notice) {
74723
74944
  process.stderr.write(`engine10: ${i.fatal ?? "not inside a git repository"}
74724
74945
  `);
74946
+ noteRefusal("not_a_repo");
74725
74947
  return 2;
74726
74948
  }
74727
74949
  process.stderr.write(`engine10: ${i.notice}
@@ -74731,6 +74953,7 @@ usage: loki "<task>" [--no-pr] [--deep] [--json] [--verbose] [--quiet] [--max-co
74731
74953
  } catch {
74732
74954
  process.stderr.write(`engine10: not inside a git repository
74733
74955
  `);
74956
+ noteRefusal("not_a_repo");
74734
74957
  return 2;
74735
74958
  }
74736
74959
  }
@@ -74740,7 +74963,7 @@ usage: loki "<task>" [--no-pr] [--deep] [--json] [--verbose] [--quiet] [--max-co
74740
74963
  return rec2;
74741
74964
  }
74742
74965
  const runId2 = `e10-${new Date().toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "Z")}-${Math.random().toString(16).slice(2, 6)}`;
74743
- const runDir = join114(repoDir, ".loki", "runs", runId2);
74966
+ const runDir = join115(repoDir, ".loki", "runs", runId2);
74744
74967
  const cap = resolveCap(maxCost, repoDir);
74745
74968
  if ("error" in cap) {
74746
74969
  process.stderr.write(`engine10: ${cap.error}
@@ -74778,7 +75001,7 @@ usage: loki "<task>" [--no-pr] [--deep] [--json] [--verbose] [--quiet] [--max-co
74778
75001
  }
74779
75002
  if (spec) {
74780
75003
  mkdirSync63(runDir, { recursive: true });
74781
- writeFileSync60(join114(runDir, "spec.snapshot.md"), spec.raw);
75004
+ writeFileSync60(join115(runDir, "spec.snapshot.md"), spec.raw);
74782
75005
  for (const e10 of [env, process.env]) {
74783
75006
  e10.LOKI_E10_SPEC_PATH = relative26(repoDir, spec.path);
74784
75007
  e10.LOKI_E10_SPEC_SHA256 = spec.sha256;
@@ -74803,9 +75026,9 @@ usage: loki "<task>" [--no-pr] [--deep] [--json] [--verbose] [--quiet] [--max-co
74803
75026
  mkdirSync63(runDir, { recursive: true });
74804
75027
  try {
74805
75028
  if (trackerRef)
74806
- await fetchTrackerIssueToFile(trackerRef, join114(runDir, "issue.json"));
75029
+ await fetchTrackerIssueToFile(trackerRef, join115(runDir, "issue.json"));
74807
75030
  else
74808
- fetchIssueToFile(task, join114(runDir, "issue.json"));
75031
+ fetchIssueToFile(task, join115(runDir, "issue.json"));
74809
75032
  } catch (err) {
74810
75033
  process.stderr.write(`engine10: issue fetch failed: ${err.message.split(`
74811
75034
  `)[0]}
@@ -74835,7 +75058,7 @@ usage: loki "<task>" [--no-pr] [--deep] [--json] [--verbose] [--quiet] [--max-co
74835
75058
  process.stdout.write(`${capLine}
74836
75059
  `);
74837
75060
  const t02 = Date.now();
74838
- const eventsPath = join114(repoDir, eventsRelPath(runId2));
75061
+ const eventsPath = join115(repoDir, eventsRelPath(runId2));
74839
75062
  const live2 = (e10) => {
74840
75063
  const clockS = (Date.parse(e10.ts) - t02) / 1000;
74841
75064
  const d = e10.data;
@@ -74882,7 +75105,7 @@ usage: loki "<task>" [--no-pr] [--deep] [--json] [--verbose] [--quiet] [--max-co
74882
75105
  const reqOnce = async (evs) => {
74883
75106
  if (reqMap === undefined) {
74884
75107
  const rq2 = await Promise.resolve().then(() => (init_contract(), exports_contract));
74885
- reqMap = rq2.writeFromEngine10(repoDir, join114(repoDir, ".loki"), runDir, isIssue ? null : task, evs);
75108
+ reqMap = rq2.writeFromEngine10(repoDir, join115(repoDir, ".loki"), runDir, isIssue ? null : task, evs);
74886
75109
  }
74887
75110
  return reqMap;
74888
75111
  };
@@ -74892,6 +75115,7 @@ usage: loki "<task>" [--no-pr] [--deep] [--json] [--verbose] [--quiet] [--max-co
74892
75115
  if (e10.type === "stage.completed" && e10.stage === "plan")
74893
75116
  statusStep();
74894
75117
  }, { intervalMs: 500 }) : () => {};
75118
+ let refusedAs = "other";
74895
75119
  const res = await runSupervisor({
74896
75120
  runId: runId2,
74897
75121
  repoDir,
@@ -74945,7 +75169,7 @@ usage: loki "<task>" [--no-pr] [--deep] [--json] [--verbose] [--quiet] [--max-co
74945
75169
  comment: noPr ? undefined : async ({ issueRef, reason, prUrl }) => {
74946
75170
  const { DEFAULT_PUSH_SH: DEFAULT_PUSH_SH2 } = await Promise.resolve().then(() => (init_pr(), exports_pr));
74947
75171
  mkdirSync63(runDir, { recursive: true });
74948
- const bodyFile = join114(runDir, "backstop-comment.md");
75172
+ const bodyFile = join115(runDir, "backstop-comment.md");
74949
75173
  writeFileSync60(bodyFile, `<!-- loki-backstop -->
74950
75174
  Loki 10 run ${runId2} ${prUrl ? `opened draft PR ${prUrl}` : "ended without a PR"}.
74951
75175
 
@@ -74960,6 +75184,7 @@ ${prUrl ? "One question" : "Reason"}: ${reason}
74960
75184
  throw e10;
74961
75185
  process.stderr.write(`${e10.message}
74962
75186
  `);
75187
+ refusedAs = e10.blocker;
74963
75188
  return null;
74964
75189
  });
74965
75190
  clearInterval(tailTimer);
@@ -74967,12 +75192,14 @@ ${prUrl ? "One question" : "Reason"}: ${reason}
74967
75192
  if (!res) {
74968
75193
  stopTail();
74969
75194
  liveStop();
75195
+ noteRefusal(refusedAs);
74970
75196
  return 2;
74971
75197
  }
74972
75198
  await new Promise((r) => setTimeout(r, 300));
74973
75199
  stopTail();
74974
75200
  liveStop();
74975
75201
  const events2 = readEvents(eventsPath), f = fold(events2);
75202
+ noteRefusalFromEvents(events2);
74976
75203
  const sawCost = events2.some((e10) => e10.type === "cost"), cli = process.env.LOKI_E10_INVOKER === "cli";
74977
75204
  const { usd, pc: pc2 } = summaryCost(events2, res.tampered);
74978
75205
  const out3 = json2 ? `${JSON.stringify({ ok: EXIT[res.outcome] === 0, outcome: res.outcome, stop: res.stop, run_id: runId2, receipt_sha256: res.receiptSha })}
@@ -75007,7 +75234,7 @@ ${prUrl ? "One question" : "Reason"}: ${reason}
75007
75234
  const rr2 = resultOf(res.outcome);
75008
75235
  if (res.outcome === "BUDGET_STOP" && cap.usd > 0)
75009
75236
  writeBudgetStop(repoDir, runId2, { task: task.trim(), cap_usd: cap.usd, spent_usd: seed + (usd ?? 0), source: cap.source });
75010
- const ui2 = { result: rr2, filesChanged: ds2?.files ?? null, insertions: ds2?.ins, deletions: ds2?.del, costUsd: usd, elapsedS: Number(f.run.completed?.data.wall_s ?? (Date.now() - t02) / 1000), receiptPath: res.receiptSha ? join114(runDir, "receipt.json") : null, next: res.outcome === "BUDGET_STOP" && cap.usd > 0 ? budgetNext(seed + (usd ?? 0), cap.usd) : nextOf(rr2, ds2?.files ?? null, reasonOf(events2, res.tampered, res.stop, res.outcome), provider, runId2), uncovered };
75237
+ const ui2 = { result: rr2, filesChanged: ds2?.files ?? null, insertions: ds2?.ins, deletions: ds2?.del, costUsd: usd, elapsedS: Number(f.run.completed?.data.wall_s ?? (Date.now() - t02) / 1000), receiptPath: res.receiptSha ? join115(runDir, "receipt.json") : null, next: res.outcome === "BUDGET_STOP" && cap.usd > 0 ? budgetNext(seed + (usd ?? 0), cap.usd) : nextOf(rr2, ds2?.files ?? null, reasonOf(events2, res.tampered, res.stop, res.outcome), provider, runId2), uncovered };
75011
75238
  const rdy = events2.find((e10) => e10.type === "stage.completed" && e10.stage === "intake")?.data.readiness, foldTail = [handoffRef, typeof rdy === "string" ? rdy : ""].filter(Boolean).join("; ");
75012
75239
  const riskLine = readRiskSummary(repoDir, t02);
75013
75240
  process.stdout.write(json2 ? `${JSON.stringify({ ...JSON.parse(out3), summary: { ...summaryObject(ui2), ...riskLine ? { risk: riskLine } : {} } })}
@@ -75046,6 +75273,7 @@ var init_supervisor = __esm(() => {
75046
75273
  init_worker_proc();
75047
75274
  init_intent_card();
75048
75275
  init_preflight();
75276
+ init_funnel();
75049
75277
  init_session();
75050
75278
  init_failure_memory();
75051
75279
  init_model_downgrades();
@@ -75062,8 +75290,8 @@ var init_supervisor = __esm(() => {
75062
75290
  });
75063
75291
 
75064
75292
  // ../../loki-ts/src/e10ext/compound_match.ts
75065
- import { readFileSync as readFileSync99 } from "fs";
75066
- import { basename as basename29, join as join115 } from "path";
75293
+ import { readFileSync as readFileSync100 } from "fs";
75294
+ import { basename as basename29, join as join116 } from "path";
75067
75295
  function parts(s) {
75068
75296
  return s.replace(/([a-z0-9])([A-Z])/g, "$1 $2").toLowerCase().match(/[a-z0-9]+/g) ?? [];
75069
75297
  }
@@ -75090,7 +75318,7 @@ function linkedHits(word, repoMap, testMap, repoDir) {
75090
75318
  continue;
75091
75319
  let body;
75092
75320
  try {
75093
- body = importLines(readFileSync99(join115(repoDir, t.path), "utf8"));
75321
+ body = importLines(readFileSync100(join116(repoDir, t.path), "utf8"));
75094
75322
  } catch {
75095
75323
  continue;
75096
75324
  }
@@ -75111,8 +75339,8 @@ var init_compound_match = __esm(() => {
75111
75339
  });
75112
75340
 
75113
75341
  // ../../loki-ts/src/util/already_done_evidence.ts
75114
- import { existsSync as existsSync81, readFileSync as readFileSync100 } from "fs";
75115
- import { basename as basename30, join as join116 } from "path";
75342
+ import { existsSync as existsSync81, readFileSync as readFileSync101 } from "fs";
75343
+ import { basename as basename30, join as join117 } from "path";
75116
75344
  function keywords2(task) {
75117
75345
  const words3 = task.toLowerCase().match(/[a-z0-9_]+/g) ?? [];
75118
75346
  return Array.from(new Set(words3.filter((w) => w.length > 2 && !STOP_WORDS.has(w))));
@@ -75144,7 +75372,7 @@ function docEvidence(words3, repoDir) {
75144
75372
  for (const name of DOC_FILES) {
75145
75373
  let text4;
75146
75374
  try {
75147
- text4 = readFileSync100(join116(repoDir, name), "utf8");
75375
+ text4 = readFileSync101(join117(repoDir, name), "utf8");
75148
75376
  } catch {
75149
75377
  continue;
75150
75378
  }
@@ -75206,7 +75434,7 @@ function citesToken(text4, token) {
75206
75434
  function citesRealHit(text4, hit, repoDir) {
75207
75435
  if (hit.source === "changelog")
75208
75436
  return false;
75209
- return (citesToken(text4, hit.path) || citesToken(text4, basename30(hit.path))) && existsSync81(join116(repoDir, hit.path));
75437
+ return (citesToken(text4, hit.path) || citesToken(text4, basename30(hit.path))) && existsSync81(join117(repoDir, hit.path));
75210
75438
  }
75211
75439
  function renderAlreadyDoneComment(evidence) {
75212
75440
  return ["Loki 10: no change needed. This already appears to be implemented.", "", "Evidence:", ...evidence.map((e10) => `- ${e10}`), ""].join(`
@@ -75408,9 +75636,9 @@ __export(exports_warm, {
75408
75636
  WarmEngine: () => WarmEngine
75409
75637
  });
75410
75638
  import { createHash as createHash33 } from "crypto";
75411
- import { existsSync as existsSync82, mkdirSync as mkdirSync64, readFileSync as readFileSync101, statSync as statSync32, unlinkSync as unlinkSync11 } from "fs";
75639
+ import { existsSync as existsSync82, mkdirSync as mkdirSync64, readFileSync as readFileSync102, statSync as statSync32, unlinkSync as unlinkSync11 } from "fs";
75412
75640
  import { createServer as createServer2 } from "net";
75413
- import { dirname as dirname45, resolve as resolve37 } from "path";
75641
+ import { dirname as dirname46, resolve as resolve37 } from "path";
75414
75642
  function speedEnabled() {
75415
75643
  return process.env["LOKI_SPEED"] !== "0";
75416
75644
  }
@@ -75438,7 +75666,7 @@ function dirtyHash(repoDir) {
75438
75666
  try {
75439
75667
  const p = resolve37(repoDir, rel);
75440
75668
  if (existsSync82(p) && statSync32(p).isFile() && statSync32(p).size <= MAX_HASHED_BYTES)
75441
- h10.update(readFileSync101(p));
75669
+ h10.update(readFileSync102(p));
75442
75670
  } catch {}
75443
75671
  }
75444
75672
  return h10.digest("hex");
@@ -75491,7 +75719,7 @@ function startWarmIfEnabled() {
75491
75719
  }
75492
75720
  }
75493
75721
  function startWarmServer(path = warmSocketPath(), engine = new WarmEngine) {
75494
- mkdirSync64(dirname45(path), { recursive: true });
75722
+ mkdirSync64(dirname46(path), { recursive: true });
75495
75723
  try {
75496
75724
  unlinkSync11(path);
75497
75725
  } catch {}
@@ -75550,7 +75778,7 @@ var init_warm = __esm(() => {
75550
75778
  import { execFile as execFile3 } from "child_process";
75551
75779
  import { mkdirSync as mkdirSync65, mkdtempSync as mkdtempSync16, rmSync as rmSync34 } from "fs";
75552
75780
  import { tmpdir as tmpdir20 } from "os";
75553
- import { join as join117 } from "path";
75781
+ import { join as join118 } from "path";
75554
75782
  function hitsUnchangedFromBase(repoDir, baseSha, paths) {
75555
75783
  if (paths.length === 0 || !baseSha)
75556
75784
  return false;
@@ -75588,23 +75816,23 @@ function dropRoot(root) {
75588
75816
  function pinBaseTree(ctx, signal) {
75589
75817
  let root;
75590
75818
  try {
75591
- root = mkdtempSync16(join117(tmpdir20(), "loki-already-done-"));
75819
+ root = mkdtempSync16(join118(tmpdir20(), "loki-already-done-"));
75592
75820
  } catch {
75593
75821
  return Promise.resolve(null);
75594
75822
  }
75595
75823
  trackRoot(root);
75596
75824
  try {
75597
- mkdirSync65(join117(root, "tree"));
75825
+ mkdirSync65(join118(root, "tree"));
75598
75826
  } catch {
75599
75827
  dropRoot(root);
75600
75828
  return Promise.resolve(null);
75601
75829
  }
75602
- const tarball = join117(root, "base.tar");
75830
+ const tarball = join118(root, "base.tar");
75603
75831
  const step = (cmd2, args, cwd) => new Promise((res) => {
75604
75832
  execFile3(cmd2, args, { env: process.env, signal, cwd }, (err) => res(!err));
75605
75833
  });
75606
75834
  return (async () => {
75607
- if (!ctx.baseSha || (await safeGitRun(ctx.repoDir, ["archive", "-o", tarball, ctx.baseSha], { signal })).exitCode !== 0 || !await step("tar", ["-x", "-f", tarball, "-C", join117(root, "tree")], root)) {
75835
+ if (!ctx.baseSha || (await safeGitRun(ctx.repoDir, ["archive", "-o", tarball, ctx.baseSha], { signal })).exitCode !== 0 || !await step("tar", ["-x", "-f", tarball, "-C", join118(root, "tree")], root)) {
75608
75836
  dropRoot(root);
75609
75837
  return null;
75610
75838
  }
@@ -75662,7 +75890,7 @@ function deferAlreadyDone(ctx, signal, task, repoMap, testMap, apply) {
75662
75890
  if (!root)
75663
75891
  return;
75664
75892
  try {
75665
- const r = await checkAlreadyDone({ ...ctx, repoDir: join117(root, "tree"), sessions: inner }, check.signal, task, repoMap, testMap);
75893
+ const r = await checkAlreadyDone({ ...ctx, repoDir: join118(root, "tree"), sessions: inner }, check.signal, task, repoMap, testMap);
75666
75894
  const ph = phase;
75667
75895
  if (r && ph !== "done" && !check.signal.aborted) {
75668
75896
  hit = r;
@@ -75688,8 +75916,8 @@ __export(exports_intake, {
75688
75916
  stage: () => stage8,
75689
75917
  runIntake: () => runIntake
75690
75918
  });
75691
- import { appendFileSync as appendFileSync14, existsSync as existsSync83, mkdirSync as mkdirSync66, readFileSync as readFileSync102, writeFileSync as writeFileSync61 } from "fs";
75692
- import { dirname as dirname46, join as join118, resolve as resolve38 } from "path";
75919
+ import { appendFileSync as appendFileSync14, existsSync as existsSync83, mkdirSync as mkdirSync66, readFileSync as readFileSync103, writeFileSync as writeFileSync61 } from "fs";
75920
+ import { dirname as dirname47, join as join119, resolve as resolve38 } from "path";
75693
75921
  function issueRefOf(raw2) {
75694
75922
  return typeof raw2.repo === "string" && raw2.repo && typeof raw2.number === "number" ? `${raw2.repo}#${raw2.number}` : null;
75695
75923
  }
@@ -75709,15 +75937,15 @@ function ensureBranch(repoDir, branch, from) {
75709
75937
  }
75710
75938
  }
75711
75939
  function excludeLokiDir(repoDir) {
75712
- let path = join118(repoDir, ".git", "info", "exclude");
75940
+ let path = join119(repoDir, ".git", "info", "exclude");
75713
75941
  try {
75714
75942
  path = resolve38(repoDir, git13(repoDir, ["rev-parse", "--git-path", "info/exclude"]));
75715
75943
  } catch {}
75716
- const existing = existsSync83(path) ? readFileSync102(path, "utf8") : "";
75944
+ const existing = existsSync83(path) ? readFileSync103(path, "utf8") : "";
75717
75945
  if (existing.split(`
75718
75946
  `).some((l) => l.trim() === ".loki/"))
75719
75947
  return;
75720
- mkdirSync66(dirname46(path), { recursive: true });
75948
+ mkdirSync66(dirname47(path), { recursive: true });
75721
75949
  const sep20 = existing.length > 0 && !existing.endsWith(`
75722
75950
  `) ? `
75723
75951
  ` : "";
@@ -75725,7 +75953,7 @@ function excludeLokiDir(repoDir) {
75725
75953
  `);
75726
75954
  }
75727
75955
  function loadIssue(path) {
75728
- const raw2 = JSON.parse(readFileSync102(path, "utf8"));
75956
+ const raw2 = JSON.parse(readFileSync103(path, "utf8"));
75729
75957
  return { state: typeof raw2.state === "string" ? raw2.state.toLowerCase() : null, closed_by_merged_pr: raw2.closed_by_merged_pr === true };
75730
75958
  }
75731
75959
  function isAlreadyDone(issue) {
@@ -75756,7 +75984,7 @@ async function runIntakeBody(ctx, signal, opts, held) {
75756
75984
  return { status: "failed", data: {}, reason: "aborted before intake started" };
75757
75985
  const { blocking: dirty, preexisting } = splitDirty(ctx.repoDir, dirtyTrackedFiles(ctx.repoDir));
75758
75986
  if (dirty.length > 0)
75759
- return { status: "failed", data: {}, reason: `dirty tracked tree: ${dirty.join(", ")}` };
75987
+ return { status: "failed", data: { blocker: "dirty_tracked_tree" }, reason: `dirty tracked tree: ${dirty.join(", ")}` };
75760
75988
  let baseSha = git13(ctx.repoDir, ["rev-parse", "HEAD"]);
75761
75989
  const startBranch = git13(ctx.repoDir, ["symbolic-ref", "-q", "--short", "HEAD"]);
75762
75990
  let stacked = stackedOnLokiRun(ctx.repoDir);
@@ -75775,7 +76003,7 @@ async function runIntakeBody(ctx, signal, opts, held) {
75775
76003
  ensureBranch(ctx.repoDir, ctx.branch);
75776
76004
  const tree = git13(ctx.repoDir, ["rev-parse", "HEAD^{tree}"]);
75777
76005
  excludeLokiDir(ctx.repoDir);
75778
- const issueJsonPath = opts.issueJsonPath ?? process.env.LOKI_E10_ISSUE_JSON ?? join118(ctx.runDir, "issue.json");
76006
+ const issueJsonPath = opts.issueJsonPath ?? process.env.LOKI_E10_ISSUE_JSON ?? join119(ctx.runDir, "issue.json");
75779
76007
  const taskText = opts.taskText ?? process.env.LOKI_E10_TASK_TEXT;
75780
76008
  let source;
75781
76009
  let taskSha256;
@@ -75784,7 +76012,7 @@ async function runIntakeBody(ctx, signal, opts, held) {
75784
76012
  let issueRef = null;
75785
76013
  if (existsSync83(issueJsonPath)) {
75786
76014
  source = "issue";
75787
- const raw2 = readFileSync102(issueJsonPath, "utf8");
76015
+ const raw2 = readFileSync103(issueJsonPath, "utf8");
75788
76016
  taskSha256 = sha2562(raw2);
75789
76017
  const i = JSON.parse(raw2);
75790
76018
  task = [i.title, i.body].filter((x3) => typeof x3 === "string" && x3 !== "").join(`
@@ -75805,7 +76033,7 @@ async function runIntakeBody(ctx, signal, opts, held) {
75805
76033
  return { status: "completed", data: { ...common, task_sha256: taskSha256, source, base_sha: baseSha, tree, branch: ctx.branch, already_satisfied: true } };
75806
76034
  }
75807
76035
  mkdirSync66(ctx.runDir, { recursive: true });
75808
- const repomapRef = join118(ctx.runDir, "repomap.json");
76036
+ const repomapRef = join119(ctx.runDir, "repomap.json");
75809
76037
  const cacheDir = repoCacheDir(repoKey(null, ctx.repoDir));
75810
76038
  const repoMap = cachedRepoMap(cacheDir, tree, () => buildRepoMap(ctx.repoDir));
75811
76039
  writeFileSync61(repomapRef, JSON.stringify(repoMap));
@@ -75826,7 +76054,7 @@ async function runIntakeBody(ctx, signal, opts, held) {
75826
76054
  const already = speedEnabled() ? null : await checkAlreadyDone(ctx, signal, task, repoMap, testmap);
75827
76055
  const alreadyData = (already2) => {
75828
76056
  const comment = renderAlreadyDoneComment(already2.evidence);
75829
- const bodyFile = join118(ctx.runDir, "already-done-comment.md");
76057
+ const bodyFile = join119(ctx.runDir, "already-done-comment.md");
75830
76058
  writeFileSync61(bodyFile, comment, "utf8");
75831
76059
  const commentArgv = source === "issue" && issueRef ? buildAlreadyDoneCommentArgv(ctx.runId, issueRef, bodyFile) : undefined;
75832
76060
  return { already_satisfied: true, evidence: already2.evidence, iteration_ids: [`${ctx.runId}-already-done`], comment, ...commentArgv ? { comment_argv: commentArgv } : {} };
@@ -76020,7 +76248,7 @@ __export(exports_keys_cmd, {
76020
76248
  takePubkey: () => takePubkey,
76021
76249
  main: () => main5
76022
76250
  });
76023
- import { readFileSync as readFileSync103 } from "fs";
76251
+ import { readFileSync as readFileSync104 } from "fs";
76024
76252
  import { parseArgs } from "util";
76025
76253
  import { createPublicKey as createPublicKey4 } from "crypto";
76026
76254
  function takePubkey(args) {
@@ -76033,7 +76261,7 @@ function takePubkey(args) {
76033
76261
  return { args: rest };
76034
76262
  if (!(file = pubkey[0]))
76035
76263
  throw new Error("--pubkey requires a file argument");
76036
- const t = readFileSync103(file, "utf8"), key = createPublicKey4(t.trim().startsWith("{") ? { key: JSON.parse(t), format: "jwk" } : t);
76264
+ const t = readFileSync104(file, "utf8"), key = createPublicKey4(t.trim().startsWith("{") ? { key: JSON.parse(t), format: "jwk" } : t);
76037
76265
  return key.asymmetricKeyType === "ed25519" ? { args: rest, pubkey: key } : { args: rest, error: `cannot read an Ed25519 public key from ${file}` };
76038
76266
  } catch (e10) {
76039
76267
  return { args: [], error: file ? `cannot read an Ed25519 public key from ${file}` : e10.message.replace(/^./, (c) => c.toLowerCase()) };
@@ -76291,7 +76519,7 @@ var groupRoute = async (repoDir, rawGroup) => {
76291
76519
  };
76292
76520
 
76293
76521
  // ../../loki-ts/src/engine10/modernize/types.ts
76294
- import { join as join119 } from "path";
76522
+ import { join as join120 } from "path";
76295
76523
  function makeModernizeId(now2 = new Date) {
76296
76524
  const utc = now2.toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "Z");
76297
76525
  const short = Math.floor(Math.random() * 16777215).toString(16).padStart(6, "0");
@@ -76301,13 +76529,13 @@ function isModernizeId(mid) {
76301
76529
  return MID_RE.test(mid);
76302
76530
  }
76303
76531
  function modernizeRoot(repoDir, mid) {
76304
- return join119(repoDir, ".loki", "modernize", mid);
76532
+ return join120(repoDir, ".loki", "modernize", mid);
76305
76533
  }
76306
76534
  function modernizeEventsPath(repoDir, mid) {
76307
- return join119(modernizeRoot(repoDir, mid), "events.jsonl");
76535
+ return join120(modernizeRoot(repoDir, mid), "events.jsonl");
76308
76536
  }
76309
76537
  function planPath(repoDir, mid) {
76310
- return join119(modernizeRoot(repoDir, mid), "plan.json");
76538
+ return join120(modernizeRoot(repoDir, mid), "plan.json");
76311
76539
  }
76312
76540
  function isSafeUnitId(unit) {
76313
76541
  return typeof unit === "string" && unit.length <= MAX_UNIT_ID && UNIT_ID_RE2.test(unit) && !unit.includes("..");
@@ -76318,13 +76546,13 @@ function encodeUnitId(unit) {
76318
76546
  return unit.replace(/\//g, "%2F");
76319
76547
  }
76320
76548
  function oracleDir(repoDir, mid, unit) {
76321
- return join119(modernizeRoot(repoDir, mid), "oracle", encodeUnitId(unit));
76549
+ return join120(modernizeRoot(repoDir, mid), "oracle", encodeUnitId(unit));
76322
76550
  }
76323
76551
  function reportJsonPath(repoDir, mid) {
76324
- return join119(modernizeRoot(repoDir, mid), "report.json");
76552
+ return join120(modernizeRoot(repoDir, mid), "report.json");
76325
76553
  }
76326
76554
  function reportMdPath(repoDir, mid) {
76327
- return join119(modernizeRoot(repoDir, mid), "report.md");
76555
+ return join120(modernizeRoot(repoDir, mid), "report.md");
76328
76556
  }
76329
76557
  var MID_RE, UNIT_ID_SEGMENT = "[A-Za-z0-9][A-Za-z0-9_.-]*", UNIT_ID_RE2, MAX_UNIT_ID = 128;
76330
76558
  var init_types2 = __esm(() => {
@@ -76364,9 +76592,9 @@ __export(exports_dashboard, {
76364
76592
  listModernizeIds: () => listModernizeIds
76365
76593
  });
76366
76594
  import { existsSync as existsSync84, readdirSync as readdirSync36 } from "fs";
76367
- import { join as join120 } from "path";
76595
+ import { join as join121 } from "path";
76368
76596
  function modernizeDir(repoDir) {
76369
- return join120(repoDir, ".loki", "modernize");
76597
+ return join121(repoDir, ".loki", "modernize");
76370
76598
  }
76371
76599
  function listModernizeIds(repoDir) {
76372
76600
  const dir = modernizeDir(repoDir);
@@ -76701,11 +76929,11 @@ var init_engine10_dashboard = __esm(() => {
76701
76929
  });
76702
76930
 
76703
76931
  // ../../loki-ts/src/engine10/modernize/inventory.ts
76704
- import { readFileSync as readFileSync104 } from "fs";
76705
- import { extname as extname4, join as join121 } from "path";
76932
+ import { readFileSync as readFileSync105 } from "fs";
76933
+ import { extname as extname4, join as join122 } from "path";
76706
76934
  function readCapped2(absPath) {
76707
76935
  try {
76708
- return readFileSync104(absPath, "utf8").slice(0, MAX_SCAN_BYTES2);
76936
+ return readFileSync105(absPath, "utf8").slice(0, MAX_SCAN_BYTES2);
76709
76937
  } catch {
76710
76938
  return "";
76711
76939
  }
@@ -76722,9 +76950,9 @@ function detectEntryPoints(repoDir, files) {
76722
76950
  const out3 = [];
76723
76951
  for (const rel of files) {
76724
76952
  const ext = extname4(rel);
76725
- if (ext === ".py" && PY_MAIN_RE.test(readCapped2(join121(repoDir, rel))))
76953
+ if (ext === ".py" && PY_MAIN_RE.test(readCapped2(join122(repoDir, rel))))
76726
76954
  out3.push(rel);
76727
- else if (ext === ".java" && JAVA_MAIN_RE.test(readCapped2(join121(repoDir, rel))))
76955
+ else if (ext === ".java" && JAVA_MAIN_RE.test(readCapped2(join122(repoDir, rel))))
76728
76956
  out3.push(rel);
76729
76957
  }
76730
76958
  return out3;
@@ -76774,7 +77002,7 @@ var init_inventory = __esm(() => {
76774
77002
  });
76775
77003
 
76776
77004
  // ../../loki-ts/src/engine10/modernize/lang/python.ts
76777
- import { join as join122 } from "path";
77005
+ import { join as join123 } from "path";
76778
77006
  async function buildPythonGraph(repoDir, files, opts = {}) {
76779
77007
  if (files.length === 0)
76780
77008
  return { graph: { nodes: [], edges: [] }, unresolved: [] };
@@ -76813,7 +77041,7 @@ var init_python2 = __esm(() => {
76813
77041
  init_paths();
76814
77042
  init_python();
76815
77043
  init_shell();
76816
- SCRIPT = join122(REPO_ROOT, "autonomy", "lib", "modernize", "py_imports.py");
77044
+ SCRIPT = join123(REPO_ROOT, "autonomy", "lib", "modernize", "py_imports.py");
76817
77045
  });
76818
77046
 
76819
77047
  // ../../loki-ts/src/engine10/modernize/cluster.ts
@@ -76992,8 +77220,8 @@ var init_codemod = __esm(() => {
76992
77220
 
76993
77221
  // ../../loki-ts/src/engine10/modernize/oracle/seal.ts
76994
77222
  import { createHash as createHash34 } from "crypto";
76995
- import { existsSync as existsSync85, mkdirSync as mkdirSync67, readFileSync as readFileSync105, writeFileSync as writeFileSync62 } from "fs";
76996
- import { join as join123 } from "path";
77223
+ import { existsSync as existsSync85, mkdirSync as mkdirSync67, readFileSync as readFileSync106, writeFileSync as writeFileSync62 } from "fs";
77224
+ import { join as join124 } from "path";
76997
77225
  function normalizersSha(n11) {
76998
77226
  return sha2564(JSON.stringify({
76999
77227
  float_tolerance: n11.float_tolerance,
@@ -77055,9 +77283,9 @@ function alreadySealedInLog(repoDir, mid, unit) {
77055
77283
  }
77056
77284
  function sealOracle(repoDir, mid, unit, log, normalizers = DEFAULT_NORMALIZERS) {
77057
77285
  const dir = oracleDir(repoDir, mid, unit);
77058
- const casesPath = join123(dir, "cases.jsonl");
77059
- const coveragePath = join123(dir, "coverage.json");
77060
- const sealedPath = join123(dir, "sealed.json");
77286
+ const casesPath = join124(dir, "cases.jsonl");
77287
+ const coveragePath = join124(dir, "coverage.json");
77288
+ const sealedPath = join124(dir, "sealed.json");
77061
77289
  if (alreadySealedInLog(repoDir, mid, unit)) {
77062
77290
  throw new Error(`oracle seal: ${unit} already has a sealing event in the modernize log; re-seal refused (seal is write-once)`);
77063
77291
  }
@@ -77068,8 +77296,8 @@ function sealOracle(repoDir, mid, unit, log, normalizers = DEFAULT_NORMALIZERS)
77068
77296
  throw new Error(`oracle seal: missing ${casesPath}`);
77069
77297
  if (!existsSync85(coveragePath))
77070
77298
  throw new Error(`oracle seal: missing ${coveragePath}`);
77071
- const casesRaw = readFileSync105(casesPath, "utf8");
77072
- const coverageRaw = readFileSync105(coveragePath, "utf8");
77299
+ const casesRaw = readFileSync106(casesPath, "utf8");
77300
+ const coverageRaw = readFileSync106(coveragePath, "utf8");
77073
77301
  const normalizersHash = normalizersSha(normalizers);
77074
77302
  const sealed = buildSealedOracle(unit, casesRaw, coverageRaw, normalizersHash);
77075
77303
  mkdirSync67(dir, { recursive: true });
@@ -77088,9 +77316,9 @@ function sealOracle(repoDir, mid, unit, log, normalizers = DEFAULT_NORMALIZERS)
77088
77316
  }
77089
77317
  function verifySeal(repoDir, mid, unit) {
77090
77318
  const dir = oracleDir(repoDir, mid, unit);
77091
- const sealedPath = join123(dir, "sealed.json");
77092
- const casesPath = join123(dir, "cases.jsonl");
77093
- const coveragePath = join123(dir, "coverage.json");
77319
+ const sealedPath = join124(dir, "sealed.json");
77320
+ const casesPath = join124(dir, "cases.jsonl");
77321
+ const coveragePath = join124(dir, "coverage.json");
77094
77322
  if (!existsSync85(sealedPath))
77095
77323
  return { ok: false, reason: "no sealed.json" };
77096
77324
  if (!existsSync85(casesPath))
@@ -77101,11 +77329,11 @@ function verifySeal(repoDir, mid, unit) {
77101
77329
  if (!sealEvent) {
77102
77330
  return { ok: false, reason: "no sealing event for this unit in the modernize log; sealed.json is not anchored" };
77103
77331
  }
77104
- const casesRaw = readFileSync105(casesPath, "utf8");
77332
+ const casesRaw = readFileSync106(casesPath, "utf8");
77105
77333
  if (sha2564(casesRaw) !== sealEvent.data.cases_sha256) {
77106
77334
  return { ok: false, reason: "cases.jsonl does not match the sealing event's hash (tampered or re-captured)" };
77107
77335
  }
77108
- const coverageRaw = readFileSync105(coveragePath, "utf8");
77336
+ const coverageRaw = readFileSync106(coveragePath, "utf8");
77109
77337
  if (sha2564(coverageRaw) !== sealEvent.data.coverage_sha256) {
77110
77338
  return { ok: false, reason: "coverage.json does not match the sealing event's hash (tampered or re-captured)" };
77111
77339
  }
@@ -77121,7 +77349,7 @@ function verifySeal(repoDir, mid, unit) {
77121
77349
  reason: `verdict does not match the sealing event (event type ${sealEvent.type}, recomputed verdict ${recomputed.verdict})`
77122
77350
  };
77123
77351
  }
77124
- const sealed = JSON.parse(readFileSync105(sealedPath, "utf8"));
77352
+ const sealed = JSON.parse(readFileSync106(sealedPath, "utf8"));
77125
77353
  if (JSON.stringify(sealed) !== JSON.stringify(recomputed)) {
77126
77354
  return { ok: false, reason: "sealed.json does not match the record recomputed from cases.jsonl and coverage.json (hand-edited)" };
77127
77355
  }
@@ -77137,9 +77365,9 @@ var init_seal2 = __esm(() => {
77137
77365
 
77138
77366
  // ../../loki-ts/src/engine10/modernize/oracle/search.ts
77139
77367
  import { spawnSync as spawnSync18 } from "child_process";
77140
- import { copyFileSync as copyFileSync6, existsSync as existsSync86, linkSync as linkSync4, mkdirSync as mkdirSync68, mkdtempSync as mkdtempSync17, readFileSync as readFileSync106, renameSync as renameSync22, rmSync as rmSync35, rmdirSync as rmdirSync2, writeFileSync as writeFileSync63 } from "fs";
77368
+ import { copyFileSync as copyFileSync6, existsSync as existsSync86, linkSync as linkSync4, mkdirSync as mkdirSync68, mkdtempSync as mkdtempSync17, readFileSync as readFileSync107, renameSync as renameSync22, rmSync as rmSync35, rmdirSync as rmdirSync2, writeFileSync as writeFileSync63 } from "fs";
77141
77369
  import { tmpdir as tmpdir21 } from "os";
77142
- import { basename as basename31, dirname as dirname47, join as join124 } from "path";
77370
+ import { basename as basename31, dirname as dirname48, join as join125 } from "path";
77143
77371
  function search(unitSource, seedCases, propose, runCapture, opts = {}) {
77144
77372
  const maxRounds = opts.maxRounds ?? 10;
77145
77373
  const plateauLimit = opts.plateauRounds ?? 2;
@@ -77196,10 +77424,10 @@ function realCaptureRunner(unitPath, cases, outPath) {
77196
77424
  return captureFailed("old runtime unavailable");
77197
77425
  let dir = "";
77198
77426
  try {
77199
- dir = mkdtempSync17(join124(tmpdir21(), "m10-search-"));
77200
- const casesFile = join124(dir, "cases.jsonl");
77201
- const outFile = join124(dir, "out.jsonl");
77202
- const covFile = join124(dir, "coverage.json");
77427
+ dir = mkdtempSync17(join125(tmpdir21(), "m10-search-"));
77428
+ const casesFile = join125(dir, "cases.jsonl");
77429
+ const outFile = join125(dir, "out.jsonl");
77430
+ const covFile = join125(dir, "coverage.json");
77203
77431
  const lines2 = cases.map((c) => JSON.stringify({ entry: c.entry, args: c.args, kwargs: c.kwargs }));
77204
77432
  writeFileSync63(casesFile, lines2.length ? lines2.join(`
77205
77433
  `) + `
@@ -77220,7 +77448,7 @@ function realCaptureRunner(unitPath, cases, outPath) {
77220
77448
  `).find((l) => l.trim().length > 0) ?? "(no stderr)";
77221
77449
  return captureFailed(`py_capture.py exit ${r.status}: ${firstErrLine}`);
77222
77450
  }
77223
- const raw2 = JSON.parse(readFileSync106(covFile, "utf8"));
77451
+ const raw2 = JSON.parse(readFileSync107(covFile, "utf8"));
77224
77452
  if (outPath)
77225
77453
  copyFileSync6(outFile, outPath);
77226
77454
  return {
@@ -77247,13 +77475,13 @@ function resolveOldRuntimeSync() {
77247
77475
  }
77248
77476
  function makeProposeInputs(session, cap = 20) {
77249
77477
  return (unitPath, missing, round2) => {
77250
- const cwd = mkdtempSync17(join124(tmpdir21(), "m27-propose-"));
77478
+ const cwd = mkdtempSync17(join125(tmpdir21(), "m27-propose-"));
77251
77479
  try {
77252
- const unitFile = join124(cwd, basename31(unitPath));
77480
+ const unitFile = join125(cwd, basename31(unitPath));
77253
77481
  copyFileSync6(unitPath, unitFile);
77254
77482
  session({ cwd, env: tokenFreeEnv(), unitFile, missing, round: round2 });
77255
77483
  const out3 = [];
77256
- for (const line2 of readFileSync106(join124(cwd, "proposals.jsonl"), "utf8").split(`
77484
+ for (const line2 of readFileSync107(join125(cwd, "proposals.jsonl"), "utf8").split(`
77257
77485
  `)) {
77258
77486
  try {
77259
77487
  const c = JSON.parse(line2);
@@ -77271,7 +77499,7 @@ function makeProposeInputs(session, cap = 20) {
77271
77499
  }
77272
77500
  function captureUnitOracle(a) {
77273
77501
  const dir = oracleDir(a.repoDir, a.mid, a.unit);
77274
- if (existsSync86(join124(dir, "cases.jsonl")) || alreadySealedInLog(a.repoDir, a.mid, a.unit)) {
77502
+ if (existsSync86(join125(dir, "cases.jsonl")) || alreadySealedInLog(a.repoDir, a.mid, a.unit)) {
77275
77503
  return { ok: false, reason: "oracle already captured (write-once)" };
77276
77504
  }
77277
77505
  const run2 = a.runCapture ?? realCaptureRunner;
@@ -77291,21 +77519,21 @@ function captureUnitOracle(a) {
77291
77519
  }
77292
77520
  if (r.cases.length === 0)
77293
77521
  return { ok: false, reason: "no cases captured" };
77294
- const scratch = mkdtempSync17(join124(tmpdir21(), "m27-replay-"));
77295
- const t12 = join124(scratch, "cases"), t22 = join124(scratch, "replay");
77522
+ const scratch = mkdtempSync17(join125(tmpdir21(), "m27-replay-"));
77523
+ const t12 = join125(scratch, "cases"), t22 = join125(scratch, "replay");
77296
77524
  const created = [];
77297
- for (let p = dir;!existsSync86(p) && !created.includes(p); p = dirname47(p))
77525
+ for (let p = dir;!existsSync86(p) && !created.includes(p); p = dirname48(p))
77298
77526
  created.push(p);
77299
- const read2 = (p) => readFileSync106(p, "utf8").split(`
77527
+ const read3 = (p) => readFileSync107(p, "utf8").split(`
77300
77528
  `).filter(Boolean).map((l) => JSON.parse(l));
77301
- const tmpCases = join124(dir, `.cases.${process.pid}.tmp`);
77302
- const tmpCov = join124(dir, `.coverage.${process.pid}.tmp`);
77529
+ const tmpCases = join125(dir, `.cases.${process.pid}.tmp`);
77530
+ const tmpCov = join125(dir, `.coverage.${process.pid}.tmp`);
77303
77531
  try {
77304
77532
  const cov = run2(a.unitPath, r.cases, t12);
77305
77533
  const cov2 = run2(a.unitPath, r.cases, t22);
77306
77534
  if (cov.branchesTotal < 0 || cov2.branchesTotal < 0)
77307
77535
  return { ok: false, reason: cov.error ?? cov2.error ?? "replay failed" };
77308
- const recs = read2(t12), again = read2(t22);
77536
+ const recs = read3(t12), again = read3(t22);
77309
77537
  if (recs.length !== r.cases.length || again.length !== recs.length)
77310
77538
  return { ok: false, reason: "capture records missing" };
77311
77539
  recs.forEach((rec2, i) => {
@@ -77327,10 +77555,10 @@ function captureUnitOracle(a) {
77327
77555
  branch_pct: cov.branchPct,
77328
77556
  missing: cov.missing
77329
77557
  }));
77330
- if (existsSync86(join124(dir, "cases.jsonl")))
77558
+ if (existsSync86(join125(dir, "cases.jsonl")))
77331
77559
  return { ok: false, reason: "oracle already captured (write-once)" };
77332
- renameSync22(tmpCov, join124(dir, "coverage.json"));
77333
- (a.link ?? linkSync4)(tmpCases, join124(dir, "cases.jsonl"));
77560
+ renameSync22(tmpCov, join125(dir, "coverage.json"));
77561
+ (a.link ?? linkSync4)(tmpCases, join125(dir, "cases.jsonl"));
77334
77562
  return { ok: true, cases: r.cases.length, branchPct: cov.branchPct, stoppedReason: r.stoppedReason };
77335
77563
  } catch (e10) {
77336
77564
  return { ok: false, reason: `capture error: ${e10 instanceof Error ? e10.message : String(e10)}` };
@@ -77338,8 +77566,8 @@ function captureUnitOracle(a) {
77338
77566
  rmSync35(scratch, { recursive: true, force: true });
77339
77567
  for (const t of [tmpCases, tmpCov])
77340
77568
  rmSync35(t, { force: true });
77341
- if (created[0] === dir && !existsSync86(join124(dir, "cases.jsonl")))
77342
- rmSync35(join124(dir, "coverage.json"), { force: true });
77569
+ if (created[0] === dir && !existsSync86(join125(dir, "cases.jsonl")))
77570
+ rmSync35(join125(dir, "coverage.json"), { force: true });
77343
77571
  for (const p of created) {
77344
77572
  try {
77345
77573
  rmdirSync2(p);
@@ -77355,12 +77583,12 @@ var init_search = __esm(() => {
77355
77583
  init_safe_git();
77356
77584
  init_types2();
77357
77585
  init_seal2();
77358
- PY_CAPTURE_SCRIPT = join124(REPO_ROOT, "autonomy", "lib", "modernize", "py_capture.py");
77586
+ PY_CAPTURE_SCRIPT = join125(REPO_ROOT, "autonomy", "lib", "modernize", "py_capture.py");
77359
77587
  });
77360
77588
 
77361
77589
  // ../../loki-ts/src/engine10/modernize/equiv.ts
77362
- import { readFileSync as readFileSync107 } from "fs";
77363
- import { join as join125 } from "path";
77590
+ import { readFileSync as readFileSync108 } from "fs";
77591
+ import { join as join126 } from "path";
77364
77592
  function parseCases(raw2) {
77365
77593
  const out3 = [];
77366
77594
  for (const line2 of raw2.split(`
@@ -77555,11 +77783,11 @@ function checkEquivalence(repoDir, mid, unit, newTreeDir, normalizers, runNew, l
77555
77783
  return notProvenResult(unit, "normalizers invalid: skip_fields covers every field, nothing would be compared", log);
77556
77784
  }
77557
77785
  const dir = oracleDir(repoDir, mid, unit);
77558
- const sealed = JSON.parse(readFileSync107(join125(dir, "sealed.json"), "utf8"));
77786
+ const sealed = JSON.parse(readFileSync108(join126(dir, "sealed.json"), "utf8"));
77559
77787
  const normCheck = verifyNormalizersAgainstSeal(sealed, normalizers);
77560
77788
  if (!normCheck.ok)
77561
77789
  return notProvenResult(unit, `normalizers: ${normCheck.reason ?? "check failed"}`, log);
77562
- const records = parseCases(readFileSync107(join125(dir, "cases.jsonl"), "utf8"));
77790
+ const records = parseCases(readFileSync108(join126(dir, "cases.jsonl"), "utf8"));
77563
77791
  const heldOutSet = new Set(sealed.held_out);
77564
77792
  let pass = 0;
77565
77793
  let fail2 = 0;
@@ -77750,7 +77978,7 @@ var init_reslice = __esm(() => {
77750
77978
  });
77751
77979
 
77752
77980
  // ../../loki-ts/src/engine10/modernize/scheduler.ts
77753
- import { join as join126 } from "path";
77981
+ import { join as join127 } from "path";
77754
77982
  function mergeOnce(unit, ops, log, completed, worktree) {
77755
77983
  if (completed.has(unit))
77756
77984
  return "already_completed";
@@ -77871,7 +78099,7 @@ async function schedule(plan, opts) {
77871
78099
  reason = hit ? "budget stop" : "per-unit cost cap reached";
77872
78100
  break;
77873
78101
  }
77874
- const path = join126(modernizeRoot(opts.repoDir, opts.mid), "wt", variant === 0 ? encodeUnitId(unit.id) : `${encodeUnitId(unit.id)}${VARIANT_SEP}${variant}`);
78102
+ const path = join127(modernizeRoot(opts.repoDir, opts.mid), "wt", variant === 0 ? encodeUnitId(unit.id) : `${encodeUnitId(unit.id)}${VARIANT_SEP}${variant}`);
77875
78103
  let outcome;
77876
78104
  attempts++;
77877
78105
  let resumeRunId;
@@ -77980,21 +78208,21 @@ var init_scheduler = __esm(() => {
77980
78208
  });
77981
78209
 
77982
78210
  // ../../loki-ts/src/engine10/modernize/resume.ts
77983
- import { existsSync as existsSync87, readFileSync as readFileSync108 } from "fs";
78211
+ import { existsSync as existsSync87, readFileSync as readFileSync109 } from "fs";
77984
78212
  function loadResumeState(repoDir, mid) {
77985
78213
  const path = modernizeEventsPath(repoDir, mid);
77986
78214
  if (!existsSync87(path))
77987
78215
  return { ok: false, reason: `no modernize log at ${path}` };
77988
78216
  let text4;
77989
78217
  try {
77990
- text4 = readFileSync108(path, "utf8");
78218
+ text4 = readFileSync109(path, "utf8");
77991
78219
  } catch (e10) {
77992
78220
  return { ok: false, reason: `modernize log unreadable: ${e10 instanceof Error ? e10.message : String(e10)}` };
77993
78221
  }
77994
78222
  const pj2 = planPath(repoDir, mid);
77995
78223
  if (existsSync87(pj2)) {
77996
78224
  try {
77997
- JSON.parse(readFileSync108(pj2, "utf8"));
78225
+ JSON.parse(readFileSync109(pj2, "utf8"));
77998
78226
  } catch {
77999
78227
  return { ok: false, reason: `plan.json is corrupt or partial: ${pj2}` };
78000
78228
  }
@@ -78107,8 +78335,8 @@ var init_resume = __esm(() => {
78107
78335
  });
78108
78336
 
78109
78337
  // ../../loki-ts/src/engine10/modernize/report.ts
78110
- import { mkdirSync as mkdirSync69, readFileSync as readFileSync109, writeFileSync as writeFileSync64 } from "fs";
78111
- import { dirname as dirname48 } from "path";
78338
+ import { mkdirSync as mkdirSync69, readFileSync as readFileSync110, writeFileSync as writeFileSync64 } from "fs";
78339
+ import { dirname as dirname49 } from "path";
78112
78340
  function buildReport(o) {
78113
78341
  const units = o.units.map((x3) => ({ unit: x3.unit, verdict: x3.verdict, not_proven: [...x3.not_proven], rate: x3.rate, branchPct: x3.branchPct, receiptPath: x3.receiptPath, receiptSha256: x3.receiptSha256 }));
78114
78342
  const waves = o.waves.map((w) => ({
@@ -78151,7 +78379,7 @@ function renderReportMd(r) {
78151
78379
  function writeReport(o) {
78152
78380
  const sealed = sealReport(buildReport(o), o.sign);
78153
78381
  const jp2 = reportJsonPath(o.repoDir, o.mid);
78154
- mkdirSync69(dirname48(jp2), { recursive: true });
78382
+ mkdirSync69(dirname49(jp2), { recursive: true });
78155
78383
  writeFileSync64(jp2, JSON.stringify(sealed, null, 2) + `
78156
78384
  `, "utf8");
78157
78385
  writeFileSync64(reportMdPath(o.repoDir, o.mid), renderReportMd(sealed), "utf8");
@@ -78168,7 +78396,7 @@ var init_report = __esm(() => {
78168
78396
 
78169
78397
  // ../../loki-ts/src/engine10/modernize/ship.ts
78170
78398
  import { mkdirSync as mkdirSync70, writeFileSync as writeFileSync65 } from "fs";
78171
- import { join as join127 } from "path";
78399
+ import { join as join128 } from "path";
78172
78400
  function waveIsDraft(verdict, units) {
78173
78401
  return verdict === null || verdict.verified !== true || units.length === 0 || units.some((x3) => x3.verdict !== "PROVEN");
78174
78402
  }
@@ -78189,9 +78417,9 @@ function shipWave(o) {
78189
78417
  return fail2("no pinned origin: refusing to push (Rule of Two)");
78190
78418
  if (draft)
78191
78419
  return fail2("wave not verified: branch stays local, not pushed");
78192
- const dir = join127(o.repoDir, ".loki", "modernize", o.mid);
78420
+ const dir = join128(o.repoDir, ".loki", "modernize", o.mid);
78193
78421
  mkdirSync70(dir, { recursive: true });
78194
- const bodyFile = join127(dir, `wave-${o.wave}-pr-body.md`);
78422
+ const bodyFile = join128(dir, `wave-${o.wave}-pr-body.md`);
78195
78423
  writeFileSync65(bodyFile, renderWaveBody(o.wave, o.verdict, o.units), "utf8");
78196
78424
  const r = (o.push ?? runPushPr)({ repoDir: o.repoDir, branch: o.branch, title: `Loki modernize: wave ${o.wave}`, bodyFile, draft, pinnedOrigin });
78197
78425
  if (!r.ok)
@@ -78211,8 +78439,8 @@ var init_ship2 = __esm(() => {
78211
78439
  });
78212
78440
 
78213
78441
  // ../../loki-ts/src/engine10/modernize/presealed_wall.ts
78214
- import { existsSync as existsSync88, mkdirSync as mkdirSync71, readFileSync as readFileSync110, writeFileSync as writeFileSync66 } from "fs";
78215
- import { join as join128 } from "path";
78442
+ import { existsSync as existsSync88, mkdirSync as mkdirSync71, readFileSync as readFileSync111, writeFileSync as writeFileSync66 } from "fs";
78443
+ import { join as join129 } from "path";
78216
78444
  function isRealFailCount(n11) {
78217
78445
  return typeof n11 === "number" && Number.isInteger(n11) && n11 >= 1;
78218
78446
  }
@@ -78235,7 +78463,7 @@ function classifyBaseRun(o, repoDir) {
78235
78463
  return "not_run";
78236
78464
  }
78237
78465
  function preSealedPath(repoDir, mid, unit) {
78238
- return join128(oracleDir(repoDir, mid, unit), "presealed_wall.json");
78466
+ return join129(oracleDir(repoDir, mid, unit), "presealed_wall.json");
78239
78467
  }
78240
78468
  function alreadySealed(repoDir, mid, unit) {
78241
78469
  return readModernizeEvents(repoDir, mid).some((e10) => e10.type === SEALED_EVENT && e10.data.unit === unit);
@@ -78249,7 +78477,7 @@ function sealPreSealedWall(repoDir, mid, unit, target, runConformance, log, base
78249
78477
  if (!oracleCheck.ok)
78250
78478
  return refuse(`oracle seal invalid: ${oracleCheck.reason ?? "unknown"}; presealed wall refused`);
78251
78479
  const dir = oracleDir(repoDir, mid, unit);
78252
- const oracleSealed = JSON.parse(readFileSync110(join128(dir, "sealed.json"), "utf8"));
78480
+ const oracleSealed = JSON.parse(readFileSync111(join129(dir, "sealed.json"), "utf8"));
78253
78481
  if (oracleSealed.verdict !== "PROVEN_ORACLE") {
78254
78482
  return refuse(`oracle seal invalid: oracle is ${oracleSealed.verdict} (${oracleSealed.not_proven ?? "no reason recorded"}); presealed wall refused`);
78255
78483
  }
@@ -78318,7 +78546,7 @@ function verifyPreSealedWall(repoDir, mid, unit) {
78318
78546
  const expectedSha = event.data.sealed_sha256;
78319
78547
  if (typeof expectedSha !== "string")
78320
78548
  return { ok: false, reason: "sealing event has no sealed_sha256" };
78321
- const sealedRaw = readFileSync110(sealedPath, "utf8");
78549
+ const sealedRaw = readFileSync111(sealedPath, "utf8");
78322
78550
  const actualSha = sha2564(sealedRaw);
78323
78551
  if (actualSha !== expectedSha) {
78324
78552
  return { ok: false, reason: "presealed_wall.json does not match the sealing event's hash (tampered or rewritten)" };
@@ -78327,7 +78555,7 @@ function verifyPreSealedWall(repoDir, mid, unit) {
78327
78555
  if (!oracleCheck.ok) {
78328
78556
  return { ok: false, reason: `bound oracle seal is no longer valid: ${oracleCheck.reason ?? "unknown"}` };
78329
78557
  }
78330
- const oracleSealed = JSON.parse(readFileSync110(join128(oracleDir(repoDir, mid, unit), "sealed.json"), "utf8"));
78558
+ const oracleSealed = JSON.parse(readFileSync111(join129(oracleDir(repoDir, mid, unit), "sealed.json"), "utf8"));
78331
78559
  const carried = JSON.parse(sealedRaw);
78332
78560
  if (carried.oracle_cases_sha256 !== oracleSealed.cases_sha256 || carried.oracle_coverage_sha256 !== oracleSealed.coverage_sha256 || typeof carried.oracle_normalizers_sha256 !== "string" || typeof oracleSealed.normalizers_sha256 !== "string" || carried.oracle_normalizers_sha256 !== oracleSealed.normalizers_sha256) {
78333
78561
  return { ok: false, reason: "carried oracle hashes do not match the current oracle seal" };
@@ -78353,9 +78581,9 @@ var init_presealed_wall = __esm(() => {
78353
78581
  // ../../loki-ts/src/engine10/modernize/unit.ts
78354
78582
  import { spawnSync as spawnSync19 } from "child_process";
78355
78583
  import { createHash as createHash35 } from "crypto";
78356
- import { lstatSync as lstatSync29, readFileSync as readFileSync111, readdirSync as readdirSync37, readlinkSync as readlinkSync7, realpathSync as realpathSync33, rmSync as rmSync36 } from "fs";
78584
+ import { lstatSync as lstatSync29, readFileSync as readFileSync112, readdirSync as readdirSync37, readlinkSync as readlinkSync7, realpathSync as realpathSync33, rmSync as rmSync36 } from "fs";
78357
78585
  import { tmpdir as tmpdir22 } from "os";
78358
- import { join as join129, sep as sep20 } from "path";
78586
+ import { join as join130, sep as sep20 } from "path";
78359
78587
  function isSealedName(rel) {
78360
78588
  return TEST_FILE2.test(rel) || PYTEST_CFG.test(rel);
78361
78589
  }
@@ -78370,7 +78598,7 @@ function purgePycache(dir) {
78370
78598
  for (const e10 of ents) {
78371
78599
  if (!e10.isDirectory())
78372
78600
  continue;
78373
- const full = join129(d, e10.name);
78601
+ const full = join130(d, e10.name);
78374
78602
  if (e10.name === "__pycache__")
78375
78603
  rmSync36(full, { recursive: true, force: true });
78376
78604
  else if (!skipName(e10.name))
@@ -78425,13 +78653,13 @@ function outsideTargetDigest(dir, full) {
78425
78653
  }
78426
78654
  for (const n11 of names) {
78427
78655
  h10.update("D" + n11);
78428
- walk(join129(p, n11));
78656
+ walk(join130(p, n11));
78429
78657
  }
78430
78658
  return;
78431
78659
  }
78432
78660
  if (st2.isFile()) {
78433
78661
  try {
78434
- h10.update(readFileSync111(p));
78662
+ h10.update(readFileSync112(p));
78435
78663
  } catch {
78436
78664
  h10.update("unreadable");
78437
78665
  }
@@ -78446,7 +78674,7 @@ function conformanceHashes(dir) {
78446
78674
  const walk = (sub2, inSkip) => {
78447
78675
  let ents;
78448
78676
  try {
78449
- ents = readdirSync37(join129(dir, sub2), { withFileTypes: true });
78677
+ ents = readdirSync37(join130(dir, sub2), { withFileTypes: true });
78450
78678
  } catch {
78451
78679
  return;
78452
78680
  }
@@ -78477,14 +78705,14 @@ function conformanceHashes(dir) {
78477
78705
  for (const rel of rels) {
78478
78706
  let data;
78479
78707
  try {
78480
- const st2 = lstatSync29(join129(dir, rel));
78708
+ const st2 = lstatSync29(join130(dir, rel));
78481
78709
  if (st2.isSymbolicLink()) {
78482
- out3[rel] = `${LINK}${readlinkSync7(join129(dir, rel))}|${outsideTargetDigest(dir, join129(dir, rel))}`;
78710
+ out3[rel] = `${LINK}${readlinkSync7(join130(dir, rel))}|${outsideTargetDigest(dir, join130(dir, rel))}`;
78483
78711
  continue;
78484
78712
  }
78485
78713
  if (!st2.isFile())
78486
78714
  continue;
78487
- data = readFileSync111(join129(dir, rel));
78715
+ data = readFileSync112(join130(dir, rel));
78488
78716
  } catch {
78489
78717
  continue;
78490
78718
  }
@@ -78543,7 +78771,7 @@ function notProvenUnitResult(unit, reason, oracle, wall) {
78543
78771
  return { unit, verdict: "NOT_PROVEN", oracle, wall, equiv: null, not_proven: [reason], conformance: null };
78544
78772
  }
78545
78773
  function readOracleSealed(repoDir, mid, unit) {
78546
- return JSON.parse(readFileSync111(join129(oracleDir(repoDir, mid, unit), "sealed.json"), "utf8"));
78774
+ return JSON.parse(readFileSync112(join130(oracleDir(repoDir, mid, unit), "sealed.json"), "utf8"));
78547
78775
  }
78548
78776
  function runUnit(card, log, runConformance, implement, runNew, runStub, collect) {
78549
78777
  const { repoDir, mid, unit } = card;
@@ -78654,8 +78882,8 @@ var init_unit = __esm(() => {
78654
78882
 
78655
78883
  // ../../loki-ts/src/engine10/modernize/wave.ts
78656
78884
  import { spawnSync as spawnSync20 } from "child_process";
78657
- import { readFileSync as readFileSync112, statSync as statSync33 } from "fs";
78658
- import { join as join130 } from "path";
78885
+ import { readFileSync as readFileSync113, statSync as statSync33 } from "fs";
78886
+ import { join as join131 } from "path";
78659
78887
  function clampTimeout(ms) {
78660
78888
  if (ms === undefined || !Number.isFinite(ms) || ms <= 0)
78661
78889
  return DEFAULT_STEP_TIMEOUT_MS;
@@ -78724,7 +78952,7 @@ function detectWaveCommands(inv, target) {
78724
78952
  const none = { build: null, integration: null, original_suite: null };
78725
78953
  const text4 = () => {
78726
78954
  try {
78727
- return readFileSync112(join130(target, marker ?? ""), "utf8");
78955
+ return readFileSync113(join131(target, marker ?? ""), "utf8");
78728
78956
  } catch {
78729
78957
  return "";
78730
78958
  }
@@ -78736,7 +78964,7 @@ function detectWaveCommands(inv, target) {
78736
78964
  if (system === "gradle") {
78737
78965
  let gw2 = "gradle";
78738
78966
  try {
78739
- if (inv.files.includes("gradlew") && (statSync33(join130(target, "gradlew")).mode & 73) !== 0)
78967
+ if (inv.files.includes("gradlew") && (statSync33(join131(target, "gradlew")).mode & 73) !== 0)
78740
78968
  gw2 = "./gradlew";
78741
78969
  } catch {}
78742
78970
  return { build: { argv: [gw2, "assemble"] }, integration: text4().includes("integrationTest") ? { argv: [gw2, "integrationTest"] } : null, original_suite: { argv: [gw2, "test"] } };
@@ -78748,7 +78976,7 @@ function detectWaveCommands(inv, target) {
78748
78976
  let toxIni = "";
78749
78977
  if (inv.files.includes("tox.ini")) {
78750
78978
  try {
78751
- toxIni = readFileSync112(join130(target, "tox.ini"), "utf8");
78979
+ toxIni = readFileSync113(join131(target, "tox.ini"), "utf8");
78752
78980
  } catch {}
78753
78981
  }
78754
78982
  const integration = toxIni.includes("[testenv:integration") ? { argv: ["tox", "-e", "integration"] } : itDir && pytest ? { argv: ["python3", "-m", "pytest", "-q", itDir] } : null;
@@ -78780,9 +79008,9 @@ var init_wave = __esm(() => {
78780
79008
 
78781
79009
  // ../../loki-ts/src/util/modernize_unit.ts
78782
79010
  import { spawnSync as spawnSync21 } from "child_process";
78783
- import { existsSync as existsSync89, lstatSync as lstatSync30, mkdtempSync as mkdtempSync18, readFileSync as readFileSync113, realpathSync as realpathSync34, rmSync as rmSync37, statSync as statSync34, writeFileSync as writeFileSync67 } from "fs";
79011
+ import { existsSync as existsSync89, lstatSync as lstatSync30, mkdtempSync as mkdtempSync18, readFileSync as readFileSync114, realpathSync as realpathSync34, rmSync as rmSync37, statSync as statSync34, writeFileSync as writeFileSync67 } from "fs";
78784
79012
  import { tmpdir as tmpdir23 } from "os";
78785
- import { join as join131, sep as sep21 } from "path";
79013
+ import { join as join132, sep as sep21 } from "path";
78786
79014
  function parseUnitArgs(args) {
78787
79015
  const f = {};
78788
79016
  for (let i = 0;i < args.length; i++) {
@@ -78854,7 +79082,7 @@ function makeUnitRunners(o) {
78854
79082
  }
78855
79083
  function makeSessionRunner(o) {
78856
79084
  const limitS = o.sessionLimitS ?? SESSION_LIMIT_S2;
78857
- const cli = import.meta.path.endsWith("modernize_unit.ts") ? join131(import.meta.dir, "..", "cli.ts") : import.meta.path;
79085
+ const cli = import.meta.path.endsWith("modernize_unit.ts") ? join132(import.meta.dir, "..", "cli.ts") : import.meta.path;
78858
79086
  return o.session ?? ((_brief, cwd, env) => spawnSync21(process.execPath, [...SAFE_BUN_FLAGS, cli, "engine10", "session"], { cwd, env, stdio: ["ignore", "ignore", "pipe"], timeout: limitS * 1000 }));
78859
79087
  }
78860
79088
  function defaultUnitFile(unitId, newTreeDir) {
@@ -78862,7 +79090,7 @@ function defaultUnitFile(unitId, newTreeDir) {
78862
79090
  return null;
78863
79091
  try {
78864
79092
  const root = realpathSync34(newTreeDir);
78865
- const real3 = realpathSync34(join131(root, unitId));
79093
+ const real3 = realpathSync34(join132(root, unitId));
78866
79094
  return real3.startsWith(root + sep21) ? real3 : null;
78867
79095
  } catch {
78868
79096
  return null;
@@ -78899,16 +79127,16 @@ function runPythonCase(o, unitId, newTreeDir, rec2, stub) {
78899
79127
  const src = o.unitFile ? o.unitFile(unitId, newTreeDir) : defaultUnitFile(unitId, newTreeDir);
78900
79128
  if (!src || !src.endsWith(".py") || !existsSync89(src))
78901
79129
  throw new Error(`cannot locate the source of unit ${unitId} in the new tree`);
78902
- const dir = mkdtempSync18(join131(tmpdir23(), "loki-newcase-"));
79130
+ const dir = mkdtempSync18(join132(tmpdir23(), "loki-newcase-"));
78903
79131
  try {
78904
- const cases = join131(dir, "in.jsonl"), out3 = join131(dir, "out.jsonl");
79132
+ const cases = join132(dir, "in.jsonl"), out3 = join132(dir, "out.jsonl");
78905
79133
  writeFileSync67(cases, JSON.stringify({ entry: rec2.entry, args: rec2.args, kwargs: rec2.kwargs, boundaries: boundariesFromCase(rec2) }) + `
78906
79134
  `, "utf8");
78907
- const r = spawnSync21(o.pythonBin ?? "python3", [join131(REPO_ROOT, "autonomy", "lib", "modernize", "py_capture.py"), "--unit", src, "--cases", cases, "--out", out3, ...stub ? ["--stub"] : []], { cwd: newTreeDir, encoding: "utf8", timeout: CASE_TIMEOUT_MS, env: { ...tokenFreeEnv(), PYTHONDONTWRITEBYTECODE: "1" } });
79135
+ const r = spawnSync21(o.pythonBin ?? "python3", [join132(REPO_ROOT, "autonomy", "lib", "modernize", "py_capture.py"), "--unit", src, "--cases", cases, "--out", out3, ...stub ? ["--stub"] : []], { cwd: newTreeDir, encoding: "utf8", timeout: CASE_TIMEOUT_MS, env: { ...tokenFreeEnv(), PYTHONDONTWRITEBYTECODE: "1" } });
78908
79136
  if (r.status !== 0 || !existsSync89(out3))
78909
79137
  throw new Error(`new-tree case runner failed (${r.status ?? r.signal ?? "no status"}): ${String(r.stderr ?? "").trim().split(`
78910
79138
  `).pop() ?? ""}`);
78911
- const line2 = readFileSync113(out3, "utf8").split(`
79139
+ const line2 = readFileSync114(out3, "utf8").split(`
78912
79140
  `).find((l) => l.trim() !== "");
78913
79141
  if (!line2)
78914
79142
  throw new Error("new-tree case runner produced no record");
@@ -78934,7 +79162,7 @@ Usage: ${UNIT_USAGE}
78934
79162
  const root = u10.tmpRoot ?? (runTmp !== "" && isRealDir(runTmp) ? runTmp : tmpdir23());
78935
79163
  let repoDir;
78936
79164
  try {
78937
- repoDir = mkdtempSync18(join131(root, "loki-unit-"));
79165
+ repoDir = mkdtempSync18(join132(root, "loki-unit-"));
78938
79166
  } catch (e10) {
78939
79167
  process.stderr.write(`modernize unit: cannot create a temp checkout directory: ${e10.message}
78940
79168
  `);
@@ -79030,11 +79258,11 @@ var init_modernize_unit = __esm(() => {
79030
79258
 
79031
79259
  // ../../loki-ts/src/util/modernize_coordinator.ts
79032
79260
  import { createHash as createHash36 } from "crypto";
79033
- import { existsSync as existsSync90, mkdtempSync as mkdtempSync19, readFileSync as readFileSync114, rmSync as rmSync38 } from "fs";
79261
+ import { existsSync as existsSync90, mkdtempSync as mkdtempSync19, readFileSync as readFileSync115, rmSync as rmSync38 } from "fs";
79034
79262
  import { tmpdir as tmpdir24 } from "os";
79035
- import { join as join132 } from "path";
79263
+ import { join as join133 } from "path";
79036
79264
  function shipUnitOf(d, unit, o) {
79037
- const sealed = join132(oracleDir(d.repoDir, d.mid, unit), "sealed.json");
79265
+ const sealed = join133(oracleDir(d.repoDir, d.mid, unit), "sealed.json");
79038
79266
  const eq3 = o?.result?.equiv;
79039
79267
  return {
79040
79268
  unit,
@@ -79051,7 +79279,7 @@ function scopeBuildToWave(cmd2, repoDir, units) {
79051
79279
  const x3 = cmd2?.argv.indexOf("-x") ?? -1;
79052
79280
  if (!cmd2 || !cmd2.argv.includes("compileall") || x3 < 0)
79053
79281
  return cmd2;
79054
- const files = [...new Set(units.flatMap((u10) => u10.nodes))].filter((n11) => n11.endsWith(".py") && isSafeUnitId(n11) && existsSync90(join132(repoDir, n11)));
79282
+ const files = [...new Set(units.flatMap((u10) => u10.nodes))].filter((n11) => n11.endsWith(".py") && isSafeUnitId(n11) && existsSync90(join133(repoDir, n11)));
79055
79283
  return files.length ? { ...cmd2, argv: [...cmd2.argv.slice(0, x3 + 2), ...files] } : cmd2;
79056
79284
  }
79057
79285
  async function runWaves(plan, d) {
@@ -79210,16 +79438,16 @@ function makeAttemptRunner(o) {
79210
79438
  }
79211
79439
  function makeUnitPrep(o) {
79212
79440
  const runtimeOk = o.runtimeOk ?? (() => {
79213
- const dir = mkdtempSync19(join132(tmpdir24(), "loki-probe-"));
79441
+ const dir = mkdtempSync19(join133(tmpdir24(), "loki-probe-"));
79214
79442
  try {
79215
- return realCaptureRunner(join132(dir, "probe.py"), []).error !== "old runtime unavailable";
79443
+ return realCaptureRunner(join133(dir, "probe.py"), []).error !== "old runtime unavailable";
79216
79444
  } finally {
79217
79445
  rmSync38(dir, { recursive: true, force: true });
79218
79446
  }
79219
79447
  });
79220
79448
  let runtime = null;
79221
79449
  return (unit) => {
79222
- if (existsSync90(join132(oracleDir(o.repoDir, o.mid, unit.id), "cases.jsonl")) || alreadySealedInLog(o.repoDir, o.mid, unit.id))
79450
+ if (existsSync90(join133(oracleDir(o.repoDir, o.mid, unit.id), "cases.jsonl")) || alreadySealedInLog(o.repoDir, o.mid, unit.id))
79223
79451
  return null;
79224
79452
  runtime ??= runtimeOk();
79225
79453
  if (!runtime)
@@ -79227,7 +79455,7 @@ function makeUnitPrep(o) {
79227
79455
  const node = unit.nodes.length === 1 ? unit.nodes[0] : "";
79228
79456
  if (!node.endsWith(".py") || !isSafeUnitId(node))
79229
79457
  return MULTI_FILE_REASON;
79230
- const r = (o.capture ?? captureUnitOracle)({ repoDir: o.repoDir, mid: o.mid, unit: unit.id, unitPath: join132(o.repoDir, node), propose: o.propose });
79458
+ const r = (o.capture ?? captureUnitOracle)({ repoDir: o.repoDir, mid: o.mid, unit: unit.id, unitPath: join133(o.repoDir, node), propose: o.propose });
79231
79459
  return r.ok ? null : r.reason;
79232
79460
  };
79233
79461
  }
@@ -79286,7 +79514,7 @@ function productionWaveDeps(o) {
79286
79514
  }
79287
79515
  };
79288
79516
  }
79289
- var productionReslice, sha2565 = (p) => existsSync90(p) ? createHash36("sha256").update(readFileSync114(p)).digest("hex") : "n/a", MULTI_FILE_REASON = "multi-file unit: capture not supported (founder default)";
79517
+ var productionReslice, sha2565 = (p) => existsSync90(p) ? createHash36("sha256").update(readFileSync115(p)).digest("hex") : "n/a", MULTI_FILE_REASON = "multi-file unit: capture not supported (founder default)";
79290
79518
  var init_modernize_coordinator = __esm(() => {
79291
79519
  init_codemod();
79292
79520
  init_search();
@@ -79619,8 +79847,8 @@ __export(exports_export_sarif, {
79619
79847
  preRedFromEvents: () => preRedFromEvents,
79620
79848
  main: () => main8
79621
79849
  });
79622
- import { existsSync as existsSync92, readFileSync as readFileSync115, writeFileSync as writeFileSync68 } from "fs";
79623
- import { join as join133 } from "path";
79850
+ import { existsSync as existsSync92, readFileSync as readFileSync116, writeFileSync as writeFileSync68 } from "fs";
79851
+ import { join as join134 } from "path";
79624
79852
  function scanDiff(diff) {
79625
79853
  const out3 = [];
79626
79854
  let file = "";
@@ -79651,7 +79879,7 @@ function scanDiff(diff) {
79651
79879
  function preRedFromEvents(runDir) {
79652
79880
  try {
79653
79881
  let pre2 = [];
79654
- for (const l of readFileSync115(join133(runDir, "events.jsonl"), "utf8").split(`
79882
+ for (const l of readFileSync116(join134(runDir, "events.jsonl"), "utf8").split(`
79655
79883
  `)) {
79656
79884
  if (!l.includes('"stage.completed"'))
79657
79885
  continue;
@@ -79680,19 +79908,19 @@ async function main8(args, deps = {}) {
79680
79908
  if (bad || rest.length > 1)
79681
79909
  return process.stderr.write(`loki export --sarif: ${bad ? `unknown flag ${bad}` : "more than one run-id"}
79682
79910
  `), 2;
79683
- const runsRoot2 = deps.runsRoot ?? join133(lokiDir(), "runs");
79911
+ const runsRoot2 = deps.runsRoot ?? join134(lokiDir(), "runs");
79684
79912
  const runId2 = rest[0] ?? latestRunId(runsRoot2);
79685
79913
  if (!runId2)
79686
79914
  return process.stderr.write(`loki export --sarif: no runs found
79687
79915
  `), 66;
79688
- const runDir = join133(runsRoot2, runId2);
79689
- const receiptPath = join133(runDir, "receipt.json");
79916
+ const runDir = join134(runsRoot2, runId2);
79917
+ const receiptPath = join134(runDir, "receipt.json");
79690
79918
  if (runId2.includes("/") || runId2.includes("..") || !existsSync92(receiptPath))
79691
79919
  return process.stderr.write(`loki export --sarif: unknown run ${runId2}
79692
79920
  `), 66;
79693
79921
  let receipt;
79694
79922
  try {
79695
- receipt = JSON.parse(readFileSync115(receiptPath, "utf8"));
79923
+ receipt = JSON.parse(readFileSync116(receiptPath, "utf8"));
79696
79924
  } catch {
79697
79925
  return process.stderr.write(`loki export --sarif: unreadable receipt for ${runId2}
79698
79926
  `), 66;
@@ -79709,9 +79937,9 @@ async function main8(args, deps = {}) {
79709
79937
  findings.push(...receiptFindings(receipt, preRedFromEvents(runDir)));
79710
79938
  let version2 = "0.0.0";
79711
79939
  try {
79712
- version2 = readFileSync115(join133(REPO_ROOT, "VERSION"), "utf8").trim() || version2;
79940
+ version2 = readFileSync116(join134(REPO_ROOT, "VERSION"), "utf8").trim() || version2;
79713
79941
  } catch {}
79714
- const out3 = join133(runDir, "findings.sarif");
79942
+ const out3 = join134(runDir, "findings.sarif");
79715
79943
  writeFileSync68(out3, JSON.stringify(toSarif(findings, version2, deps.repoDir ?? process.cwd()), null, 2) + `
79716
79944
  `);
79717
79945
  process.stdout.write(`run: ${runId2}
@@ -79930,7 +80158,7 @@ var init_output = __esm(() => {
79930
80158
 
79931
80159
  // ../../loki-ts/src/features/receipt_dsse.ts
79932
80160
  import { createPublicKey as createPublicKey5, sign as sign3, verify as verify3 } from "crypto";
79933
- import { readFileSync as readFileSync116 } from "fs";
80161
+ import { readFileSync as readFileSync117 } from "fs";
79934
80162
  function pae2(payloadType, body) {
79935
80163
  const t = Buffer.from(payloadType, "utf8");
79936
80164
  return Buffer.concat([Buffer.from(`DSSEv1 ${t.length} `), t, Buffer.from(` ${body.length} `), body]);
@@ -80026,7 +80254,7 @@ function verifyDsseReceipt(env, d) {
80026
80254
  }
80027
80255
  function runIdGuard(receiptPath, runId2) {
80028
80256
  try {
80029
- return envelopeRunIdProblem(JSON.parse(readFileSync116(receiptPath, "utf8")), runId2);
80257
+ return envelopeRunIdProblem(JSON.parse(readFileSync117(receiptPath, "utf8")), runId2);
80030
80258
  } catch {
80031
80259
  return null;
80032
80260
  }
@@ -80034,7 +80262,7 @@ function runIdGuard(receiptPath, runId2) {
80034
80262
  async function exportDsseReceipt(a) {
80035
80263
  const fail2 = (rc2, m) => (process.stderr.write(`loki verify --export-dsse: ${m}
80036
80264
  `), rc2);
80037
- const rd2 = a.deps.read ?? ((p) => readFileSync116(p, "utf8"));
80265
+ const rd2 = a.deps.read ?? ((p) => readFileSync117(p, "utf8"));
80038
80266
  let text4;
80039
80267
  try {
80040
80268
  text4 = rd2(a.receiptPath);
@@ -80091,10 +80319,10 @@ var init_undo = __esm(() => {
80091
80319
  });
80092
80320
 
80093
80321
  // ../../loki-ts/src/commands/run_status.ts
80094
- import { existsSync as existsSync93, readdirSync as readdirSync38, readFileSync as readFileSync117, statSync as statSync36 } from "fs";
80095
- import { basename as basename32, dirname as dirname49, join as join134, resolve as resolve39 } from "path";
80322
+ import { existsSync as existsSync93, readdirSync as readdirSync38, readFileSync as readFileSync118, statSync as statSync36 } from "fs";
80323
+ import { basename as basename32, dirname as dirname50, join as join135, resolve as resolve39 } from "path";
80096
80324
  function runsRoot(env, repoDir) {
80097
- return env.LOKI_DIR ? join134(resolve39(repoDir, env.LOKI_DIR), "runs") : join134(repoDir, ".loki", "runs");
80325
+ return env.LOKI_DIR ? join135(resolve39(repoDir, env.LOKI_DIR), "runs") : join135(repoDir, ".loki", "runs");
80098
80326
  }
80099
80327
  function listRunIds(root) {
80100
80328
  if (!existsSync93(root))
@@ -80106,7 +80334,7 @@ function latestRunId(root) {
80106
80334
  return ids.length ? ids[ids.length - 1] : null;
80107
80335
  }
80108
80336
  function eventsPath(root, runId2) {
80109
- return join134(root, runId2, "events.jsonl");
80337
+ return join135(root, runId2, "events.jsonl");
80110
80338
  }
80111
80339
  var TERMINAL2;
80112
80340
  var init_run_status = __esm(() => {
@@ -80123,8 +80351,8 @@ var init_run_status = __esm(() => {
80123
80351
 
80124
80352
  // ../../loki-ts/src/util/seal_drift.ts
80125
80353
  import { createHash as createHash38 } from "crypto";
80126
- import { existsSync as existsSync94, readFileSync as readFileSync118, realpathSync as realpathSync35 } from "fs";
80127
- import { basename as basename33, dirname as dirname50, join as join135, relative as relative27 } from "path";
80354
+ import { existsSync as existsSync94, readFileSync as readFileSync119, realpathSync as realpathSync35 } from "fs";
80355
+ import { basename as basename33, dirname as dirname51, join as join136, relative as relative27 } from "path";
80128
80356
  function tornTail(raw2) {
80129
80357
  if (raw2 === "" || raw2.endsWith(`
80130
80358
  `))
@@ -80143,7 +80371,7 @@ function tornTail(raw2) {
80143
80371
  function boundEvents(log, bound) {
80144
80372
  if (!existsSync94(log))
80145
80373
  return null;
80146
- const lines2 = readFileSync118(log, "utf8").split(`
80374
+ const lines2 = readFileSync119(log, "utf8").split(`
80147
80375
  `).filter((l) => l.trim() !== ""), h10 = createHash38("sha256");
80148
80376
  let n11 = -1;
80149
80377
  for (let i = 0;i <= lines2.length; i++) {
@@ -80171,7 +80399,7 @@ function fabricatedPass(receiptPath, r) {
80171
80399
  const bound = r["events_sha256"];
80172
80400
  if (typeof bound !== "string" || bound === EMPTY_SHA || !Array.isArray(r["checks"]))
80173
80401
  return null;
80174
- const events2 = boundEvents(join135(dirname50(receiptPath), "events.jsonl"), bound);
80402
+ const events2 = boundEvents(join136(dirname51(receiptPath), "events.jsonl"), bound);
80175
80403
  if (!events2 || !events2.some((e10) => e10.stage === "verify"))
80176
80404
  return null;
80177
80405
  const passed = new Set(events2.filter((e10) => e10.type === "test.result" && e10.stage === "verify" && e10.data["result"] === "pass").map((e10) => String(e10.data["name"])));
@@ -80179,12 +80407,12 @@ function fabricatedPass(receiptPath, r) {
80179
80407
  return missing.length ? `receipt claims pass with no test.result pass in events.jsonl: ${missing.join(", ")}` : null;
80180
80408
  }
80181
80409
  function currentTaskSha(runDir, source, env) {
80182
- const f = source === "issue" ? join135(runDir, "issue.json") : env["LOKI_VERIFY_TASK_FILE"];
80183
- return f && existsSync94(f) ? sha6(readFileSync118(f)) : null;
80410
+ const f = source === "issue" ? join136(runDir, "issue.json") : env["LOKI_VERIFY_TASK_FILE"];
80411
+ return f && existsSync94(f) ? sha6(readFileSync119(f)) : null;
80184
80412
  }
80185
80413
  function repoOf(receiptPath) {
80186
- const runs2 = dirname50(dirname50(receiptPath));
80187
- return basename33(runs2) === "runs" && basename33(dirname50(runs2)) === ".loki" ? dirname50(dirname50(runs2)) : null;
80414
+ const runs2 = dirname51(dirname51(receiptPath));
80415
+ return basename33(runs2) === "runs" && basename33(dirname51(runs2)) === ".loki" ? dirname51(dirname51(runs2)) : null;
80188
80416
  }
80189
80417
  function overlap(repo, base, sealedHead, head) {
80190
80418
  if (typeof base !== "string" || !/^[0-9a-f]{40,64}$/.test(base) || !/^[0-9a-f]{40,64}$/.test(sealedHead))
@@ -80210,7 +80438,7 @@ function onlyWallPublish(repo, r, sealedHead, head) {
80210
80438
  } catch {
80211
80439
  return x3;
80212
80440
  }
80213
- }, rr2 = real3(repo), want = new Map(wall.map((w) => [relative27(rr2, join135(real3(dirname50(String(w.path))), basename33(String(w.path)))), String(w.sha256)]));
80441
+ }, rr2 = real3(repo), want = new Map(wall.map((w) => [relative27(rr2, join136(real3(dirname51(String(w.path))), basename33(String(w.path)))), String(w.sha256)]));
80214
80442
  const commits = safeGit(repo, ["rev-list", "--reverse", "--topo-order", `${sealedHead}..${head}`]).split(`
80215
80443
  `).filter(Boolean);
80216
80444
  if (commits.length === 0 || safeGit(repo, ["rev-list", "--merges", "--count", `${sealedHead}..${head}`]).trim() !== "0")
@@ -80248,18 +80476,18 @@ function claimsWallPublish(repo, r, sealedHead, head) {
80248
80476
  function sealDrift(given, r, env = process.env) {
80249
80477
  let receiptPath = given;
80250
80478
  try {
80251
- receiptPath = join135(realpathSync35(dirname50(given)), basename33(given));
80479
+ receiptPath = join136(realpathSync35(dirname51(given)), basename33(given));
80252
80480
  } catch {}
80253
80481
  const fab = fabricatedPass(receiptPath, r);
80254
80482
  if (fab)
80255
80483
  return { verdict: "TAMPERED", reason: fab };
80256
80484
  try {
80257
- const log = join135(dirname50(receiptPath), "events.jsonl");
80258
- if (existsSync94(log) && tornTail(readFileSync118(log, "utf8")))
80485
+ const log = join136(dirname51(receiptPath), "events.jsonl");
80486
+ if (existsSync94(log) && tornTail(readFileSync119(log, "utf8")))
80259
80487
  return { verdict: "UNCHECKED", reason: "events.jsonl ends in a torn, unterminated line (an append cut mid-write); every complete line is intact but the log is not whole" };
80260
80488
  } catch {}
80261
80489
  const task = r["task"] ?? {};
80262
- const cur = currentTaskSha(dirname50(receiptPath), task.source, env);
80490
+ const cur = currentTaskSha(dirname51(receiptPath), task.source, env);
80263
80491
  if (cur !== null && typeof task.sha256 === "string" && task.sha256 !== "" && cur !== task.sha256)
80264
80492
  return { verdict: "UNCHECKED", reason: `intent drift: sealed task sha256 ${task.sha256} differs from the current spec ${cur}` };
80265
80493
  const repo = repoOf(receiptPath);
@@ -80282,6 +80510,17 @@ function sealDrift(given, r, env = process.env) {
80282
80510
  }
80283
80511
  return null;
80284
80512
  }
80513
+ function wallNotComparedNote(receiptPath) {
80514
+ try {
80515
+ const r = JSON.parse(readFileSync119(receiptPath, "utf8"));
80516
+ if (r["schema"] !== "loki.v10.receipt/1")
80517
+ return null;
80518
+ const files = r["wall"]?.files;
80519
+ return Array.isArray(files) && files.length > 0 && !existsSync94(join136(dirname51(receiptPath), "wall")) ? "sealed Wall copies not present: not compared" : null;
80520
+ } catch {
80521
+ return null;
80522
+ }
80523
+ }
80285
80524
  var EMPTY_SHA, sha6 = (s) => createHash38("sha256").update(s).digest("hex");
80286
80525
  var init_seal_drift = __esm(() => {
80287
80526
  init_safe_git();
@@ -80289,14 +80528,14 @@ var init_seal_drift = __esm(() => {
80289
80528
  });
80290
80529
 
80291
80530
  // ../../loki-ts/src/util/composite_seal.ts
80292
- import { existsSync as existsSync95, readFileSync as readFileSync119 } from "fs";
80293
- import { basename as basename34, dirname as dirname51, join as join136 } from "path";
80531
+ import { existsSync as existsSync95, readFileSync as readFileSync120 } from "fs";
80532
+ import { basename as basename34, dirname as dirname52, join as join137 } from "path";
80294
80533
  function logProblem(runDir, integ) {
80295
80534
  if (typeof integ["log_sha256"] !== "string")
80296
80535
  return null;
80297
80536
  let b;
80298
80537
  try {
80299
- b = readFileSync119(join136(runDir, "integration.log"));
80538
+ b = readFileSync120(join137(runDir, "integration.log"));
80300
80539
  } catch {
80301
80540
  return "integration.log is missing but integration.json records its hash";
80302
80541
  }
@@ -80311,10 +80550,10 @@ function integrationProblem(integ) {
80311
80550
  return null;
80312
80551
  }
80313
80552
  function composeComposite(runDir, rh, toolchain = collectToolchain()) {
80314
- const ip = join136(runDir, "integration.json");
80553
+ const ip = join137(runDir, "integration.json");
80315
80554
  let ibytes;
80316
80555
  try {
80317
- ibytes = readFileSync119(ip);
80556
+ ibytes = readFileSync120(ip);
80318
80557
  } catch {
80319
80558
  throw new Error("integration.json missing; the workspace run did not finish");
80320
80559
  }
@@ -80338,12 +80577,12 @@ function composeComposite(runDir, rh, toolchain = collectToolchain()) {
80338
80577
  const outcome = String(integ["outcomes"][repo] ?? "");
80339
80578
  if (outcome !== "ok")
80340
80579
  throw new Error(`repo ${text3(repo, 80)} did not finish (${text3(outcome, 80) || "no outcome"}); no composite`);
80341
- const runsDir = join136(runDir, "worktrees", slugOf(repo), ".loki", "runs");
80342
- const ids = (dirNames(runsDir) ?? []).filter((n11) => existsSync95(join136(runsDir, n11, "receipt.json")));
80580
+ const runsDir = join137(runDir, "worktrees", slugOf(repo), ".loki", "runs");
80581
+ const ids = (dirNames(runsDir) ?? []).filter((n11) => existsSync95(join137(runsDir, n11, "receipt.json")));
80343
80582
  const id2 = ids[ids.length - 1];
80344
80583
  if (!id2)
80345
80584
  throw new Error(`repo ${text3(repo, 80)} has no receipt.json under worktrees/${slugOf(repo)}/.loki/runs`);
80346
- const rp = join136(runsDir, id2, "receipt.json"), bytes = readFileSync119(rp), r = readJson7(rp);
80585
+ const rp = join137(runsDir, id2, "receipt.json"), bytes = readFileSync120(rp), r = readJson7(rp);
80347
80586
  if (jsonTooDeep(r))
80348
80587
  throw new Error(`repo ${text3(repo, 80)} receipt cannot be hashed (nested too deeply); no composite`);
80349
80588
  if (!isObj10(r) || typeof r["receipt_sha256"] !== "string" || rh(r) !== r["receipt_sha256"])
@@ -80361,7 +80600,7 @@ function composeComposite(runDir, rh, toolchain = collectToolchain()) {
80361
80600
  throw new Error("workspace has no repos");
80362
80601
  return {
80363
80602
  schema: COMPOSITE_SCHEMA,
80364
- workspace: basename34(dirname51(runDir)),
80603
+ workspace: basename34(dirname52(runDir)),
80365
80604
  run_id: basename34(runDir),
80366
80605
  integration_sha256: sha4(ibytes),
80367
80606
  integration: { status: String(integ["status"]), exit_code: typeof integ["exit_code"] === "number" ? integ["exit_code"] : null, log_sha256: typeof integ["log_sha256"] === "string" ? integ["log_sha256"] : null, heads },
@@ -80371,7 +80610,7 @@ function composeComposite(runDir, rh, toolchain = collectToolchain()) {
80371
80610
  };
80372
80611
  }
80373
80612
  async function verifyComposite(receiptPath, receipt, rh, verifyOne, deps = {}) {
80374
- const runDir = dirname51(receiptPath);
80613
+ const runDir = dirname52(receiptPath);
80375
80614
  const signed = isObj10(receipt["verification"]) && typeof receipt["verification"]["jwt"] === "string";
80376
80615
  const bad = (reason) => ({ problem: { verdict: "TAMPERED", reason: `composite: ${reason}` }, verdict: "FAILED" });
80377
80616
  const deep = (what) => ({ problem: { verdict: "UNCHECKED", reason: `composite: ${what} cannot be hashed (nested too deeply)` }, verdict: "FAILED" });
@@ -80380,13 +80619,13 @@ async function verifyComposite(receiptPath, receipt, rh, verifyOne, deps = {}) {
80380
80619
  return bad("body malformed");
80381
80620
  let ibytes;
80382
80621
  try {
80383
- ibytes = readFileSync119(join136(runDir, "integration.json"));
80622
+ ibytes = readFileSync120(join137(runDir, "integration.json"));
80384
80623
  } catch {
80385
80624
  return bad("integration.json missing");
80386
80625
  }
80387
80626
  if (sha4(ibytes) !== receipt["integration_sha256"])
80388
80627
  return bad("integration.json does not match its recorded hash");
80389
- const integ = readJson7(join136(runDir, "integration.json"));
80628
+ const integ = readJson7(join137(runDir, "integration.json"));
80390
80629
  if (jsonTooDeep(integ))
80391
80630
  return deep("integration.json");
80392
80631
  if (!isObj10(integ) || !isObj10(integ["outcomes"]))
@@ -80423,10 +80662,10 @@ async function verifyComposite(receiptPath, receipt, rh, verifyOne, deps = {}) {
80423
80662
  return bad(`child ${text3(repo, 80) || "?"} has an invalid receipt path`);
80424
80663
  if (outcomes[repo] !== "ok")
80425
80664
  return bad(`child ${text3(repo, 80)} did not finish ok in integration.json`);
80426
- const rp = join136(runDir, rel);
80665
+ const rp = join137(runDir, rel);
80427
80666
  let bytes;
80428
80667
  try {
80429
- bytes = readFileSync119(rp);
80668
+ bytes = readFileSync120(rp);
80430
80669
  } catch {
80431
80670
  return bad(`child ${repo} receipt missing`);
80432
80671
  }
@@ -80486,8 +80725,8 @@ __export(exports_verify_cmd, {
80486
80725
  main: () => main9,
80487
80726
  computeReceiptHash: () => computeReceiptHash
80488
80727
  });
80489
- import { existsSync as existsSync96, readFileSync as readFileSync120, renameSync as renameSync23, statSync as statSync37, writeFileSync as writeFileSync69 } from "fs";
80490
- import { basename as basename35, dirname as dirname52, join as join137 } from "path";
80728
+ import { existsSync as existsSync96, readFileSync as readFileSync121, renameSync as renameSync23, statSync as statSync37, writeFileSync as writeFileSync69 } from "fs";
80729
+ import { basename as basename35, dirname as dirname53, join as join138 } from "path";
80491
80730
  import { createHash as createHash39, createPublicKey as createPublicKey6, verify as verify4 } from "crypto";
80492
80731
  function pubFor(kid, given) {
80493
80732
  if (given)
@@ -80495,7 +80734,7 @@ function pubFor(kid, given) {
80495
80734
  const active = loadSigningKey(false);
80496
80735
  const pubs = (process.env["LOKI_RECEIPT_RETIRED_PUBKEYS"] ?? "").split(":").map((f) => f.trim()).filter(Boolean).flatMap((f) => {
80497
80736
  try {
80498
- return [createPublicKey6(readFileSync120(f))];
80737
+ return [createPublicKey6(readFileSync121(f))];
80499
80738
  } catch {
80500
80739
  return [];
80501
80740
  }
@@ -80525,14 +80764,14 @@ function checkAttestation(jwt, expectedHash, given) {
80525
80764
  }
80526
80765
  function wallTamperProblem(receiptPath, receipt) {
80527
80766
  const wall = receipt["wall"], files = Array.isArray(wall?.files) ? wall.files : [];
80528
- const wallDir = join137(dirname52(receiptPath), "wall"), haveWallDir = existsSync96(wallDir);
80767
+ const wallDir = join138(dirname53(receiptPath), "wall"), haveWallDir = existsSync96(wallDir);
80529
80768
  for (const f of files) {
80530
80769
  if (typeof f?.path !== "string" || typeof f.sha256 !== "string")
80531
80770
  continue;
80532
- const copy = join137(wallDir, basename35(f.path));
80771
+ const copy = join138(wallDir, basename35(f.path));
80533
80772
  let cur;
80534
80773
  try {
80535
- cur = createHash39("sha256").update(readFileSync120(copy)).digest("hex");
80774
+ cur = createHash39("sha256").update(readFileSync121(copy)).digest("hex");
80536
80775
  } catch {
80537
80776
  if (haveWallDir)
80538
80777
  return `sealed Wall file ${basename35(f.path)} is missing from the run's wall directory: it was deleted after the seal`;
@@ -80559,10 +80798,10 @@ function checkEventLog(receiptPath, receipt) {
80559
80798
  const claims = st2 !== null && typeof st2 === "object" && Object.keys(st2).length > 0;
80560
80799
  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;
80561
80800
  }
80562
- const path = join137(dirname52(receiptPath), "events.jsonl");
80801
+ const path = join138(dirname53(receiptPath), "events.jsonl");
80563
80802
  if (!existsSync96(path))
80564
80803
  return "events.jsonl is missing";
80565
- const raw2 = readFileSync120(path, "utf8"), events2 = readEvents(path), all = raw2.split(`
80804
+ const raw2 = readFileSync121(path, "utf8"), events2 = readEvents(path), all = raw2.split(`
80566
80805
  `).filter((l) => l.trim() !== ""), lines2 = tornTail(raw2) ? all.slice(0, -1) : all;
80567
80806
  if (events2.length !== lines2.length || events2.some((e10, i) => e10.seq !== i))
80568
80807
  return "events.jsonl has a forged, edited or missing line";
@@ -80582,7 +80821,7 @@ function checkEventLog(receiptPath, receipt) {
80582
80821
  return h10.digest("hex") === bound ? null : "events.jsonl does not match the hash recorded at seal";
80583
80822
  }
80584
80823
  function checkLogSeal(receiptPath, hash, kid, given) {
80585
- const path = join137(dirname52(receiptPath), "events.jsonl"), events2 = readEvents(path), done = events2.findIndex((e10) => e10.type === "run.completed");
80824
+ const path = join138(dirname53(receiptPath), "events.jsonl"), events2 = readEvents(path), done = events2.findIndex((e10) => e10.type === "run.completed");
80586
80825
  if (!events2.some((e10) => e10.type === "receipt.sealed" && e10.data["receipt_sha256"] === hash))
80587
80826
  return { verdict: "TAMPERED", reason: "events.jsonl has no receipt.sealed event for this receipt" };
80588
80827
  if (done < 0)
@@ -80590,7 +80829,7 @@ function checkLogSeal(receiptPath, hash, kid, given) {
80590
80829
  const seal = events2[done + 1], d = seal?.type === "log.sealed" ? seal.data : null;
80591
80830
  if (!d)
80592
80831
  return { verdict: "TAMPERED", reason: "events.jsonl has no signed log.sealed line after run.completed" };
80593
- const lines2 = readFileSync120(path, "utf8").split(`
80832
+ const lines2 = readFileSync121(path, "utf8").split(`
80594
80833
  `).filter((l) => l.trim() !== ""), sha7 = createHash39("sha256").update(lines2.slice(0, done + 1).join(`
80595
80834
  `) + `
80596
80835
  `).digest("hex");
@@ -80604,7 +80843,7 @@ async function verifyReceipt(receiptPath, deps = {}) {
80604
80843
  return { verdict: "UNCHECKED", reasons: [`receipt not found: ${receiptPath}`] };
80605
80844
  let receipt;
80606
80845
  try {
80607
- receipt = JSON.parse((deps.read ?? ((p) => readFileSync120(p, "utf8")))(receiptPath));
80846
+ receipt = JSON.parse((deps.read ?? ((p) => readFileSync121(p, "utf8")))(receiptPath));
80608
80847
  } catch {
80609
80848
  return { verdict: "UNCHECKED", reasons: ["receipt.json is not valid JSON"] };
80610
80849
  }
@@ -80699,7 +80938,7 @@ function sealCompositeCmd(runDir) {
80699
80938
  `), 2;
80700
80939
  }
80701
80940
  const hash = compositeHash(body), sig = signReceipt(body.run_id, hash);
80702
- const out3 = { ...body, composite_sha256: hash, verification: { jwt: sig.jwt, kid: sig.kid } }, path = join137(runDir, "composite.json");
80941
+ const out3 = { ...body, composite_sha256: hash, verification: { jwt: sig.jwt, kid: sig.kid } }, path = join138(runDir, "composite.json");
80703
80942
  writeFileSync69(`${path}.tmp`, JSON.stringify(out3, null, 2) + `
80704
80943
  `);
80705
80944
  renameSync23(`${path}.tmp`, path);
@@ -80715,7 +80954,7 @@ ${compositeLines(out3).join(`
80715
80954
  function independentLine(receiptPath) {
80716
80955
  let checks = [];
80717
80956
  try {
80718
- const c = JSON.parse(readFileSync120(receiptPath, "utf8")).checks;
80957
+ const c = JSON.parse(readFileSync121(receiptPath, "utf8")).checks;
80719
80958
  if (Array.isArray(c))
80720
80959
  checks = c;
80721
80960
  } catch {}
@@ -80725,6 +80964,14 @@ function independentLine(receiptPath) {
80725
80964
  const k3 = pass.filter((c) => isExecutedProof(c) && (c.provenance === "exogenous" || c.provenance === "independent")).length, m = pass.filter((c) => c.provenance === "agent_authored" || c.provenance === "llm_judge").length;
80726
80965
  return { line: `agent-independent: ${k3} of ${pass.length} passing checks (wall/holdout/pre-existing/static/probe); advisory: ${m}`, k: k3, of: pass.length };
80727
80966
  }
80967
+ function signedRunIdProblem(receiptPath, runId2) {
80968
+ try {
80969
+ const r = JSON.parse(readFileSync121(receiptPath, "utf8")), s = r["run_id"];
80970
+ return isEnvelope(r) || typeof s !== "string" || s === runId2 ? null : `receipt run_id ${JSON.stringify(printable(s).slice(0, 128))} does not match the run id ${JSON.stringify(runId2)} it was found under (a sealed run copied under another id)`;
80971
+ } catch {
80972
+ return null;
80973
+ }
80974
+ }
80728
80975
  async function verifyMain(args, deps, rec2) {
80729
80976
  const allowUnsigned = args.includes("--allow-unsigned") || process.env["LOKI_VERIFY_ALLOW_UNSIGNED"] === "1";
80730
80977
  const exportDsse = args.includes("--export-dsse"), requireExo = args.includes("--require-exogenous") || process.env["LOKI_VERIFY_REQUIRE_EXOGENOUS"] === "1";
@@ -80772,20 +81019,20 @@ ${/^(unknown option|expected at most one)/.test(pk2.error) ? `Usage: loki verify
80772
81019
  args = pk2.args;
80773
81020
  if (pk2.pubkey)
80774
81021
  deps = { ...deps, pubkey: pk2.pubkey };
80775
- const runsRoot2 = deps.runsRoot ?? join137(lokiDir(), "runs");
81022
+ const runsRoot2 = deps.runsRoot ?? join138(lokiDir(), "runs");
80776
81023
  const runId2 = args[0] ?? latestRunId(runsRoot2) ?? undefined;
80777
81024
  if (!runId2)
80778
81025
  return process.stderr.write(`loki verify: no runs found
80779
81026
  `), 66;
80780
81027
  const isFile = existsSync96(runId2) && statSync37(runId2).isFile();
80781
81028
  const isPath = isFile || /[\\/]/.test(runId2) || runId2.endsWith(".json");
80782
- const receiptPath = isPath ? runId2 : join137(runsRoot2, runId2, "receipt.json");
81029
+ const receiptPath = isPath ? runId2 : join138(runsRoot2, runId2, "receipt.json");
80783
81030
  const byRunId = !isPath;
80784
81031
  rec2.runId = runId2;
80785
81032
  rec2.receiptPath = receiptPath;
80786
81033
  if (exportDsse)
80787
81034
  return exportDsseReceipt({ receiptPath, runId: byRunId ? runId2 : null, deps, verify: verifyReceipt, key: loadSigningKey(false), kidOf: kidOf2 });
80788
- const bad = byRunId ? runIdGuard(receiptPath, runId2) : null;
81035
+ const bad = byRunId ? runIdGuard(receiptPath, runId2) ?? signedRunIdProblem(receiptPath, runId2) : null;
80789
81036
  if (bad)
80790
81037
  return rec2.verdict = "TAMPERED", rec2.reasons = [bad], process.stdout.write(`run: ${runId2}
80791
81038
  verdict: TAMPERED
@@ -80795,7 +81042,7 @@ verdict: TAMPERED
80795
81042
  if (result.verdict === "VERIFIED" || result.verdict === "UNSIGNED") {
80796
81043
  const d = (() => {
80797
81044
  try {
80798
- return sealDrift(receiptPath, JSON.parse(readFileSync120(receiptPath, "utf8")));
81045
+ return sealDrift(receiptPath, JSON.parse(readFileSync121(receiptPath, "utf8")));
80799
81046
  } catch {
80800
81047
  return null;
80801
81048
  }
@@ -80808,7 +81055,7 @@ verdict: TAMPERED
80808
81055
  {
80809
81056
  const id2 = (() => {
80810
81057
  try {
80811
- const r = JSON.parse(readFileSync120(receiptPath, "utf8"));
81058
+ const r = JSON.parse(readFileSync121(receiptPath, "utf8"));
80812
81059
  const j10 = r["verification"]?.jwt;
80813
81060
  const k3 = result.verdict === "VERIFIED" && typeof j10 === "string" ? JSON.parse(Buffer.from(j10.split(".")[0], "base64url").toString()).kid : null;
80814
81061
  return { kid: typeof k3 === "string" ? k3 : null, head: typeof r["head_sha"] === "string" ? r["head_sha"] : null, verdict: typeof r["verdict"] === "string" ? r["verdict"] : null, run: typeof r["run_id"] === "string" ? r["run_id"] : null };
@@ -80826,7 +81073,7 @@ verdict: TAMPERED
80826
81073
  if (result.verdict === "VERIFIED" || result.verdict === "UNSIGNED") {
80827
81074
  const outcome = (() => {
80828
81075
  try {
80829
- return outcomeOf2(JSON.parse(readFileSync120(receiptPath, "utf8")));
81076
+ return outcomeOf2(JSON.parse(readFileSync121(receiptPath, "utf8")));
80830
81077
  } catch {
80831
81078
  return "UNREADABLE";
80832
81079
  }
@@ -80840,6 +81087,11 @@ verdict: NOT VERIFIED (run outcome ${outcome}; receipt integrity ${result.verdic
80840
81087
  return 4;
80841
81088
  }
80842
81089
  }
81090
+ if (result.verdict === "VERIFIED" || result.verdict === "UNSIGNED") {
81091
+ const note = wallNotComparedNote(receiptPath);
81092
+ if (note)
81093
+ result = { ...result, reasons: [...result.reasons, note] };
81094
+ }
80843
81095
  rec2.verdict = result.verdict;
80844
81096
  rec2.reasons = result.reasons;
80845
81097
  rec2.receiptSha256 = result.receiptSha256 ?? null;
@@ -80855,7 +81107,7 @@ verdict: ${result.verdict}
80855
81107
  `);
80856
81108
  if (result.verdict !== "TAMPERED")
80857
81109
  try {
80858
- const r = JSON.parse(readFileSync120(receiptPath, "utf8"));
81110
+ const r = JSON.parse(readFileSync121(receiptPath, "utf8"));
80859
81111
  if (isComposite(r))
80860
81112
  for (const l of compositeLines(r))
80861
81113
  process.stdout.write(`${l}
@@ -80913,8 +81165,8 @@ var init_verify_cmd = __esm(() => {
80913
81165
  });
80914
81166
 
80915
81167
  // src/server/app.ts
80916
- import { existsSync as existsSync98, readFileSync as readFileSync123, statSync as statSync38 } from "fs";
80917
- import { join as join140, resolve as resolve40, sep as sep23 } from "path";
81168
+ import { existsSync as existsSync98, readFileSync as readFileSync124, statSync as statSync38 } from "fs";
81169
+ import { join as join141, resolve as resolve40, sep as sep23 } from "path";
80918
81170
 
80919
81171
  // node_modules/hono/dist/request/constants.js
80920
81172
  var GET_MATCH_RESULT = Symbol();
@@ -91225,9 +91477,9 @@ function mount20(ctx) {
91225
91477
  }
91226
91478
 
91227
91479
  // src/server/routes/verify.ts
91228
- import { readFileSync as readFileSync121, realpathSync as realpathSync36 } from "fs";
91480
+ import { readFileSync as readFileSync122, realpathSync as realpathSync36 } from "fs";
91229
91481
  import { createPublicKey as createPublicKey7 } from "crypto";
91230
- import { join as join138, sep as sep22 } from "path";
91482
+ import { join as join139, sep as sep22 } from "path";
91231
91483
  init_verify_cmd();
91232
91484
  init_seal();
91233
91485
  init_receipt_dsse();
@@ -91254,11 +91506,11 @@ function mount21(ctx) {
91254
91506
  return done(404, "receipt not available", "not_found");
91255
91507
  let runDir, file;
91256
91508
  try {
91257
- const root = realpathSync36(join138(repo.p, ".loki", "runs"));
91258
- runDir = realpathSync36(join138(root, run2));
91259
- if (runDir !== join138(root, run2))
91509
+ const root = realpathSync36(join139(repo.p, ".loki", "runs"));
91510
+ runDir = realpathSync36(join139(root, run2));
91511
+ if (runDir !== join139(root, run2))
91260
91512
  return done(404, "receipt not found", "not_found");
91261
- file = realpathSync36(join138(runDir, "receipt.json"));
91513
+ file = realpathSync36(join139(runDir, "receipt.json"));
91262
91514
  } catch {
91263
91515
  return done(404, "receipt not found", "not_found");
91264
91516
  }
@@ -91277,7 +91529,7 @@ function mount21(ctx) {
91277
91529
  sha7 = r.receiptSha256 ?? null;
91278
91530
  }
91279
91531
  try {
91280
- outcome = outcomeOf2(JSON.parse(readFileSync121(file, "utf8")));
91532
+ outcome = outcomeOf2(JSON.parse(readFileSync122(file, "utf8")));
91281
91533
  } catch {
91282
91534
  outcome = "UNREADABLE";
91283
91535
  }
@@ -91339,8 +91591,8 @@ function ttlCache(ttlMs = PROBE_CACHE_MS, now2 = Date.now) {
91339
91591
  }
91340
91592
 
91341
91593
  // src/server/legacy/shim.ts
91342
- import { existsSync as existsSync97, readFileSync as readFileSync122 } from "fs";
91343
- import { join as join139 } from "path";
91594
+ import { existsSync as existsSync97, readFileSync as readFileSync123 } from "fs";
91595
+ import { join as join140 } from "path";
91344
91596
 
91345
91597
  // src/server/legacy/routes.ts
91346
91598
  var LEGACY_ROUTES = [
@@ -91718,10 +91970,10 @@ var logged = new Set;
91718
91970
  var toHono = (p) => p.replace(/\{([A-Za-z_]+):path\}/g, ":$1{.+}").replace(/\{([A-Za-z_]+)\}/g, ":$1");
91719
91971
  var NOT_SUPPORTED = "not yet supported by the Control Plane";
91720
91972
  var repoVersion = () => {
91721
- for (const f of [join139(import.meta.dir, "../../../../../VERSION")]) {
91973
+ for (const f of [join140(import.meta.dir, "../../../../../VERSION")]) {
91722
91974
  try {
91723
91975
  if (existsSync97(f))
91724
- return readFileSync122(f, "utf8").trim();
91976
+ return readFileSync123(f, "utf8").trim();
91725
91977
  } catch {}
91726
91978
  }
91727
91979
  return "unknown";
@@ -91903,7 +92155,7 @@ function legacyShim(opts) {
91903
92155
 
91904
92156
  // src/server/app.ts
91905
92157
  var MAX_BODY2 = 1e6;
91906
- var defaultUiDir = () => [join140(import.meta.dir, "../../ui/dist"), join140(import.meta.dir, "../ui/dist")].find((d) => existsSync98(join140(d, "index.html")));
92158
+ var defaultUiDir = () => [join141(import.meta.dir, "../../ui/dist"), join141(import.meta.dir, "../ui/dist")].find((d) => existsSync98(join141(d, "index.html")));
91907
92159
  function createApp(opts) {
91908
92160
  const uiDir = opts.uiDir ?? defaultUiDir();
91909
92161
  const { db: db2, sqlite } = openDb(opts.dbPath);
@@ -91932,10 +92184,10 @@ function createApp(opts) {
91932
92184
  await next();
91933
92185
  });
91934
92186
  const readInstalled = () => {
91935
- for (const f of [process.env.LOKI_VERSION_FILE, join140(import.meta.dir, "../../../../VERSION")]) {
92187
+ for (const f of [process.env.LOKI_VERSION_FILE, join141(import.meta.dir, "../../../../VERSION")]) {
91936
92188
  try {
91937
92189
  if (f)
91938
- return readFileSync123(f, "utf8").trim() || "unknown";
92190
+ return readFileSync124(f, "utf8").trim() || "unknown";
91939
92191
  } catch {}
91940
92192
  }
91941
92193
  return "unknown";
@@ -92050,7 +92302,7 @@ function createApp(opts) {
92050
92302
  return new Response(Bun.file(f));
92051
92303
  if (/\.[a-z0-9]+$/i.test(p))
92052
92304
  return c.json({ error: "not found" }, 404);
92053
- return new Response(Bun.file(join140(root, "index.html")));
92305
+ return new Response(Bun.file(join141(root, "index.html")));
92054
92306
  });
92055
92307
  return { app, db: db2, close: () => {
92056
92308
  clearInterval(reconciler);
@@ -92059,9 +92311,9 @@ function createApp(opts) {
92059
92311
  }
92060
92312
 
92061
92313
  // src/server/serve.ts
92062
- var refusal = bindRefusal(process.env);
92063
- if (refusal) {
92064
- console.error(refusal);
92314
+ var refusal2 = bindRefusal(process.env);
92315
+ if (refusal2) {
92316
+ console.error(refusal2);
92065
92317
  process.exit(2);
92066
92318
  }
92067
92319
  var warning = insecureBindWarning(process.env);