loki-mode 11.17.34 → 11.17.35

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 (75) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/lib/proof-generator.py +53 -0
  4. package/autonomy/loki +171 -14
  5. package/completions/_loki +1 -0
  6. package/completions/loki.bash +1 -1
  7. package/dashboard/__init__.py +1 -1
  8. package/docs/CLI-REFERENCE.md +1 -1
  9. package/docs/INSTALLATION.md +1 -1
  10. package/docs/v10/BOARD.md +4 -4
  11. package/docs/v10/DECISIONS.md +8 -0
  12. package/docs/v10/PROGRESS.md +3 -0
  13. package/loki-ts/dist/loki.js +927 -927
  14. package/mcp/__init__.py +1 -1
  15. package/package.json +2 -2
  16. package/packages/control-plane/dist/server.js +453 -412
  17. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  18. package/web-app/dist/assets/{AdminPage-o3gtaCnU.js → AdminPage-DtJ40-0A.js} +1 -1
  19. package/web-app/dist/assets/{Avatar-C02t-Irl.js → Avatar-BroDCINh.js} +1 -1
  20. package/web-app/dist/assets/{Badge-BuN80MKq.js → Badge-BS02diTl.js} +1 -1
  21. package/web-app/dist/assets/{Button-lPXsKVcs.js → Button-DV7QKQIh.js} +1 -1
  22. package/web-app/dist/assets/{CockpitPage-8CNxkZSh.js → CockpitPage-_jJB0SSp.js} +1 -1
  23. package/web-app/dist/assets/{ComparePage-j-XhFiwH.js → ComparePage-9G53m6VG.js} +1 -1
  24. package/web-app/dist/assets/{ErrorBoundary-D8nyc_y_.js → ErrorBoundary-BxAWorBT.js} +1 -1
  25. package/web-app/dist/assets/{EvidenceReceiptPanel-DtTSMxZm.js → EvidenceReceiptPanel-D5_6xbqU.js} +1 -1
  26. package/web-app/dist/assets/{GitHubIssuesPanel-Bzmm3gBY.js → GitHubIssuesPanel-D4lz3Q9l.js} +1 -1
  27. package/web-app/dist/assets/{GitHubPRsPanel-Dh6vSHLE.js → GitHubPRsPanel-BDHX9d5m.js} +1 -1
  28. package/web-app/dist/assets/{HomePage-CKKPOMOg.js → HomePage-DP1R90H7.js} +2 -2
  29. package/web-app/dist/assets/{LoginPage-49FrYkL9.js → LoginPage-DWMnArZX.js} +1 -1
  30. package/web-app/dist/assets/{MagicPage-D5psAu69.js → MagicPage-DVvZ-ytQ.js} +1 -1
  31. package/web-app/dist/assets/{MetricsPage-oQXV5q4J.js → MetricsPage-BM5Zifpz.js} +1 -1
  32. package/web-app/dist/assets/{NotFoundPage-C2hj6k1f.js → NotFoundPage-CYrJ2hCM.js} +1 -1
  33. package/web-app/dist/assets/{ProjectPage-Bo8ocjwn.js → ProjectPage-C_KU_B2Z.js} +3 -3
  34. package/web-app/dist/assets/{ProjectsPage-QUhbz991.js → ProjectsPage-BKOoyezO.js} +1 -1
  35. package/web-app/dist/assets/{SettingsPage-6XW8I3LO.js → SettingsPage-D0YIMzR4.js} +1 -1
  36. package/web-app/dist/assets/{ShowcasePage-9CHGu9uW.js → ShowcasePage-AgAwQE4Q.js} +1 -1
  37. package/web-app/dist/assets/{SystemSettingsPage-gZZK7T45.js → SystemSettingsPage-Cin_takd.js} +1 -1
  38. package/web-app/dist/assets/{TeamsPage-DSlKvZhA.js → TeamsPage-BhpuLv8p.js} +1 -1
  39. package/web-app/dist/assets/{TemplatesPage-BVDR5mF2.js → TemplatesPage-DysLVH1s.js} +1 -1
  40. package/web-app/dist/assets/{TerminalOutput-DnOFdmTG.js → TerminalOutput-BNwZci_n.js} +1 -1
  41. package/web-app/dist/assets/{activity-D22UFJWA.js → activity-CWziiy0I.js} +1 -1
  42. package/web-app/dist/assets/{bell-B2Mfgp26.js → bell-DXJj9c93.js} +1 -1
  43. package/web-app/dist/assets/{bot-CTXo6aac.js → bot-BXjVlRf9.js} +1 -1
  44. package/web-app/dist/assets/{check-D9kJod1H.js → check-B0m-S8D_.js} +1 -1
  45. package/web-app/dist/assets/{chevron-left-XI4pnrlY.js → chevron-left-kFvUdte6.js} +1 -1
  46. package/web-app/dist/assets/{circle-alert-CvS3mi0t.js → circle-alert-CxRoiGmA.js} +1 -1
  47. package/web-app/dist/assets/{clock-CCgwQ80p.js → clock-BJ39Nl09.js} +1 -1
  48. package/web-app/dist/assets/{cloud-S-SuEsEp.js → cloud-DK2q56ot.js} +1 -1
  49. package/web-app/dist/assets/{code-xml-PRnhUKWP.js → code-xml-BQUCyHmu.js} +1 -1
  50. package/web-app/dist/assets/{database-C_a7H_3N.js → database-CGGMJBY-.js} +1 -1
  51. package/web-app/dist/assets/{dollar-sign-FDCzdLrB.js → dollar-sign-C6gRmaFY.js} +1 -1
  52. package/web-app/dist/assets/{file-code-corner-28-hDPSO.js → file-code-corner-Cf25WTZR.js} +1 -1
  53. package/web-app/dist/assets/{file-plus-c0yygSC8.js → file-plus-D3z0a6s8.js} +1 -1
  54. package/web-app/dist/assets/{globe-DOA9Y_1n.js → globe-Ft1PAFtm.js} +1 -1
  55. package/web-app/dist/assets/{hammer-Omzy4vB3.js → hammer-uSNPcG6-.js} +1 -1
  56. package/web-app/dist/assets/{index-Dp6emuTo.js → index-CVdTpox_.js} +3 -3
  57. package/web-app/dist/assets/{layers-D7ZjWXJQ.js → layers-Dc50swfm.js} +1 -1
  58. package/web-app/dist/assets/{loader-circle-CJ2SKm0h.js → loader-circle-VEyejUbH.js} +1 -1
  59. package/web-app/dist/assets/{lock-HKmv1nIN.js → lock-DjSnxn6I.js} +1 -1
  60. package/web-app/dist/assets/{package-FQl71HNO.js → package-DZoaxJbK.js} +1 -1
  61. package/web-app/dist/assets/{plus-DY8mlU6I.js → plus-CfEwV_6v.js} +1 -1
  62. package/web-app/dist/assets/{refresh-cw-CJ_pkRQQ.js → refresh-cw-8UjV3w0I.js} +1 -1
  63. package/web-app/dist/assets/{rotate-ccw-rGU_udZ1.js → rotate-ccw-Br7s9zAf.js} +1 -1
  64. package/web-app/dist/assets/{scroll-text-CeVAfOXM.js → scroll-text-CuAQTRV9.js} +1 -1
  65. package/web-app/dist/assets/{server-D-N_u9OT.js → server-BDj53pad.js} +1 -1
  66. package/web-app/dist/assets/{shield-alert-CJfx3HCX.js → shield-alert-Yq8Exf7A.js} +1 -1
  67. package/web-app/dist/assets/{thumbs-up-BrC-E9mS.js → thumbs-up-DbolTUui.js} +1 -1
  68. package/web-app/dist/assets/{trash-2-Bb3mW1oq.js → trash-2-Band0V5Q.js} +1 -1
  69. package/web-app/dist/assets/{trending-down-CrgUJZLA.js → trending-down-tVJY7vOw.js} +1 -1
  70. package/web-app/dist/assets/{trending-up-Dk_GS57K.js → trending-up-DzJ3qeYe.js} +1 -1
  71. package/web-app/dist/assets/{upload-BAxHyFqH.js → upload-kvP9eEgy.js} +1 -1
  72. package/web-app/dist/assets/{usePolling-CkTdc2YU.js → usePolling-CBydUyUd.js} +1 -1
  73. package/web-app/dist/assets/{user-Dr6XCReg.js → user-CglUAW3P.js} +1 -1
  74. package/web-app/dist/index.html +1 -1
  75. package/web-app/server.py +164 -132
@@ -10877,6 +10877,21 @@ async function run(argv, opts = {}) {
10877
10877
  clearTimeout(killTimer);
10878
10878
  }
10879
10879
  }
10880
+ async function commandExists(name) {
10881
+ const safe = shEscape(name);
10882
+ const r = await run(["sh", "-c", `command -v ${safe}`], { timeoutMs: 5000 });
10883
+ if (r.exitCode === 0) {
10884
+ const path = r.stdout.trim();
10885
+ return path || null;
10886
+ }
10887
+ return null;
10888
+ }
10889
+ function shEscape(name) {
10890
+ if (!/^[A-Za-z0-9._/-]+$/.test(name)) {
10891
+ throw new Error(`refused to shell-escape suspect token: ${name}`);
10892
+ }
10893
+ return name;
10894
+ }
10880
10895
  var MAX_STDOUT_BYTES;
