loki-mode 11.17.67 → 11.17.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/dashboard/__init__.py +1 -1
  4. package/docs/CLI-REFERENCE.md +1 -1
  5. package/docs/INSTALLATION.md +1 -1
  6. package/docs/v10/FAILURE-CLASSES.md +16 -0
  7. package/docs/v10/PROGRESS.md +3 -0
  8. package/loki-ts/dist/loki.js +1125 -1123
  9. package/mcp/__init__.py +1 -1
  10. package/package.json +2 -2
  11. package/packages/control-plane/dist/server.js +390 -338
  12. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  13. package/web-app/dist/assets/{AdminPage-Qa4gBgov.js → AdminPage-B15Qsswe.js} +1 -1
  14. package/web-app/dist/assets/{Avatar-efTNmkmO.js → Avatar-Tg0XGgMO.js} +1 -1
  15. package/web-app/dist/assets/{Badge-CK4rc7EB.js → Badge-Ca60FBOF.js} +1 -1
  16. package/web-app/dist/assets/{Button-EJaTtEtn.js → Button-JRbzwosm.js} +1 -1
  17. package/web-app/dist/assets/{CockpitPage-BQTfAMqI.js → CockpitPage-Q6PdXXXu.js} +1 -1
  18. package/web-app/dist/assets/{ComparePage-BVrkV0Ng.js → ComparePage-DIZPqHgs.js} +1 -1
  19. package/web-app/dist/assets/{ErrorBoundary-BNuHgr9r.js → ErrorBoundary-DYwpjJYQ.js} +1 -1
  20. package/web-app/dist/assets/{EvidenceReceiptPanel--Wa-QyXy.js → EvidenceReceiptPanel-A70AN7Jx.js} +1 -1
  21. package/web-app/dist/assets/{GitHubIssuesPanel-D-rAxU57.js → GitHubIssuesPanel-DxC81nZf.js} +1 -1
  22. package/web-app/dist/assets/{GitHubPRsPanel-D-EkwtNX.js → GitHubPRsPanel-CG-XS678.js} +1 -1
  23. package/web-app/dist/assets/{HomePage-DOqpDt3n.js → HomePage-g9GK0F4E.js} +2 -2
  24. package/web-app/dist/assets/{LoginPage-BdIpRA07.js → LoginPage-C3SUeWJ_.js} +1 -1
  25. package/web-app/dist/assets/{MagicPage-JmGuSXOw.js → MagicPage-C6uzZ_ZM.js} +1 -1
  26. package/web-app/dist/assets/{MetricsPage-rZmEbfYy.js → MetricsPage-gYF75wla.js} +1 -1
  27. package/web-app/dist/assets/{NotFoundPage-0f68R93z.js → NotFoundPage-Dg3peDQg.js} +1 -1
  28. package/web-app/dist/assets/{ProjectPage-Bp-ESNWK.js → ProjectPage-DgrTvsTT.js} +3 -3
  29. package/web-app/dist/assets/{ProjectsPage-BsBCWYpr.js → ProjectsPage-CS782pT9.js} +1 -1
  30. package/web-app/dist/assets/{SettingsPage-CNX97dyG.js → SettingsPage-BufM6rki.js} +1 -1
  31. package/web-app/dist/assets/{ShowcasePage-B6USf2fE.js → ShowcasePage-DUfcAQ3p.js} +1 -1
  32. package/web-app/dist/assets/{SystemSettingsPage-JOg76RLX.js → SystemSettingsPage-GGa7ZEAu.js} +1 -1
  33. package/web-app/dist/assets/{TeamsPage-C_MbEYKQ.js → TeamsPage-Duo-UX8d.js} +1 -1
  34. package/web-app/dist/assets/{TemplatesPage-D6GG3YaD.js → TemplatesPage-BiKp5wqf.js} +1 -1
  35. package/web-app/dist/assets/{TerminalOutput-xPHdR6Pn.js → TerminalOutput-BleBo8aa.js} +1 -1
  36. package/web-app/dist/assets/{activity-BsfOdOmx.js → activity-CzHPIm9R.js} +1 -1
  37. package/web-app/dist/assets/{bell-Bv2c5maD.js → bell-CX0W4Dl8.js} +1 -1
  38. package/web-app/dist/assets/{bot-CwISrbFp.js → bot-BVbxhF0V.js} +1 -1
  39. package/web-app/dist/assets/{check-4UMCmMrx.js → check-BrsmbSbu.js} +1 -1
  40. package/web-app/dist/assets/{chevron-left-DpKdpXdw.js → chevron-left-DSmawbvA.js} +1 -1
  41. package/web-app/dist/assets/{circle-alert-B10hQv6x.js → circle-alert-CQdXcZiI.js} +1 -1
  42. package/web-app/dist/assets/{clock-_fgSSzc8.js → clock-DlZBar7-.js} +1 -1
  43. package/web-app/dist/assets/{cloud-DcqwLZCt.js → cloud-B1PSR57L.js} +1 -1
  44. package/web-app/dist/assets/{code-xml-DWSzxARy.js → code-xml-BoRrOQ2s.js} +1 -1
  45. package/web-app/dist/assets/{database-BZNt8CdB.js → database-tR5zTmu6.js} +1 -1
  46. package/web-app/dist/assets/{dollar-sign-T2Q2FX-M.js → dollar-sign-DNZJ02Ej.js} +1 -1
  47. package/web-app/dist/assets/{file-code-corner-CNVXYv89.js → file-code-corner-CgsOh3Af.js} +1 -1
  48. package/web-app/dist/assets/{file-plus-J498H8Gi.js → file-plus-B7gxwh23.js} +1 -1
  49. package/web-app/dist/assets/{globe-yPUkr5E_.js → globe-CIy0VK9i.js} +1 -1
  50. package/web-app/dist/assets/{hammer-CiEKjMkP.js → hammer-Bks8T72X.js} +1 -1
  51. package/web-app/dist/assets/{index-B9O_HR7I.js → index-DBWJ1wdp.js} +3 -3
  52. package/web-app/dist/assets/{layers-C5je2Gm3.js → layers-D2NPSlUm.js} +1 -1
  53. package/web-app/dist/assets/{loader-circle-i2izIIWo.js → loader-circle-jJZaJ1OS.js} +1 -1
  54. package/web-app/dist/assets/{lock-B-jl4ziA.js → lock-DvtCAt-o.js} +1 -1
  55. package/web-app/dist/assets/{package-D5x3FL7c.js → package-Bi6Zqo8v.js} +1 -1
  56. package/web-app/dist/assets/{plus-BzSslmtd.js → plus-Ctah3HPx.js} +1 -1
  57. package/web-app/dist/assets/{refresh-cw-DfnUhgek.js → refresh-cw-BPY6lhZ1.js} +1 -1
  58. package/web-app/dist/assets/{rotate-ccw-iuRaooxt.js → rotate-ccw-CQ9TURIT.js} +1 -1
  59. package/web-app/dist/assets/{scroll-text-C7vGPzBx.js → scroll-text-BtMvvPvt.js} +1 -1
  60. package/web-app/dist/assets/{server-CQqjDruY.js → server-BinZFvpC.js} +1 -1
  61. package/web-app/dist/assets/{shield-alert-DhvInzrc.js → shield-alert-DDTgtEDV.js} +1 -1
  62. package/web-app/dist/assets/{thumbs-up-BJkdEnFB.js → thumbs-up-CqGJTWTZ.js} +1 -1
  63. package/web-app/dist/assets/{trash-2-DRXkf-Xt.js → trash-2-CCwsNari.js} +1 -1
  64. package/web-app/dist/assets/{trending-down-LoBkUtqd.js → trending-down-CUo25NgU.js} +1 -1
  65. package/web-app/dist/assets/{trending-up-BZrKN4XD.js → trending-up-OY9jb7Yb.js} +1 -1
  66. package/web-app/dist/assets/{upload-ChWk0ZsA.js → upload-BjtCOD-s.js} +1 -1
  67. package/web-app/dist/assets/{usePolling-Ttl__jEW.js → usePolling-88InUUXn.js} +1 -1
  68. package/web-app/dist/assets/{user-CuR9mmaM.js → user-Bq6O7zYo.js} +1 -1
  69. package/web-app/dist/index.html +1 -1
@@ -9418,15 +9418,15 @@ function classifyRisk(files, env = process.env) {
9418
9418
  summary
9419
9419
  };
9420
9420
  }
9421
- function changedFiles(repoDir, baseSha) {
9421
+ function changedFiles(repoDir, baseSha, skip) {
9422
9422
  const run = (args) => safeGit(repoDir, args).split(`
9423
9423
  `).map((l) => l.trim()).filter(Boolean);
9424
9424
  const tracked = run(["diff", "--name-only", baseSha]);
9425
9425
  const untracked = run(["ls-files", "--others", "--exclude-standard"]);
9426
- return [...new Set([...tracked, ...untracked])].filter((f) => !f.startsWith(".loki/"));
9426
+ return [...new Set([...tracked, ...untracked])].filter((f) => !f.startsWith(".loki/") && !skip?.(f));
9427
9427
  }
9428
- function diffFiles(repoDir, baseSha) {
9429
- const paths = changedFiles(repoDir, baseSha), stat = new Map;
9428
+ function diffFiles(repoDir, baseSha, skip) {
9429
+ const paths = changedFiles(repoDir, baseSha, skip), stat = new Map;
9430
9430
  for (const l of safeGit(repoDir, ["diff", "--numstat", baseSha]).split(`
9431
9431
  `)) {
9432
9432
  const [a, d, ...p] = l.split("\t"), path = p.join("\t");
@@ -9710,7 +9710,7 @@ var NO_TESTS_REASON = "no tests executed", GO_EXIT0_REASON = "test count could n
9710
9710
  `).filter((x) => x.trim()).slice(-12), GO_PKG_RE, isExecutedProof = (c) => c.result === "pass" && typeof c.n === "number" && c.n > 0, hasExecutedProof = (checks) => checks.some(isExecutedProof), LLM_JUDGES, NON_RUNNER, normPath = (p) => p.replace(/^(?:\.\/)+/, ""), hasExogenousProof = (checks, ctx) => checks.some((c) => isExecutedProof(c) && ((p) => p !== "agent_authored" && p !== "llm_judge")(checkProvenance(c.name ?? "", ctx))), SENSITIVE, API, TEST_CFG, RANK2, FILES_MEDIUM = 4, FILES_HIGH = 15, LINES_MEDIUM = 100, LINES_HIGH = 500, RAN_ALWAYS, PLAN, LOW_SKIPPED, deferredOf = (tier, selected, executed) => (tier === "low" ? LOW_SKIPPED : selected).filter((c) => !RAN_ALWAYS.includes(c) && !executed.includes(c)), MANIFEST_LOCKS, dirOf = (p) => p.includes("/") ? p.slice(0, p.lastIndexOf("/")) : "", PKG_DEP_KEYS, PYPROJECT_NONDEP, EXCERPT_GROUP_CAP = 1500, EXCERPT_TOTAL_CAP = 6144, verifyJobs = () => {
9711
9711
  const n2 = Number.parseInt(process.env["LOKI_E10_VERIFY_JOBS"] ?? "", 10);
9712
9712
  return Number.isFinite(n2) && n2 >= 1 ? Math.min(n2, 8) : 1;
9713
- };
9713
+ }, FULL_SUITE_CMD;
9714
9714
  var init_check_result = __esm(() => {
9715
9715
  init_resolve();
9716
9716
  init_testmap();
@@ -9748,6 +9748,16 @@ var init_check_result = __esm(() => {
9748
9748
  ];
9749
9749
  PKG_DEP_KEYS = ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"];
9750
9750
  PYPROJECT_NONDEP = /^(name|version|description|readme|license|requires-python|python|authors|maintainers|keywords|classifiers|homepage|repository|documentation|packages|include|exclude)$/;
9751
+ FULL_SUITE_CMD = {
9752
+ pytest: { cmd: "python", args: ["-m", "pytest", "-q"] },
9753
+ vitest: { cmd: "npx", args: ["vitest", "run"] },
9754
+ jest: { cmd: "npx", args: ["jest"] },
9755
+ bun: { cmd: "bun", args: ["test"] },
9756
+ node: { cmd: "node", args: ["--test"] },
9757
+ npm: { cmd: "npm", args: ["test", "--silent"] },
9758
+ go: { cmd: "go", args: ["test", "-json", "./..."] },
9759
+ cargo: { cmd: "cargo", args: ["test"] }
9760
+ };
9751
9761
  });
9752
9762
 
9753
9763
  // ../../loki-ts/src/util/receipt_signer.ts
@@ -10713,7 +10723,7 @@ function failIds(output) {
10713
10723
  }
10714
10724
  var ID_LINE;
10715
10725
  var init_failures = __esm(() => {
10716
- ID_LINE = /^(?:(?:FAILED|ERROR)\s+(\S+::\S*)(?:\s.*)?|\u25cf\s+(?!Console|Test suite failed)(.+)|not ok \d+ - (.+?)(?:\s+#.*)?|\u2716\s+(?!failing tests:)(.+?)(?:\s+\([\d.]+ms\))?|(?:FAIL|\u00d7)\s+(.+))$/;
10726
+ ID_LINE = /^(?:(?:FAILED|ERROR)\s+(\S+::\S*)(?:\s.*)?|\u25cf\s+(?!Console|Test suite failed)(.+)|not ok \d+ - (.+?)(?:\s+#.*)?|\u2716\s+(?!failing tests:)(.+?)(?:\s+\([\d.]+ms\))?|FAIL\s+(.+)|\u00d7\s+(.+?)(?:\s+\d+(?:\.\d+)?\s*m?s)?)$/;
10717
10727
  });
10718
10728
 
10719
10729
  // ../../loki-ts/src/runner/state.ts
@@ -10785,10 +10795,14 @@ function attribute(repoDir, baseSha, failing) {
10785
10795
  const p = loadProfile(repoDir), none = { preExistingChecks: [], preExistingIds: [], introducedChecks: failing.map((f) => f.name), line: null };
10786
10796
  if (!p || p.revision !== baseSha || !p.baseline.attributable || p.baseline.failing_ids.length === 0 || failing.length === 0)
10787
10797
  return none;
10788
- const base = new Set(p.baseline.failing_ids), pre = failing.filter((f) => f.eligible && f.ids?.length && f.ids.every((i) => base.has(i)));
10798
+ const base = new Set(p.baseline.failing_ids);
10799
+ return split(failing.map((f) => ({ ...f, base })), base.size);
10800
+ }
10801
+ function split(failing, known) {
10802
+ const pre = failing.filter((f) => f.eligible && f.ids?.length && f.ids.every((i) => f.base.has(i)));
10789
10803
  const introduced = failing.filter((f) => !pre.includes(f)).map((f) => f.name);
10790
10804
  if (pre.length === 0)
10791
- return { ...none, line: `baseline: ${base.size} known failure(s) before this run; none of the failing checks match them, ${introduced.length} introduced (blocking)` };
10805
+ return { preExistingChecks: [], preExistingIds: [], introducedChecks: introduced, line: `baseline: ${known} known failure(s) before this run; none of the failing checks match them, ${introduced.length} introduced (blocking)` };
10792
10806
  return {
10793
10807
  preExistingChecks: pre.map((f) => f.name),
10794
10808
  preExistingIds: pre.flatMap((f) => f.ids ?? []),
@@ -10797,14 +10811,20 @@ function attribute(repoDir, baseSha, failing) {
10797
10811
  };
10798
10812
  }
10799
10813
  function attributeFullSuite(repoDir, baseSha, full, blocked, changed) {
10800
- const bad = full.filter((c) => c.result === "fail"), none = { preExistingChecks: [], preExistingIds: [], introducedChecks: bad.map((c) => c.name), line: null };
10801
- const norm3 = (s) => s.replace(/\s+--silent\b/, "").trim(), p = loadProfile(repoDir);
10802
- if (!bad.length || !p || p.revision !== baseSha || !p.baseline.attributable || !p.baseline.failing_ids.length)
10814
+ const bad = full.filter((c) => c.result === "fail"), none = { preExistingChecks: [], preExistingIds: [], introducedChecks: bad.map((c) => c.name), line: null }, p = loadProfile(repoDir);
10815
+ if (!bad.length || !p || p.revision !== baseSha)
10803
10816
  return none;
10804
- if (bad.some((c) => norm3(c.cmd) !== norm3(p.baseline.command ?? "")))
10805
- return { ...none, line: `baseline: ran "${p.baseline.command}", not the full suite command, ids not comparable, full suite failures not excused` };
10806
- const block = new Set(blocked);
10807
- return attribute(repoDir, baseSha, bad.map((c) => ({ name: c.name, ...c.ids ? { ids: c.ids } : {}, eligible: (c.ids ?? []).every((i) => !block.has(i) && !changed.some((f) => i.includes(f))) })));
10817
+ const runs2 = [p.baseline, ...p.suites ?? []].filter((b) => b.ran), of = (cmd) => runs2.find((b) => normCmd(b.command ?? "") === normCmd(cmd));
10818
+ const ids = (cmd) => {
10819
+ const b = of(cmd);
10820
+ return b?.attributable ? b.failing_ids : [];
10821
+ }, miss = bad.find((c) => !of(c.cmd));
10822
+ if (miss)
10823
+ return { ...none, line: `baseline: ran ${runs2.map((b) => `"${b.command}"`).join(", ") || "nothing"}, not the full suite command "${miss.cmd}", ids not comparable, full suite failures not excused` };
10824
+ const known = new Set(bad.flatMap((c) => ids(c.cmd))), block = new Set(blocked);
10825
+ if (known.size === 0)
10826
+ return none;
10827
+ return split(bad.map((c) => ({ name: c.name, ...c.ids ? { ids: c.ids } : {}, eligible: (c.ids ?? []).every((i) => !block.has(i) && !changed.some((f) => i.includes(f))), base: new Set(ids(c.cmd)) })), known.size);
10808
10828
  }
10809
10829
  function parseStatic(tool, out2) {
10810
10830
  const re = STATIC_DIAG[tool], m = new Map;
@@ -10872,7 +10892,7 @@ var commandProfilePath = (repoDir) => join39(repoDir, ".loki", "state", "repo-pr
10872
10892
  } catch {
10873
10893
  return "";
10874
10894
  }
10875
- }, STATIC_DIAG, STATIC_NOISE, STATIC_SUMMARY;
10895
+ }, normCmd = (s) => s.replace(/\s+--silent\b/, "").trim(), STATIC_DIAG, STATIC_NOISE, STATIC_SUMMARY;
10876
10896
  var init_repo_profile = __esm(() => {
10877
10897
  init_failures();
10878
10898
  init_check_result();
@@ -12388,9 +12408,278 @@ function recordHoldoutTriage(runDir, entry) {
12388
12408
  var sha2 = (s) => createHash13("sha256").update(s).digest("hex"), WALL_HOLDOUT_DEFAULT_RATIO = 0.2, isHoldoutCheck = (name) => name.startsWith("holdout:"), holdoutDirFor = (runId2, repoDir) => join44(tmpdir6(), `loki-e10-holdout-${sha2(`${runId2}:${repoDir}`).slice(0, 16)}`), MANIFEST = "manifest.json", WALL_HOLDOUT_MIN = 5, HOLDOUT_TRIAGE_FILE = "holdout-triage.jsonl";
12389
12409
  var init_holdout = () => {};
12390
12410
 
12411
+ // ../../loki-ts/src/runner/runner_errors.ts
12412
+ function hasRealTestFailure(out2) {
12413
+ return /^\s*Tests:?\s+.*\b[1-9]\d* failed\b/m.test(out2) || /^(?:=+ )?.*\b[1-9]\d* failed\b.* in [\d.]+s/m.test(out2) || /^FAILED \S+::/m.test(out2) || /^(?:#|\u2139) fail [1-9]/m.test(out2) || /^\s*[1-9]\d*\s+fail\s*$/m.test(out2) || /^\s*(?:FAIL|\u00D7)\s+\S.*\s>\s/m.test(out2) || /\bAssertionError\b/.test(out2);
12414
+ }
12415
+ function firstLoadLine(out2) {
12416
+ const lines = out2.split(`
12417
+ `).map((l2) => l2.trim()).filter(Boolean);
12418
+ const l = lines.find((x) => /^(?:E\s+)?(?:Error|\w*Error|ERROR|Failed|FAIL)\b|Cannot find|Interrupted:|No test files found|\d+: [\w.-]+: not found$|: command not found$|canceled due to missing packages/.test(x)) ?? lines[0] ?? "";
12419
+ return l.replace(/\s+/g, " ").slice(0, 160);
12420
+ }
12421
+ function classifyRunnerOutput(out2) {
12422
+ if (!hasRealTestFailure(out2)) {
12423
+ for (const [re, why] of LOAD_PATTERNS) {
12424
+ if (re.test(out2))
12425
+ return { kind: "load_error", owner: "harness", reason: `runner could not load: ${why}: ${firstLoadLine(out2)}` };
12426
+ }
12427
+ }
12428
+ return { kind: "test_failure", owner: "code" };
12429
+ }
12430
+ var LOAD_PATTERNS;
12431
+ var init_runner_errors = __esm(() => {
12432
+ LOAD_PATTERNS = [
12433
+ [/Failed Suites\s+[1-9]/, "test suite failed to load"],
12434
+ [/Test suite failed to run/, "test suite failed to run"],
12435
+ [/Failed to load (?:url|config)|failed to load config|Failed to resolve (?:import|entry)/i, "runner config or import could not be loaded"],
12436
+ [/^\s*(?:\w*Error: )?Cannot find (?:module|package) '[^']+'/m, "module not found while loading tests"],
12437
+ [/ERR_MODULE_NOT_FOUND/, "module not found while loading tests"],
12438
+ [/Interrupted: \d+ errors? during collection/, "collection error"],
12439
+ [/^_+ ERROR collecting /m, "collection error"],
12440
+ [/ImportError while importing test module/, "test module import error"],
12441
+ [/ImportError: Failed to import test module/, "unittest test module import error"],
12442
+ [/^ERROR: (?:file or directory not found|not found:)/m, "test path not found by the runner"],
12443
+ [/No test files found, exiting with code [1-9]/, "runner found no test files (wrong cwd or path)"],
12444
+ [/\[setup failed\]|cannot find package|no required module provides package/, "go package could not be set up"],
12445
+ [/could not determine executable to run/i, "test runner executable not found"],
12446
+ [/^(?:\S+: )?(?:line \d+: )?[\w.-]+: command not found$/m, "test runner executable not found"],
12447
+ [/^(?:\S+: )?\d+: [\w.-]+: not found$/m, "test runner executable not found (not installed)"],
12448
+ [/^npm (?:error|ERR!) (?:npx )?canceled due to missing packages/m, "test runner package not installed"]
12449
+ ];
12450
+ });
12451
+
12452
+ // ../../loki-ts/src/runner/load_owner.ts
12453
+ import { spawnSync as spawnSync5 } from "child_process";
12454
+ import { mkdtempSync as mkdtempSync5, realpathSync as realpathSync19, rmSync as rmSync13 } from "fs";
12455
+ import { tmpdir as tmpdir7 } from "os";
12456
+ import { basename as basename18, extname as extname2, join as join45 } from "path";
12457
+ function changedFilesNamed(out2, repoDir, changed) {
12458
+ return changed.filter((f) => {
12459
+ if (out2.includes(f) || out2.includes(join45(repoDir, f)))
12460
+ return true;
12461
+ const segs = f.split("/");
12462
+ if (suffixes(segs, 2).some((x) => x !== f && bounded(out2, x, "(?![\\w-])")))
12463
+ return true;
12464
+ if (extname2(f) === ".go" && segs.length > 1 && suffixes(segs.slice(0, -1), 1).some((d) => new RegExp(`(?<=[\\w-])/${esc(d)}(?![\\w./-])`).test(out2)))
12465
+ return true;
12466
+ const stem = basename18(f, extname2(f));
12467
+ if (stem.length < 2 || stem === "index" || stem === "__init__")
12468
+ return false;
12469
+ return new RegExp(`(?<![\\w-])${esc(stem)}(?![\\w-])`).test(out2);
12470
+ });
12471
+ }
12472
+ function loadSignature(out2, roots) {
12473
+ let o = out2;
12474
+ for (const r of roots.flatMap((x) => {
12475
+ try {
12476
+ return [x, realpathSync19(x)];
12477
+ } catch {
12478
+ return [x];
12479
+ }
12480
+ }).sort((a, b) => b.length - a.length))
12481
+ o = o.split(r).join("<repo>");
12482
+ const keys = new Set;
12483
+ for (const m of o.matchAll(/Cannot find (?:module|package) '([^']+)'/g))
12484
+ keys.add(`mod:${m[1]}`);
12485
+ for (const m of o.matchAll(/([\w.-]+): command not found/g))
12486
+ keys.add(`cmd:${m[1]}`);
12487
+ for (const m of o.matchAll(/^(?:\S+: )?\d+: ([\w.-]+): not found$/gm))
12488
+ keys.add(`cmd:${m[1]}`);
12489
+ for (const m of o.matchAll(/canceled due to missing packages[^\[\n]*\[([^\]\n]*)\]/g))
12490
+ for (const p of (m[1] ?? "").split(",")) {
12491
+ const n2 = p.trim().replace(/^["']|["']$/g, "").replace(/(?<=.)@[^@/]*$/, "");
12492
+ if (n2)
12493
+ keys.add(`pkg:${n2}`);
12494
+ }
12495
+ return { keys, reason: (classifyRunnerOutput(o).reason ?? "").replace(/:\d+(?::\d+)?/g, "") };
12496
+ }
12497
+ function sameLoadError(head, base, headRoots, baseRoots) {
12498
+ const h = loadSignature(head, headRoots), b = loadSignature(base, baseRoots);
12499
+ if (b.keys.size)
12500
+ return h.keys.size > 0 && [...b.keys].every((k) => h.keys.has(k));
12501
+ return h.keys.size === 0 && h.reason === b.reason;
12502
+ }
12503
+ function killTree(pid) {
12504
+ const all = [pid];
12505
+ for (let k = 0;k < all.length; k++) {
12506
+ const kids = spawnSync5("pgrep", ["-P", String(all[k])], { encoding: "utf8", env: process.env }).stdout.split(/\s+/).filter(Boolean).map(Number);
12507
+ all.push(...kids.filter((x) => Number.isInteger(x) && !all.includes(x)));
12508
+ }
12509
+ try {
12510
+ if (Number.isInteger(pid) && pid > 1)
12511
+ process.kill(-pid, "SIGKILL");
12512
+ } catch {}
12513
+ for (const p of all.reverse()) {
12514
+ try {
12515
+ process.kill(p, "SIGKILL");
12516
+ } catch {}
12517
+ }
12518
+ }
12519
+ async function runOnBase(i, dir) {
12520
+ const sub2 = (s) => s.split(i.repoDir).join(dir);
12521
+ const stop = AbortSignal.any([i.signal, AbortSignal.timeout(i.timeoutMs ?? 60000)]);
12522
+ try {
12523
+ const proc = Bun.spawn([sub2(i.cmd), ...i.args.map(sub2)], {
12524
+ cwd: sub2(i.cwd ?? i.repoDir),
12525
+ stdin: "ignore",
12526
+ stdout: "pipe",
12527
+ stderr: "pipe",
12528
+ detached: true,
12529
+ env: { ...plainTestEnv(), ...i.env ?? {} }
12530
+ });
12531
+ let tail = "";
12532
+ const rs = [proc.stdout, proc.stderr].map((x) => x.getReader());
12533
+ const pumps = rs.map(async (r) => {
12534
+ const d = new TextDecoder;
12535
+ for (;; ) {
12536
+ const c = await r.read().catch(() => ({ done: true, value: undefined }));
12537
+ if (c.done)
12538
+ return;
12539
+ tail = (tail + d.decode(c.value, { stream: true })).slice(-65536);
12540
+ }
12541
+ });
12542
+ const cut = new Promise((res) => {
12543
+ if (stop.aborted)
12544
+ res(null);
12545
+ else
12546
+ stop.addEventListener("abort", () => res(null), { once: true });
12547
+ });
12548
+ const code = await Promise.race([proc.exited, cut]);
12549
+ if (code === null) {
12550
+ killTree(proc.pid);
12551
+ return null;
12552
+ }
12553
+ await Promise.race([Promise.all(pumps), new Promise((r) => setTimeout(r, 300))]);
12554
+ rs.forEach((r) => r.cancel().catch(() => {}));
12555
+ return stop.aborted || code === 0 ? null : stripAnsi(tail);
12556
+ } catch {
12557
+ return null;
12558
+ }
12559
+ }
12560
+ function changedSince(repoDir, baseSha, skip) {
12561
+ const g = (a) => safeGit(repoDir, a).split(`
12562
+ `).map((l) => l.trim()).filter(Boolean);
12563
+ return [...new Set([...g(["diff", "--name-only", baseSha]), ...g(["ls-files", "--others", "--exclude-standard"])])].filter((f) => !f.startsWith(".loki/") && !skip?.(f));
12564
+ }
12565
+ async function loadErrorIsHarnessOwned(i) {
12566
+ if (i.protect || !i.baseSha || i.signal.aborted)
12567
+ return false;
12568
+ let changed;
12569
+ try {
12570
+ changed = changedSince(i.repoDir, i.baseSha, i.skip);
12571
+ } catch {
12572
+ return false;
12573
+ }
12574
+ if (changedFilesNamed(i.out, i.repoDir, changed).length > 0)
12575
+ return false;
12576
+ if (i.args.some((a) => changed.includes(a.replace(/^\.\//, ""))))
12577
+ return false;
12578
+ const dir = mkdtempSync5(join45(tmpdir7(), "e10-loadown-"));
12579
+ const git3 = (args) => {
12580
+ safeGit(i.repoDir, args, { stdio: "ignore" });
12581
+ };
12582
+ try {
12583
+ git3(["worktree", "add", "--detach", dir, i.baseSha]);
12584
+ const base = await runOnBase(i, dir);
12585
+ return base !== null && classifyRunnerOutput(base).kind === "load_error" && sameLoadError(i.out, base, [i.repoDir, ...i.cwd ? [i.cwd] : []], [dir]);
12586
+ } catch {
12587
+ return false;
12588
+ } finally {
12589
+ try {
12590
+ git3(["worktree", "remove", "--force", dir]);
12591
+ } catch {}
12592
+ rmSync13(dir, { recursive: true, force: true });
12593
+ try {
12594
+ git3(["worktree", "prune"]);
12595
+ } catch {}
12596
+ }
12597
+ }
12598
+ async function harnessLoadReason(i) {
12599
+ const c = classifyRunnerOutput(i.out);
12600
+ return c.kind === "load_error" && await loadErrorIsHarnessOwned(i) ? c.reason : undefined;
12601
+ }
12602
+ var esc = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), suffixes = (segs, min) => segs.map((_, k) => segs.slice(k).join("/")).filter((x) => x.split("/").length >= min), bounded = (out2, tok2, tail) => new RegExp(`(?<![\\w.-])${esc(tok2)}${tail}`).test(out2);
12603
+ var init_load_owner = __esm(() => {
12604
+ init_runner_errors();
12605
+ init_safe_git();
12606
+ init_check_result();
12607
+ });
12608
+
12609
+ // ../../loki-ts/src/project_model/package_suite.ts
12610
+ import { join as join46 } from "path";
12611
+ function packageSuiteSpecs(api) {
12612
+ if (!isMultiRoot(api))
12613
+ return null;
12614
+ const specs = api.packages().filter((p) => p.commands.test).map((p) => {
12615
+ const tc = p.commands.test;
12616
+ return { name: `full suite: ${p.name}`, cmd: `(cd ${tc.cwd} && ${tc.cmd})`, cwd: tc.cwd, run: tc.cmd };
12617
+ });
12618
+ return specs.length ? specs : null;
12619
+ }
12620
+ async function runPackageSuites(repoDir, signal, opts, checks, notProven) {
12621
+ const api = loadProjectApi(repoDir), specs = packageSuiteSpecs(api);
12622
+ if (!api || !specs)
12623
+ return false;
12624
+ for (const { name, cmd: cmd2, cwd, run: line2 } of specs) {
12625
+ const started = Date.now();
12626
+ const r = await run(["bash", "-c", line2], { cwd: join46(repoDir, cwd), timeoutMs: opts.timeoutMs, ...opts.path ? { env: { PATH: opts.path } } : {} });
12627
+ const duration_s = (Date.now() - started) / 1000;
12628
+ if (signal.aborted) {
12629
+ checks.push({ name, cmd: cmd2, result: "not_run", duration_s });
12630
+ notProven.add(`not run: ${name} (aborted)`);
12631
+ continue;
12632
+ }
12633
+ const out2 = `${r.stdout}
12634
+ ${r.stderr}`;
12635
+ const lr = r.exitCode === 0 || !opts.baseSha ? undefined : await harnessLoadReason({ repoDir, baseSha: opts.baseSha, ...opts.skip ? { skip: opts.skip } : {}, out: out2, cmd: "bash", args: ["-c", line2], signal, cwd: join46(repoDir, cwd), ...opts.path ? { env: { PATH: opts.path } } : {} });
12636
+ if (lr) {
12637
+ checks.push({ name, cmd: cmd2, result: "not_run", duration_s });
12638
+ notProven.add(`${lr} (${name}; harness-owned)`);
12639
+ continue;
12640
+ }
12641
+ const cls = classifyCheck({ kind: "test", ok: r.exitCode === 0, out: out2, ...goRunner(line2) });
12642
+ checks.push({ name, cmd: cmd2, result: cls.result, duration_s, ...cls.result === "fail" ? { ids: failIds(out2) } : {} });
12643
+ if (cls.result === "not_run")
12644
+ notProven.add(`not run: ${name} (${cls.reason ?? NO_TESTS_REASON})`);
12645
+ }
12646
+ for (const pkg of api.packages().filter((p) => !p.commands.test))
12647
+ notProven.add(`full suite: package ${pkg.name} defines no test command`);
12648
+ return true;
12649
+ }
12650
+ var init_package_suite = __esm(() => {
12651
+ init_load_owner();
12652
+ init_check_result();
12653
+ init_shell();
12654
+ init_failures();
12655
+ init_resolve();
12656
+ });
12657
+
12658
+ // ../../loki-ts/src/project_model/install.ts
12659
+ function installOwned(repoDir, rec, env = process.env) {
12660
+ const r = rec, files = r && typeof r.files === "object" && r.files ? r.files : {}, dirs = Array.isArray(r?.dirs) ? r.dirs : [];
12661
+ return (f) => dirs.some((d) => typeof d === "string" && f.startsWith(d)) || Object.hasOwn(files, f) && (() => {
12662
+ try {
12663
+ return hashOf(repoDir, f, env) === files[f];
12664
+ } catch {
12665
+ return false;
12666
+ }
12667
+ })();
12668
+ }
12669
+ var memo3, STATUS_MAX_BUFFER, hashOf = (repoDir, path, env = process.env) => safeGit(repoDir, ["hash-object", "--no-filters", "--", path], { env }).trim();
12670
+ var init_install = __esm(() => {
12671
+ init_safe_git();
12672
+ init_yaml_key();
12673
+ init_repo_profile();
12674
+ init_package_suite();
12675
+ init_resolve();
12676
+ memo3 = new Set;
12677
+ STATUS_MAX_BUFFER = 64 * 1024 * 1024;
12678
+ });
12679
+
12391
12680
  // ../../loki-ts/src/features/runner_config.ts
12392
12681
  import { readFileSync as readFileSync37 } from "fs";
12393
- import { dirname as dirname17, join as join45, normalize as normalize2 } from "path";
12682
+ import { dirname as dirname17, join as join47, normalize as normalize2 } from "path";
12394
12683
  function tomlKey2(s, i = 0, eq2 = true) {
12395
12684
  const parts = [], ws = () => {
12396
12685
  while (/\s/.test(s[i] ?? "x"))
@@ -12667,8 +12956,8 @@ function referenced(cfg, text2) {
12667
12956
  }
12668
12957
  const dir = dirname17(cfg), explicit = ROOT_DIR.exec(text2), roots = [dir];
12669
12958
  if (explicit)
12670
- roots.push("", ...explicit[1] ? [join45(dir, explicit[1])] : []);
12671
- return [...raw2.flatMap((r) => r.startsWith("/") ? [normalize2(r.slice(1))] : roots.map((root) => normalize2(join45(root, r.replace(/^<rootDir>\/?/, ""))))), ...patchedTargets(cfg, text2).map((t) => normalize2(join45(dir, t)))];
12959
+ roots.push("", ...explicit[1] ? [join47(dir, explicit[1])] : []);
12960
+ return [...raw2.flatMap((r) => r.startsWith("/") ? [normalize2(r.slice(1))] : roots.map((root) => normalize2(join47(root, r.replace(/^<rootDir>\/?/, ""))))), ...patchedTargets(cfg, text2).map((t) => normalize2(join47(dir, t)))];
12672
12961
  }
12673
12962
  function runnerConfigNotes(repoDir, baseSha, head, changed, signal) {
12674
12963
  const notes = new Set, ch = new Set(changed.map((c) => normalize2(c)));
@@ -12748,7 +13037,7 @@ var PKG_KEYS, RAW_CONFIGS, RUNNER_CONFIGS, DEP_MAPS, RUNNER_DEP, LOCAL_SPEC, dep
12748
13037
  }
12749
13038
  }, headText = (dir, f) => {
12750
13039
  try {
12751
- return readFileSync37(join45(dir, f), "utf8");
13040
+ return readFileSync37(join47(dir, f), "utf8");
12752
13041
  } catch {
12753
13042
  return "";
12754
13043
  }
@@ -12787,21 +13076,21 @@ var init_runner_config = __esm(() => {
12787
13076
  });
12788
13077
 
12789
13078
  // ../../loki-ts/src/e10ext/assert_delta.ts
12790
- import { execFileSync as execFileSync3 } from "child_process";
12791
- import { mkdtempSync as mkdtempSync5, readFileSync as readFileSync38, rmSync as rmSync13 } from "fs";
12792
- import { tmpdir as tmpdir7 } from "os";
12793
- import { join as join46 } from "path";
12794
- import { basename as basename18 } from "path";
13079
+ import { execFileSync as execFileSync4 } from "child_process";
13080
+ import { mkdtempSync as mkdtempSync6, readFileSync as readFileSync38, rmSync as rmSync14 } from "fs";
13081
+ import { tmpdir as tmpdir8 } from "os";
13082
+ import { join as join48 } from "path";
13083
+ import { basename as basename19 } from "path";
12795
13084
  function classifyAssertDelta(inp) {
12796
- const f = basename18(inp.path);
13085
+ const f = basename19(inp.path);
12797
13086
  if (!/^(test_.*|.*_test)\.py$/.test(f))
12798
13087
  return WEAKENED;
12799
13088
  if (inp.headCounts.run !== inp.baseCounts.run || inp.headCounts.skipped !== inp.baseCounts.skipped)
12800
13089
  return WEAKENED;
12801
13090
  let cwd = "";
12802
13091
  try {
12803
- cwd = mkdtempSync5(join46(tmpdir7(), "loki-ad-"));
12804
- const raw2 = execFileSync3("python3", ["-I", "-c", PY], {
13092
+ cwd = mkdtempSync6(join48(tmpdir8(), "loki-ad-"));
13093
+ const raw2 = execFileSync4("python3", ["-I", "-c", PY], {
12805
13094
  input: JSON.stringify({ path: inp.path, base: inp.base, head: inp.head, task: inp.task }),
12806
13095
  cwd,
12807
13096
  env: process.env,
@@ -12823,7 +13112,7 @@ function classifyAssertDelta(inp) {
12823
13112
  return WEAKENED;
12824
13113
  } finally {
12825
13114
  if (cwd)
12826
- rmSync13(cwd, { recursive: true, force: true });
13115
+ rmSync14(cwd, { recursive: true, force: true });
12827
13116
  }
12828
13117
  }
12829
13118
  function assertDeltaNotes(repoDir, baseSha, headRef, path, task, baseCounts, headCounts) {
@@ -12831,7 +13120,7 @@ function assertDeltaNotes(repoDir, baseSha, headRef, path, task, baseCounts, hea
12831
13120
  return null;
12832
13121
  try {
12833
13122
  const show = (ref) => safeGit(repoDir, ["show", `${ref}:${path}`]);
12834
- const head = headRef ? show(headRef) : readFileSync38(join46(repoDir, path), "utf8");
13123
+ const head = headRef ? show(headRef) : readFileSync38(join48(repoDir, path), "utf8");
12835
13124
  const r = classifyTestEdit(path, show(baseSha), head, task, baseCounts, headCounts);
12836
13125
  return r[0]?.kind === "literal-only" ? r.map((e) => `assertion value changed (not shown to be required by the task): ${e.file}:${e.line} ${e.old} -> ${e.new}`) : null;
12837
13126
  } catch {
@@ -13013,196 +13302,8 @@ var init_select = __esm(() => {
13013
13302
  PYTEST_COLLECTION_EXITS = new Set([2, 3, 4, 5]);
13014
13303
  });
13015
13304
 
13016
- // ../../loki-ts/src/runner/runner_errors.ts
13017
- function hasRealTestFailure(out2) {
13018
- return /^\s*Tests:?\s+.*\b[1-9]\d* failed\b/m.test(out2) || /^(?:=+ )?.*\b[1-9]\d* failed\b.* in [\d.]+s/m.test(out2) || /^FAILED \S+::/m.test(out2) || /^(?:#|\u2139) fail [1-9]/m.test(out2) || /^\s*[1-9]\d*\s+fail\s*$/m.test(out2) || /^\s*(?:FAIL|\u00D7)\s+\S.*\s>\s/m.test(out2) || /\bAssertionError\b/.test(out2);
13019
- }
13020
- function firstLoadLine(out2) {
13021
- const lines2 = out2.split(`
13022
- `).map((l2) => l2.trim()).filter(Boolean);
13023
- const l = lines2.find((x) => /^(?:E\s+)?(?:Error|\w*Error|ERROR|Failed|FAIL)\b|Cannot find|Interrupted:|No test files found/.test(x)) ?? lines2[0] ?? "";
13024
- return l.replace(/\s+/g, " ").slice(0, 160);
13025
- }
13026
- function classifyRunnerOutput(out2) {
13027
- if (!hasRealTestFailure(out2)) {
13028
- for (const [re, why] of LOAD_PATTERNS) {
13029
- if (re.test(out2))
13030
- return { kind: "load_error", owner: "harness", reason: `runner could not load: ${why}: ${firstLoadLine(out2)}` };
13031
- }
13032
- }
13033
- return { kind: "test_failure", owner: "code" };
13034
- }
13035
- var LOAD_PATTERNS;
13036
- var init_runner_errors = __esm(() => {
13037
- LOAD_PATTERNS = [
13038
- [/Failed Suites\s+[1-9]/, "test suite failed to load"],
13039
- [/Test suite failed to run/, "test suite failed to run"],
13040
- [/Failed to load (?:url|config)|failed to load config|Failed to resolve (?:import|entry)/i, "runner config or import could not be loaded"],
13041
- [/^\s*(?:\w*Error: )?Cannot find (?:module|package) '[^']+'/m, "module not found while loading tests"],
13042
- [/ERR_MODULE_NOT_FOUND/, "module not found while loading tests"],
13043
- [/Interrupted: \d+ errors? during collection/, "collection error"],
13044
- [/^_+ ERROR collecting /m, "collection error"],
13045
- [/ImportError while importing test module/, "test module import error"],
13046
- [/ImportError: Failed to import test module/, "unittest test module import error"],
13047
- [/^ERROR: (?:file or directory not found|not found:)/m, "test path not found by the runner"],
13048
- [/No test files found, exiting with code [1-9]/, "runner found no test files (wrong cwd or path)"],
13049
- [/\[setup failed\]|cannot find package|no required module provides package/, "go package could not be set up"],
13050
- [/could not determine executable to run/i, "test runner executable not found"],
13051
- [/^(?:\S+: )?(?:line \d+: )?[\w.-]+: command not found$/m, "test runner executable not found"]
13052
- ];
13053
- });
13054
-
13055
- // ../../loki-ts/src/runner/load_owner.ts
13056
- import { spawnSync as spawnSync5 } from "child_process";
13057
- import { mkdtempSync as mkdtempSync6, realpathSync as realpathSync19, rmSync as rmSync14 } from "fs";
13058
- import { tmpdir as tmpdir8 } from "os";
13059
- import { basename as basename19, extname as extname2, join as join47 } from "path";
13060
- function changedFilesNamed(out2, repoDir, changed) {
13061
- return changed.filter((f) => {
13062
- if (out2.includes(f) || out2.includes(join47(repoDir, f)))
13063
- return true;
13064
- const segs = f.split("/");
13065
- if (suffixes(segs, 2).some((x) => x !== f && bounded(out2, x, "(?![\\w-])")))
13066
- return true;
13067
- if (extname2(f) === ".go" && segs.length > 1 && suffixes(segs.slice(0, -1), 1).some((d) => new RegExp(`(?<=[\\w-])/${esc(d)}(?![\\w./-])`).test(out2)))
13068
- return true;
13069
- const stem = basename19(f, extname2(f));
13070
- if (stem.length < 2 || stem === "index" || stem === "__init__")
13071
- return false;
13072
- return new RegExp(`(?<![\\w-])${esc(stem)}(?![\\w-])`).test(out2);
13073
- });
13074
- }
13075
- function loadSignature(out2, roots) {
13076
- let o = out2;
13077
- for (const r of roots.flatMap((x) => {
13078
- try {
13079
- return [x, realpathSync19(x)];
13080
- } catch {
13081
- return [x];
13082
- }
13083
- }).sort((a, b) => b.length - a.length))
13084
- o = o.split(r).join("<repo>");
13085
- const keys = new Set;
13086
- for (const m of o.matchAll(/Cannot find (?:module|package) '([^']+)'/g))
13087
- keys.add(`mod:${m[1]}`);
13088
- for (const m of o.matchAll(/([\w.-]+): command not found/g))
13089
- keys.add(`cmd:${m[1]}`);
13090
- return { keys, reason: (classifyRunnerOutput(o).reason ?? "").replace(/:\d+(?::\d+)?/g, "") };
13091
- }
13092
- function sameLoadError(head, base, headRoots, baseRoots) {
13093
- const h = loadSignature(head, headRoots), b = loadSignature(base, baseRoots);
13094
- if (b.keys.size)
13095
- return h.keys.size > 0 && [...b.keys].every((k) => h.keys.has(k));
13096
- return h.keys.size === 0 && h.reason === b.reason;
13097
- }
13098
- function killTree(pid) {
13099
- const all = [pid];
13100
- for (let k = 0;k < all.length; k++) {
13101
- const kids = spawnSync5("pgrep", ["-P", String(all[k])], { encoding: "utf8", env: process.env }).stdout.split(/\s+/).filter(Boolean).map(Number);
13102
- all.push(...kids.filter((x) => Number.isInteger(x) && !all.includes(x)));
13103
- }
13104
- try {
13105
- if (Number.isInteger(pid) && pid > 1)
13106
- process.kill(-pid, "SIGKILL");
13107
- } catch {}
13108
- for (const p of all.reverse()) {
13109
- try {
13110
- process.kill(p, "SIGKILL");
13111
- } catch {}
13112
- }
13113
- }
13114
- async function runOnBase(i, dir) {
13115
- const sub2 = (s) => s.split(i.repoDir).join(dir);
13116
- const stop = AbortSignal.any([i.signal, AbortSignal.timeout(i.timeoutMs ?? 60000)]);
13117
- try {
13118
- const proc = Bun.spawn([sub2(i.cmd), ...i.args.map(sub2)], {
13119
- cwd: sub2(i.cwd ?? i.repoDir),
13120
- stdin: "ignore",
13121
- stdout: "pipe",
13122
- stderr: "pipe",
13123
- detached: true,
13124
- env: { ...plainTestEnv(), ...i.env ?? {} }
13125
- });
13126
- let tail = "";
13127
- const rs = [proc.stdout, proc.stderr].map((x) => x.getReader());
13128
- const pumps = rs.map(async (r) => {
13129
- const d = new TextDecoder;
13130
- for (;; ) {
13131
- const c = await r.read().catch(() => ({ done: true, value: undefined }));
13132
- if (c.done)
13133
- return;
13134
- tail = (tail + d.decode(c.value, { stream: true })).slice(-65536);
13135
- }
13136
- });
13137
- const cut = new Promise((res) => {
13138
- if (stop.aborted)
13139
- res(null);
13140
- else
13141
- stop.addEventListener("abort", () => res(null), { once: true });
13142
- });
13143
- const code = await Promise.race([proc.exited, cut]);
13144
- if (code === null) {
13145
- killTree(proc.pid);
13146
- return null;
13147
- }
13148
- await Promise.race([Promise.all(pumps), new Promise((r) => setTimeout(r, 300))]);
13149
- rs.forEach((r) => r.cancel().catch(() => {}));
13150
- return stop.aborted || code === 0 ? null : stripAnsi(tail);
13151
- } catch {
13152
- return null;
13153
- }
13154
- }
13155
- function changedSince(repoDir, baseSha) {
13156
- const g = (a) => safeGit(repoDir, a).split(`
13157
- `).map((l) => l.trim()).filter(Boolean);
13158
- return [...new Set([...g(["diff", "--name-only", baseSha]), ...g(["ls-files", "--others", "--exclude-standard"])])].filter((f) => !f.startsWith(".loki/"));
13159
- }
13160
- async function loadErrorIsHarnessOwned(i) {
13161
- if (i.protect || !i.baseSha || i.signal.aborted)
13162
- return false;
13163
- let changed;
13164
- try {
13165
- changed = changedSince(i.repoDir, i.baseSha);
13166
- } catch {
13167
- return false;
13168
- }
13169
- if (changedFilesNamed(i.out, i.repoDir, changed).length > 0)
13170
- return false;
13171
- if (i.args.some((a) => changed.includes(a.replace(/^\.\//, ""))))
13172
- return false;
13173
- const dir = mkdtempSync6(join47(tmpdir8(), "e10-loadown-"));
13174
- const git3 = (args) => {
13175
- safeGit(i.repoDir, args, { stdio: "ignore" });
13176
- };
13177
- try {
13178
- git3(["worktree", "add", "--detach", dir, i.baseSha]);
13179
- const base = await runOnBase(i, dir);
13180
- return base !== null && classifyRunnerOutput(base).kind === "load_error" && sameLoadError(i.out, base, [i.repoDir, ...i.cwd ? [i.cwd] : []], [dir]);
13181
- } catch {
13182
- return false;
13183
- } finally {
13184
- try {
13185
- git3(["worktree", "remove", "--force", dir]);
13186
- } catch {}
13187
- rmSync14(dir, { recursive: true, force: true });
13188
- try {
13189
- git3(["worktree", "prune"]);
13190
- } catch {}
13191
- }
13192
- }
13193
- async function harnessLoadReason(i) {
13194
- const c = classifyRunnerOutput(i.out);
13195
- return c.kind === "load_error" && await loadErrorIsHarnessOwned(i) ? c.reason : undefined;
13196
- }
13197
- var esc = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), suffixes = (segs, min) => segs.map((_, k) => segs.slice(k).join("/")).filter((x) => x.split("/").length >= min), bounded = (out2, tok2, tail) => new RegExp(`(?<![\\w.-])${esc(tok2)}${tail}`).test(out2);
13198
- var init_load_owner = __esm(() => {
13199
- init_runner_errors();
13200
- init_safe_git();
13201
- init_check_result();
13202
- });
13203
-
13204
13305
  // ../../loki-ts/src/util/wall_owned.ts
13205
- import { isAbsolute as isAbsolute7, join as join48, relative as relative6 } from "path";
13306
+ import { isAbsolute as isAbsolute7, join as join49, relative as relative6 } from "path";
13206
13307
  function failingLocations(raw2, cwd, repoDir) {
13207
13308
  const out2 = raw2.replace(ANSI2, "").replace(/\r\n?/g, `
13208
13309
  `), files = new Set;
@@ -13234,7 +13335,7 @@ function failingLocations(raw2, cwd, repoDir) {
13234
13335
  }
13235
13336
  if (errors2 === 0 || located !== errors2)
13236
13337
  return null;
13237
- return [...files].map((f) => relative6(repoDir, isAbsolute7(f) ? f : join48(cwd, f)));
13338
+ return [...files].map((f) => relative6(repoDir, isAbsolute7(f) ? f : join49(cwd, f)));
13238
13339
  }
13239
13340
  function wallOwnedFailure(raw2, cwd, repoDir, wall) {
13240
13341
  const locs = failingLocations(raw2, cwd, repoDir);
@@ -13248,7 +13349,7 @@ var init_wall_owned = __esm(() => {
13248
13349
  // ../../loki-ts/src/util/app_probe.ts
13249
13350
  import { spawnSync as spawnSync6 } from "child_process";
13250
13351
  import { existsSync as existsSync30, mkdirSync as mkdirSync19, readFileSync as readFileSync39, renameSync as renameSync11, writeFileSync as writeFileSync22 } from "fs";
13251
- import { join as join49 } from "path";
13352
+ import { join as join50 } from "path";
13252
13353
  function readJson4(p) {
13253
13354
  try {
13254
13355
  const v = JSON.parse(readFileSync39(p, "utf8"));
@@ -13258,14 +13359,14 @@ function readJson4(p) {
13258
13359
  }
13259
13360
  }
13260
13361
  function stopApp(repoDir, opts = {}) {
13261
- const runner = opts.runnerPath ?? join49(REPO_ROOT, "autonomy", "app-runner.sh");
13262
- if (!existsSync30(runner) || !existsSync30(join49(repoDir, ".loki", "app-runner", "app.pid")))
13362
+ const runner = opts.runnerPath ?? join50(REPO_ROOT, "autonomy", "app-runner.sh");
13363
+ if (!existsSync30(runner) || !existsSync30(join50(repoDir, ".loki", "app-runner", "app.pid")))
13263
13364
  return;
13264
13365
  spawnSync6("bash", ["-c", STOP, "app-probe", repoDir, runner], { cwd: repoDir, env: plainTestEnv(), timeout: opts.timeoutMs ?? 60000, killSignal: "SIGKILL", stdio: "ignore" });
13265
13366
  }
13266
13367
  async function appProbe(repoDir, lokiDir2, opts = {}) {
13267
- const timeoutMs = opts.timeoutMs ?? 60000, runner = opts.runnerPath ?? join49(REPO_ROOT, "autonomy", "app-runner.sh");
13268
- const dir = join49(repoDir, ".loki", "app-runner"), checks = [];
13368
+ const timeoutMs = opts.timeoutMs ?? 60000, runner = opts.runnerPath ?? join50(REPO_ROOT, "autonomy", "app-runner.sh");
13369
+ const dir = join50(repoDir, ".loki", "app-runner"), checks = [];
13269
13370
  const t0 = Date.now();
13270
13371
  const mk2 = (name, result, reason) => ({ name, cmd: "autonomy/app-runner.sh", result, duration_s: (Date.now() - t0) / 1000, reason });
13271
13372
  const sh = (script) => {
@@ -13283,9 +13384,9 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
13283
13384
  return { checks, pid, url };
13284
13385
  }
13285
13386
  const ir = Number(m[1]), sr = Number(m[2]), hr = Number(m[3]);
13286
- const pidTxt = existsSync30(join49(dir, "app.pid")) ? readFileSync39(join49(dir, "app.pid"), "utf8").trim() : "";
13387
+ const pidTxt = existsSync30(join50(dir, "app.pid")) ? readFileSync39(join50(dir, "app.pid"), "utf8").trim() : "";
13287
13388
  pid = /^\d+$/.test(pidTxt) && sr >= 0 ? Number(pidTxt) : null;
13288
- const st = readJson4(join49(dir, "state.json"));
13389
+ const st = readJson4(join50(dir, "state.json"));
13289
13390
  url = typeof st?.["url"] === "string" ? st["url"] : null;
13290
13391
  if (sr < 0) {
13291
13392
  checks.push(mk2("app boot", "not_run", ir === 0 ? "app-runner detected no app" : "no runnable app detected or runtime missing"), mk2("http probe", "not_run", "app not booted"));
@@ -13296,7 +13397,7 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
13296
13397
  return { checks, pid, url };
13297
13398
  }
13298
13399
  checks.push(mk2("app boot", "pass", "app process started"));
13299
- const health = readJson4(join49(dir, "health.json"));
13400
+ const health = readJson4(join50(dir, "health.json"));
13300
13401
  checks.push(hr === 0 && health?.["ok"] === true ? mk2("http probe", "pass", "health.json ok") : mk2("http probe", "fail", "app-runner health check failed"));
13301
13402
  if (opts.specText !== undefined && checks[1]?.result === "pass" && url)
13302
13403
  checks.push(await functionalVerify(opts, url, dir, lokiDir2, timeoutMs));
@@ -13309,10 +13410,10 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
13309
13410
  async function functionalVerify(opts, url, dir, lokiDir2, timeoutMs) {
13310
13411
  const t0 = Date.now();
13311
13412
  const res = (result, reason) => ({ name: "functional verify", cmd: "autonomy/lib/functional-verify.py", result, duration_s: (Date.now() - t0) / 1000, reason });
13312
- const py = await findPython3(), script = opts.verifyPath ?? join49(REPO_ROOT, "autonomy", "lib", "functional-verify.py");
13413
+ const py = await findPython3(), script = opts.verifyPath ?? join50(REPO_ROOT, "autonomy", "lib", "functional-verify.py");
13313
13414
  if (!py || !existsSync30(script))
13314
13415
  return res("not_run", "python3 or functional-verify.py unavailable");
13315
- const specFile = join49(dir, "spec.txt");
13416
+ const specFile = join50(dir, "spec.txt");
13316
13417
  writeFileSync22(specFile, opts.specText ?? "");
13317
13418
  const r = spawnSync6(py, ["-I", script, specFile, url], { env: plainTestEnv(), encoding: "utf8", timeout: timeoutMs, killSignal: "SIGKILL", stdio: ["ignore", "pipe", "ignore"] });
13318
13419
  let out2 = null;
@@ -13324,11 +13425,11 @@ async function functionalVerify(opts, url, dir, lokiDir2, timeoutMs) {
13324
13425
  }
13325
13426
  if (!out2 || r.status !== 0)
13326
13427
  return res("not_run", "functional harness produced no result");
13327
- const q = join49(lokiDir2, "quality");
13428
+ const q = join50(lokiDir2, "quality");
13328
13429
  mkdirSync19(q, { recursive: true });
13329
- const tmp = join49(q, `functional-results.json.tmp.${process.pid}`);
13430
+ const tmp = join50(q, `functional-results.json.tmp.${process.pid}`);
13330
13431
  writeFileSync22(tmp, JSON.stringify(out2, null, 2));
13331
- renameSync11(tmp, join49(q, "functional-results.json"));
13432
+ renameSync11(tmp, join50(q, "functional-results.json"));
13332
13433
  const s = String(out2["functional_status"] ?? "inconclusive");
13333
13434
  return res(s === "verified" ? "pass" : s === "failed" ? "fail" : "not_run", `functional_status ${s}`);
13334
13435
  }
@@ -13361,12 +13462,12 @@ app_runner_stop >/dev/null 2>&1
13361
13462
  import { existsSync as existsSync31, mkdirSync as mkdirSync20, mkdtempSync as mkdtempSync7, readFileSync as readFileSync40, realpathSync as realpathSync20, rmSync as rmSync15, statSync as statSync19, writeFileSync as writeFileSync23 } from "fs";
13362
13463
  import { randomBytes as randomBytes5 } from "crypto";
13363
13464
  import { tmpdir as tmpdir9 } from "os";
13364
- import { basename as basename20, dirname as dirname18, join as join50, resolve as resolve15, sep as sep11 } from "path";
13465
+ import { basename as basename20, dirname as dirname18, join as join51, resolve as resolve15, sep as sep11 } from "path";
13365
13466
  function fail(error) {
13366
13467
  return { ok: false, findings: [], error };
13367
13468
  }
13368
13469
  async function runSecureScan(targetDir, opts = {}) {
13369
- const script = opts.scriptPath ?? join50(REPO_ROOT, "autonomy", "lib", "secure-scan.py");
13470
+ const script = opts.scriptPath ?? join51(REPO_ROOT, "autonomy", "lib", "secure-scan.py");
13370
13471
  if (!existsSync31(script))
13371
13472
  return fail(`secure-scan script not found: ${script}`);
13372
13473
  const py = await findPython3();
@@ -13536,7 +13637,7 @@ async function scanAddedLines(repoDir, opts = {}) {
13536
13637
  const skipped2 = [];
13537
13638
  for (const p of untracked.split("\x00").filter(Boolean)) {
13538
13639
  try {
13539
- const st = statSync19(join50(repoDir, p));
13640
+ const st = statSync19(join51(repoDir, p));
13540
13641
  if (!st.isFile())
13541
13642
  continue;
13542
13643
  if (st.size > MAX_ADDED_FILE_BYTES) {
@@ -13551,14 +13652,14 @@ async function scanAddedLines(repoDir, opts = {}) {
13551
13652
  continue;
13552
13653
  }
13553
13654
  const lines2 = new Map;
13554
- readFileSync40(join50(repoDir, p), "utf8").split(`
13655
+ readFileSync40(join51(repoDir, p), "utf8").split(`
13555
13656
  `).forEach((t, i) => lines2.set(i + 1, t));
13556
13657
  added.set(p, lines2);
13557
13658
  } catch {}
13558
13659
  }
13559
13660
  if (added.size === 0)
13560
13661
  return { ok: true, findings: skipped2 };
13561
- const mirror = mkdtempSync7(join50(tmpdir9(), "loki-secure-added-"));
13662
+ const mirror = mkdtempSync7(join51(tmpdir9(), "loki-secure-added-"));
13562
13663
  try {
13563
13664
  const root = resolve15(mirror) + sep11;
13564
13665
  const chunkMap = new Map;
@@ -13604,7 +13705,7 @@ async function scanAddedLines(repoDir, opts = {}) {
13604
13705
  chunks.push(cur);
13605
13706
  const whole = chunks.length === 1;
13606
13707
  for (const c of chunks) {
13607
- const rel = whole ? p : join50(chunkRoot, String(chunkSeq++), basename20(p));
13708
+ const rel = whole ? p : join51(chunkRoot, String(chunkSeq++), basename20(p));
13608
13709
  const out2 = whole ? dest : resolve15(mirror, rel);
13609
13710
  if (!out2.startsWith(root))
13610
13711
  break;
@@ -13756,7 +13857,7 @@ import { spawn as spawn8 } from "child_process";
13756
13857
  import { createHash as createHash14, randomBytes as randomBytes6 } from "crypto";
13757
13858
  import { existsSync as existsSync32, lstatSync as lstatSync12, mkdirSync as mkdirSync21, readdirSync as readdirSync18, readFileSync as readFileSync41, writeFileSync as writeFileSync24 } from "fs";
13758
13859
  import { createServer } from "net";
13759
- import { dirname as dirname19, isAbsolute as isAbsolute8, join as join51, normalize as normalize3, relative as relative7, sep as sep12 } from "path";
13860
+ import { dirname as dirname19, isAbsolute as isAbsolute8, join as join52, normalize as normalize3, relative as relative7, sep as sep12 } from "path";
13760
13861
  function routeFor(file) {
13761
13862
  let r = file.replace(/^(?:.*?\/)?(?:app|pages|src|public)\//, "").replace(/^(?:routes|pages)\//, "");
13762
13863
  r = r.replace(/\.(?:html|jsx|tsx|vue|svelte)$/, "").replace(/\/?(?:page|index|\+page)$/, "");
@@ -13766,7 +13867,7 @@ function hashScreens(runDir, rels) {
13766
13867
  const out2 = [];
13767
13868
  for (const rel of rels) {
13768
13869
  try {
13769
- out2.push({ path: rel, sha256: sha256File(join51(runDir, rel)) });
13870
+ out2.push({ path: rel, sha256: sha256File(join52(runDir, rel)) });
13770
13871
  } catch {}
13771
13872
  }
13772
13873
  return out2;
@@ -13779,10 +13880,10 @@ function checkScreens(runDir, screens) {
13779
13880
  return "evidence_screens entry is malformed";
13780
13881
  if (isAbsolute8(s.path) || normalize3(s.path).startsWith(".."))
13781
13882
  return `evidence screenshot path escapes the evidence dir: ${s.path}`;
13782
- const file = join51(runDir, s.path);
13883
+ const file = join52(runDir, s.path);
13783
13884
  let cur = runDir;
13784
13885
  for (const seg of normalize3(s.path).split(sep12)) {
13785
- cur = join51(cur, seg);
13886
+ cur = join52(cur, seg);
13786
13887
  if (isSymlink(cur))
13787
13888
  return `evidence screenshot path is a symlink: ${s.path}`;
13788
13889
  }
@@ -13829,7 +13930,7 @@ async function waitUp(url, ms, signal) {
13829
13930
  }
13830
13931
  function openapiPaths(repoDir) {
13831
13932
  for (const f of ["openapi.json", "openapi.yaml", "openapi.yml", "swagger.json"]) {
13832
- const p = join51(repoDir, f);
13933
+ const p = join52(repoDir, f);
13833
13934
  if (!existsSync32(p))
13834
13935
  continue;
13835
13936
  try {
@@ -13847,24 +13948,24 @@ async function recordE2eMedia(repoDir, runDir, relDir, base, routes, ms, signal)
13847
13948
  if (!pw || !pkg)
13848
13949
  return { rels: [], skipped: "playwright e2e video and trace skipped: @playwright/test is not installed in the repo" };
13849
13950
  try {
13850
- const dir = join51(runDir, relDir, "e2e");
13951
+ const dir = join52(runDir, relDir, "e2e");
13851
13952
  mkdirSync21(dir, { recursive: true });
13852
- writeFileSync24(join51(dir, "walk.spec.cjs"), e2eSpecSource(pkg, base, routes));
13853
- writeFileSync24(join51(dir, "playwright.config.cjs"), `module.exports = { testDir: ".", testMatch: "walk.spec.cjs", outputDir: "./out", reporter: "null", use: { video: "on", trace: "on" } };
13953
+ writeFileSync24(join52(dir, "walk.spec.cjs"), e2eSpecSource(pkg, base, routes));
13954
+ writeFileSync24(join52(dir, "playwright.config.cjs"), `module.exports = { testDir: ".", testMatch: "walk.spec.cjs", outputDir: "./out", reporter: "null", use: { video: "on", trace: "on" } };
13854
13955
  `);
13855
- if (!await shoot(pw, ["test", "--config", join51(dir, "playwright.config.cjs")], repoDir, ms, signal))
13956
+ if (!await shoot(pw, ["test", "--config", join52(dir, "playwright.config.cjs")], repoDir, ms, signal))
13856
13957
  return { rels: [], skipped: "playwright e2e video and trace skipped: the run failed or timed out" };
13857
13958
  const rels = [];
13858
13959
  const walk = (d) => {
13859
13960
  for (const e of readdirSync18(d, { withFileTypes: true })) {
13860
- const full = join51(d, e.name);
13961
+ const full = join52(d, e.name);
13861
13962
  if (e.isDirectory())
13862
13963
  walk(full);
13863
13964
  else if (e.isFile() && /\.(webm|zip)$/.test(e.name))
13864
- rels.push(join51(relDir, "e2e", relative7(dir, full)));
13965
+ rels.push(join52(relDir, "e2e", relative7(dir, full)));
13865
13966
  }
13866
13967
  };
13867
- walk(join51(dir, "out"));
13968
+ walk(join52(dir, "out"));
13868
13969
  return rels.length > 0 ? { rels, skipped: null } : { rels, skipped: "playwright e2e video and trace skipped: no video or trace was produced" };
13869
13970
  } catch (e) {
13870
13971
  return { rels: [], skipped: `playwright e2e video and trace skipped: ${String(e?.message ?? e).slice(0, 120)}` };
@@ -13943,15 +14044,15 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
13943
14044
  if (!visualEvidenceEnabled(opts.env))
13944
14045
  return skip("LOKI_VISUAL_EVIDENCE is 0");
13945
14046
  const api = loadProjectApi(repoDir), boot = isMultiRoot(api) ? api.uiBoot() : null;
13946
- const appDir = boot ? join51(repoDir, boot.boot.cwd) : repoDir;
13947
- const pkgPath = join51(appDir, "package.json");
14047
+ const appDir = boot ? join52(repoDir, boot.boot.cwd) : repoDir;
14048
+ const pkgPath = join52(appDir, "package.json");
13948
14049
  let script = null;
13949
14050
  if (!boot) {
13950
14051
  if (!existsSync32(pkgPath)) {
13951
- const subs = ["backend", "frontend"].filter((d) => existsSync32(join51(repoDir, d, "package.json")));
14052
+ const subs = ["backend", "frontend"].filter((d) => existsSync32(join52(repoDir, d, "package.json")));
13952
14053
  const has = (d) => {
13953
14054
  try {
13954
- return pickScript(JSON.parse(readFileSync41(join51(repoDir, d, "package.json"), "utf8"))) !== null;
14055
+ return pickScript(JSON.parse(readFileSync41(join52(repoDir, d, "package.json"), "utf8"))) !== null;
13955
14056
  } catch {
13956
14057
  return false;
13957
14058
  }
@@ -13985,20 +14086,20 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
13985
14086
  }
13986
14087
  if (!await waitUp(base, left(), signal))
13987
14088
  return skip(aborted() ? "aborted" : `${script} server did not answer within ${Math.round(budget / 1000)}s`);
13988
- const evRoot = join51(runDir, "evidence");
14089
+ const evRoot = join52(runDir, "evidence");
13989
14090
  if (isSymlink(evRoot))
13990
14091
  return skip("evidence dir is a symlink");
13991
14092
  mkdirSync21(evRoot, { recursive: true });
13992
14093
  if (pages.length > 0) {
13993
- const rel0 = join51("evidence", randomBytes6(6).toString("hex"));
13994
- mkdirSync21(join51(runDir, rel0));
14094
+ const rel0 = join52("evidence", randomBytes6(6).toString("hex"));
14095
+ mkdirSync21(join52(runDir, rel0));
13995
14096
  const rels = [];
13996
14097
  for (const route of [...new Set(pages.map(routeFor))].slice(0, opts.maxRoutes ?? MAX_ROUTES)) {
13997
14098
  if (aborted() || left() <= 0)
13998
14099
  break;
13999
- const rel = join51(rel0, `${screenName(route)}.png`);
14000
- const ok = await shoot(pw, ["screenshot", `${base}${route}`, join51(runDir, rel)], appDir, left(), signal);
14001
- if (ok && !aborted() && !isSymlink(join51(runDir, rel)) && existsSync32(join51(runDir, rel)))
14100
+ const rel = join52(rel0, `${screenName(route)}.png`);
14101
+ const ok = await shoot(pw, ["screenshot", `${base}${route}`, join52(runDir, rel)], appDir, left(), signal);
14102
+ if (ok && !aborted() && !isSymlink(join52(runDir, rel)) && existsSync32(join52(runDir, rel)))
14002
14103
  rels.push(rel);
14003
14104
  }
14004
14105
  if (aborted())
@@ -14023,9 +14124,9 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
14023
14124
  }
14024
14125
  if (aborted())
14025
14126
  return skip("aborted");
14026
- const hdir = join51(evRoot, randomBytes6(6).toString("hex"));
14127
+ const hdir = join52(evRoot, randomBytes6(6).toString("hex"));
14027
14128
  mkdirSync21(hdir);
14028
- writeFileSync24(join51(hdir, "http.json"), JSON.stringify(rows, null, 2) + `
14129
+ writeFileSync24(join52(hdir, "http.json"), JSON.stringify(rows, null, 2) + `
14029
14130
  `);
14030
14131
  return { screens: [], http: true, skipped: null };
14031
14132
  } catch (e) {
@@ -14055,11 +14156,11 @@ function receiptScreensProblem(receiptPath, receipt) {
14055
14156
  return receipt["evidence_screens"] === undefined ? null : checkScreens(dirname19(receiptPath), receipt["evidence_screens"]);
14056
14157
  }
14057
14158
  var visualEvidenceEnabled = (env = process.env) => env["LOKI_VISUAL_EVIDENCE"] !== "0", visualGateEnabled = (env = process.env) => env["LOKI_VISUAL_GATE"] === "1", PAGE_RE, isPageFile = (p) => PAGE_RE.test(p), screenName = (route) => (route === "/" ? "index" : route.slice(1).replace(/[^A-Za-z0-9._-]+/g, "_")) || "index", sha256File = (p) => createHash14("sha256").update(readFileSync41(p)).digest("hex"), playwrightBin = (repoDir) => {
14058
- const bin = join51(repoDir, "node_modules", ".bin", "playwright");
14159
+ const bin = join52(repoDir, "node_modules", ".bin", "playwright");
14059
14160
  return existsSync32(bin) ? bin : null;
14060
14161
  }, playwrightTestPkg = (repoDir) => {
14061
- const d = join51(repoDir, "node_modules", "@playwright", "test");
14062
- return existsSync32(join51(d, "package.json")) ? d : null;
14162
+ const d = join52(repoDir, "node_modules", "@playwright", "test");
14163
+ return existsSync32(join52(d, "package.json")) ? d : null;
14063
14164
  }, e2eSpecSource = (pkgDir, base, routes) => `const { test } = require(${JSON.stringify(pkgDir)});
14064
14165
  test("loki e2e walkthrough", async ({ page }) => {
14065
14166
  for (const r of ${JSON.stringify(routes)}) { await page.goto(${JSON.stringify(base)} + r); await page.waitForLoadState("load"); }
@@ -14105,7 +14206,7 @@ var init_outbox = __esm(() => {
14105
14206
  });
14106
14207
 
14107
14208
  // ../../loki-ts/src/engine10/stages/pr.ts
14108
- import { join as join52 } from "path";
14209
+ import { join as join53 } from "path";
14109
14210
  var DEFAULT_PUSH_SH, DEFAULT_PUSH_GITLAB_SH;
14110
14211
  var init_pr = __esm(() => {
14111
14212
  init_types();
@@ -14124,13 +14225,13 @@ var init_pr = __esm(() => {
14124
14225
  init_receipt_surface();
14125
14226
  init_yaml_key();
14126
14227
  init_outbox();
14127
- DEFAULT_PUSH_SH = join52(REPO_ROOT, "autonomy/lib/engine10-push.sh");
14128
- DEFAULT_PUSH_GITLAB_SH = join52(REPO_ROOT, "autonomy/lib/engine10-push-gitlab.sh");
14228
+ DEFAULT_PUSH_SH = join53(REPO_ROOT, "autonomy/lib/engine10-push.sh");
14229
+ DEFAULT_PUSH_GITLAB_SH = join53(REPO_ROOT, "autonomy/lib/engine10-push-gitlab.sh");
14129
14230
  });
14130
14231
 
14131
14232
  // ../../loki-ts/src/util/pr_lessons.ts
14132
14233
  import { existsSync as existsSync33, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync8, readFileSync as readFileSync42, rmSync as rmSync16, writeFileSync as writeFileSync25 } from "fs";
14133
- import { dirname as dirname20, join as join53 } from "path";
14234
+ import { dirname as dirname20, join as join54 } from "path";
14134
14235
  import { createHash as createHash15 } from "crypto";
14135
14236
  function loadLessons(repoDir) {
14136
14237
  const p = lessonsPath(repoDir);
@@ -14179,7 +14280,7 @@ function recordRunVerdict(repoDir, runId2, verdict) {
14179
14280
  if (dirty)
14180
14281
  save(repoDir, lessons);
14181
14282
  }
14182
- var lessonsPath = (repoDir) => join53(repoDir, ".loki", "memory", "semantic", "pr-lessons.json"), KINDS;
14283
+ var lessonsPath = (repoDir) => join54(repoDir, ".loki", "memory", "semantic", "pr-lessons.json"), KINDS;
14183
14284
  var init_pr_lessons = __esm(() => {
14184
14285
  init_atomic();
14185
14286
  init_safe_git();
@@ -14346,10 +14447,10 @@ var init_providers = __esm(() => {
14346
14447
 
14347
14448
  // ../../loki-ts/src/runner/router/route_record.ts
14348
14449
  import { existsSync as existsSync35, lstatSync as lstatSync13, mkdirSync as mkdirSync23, readFileSync as readFileSync44, writeFileSync as writeFileSync26 } from "fs";
14349
- import { join as join54 } from "path";
14450
+ import { join as join55 } from "path";
14350
14451
  function loadRouteRecord(runDir) {
14351
14452
  try {
14352
- const p = join54(runDir, ROUTE_RECORD_FILE);
14453
+ const p = join55(runDir, ROUTE_RECORD_FILE);
14353
14454
  if (!existsSync35(p) || !lstatSync13(p).isFile())
14354
14455
  return;
14355
14456
  const v = JSON.parse(readFileSync44(p, "utf8"));
@@ -14411,6 +14512,7 @@ var init_implement_route = __esm(() => {
14411
14512
 
14412
14513
  // ../../loki-ts/src/engine10/stages/implement.ts
14413
14514
  var init_implement = __esm(() => {
14515
+ init_install();
14414
14516
  init_lean_prefix();
14415
14517
  init_pr_lessons();
14416
14518
  init_context();
@@ -14488,50 +14590,6 @@ var init_worker = __esm(() => {
14488
14590
  init_safe_git();
14489
14591
  });
14490
14592
 
14491
- // ../../loki-ts/src/project_model/package_suite.ts
14492
- import { join as join55 } from "path";
14493
- async function runPackageSuites(repoDir, signal, opts, checks, notProven) {
14494
- const api = loadProjectApi(repoDir);
14495
- if (!isMultiRoot(api))
14496
- return false;
14497
- const withTests = api.packages().filter((p) => p.commands.test);
14498
- if (withTests.length === 0)
14499
- return false;
14500
- for (const pkg of withTests) {
14501
- const tc = pkg.commands.test, name = `full suite: ${pkg.name}`, cmd2 = `(cd ${tc.cwd} && ${tc.cmd})`;
14502
- const started = Date.now();
14503
- const r = await run(["bash", "-c", tc.cmd], { cwd: join55(repoDir, tc.cwd), timeoutMs: opts.timeoutMs, ...opts.path ? { env: { PATH: opts.path } } : {} });
14504
- const duration_s = (Date.now() - started) / 1000;
14505
- if (signal.aborted) {
14506
- checks.push({ name, cmd: cmd2, result: "not_run", duration_s });
14507
- notProven.add(`not run: ${name} (aborted)`);
14508
- continue;
14509
- }
14510
- const out2 = `${r.stdout}
14511
- ${r.stderr}`;
14512
- const lr = r.exitCode === 0 || !opts.baseSha ? undefined : await harnessLoadReason({ repoDir, baseSha: opts.baseSha, out: out2, cmd: "bash", args: ["-c", tc.cmd], signal, cwd: join55(repoDir, tc.cwd), ...opts.path ? { env: { PATH: opts.path } } : {} });
14513
- if (lr) {
14514
- checks.push({ name, cmd: cmd2, result: "not_run", duration_s });
14515
- notProven.add(`${lr} (${name}; harness-owned)`);
14516
- continue;
14517
- }
14518
- const cls = classifyCheck({ kind: "test", ok: r.exitCode === 0, out: out2, ...goRunner(tc.cmd) });
14519
- checks.push({ name, cmd: cmd2, result: cls.result, duration_s, ...cls.result === "fail" ? { ids: failIds(out2) } : {} });
14520
- if (cls.result === "not_run")
14521
- notProven.add(`not run: ${name} (${cls.reason ?? NO_TESTS_REASON})`);
14522
- }
14523
- for (const pkg of api.packages().filter((p) => !p.commands.test))
14524
- notProven.add(`full suite: package ${pkg.name} defines no test command`);
14525
- return true;
14526
- }
14527
- var init_package_suite = __esm(() => {
14528
- init_load_owner();
14529
- init_check_result();
14530
- init_shell();
14531
- init_failures();
14532
- init_resolve();
14533
- });
14534
-
14535
14593
  // ../../loki-ts/src/engine10/stages/deep.ts
14536
14594
  var exports_deep = {};
14537
14595
  __export(exports_deep, {
@@ -14577,7 +14635,7 @@ function sessionCouncil(sessions) {
14577
14635
  } };
14578
14636
  }
14579
14637
  async function runFullSuite(ctx, signal, opts, checks, notProven) {
14580
- if (await runPackageSuites(ctx.repoDir, signal, { path: opts.path, timeoutMs: opts.fullSuiteTimeoutMs ?? FULL_SUITE_TIMEOUT_MS, baseSha: ctx.baseSha }, checks, notProven))
14638
+ if (await runPackageSuites(ctx.repoDir, signal, { path: opts.path, timeoutMs: opts.fullSuiteTimeoutMs ?? FULL_SUITE_TIMEOUT_MS, baseSha: ctx.baseSha, skip: installOwned(ctx.repoDir, ctx.outputs().intake?.install_created) }, checks, notProven))
14581
14639
  return;
14582
14640
  const map = await ctx.tests.detect(ctx.repoDir);
14583
14641
  if (map.runners.length === 0) {
@@ -14605,7 +14663,7 @@ async function runFullSuite(ctx, signal, opts, checks, notProven) {
14605
14663
  continue;
14606
14664
  }
14607
14665
  const out2 = `${r.stdout}
14608
- ${r.stderr}`, lr = r.exitCode === 0 ? undefined : await harnessLoadReason({ repoDir: ctx.repoDir, baseSha: ctx.baseSha, out: out2, cmd: spec.cmd, args: spec.args, signal, ...opts.path ? { env: { PATH: opts.path } } : {} });
14666
+ ${r.stderr}`, lr = r.exitCode === 0 ? undefined : await harnessLoadReason({ repoDir: ctx.repoDir, baseSha: ctx.baseSha, skip: installOwned(ctx.repoDir, ctx.outputs().intake?.install_created), out: out2, cmd: spec.cmd, args: spec.args, signal, ...opts.path ? { env: { PATH: opts.path } } : {} });
14609
14667
  if (lr) {
14610
14668
  checks.push({ name, cmd: [spec.cmd, ...spec.args].join(" "), result: "not_run", duration_s: durationS });
14611
14669
  notProven.add(`${lr} (${name}; harness-owned)`);
@@ -14757,7 +14815,7 @@ async function runDeep(ctx, signal, opts = {}) {
14757
14815
  }
14758
14816
  let changed;
14759
14817
  try {
14760
- changed = changedFiles(ctx.repoDir, ctx.baseSha);
14818
+ changed = changedFiles(ctx.repoDir, ctx.baseSha, installOwned(ctx.repoDir, ctx.outputs().intake?.install_created));
14761
14819
  } catch (err) {
14762
14820
  return { status: "failed", data: {}, reason: `git diff against base failed: ${err.message}` };
14763
14821
  }
@@ -14789,8 +14847,9 @@ async function runDeep(ctx, signal, opts = {}) {
14789
14847
  ctx.emit("deep.completed", "deep", { checks, status_state: statusState, addendum_sha256: addendumSha256 });
14790
14848
  return { status: "completed", data: { checks, addendum_sha256: addendumSha256, status_state: statusState, not_proven: allNotProven } };
14791
14849
  }
14792
- var DEFAULT_PUSH_SH2, DEFAULT_SECRET_SCAN_SH, MAX_COUNCIL_DIFF_BYTES = 400000, COUNCIL_LIMIT_S = 600, FULL_SUITE_TIMEOUT_MS = 300000, PR_NUMBER_RE, SHA_RE, FULL_SUITE_CMD, deepStage, stage;
14850
+ var DEFAULT_PUSH_SH2, DEFAULT_SECRET_SCAN_SH, MAX_COUNCIL_DIFF_BYTES = 400000, COUNCIL_LIMIT_S = 600, FULL_SUITE_TIMEOUT_MS = 300000, PR_NUMBER_RE, SHA_RE, deepStage, stage;
14793
14851
  var init_deep = __esm(() => {
14852
+ init_install();
14794
14853
  init_app_probe();
14795
14854
  init_secure_scan();
14796
14855
  init_shell();
@@ -14808,16 +14867,6 @@ var init_deep = __esm(() => {
14808
14867
  DEFAULT_SECRET_SCAN_SH = new URL("../../../../autonomy/lib/secret-scan.sh", import.meta.url).pathname;
14809
14868
  PR_NUMBER_RE = /\/pull\/(\d+)$/;
14810
14869
  SHA_RE = /^[0-9a-f]{40}$/;
14811
- FULL_SUITE_CMD = {
14812
- pytest: { cmd: "python", args: ["-m", "pytest", "-q"] },
14813
- vitest: { cmd: "npx", args: ["vitest", "run"] },
14814
- jest: { cmd: "npx", args: ["jest"] },
14815
- bun: { cmd: "bun", args: ["test"] },
14816
- node: { cmd: "node", args: ["--test"] },
14817
- npm: { cmd: "npm", args: ["test", "--silent"] },
14818
- go: { cmd: "go", args: ["test", "-json", "./..."] },
14819
- cargo: { cmd: "cargo", args: ["test"] }
14820
- };
14821
14870
  deepStage = {
14822
14871
  name: "deep",
14823
14872
  ...STAGE_BUDGETS.deep,
@@ -14866,7 +14915,7 @@ async function runCheck(ctx, name, cmd2, args, signal, checks, opts = {}) {
14866
14915
  const cwd = opts.cwd ?? ctx.repoDir;
14867
14916
  const one = async (a) => {
14868
14917
  let c2 = classifyCheck({ kind, ok: a.ok, cut: a.cut, missing: a.missing, out: a.out, ...goRunner(cmd2, args), path: /\.[cm]?[jt]s$/.test(args[args.length - 1] ?? "") ? args[args.length - 1] : undefined });
14869
- const lr = kind === "test" && !a.ok && !a.cut && !a.missing ? await harnessLoadReason({ repoDir: ctx.repoDir, baseSha: ctx.baseSha, out: a.out, cmd: cmd2, args, signal, cwd, protect: opts.protect, ...opts.path ? { env: { PATH: opts.path } } : {} }) : undefined;
14918
+ const lr = kind === "test" && !a.ok && !a.cut && !a.missing ? await harnessLoadReason({ repoDir: ctx.repoDir, baseSha: ctx.baseSha, skip: installOwned(ctx.repoDir, ctx.outputs?.().intake?.install_created), out: a.out, cmd: cmd2, args, signal, cwd, protect: opts.protect, ...opts.path ? { env: { PATH: opts.path } } : {} }) : undefined;
14870
14919
  if (lr)
14871
14920
  c2 = { result: "not_run", reason: lr, owner: "harness" };
14872
14921
  if (!lr && kind === "static" && !a.ok && !a.cut && !a.missing && opts.wall?.size && wallOwnedFailure(a.out, cwd, ctx.repoDir, opts.wall))
@@ -14985,6 +15034,7 @@ var CHECK_TIMEOUT_MS = 60000, excerpts, isHold = (c) => isHoldoutCheck(c.name),
14985
15034
  }
14986
15035
  } }), verifyStage;
14987
15036
  var init_verify = __esm(() => {
15037
+ init_install();
14988
15038
  init_scope();
14989
15039
  init_runner_config();
14990
15040
  init_assert_delta();
@@ -15015,7 +15065,7 @@ var init_verify = __esm(() => {
15015
15065
  async run(ctx, signal) {
15016
15066
  let changed;
15017
15067
  try {
15018
- changed = changedFiles(ctx.repoDir, ctx.baseSha);
15068
+ changed = changedFiles(ctx.repoDir, ctx.baseSha, installOwned(ctx.repoDir, ctx.outputs().intake?.install_created));
15019
15069
  } catch (err) {
15020
15070
  return { status: "failed", data: {}, reason: `git diff against base failed: ${err.message}` };
15021
15071
  }
@@ -15028,7 +15078,7 @@ var init_verify = __esm(() => {
15028
15078
  }
15029
15079
  let risk = (() => {
15030
15080
  try {
15031
- const r = classifyRisk(diffFiles(ctx.repoDir, ctx.baseSha));
15081
+ const r = classifyRisk(diffFiles(ctx.repoDir, ctx.baseSha, installOwned(ctx.repoDir, ctx.outputs().intake?.install_created)));
15032
15082
  recordRisk(ctx.repoDir, r);
15033
15083
  return r;
15034
15084
  } catch {
@@ -15139,7 +15189,7 @@ ${x}` : c.cmd };
15139
15189
  return [`weakened test: ${t.path}`, ...assertDeltaNotes(ctx.repoDir, ctx.baseSha, null, t.path, intake?.task ?? "", k?.b, k?.h) ?? []];
15140
15190
  });
15141
15191
  const weakened = [...modifiedRel, ...cfgChanged.map((f) => `test configuration changed: ${f}`), ...preRed.weak.map((n2) => `skipped or fewer tests than base: ${n2}`)];
15142
- const notProven = [...weakened, ...pub.filter((c) => c.name === "holdout" && c.result !== "pass").map((c) => c.result === "not_run" ? "holdout not executed" : "holdout check failed"), ...[...fullNotProven].filter((n2) => !n2.startsWith("full suite (no test runner")), ...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"))];
15192
+ 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((n2) => !n2.startsWith("full suite (no test runner")), ...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"))];
15143
15193
  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 && wallRun.every((c) => c.result === "pass") ? true : undefined;
15144
15194
  return { status: "completed", data: { checks: pub, flaky, ...wallPassed === undefined ? {} : { wall_passed: wallPassed }, failures_grouped: failuresGrouped, holdout_failed: holdoutFailed, changed_files: changed, not_proven: notProven, pre_red: preRed.ids, pre_red_checks: preRed.names, ...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 } };
15145
15195
  }
@@ -15605,12 +15655,14 @@ var init_preexisting_dirty = __esm(() => {
15605
15655
 
15606
15656
  // ../../loki-ts/src/e10ext/commit_filter.ts
15607
15657
  import { dirname as dirname26 } from "path";
15608
- function dropSet(repoDir, staged, preexistingDirty, env = process.env) {
15609
- return staged.concat(untouchedSinceIntake(repoDir, preexistingDirty, env).map((f) => ({ st: "L", f }))).filter(({ st, f }) => f.startsWith(".loki/") || st === "L" || /(^|\/)loki_wall_[^/]*$/.test(f) || st === "A" && !staged.some(({ f: m }) => /(^|\/)(package\.json|pyproject\.toml|requirements\.txt|Cargo\.toml|go\.mod)$/.test(m) && dirname26(m) === dirname26(f)) && /(^|\/)(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|bun\.lockb?|poetry\.lock|Cargo\.lock|go\.sum)$/.test(f));
15658
+ function dropSet(repoDir, staged, preexistingDirty, env = process.env, installCreated) {
15659
+ const owned = installOwned(repoDir, installCreated, env), made = installCreated?.files ?? {};
15660
+ return staged.concat(untouchedSinceIntake(repoDir, preexistingDirty, env).map((f) => ({ st: "L", f })), staged.filter(({ f }) => owned(f)).map(({ f }) => ({ st: "L", f }))).filter(({ st, f }) => f.startsWith(".loki/") || st === "L" || /(^|\/)loki_wall_[^/]*$/.test(f) || st === "A" && !Object.hasOwn(made, f) && !staged.some(({ f: m }) => /(^|\/)(package\.json|pyproject\.toml|requirements\.txt|Cargo\.toml|go\.mod)$/.test(m) && dirname26(m) === dirname26(f)) && /(^|\/)(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|bun\.lockb?|poetry\.lock|Cargo\.lock|go\.sum)$/.test(f));
15610
15661
  }
15611
15662
  var parseStaged = (out2) => out2.split("\x00").reduce((a, t, i, all) => i % 2 === 0 && t ? [...a, { st: t, f: all[i + 1] }] : a, []), formatChanged = (repoDir, staged, dropped2, env = process.env) => runFormatters(repoDir, staged.filter(({ st, f }) => (st === "A" || st === "M") && !dropped2.has(f) && !f.startsWith(".loki/")).map(({ f }) => f), tokenFreeEnv(env));
15612
15663
  var init_commit_filter = __esm(() => {
15613
15664
  init_preexisting_dirty();
15665
+ init_install();
15614
15666
  init_repo_profile();
15615
15667
  init_safe_git();
15616
15668
  });
@@ -16623,7 +16675,7 @@ var init_seal = __esm(() => {
16623
16675
  if (sd.code !== 0)
16624
16676
  return { status: "failed", data: {}, reason: "git diff against base failed" };
16625
16677
  const staged = parseStaged(sd.out);
16626
- const drop = dropSet(ctx.repoDir, staged, ctx.outputs().intake?.preexisting_dirty);
16678
+ const drop = dropSet(ctx.repoDir, staged, ctx.outputs().intake?.preexisting_dirty, process.env, ctx.outputs().intake?.install_created);
16627
16679
  const sat = await discardIfSatisfied((a) => git4(ctx, a), ctx.baseSha, ctx.outputs(), staged, new Set(drop.filter(({ st }) => st === "L").map(({ f }) => f)), ctx.repoDir);
16628
16680
  if (sat)
16629
16681
  return sat;