10881
10896
  var init_shell = __esm(() => {
10882
10897
  MAX_STDOUT_BYTES = 16 * 1024 * 1024;
@@ -10886,6 +10901,23 @@ var init_shell = __esm(() => {
10886
10901
  import { accessSync, constants as constants3, existsSync as existsSync26, mkdtempSync as mkdtempSync4, readFileSync as readFileSync33, realpathSync as realpathSync17, rmSync as rmSync11, statSync as statSync16 } from "fs";
10887
10902
  import { spawnSync as spawnSync2 } from "child_process";
10888
10903
  import { tmpdir as tmpdir5 } from "os";
10904
+ async function findPython3() {
10905
+ if (_pythonCache !== undefined)
10906
+ return _pythonCache;
10907
+ const homebrew = "/opt/homebrew/bin/python3.12";
10908
+ if (existsSync26(homebrew)) {
10909
+ _pythonCache = homebrew;
10910
+ return homebrew;
10911
+ }
10912
+ const py312 = await commandExists("python3.12");
10913
+ if (py312) {
10914
+ _pythonCache = py312;
10915
+ return py312;
10916
+ }
10917
+ const py3 = await commandExists("python3");
10918
+ _pythonCache = py3;
10919
+ return py3;
10920
+ }
10889
10921
  function resolvePython3() {
10890
10922
  for (const dir of (process.env.PATH ?? "").split(":")) {
10891
10923
  if (!dir || !dir.startsWith("/"))
@@ -10922,7 +10954,7 @@ function pySignatures(src) {
10922
10954
  return [];
10923
10955
  }
10924
10956
  }
10925
- var PY_TIMEOUT_MS = 5000, PY_SCRIPT = `
10957
+ var _pythonCache, PY_TIMEOUT_MS = 5000, PY_SCRIPT = `
10926
10958
  import ast, sys, json, re
10927
10959
  def u(n): return ast.unparse(n)
10928
10960
  def chain(n):
@@ -12232,176 +12264,162 @@ var init_wall_owned = __esm(() => {
12232
12264
  ANSI2 = /\u001b\[[0-9;?]*[ -/]*[@-~]/g;
12233
12265
  });
12234
12266
 
12235
- // ../../loki-ts/src/project_graph.ts
12236
- import { createHash as createHash13 } from "crypto";
12237
- import {
12238
- existsSync as existsSync28,
12239
- readdirSync as readdirSync16,
12240
- readFileSync as readFileSync37,
12241
- statSync as statSync17,
12242
- writeFileSync as writeFileSync21,
12243
- mkdirSync as mkdirSync18
12244
- } from "fs";
12245
- import { basename as basename19, dirname as dirname16, join as join48, resolve as resolve14 } from "path";
12246
- function readManifest(path) {
12247
- if (!existsSync28(path)) {
12248
- return null;
12249
- }
12250
- let raw2;
12251
- try {
12252
- raw2 = readFileSync37(path, "utf8");
12253
- } catch {
12254
- return null;
12255
- }
12256
- let parsed;
12267
+ // ../../loki-ts/src/util/app_probe.ts
12268
+ import { spawnSync as spawnSync4 } from "child_process";
12269
+ import { existsSync as existsSync28, mkdirSync as mkdirSync18, readFileSync as readFileSync37, renameSync as renameSync11, writeFileSync as writeFileSync21 } from "fs";
12270
+ import { join as join48 } from "path";
12271
+ function readJson4(p) {
12257
12272
  try {
12258
- parsed = JSON.parse(raw2);
12273
+ const v = JSON.parse(readFileSync37(p, "utf8"));
12274
+ return v && typeof v === "object" ? v : null;
12259
12275
  } catch {
12260
12276
  return null;
12261
12277
  }
12262
- if (typeof parsed !== "object" || parsed === null) {
12263
- return null;
12264
- }
12265
- const obj = parsed;
12266
- if (obj["schema_version"] !== SUPPORTED_SCHEMA_VERSION) {
12267
- console.warn(`[loki:project_graph] unsupported schema_version in ${path}: ` + `${String(obj["schema_version"])} (expected ${SUPPORTED_SCHEMA_VERSION})`);
12268
- return null;
12269
- }
12270
- const appId = obj["app_id"];
12271
- if (typeof appId !== "string" || !APP_ID_REGEX.test(appId)) {
12272
- console.warn(`[loki:project_graph] invalid app_id in ${path}: ${String(appId)}`);
12273
- return null;
12274
- }
12275
- const members = Array.isArray(obj["members"]) ? obj["members"].filter((m) => typeof m === "string") : [];
12276
- const sharedMemoryDir = typeof obj["shared_memory_dir"] === "string" ? obj["shared_memory_dir"] : undefined;
12277
- return {
12278
- schema_version: SUPPORTED_SCHEMA_VERSION,
12279
- app_id: appId,
12280
- members,
12281
- shared_memory_dir: sharedMemoryDir
12282
- };
12283
12278
  }
12284
- function resolveMembers(rootDir, declared, selfBasename) {
12285
- const out2 = [];
12286
- const seen = new Set;
12287
- let children;
12279
+ function stopApp(repoDir, opts = {}) {
12280
+ const runner = opts.runnerPath ?? join48(REPO_ROOT, "autonomy", "app-runner.sh");
12281
+ if (!existsSync28(runner) || !existsSync28(join48(repoDir, ".loki", "app-runner", "app.pid")))
12282
+ return;
12283
+ spawnSync4("bash", ["-c", STOP, "app-probe", repoDir, runner], { cwd: repoDir, env: plainTestEnv(), timeout: opts.timeoutMs ?? 60000, killSignal: "SIGKILL", stdio: "ignore" });
12284
+ }
12285
+ async function appProbe(repoDir, lokiDir2, opts = {}) {
12286
+ const timeoutMs = opts.timeoutMs ?? 60000, runner = opts.runnerPath ?? join48(REPO_ROOT, "autonomy", "app-runner.sh");
12287
+ const dir = join48(repoDir, ".loki", "app-runner"), checks = [];
12288
+ const t0 = Date.now();
12289
+ const mk2 = (name, result, reason) => ({ name, cmd: "autonomy/app-runner.sh", result, duration_s: (Date.now() - t0) / 1000, reason });
12290
+ const sh = (script) => {
12291
+ const r = spawnSync4("bash", ["-c", script, "app-probe", repoDir, runner], { cwd: repoDir, env: { ...plainTestEnv(), ...opts.env ?? {} }, encoding: "utf8", timeout: timeoutMs, killSignal: "SIGKILL", stdio: ["ignore", "pipe", "ignore"] });
12292
+ return { out: r.stdout ?? "", status: r.error ? null : r.status };
12293
+ };
12294
+ let pid = null, url = null;
12295
+ if (!existsSync28(runner))
12296
+ return { checks: [mk2("app boot", "not_run", "app-runner.sh not found"), mk2("http probe", "not_run", "app not booted")], pid, url };
12288
12297
  try {
12289
- children = readdirSync16(rootDir);
12298
+ const b = sh(BOOT);
12299
+ const m = b.out.match(/__APP_PROBE__ (-?\d+) (-?\d+) (-?\d+)/);
12300
+ if (!m) {
12301
+ checks.push(mk2("app boot", "not_run", b.status === null ? "bash unavailable or boot timed out" : "app-runner did not report"), mk2("http probe", "not_run", "app not booted"));
12302
+ return { checks, pid, url };
12303
+ }
12304
+ const ir = Number(m[1]), sr = Number(m[2]), hr = Number(m[3]);
12305
+ const pidTxt = existsSync28(join48(dir, "app.pid")) ? readFileSync37(join48(dir, "app.pid"), "utf8").trim() : "";
12306
+ pid = /^\d+$/.test(pidTxt) && sr >= 0 ? Number(pidTxt) : null;
12307
+ const st = readJson4(join48(dir, "state.json"));
12308
+ url = typeof st?.["url"] === "string" ? st["url"] : null;
12309
+ if (sr < 0) {
12310
+ 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"));
12311
+ return { checks, pid, url };
12312
+ }
12313
+ if (sr !== 0) {
12314
+ checks.push(mk2("app boot", "fail", "app start command failed or exited"), mk2("http probe", "not_run", "app not booted"));
12315
+ return { checks, pid, url };
12316
+ }
12317
+ checks.push(mk2("app boot", "pass", "app process started"));
12318
+ const health = readJson4(join48(dir, "health.json"));
12319
+ checks.push(hr === 0 && health?.["ok"] === true ? mk2("http probe", "pass", "health.json ok") : mk2("http probe", "fail", "app-runner health check failed"));
12320
+ if (opts.specText !== undefined && checks[1]?.result === "pass" && url)
12321
+ checks.push(await functionalVerify(opts, url, dir, lokiDir2, timeoutMs));
12322
+ return { checks, pid, url };
12323
+ } finally {
12324
+ if (!opts.skipStop)
12325
+ stopApp(repoDir, { runnerPath: runner, timeoutMs });
12326
+ }
12327
+ }
12328
+ async function functionalVerify(opts, url, dir, lokiDir2, timeoutMs) {
12329
+ const t0 = Date.now();
12330
+ const res = (result, reason) => ({ name: "functional verify", cmd: "autonomy/lib/functional-verify.py", result, duration_s: (Date.now() - t0) / 1000, reason });
12331
+ const py = await findPython3(), script = opts.verifyPath ?? join48(REPO_ROOT, "autonomy", "lib", "functional-verify.py");
12332
+ if (!py || !existsSync28(script))
12333
+ return res("not_run", "python3 or functional-verify.py unavailable");
12334
+ const specFile = join48(dir, "spec.txt");
12335
+ writeFileSync21(specFile, opts.specText ?? "");
12336
+ const r = spawnSync4(py, ["-I", script, specFile, url], { env: plainTestEnv(), encoding: "utf8", timeout: timeoutMs, killSignal: "SIGKILL", stdio: ["ignore", "pipe", "ignore"] });
12337
+ let out2 = null;
12338
+ try {
12339
+ const v = JSON.parse(r.stdout ?? "");
12340
+ out2 = v && typeof v === "object" ? v : null;
12290
12341
  } catch {
12291
- children = [];
12292
- }
12293
- const matchPattern = (pattern, name) => {
12294
- if (!pattern.includes("*") && !pattern.includes("?")) {
12295
- return pattern === name;
12296
- }
12297
- const re = new RegExp("^" + pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".") + "$");
12298
- return re.test(name);
12299
- };
12300
- for (const name of declared) {
12301
- for (const child of children) {
12302
- if (!matchPattern(name, child))
12303
- continue;
12304
- const full = join48(rootDir, child);
12305
- if (seen.has(full))
12306
- continue;
12307
- let st;
12308
- try {
12309
- st = statSync17(full);
12310
- } catch {
12311
- continue;
12312
- }
12313
- if (!st.isDirectory())
12314
- continue;
12315
- seen.add(full);
12316
- out2.push(full);
12317
- }
12318
- }
12319
- if (declared.length === 0) {
12320
- for (const child of children) {
12321
- const full = join48(rootDir, child);
12322
- if (seen.has(full))
12323
- continue;
12324
- let st;
12325
- try {
12326
- st = statSync17(full);
12327
- } catch {
12328
- continue;
12329
- }
12330
- if (!st.isDirectory())
12331
- continue;
12332
- if (!existsSync28(join48(full, ".loki", "app.json")))
12333
- continue;
12334
- seen.add(full);
12335
- out2.push(full);
12336
- }
12337
- }
12338
- return out2;
12339
- }
12340
- function cacheKey(manifestPaths) {
12341
- const parts = [];
12342
- for (const p of manifestPaths.sort()) {
12343
- let mtime = 0;
12344
- try {
12345
- mtime = statSync17(p).mtimeMs;
12346
- } catch {}
12347
- parts.push(`${p}:${mtime}`);
12348
- }
12349
- return createHash13("sha256").update(parts.join("|")).digest("hex");
12350
- }
12351
- function writeCache(targetDir, key, result) {
12342
+ out2 = null;
12343
+ }
12344
+ if (!out2 || r.status !== 0)
12345
+ return res("not_run", "functional harness produced no result");
12346
+ const q = join48(lokiDir2, "quality");
12347
+ mkdirSync18(q, { recursive: true });
12348
+ const tmp = join48(q, `functional-results.json.tmp.${process.pid}`);
12349
+ writeFileSync21(tmp, JSON.stringify(out2, null, 2));
12350
+ renameSync11(tmp, join48(q, "functional-results.json"));
12351
+ const s = String(out2["functional_status"] ?? "inconclusive");
12352
+ return res(s === "verified" ? "pass" : s === "failed" ? "fail" : "not_run", `functional_status ${s}`);
12353
+ }
12354
+ var PRELUDE = `set +e
12355
+ log_info() { :; }; log_warn() { :; }; log_error() { :; }; log_step() { :; }; register_pid() { :; }
12356
+ export APP_RUNNER_ENABLED=true
12357
+ export TARGET_DIR="$1"
12358
+ source "$2" >/dev/null 2>&1 || exit 90
12359
+ `, BOOT, STOP;
12360
+ var init_app_probe = __esm(() => {
12361
+ init_check_result();
12362
+ init_python();
12363
+ init_paths();
12364
+ BOOT = `${PRELUDE}
12365
+ app_runner_init >/dev/null 2>&1; ir=$?
12366
+ sr=-1; hr=-1
12367
+ if [ "$ir" -eq 0 ] && [ -s "$TARGET_DIR/.loki/app-runner/detection.json" ]; then
12368
+ app_runner_start >/dev/null 2>&1; sr=$?
12369
+ [ "$sr" -eq 0 ] && { app_runner_health_check >/dev/null 2>&1; hr=$?; }
12370
+ fi
12371
+ printf '__APP_PROBE__ %s %s %s\\n' "$ir" "$sr" "$hr"
12372
+ `;
12373
+ STOP = `${PRELUDE}
12374
+ _app_runner_dir
12375
+ app_runner_stop >/dev/null 2>&1
12376
+ `;
12377
+ });
12378
+
12379
+ // ../../loki-ts/src/util/secure_scan.ts
12380
+ import { existsSync as existsSync29 } from "fs";
12381
+ import { join as join49 } from "path";
12382
+ function fail(error) {
12383
+ return { ok: false, findings: [], error };
12384
+ }
12385
+ async function runSecureScan(targetDir, opts = {}) {
12386
+ const script = opts.scriptPath ?? join49(REPO_ROOT, "autonomy", "lib", "secure-scan.py");
12387
+ if (!existsSync29(script))
12388
+ return fail(`secure-scan script not found: ${script}`);
12389
+ const py = await findPython3();
12390
+ if (!py)
12391
+ return fail("python3 not found");
12392
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_SECURE_SCAN_TIMEOUT_MS;
12393
+ const started = Date.now();
12394
+ const res = await run([py, script, targetDir, "--json", ...opts.secretsEverywhere ? ["--secrets-everywhere"] : []], { timeoutMs });
12395
+ const elapsed = Date.now() - started;
12396
+ let parsed;
12352
12397
  try {
12353
- const cacheDir = join48(targetDir, ".loki", "state");
12354
- mkdirSync18(cacheDir, { recursive: true });
12355
- const cachePath = join48(cacheDir, "project-graph.json");
12356
- writeFileSync21(cachePath, JSON.stringify({ key, result }, null, 2), "utf8");
12357
- } catch {}
12358
- }
12359
- function discoverProjectGraph(targetDir) {
12360
- const absTarget = resolve14(targetDir);
12361
- const targetManifest = join48(absTarget, ".loki", "app.json");
12362
- const parentDir = dirname16(absTarget);
12363
- const parentManifest = join48(parentDir, ".loki", "app.json");
12364
- const examined = [];
12365
- let chosenManifest = null;
12366
- let chosenRoot = "";
12367
- if (existsSync28(parentManifest) && parentDir !== absTarget) {
12368
- examined.push(parentManifest);
12369
- chosenManifest = readManifest(parentManifest);
12370
- chosenRoot = parentDir;
12371
- }
12372
- if (!chosenManifest && existsSync28(targetManifest)) {
12373
- examined.push(targetManifest);
12374
- chosenManifest = readManifest(targetManifest);
12375
- chosenRoot = absTarget;
12376
- }
12377
- if (!chosenManifest)
12378
- return null;
12379
- const declared = chosenManifest.members ?? [];
12380
- const members = resolveMembers(chosenRoot, declared, basename19(absTarget));
12381
- const filtered = [];
12382
- for (const m of members) {
12383
- const sibManifestPath = join48(m, ".loki", "app.json");
12384
- if (existsSync28(sibManifestPath)) {
12385
- examined.push(sibManifestPath);
12386
- const sibManifest = readManifest(sibManifestPath);
12387
- if (sibManifest && sibManifest.app_id !== chosenManifest.app_id) {
12388
- continue;
12389
- }
12390
- }
12391
- filtered.push(m);
12392
- }
12393
- const result = {
12394
- appId: chosenManifest.app_id,
12395
- root: chosenRoot,
12396
- members: filtered,
12397
- sharedMemoryDir: chosenManifest.shared_memory_dir
12398
- };
12399
- writeCache(absTarget, cacheKey(examined), result);
12400
- return result;
12401
- }
12402
- var APP_ID_REGEX, SUPPORTED_SCHEMA_VERSION = 1;
12403
- var init_project_graph = __esm(() => {
12404
- APP_ID_REGEX = /^[a-z0-9-]{3,40}$/;
12398
+ parsed = JSON.parse(res.stdout);
12399
+ } catch {
12400
+ parsed = undefined;
12401
+ }
12402
+ const obj = parsed && typeof parsed === "object" ? parsed : undefined;
12403
+ if ((res.exitCode === 0 || res.exitCode === 1) && obj && Array.isArray(obj.findings)) {
12404
+ const findings = obj.findings;
12405
+ if (res.exitCode === 1 === findings.length > 0)
12406
+ return { ok: true, findings };
12407
+ return fail(`secure-scan exit ${res.exitCode} disagrees with ${findings.length} findings`);
12408
+ }
12409
+ if (res.exitCode !== 0 && res.exitCode !== 1 && res.exitCode !== 2 && elapsed >= timeoutMs) {
12410
+ return fail(`secure-scan timed out after ${timeoutMs}ms`);
12411
+ }
12412
+ if (obj && typeof obj.error === "string")
12413
+ return fail(`secure-scan: ${obj.error}`);
12414
+ const tail = (res.stderr || res.stdout).trim().split(`
12415
+ `).slice(-3).join(" | ");
12416
+ return fail(`secure-scan failed (exit ${res.exitCode}): ${tail}`);
12417
+ }
12418
+ var DEFAULT_SECURE_SCAN_TIMEOUT_MS = 120000;
12419
+ var init_secure_scan = __esm(() => {
12420
+ init_paths();
12421
+ init_python();
12422
+ init_shell();
12405
12423
  });
12406
12424
 
12407
12425
  // ../../loki-ts/src/runner/retry_class.ts
@@ -12509,10 +12527,10 @@ var init_route_block = __esm(() => {
12509
12527
 
12510
12528
  // ../../loki-ts/src/features/visual_evidence.ts
12511
12529
  import { spawn as spawn7 } from "child_process";
12512
- import { createHash as createHash14, randomBytes as randomBytes5 } from "crypto";
12513
- import { existsSync as existsSync29, lstatSync as lstatSync10, mkdirSync as mkdirSync19, readdirSync as readdirSync17, readFileSync as readFileSync38, writeFileSync as writeFileSync22 } from "fs";
12530
+ import { createHash as createHash13, randomBytes as randomBytes5 } from "crypto";
12531
+ import { existsSync as existsSync30, lstatSync as lstatSync10, mkdirSync as mkdirSync19, readdirSync as readdirSync16, readFileSync as readFileSync38, writeFileSync as writeFileSync22 } from "fs";
12514
12532
  import { createServer } from "net";
12515
- import { dirname as dirname17, isAbsolute as isAbsolute7, join as join49, normalize as normalize3, relative as relative6, sep as sep11 } from "path";
12533
+ import { dirname as dirname16, isAbsolute as isAbsolute7, join as join50, normalize as normalize3, relative as relative6, sep as sep11 } from "path";
12516
12534
  function routeFor(file) {
12517
12535
  let r = file.replace(/^(?:.*?\/)?(?:app|pages|src|public)\//, "").replace(/^(?:routes|pages)\//, "");
12518
12536
  r = r.replace(/\.(?:html|jsx|tsx|vue|svelte)$/, "").replace(/\/?(?:page|index|\+page)$/, "");
@@ -12522,7 +12540,7 @@ function hashScreens(runDir, rels) {
12522
12540
  const out2 = [];
12523
12541
  for (const rel of rels) {
12524
12542
  try {
12525
- out2.push({ path: rel, sha256: sha256File(join49(runDir, rel)) });
12543
+ out2.push({ path: rel, sha256: sha256File(join50(runDir, rel)) });
12526
12544
  } catch {}
12527
12545
  }
12528
12546
  return out2;
@@ -12535,14 +12553,14 @@ function checkScreens(runDir, screens) {
12535
12553
  return "evidence_screens entry is malformed";
12536
12554
  if (isAbsolute7(s.path) || normalize3(s.path).startsWith(".."))
12537
12555
  return `evidence screenshot path escapes the evidence dir: ${s.path}`;
12538
- const file = join49(runDir, s.path);
12556
+ const file = join50(runDir, s.path);
12539
12557
  let cur = runDir;
12540
12558
  for (const seg of normalize3(s.path).split(sep11)) {
12541
- cur = join49(cur, seg);
12559
+ cur = join50(cur, seg);
12542
12560
  if (isSymlink(cur))
12543
12561
  return `evidence screenshot path is a symlink: ${s.path}`;
12544
12562
  }
12545
- if (!existsSync29(file))
12563
+ if (!existsSync30(file))
12546
12564
  return `evidence screenshot is missing: ${s.path}`;
12547
12565
  if (!isRegularFile(file))
12548
12566
  return `evidence screenshot is not a regular file: ${s.path}`;
@@ -12585,8 +12603,8 @@ async function waitUp(url, ms, signal) {
12585
12603
  }
12586
12604
  function openapiPaths(repoDir) {
12587
12605
  for (const f of ["openapi.json", "openapi.yaml", "openapi.yml", "swagger.json"]) {
12588
- const p = join49(repoDir, f);
12589
- if (!existsSync29(p))
12606
+ const p = join50(repoDir, f);
12607
+ if (!existsSync30(p))
12590
12608
  continue;
12591
12609
  try {
12592
12610
  const txt = readFileSync38(p, "utf8");
@@ -12603,24 +12621,24 @@ async function recordE2eMedia(repoDir, runDir, relDir, base, routes, ms, signal)
12603
12621
  if (!pw || !pkg)
12604
12622
  return { rels: [], skipped: "playwright e2e video and trace skipped: @playwright/test is not installed in the repo" };
12605
12623
  try {
12606
- const dir = join49(runDir, relDir, "e2e");
12624
+ const dir = join50(runDir, relDir, "e2e");
12607
12625
  mkdirSync19(dir, { recursive: true });
12608
- writeFileSync22(join49(dir, "walk.spec.cjs"), e2eSpecSource(pkg, base, routes));
12609
- writeFileSync22(join49(dir, "playwright.config.cjs"), `module.exports = { testDir: ".", testMatch: "walk.spec.cjs", outputDir: "./out", reporter: "null", use: { video: "on", trace: "on" } };
12626
+ writeFileSync22(join50(dir, "walk.spec.cjs"), e2eSpecSource(pkg, base, routes));
12627
+ writeFileSync22(join50(dir, "playwright.config.cjs"), `module.exports = { testDir: ".", testMatch: "walk.spec.cjs", outputDir: "./out", reporter: "null", use: { video: "on", trace: "on" } };
12610
12628
  `);
12611
- if (!await shoot(pw, ["test", "--config", join49(dir, "playwright.config.cjs")], repoDir, ms, signal))
12629
+ if (!await shoot(pw, ["test", "--config", join50(dir, "playwright.config.cjs")], repoDir, ms, signal))
12612
12630
  return { rels: [], skipped: "playwright e2e video and trace skipped: the run failed or timed out" };
12613
12631
  const rels = [];
12614
12632
  const walk = (d) => {
12615
- for (const e of readdirSync17(d, { withFileTypes: true })) {
12616
- const full = join49(d, e.name);
12633
+ for (const e of readdirSync16(d, { withFileTypes: true })) {
12634
+ const full = join50(d, e.name);
12617
12635
  if (e.isDirectory())
12618
12636
  walk(full);
12619
12637
  else if (e.isFile() && /\.(webm|zip)$/.test(e.name))
12620
- rels.push(join49(relDir, "e2e", relative6(dir, full)));
12638
+ rels.push(join50(relDir, "e2e", relative6(dir, full)));
12621
12639
  }
12622
12640
  };
12623
- walk(join49(dir, "out"));
12641
+ walk(join50(dir, "out"));
12624
12642
  return rels.length > 0 ? { rels, skipped: null } : { rels, skipped: "playwright e2e video and trace skipped: no video or trace was produced" };
12625
12643
  } catch (e) {
12626
12644
  return { rels: [], skipped: `playwright e2e video and trace skipped: ${String(e?.message ?? e).slice(0, 120)}` };
@@ -12699,15 +12717,15 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
12699
12717
  if (!visualEvidenceEnabled(opts.env))
12700
12718
  return skip("LOKI_VISUAL_EVIDENCE is 0");
12701
12719
  const api = loadProjectApi(repoDir), boot = isMultiRoot(api) ? api.uiBoot() : null;
12702
- const appDir = boot ? join49(repoDir, boot.boot.cwd) : repoDir;
12703
- const pkgPath = join49(appDir, "package.json");
12720
+ const appDir = boot ? join50(repoDir, boot.boot.cwd) : repoDir;
12721
+ const pkgPath = join50(appDir, "package.json");
12704
12722
  let script = null;
12705
12723
  if (!boot) {
12706
- if (!existsSync29(pkgPath)) {
12707
- const subs = ["backend", "frontend"].filter((d) => existsSync29(join49(repoDir, d, "package.json")));
12724
+ if (!existsSync30(pkgPath)) {
12725
+ const subs = ["backend", "frontend"].filter((d) => existsSync30(join50(repoDir, d, "package.json")));
12708
12726
  const has = (d) => {
12709
12727
  try {
12710
- return pickScript(JSON.parse(readFileSync38(join49(repoDir, d, "package.json"), "utf8"))) !== null;
12728
+ return pickScript(JSON.parse(readFileSync38(join50(repoDir, d, "package.json"), "utf8"))) !== null;
12711
12729
  } catch {
12712
12730
  return false;
12713
12731
  }
@@ -12741,20 +12759,20 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
12741
12759
  }
12742
12760
  if (!await waitUp(base, left(), signal))
12743
12761
  return skip(aborted() ? "aborted" : `${script} server did not answer within ${Math.round(budget / 1000)}s`);
12744
- const evRoot = join49(runDir, "evidence");
12762
+ const evRoot = join50(runDir, "evidence");
12745
12763
  if (isSymlink(evRoot))
12746
12764
  return skip("evidence dir is a symlink");
12747
12765
  mkdirSync19(evRoot, { recursive: true });
12748
12766
  if (pages.length > 0) {
12749
- const rel0 = join49("evidence", randomBytes5(6).toString("hex"));
12750
- mkdirSync19(join49(runDir, rel0));
12767
+ const rel0 = join50("evidence", randomBytes5(6).toString("hex"));
12768
+ mkdirSync19(join50(runDir, rel0));
12751
12769
  const rels = [];
12752
12770
  for (const route of [...new Set(pages.map(routeFor))].slice(0, opts.maxRoutes ?? MAX_ROUTES)) {
12753
12771
  if (aborted() || left() <= 0)
12754
12772
  break;
12755
- const rel = join49(rel0, `${screenName(route)}.png`);
12756
- const ok = await shoot(pw, ["screenshot", `${base}${route}`, join49(runDir, rel)], appDir, left(), signal);
12757
- if (ok && !aborted() && !isSymlink(join49(runDir, rel)) && existsSync29(join49(runDir, rel)))
12773
+ const rel = join50(rel0, `${screenName(route)}.png`);
12774
+ const ok = await shoot(pw, ["screenshot", `${base}${route}`, join50(runDir, rel)], appDir, left(), signal);
12775
+ if (ok && !aborted() && !isSymlink(join50(runDir, rel)) && existsSync30(join50(runDir, rel)))
12758
12776
  rels.push(rel);
12759
12777
  }
12760
12778
  if (aborted())
@@ -12779,9 +12797,9 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
12779
12797
  }
12780
12798
  if (aborted())
12781
12799
  return skip("aborted");
12782
- const hdir = join49(evRoot, randomBytes5(6).toString("hex"));
12800
+ const hdir = join50(evRoot, randomBytes5(6).toString("hex"));
12783
12801
  mkdirSync19(hdir);
12784
- writeFileSync22(join49(hdir, "http.json"), JSON.stringify(rows, null, 2) + `
12802
+ writeFileSync22(join50(hdir, "http.json"), JSON.stringify(rows, null, 2) + `
12785
12803
  `);
12786
12804
  return { screens: [], http: true, skipped: null };
12787
12805
  } catch (e) {
@@ -12808,14 +12826,14 @@ async function sealEvidence(repoDir, runDir, o, notProven, signal, emit) {
12808
12826
  function receiptScreensProblem(receiptPath, receipt) {
12809
12827
  if (visualGateEnabled() && typeof receipt["evidence_failed"] === "string")
12810
12828
  return `visual evidence failed (LOKI_VISUAL_GATE=1): ${receipt["evidence_failed"]}`;
12811
- return receipt["evidence_screens"] === undefined ? null : checkScreens(dirname17(receiptPath), receipt["evidence_screens"]);
12829
+ return receipt["evidence_screens"] === undefined ? null : checkScreens(dirname16(receiptPath), receipt["evidence_screens"]);
12812
12830
  }
12813
- 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(readFileSync38(p)).digest("hex"), playwrightBin = (repoDir) => {
12814
- const bin = join49(repoDir, "node_modules", ".bin", "playwright");
12815
- return existsSync29(bin) ? bin : null;
12831
+ var visualEvidenceEnabled = (env = process.env) => env["LOKI_VISUAL_EVIDENCE"] !== "0", visualGateEnabled = (env = process.env) => env["LOKI_VISUAL_GATE"] === "1", PAGE_RE, isPageFile = (p) => PAGE_RE.test(p), screenName = (route) => (route === "/" ? "index" : route.slice(1).replace(/[^A-Za-z0-9._-]+/g, "_")) || "index", sha256File = (p) => createHash13("sha256").update(readFileSync38(p)).digest("hex"), playwrightBin = (repoDir) => {
12832
+ const bin = join50(repoDir, "node_modules", ".bin", "playwright");
12833
+ return existsSync30(bin) ? bin : null;
12816
12834
  }, playwrightTestPkg = (repoDir) => {
12817
- const d = join49(repoDir, "node_modules", "@playwright", "test");
12818
- return existsSync29(join49(d, "package.json")) ? d : null;
12835
+ const d = join50(repoDir, "node_modules", "@playwright", "test");
12836
+ return existsSync30(join50(d, "package.json")) ? d : null;
12819
12837
  }, e2eSpecSource = (pkgDir, base, routes) => `const { test } = require(${JSON.stringify(pkgDir)});
12820
12838
  test("loki e2e walkthrough", async ({ page }) => {
12821
12839
  for (const r of ${JSON.stringify(routes)}) { await page.goto(${JSON.stringify(base)} + r); await page.waitForLoadState("load"); }
@@ -12858,7 +12876,7 @@ var init_outbox = __esm(() => {
12858
12876
  });
12859
12877
 
12860
12878
  // ../../loki-ts/src/engine10/stages/pr.ts
12861
- import { join as join50 } from "path";
12879
+ import { join as join51 } from "path";
12862
12880
  var DEFAULT_PUSH_SH;
12863
12881
  var init_pr = __esm(() => {
12864
12882
  init_types();
@@ -12875,16 +12893,16 @@ var init_pr = __esm(() => {
12875
12893
  init_run_outputs();
12876
12894
  init_yaml_key();
12877
12895
  init_outbox();
12878
- DEFAULT_PUSH_SH = join50(REPO_ROOT, "autonomy/lib/engine10-push.sh");
12896
+ DEFAULT_PUSH_SH = join51(REPO_ROOT, "autonomy/lib/engine10-push.sh");
12879
12897
  });
12880
12898
 
12881
12899
  // ../../loki-ts/src/util/pr_lessons.ts
12882
- import { existsSync as existsSync30, mkdirSync as mkdirSync20, mkdtempSync as mkdtempSync7, readFileSync as readFileSync39, rmSync as rmSync15, writeFileSync as writeFileSync23 } from "fs";
12883
- import { dirname as dirname18, join as join51 } from "path";
12884
- import { createHash as createHash15 } from "crypto";
12900
+ import { existsSync as existsSync31, mkdirSync as mkdirSync20, mkdtempSync as mkdtempSync7, readFileSync as readFileSync39, rmSync as rmSync15, writeFileSync as writeFileSync23 } from "fs";
12901
+ import { dirname as dirname17, join as join52 } from "path";
12902
+ import { createHash as createHash14 } from "crypto";
12885
12903
  function loadLessons(repoDir) {
12886
12904
  const p = lessonsPath(repoDir);
12887
- if (!existsSync30(p))
12905
+ if (!existsSync31(p))
12888
12906
  return [];
12889
12907
  try {
12890
12908
  const j = JSON.parse(readFileSync39(p, "utf-8"));
@@ -12895,11 +12913,11 @@ function loadLessons(repoDir) {
12895
12913
  }
12896
12914
  function save(repoDir, lessons) {
12897
12915
  const p = lessonsPath(repoDir);
12898
- mkdirSync20(dirname18(p), { recursive: true });
12916
+ mkdirSync20(dirname17(p), { recursive: true });
12899
12917
  atomicWriteJson(p, { version: 2, lessons });
12900
12918
  }
12901
12919
  function appendReceiptFact(repoDir, f, now2 = () => new Date) {
12902
- const id = `rcp-${createHash15("sha256").update(f.runId).digest("hex").slice(0, 12)}`;
12920
+ const id = `rcp-${createHash14("sha256").update(f.runId).digest("hex").slice(0, 12)}`;
12903
12921
  const lessons = loadLessons(repoDir);
12904
12922
  if (lessons.some((l) => l.id === id))
12905
12923
  return false;
@@ -12929,7 +12947,7 @@ function recordRunVerdict(repoDir, runId, verdict) {
12929
12947
  if (dirty)
12930
12948
  save(repoDir, lessons);
12931
12949
  }
12932
- var lessonsPath = (repoDir) => join51(repoDir, ".loki", "memory", "semantic", "pr-lessons.json"), KINDS;
12950
+ var lessonsPath = (repoDir) => join52(repoDir, ".loki", "memory", "semantic", "pr-lessons.json"), KINDS;
12933
12951
  var init_pr_lessons = __esm(() => {
12934
12952
  init_atomic();
12935
12953
  init_safe_git();
@@ -12961,8 +12979,8 @@ var init_attempts = __esm(() => {
12961
12979
  var init_mcp_config = () => {};
12962
12980
 
12963
12981
  // ../../loki-ts/src/providers/claude_flags.ts
12964
- import { existsSync as existsSync31, readFileSync as readFileSync40 } from "fs";
12965
- import { resolve as resolvePath, dirname as dirname19 } from "path";
12982
+ import { existsSync as existsSync32, readFileSync as readFileSync40 } from "fs";
12983
+ import { resolve as resolvePath, dirname as dirname18 } from "path";
12966
12984
  import { fileURLToPath as fileURLToPath4 } from "url";
12967
12985
  function claudeFlagSupported(flag, helpText) {
12968
12986
  const txt = helpText ?? _claudeHelpCache;
@@ -13009,13 +13027,13 @@ function leanReviewerFlags(opts = {}) {
13009
13027
  }
13010
13028
  function designArchetypesText() {
13011
13029
  try {
13012
- const moduleDir = dirname19(fileURLToPath4(import.meta.url));
13030
+ const moduleDir = dirname18(fileURLToPath4(import.meta.url));
13013
13031
  for (const rel of [
13014
13032
  ["..", "..", "..", "references", "design-archetypes.md"],
13015
13033
  ["..", "..", "references", "design-archetypes.md"]
13016
13034
  ]) {
13017
13035
  const p = resolvePath(moduleDir, ...rel);
13018
- if (existsSync31(p))
13036
+ if (existsSync32(p))
13019
13037
  return readFileSync40(p, "utf8");
13020
13038
  }
13021
13039
  } catch {}
@@ -13100,12 +13118,12 @@ var init_providers = __esm(() => {
13100
13118
  });
13101
13119
 
13102
13120
  // ../../loki-ts/src/runner/router/route_record.ts
13103
- import { existsSync as existsSync32, lstatSync as lstatSync11, mkdirSync as mkdirSync21, readFileSync as readFileSync41, writeFileSync as writeFileSync24 } from "fs";
13104
- import { join as join52 } from "path";
13121
+ import { existsSync as existsSync33, lstatSync as lstatSync11, mkdirSync as mkdirSync21, readFileSync as readFileSync41, writeFileSync as writeFileSync24 } from "fs";
13122
+ import { join as join53 } from "path";
13105
13123
  function loadRouteRecord(runDir) {
13106
13124
  try {
13107
- const p = join52(runDir, ROUTE_RECORD_FILE);
13108
- if (!existsSync32(p) || !lstatSync11(p).isFile())
13125
+ const p = join53(runDir, ROUTE_RECORD_FILE);
13126
+ if (!existsSync33(p) || !lstatSync11(p).isFile())
13109
13127
  return;
13110
13128
  const v = JSON.parse(readFileSync41(p, "utf8"));
13111
13129
  return typeof v === "object" && v !== null && !Array.isArray(v) ? v : undefined;
@@ -13236,7 +13254,7 @@ var init_worker = __esm(() => {
13236
13254
  });
13237
13255
 
13238
13256
  // ../../loki-ts/src/project_model/package_suite.ts
13239
- import { join as join53 } from "path";
13257
+ import { join as join54 } from "path";
13240
13258
  async function runPackageSuites(repoDir, signal, opts, checks, notProven) {
13241
13259
  const api = loadProjectApi(repoDir);
13242
13260
  if (!isMultiRoot(api))
@@ -13247,7 +13265,7 @@ async function runPackageSuites(repoDir, signal, opts, checks, notProven) {
13247
13265
  for (const pkg of withTests) {
13248
13266
  const tc = pkg.commands.test, name = `full suite: ${pkg.name}`, cmd = `(cd ${tc.cwd} && ${tc.cmd})`;
13249
13267
  const started = Date.now();
13250
- const r = await run(["bash", "-c", tc.cmd], { cwd: join53(repoDir, tc.cwd), timeoutMs: opts.timeoutMs, ...opts.path ? { env: { PATH: opts.path } } : {} });
13268
+ const r = await run(["bash", "-c", tc.cmd], { cwd: join54(repoDir, tc.cwd), timeoutMs: opts.timeoutMs, ...opts.path ? { env: { PATH: opts.path } } : {} });
13251
13269
  const duration_s = (Date.now() - started) / 1000;
13252
13270
  if (signal.aborted) {
13253
13271
  checks.push({ name, cmd, result: "not_run", duration_s });
@@ -13256,7 +13274,7 @@ async function runPackageSuites(repoDir, signal, opts, checks, notProven) {
13256
13274
  }
13257
13275
  const out2 = `${r.stdout}
13258
13276
  ${r.stderr}`;
13259
- const lr = r.exitCode === 0 || !opts.baseSha ? undefined : await harnessLoadReason({ repoDir, baseSha: opts.baseSha, out: out2, cmd: "bash", args: ["-c", tc.cmd], signal, cwd: join53(repoDir, tc.cwd), ...opts.path ? { env: { PATH: opts.path } } : {} });
13277
+ const lr = r.exitCode === 0 || !opts.baseSha ? undefined : await harnessLoadReason({ repoDir, baseSha: opts.baseSha, out: out2, cmd: "bash", args: ["-c", tc.cmd], signal, cwd: join54(repoDir, tc.cwd), ...opts.path ? { env: { PATH: opts.path } } : {} });
13260
13278
  if (lr) {
13261
13279
  checks.push({ name, cmd, result: "not_run", duration_s });
13262
13280
  notProven.add(`${lr} (${name}; harness-owned)`);
@@ -13290,14 +13308,14 @@ __export(exports_deep, {
13290
13308
  DEFAULT_SECRET_SCAN_SH: () => DEFAULT_SECRET_SCAN_SH,
13291
13309
  DEFAULT_PUSH_SH: () => DEFAULT_PUSH_SH2
13292
13310
  });
13293
- import { existsSync as existsSync33, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync8, rmSync as rmSync16, writeFileSync as writeFileSync25 } from "fs";
13311
+ import { copyFileSync as copyFileSync3, existsSync as existsSync34, lstatSync as lstatSync12, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync8, rmSync as rmSync16, writeFileSync as writeFileSync25 } from "fs";
13294
13312
  import { tmpdir as tmpdir9 } from "os";
13295
- import { join as join54 } from "path";
13313
+ import { dirname as dirname19, join as join55 } from "path";
13296
13314
  function sessionCouncil(sessions) {
13297
13315
  return { async run(input, signal) {
13298
- const cwd = mkdtempSync8(join54(tmpdir9(), "loki-deep-council-"));
13316
+ const cwd = mkdtempSync8(join55(tmpdir9(), "loki-deep-council-"));
13299
13317
  try {
13300
- writeFileSync25(join54(cwd, "diff.patch"), input.diff, "utf8");
13318
+ writeFileSync25(join55(cwd, "diff.patch"), input.diff, "utf8");
13301
13319
  const r = await sessions.run({
13302
13320
  stage: "deep",
13303
13321
  tier: "development",
@@ -13364,16 +13382,20 @@ ${r.stderr}`, lr = r.exitCode === 0 ? undefined : await harnessLoadReason({ repo
13364
13382
  notProven.add(`not run: ${name} (${cls.reason ?? NO_TESTS_REASON})`);
13365
13383
  }
13366
13384
  }
13367
- function runAppBoot(ctx, opts, checks, notProven) {
13368
- const discover = opts.discoverGraph ?? discoverProjectGraph;
13369
- let graph = null;
13385
+ async function runAppBoot(ctx, opts, checks, notProven) {
13386
+ let r;
13370
13387
  try {
13371
- graph = discover(ctx.repoDir);
13372
- } catch {
13373
- graph = null;
13388
+ r = await (opts.appProbe ?? appProbe)(ctx.repoDir, join55(ctx.repoDir, ".loki"));
13389
+ } catch (err) {
13390
+ 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 };
13391
+ }
13392
+ if (!r.checks.some((c) => c.name === "app boot"))
13393
+ notProven.add("not run: app boot (app probe reported no result)");
13394
+ for (const c of r.checks) {
13395
+ checks.push(c);
13396
+ if (c.result === "not_run")
13397
+ notProven.add(`not run: ${c.name} (${c.reason ?? "no reason given"})`);
13374
13398
  }
13375
- checks.push({ name: "app boot", cmd: "project_graph.ts discoverProjectGraph", result: "not_run", duration_s: 0 });
13376
- notProven.add(graph ? `app boot not run (app graph discovered, ${graph.members.length} member(s))` : "app boot not run (no app graph discovered)");
13377
13399
  }
13378
13400
  async function runCouncilCheck(ctx, changed, baseSha, signal, opts, checks, notProven) {
13379
13401
  const codeFiles = changed.filter((f) => !f.endsWith(".md"));
@@ -13404,30 +13426,48 @@ async function runCouncilCheck(ctx, changed, baseSha, signal, opts, checks, notP
13404
13426
  notProven.add(`council (refused: ${err.message})`);
13405
13427
  }
13406
13428
  }
13429
+ async function secureScanChanged(repoDir, changed, opts) {
13430
+ const dir = mkdtempSync8(join55(tmpdir9(), "loki-deep-secure-"));
13431
+ try {
13432
+ for (const f of changed)
13433
+ if (existsSync34(join55(repoDir, f)) && lstatSync12(join55(repoDir, f)).isFile()) {
13434
+ mkdirSync22(dirname19(join55(dir, f)), { recursive: true });
13435
+ copyFileSync3(join55(repoDir, f), join55(dir, f));
13436
+ }
13437
+ return await runSecureScan(dir, { ...opts.secureScanPath ? { scriptPath: opts.secureScanPath } : {}, timeoutMs: 60000 });
13438
+ } finally {
13439
+ rmSync16(dir, { recursive: true, force: true });
13440
+ }
13441
+ }
13407
13442
  async function runSecretScan(ctx, changed, opts, checks, notProven) {
13408
- const scriptPath = opts.secretScanShPath ?? DEFAULT_SECRET_SCAN_SH;
13409
- const name = "security scan";
13410
- if (!existsSync33(scriptPath)) {
13411
- checks.push({ name, cmd: "secret-scan.sh", result: "not_run", duration_s: 0 });
13443
+ const scriptPath = opts.secretScanShPath ?? DEFAULT_SECRET_SCAN_SH, name = "security scan", cmd = "secret-scan.sh + secure-scan.py";
13444
+ if (!existsSync34(scriptPath)) {
13445
+ checks.push({ name, cmd, result: "not_run", duration_s: 0 });
13412
13446
  notProven.add(`not run: ${name} (secret-scan.sh not found)`);
13413
13447
  return;
13414
13448
  }
13415
13449
  if (changed.length === 0) {
13416
- checks.push({ name, cmd: "secret-scan.sh", result: "pass", duration_s: 0 });
13450
+ checks.push({ name, cmd, result: "pass", duration_s: 0 });
13417
13451
  return;
13418
13452
  }
13419
13453
  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"';
13420
13454
  const started = Date.now();
13421
- const r = await run(["bash", "-c", inline, "_", scriptPath, ...changed.map((f) => join54(ctx.repoDir, f))], { cwd: ctx.repoDir, timeoutMs: 30000 });
13422
- const durationS = (Date.now() - started) / 1000;
13423
- if (r.exitCode === 3) {
13424
- checks.push({ name, cmd: "secret-scan.sh", result: "not_run", duration_s: durationS });
13425
- notProven.add(`not run: ${name} (secret-scan.sh failed to load)`);
13426
- return;
13427
- }
13428
- const hits = r.stdout.split(`
13429
- `).map((l) => l.trim()).filter(Boolean);
13430
- checks.push({ name, cmd: "secret-scan.sh", result: hits.length > 0 ? "fail" : "pass", duration_s: durationS, ...hits.length > 0 ? { reason: `secret match: ${hits.join(", ")}` } : {} });
13455
+ const r = await run(["bash", "-c", inline, "_", scriptPath, ...changed.map((f) => join55(ctx.repoDir, f))], { cwd: ctx.repoDir, timeoutMs: 30000 });
13456
+ const sec = await secureScanChanged(ctx.repoDir, changed, opts), gaps = [], reasons = [];
13457
+ const hits = r.exitCode === 3 ? [] : r.stdout.split(`
13458
+ `).map((l) => l.trim()).filter(Boolean), high = sec.findings.filter((f) => String(f.severity).toUpperCase() === "HIGH");
13459
+ if (r.exitCode === 3)
13460
+ gaps.push("secret-scan.sh failed to load");
13461
+ if (!sec.ok)
13462
+ gaps.push(sec.error ?? "secure-scan failed");
13463
+ if (hits.length > 0)
13464
+ reasons.push(`secret match: ${hits.join(", ")}`);
13465
+ if (high.length > 0)
13466
+ reasons.push(`secure-scan: ${high.map((f) => `${f.rule}: ${f.file}:${f.line}`).join(", ")}`);
13467
+ const result = reasons.length > 0 ? "fail" : gaps.length > 0 ? "not_run" : "pass";
13468
+ checks.push({ name, cmd, result, duration_s: (Date.now() - started) / 1000, ...result === "pass" ? {} : { reason: (result === "fail" ? reasons : gaps).join("; ") } });
13469
+ if (result === "not_run")
13470
+ notProven.add(`not run: ${name} (${gaps.join("; ")})`);
13431
13471
  }
13432
13472
  function commentArgv(prNumber, bodyFile) {
13433
13473
  return ["comment", prNumber, bodyFile];
@@ -13453,7 +13493,7 @@ async function postResults(ctx, opts, checks, notProven, statusState) {
13453
13493
  const prNumber = prUrl ? PR_NUMBER_RE.exec(prUrl)?.[1] : undefined;
13454
13494
  if (prNumber) {
13455
13495
  mkdirSync22(ctx.runDir, { recursive: true });
13456
- const bodyFile = join54(ctx.runDir, "deep-comment.md");
13496
+ const bodyFile = join55(ctx.runDir, "deep-comment.md");
13457
13497
  writeFileSync25(bodyFile, buildCommentBody(checks, notProven, statusState), "utf8");
13458
13498
  const commentResult = await run(["bash", scriptPath, ...commentArgv(prNumber, bodyFile)], { cwd: ctx.repoDir, env, timeoutMs: 30000 });
13459
13499
  if (commentResult.exitCode !== 0)
@@ -13489,7 +13529,7 @@ async function runDeep(ctx, signal, opts = {}) {
13489
13529
  const checks = [];
13490
13530
  const notProven = new Set;
13491
13531
  await runFullSuite(ctx, signal, opts, checks, notProven);
13492
- runAppBoot(ctx, opts, checks, notProven);
13532
+ await runAppBoot(ctx, opts, checks, notProven);
13493
13533
  await runCouncilCheck(ctx, changed, ctx.baseSha, signal, opts, checks, notProven);
13494
13534
  await runSecretScan(ctx, changed, opts, checks, notProven);
13495
13535
  const statusState = checks.some((c) => c.result === "fail") ? "failure" : "success";
@@ -13507,7 +13547,7 @@ async function runDeep(ctx, signal, opts = {}) {
13507
13547
  const sig = signReceipt(`${ctx.runId}-deep`, addendumSha256);
13508
13548
  const addendum = { ...addendumBody, addendum_sha256: addendumSha256, verification: { jwt: sig.jwt, kid: sig.kid } };
13509
13549
  mkdirSync22(ctx.runDir, { recursive: true });
13510
- writeFileSync25(join54(ctx.runDir, "receipt-addendum-1.json"), JSON.stringify(addendum, null, 2) + `
13550
+ writeFileSync25(join55(ctx.runDir, "receipt-addendum-1.json"), JSON.stringify(addendum, null, 2) + `
13511
13551
  `);
13512
13552
  const pushNotProven = await postResults(ctx, opts, checks, notProvenList, statusState);
13513
13553
  const allNotProven = [...notProvenList, ...pushNotProven];
@@ -13516,7 +13556,8 @@ async function runDeep(ctx, signal, opts = {}) {
13516
13556
  }
13517
13557
  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;
13518
13558
  var init_deep = __esm(() => {
13519
- init_project_graph();
13559
+ init_app_probe();
13560
+ init_secure_scan();
13520
13561
  init_shell();
13521
13562
  init_load_owner();
13522
13563
  init_worker();
@@ -13551,9 +13592,9 @@ var init_deep = __esm(() => {
13551
13592
  });
13552
13593
 
13553
13594
  // ../../loki-ts/src/engine10/stages/verify.ts
13554
- import { existsSync as existsSync34, mkdtempSync as mkdtempSync9, realpathSync as realpathSync19, rmSync as rmSync17 } from "fs";
13595
+ import { existsSync as existsSync35, mkdtempSync as mkdtempSync9, realpathSync as realpathSync19, rmSync as rmSync17 } from "fs";
13555
13596
  import { tmpdir as tmpdir10 } from "os";
13556
- import { dirname as dirname20, isAbsolute as isAbsolute8, join as join55, relative as relative7 } from "path";
13597
+ import { dirname as dirname20, isAbsolute as isAbsolute8, join as join56, relative as relative7 } from "path";
13557
13598
  function resolveTool(repoDir, bin, fallback, lastResort = fallback) {
13558
13599
  const inRepo = (p) => {
13559
13600
  try {
@@ -13564,7 +13605,7 @@ function resolveTool(repoDir, bin, fallback, lastResort = fallback) {
13564
13605
  }
13565
13606
  };
13566
13607
  const venvEnv = process.env["VIRTUAL_ENV"];
13567
- const project = [join55(repoDir, ".venv", "bin", bin), join55(repoDir, "venv", "bin", bin), ...venvEnv && inRepo(venvEnv) ? [join55(venvEnv, "bin", bin)] : []].find(existsSync34);
13608
+ const project = [join56(repoDir, ".venv", "bin", bin), join56(repoDir, "venv", "bin", bin), ...venvEnv && inRepo(venvEnv) ? [join56(venvEnv, "bin", bin)] : []].find(existsSync35);
13568
13609
  return project ? [project, "project"] : [Bun.which(fallback) ? fallback : lastResort, "system"];
13569
13610
  }
13570
13611
  function runnerCmd(t, repoDir) {
@@ -13679,7 +13720,7 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal)
13679
13720
  const sus = pairs.filter(({ c }) => rel.has(c.name) && c.result === "pass");
13680
13721
  if (!(un.some(({ c }) => c.result === "fail" && c.ids?.length) || sus.length) || signal.aborted)
13681
13722
  return out2;
13682
- const dir = mkdtempSync9(join55(tmpdir10(), "e10-base-"));
13723
+ const dir = mkdtempSync9(join56(tmpdir10(), "e10-base-"));
13683
13724
  const git3 = (args) => {
13684
13725
  safeGit(ctx.repoDir, args, { stdio: "ignore", repoDrivers: true });
13685
13726
  };
@@ -13717,7 +13758,7 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal)
13717
13758
  return out2;
13718
13759
  }
13719
13760
  function isLokiModeRepo(repoDir) {
13720
- return existsSync34(join55(repoDir, "scripts", "select-tests.sh"));
13761
+ return existsSync35(join56(repoDir, "scripts", "select-tests.sh"));
13721
13762
  }
13722
13763
  async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
13723
13764
  const { api, ...runOpts } = opts;
@@ -13739,9 +13780,9 @@ async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
13739
13780
  }
13740
13781
  for (const g of groupByPackage(api, ctx.repoDir, changed.filter((f) => /\.(ts|tsx|js|jsx)$/.test(f)))) {
13741
13782
  const sfx = g.root === "." ? "" : `:${g.root}`, co = g.root === "." ? opts : { ...opts, cwd: g.cwd };
13742
- if (existsSync34(join55(g.cwd, "tsconfig.json")))
13783
+ if (existsSync35(join56(g.cwd, "tsconfig.json")))
13743
13784
  await runCheck(ctx, `lint:tsc${sfx}`, "npx", ["tsc", "--noEmit", "-p", "."], signal, checks, { ...co, kind: "static" });
13744
- if (ESLINT_CONFIGS.some((f) => existsSync34(join55(g.cwd, f)))) {
13785
+ if (ESLINT_CONFIGS.some((f) => existsSync35(join56(g.cwd, f)))) {
13745
13786
  const c = await runCheck(ctx, `lint:eslint${sfx}`, "npx", ["eslint", ...g.rel], signal, checks, { ...co, kind: "static" });
13746
13787
  if (await excuseLint(ctx, signal, c, "eslint", "npx", ["eslint"], g.cwd, g.rel, co))
13747
13788
  pre.push(c.name);
@@ -13756,7 +13797,7 @@ var CHECK_TIMEOUT_MS = 60000, excerpts, isHold = (c) => isHoldoutCheck(c.name),
13756
13797
  return r.missing || r.cut ? null : r;
13757
13798
  }, base: (f) => {
13758
13799
  try {
13759
- return safeGit(ctx.repoDir, ["show", `${ctx.baseSha}:${relative7(ctx.repoDir, join55(cwd, f))}`], { stdio: ["ignore", "pipe", "ignore"] });
13800
+ return safeGit(ctx.repoDir, ["show", `${ctx.baseSha}:${relative7(ctx.repoDir, join56(cwd, f))}`], { stdio: ["ignore", "pipe", "ignore"] });
13760
13801
  } catch {
13761
13802
  return null;
13762
13803
  }
@@ -13921,8 +13962,8 @@ ${x}` : c.cmd };
13921
13962
  });
13922
13963
 
13923
13964
  // ../../loki-ts/src/project_model/conventions.ts
13924
- import { existsSync as existsSync35, readdirSync as readdirSync18, readFileSync as readFileSync42 } from "fs";
13925
- import { dirname as dirname21, join as join56 } from "path";
13965
+ import { existsSync as existsSync36, readdirSync as readdirSync17, readFileSync as readFileSync42 } from "fs";
13966
+ import { dirname as dirname21, join as join57 } from "path";
13926
13967
  function parseJsonc(text2) {
13927
13968
  let out2 = "", i = 0;
13928
13969
  while (i < text2.length) {
@@ -13948,7 +13989,7 @@ function parseJsonc(text2) {
13948
13989
  return JSON.parse(out2.replace(/,(\s*[}\]])/g, "$1"));
13949
13990
  }
13950
13991
  function moduleOf(file, depth = 0) {
13951
- const j = readJson4(file);
13992
+ const j = readJson5(file);
13952
13993
  if (!j || depth > 4)
13953
13994
  return null;
13954
13995
  const m = j.compilerOptions?.module;
@@ -13957,25 +13998,25 @@ function moduleOf(file, depth = 0) {
13957
13998
  const ext = typeof j.extends === "string" ? j.extends : null;
13958
13999
  if (!ext || !ext.startsWith("."))
13959
14000
  return null;
13960
- const next = join56(dirname21(file), ext.endsWith(".json") ? ext : `${ext}.json`);
13961
- return existsSync35(next) ? moduleOf(next, depth + 1) : null;
14001
+ const next = join57(dirname21(file), ext.endsWith(".json") ? ext : `${ext}.json`);
14002
+ return existsSync36(next) ? moduleOf(next, depth + 1) : null;
13962
14003
  }
13963
14004
  function readPackageConventions(pkgDir, runner = null) {
13964
14005
  let names = [];
13965
14006
  try {
13966
- names = readdirSync18(pkgDir).filter((f) => f.endsWith(".json")).sort((x, y) => x.length - y.length || x.localeCompare(y));
14007
+ names = readdirSync17(pkgDir).filter((f) => f.endsWith(".json")).sort((x, y) => x.length - y.length || x.localeCompare(y));
13967
14008
  } catch {
13968
14009
  return null;
13969
14010
  }
13970
14011
  let packageType = null, tsModule = null;
13971
14012
  for (const n2 of names) {
13972
- const j = readJson4(join56(pkgDir, n2));
14013
+ const j = readJson5(join57(pkgDir, n2));
13973
14014
  if (!j)
13974
14015
  continue;
13975
14016
  if (packageType === null && typeof j.type === "string" && typeof j.name === "string")
13976
14017
  packageType = j.type;
13977
14018
  if (tsModule === null && j.compilerOptions !== undefined)
13978
- tsModule = moduleOf(join56(pkgDir, n2));
14019
+ tsModule = moduleOf(join57(pkgDir, n2));
13979
14020
  }
13980
14021
  if (packageType === null && tsModule === null)
13981
14022
  return null;
@@ -13995,7 +14036,7 @@ function conventionViolation(c, fileName, content) {
13995
14036
  const code = content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1").replace(/(["'`])(?:\\.|(?!\1)[^\\\n])*\1/g, '""');
13996
14037
  return /\bimport\.meta\b/.test(code) ? "import.meta is not allowed in a CommonJS package (TS1470)" : null;
13997
14038
  }
13998
- var readJson4 = (p) => {
14039
+ var readJson5 = (p) => {
13999
14040
  try {
14000
14041
  const v = parseJsonc(readFileSync42(p, "utf8"));
14001
14042
  return v && typeof v === "object" && !Array.isArray(v) ? v : null;
@@ -14006,16 +14047,16 @@ var readJson4 = (p) => {
14006
14047
  var init_conventions = () => {};
14007
14048
 
14008
14049
  // ../../loki-ts/src/engine10/stages/wall.ts
14009
- import { spawnSync as spawnSync4 } from "child_process";
14010
- import { existsSync as existsSync36, mkdirSync as mkdirSync23, mkdtempSync as mkdtempSync10, readFileSync as readFileSync43, readdirSync as readdirSync19, realpathSync as realpathSync20, rmSync as rmSync18, writeFileSync as writeFileSync26 } from "fs";
14050
+ import { spawnSync as spawnSync5 } from "child_process";
14051
+ import { existsSync as existsSync37, mkdirSync as mkdirSync23, mkdtempSync as mkdtempSync10, readFileSync as readFileSync43, readdirSync as readdirSync18, realpathSync as realpathSync20, rmSync as rmSync18, writeFileSync as writeFileSync26 } from "fs";
14011
14052
  import { tmpdir as tmpdir11 } from "os";
14012
- import { dirname as dirname22, isAbsolute as isAbsolute9, join as join57, relative as relative8 } from "path";
14053
+ import { dirname as dirname22, isAbsolute as isAbsolute9, join as join58, relative as relative8 } from "path";
14013
14054
  function pytestCollectionIsRed(output, repoDir) {
14014
14055
  if (/ModuleNotFoundError/.test(output))
14015
14056
  return false;
14016
14057
  const real2 = (p) => {
14017
14058
  try {
14018
- return realpathSync20(isAbsolute9(p) ? p : join57(repoDir, p));
14059
+ return realpathSync20(isAbsolute9(p) ? p : join58(repoDir, p));
14019
14060
  } catch {
14020
14061
  return null;
14021
14062
  }
@@ -14052,7 +14093,7 @@ function pytestCollectionIsRed(output, repoDir) {
14052
14093
  }
14053
14094
  function moduleUnderRepo(repoDir, name) {
14054
14095
  const rel = name.replace(/\./g, "/");
14055
- return existsSync36(join57(repoDir, `${rel}.py`)) || existsSync36(join57(repoDir, rel, "__init__.py"));
14096
+ return existsSync37(join58(repoDir, `${rel}.py`)) || existsSync37(join58(repoDir, rel, "__init__.py"));
14056
14097
  }
14057
14098
  function pytestExit1IsRed(output) {
14058
14099
  if (/^!+ _pytest\.outcomes\.Exit\b/m.test(output))
@@ -14107,26 +14148,26 @@ class RealBaseTestRunner {
14107
14148
  }
14108
14149
  run(repoDir, files) {
14109
14150
  this.lastNotRunFiles = [];
14110
- let pass = 0, fail = 0, not_run = 0;
14151
+ let pass = 0, fail2 = 0, not_run = 0;
14111
14152
  const not_run_files = [];
14112
14153
  const api = this.api === undefined ? loadProjectApi(repoDir) : this.api;
14113
14154
  for (const f of files) {
14114
14155
  const { cmd, args, interpreter, cwd } = commandFor(f, repoDir, api);
14115
- const r = spawnSync4(cmd, f.runner === "pytest" ? [...args, "-rfE"] : args, { cwd, encoding: "utf8", timeout: Math.max(1000, this.timeoutMs), env: plainTestEnv() });
14156
+ const r = spawnSync5(cmd, f.runner === "pytest" ? [...args, "-rfE"] : args, { cwd, encoding: "utf8", timeout: Math.max(1000, this.timeoutMs), env: plainTestEnv() });
14116
14157
  const status = r.error ? null : r.status;
14117
14158
  const result = classify(f, status, stripAnsi(`${r.stdout ?? ""}
14118
14159
  ${r.stderr ?? ""}`), repoDir, interpreter);
14119
14160
  if (result === "pass")
14120
14161
  pass++;
14121
14162
  else if (result === "fail")
14122
- fail++;
14163
+ fail2++;
14123
14164
  else {
14124
14165
  not_run++;
14125
14166
  not_run_files.push({ file: f.path, reason: notRunReason(status, interpreter) });
14126
14167
  }
14127
14168
  }
14128
14169
  this.lastNotRunFiles = not_run_files;
14129
- return { pass, fail, not_run };
14170
+ return { pass, fail: fail2, not_run };
14130
14171
  }
14131
14172
  }
14132
14173
  function buildWallBrief(task, repomapText = "", runners = [], hasManifest = false, conventions = "", acceptance = []) {
@@ -14151,8 +14192,8 @@ ${acceptance.map((a) => `Acceptance: ${a}`).join(`
14151
14192
  function loadTaskText(ctx, fromPrior) {
14152
14193
  if (fromPrior)
14153
14194
  return fromPrior;
14154
- const issueJsonPath = process.env.LOKI_E10_ISSUE_JSON ?? join57(ctx.runDir, "issue.json");
14155
- if (existsSync36(issueJsonPath)) {
14195
+ const issueJsonPath = process.env.LOKI_E10_ISSUE_JSON ?? join58(ctx.runDir, "issue.json");
14196
+ if (existsSync37(issueJsonPath)) {
14156
14197
  try {
14157
14198
  const issue = JSON.parse(readFileSync43(issueJsonPath, "utf8"));
14158
14199
  const text2 = [issue.title, issue.body].filter((s) => typeof s === "string" && s.length > 0).join(`
@@ -14166,7 +14207,7 @@ function loadTaskText(ctx, fromPrior) {
14166
14207
  }
14167
14208
  function wallTargetDir(repoDir, existingTests) {
14168
14209
  const first = existingTests[0];
14169
- return first ? join57(repoDir, dirname22(first.path)) : join57(repoDir, "tests");
14210
+ return first ? join58(repoDir, dirname22(first.path)) : join58(repoDir, "tests");
14170
14211
  }
14171
14212
  function guessRunner(fileName, runners) {
14172
14213
  if (fileName.endsWith(".py"))
@@ -14199,11 +14240,11 @@ async function wallAuthor(ctx, signal, retry) {
14199
14240
  const tree = prior.intake?.tree;
14200
14241
  const repomapText = repoMapText(ctx.repoDir, tree, repomapRef, WALL_MAP_MAX_LINES);
14201
14242
  const targetDir = wallTargetDir(ctx.repoDir, existingTests), pkg = loadProjectApi(ctx.repoDir)?.packageOf(`${relative8(ctx.repoDir, targetDir)}/x`);
14202
- const conv2 = readPackageConventions(join57(ctx.repoDir, pkg?.root ?? "."), pkg?.runner ?? null);
14203
- const cwd = mkdtempSync10(join57(tmpdir11(), "loki-e15-wall-"));
14243
+ const conv2 = readPackageConventions(join58(ctx.repoDir, pkg?.root ?? "."), pkg?.runner ?? null);
14244
+ const cwd = mkdtempSync10(join58(tmpdir11(), "loki-e15-wall-"));
14204
14245
  const wm = wallManifestFor(ctx.repoDir, tree, task);
14205
14246
  for (const [n2, c] of [["task.md", task], ["repomap.txt", repomapText], ...wm ? [["wall_manifest.txt", wm.text]] : []])
14206
- writeFileSync26(join57(cwd, n2), c, "utf8");
14247
+ writeFileSync26(join58(cwd, n2), c, "utf8");
14207
14248
  const model = retry?.model ?? wallFirstModel(sz.size), iterationId = `${ctx.runId}-wall${retry?.suffix ?? ""}`;
14208
14249
  const session = await ctx.sessions.run({
14209
14250
  stage: "wall",
@@ -14219,15 +14260,15 @@ async function wallAuthor(ctx, signal, retry) {
14219
14260
  rmSync18(cwd, { recursive: true, force: true });
14220
14261
  return done({ status: "failed", data: { iteration_ids: [iterationId], model }, reason: "wall session aborted, killed, or timed out", killed: true });
14221
14262
  }
14222
- const all = readdirSync19(cwd).filter((f) => f.startsWith(WALL_PREFIX)), held = stashHoldout({ runId: ctx.runId, repoDir: ctx.repoDir, srcDir: cwd, targetDir, names: all.filter((n2) => !conventionViolation(conv2, n2, readFileSync43(join57(cwd, n2), "utf8"))), runnerOf: (n2) => guessRunner(n2, runners) }), generated = all.filter((n2) => !held?.names.has(n2));
14223
- const sealedDir = join57(ctx.runDir, "wall");
14263
+ const all = readdirSync18(cwd).filter((f) => f.startsWith(WALL_PREFIX)), held = stashHoldout({ runId: ctx.runId, repoDir: ctx.repoDir, srcDir: cwd, targetDir, names: all.filter((n2) => !conventionViolation(conv2, n2, readFileSync43(join58(cwd, n2), "utf8"))), runnerOf: (n2) => guessRunner(n2, runners) }), generated = all.filter((n2) => !held?.names.has(n2));
14264
+ const sealedDir = join58(ctx.runDir, "wall");
14224
14265
  if (generated.length > 0)
14225
14266
  mkdirSync23(sealedDir, { recursive: true });
14226
14267
  const contents = new Map;
14227
14268
  const discarded = [];
14228
14269
  for (const name of generated) {
14229
- const content = readFileSync43(join57(cwd, name), "utf8"), bad = conventionViolation(conv2, name, content);
14230
- writeFileSync26(join57(sealedDir, name), content, "utf8");
14270
+ const content = readFileSync43(join58(cwd, name), "utf8"), bad = conventionViolation(conv2, name, content);
14271
+ writeFileSync26(join58(sealedDir, name), content, "utf8");
14231
14272
  if (bad)
14232
14273
  discarded.push({ file: name, reason: `${bad}; wall test did not compile under the package config` });
14233
14274
  else
@@ -14247,7 +14288,7 @@ function installWall(ctx, a, baseDir, opts = {}) {
14247
14288
  const content = contents.get(name);
14248
14289
  if (content === undefined)
14249
14290
  continue;
14250
- const dest = join57(targetDir, name), runner = guessRunner(name, runners);
14291
+ const dest = join58(targetDir, name), runner = guessRunner(name, runners);
14251
14292
  writeFileSync26(dest, content, "utf8");
14252
14293
  sealedFiles.push({ path: dest, sha256: sha2562(content) });
14253
14294
  readOnlyFiles.push({ path: dest, content });
@@ -14258,7 +14299,7 @@ function installWall(ctx, a, baseDir, opts = {}) {
14258
14299
  ctx.emit("wall.sealed", "wall", { files: sealedFiles, ...a.manifestSha256 ? { manifest_sha256: a.manifestSha256 } : {} });
14259
14300
  const baseRunner = opts.baseRunner ?? new RealBaseTestRunner, baseRun = { pass: 0, fail: 0, not_run: discarded.length }, notRunFiles = [];
14260
14301
  for (const t of wallTests) {
14261
- const r = baseRunner.run(baseDir, [t]), abs = join57(ctx.repoDir, t.path);
14302
+ const r = baseRunner.run(baseDir, [t]), abs = join58(ctx.repoDir, t.path);
14262
14303
  baseRun.pass += r.pass;
14263
14304
  baseRun.fail += r.fail;
14264
14305
  baseRun.not_run += r.not_run ?? 0;
@@ -14298,7 +14339,7 @@ async function runWall(ctx, signal, opts = {}) {
14298
14339
  if (a.kind === "authored") {
14299
14340
  for (const f of first.data.files ?? [])
14300
14341
  rmSync18(f.path, { force: true });
14301
- rmSync18(join57(ctx.runDir, "wall"), { recursive: true, force: true });
14342
+ rmSync18(join58(ctx.runDir, "wall"), { recursive: true, force: true });
14302
14343
  ctx.wallSealed = false;
14303
14344
  }
14304
14345
  removeHoldout(ctx.runId, ctx.repoDir);
@@ -14333,18 +14374,18 @@ var init_wall = __esm(() => {
14333
14374
  });
14334
14375
 
14335
14376
  // ../../loki-ts/src/e10ext/discard.ts
14336
- import { chmodSync as chmodSync5, closeSync as closeSync9, lstatSync as lstatSync12, mkdirSync as mkdirSync24, openSync as openSync9, readFileSync as readFileSync44, realpathSync as realpathSync21, rmdirSync, unlinkSync as unlinkSync6, writeFileSync as writeFileSync27 } from "fs";
14337
- import { dirname as dirname23, join as join58, relative as relative9, sep as sep12 } from "path";
14377
+ import { chmodSync as chmodSync5, closeSync as closeSync9, lstatSync as lstatSync13, mkdirSync as mkdirSync24, openSync as openSync9, readFileSync as readFileSync44, realpathSync as realpathSync21, rmdirSync, unlinkSync as unlinkSync6, writeFileSync as writeFileSync27 } from "fs";
14378
+ import { dirname as dirname23, join as join59, relative as relative9, sep as sep12 } from "path";
14338
14379
  function safeRestore(repoDir, f, want, mode) {
14339
- const root = realpathSync21(repoDir), fp = join58(root, f), rel = relative9(root, dirname23(fp));
14380
+ const root = realpathSync21(repoDir), fp = join59(root, f), rel = relative9(root, dirname23(fp));
14340
14381
  if (rel.startsWith(".."))
14341
14382
  throw new Error("outside repo");
14342
14383
  let cur = root;
14343
14384
  for (const part of rel === "" ? [] : rel.split(sep12)) {
14344
- cur = join58(cur, part);
14385
+ cur = join59(cur, part);
14345
14386
  let st2;
14346
14387
  try {
14347
- st2 = lstatSync12(cur);
14388
+ st2 = lstatSync13(cur);
14348
14389
  } catch {
14349
14390
  mkdirSync24(cur);
14350
14391
  continue;
@@ -14354,7 +14395,7 @@ function safeRestore(repoDir, f, want, mode) {
14354
14395
  }
14355
14396
  let st;
14356
14397
  try {
14357
- st = lstatSync12(fp);
14398
+ st = lstatSync13(fp);
14358
14399
  } catch {
14359
14400
  st = null;
14360
14401
  }
@@ -14396,10 +14437,10 @@ async function discardIfSatisfied(git3, base, o, staged, keep, repoDir) {
14396
14437
  return { status: "failed", data: {}, reason: "already-satisfied discard failed" };
14397
14438
  const notProven = [];
14398
14439
  for (const [f, v] of Object.entries(o.intake?.preexisting_untracked_blobs ?? {})) {
14399
- const fp = join58(repoDir, f);
14440
+ const fp = join59(repoDir, f);
14400
14441
  try {
14401
14442
  if (v.startsWith("!")) {
14402
- const st = lstatSync12(fp);
14443
+ const st = lstatSync13(fp);
14403
14444
  if (`!${st.size}:${st.mtimeMs}:${st.ctimeMs}` !== v)
14404
14445
  throw new Error("changed, not snapshotted");
14405
14446
  continue;
@@ -14415,7 +14456,7 @@ async function discardIfSatisfied(git3, base, o, staged, keep, repoDir) {
14415
14456
  try {
14416
14457
  let m = 420;
14417
14458
  try {
14418
- const l = lstatSync12(join58(repoDir, f));
14459
+ const l = lstatSync13(join59(repoDir, f));
14419
14460
  if (l.isFile())
14420
14461
  m = l.mode & 511;
14421
14462
  } catch {}
@@ -14459,7 +14500,7 @@ var init_commit_filter = __esm(() => {
14459
14500
  });
14460
14501
 
14461
14502
  // ../../loki-ts/src/e10ext/scope.ts
14462
- import { basename as basename21, dirname as dirname25 } from "path";
14503
+ import { basename as basename20, dirname as dirname25 } from "path";
14463
14504
  function contractText(o) {
14464
14505
  const c = o.intake?.contract_snapshot?.contract;
14465
14506
  return Array.isArray(c?.criteria) ? c.criteria.map((x) => typeof x?.text === "string" ? x.text : "").join(`
@@ -14474,26 +14515,26 @@ function outsideScope(o, staged) {
14474
14515
  ${typeof o.intake?.task === "string" ? o.intake.task : ""}
14475
14516
  ${contractText(o)}`, pre = o.intake?.preexisting_dirty ?? {};
14476
14517
  const toks = surfaceTokens(text2), plannedDirs = new Set(rel.map((r) => dirname25(r)).filter((d) => d !== "."));
14477
- return staged.filter(({ st, f }) => st !== "A" && !isTestFile(f) && !Object.hasOwn(pre, f) && !rel.includes(f) && !mentions(text2, f) && !mentions(text2, basename21(f)) && !plannedDirs.has(dirname25(f)) && !dirSegs(f).some((d) => toks.has(d))).map(({ f }) => f);
14518
+ return staged.filter(({ st, f }) => st !== "A" && !isTestFile(f) && !Object.hasOwn(pre, f) && !rel.includes(f) && !mentions(text2, f) && !mentions(text2, basename20(f)) && !plannedDirs.has(dirname25(f)) && !dirSegs(f).some((d) => toks.has(d))).map(({ f }) => f);
14478
14519
  }
14479
14520
  function flagOutsideScope(o, staged) {
14480
14521
  const unit = unitFlags(staged, process.env, o.intake?.preexisting_dirty ?? {});
14481
14522
  const un = outsideScope(o, staged), seen = new Set((unit ?? []).map(outsideNote));
14482
14523
  return [...(unit ?? []).map(outsideNote), ...un ? un.map(outsideNote).filter((n2) => !seen.has(n2)) : staged.length > 0 ? [SCOPE_UNDETERMINED] : []];
14483
14524
  }
14484
- var SCOPE_UNDETERMINED = "scope not determined; all edits committed", outsideNote = (f) => `outside stated scope: ${f}`, esc2 = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), mentions = (text2, name) => new RegExp(`(?<![\\w./-])${esc2(name)}(?![\\w-]|\\.\\w)`).test(text2), STOP, stem = (w) => w.length > 3 && w.endsWith("s") ? w.slice(0, -1) : w, surfaceTokens = (text2) => new Set((text2.toLowerCase().match(/[a-z][a-z0-9_-]{2,}/g) ?? []).filter((w) => !STOP.has(w)).map(stem)), dirSegs = (f) => f.split("/").slice(0, -1).map((d) => stem(d.toLowerCase()));
14525
+ var SCOPE_UNDETERMINED = "scope not determined; all edits committed", outsideNote = (f) => `outside stated scope: ${f}`, esc2 = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), mentions = (text2, name) => new RegExp(`(?<![\\w./-])${esc2(name)}(?![\\w-]|\\.\\w)`).test(text2), STOP2, stem = (w) => w.length > 3 && w.endsWith("s") ? w.slice(0, -1) : w, surfaceTokens = (text2) => new Set((text2.toLowerCase().match(/[a-z][a-z0-9_-]{2,}/g) ?? []).filter((w) => !STOP2.has(w)).map(stem)), dirSegs = (f) => f.split("/").slice(0, -1).map((d) => stem(d.toLowerCase()));
14485
14526
  var init_scope2 = __esm(() => {
14486
14527
  init_testmap();
14487
14528
  init_unit_mode();
14488
- STOP = new Set(["the", "and", "for", "with", "that", "this", "all", "any", "src", "from", "into", "each", "across", "apply", "add", "use", "make"]);
14529
+ STOP2 = new Set(["the", "and", "for", "with", "that", "this", "all", "any", "src", "from", "into", "each", "across", "apply", "add", "use", "make"]);
14489
14530
  });
14490
14531
 
14491
14532
  // ../../loki-ts/src/council/role_agents.ts
14492
- import { existsSync as existsSync37, readdirSync as readdirSync20, readFileSync as readFileSync45 } from "fs";
14533
+ import { existsSync as existsSync38, readdirSync as readdirSync19, readFileSync as readFileSync45 } from "fs";
14493
14534
  import { homedir as homedir9 } from "os";
14494
- import { join as join59 } from "path";
14535
+ import { join as join60 } from "path";
14495
14536
  function agentDirs(repoDir, env = process.env) {
14496
- return [env["LOKI_AGENTS_PROJECT_DIR"] || join59(repoDir, ".loki", "agents"), env["LOKI_AGENTS_USER_DIR"] || join59(env["XDG_CONFIG_HOME"] || join59(homedir9(), ".config"), "loki", "agents")];
14537
+ return [env["LOKI_AGENTS_PROJECT_DIR"] || join60(repoDir, ".loki", "agents"), env["LOKI_AGENTS_USER_DIR"] || join60(env["XDG_CONFIG_HOME"] || join60(homedir9(), ".config"), "loki", "agents")];
14497
14538
  }
14498
14539
  function parseAgent(file, stem2) {
14499
14540
  const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(readFileSync45(file, "utf8"));
@@ -14510,18 +14551,18 @@ function parseAgent(file, stem2) {
14510
14551
  }
14511
14552
  function loadRoleAgent(repoDir, role, env = process.env) {
14512
14553
  for (const d of agentDirs(repoDir, env)) {
14513
- if (!existsSync37(d))
14554
+ if (!existsSync38(d))
14514
14555
  continue;
14515
14556
  let names;
14516
14557
  try {
14517
- names = readdirSync20(d).filter((n2) => n2.endsWith(".md") && !n2.startsWith(".")).sort();
14558
+ names = readdirSync19(d).filter((n2) => n2.endsWith(".md") && !n2.startsWith(".")).sort();
14518
14559
  } catch {
14519
14560
  continue;
14520
14561
  }
14521
14562
  const ordered = [...names.filter((n2) => n2 === `${role}.md`), ...names.filter((n2) => n2 !== `${role}.md`)];
14522
14563
  for (const n2 of ordered) {
14523
14564
  try {
14524
- const a = parseAgent(join59(d, n2), n2.slice(0, -3));
14565
+ const a = parseAgent(join60(d, n2), n2.slice(0, -3));
14525
14566
  if (a && a.role === role)
14526
14567
  return a;
14527
14568
  } catch {}
@@ -14539,7 +14580,7 @@ var init_role_agents = __esm(() => {
14539
14580
 
14540
14581
  // ../../loki-ts/src/util/child_ledger.ts
14541
14582
  import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync25 } from "fs";
14542
- import { join as join60 } from "path";
14583
+ import { join as join61 } from "path";
14543
14584
  function unmeasuredRecord(phase, model, source) {
14544
14585
  return { phase, model, input_tokens: 0, output_tokens: 0, cache_creation_tokens: 0, cache_read_tokens: 0, source, cost_status: "unmeasured" };
14545
14586
  }
@@ -14564,9 +14605,9 @@ function recordFromClaudeResult(phase, payload, source = "claude-json") {
14564
14605
  }
14565
14606
  function appendChildLedger(lokiDir2, rec2) {
14566
14607
  try {
14567
- const dir = join60(lokiDir2, "metrics");
14608
+ const dir = join61(lokiDir2, "metrics");
14568
14609
  mkdirSync25(dir, { recursive: true });
14569
- appendFileSync4(join60(dir, "child-sessions.jsonl"), `${JSON.stringify(rec2)}
14610
+ appendFileSync4(join61(dir, "child-sessions.jsonl"), `${JSON.stringify(rec2)}
14570
14611
  `);
14571
14612
  return true;
14572
14613
  } catch {
@@ -14596,12 +14637,12 @@ var init_child_ledger = __esm(() => {
14596
14637
  });
14597
14638
 
14598
14639
  // ../../loki-ts/src/util/run_summary.ts
14599
- import { existsSync as existsSync38, mkdirSync as mkdirSync26, readFileSync as readFileSync46, renameSync as renameSync11, statSync as statSync18, writeFileSync as writeFileSync28 } from "fs";
14600
- import { join as join61 } from "path";
14640
+ import { existsSync as existsSync39, mkdirSync as mkdirSync26, readFileSync as readFileSync46, renameSync as renameSync12, statSync as statSync17, writeFileSync as writeFileSync28 } from "fs";
14641
+ import { join as join62 } from "path";
14601
14642
  function readRiskRecord(repoDir, sinceMs = 0) {
14602
14643
  try {
14603
- const p = join61(repoDir, ".loki", "state", "risk-tier.json");
14604
- if (statSync18(p).mtimeMs < sinceMs)
14644
+ const p = join62(repoDir, ".loki", "state", "risk-tier.json");
14645
+ if (statSync17(p).mtimeMs < sinceMs)
14605
14646
  return null;
14606
14647
  const r = JSON.parse(readFileSync46(p, "utf8"));
14607
14648
  return r && typeof r === "object" ? r : null;
@@ -14617,8 +14658,8 @@ var init_run_summary = __esm(() => {
14617
14658
  });
14618
14659
 
14619
14660
  // ../../loki-ts/src/engine10/stages/xreview.ts
14620
- import { existsSync as existsSync39, readFileSync as readFileSync47 } from "fs";
14621
- import { join as join62 } from "path";
14661
+ import { existsSync as existsSync40, readFileSync as readFileSync47 } from "fs";
14662
+ import { join as join63 } from "path";
14622
14663
  function minVerdict(verdict, review) {
14623
14664
  const ceiling = review?.level === "block" ? "PARTIAL" : verdict;
14624
14665
  return RANK3[ceiling] < RANK3[verdict] ? ceiling : verdict;
@@ -14631,8 +14672,8 @@ function explicitReview(repoDir, env) {
14631
14672
  if (flag && isOff(ev))
14632
14673
  return "off";
14633
14674
  for (const f of ["loki.yaml", "loki.yml"]) {
14634
- const p = join62(repoDir, f);
14635
- if (!existsSync39(p))
14675
+ const p = join63(repoDir, f);
14676
+ if (!existsSync40(p))
14636
14677
  continue;
14637
14678
  try {
14638
14679
  const m = /^review:[ \t]*["']?([A-Za-z]+)["']?[ \t]*(?:#.*)?$/m.exec(readFileSync47(p, "utf8"));
@@ -14717,7 +14758,7 @@ Review ONLY the diff below. Do not modify files.` : "You are an independent code
14717
14758
  try {
14718
14759
  if (p === "claude")
14719
14760
  await ensureClaudeHelpCache();
14720
- const r = await withChildLedger(run, join62(ctx.repoDir, ".loki"), "xreview")(reviewArgv(p, prompt, process.env, p === "claude" ? agent?.model : undefined), { cwd: ctx.repoDir, timeoutMs: TIMEOUT_MS });
14761
+ const r = await withChildLedger(run, join63(ctx.repoDir, ".loki"), "xreview")(reviewArgv(p, prompt, process.env, p === "claude" ? agent?.model : undefined), { cwd: ctx.repoDir, timeoutMs: TIMEOUT_MS });
14721
14762
  if (r.exitCode !== 0)
14722
14763
  return { provider: p, level: "not_run", notes: [`cross-review not run: ${p} exited ${r.exitCode}`] };
14723
14764
  return parseReview(p, r.stdout);
@@ -14811,14 +14852,14 @@ See also: loki cost --detail (what a run ALREADY spent)
14811
14852
  });
14812
14853
 
14813
14854
  // ../../loki-ts/src/features/contract.ts
14814
- import { existsSync as existsSync40, lstatSync as lstatSync13, mkdirSync as mkdirSync27, readFileSync as readFileSync48, rmSync as rmSync19, writeFileSync as writeFileSync29 } from "fs";
14815
- import { dirname as dirname26, join as join63 } from "path";
14816
- import { createHash as createHash16 } from "crypto";
14855
+ import { existsSync as existsSync41, lstatSync as lstatSync14, mkdirSync as mkdirSync27, readFileSync as readFileSync48, rmSync as rmSync19, writeFileSync as writeFileSync29 } from "fs";
14856
+ import { dirname as dirname26, join as join64 } from "path";
14857
+ import { createHash as createHash15 } from "crypto";
14817
14858
  function contractEnabled(env = process.env) {
14818
14859
  return env["LOKI_CONTRACT"] !== "0";
14819
14860
  }
14820
14861
  function words(s) {
14821
- return [...new Set(s.toLowerCase().split(/[^a-z0-9]+/).filter((w) => w.length >= 3 && !STOP2.has(w)))];
14862
+ return [...new Set(s.toLowerCase().split(/[^a-z0-9]+/).filter((w) => w.length >= 3 && !STOP3.has(w)))];
14822
14863
  }
14823
14864
  function overlaps(criterionWords, target) {
14824
14865
  const tw = new Set(words(target));
@@ -14844,13 +14885,13 @@ function untracedLines(trace) {
14844
14885
  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)}`);
14845
14886
  }
14846
14887
  function contractPath(repoDir) {
14847
- return join63(repoDir, ".loki", "contract.json");
14888
+ return join64(repoDir, ".loki", "contract.json");
14848
14889
  }
14849
14890
  function readContract(repoDir) {
14850
14891
  const p = contractPath(repoDir);
14851
14892
  let st;
14852
14893
  try {
14853
- st = lstatSync13(p);
14894
+ st = lstatSync14(p);
14854
14895
  } catch {
14855
14896
  return { contract: null, notes: [], sha256: null };
14856
14897
  }
@@ -14864,7 +14905,7 @@ function readContract(repoDir) {
14864
14905
  } catch {
14865
14906
  return { contract: null, notes: ["contract unreadable: read failed"], sha256: null };
14866
14907
  }
14867
- const sha2563 = createHash16("sha256").update(raw2).digest("hex");
14908
+ const sha2563 = createHash15("sha256").update(raw2).digest("hex");
14868
14909
  let j;
14869
14910
  try {
14870
14911
  j = JSON.parse(raw2.toString("utf8"));
@@ -14895,7 +14936,7 @@ function sealContract(repoDir, body, rawDiff, checks, env = process.env, snap) {
14895
14936
  const live2 = readContract(repoDir);
14896
14937
  let exists2 = true;
14897
14938
  try {
14898
- lstatSync13(contractPath(repoDir));
14939
+ lstatSync14(contractPath(repoDir));
14899
14940
  } catch {
14900
14941
  exists2 = false;
14901
14942
  }
@@ -14921,36 +14962,36 @@ function sealContract(repoDir, body, rawDiff, checks, env = process.env, snap) {
14921
14962
  return [`contract trace failed: ${sanitizeCriterion(e instanceof Error ? e.message : String(e))}`];
14922
14963
  }
14923
14964
  }
14924
- var MAX_CRITERIA = 50, MAX_TEXT = 500, STOP2, MAX_CONTRACT_BYTES, REQ_MAP_REL, REQ_STOP;
14965
+ var MAX_CRITERIA = 50, MAX_TEXT = 500, STOP3, MAX_CONTRACT_BYTES, REQ_MAP_REL, REQ_STOP;
14925
14966
  var init_contract = __esm(() => {
14926
14967
  init_atomic();
14927
14968
  init_spec_file();
14928
14969
  init_paths();
14929
14970
  init_safe_git();
14930
- STOP2 = 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"]);
14971
+ 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"]);
14931
14972
  MAX_CONTRACT_BYTES = 1024 * 1024;
14932
- REQ_MAP_REL = join63(".loki", "state", "requirements-map.json");
14973
+ REQ_MAP_REL = join64(".loki", "state", "requirements-map.json");
14933
14974
  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"]);
14934
14975
  });
14935
14976
 
14936
14977
  // ../../loki-ts/src/features/speed/seal_group.ts
14937
- import { createHash as createHash17 } from "crypto";
14938
- import { existsSync as existsSync41, mkdirSync as mkdirSync28, readdirSync as readdirSync21, readFileSync as readFileSync49, renameSync as renameSync12, statSync as statSync19, writeFileSync as writeFileSync30 } from "fs";
14939
- import { dirname as dirname27, join as join64 } from "path";
14978
+ import { createHash as createHash16 } from "crypto";
14979
+ import { existsSync as existsSync42, mkdirSync as mkdirSync28, readdirSync as readdirSync20, readFileSync as readFileSync49, renameSync as renameSync13, statSync as statSync18, writeFileSync as writeFileSync30 } from "fs";
14980
+ import { dirname as dirname27, join as join65 } from "path";
14940
14981
  function sealGroup(runDir, rh) {
14941
- const manifestPath = join64(runDir, "group", "manifest.json");
14942
- if (!existsSync41(manifestPath))
14982
+ const manifestPath = join65(runDir, "group", "manifest.json");
14983
+ if (!existsSync42(manifestPath))
14943
14984
  return { section: undefined, notProven: [], problems: 0, allUnitsPass: true };
14944
14985
  const notProven = [];
14945
14986
  let problems = 0;
14946
- const fail = (m2) => {
14987
+ const fail2 = (m2) => {
14947
14988
  problems++;
14948
14989
  notProven.push(`group: ${m2}`);
14949
14990
  };
14950
- const m = readJson5(manifestPath);
14991
+ const m = readJson6(manifestPath);
14951
14992
  const list = isObj10(m) && Array.isArray(m["units"]) ? m["units"] : [];
14952
14993
  if (!isObj10(m) || !ID_RE.test(String(m["group_id"] ?? "")) || list.length === 0) {
14953
- fail("manifest missing, unreadable or empty");
14994
+ fail2("manifest missing, unreadable or empty");
14954
14995
  return { section: undefined, notProven, problems, allUnitsPass: false };
14955
14996
  }
14956
14997
  const units = [];
@@ -14960,19 +15001,19 @@ function sealGroup(runDir, rh) {
14960
15001
  const u = isObj10(raw2) ? raw2 : {};
14961
15002
  const id = String(u["unit_id"] ?? "");
14962
15003
  if (!ID_RE.test(id) || seen.has(id) || seenLower.has(id.toLowerCase()))
14963
- return fail(`unit ${index2} has an invalid, duplicate or case-colliding id`);
15004
+ return fail2(`unit ${index2} has an invalid, duplicate or case-colliding id`);
14964
15005
  seen.add(id);
14965
15006
  seenLower.add(id.toLowerCase());
14966
- const dir = join64(unitsDir(runDir), id), rp = join64(dir, "receipt.json"), ep = join64(dir, "events.jsonl");
15007
+ const dir = join65(unitsDir(runDir), id), rp = join65(dir, "receipt.json"), ep = join65(dir, "events.jsonl");
14967
15008
  let bytes;
14968
15009
  try {
14969
15010
  bytes = readFileSync49(rp);
14970
15011
  } catch {
14971
- return fail(`unit ${id} sub-receipt missing`);
15012
+ return fail2(`unit ${id} sub-receipt missing`);
14972
15013
  }
14973
- const sub = readJson5(rp);
15014
+ const sub = readJson6(rp);
14974
15015
  if (!isObj10(sub) || typeof sub["receipt_sha256"] !== "string" || rh(sub) !== sub["receipt_sha256"])
14975
- return fail(`unit ${id} sub-receipt unreadable or its hash does not recompute`);
15016
+ return fail2(`unit ${id} sub-receipt unreadable or its hash does not recompute`);
14976
15017
  const verdict = String(sub["verdict"] ?? "");
14977
15018
  if (!PASSING.has(verdict)) {
14978
15019
  allUnitsPass = false;
@@ -14983,7 +15024,7 @@ function sealGroup(runDir, rh) {
14983
15024
  unit_id: id,
14984
15025
  sub_receipt_sha256: sha3(bytes),
14985
15026
  receipt_sha256: sub["receipt_sha256"],
14986
- events_file_sha256: existsSync41(ep) ? sha3(readFileSync49(ep)) : null,
15027
+ events_file_sha256: existsSync42(ep) ? sha3(readFileSync49(ep)) : null,
14987
15028
  verdict,
14988
15029
  goal: text2(u["goal"], 200),
14989
15030
  files: (Array.isArray(u["files"]) ? u["files"] : []).map((f) => text2(f, 200)).filter(Boolean).slice(0, 50),
@@ -14994,7 +15035,7 @@ function sealGroup(runDir, rh) {
14994
15035
  });
14995
15036
  const extra = (dirNames(unitsDir(runDir)) ?? []).filter((n3) => !seen.has(n3));
14996
15037
  for (const n3 of extra)
14997
- fail(`unit directory ${text2(n3, 64)} is not in the manifest`);
15038
+ fail2(`unit directory ${text2(n3, 64)} is not in the manifest`);
14998
15039
  return { section: problems === 0 ? { group_id: String(m["group_id"]), units } : undefined, notProven, problems, allUnitsPass: allUnitsPass && problems === 0 };
14999
15040
  }
15000
15041
  function capGroupVerdict(v, g) {
@@ -15008,7 +15049,7 @@ async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
15008
15049
  const bad = (reason) => ({ verdict: "TAMPERED", reason: `group: ${reason}` });
15009
15050
  const g = receipt["group"];
15010
15051
  if (g === undefined)
15011
- return existsSync41(join64(runDir, "group", "manifest.json")) ? bad("group directory present but the receipt has no group section") : null;
15052
+ return existsSync42(join65(runDir, "group", "manifest.json")) ? bad("group directory present but the receipt has no group section") : null;
15012
15053
  if (!isObj10(g) || !ID_RE.test(String(g["group_id"] ?? "")) || !Array.isArray(g["units"]) || g["units"].length === 0)
15013
15054
  return bad("group section malformed");
15014
15055
  const entries = g["units"];
@@ -15020,12 +15061,12 @@ async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
15020
15061
  return bad("unit directories do not match the receipt (missing or extra unit)");
15021
15062
  let unchecked = null;
15022
15063
  for (let i = 0;i < entries.length; i++) {
15023
- const e = entries[i], id = ids[i], dir = join64(unitsDir(runDir), id), rp = join64(dir, "receipt.json"), ep = join64(dir, "events.jsonl");
15064
+ const e = entries[i], id = ids[i], dir = join65(unitsDir(runDir), id), rp = join65(dir, "receipt.json"), ep = join65(dir, "events.jsonl");
15024
15065
  if (e["index"] !== i)
15025
15066
  return bad(`unit ${id} is out of order (index ${String(e["index"])} at position ${i})`);
15026
15067
  let bytes;
15027
15068
  try {
15028
- if (!statSync19(dir).isDirectory())
15069
+ if (!statSync18(dir).isDirectory())
15029
15070
  return bad(`unit ${id} is not a directory`);
15030
15071
  bytes = readFileSync49(rp);
15031
15072
  } catch {
@@ -15033,10 +15074,10 @@ async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
15033
15074
  }
15034
15075
  if (sha3(bytes) !== e["sub_receipt_sha256"])
15035
15076
  return bad(`unit ${id} sub-receipt does not match its recorded hash`);
15036
- const evSha = existsSync41(ep) ? sha3(readFileSync49(ep)) : null;
15077
+ const evSha = existsSync42(ep) ? sha3(readFileSync49(ep)) : null;
15037
15078
  if (evSha !== (e["events_file_sha256"] ?? null))
15038
15079
  return bad(`unit ${id} events.jsonl does not match its recorded hash`);
15039
- const sub = readJson5(rp);
15080
+ const sub = readJson6(rp);
15040
15081
  if (!isObj10(sub) || sub["receipt_sha256"] !== e["receipt_sha256"] || rh(sub) !== e["receipt_sha256"])
15041
15082
  return bad(`unit ${id} sub-receipt hash does not recompute`);
15042
15083
  if (String(sub["verdict"] ?? "") !== e["verdict"])
@@ -15056,7 +15097,7 @@ function compositeVerdict(childVerdicts) {
15056
15097
  const failed2 = childVerdicts.filter((v) => v === "FAILED" || !["VERIFIED", "ALREADY_SATISFIED", "PARTIAL", "SPEC_CONFLICT"].includes(v)).length;
15057
15098
  return capGroupVerdict(base, { section: undefined, notProven: [], problems: failed2, allUnitsPass: childVerdicts.every((v) => PASSING.has(v)) });
15058
15099
  }
15059
- var ID_RE, PASSING, sha3 = (b) => createHash17("sha256").update(b).digest("hex"), isObj10 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), text2 = (v, cap) => typeof v === "string" ? v.replace(/[\x00-\x1f\x7f]+/g, " ").trim().slice(0, cap) : "", num4 = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : 0, unitsDir = (runDir) => join64(runDir, "group", "units"), readJson5 = (p) => {
15100
+ var ID_RE, PASSING, sha3 = (b) => createHash16("sha256").update(b).digest("hex"), isObj10 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), text2 = (v, cap) => typeof v === "string" ? v.replace(/[\x00-\x1f\x7f]+/g, " ").trim().slice(0, cap) : "", num4 = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : 0, unitsDir = (runDir) => join65(runDir, "group", "units"), readJson6 = (p) => {
15060
15101
  try {
15061
15102
  return JSON.parse(readFileSync49(p, "utf8"));
15062
15103
  } catch {
@@ -15064,7 +15105,7 @@ var ID_RE, PASSING, sha3 = (b) => createHash17("sha256").update(b).digest("hex")
15064
15105
  }
15065
15106
  }, dirNames = (d) => {
15066
15107
  try {
15067
- return readdirSync21(d).filter((n3) => !n3.startsWith(".")).sort();
15108
+ return readdirSync20(d).filter((n3) => !n3.startsWith(".")).sort();
15068
15109
  } catch {
15069
15110
  return null;
15070
15111
  }
@@ -15076,8 +15117,8 @@ var init_seal_group = __esm(() => {
15076
15117
  });
15077
15118
 
15078
15119
  // ../../loki-ts/src/supply/supply_guard.ts
15079
- import { existsSync as existsSync42, readFileSync as readFileSync50, statSync as statSync20 } from "fs";
15080
- import { basename as basename22, join as join65 } from "path";
15120
+ import { existsSync as existsSync43, readFileSync as readFileSync50, statSync as statSync19 } from "fs";
15121
+ import { basename as basename21, join as join66 } from "path";
15081
15122
  function supplyEnabled(env) {
15082
15123
  return env["LOKI_SUPPLY_GUARD"] !== "0";
15083
15124
  }
@@ -15089,14 +15130,14 @@ function supplyVerdict(verdict, r) {
15089
15130
  return r.blocked && verdict === "VERIFIED" ? "FAILED" : verdict;
15090
15131
  }
15091
15132
  function isManifestPath(path) {
15092
- return MANIFESTS.test(basename22(path));
15133
+ return MANIFESTS.test(basename21(path));
15093
15134
  }
15094
15135
  function readDeclared(repoDir) {
15095
- const p = join65(repoDir, ".loki", DECLARED_FILE);
15096
- if (!existsSync42(p))
15136
+ const p = join66(repoDir, ".loki", DECLARED_FILE);
15137
+ if (!existsSync43(p))
15097
15138
  return { deps: [], problem: null };
15098
15139
  try {
15099
- if (statSync20(p).size > MAX_FILE_BYTES)
15140
+ if (statSync19(p).size > MAX_FILE_BYTES)
15100
15141
  return { deps: [], problem: "declaration file too large" };
15101
15142
  const j = JSON.parse(readFileSync50(p, "utf8"));
15102
15143
  if (!Array.isArray(j))
@@ -15118,8 +15159,8 @@ function readDeclared(repoDir) {
15118
15159
  }
15119
15160
  }
15120
15161
  function readAllowlist(repoDir) {
15121
- const p = join65(repoDir, ".loki", "supply-allowlist");
15122
- if (!existsSync42(p))
15162
+ const p = join66(repoDir, ".loki", "supply-allowlist");
15163
+ if (!existsSync43(p))
15123
15164
  return new Set;
15124
15165
  try {
15125
15166
  return new Set(readFileSync50(p, "utf8").split(`
@@ -15163,7 +15204,7 @@ function userConfigPrivate(eco, repoDir, env, goEnv = {}, name = "") {
15163
15204
  if (eco === "npm") {
15164
15205
  if (privateUrlList([env["npm_config_registry"] ?? "", env["NPM_CONFIG_REGISTRY"] ?? ""]))
15165
15206
  return true;
15166
- return files(join65(repoDir, ".npmrc"), home ? join65(home, ".npmrc") : "").some((t) => t.split(`
15207
+ return files(join66(repoDir, ".npmrc"), home ? join66(home, ".npmrc") : "").some((t) => t.split(`
15167
15208
  `).some((l) => {
15168
15209
  const m = /^\s*(?:(@[^:\s]+):)?registry\s*=\s*(\S+)/.exec(l);
15169
15210
  return !!m && privateUrl(m[2]) && (m[1] === undefined || name.startsWith(`${m[1]}/`));
@@ -15172,7 +15213,7 @@ function userConfigPrivate(eco, repoDir, env, goEnv = {}, name = "") {
15172
15213
  if (eco === "pypi") {
15173
15214
  if (privateUrlList([env["PIP_INDEX_URL"] ?? "", env["PIP_EXTRA_INDEX_URL"] ?? ""]))
15174
15215
  return true;
15175
- const cfg = [env["PIP_CONFIG_FILE"] ?? "", home ? join65(home, ".config", "pip", "pip.conf") : "", home ? join65(home, ".pip", "pip.conf") : "", join65(repoDir, "pip.conf")];
15216
+ const cfg = [env["PIP_CONFIG_FILE"] ?? "", home ? join66(home, ".config", "pip", "pip.conf") : "", home ? join66(home, ".pip", "pip.conf") : "", join66(repoDir, "pip.conf")];
15176
15217
  return files(...cfg).some((t) => t.split(`
15177
15218
  `).some((l) => {
15178
15219
  const m = /^\s*(?:extra-)?index-url\s*[=:]\s*(.+)$/.exec(l);
@@ -15182,7 +15223,7 @@ function userConfigPrivate(eco, repoDir, env, goEnv = {}, name = "") {
15182
15223
  if (eco === "cargo") {
15183
15224
  if (Object.keys(env).some((k) => /^CARGO_REGISTRIES_.+_INDEX$/.test(k) || /^CARGO_SOURCE_/.test(k)))
15184
15225
  return true;
15185
- return files(join65(repoDir, ".cargo", "config.toml"), join65(repoDir, ".cargo", "config"), home ? join65(home, ".cargo", "config.toml") : "", home ? join65(home, ".cargo", "config") : "").some((t) => /^\s*\[(registries\.|source\.)/m.test(t) || /replace-with\s*=/.test(t));
15226
+ return files(join66(repoDir, ".cargo", "config.toml"), join66(repoDir, ".cargo", "config"), home ? join66(home, ".cargo", "config.toml") : "", home ? join66(home, ".cargo", "config") : "").some((t) => /^\s*\[(registries\.|source\.)/m.test(t) || /replace-with\s*=/.test(t));
15186
15227
  }
15187
15228
  if (eco === "go") {
15188
15229
  const gp = goEnv["GOPROXY"] ?? env["GOPROXY"] ?? "";
@@ -15305,7 +15346,7 @@ var MIN_AGE_DAYS = 7, DECLARED_FILE = "supply-declared.json", MAX_CHECKED = 50,
15305
15346
  }
15306
15347
  }, PUBLIC_HOSTS, hostOf = (u) => u.trim().toLowerCase().replace(/^[a-z][a-z0-9+.-]*:\/\//, "").replace(/^www\./, "").split(/[/?#\s]/)[0].replace(/^[^@]*@/, "").replace(/:\d+$/, ""), privateUrl = (u) => /[a-z0-9]/i.test(u) && !PUBLIC_HOSTS.has(hostOf(u)), readSmall = (p) => {
15307
15348
  try {
15308
- return statSync20(p).size <= MAX_FILE_BYTES ? readFileSync50(p, "utf8") : "";
15349
+ return statSync19(p).size <= MAX_FILE_BYTES ? readFileSync50(p, "utf8") : "";
15309
15350
  } catch {
15310
15351
  return "";
15311
15352
  }
@@ -15320,9 +15361,9 @@ var init_supply_guard = __esm(() => {
15320
15361
  });
15321
15362
 
15322
15363
  // ../../loki-ts/src/engine10/stages/seal.ts
15323
- import { createHash as createHash18 } from "crypto";
15324
- import { existsSync as existsSync43, readdirSync as readdirSync22, mkdirSync as mkdirSync29, readFileSync as readFileSync51, writeFileSync as writeFileSync31 } from "fs";
15325
- import { basename as basename23, isAbsolute as isAbsolute10, join as join66, relative as relative10 } from "path";
15364
+ import { createHash as createHash17 } from "crypto";
15365
+ import { existsSync as existsSync44, readdirSync as readdirSync21, mkdirSync as mkdirSync29, readFileSync as readFileSync51, writeFileSync as writeFileSync31 } from "fs";
15366
+ import { basename as basename22, isAbsolute as isAbsolute10, join as join67, relative as relative10 } from "path";
15326
15367
  function sanitizeReason(s) {
15327
15368
  const collapsed = s.replace(/[\x00-\x1f\x7f]+/g, " ").trim();
15328
15369
  const capped = collapsed.length > 500 ? `${collapsed.slice(0, 500)}...` : collapsed;
@@ -15397,8 +15438,8 @@ function renderReceiptMd(r) {
15397
15438
  ].join(`
15398
15439
  `);
15399
15440
  }
15400
- var DEEP_NOT_PROVEN, SIGNING_UNAVAILABLE = "receipt signing unavailable (no usable signing key: invalid key or unwritable ~/.loki/keys)", AGENT_ONLY_REASON = "only agent-authored tests executed (no agent-independent proof)", EXCLUDE_LOKI = ":(exclude).loki", sha2562 = (s) => createHash18("sha256").update(s).digest("hex"), str3 = (v) => typeof v === "string" && v !== "" ? v : null, strs2 = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string" && x !== "") : [], receiptRel = (ctx) => {
15401
- const r = relative10(ctx.repoDir, join66(ctx.runDir, "receipt.json"));
15441
+ var DEEP_NOT_PROVEN, SIGNING_UNAVAILABLE = "receipt signing unavailable (no usable signing key: invalid key or unwritable ~/.loki/keys)", AGENT_ONLY_REASON = "only agent-authored tests executed (no agent-independent proof)", EXCLUDE_LOKI = ":(exclude).loki", sha2562 = (s) => createHash17("sha256").update(s).digest("hex"), str3 = (v) => typeof v === "string" && v !== "" ? v : null, strs2 = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string" && x !== "") : [], receiptRel = (ctx) => {
15442
+ const r = relative10(ctx.repoDir, join67(ctx.runDir, "receipt.json"));
15402
15443
  return r.startsWith("..") || isAbsolute10(r) ? `.loki/runs/${ctx.runId}/receipt.json` : r;
15403
15444
  }, commitStage, wallGreenOnBaseOf = (o) => {
15404
15445
  const b = o.wall?.base_run ?? {};
@@ -15510,8 +15551,8 @@ var init_seal = __esm(() => {
15510
15551
  notProven.add(`Wall test not executed: ${wallNotRun} file(s), no reason recorded`);
15511
15552
  if (wallNotRun > 0) {
15512
15553
  try {
15513
- const kept = new Set((Array.isArray(o.wall?.files) ? o.wall.files : []).map((f) => basename23(String(f.path))));
15514
- for (const n3 of readdirSync22(join66(ctx.runDir, "wall")).sort())
15554
+ const kept = new Set((Array.isArray(o.wall?.files) ? o.wall.files : []).map((f) => basename22(String(f.path))));
15555
+ for (const n3 of readdirSync21(join67(ctx.runDir, "wall")).sort())
15515
15556
  if (!kept.has(n3))
15516
15557
  notProven.add(`wall test discarded: ${n3} (not_run)`);
15517
15558
  } catch {}
@@ -15574,19 +15615,19 @@ var init_seal = __esm(() => {
15574
15615
  for (const [s, d] of Object.entries(o))
15575
15616
  if (typeof d?.duration_s === "number")
15576
15617
  stages[s] = d.duration_s;
15577
- const T = hooks.time, time = T ? T.build(ctx, stages, T.firstEventMs(join66(ctx.runDir, "events.jsonl"))) : { wall_s: Object.values(stages).reduce((a, b) => a + (b ?? 0), 0), stages }, totalS = T?.reconciled(time) ?? null;
15618
+ const T = hooks.time, time = T ? T.build(ctx, stages, T.firstEventMs(join67(ctx.runDir, "events.jsonl"))) : { wall_s: Object.values(stages).reduce((a, b) => a + (b ?? 0), 0), stages }, totalS = T?.reconciled(time) ?? null;
15578
15619
  const iterIds = [...new Set([...Object.values(o).flatMap((d) => [...strs2(d?.iteration_ids), ...strs2([d?.iteration_id])]), ...ctx.sessionIds?.() ?? []])];
15579
15620
  if (iterIds.length === 0)
15580
15621
  notProven.add("cost not measured (no iteration ids recorded)");
15581
15622
  const cost = ctx.cost.read(ctx.repoDir, iterIds);
15582
15623
  if (cost.unmetered)
15583
15624
  notProven.add("cost unmetered (CLI invoker; recorded as 0)");
15584
- const eventsPath = join66(ctx.runDir, "events.jsonl");
15625
+ const eventsPath = join67(ctx.runDir, "events.jsonl");
15585
15626
  const wallFiles = Array.isArray(o.wall?.files) ? o.wall.files : [];
15586
15627
  const wallPassed = typeof o.verify?.wall_passed === "boolean" ? o.verify.wall_passed : null;
15587
15628
  if (wallFiles.length > 0 && wallPassed === null)
15588
15629
  notProven.add("wall result not recorded by verify");
15589
- 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(join66(ctx.repoDir, ".loki"), liveArchivedCosts(join66(ctx.repoDir, ".loki"), iterIds, UNMETERED)).router : undefined), ctx.model);
15630
+ 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(join67(ctx.repoDir, ".loki"), liveArchivedCosts(join67(ctx.repoDir, ".loki"), iterIds, UNMETERED)).router : undefined), ctx.model);
15590
15631
  if (routeBlock)
15591
15632
  for (const l of routeNotProven(routeBlock))
15592
15633
  notProven.add(l);
@@ -15628,7 +15669,7 @@ var init_seal = __esm(() => {
15628
15669
  provider: ctx.provider,
15629
15670
  model: ctx.model,
15630
15671
  resumed: o.intake?.resumed === true,
15631
- events_sha256: sha2562(existsSync43(eventsPath) ? readFileSync51(eventsPath) : ""),
15672
+ events_sha256: sha2562(existsSync44(eventsPath) ? readFileSync51(eventsPath) : ""),
15632
15673
  ...await sealEvidence(ctx.repoDir, ctx.runDir, o, notProven, signal, ctx.emit),
15633
15674
  log_seal: true,
15634
15675
  ...receiptBlock(process.env, cost.usd, cost.unmetered === true, totalS),
@@ -15650,10 +15691,10 @@ var init_seal = __esm(() => {
15650
15691
  }
15651
15692
  const receipt = { ...body, receipt_sha256: hash, verification: { jwt: sig.jwt, kid: sig.kid } };
15652
15693
  mkdirSync29(ctx.runDir, { recursive: true });
15653
- const path = join66(ctx.runDir, "receipt.json");
15694
+ const path = join67(ctx.runDir, "receipt.json");
15654
15695
  writeFileSync31(path, JSON.stringify(receipt, null, 2) + `
15655
15696
  `);
15656
- writeFileSync31(join66(ctx.runDir, "receipt.md"), renderReceiptMd(receipt));
15697
+ writeFileSync31(join67(ctx.runDir, "receipt.md"), renderReceiptMd(receipt));
15657
15698
  recordRun(process.env, ctx.repoDir, ranModel(o.implement, ctx.model, o.fix), verdict, cost.usd, cost.unmetered === true, totalS);
15658
15699
  try {
15659
15700
  hooks.sealed?.(ctx.runDir, JSON.parse(JSON.stringify(receipt), (_k, v) => v && typeof v === "object" ? Object.freeze(v) : v));
@@ -15765,14 +15806,14 @@ var DSSE_PAYLOAD_TYPE = "application/vnd.in-toto+json", STATEMENT_TYPE = "https:
15765
15806
  var init_receipt_dsse = () => {};
15766
15807
 
15767
15808
  // ../../loki-ts/src/util/composite_seal.ts
15768
- import { existsSync as existsSync44, readFileSync as readFileSync53 } from "fs";
15769
- import { basename as basename24, dirname as dirname29, join as join67 } from "path";
15809
+ import { existsSync as existsSync45, readFileSync as readFileSync53 } from "fs";
15810
+ import { basename as basename23, dirname as dirname29, join as join68 } from "path";
15770
15811
  function logProblem(runDir, integ) {
15771
15812
  if (typeof integ["log_sha256"] !== "string")
15772
15813
  return null;
15773
15814
  let b;
15774
15815
  try {
15775
- b = readFileSync53(join67(runDir, "integration.log"));
15816
+ b = readFileSync53(join68(runDir, "integration.log"));
15776
15817
  } catch {
15777
15818
  return "integration.log is missing but integration.json records its hash";
15778
15819
  }
@@ -15795,13 +15836,13 @@ async function verifyComposite(receiptPath, receipt, rh, verifyOne, deps = {}) {
15795
15836
  return bad("body malformed");
15796
15837
  let ibytes;
15797
15838
  try {
15798
- ibytes = readFileSync53(join67(runDir, "integration.json"));
15839
+ ibytes = readFileSync53(join68(runDir, "integration.json"));
15799
15840
  } catch {
15800
15841
  return bad("integration.json missing");
15801
15842
  }
15802
15843
  if (sha3(ibytes) !== receipt["integration_sha256"])
15803
15844
  return bad("integration.json does not match its recorded hash");
15804
- const integ = readJson5(join67(runDir, "integration.json"));
15845
+ const integ = readJson6(join68(runDir, "integration.json"));
15805
15846
  if (!isObj10(integ) || !isObj10(integ["outcomes"]))
15806
15847
  return bad("integration.json has no outcomes");
15807
15848
  const iprob = integrationProblem(integ);
@@ -15831,7 +15872,7 @@ async function verifyComposite(receiptPath, receipt, rh, verifyOne, deps = {}) {
15831
15872
  return bad(`child ${text2(repo, 80) || "?"} has an invalid receipt path`);
15832
15873
  if (outcomes[repo] !== "ok")
15833
15874
  return bad(`child ${text2(repo, 80)} did not finish ok in integration.json`);
15834
- const rp = join67(runDir, rel);
15875
+ const rp = join68(runDir, rel);
15835
15876
  let bytes;
15836
15877
  try {
15837
15878
  bytes = readFileSync53(rp);
@@ -15840,7 +15881,7 @@ async function verifyComposite(receiptPath, receipt, rh, verifyOne, deps = {}) {
15840
15881
  }
15841
15882
  if (sha3(bytes) !== c["receipt_file_sha256"])
15842
15883
  return bad(`child ${repo} receipt does not match its recorded hash (swapped or edited)`);
15843
- const sub = readJson5(rp);
15884
+ const sub = readJson6(rp);
15844
15885
  if (!isObj10(sub) || sub["receipt_sha256"] !== c["receipt_sha256"] || rh(sub) !== c["receipt_sha256"])
15845
15886
  return bad(`child ${repo} receipt hash does not recompute`);
15846
15887
  if (String(sub["verdict"] ?? "") !== c["verdict"])
@@ -15883,9 +15924,9 @@ var init_keys_cmd = __esm(() => {
15883
15924
  });
15884
15925
 
15885
15926
  // ../../loki-ts/src/engine10/verify_cmd.ts
15886
- import { existsSync as existsSync45, readFileSync as readFileSync54, renameSync as renameSync13, statSync as statSync22, writeFileSync as writeFileSync32 } from "fs";
15887
- import { basename as basename25, dirname as dirname30, join as join68 } from "path";
15888
- import { createHash as createHash19, createPublicKey as createPublicKey4, verify as verify4 } from "crypto";
15927
+ import { existsSync as existsSync46, readFileSync as readFileSync54, renameSync as renameSync14, statSync as statSync21, writeFileSync as writeFileSync32 } from "fs";
15928
+ import { basename as basename24, dirname as dirname30, join as join69 } from "path";
15929
+ import { createHash as createHash18, createPublicKey as createPublicKey4, verify as verify4 } from "crypto";
15889
15930
  function pubFor(kid, given) {
15890
15931
  if (given)
15891
15932
  return kidOf2(given) === kid ? given : undefined;
@@ -15931,13 +15972,13 @@ function checkEventLog(receiptPath, receipt) {
15931
15972
  }
15932
15973
  if (typeof bound !== "string")
15933
15974
  return null;
15934
- if (bound === createHash19("sha256").digest("hex")) {
15975
+ if (bound === createHash18("sha256").digest("hex")) {
15935
15976
  const st = receipt["time"]?.stages;
15936
15977
  const claims = st !== null && typeof st === "object" && Object.keys(st).length > 0;
15937
15978
  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;
15938
15979
  }
15939
- const path = join68(dirname30(receiptPath), "events.jsonl");
15940
- if (!existsSync45(path))
15980
+ const path = join69(dirname30(receiptPath), "events.jsonl");
15981
+ if (!existsSync46(path))
15941
15982
  return "events.jsonl is missing";
15942
15983
  const raw2 = readFileSync54(path, "utf8"), events2 = readEvents(path), lines2 = raw2.split(`
15943
15984
  `).filter((l) => l.trim() !== "");
@@ -15945,7 +15986,7 @@ function checkEventLog(receiptPath, receipt) {
15945
15986
  return "events.jsonl has a forged, edited or missing line";
15946
15987
  if (events2.some((e) => e.type === "tamper.detected"))
15947
15988
  return "the supervisor detected events.jsonl being modified during the run";
15948
- const h = createHash19("sha256");
15989
+ const h = createHash18("sha256");
15949
15990
  for (const l of lines2) {
15950
15991
  if (h.copy().digest("hex") === bound)
15951
15992
  return null;
@@ -15955,7 +15996,7 @@ function checkEventLog(receiptPath, receipt) {
15955
15996
  return h.digest("hex") === bound ? null : "events.jsonl does not match the hash recorded at seal";
15956
15997
  }
15957
15998
  function checkLogSeal(receiptPath, hash, kid, given) {
15958
- const path = join68(dirname30(receiptPath), "events.jsonl"), events2 = readEvents(path), done = events2.findIndex((e) => e.type === "run.completed");
15999
+ const path = join69(dirname30(receiptPath), "events.jsonl"), events2 = readEvents(path), done = events2.findIndex((e) => e.type === "run.completed");
15959
16000
  if (!events2.some((e) => e.type === "receipt.sealed" && e.data["receipt_sha256"] === hash))
15960
16001
  return { verdict: "TAMPERED", reason: "events.jsonl has no receipt.sealed event for this receipt" };
15961
16002
  if (done < 0)
@@ -15964,7 +16005,7 @@ function checkLogSeal(receiptPath, hash, kid, given) {
15964
16005
  if (!d)
15965
16006
  return { verdict: "TAMPERED", reason: "events.jsonl has no signed log.sealed line after run.completed" };
15966
16007
  const lines2 = readFileSync54(path, "utf8").split(`
15967
- `).filter((l) => l.trim() !== ""), sha4 = createHash19("sha256").update(lines2.slice(0, done + 1).join(`
16008
+ `).filter((l) => l.trim() !== ""), sha4 = createHash18("sha256").update(lines2.slice(0, done + 1).join(`
15968
16009
  `) + `
15969
16010
  `).digest("hex");
15970
16011
  const pub = d["kid"] === kid ? pubFor(kid, given) : undefined;
@@ -15973,7 +16014,7 @@ function checkLogSeal(receiptPath, hash, kid, given) {
15973
16014
  return null;
15974
16015
  }
15975
16016
  async function verifyReceipt(receiptPath, deps = {}) {
15976
- if (!existsSync45(receiptPath))
16017
+ if (!existsSync46(receiptPath))
15977
16018
  return { verdict: "UNCHECKED", reasons: [`receipt not found: ${receiptPath}`] };
15978
16019
  let receipt;
15979
16020
  try {
@@ -16066,8 +16107,8 @@ var init_verify_cmd = __esm(() => {
16066
16107
  });
16067
16108
 
16068
16109
  // src/server/app.ts
16069
- import { existsSync as existsSync47, readFileSync as readFileSync57, statSync as statSync23 } from "fs";
16070
- import { join as join71, resolve as resolve15, sep as sep14 } from "path";
16110
+ import { existsSync as existsSync48, readFileSync as readFileSync57, statSync as statSync22 } from "fs";
16111
+ import { join as join72, resolve as resolve14, sep as sep14 } from "path";
16071
16112
 
16072
16113
  // node_modules/hono/dist/request/constants.js
16073
16114
  var GET_MATCH_RESULT = Symbol();
@@ -26351,7 +26392,7 @@ function mount20(ctx) {
26351
26392
  // src/server/routes/verify.ts
26352
26393
  import { readFileSync as readFileSync55, realpathSync as realpathSync22 } from "fs";
26353
26394
  import { createPublicKey as createPublicKey5 } from "crypto";
26354
- import { join as join69, sep as sep13 } from "path";
26395
+ import { join as join70, sep as sep13 } from "path";
26355
26396
  init_verify_cmd();
26356
26397
  init_seal();
26357
26398
  init_receipt_dsse();
@@ -26378,11 +26419,11 @@ function mount21(ctx) {
26378
26419
  return done(404, "receipt not available", "not_found");
26379
26420
  let runDir, file;
26380
26421
  try {
26381
- const root = realpathSync22(join69(repo.p, ".loki", "runs"));
26382
- runDir = realpathSync22(join69(root, run2));
26383
- if (runDir !== join69(root, run2))
26422
+ const root = realpathSync22(join70(repo.p, ".loki", "runs"));
26423
+ runDir = realpathSync22(join70(root, run2));
26424
+ if (runDir !== join70(root, run2))
26384
26425
  return done(404, "receipt not found", "not_found");
26385
- file = realpathSync22(join69(runDir, "receipt.json"));
26426
+ file = realpathSync22(join70(runDir, "receipt.json"));
26386
26427
  } catch {
26387
26428
  return done(404, "receipt not found", "not_found");
26388
26429
  }
@@ -26463,8 +26504,8 @@ function ttlCache(ttlMs = PROBE_CACHE_MS, now2 = Date.now) {
26463
26504
  }
26464
26505
 
26465
26506
  // src/server/legacy/shim.ts
26466
- import { existsSync as existsSync46, readFileSync as readFileSync56 } from "fs";
26467
- import { join as join70 } from "path";
26507
+ import { existsSync as existsSync47, readFileSync as readFileSync56 } from "fs";
26508
+ import { join as join71 } from "path";
26468
26509
 
26469
26510
  // src/server/legacy/routes.ts
26470
26511
  var LEGACY_ROUTES = [
@@ -26842,9 +26883,9 @@ var logged = new Set;
26842
26883
  var toHono = (p) => p.replace(/\{([A-Za-z_]+):path\}/g, ":$1{.+}").replace(/\{([A-Za-z_]+)\}/g, ":$1");
26843
26884
  var NOT_SUPPORTED = "not yet supported by the Control Plane";
26844
26885
  var repoVersion = () => {
26845
- for (const f of [join70(import.meta.dir, "../../../../../VERSION")]) {
26886
+ for (const f of [join71(import.meta.dir, "../../../../../VERSION")]) {
26846
26887
  try {
26847
- if (existsSync46(f))
26888
+ if (existsSync47(f))
26848
26889
  return readFileSync56(f, "utf8").trim();
26849
26890
  } catch {}
26850
26891
  }
@@ -27027,7 +27068,7 @@ function legacyShim(opts) {
27027
27068
 
27028
27069
  // src/server/app.ts
27029
27070
  var MAX_BODY2 = 1e6;
27030
- var defaultUiDir = () => [join71(import.meta.dir, "../../ui/dist"), join71(import.meta.dir, "../ui/dist")].find((d) => existsSync47(join71(d, "index.html")));
27071
+ var defaultUiDir = () => [join72(import.meta.dir, "../../ui/dist"), join72(import.meta.dir, "../ui/dist")].find((d) => existsSync48(join72(d, "index.html")));
27031
27072
  function createApp(opts) {
27032
27073
  const uiDir = opts.uiDir ?? defaultUiDir();
27033
27074
  const { db, sqlite } = openDb(opts.dbPath);
@@ -27056,7 +27097,7 @@ function createApp(opts) {
27056
27097
  await next();
27057
27098
  });
27058
27099
  const readInstalled = () => {
27059
- for (const f of [process.env.LOKI_VERSION_FILE, join71(import.meta.dir, "../../../../VERSION")]) {
27100
+ for (const f of [process.env.LOKI_VERSION_FILE, join72(import.meta.dir, "../../../../VERSION")]) {
27060
27101
  try {
27061
27102
  if (f)
27062
27103
  return readFileSync57(f, "utf8").trim() || "unknown";
@@ -27168,13 +27209,13 @@ function createApp(opts) {
27168
27209
  }
27169
27210
  if (!uiDir || p.startsWith("/v1/"))
27170
27211
  return c.json({ error: "not found" }, 404);
27171
- const root = resolve15(uiDir);
27172
- const f = resolve15(root, `.${p}`);
27173
- if (f.startsWith(root + sep14) && existsSync47(f) && statSync23(f).isFile())
27212
+ const root = resolve14(uiDir);
27213
+ const f = resolve14(root, `.${p}`);
27214
+ if (f.startsWith(root + sep14) && existsSync48(f) && statSync22(f).isFile())
27174
27215
  return new Response(Bun.file(f));
27175
27216
  if (/\.[a-z0-9]+$/i.test(p))
27176
27217
  return c.json({ error: "not found" }, 404);
27177
- return new Response(Bun.file(join71(root, "index.html")));
27218
+ return new Response(Bun.file(join72(root, "index.html")));
27178
27219
  });
27179
27220
  return { app, db, close: () => {
27180
27221
  clearInterval(reconciler);