loki-mode 11.51.0 → 11.51.2

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 (67) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/dashboard/__init__.py +1 -1
  4. package/docs/CLI-REFERENCE.md +1 -1
  5. package/docs/INSTALLATION.md +1 -1
  6. package/loki-ts/dist/loki.js +1105 -1103
  7. package/mcp/__init__.py +1 -1
  8. package/package.json +2 -2
  9. package/packages/control-plane/dist/server.js +440 -439
  10. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  11. package/web-app/dist/assets/{AdminPage-CaIJn6cH.js → AdminPage-ByOJNu5y.js} +1 -1
  12. package/web-app/dist/assets/{Avatar-dVmwCh5N.js → Avatar-CoZ-ofeP.js} +1 -1
  13. package/web-app/dist/assets/{Badge-HvHbM4jj.js → Badge-BOZM8PNP.js} +1 -1
  14. package/web-app/dist/assets/{Button-5fe1mbnW.js → Button-CzMxcI0Q.js} +1 -1
  15. package/web-app/dist/assets/{CockpitPage-CD0RvCiF.js → CockpitPage-B278f5SK.js} +1 -1
  16. package/web-app/dist/assets/{ComparePage-CbaluJD-.js → ComparePage-Cp88FKzT.js} +1 -1
  17. package/web-app/dist/assets/{ErrorBoundary-BpK2aRWD.js → ErrorBoundary-CRw4LAKs.js} +1 -1
  18. package/web-app/dist/assets/{EvidenceReceiptPanel-CyEySJZi.js → EvidenceReceiptPanel-8wmYECtQ.js} +1 -1
  19. package/web-app/dist/assets/{GitHubIssuesPanel-Ci2AAQkj.js → GitHubIssuesPanel-Bj5oJskW.js} +1 -1
  20. package/web-app/dist/assets/{GitHubPRsPanel-BUYaYXHS.js → GitHubPRsPanel-Cbe7kg0X.js} +1 -1
  21. package/web-app/dist/assets/{HomePage-D5_HXS1Q.js → HomePage-CRcJUAy0.js} +2 -2
  22. package/web-app/dist/assets/{LoginPage-D3gyY-ls.js → LoginPage-DLQL2Kvm.js} +1 -1
  23. package/web-app/dist/assets/{MagicPage-Bsn48Ur5.js → MagicPage-M9J5khqf.js} +1 -1
  24. package/web-app/dist/assets/{MetricsPage-B6YUOQT2.js → MetricsPage-C2aSq2eq.js} +1 -1
  25. package/web-app/dist/assets/{NotFoundPage-ChVB9LFE.js → NotFoundPage-z7Ad3b5Z.js} +1 -1
  26. package/web-app/dist/assets/{ProjectPage-Xtbz9rr-.js → ProjectPage-CCij-iYF.js} +3 -3
  27. package/web-app/dist/assets/{ProjectsPage-Cd5cM4xT.js → ProjectsPage-DzYXxvEH.js} +1 -1
  28. package/web-app/dist/assets/{SettingsPage-DbullC_M.js → SettingsPage-kaIblmv8.js} +1 -1
  29. package/web-app/dist/assets/{ShowcasePage-C-ptVozh.js → ShowcasePage-C3UsOlE6.js} +1 -1
  30. package/web-app/dist/assets/{SystemSettingsPage-BqKjLA_f.js → SystemSettingsPage-L9alZW2b.js} +1 -1
  31. package/web-app/dist/assets/{TeamsPage-Cs-MLZLd.js → TeamsPage-CUN1TLAC.js} +1 -1
  32. package/web-app/dist/assets/{TemplatesPage-BhZCjlR8.js → TemplatesPage-B1NtMQlZ.js} +1 -1
  33. package/web-app/dist/assets/{TerminalOutput-Bd8EQQ0X.js → TerminalOutput-D0pKSlc-.js} +1 -1
  34. package/web-app/dist/assets/{activity-Ghjc1KL0.js → activity-C03x03AH.js} +1 -1
  35. package/web-app/dist/assets/{bell-B6yS64ng.js → bell-8hDBaFQB.js} +1 -1
  36. package/web-app/dist/assets/{bot-6O9QuDQ4.js → bot-DLQhJqda.js} +1 -1
  37. package/web-app/dist/assets/{check-BbWxeQg7.js → check-CLzpVJ44.js} +1 -1
  38. package/web-app/dist/assets/{chevron-left-D_1VwLoo.js → chevron-left-CQ7OLcYf.js} +1 -1
  39. package/web-app/dist/assets/{circle-alert-BnExIPLS.js → circle-alert-cEdG9TXw.js} +1 -1
  40. package/web-app/dist/assets/{clock-CZtHVj7a.js → clock-ChFx5TEw.js} +1 -1
  41. package/web-app/dist/assets/{cloud-DarO4XFf.js → cloud-MYMvEmfN.js} +1 -1
  42. package/web-app/dist/assets/{code-xml-B1bGHzXN.js → code-xml-bvE5DDtJ.js} +1 -1
  43. package/web-app/dist/assets/{database-lDd4a5mU.js → database-D9zj2H1_.js} +1 -1
  44. package/web-app/dist/assets/{dollar-sign-i28QkMfY.js → dollar-sign-BsbH0RG0.js} +1 -1
  45. package/web-app/dist/assets/{file-code-corner-3ohb1kRc.js → file-code-corner-DGarmzGt.js} +1 -1
  46. package/web-app/dist/assets/{file-plus-Cp5yulA3.js → file-plus-k4z_rNeN.js} +1 -1
  47. package/web-app/dist/assets/{globe-cNc9gWtx.js → globe-MJLSZC2e.js} +1 -1
  48. package/web-app/dist/assets/{hammer-BRFscyI0.js → hammer-Dd5_Zi5s.js} +1 -1
  49. package/web-app/dist/assets/{index-p3XpK3ZT.js → index-BMcYE1jz.js} +3 -3
  50. package/web-app/dist/assets/{layers-CGy_6jwr.js → layers-DvcCkeHJ.js} +1 -1
  51. package/web-app/dist/assets/{loader-circle-B0t6WEe8.js → loader-circle-D-ZWcTLu.js} +1 -1
  52. package/web-app/dist/assets/{lock-CtMLtv4v.js → lock-BISBkUVy.js} +1 -1
  53. package/web-app/dist/assets/{package-ATt-2SH-.js → package-7qbdDVIE.js} +1 -1
  54. package/web-app/dist/assets/{plus-cGAE5CuJ.js → plus-o52_30l5.js} +1 -1
  55. package/web-app/dist/assets/{refresh-cw-D0J0Bnaz.js → refresh-cw-BVvykHjR.js} +1 -1
  56. package/web-app/dist/assets/{rotate-ccw-BSZHcpHe.js → rotate-ccw-BtYo8dnt.js} +1 -1
  57. package/web-app/dist/assets/{scroll-text-BShob4O2.js → scroll-text-CL4yV4VG.js} +1 -1
  58. package/web-app/dist/assets/{server-saMTHour.js → server-UCe-Ic3k.js} +1 -1
  59. package/web-app/dist/assets/{shield-alert-BO6n8obe.js → shield-alert-Bq1Elbpw.js} +1 -1
  60. package/web-app/dist/assets/{thumbs-up-BY687kRl.js → thumbs-up-Y4uvYI48.js} +1 -1
  61. package/web-app/dist/assets/{trash-2-B3OnxR-U.js → trash-2-CzG_qlyk.js} +1 -1
  62. package/web-app/dist/assets/{trending-down-BiNXdXei.js → trending-down-Cmubfmha.js} +1 -1
  63. package/web-app/dist/assets/{trending-up-B9M18Jr4.js → trending-up-D5zMFb3Q.js} +1 -1
  64. package/web-app/dist/assets/{upload-COmaSiCG.js → upload-Cglleu88.js} +1 -1
  65. package/web-app/dist/assets/{usePolling-DaYeZTBV.js → usePolling-7I8GJNXT.js} +1 -1
  66. package/web-app/dist/assets/{user-Bz0wAwau.js → user-BjDOr5qQ.js} +1 -1
  67. package/web-app/dist/index.html +1 -1
@@ -8806,6 +8806,289 @@ var init_session_route = __esm(() => {
8806
8806
  init_unit_model();
8807
8807
  });
8808
8808
 
8809
+ // ../../loki-ts/src/runner/worker_proc.ts
8810
+ function killGroup2(pid, sig) {
8811
+ if (!pid)
8812
+ return;
8813
+ try {
8814
+ process.kill(-pid, sig);
8815
+ } catch {}
8816
+ }
8817
+ var CANCEL_GRACE_MS;
8818
+ var init_worker_proc = __esm(() => {
8819
+ CANCEL_GRACE_MS = Number(process.env["LOKI_E10_CANCEL_GRACE_MS"]) > 0 ? Number(process.env["LOKI_E10_CANCEL_GRACE_MS"]) : 1e4;
8820
+ });
8821
+
8822
+ // ../../loki-ts/src/util/shell.ts
8823
+ async function readStreamCapped(stream, maxBytes = MAX_STDOUT_BYTES, onFirstChunk) {
8824
+ const reader = stream.getReader();
8825
+ let first = onFirstChunk;
8826
+ const decoder = new TextDecoder;
8827
+ let out2 = "";
8828
+ let total = 0;
8829
+ try {
8830
+ while (total < maxBytes) {
8831
+ const { done, value } = await reader.read();
8832
+ if (done)
8833
+ break;
8834
+ if (!value)
8835
+ continue;
8836
+ if (first && value.byteLength > 0) {
8837
+ const cb = first;
8838
+ first = undefined;
8839
+ try {
8840
+ cb();
8841
+ } catch {}
8842
+ }
8843
+ total += value.byteLength;
8844
+ if (total > maxBytes) {
8845
+ const keep = value.byteLength - (total - maxBytes);
8846
+ out2 += decoder.decode(value.subarray(0, keep), { stream: true });
8847
+ break;
8848
+ }
8849
+ out2 += decoder.decode(value, { stream: true });
8850
+ }
8851
+ out2 += decoder.decode();
8852
+ } finally {
8853
+ try {
8854
+ await reader.cancel();
8855
+ } catch {}
8856
+ reader.releaseLock();
8857
+ }
8858
+ return out2;
8859
+ }
8860
+ async function run(argv, opts = {}) {
8861
+ const proc = Bun.spawn({
8862
+ cmd: [...argv],
8863
+ stdout: "pipe",
8864
+ stderr: "pipe",
8865
+ env: opts.env ? { ...process.env, ...opts.env } : process.env,
8866
+ cwd: opts.cwd,
8867
+ ...opts.group ? { detached: true } : {}
8868
+ });
8869
+ let timer;
8870
+ let killTimer;
8871
+ const stop = () => {
8872
+ try {
8873
+ if (opts.group)
8874
+ killGroup2(proc.pid, "SIGTERM");
8875
+ else
8876
+ proc.kill("SIGTERM");
8877
+ } catch {}
8878
+ killTimer ??= setTimeout(() => {
8879
+ try {
8880
+ if (opts.group)
8881
+ killGroup2(proc.pid, "SIGKILL");
8882
+ else
8883
+ proc.kill("SIGKILL");
8884
+ } catch {}
8885
+ }, 2000);
8886
+ };
8887
+ if (opts.timeoutMs && opts.timeoutMs > 0)
8888
+ timer = setTimeout(stop, opts.timeoutMs);
8889
+ if (opts.signal) {
8890
+ if (opts.signal.aborted)
8891
+ stop();
8892
+ else
8893
+ opts.signal.addEventListener("abort", stop, { once: true });
8894
+ }
8895
+ try {
8896
+ const [stdout, stderr, exitCode] = await Promise.all([
8897
+ readStreamCapped(proc.stdout, MAX_STDOUT_BYTES, opts.onFirstStdout),
8898
+ new Response(proc.stderr).text(),
8899
+ proc.exited
8900
+ ]);
8901
+ return { stdout, stderr, exitCode };
8902
+ } finally {
8903
+ if (timer)
8904
+ clearTimeout(timer);
8905
+ if (killTimer)
8906
+ clearTimeout(killTimer);
8907
+ opts.signal?.removeEventListener("abort", stop);
8908
+ if (opts.group)
8909
+ killGroup2(proc.pid, "SIGKILL");
8910
+ }
8911
+ }
8912
+ async function commandExists(name) {
8913
+ const safe = shEscape(name);
8914
+ const r = await run(["sh", "-c", `command -v ${safe}`], { timeoutMs: 5000 });
8915
+ if (r.exitCode === 0) {
8916
+ const path = r.stdout.trim();
8917
+ return path || null;
8918
+ }
8919
+ return null;
8920
+ }
8921
+ function shEscape(name) {
8922
+ if (!/^[A-Za-z0-9._/-]+$/.test(name)) {
8923
+ throw new Error(`refused to shell-escape suspect token: ${name}`);
8924
+ }
8925
+ return name;
8926
+ }
8927
+ var MAX_STDOUT_BYTES;
8928
+ var init_shell = __esm(() => {
8929
+ init_worker_proc();
8930
+ MAX_STDOUT_BYTES = 16 * 1024 * 1024;
8931
+ });
8932
+
8933
+ // ../../loki-ts/src/providers/mcp_config.ts
8934
+ var init_mcp_config = () => {};
8935
+
8936
+ // ../../loki-ts/src/providers/claude_flags.ts
8937
+ import { existsSync as existsSync20, readFileSync as readFileSync26 } from "fs";
8938
+ import { resolve as resolvePath, dirname as dirname13 } from "path";
8939
+ import { fileURLToPath as fileURLToPath5 } from "url";
8940
+ function claudeFlagSupported(flag, helpText) {
8941
+ const txt = helpText ?? _claudeHelpCache;
8942
+ if (txt === null || txt === undefined) {
8943
+ return false;
8944
+ }
8945
+ return txt.includes(flag);
8946
+ }
8947
+ async function ensureClaudeHelpCache() {
8948
+ if (_claudeHelpCache !== null)
8949
+ return;
8950
+ try {
8951
+ const proc = Bun.spawn(["claude", "--help"], {
8952
+ stdout: "pipe",
8953
+ stderr: "pipe",
8954
+ env: { ...process.env }
8955
+ });
8956
+ const text2 = await new Response(proc.stdout).text();
8957
+ await proc.exited;
8958
+ _claudeHelpCache = text2 || "";
8959
+ } catch {
8960
+ _claudeHelpCache = "";
8961
+ }
8962
+ }
8963
+ function leanReviewerFlags(opts = {}) {
8964
+ const env = opts.env ?? process.env;
8965
+ if (env["LOKI_LEAN_CHILDREN"] === "0")
8966
+ return [];
8967
+ const ok = opts.flagSupported ?? ((f) => claudeFlagSupported(f));
8968
+ const out2 = [];
8969
+ if (env["LOKI_BARE_SUBCALLS"] !== "0" && (env["ANTHROPIC_API_KEY"] ?? "").trim() !== "" && ok("--bare")) {
8970
+ out2.push("--bare");
8971
+ } else {
8972
+ if (ok("--setting-sources"))
8973
+ out2.push("--setting-sources", opts.settingSources ?? "project");
8974
+ if (ok("--strict-mcp-config"))
8975
+ out2.push("--strict-mcp-config", "--mcp-config", '{"mcpServers":{}}');
8976
+ if (ok("--disable-slash-commands"))
8977
+ out2.push("--disable-slash-commands");
8978
+ }
8979
+ if (ok("--tools"))
8980
+ out2.push(`--tools=${opts.tools ?? ""}`);
8981
+ return out2;
8982
+ }
8983
+ function designArchetypesText() {
8984
+ try {
8985
+ const moduleDir = dirname13(fileURLToPath5(import.meta.url));
8986
+ for (const rel of [
8987
+ ["..", "..", "..", "references", "design-archetypes.md"],
8988
+ ["..", "..", "references", "design-archetypes.md"]
8989
+ ]) {
8990
+ const p = resolvePath(moduleDir, ...rel);
8991
+ if (existsSync20(p))
8992
+ return readFileSync26(p, "utf8");
8993
+ }
8994
+ } catch {}
8995
+ return "";
8996
+ }
8997
+ var REVIEW_GUARD_DENYLIST = "Edit,Write,NotebookEdit,Bash(git commit:*),Bash(git reset:*),Bash(git push:*),Bash(git checkout:*),Bash(git clean:*),Bash(git rm:*),Bash(git stash:*),Bash(git -C:*),Bash(git --git-dir:*),Bash(git -c:*),Bash(git --exec-path:*),Bash(git diff --output:*),Bash(git diff --output=:*),Bash(git diff --ext-diff:*),Bash(git diff --no-index:*),Bash(git log --output:*),Bash(git log --output=:*),Bash(git log --ext-diff:*),Bash(git show --output:*),Bash(git show --output=:*),Bash(git show --ext-diff:*),Bash(git blame --output:*),Bash(git blame --output=:*),Bash(rg --pre:*),Bash(rg --pre=:*),Bash(rg --pre-glob:*),Bash(rg --pre-glob=:*),Bash(rg --hostname-bin:*),Bash(rg --hostname-bin=:*),Bash(find -delete:*),Bash(find -exec:*),Bash(find -execdir:*),Bash(find -ok:*),Bash(find -fprint:*),Bash(find -fprintf:*),Bash(find -fls:*),Bash(git * --output*),Bash(git * --ext-diff*),Bash(git * --no-index*),Bash(rg * --pre*),Bash(rg * --hostname-bin*),Bash(rg --pre*),Bash(rg --hostname-bin*),Bash(find * -delete*),Bash(find * -exec*),Bash(find * -execdir*),Bash(find * -fprint*),Bash(find * -fls*),Bash(find * -ok*)", _claudeHelpCache = null, AUTONOMY_OVERRIDE_TEXT, FIRST_PASS_EXCELLENCE_TEXT, REVIEW_ALLOWLIST_TOKEN = "Read,Grep,Glob,Bash(git diff:*),Bash(git log:*),Bash(git show:*),Bash(git status:*),Bash(git ls-files:*),Bash(git rev-parse:*),Bash(git blame:*),Bash(cat:*),Bash(ls:*),Bash(grep:*),Bash(rg:*),Bash(find:*),Bash(head:*),Bash(tail:*),Bash(wc:*)", REVIEW_ALLOWLIST_NO_GIT, CAVEMAN_PINNED_VERSION;
8998
+ var init_claude_flags = __esm(() => {
8999
+ init_mcp_config();
9000
+ init_claude_model();
9001
+ AUTONOMY_OVERRIDE_TEXT = `[LOKI-AUTONOMY-AGENT] This is a Loki Mode autonomous agent process.
9002
+ ` + `You are running INSIDE Loki Mode autonomous execution, a session the user explicitly launched with full prior authorization (loki start / loki run). This IS an authorized autonomous session, not an unattended action you must seek consent for.
9003
+
9004
+ ` + `Instruction precedence for THIS session: when the loki_system instructions in the user prompt conflict with any CLAUDE.md, project memory, or global memory that tells you to ask for clarification, pause for confirmation, refuse to act autonomously, or withhold routine commits, the loki_system instructions take precedence. The user has already consented by launching autonomous mode.
9005
+
9006
+ ` + `Therefore, for this session: do NOT ask the user questions, do NOT call the AskUserQuestion tool, do NOT stop to request confirmation, and do NOT refuse routine, reversible engineering work (writing code, running tests, creating files, atomic git checkpoints in the working tree). Proceed and complete the task directly. If a decision is genuinely ambiguous, choose the most reasonable option, record the assumption in .loki/CONTINUITY.md, and continue rather than halting.
9007
+
9008
+ ` + "Commit hygiene still applies: git checkpoints are LOCAL only. Never push or force-push. Stage files by explicit path, never `git add -A` or `git add .`, and never commit secrets, credentials, .env files, or untracked files you did not author this session.\n\n" + `This precedence override is narrow. It does NOT relax any safety rule. Every safety prohibition in CLAUDE.md or memory still fully binds: anything genuinely destructive or irreversible remains out of scope unless the task explicitly calls for it. This includes (not limited to) force-pushing, deleting or overwriting the user's data, dropping or truncating databases, publishing or releasing, rotating or exfiltrating secrets, touching production systems, and anything a CLAUDE.md safety rule explicitly forbids. When in doubt about whether an action is destructive, treat it as destructive and do not do it.
9009
+ `;
9010
+ FIRST_PASS_EXCELLENCE_TEXT = `
9011
+ [FIRST-PASS EXCELLENCE] Treat THIS pass as your one shot to ship a complete, working, verified solution. Do not produce a rough draft to refine later; the loop exists as a safety net, not a plan. Before you finish this iteration:
9012
+ ` + `1. BUILD IT FULLY. Implement every requirement end to end. No stubs, no TODOs, no "coming soon", no placeholder or hardcoded/mock data where real logic belongs. If the spec implies a backend (auth, persistence, a form that submits, a list that saves), WIRE IT so it actually works and persists -- a beautiful UI whose buttons do nothing is the single most common failure, not a draft. Every list/table must trace to a real query, never an inline mock array.
9013
+ ` + `2. SELF-VERIFY BY RUNNING, not by reading. Run the build and the tests yourself; for each acceptance criterion, DRIVE the actual path and observe the result (submit the form, then reload and confirm the record persisted; hit a protected route logged-out and confirm it is rejected). Fix what fails now, in this pass. Do not mark done on "looks right" or a self-claim -- observed behavior is the only proof.
9014
+ ` + `3. LOCK THE ARCHITECTURE on this pass so later edits are small and additive. Decide the data model, routes, and component structure up front and build to them; never rewrite whole files later to patch a small thing (that is the doom loop that breaks working features).
9015
+ ` + `4. DESIGN: commit to ONE named aesthetic direction up front (editorial, brutalist, luxury, retro-futuristic, soft/pastel, industrial, etc. -- chosen from the product domain) and hold it on every surface. Use real content (never lorem). AVOID the AI-slop tells that instantly read as machine-generated: NO indigo/blue-to-purple gradient (the #1 tell), NO Inter/Roboto/system-font headlines (pick a real display+body pairing), NO three-equal-rounded-cards-in-a-row skeleton, NO flat 1px gray card borders or colored left-border strips, NO untouched shadcn defaults, NO reflexive dark mode. Cap the palette at ~3 hues (60/30/10), tinted not pure #fff/#000, separate sections by whitespace then a slight background shift before any border. Aim for Linear/Stripe/Duolingo-tier taste: "this does not look AI-generated".
9016
+ ` + `5. SATISFY THE GATES THAT WILL JUDGE THIS PASS. Your work is checked by deterministic gates before it can be accepted, and in measured runs EVERY extra iteration was caused by one of these rejecting the work -- never by the model failing to finish. Clear them now, in this pass:
9017
+ ` + ` - STATIC ANALYSIS: no syntax errors, no unused/undefined symbols, no lint errors in files you touched.
9018
+ ` + ` - TEST SUITE: the existing tests must still pass. Run them; do not assume.
9019
+ ` + ` - MUTATION/MOCK INTEGRITY: tests must assert real behaviour. No tautological assertions (expect(true).toBe(true)), no test that passes whether or not the code works, no mocking the very unit under test, no inline mock data standing in for a real query.
9020
+ ` + ` - CODE REVIEW: no scope creep beyond the stated task, no dead or commented-out code, no leftover debug output, and follow the conventions already in the surrounding files.
9021
+ ` + `Deliver the finished, self-verified, genuinely-designed result in THIS pass. Additional iterations should be the exception, not the plan.
9022
+ ` + designArchetypesText();
9023
+ REVIEW_ALLOWLIST_NO_GIT = REVIEW_ALLOWLIST_TOKEN.split(",").filter((t) => !t.startsWith("Bash(git ")).join(",");
9024
+ CAVEMAN_PINNED_VERSION = process.env["LOKI_CAVEMAN_VERSION"] || "1.9.0";
9025
+ });
9026
+
9027
+ // ../../loki-ts/src/features/lean_prefix.ts
9028
+ var LEAN_PREFIX, PARALLEL_TOOL_CALLS_INSTRUCTION = `PARALLEL_TOOL_CALLS: When issuing independent read-only operations (reads, greps, file lookups, LSP checks) that do not depend on each other, issue them in a single message so they run in parallel; do not serialize independent lookups.`, STAGE_PREFIX, withStagePrefix = (brief) => process.env["LOKI_SPEED"] !== "0" ? `${STAGE_PREFIX}
9029
+
9030
+ ${brief}` : brief;
9031
+ var init_lean_prefix = __esm(() => {
9032
+ LEAN_PREFIX = "You are Loki, an autonomous coding agent. Follow the task prompt exactly " + "and report only what you did.";
9033
+ STAGE_PREFIX = "You are Loki, an autonomous coding agent working one stage of a run. " + "Follow the stage prompt exactly, including the role it gives you and the rules it sets, " + "and report only what you did. " + "Never present a behavior as done when this repository's code does not provide it: a plan, a test or a change never substitutes documentation or changelog text for missing code. " + `${PARALLEL_TOOL_CALLS_INSTRUCTION} ` + "Stage-specific instructions and the task follow this block.";
9034
+ });
9035
+
9036
+ // ../../loki-ts/src/util/run_identity.ts
9037
+ var init_run_identity = __esm(() => {
9038
+ init_model_routes();
9039
+ });
9040
+
9041
+ // ../../loki-ts/src/util/update_check.ts
9042
+ var CACHE_TTL_MS, NEGATIVE_TTL_MS;
9043
+ var init_update_check = __esm(() => {
9044
+ init_paths();
9045
+ CACHE_TTL_MS = 24 * 60 * 60 * 1000;
9046
+ NEGATIVE_TTL_MS = 15 * 60 * 1000;
9047
+ });
9048
+
9049
+ // ../../loki-ts/src/runner/router/advisor_probe.ts
9050
+ var ADVISOR_ERROR_LIMIT = 3;
9051
+ var init_advisor_probe = __esm(() => {
9052
+ init_claude_model();
9053
+ init_update_check();
9054
+ });
9055
+
9056
+ // ../../loki-ts/src/runner/sdk_stream_parser.ts
9057
+ var init_sdk_stream_parser = __esm(() => {
9058
+ init_cost();
9059
+ init_run_identity();
9060
+ init_budget();
9061
+ init_advisor_probe();
9062
+ });
9063
+
9064
+ // ../../loki-ts/src/runner/trim.ts
9065
+ var init_trim = () => {};
9066
+
9067
+ // ../../loki-ts/src/runner/provider_opencode.ts
9068
+ var init_provider_opencode = __esm(() => {
9069
+ init_shell();
9070
+ init_providers();
9071
+ });
9072
+
9073
+ // ../../loki-ts/src/runner/providers.ts
9074
+ var _installedVersionCache;
9075
+ var init_providers = __esm(() => {
9076
+ init_shell();
9077
+ init_paths();
9078
+ init_claude_flags();
9079
+ init_mcp_config();
9080
+ init_lean_prefix();
9081
+ init_sdk_stream_parser();
9082
+ init_session_resume();
9083
+ init_trim();
9084
+ init_advisor_probe();
9085
+ init_claude_model();
9086
+ init_model_routes();
9087
+ init_provider_opencode();
9088
+ init_cost_breakdown();
9089
+ _installedVersionCache = new Map;
9090
+ });
9091
+
8809
9092
  // ../../loki-ts/src/providers/provider_guard.ts
8810
9093
  function providerSandboxFlags(provider) {
8811
9094
  switch (provider) {
@@ -8863,6 +9146,7 @@ var init_session = __esm(() => {
8863
9146
  init_session_route();
8864
9147
  init_safe_git();
8865
9148
  init_cost_breakdown();
9149
+ init_providers();
8866
9150
  init_provider_guard();
8867
9151
  init_budget();
8868
9152
  init_budget_cap();
@@ -8880,7 +9164,7 @@ var init_model_rank = __esm(() => {
8880
9164
  });
8881
9165
 
8882
9166
  // ../../loki-ts/src/engine10/sizing.ts
8883
- import { existsSync as existsSync20, readFileSync as readFileSync26 } from "fs";
9167
+ import { existsSync as existsSync21, readFileSync as readFileSync27 } from "fs";
8884
9168
  import { basename as basename9 } from "path";
8885
9169
  function namedFiles(task, map) {
8886
9170
  return (map?.files ?? []).filter((f) => task.toLowerCase().includes(basename9(f).toLowerCase()));
@@ -8902,7 +9186,7 @@ function sizeTask(task, map, tests) {
8902
9186
  }
8903
9187
  function loadRepoMap(repomapRef) {
8904
9188
  try {
8905
- return repomapRef && existsSync20(repomapRef) ? JSON.parse(readFileSync26(repomapRef, "utf8")) : null;
9189
+ return repomapRef && existsSync21(repomapRef) ? JSON.parse(readFileSync27(repomapRef, "utf8")) : null;
8906
9190
  } catch {
8907
9191
  return null;
8908
9192
  }
@@ -8964,14 +9248,14 @@ var init_model_downgrades = __esm(() => {
8964
9248
  });
8965
9249
 
8966
9250
  // ../../loki-ts/src/project_model/discover.ts
8967
- import { existsSync as existsSync21, mkdirSync as mkdirSync11, readFileSync as readFileSync27, rmSync as rmSync7, writeFileSync as writeFileSync14 } from "fs";
9251
+ import { existsSync as existsSync22, mkdirSync as mkdirSync11, readFileSync as readFileSync28, rmSync as rmSync7, writeFileSync as writeFileSync14 } from "fs";
8968
9252
  import { join as join34 } from "path";
8969
9253
  function projectModelEnabled(env = process.env) {
8970
9254
  return env["LOKI_E10_PROJECT_MODEL"] !== "0";
8971
9255
  }
8972
9256
  function loadCached(repoDir, now2 = Date.now()) {
8973
9257
  try {
8974
- return parseCached(repoDir, JSON.parse(readFileSync27(join34(repoDir, PROJECT_FILE), "utf8")), now2);
9258
+ return parseCached(repoDir, JSON.parse(readFileSync28(join34(repoDir, PROJECT_FILE), "utf8")), now2);
8975
9259
  } catch {
8976
9260
  return null;
8977
9261
  }
@@ -8986,7 +9270,7 @@ function loadCommitted(repoDir) {
8986
9270
  };
8987
9271
  let raw2;
8988
9272
  try {
8989
- raw2 = JSON.parse(readFileSync27(join34(repoDir, PROJECT_FILE), "utf8"));
9273
+ raw2 = JSON.parse(readFileSync28(join34(repoDir, PROJECT_FILE), "utf8"));
8990
9274
  } catch (e) {
8991
9275
  return ignore(`unreadable JSON (${e instanceof Error ? e.message : String(e)})`);
8992
9276
  }
@@ -9127,8 +9411,8 @@ var init_test_file_text = __esm(() => {
9127
9411
  });
9128
9412
 
9129
9413
  // ../../loki-ts/src/engine10/testmap.ts
9130
- import { existsSync as existsSync22, readFileSync as readFileSync28, realpathSync as realpathSync15 } from "fs";
9131
- import { basename as basename11, dirname as dirname13, extname, isAbsolute as isAbsolute2, join as join36, relative, sep as sep10 } from "path";
9414
+ import { existsSync as existsSync23, readFileSync as readFileSync29, realpathSync as realpathSync15 } from "fs";
9415
+ import { basename as basename11, dirname as dirname14, extname, isAbsolute as isAbsolute2, join as join36, relative, sep as sep10 } from "path";
9132
9416
  function projectInterpreter(root) {
9133
9417
  const ve = process.env["VIRTUAL_ENV"], inRepo = (p) => {
9134
9418
  try {
@@ -9138,7 +9422,7 @@ function projectInterpreter(root) {
9138
9422
  return false;
9139
9423
  }
9140
9424
  };
9141
- return [join36(root, ".venv", "bin", "python"), join36(root, "venv", "bin", "python"), ...ve && inRepo(ve) ? [join36(ve, "bin", "python")] : []].some(existsSync22) ? "project" : "system";
9425
+ return [join36(root, ".venv", "bin", "python"), join36(root, "venv", "bin", "python"), ...ve && inRepo(ve) ? [join36(ve, "bin", "python")] : []].some(existsSync23) ? "project" : "system";
9142
9426
  }
9143
9427
  var harnessRunners = (runners, files = [], env = process.env) => runners.length === 0 && !files.some((f) => PY_TEST_RE.test(basename11(f)) || GO_TEST_RE.test(f)) && env.LOKI_WALL_HARNESS_RUNNER !== "0" && Bun.which("bun", { PATH: env.PATH ?? "" }) ? ["bun"] : runners;
9144
9428
  var init_testmap = __esm(() => {
@@ -9151,8 +9435,8 @@ var init_testmap = __esm(() => {
9151
9435
  // ../../loki-ts/src/util/check_result.ts
9152
9436
  import { spawn as spawn7 } from "child_process";
9153
9437
  import { createHash as createHash8 } from "crypto";
9154
- import { existsSync as existsSync23, mkdirSync as mkdirSync12, readFileSync as readFileSync29, realpathSync as realpathSync16, renameSync as renameSync7, rmSync as rmSync8, writeFileSync as writeFileSync15 } from "fs";
9155
- import { basename as basename12, dirname as dirname14, isAbsolute as isAbsolute3, join as join37, relative as relative2 } from "path";
9438
+ import { existsSync as existsSync24, mkdirSync as mkdirSync12, readFileSync as readFileSync30, realpathSync as realpathSync16, renameSync as renameSync7, rmSync as rmSync8, writeFileSync as writeFileSync15 } from "fs";
9439
+ import { basename as basename12, dirname as dirname15, isAbsolute as isAbsolute3, join as join37, relative as relative2 } from "path";
9156
9440
  function plainTestEnv(base = process.env) {
9157
9441
  const e = {};
9158
9442
  for (const [k, v] of Object.entries(tokenFreeEnv(base)))
@@ -9583,7 +9867,7 @@ function publishableWall(repoDir, runDir, o, env = process.env) {
9583
9867
  if (!hit || rel.startsWith("..") || isAbsolute3(rel) || rel.startsWith(".loki/") || !basename12(rel).startsWith("loki_wall_"))
9584
9868
  continue;
9585
9869
  try {
9586
- const bytes = readFileSync29(join37(runDir, "wall", basename12(rel)));
9870
+ const bytes = readFileSync30(join37(runDir, "wall", basename12(rel)));
9587
9871
  if (createHash8("sha256").update(bytes).digest("hex") !== w["sha256"])
9588
9872
  throw new Error("hash");
9589
9873
  out2.files.push({ rel, bytes, cmd: String(hit["cmd"]) });
@@ -9594,9 +9878,9 @@ function publishableWall(repoDir, runDir, o, env = process.env) {
9594
9878
  return out2;
9595
9879
  }
9596
9880
  function changedFiles(repoDir, baseSha, skip) {
9597
- const run = (args) => safeGit(repoDir, args).split("\x00").filter(Boolean);
9598
- const tracked = run(["-c", "core.quotePath=false", "diff", "--no-renames", "--name-only", "-z", baseSha]);
9599
- const untracked = run(["-c", "core.quotePath=false", "ls-files", "--others", "--exclude-standard", "-z"]);
9881
+ const run2 = (args) => safeGit(repoDir, args).split("\x00").filter(Boolean);
9882
+ const tracked = run2(["-c", "core.quotePath=false", "diff", "--no-renames", "--name-only", "-z", baseSha]);
9883
+ const untracked = run2(["-c", "core.quotePath=false", "ls-files", "--others", "--exclude-standard", "-z"]);
9600
9884
  return [...new Set([...tracked, ...untracked])].filter((f) => !f.startsWith(".loki/") && !skip?.(f));
9601
9885
  }
9602
9886
  function diffFiles(repoDir, baseSha, skip) {
@@ -9622,7 +9906,7 @@ function diffFiles(repoDir, baseSha, skip) {
9622
9906
  return f;
9623
9907
  let n2 = 0;
9624
9908
  try {
9625
- n2 = readFileSync29(join37(repoDir, path), "utf8").split(`
9909
+ n2 = readFileSync30(join37(repoDir, path), "utf8").split(`
9626
9910
  `).length;
9627
9911
  } catch {}
9628
9912
  return { path, added: n2, deleted: 0, status: "added" };
@@ -9645,7 +9929,7 @@ function diffFiles(repoDir, baseSha, skip) {
9645
9929
  let text2 = added.get(f.path) ?? "";
9646
9930
  if (!text2 && f.status === "added") {
9647
9931
  try {
9648
- text2 = readFileSync29(join37(repoDir, f.path), "utf8");
9932
+ text2 = readFileSync30(join37(repoDir, f.path), "utf8");
9649
9933
  } catch {}
9650
9934
  }
9651
9935
  const rule = criticalRuleFor(f.path, text2, rules);
@@ -9657,7 +9941,7 @@ function diffFiles(repoDir, baseSha, skip) {
9657
9941
  continue;
9658
9942
  try {
9659
9943
  const oldText = f.status === "added" ? "" : safeGit(repoDir, ["show", `${baseSha}:${f.path}`]);
9660
- const newText = readFileSync29(join37(repoDir, f.path), "utf8");
9944
+ const newText = readFileSync30(join37(repoDir, f.path), "utf8");
9661
9945
  const patch = f.status === "added" ? newText.split(`
9662
9946
  `).map((l) => `+${l}`).join(`
9663
9947
  `) : safeGit(repoDir, ["diff", "-U0", baseSha, "--", f.path]);
@@ -9762,7 +10046,7 @@ function pytestCollectionIsRed(output, repoDir) {
9762
10046
  }
9763
10047
  function moduleUnderRepo(repoDir, name) {
9764
10048
  const rel = name.replace(/\./g, "/");
9765
- return existsSync23(join37(repoDir, `${rel}.py`)) || existsSync23(join37(repoDir, rel, "__init__.py"));
10049
+ return existsSync24(join37(repoDir, `${rel}.py`)) || existsSync24(join37(repoDir, rel, "__init__.py"));
9766
10050
  }
9767
10051
  function pytestExit1IsRed(output) {
9768
10052
  if (/^!+ _pytest\.outcomes\.Exit\b/m.test(output))
@@ -9864,8 +10148,8 @@ function resolveTool(repoDir, bin, fallback, lastResort = fallback) {
9864
10148
  }
9865
10149
  };
9866
10150
  const venvEnv = process.env["VIRTUAL_ENV"], onPath = (b) => Bun.which(b, { PATH: process.env["PATH"] ?? "" });
9867
- const project = [join37(repoDir, ".venv", "bin", bin), join37(repoDir, "venv", "bin", bin), ...venvEnv && inRepo(venvEnv) ? [join37(venvEnv, "bin", bin)] : []].find(existsSync23);
9868
- return project ? [project, "project", []] : existsSync23(join37(repoDir, "uv.lock")) && onPath("uv") ? ["uv", "project", ["run", "--", bin]] : [onPath(fallback) ? fallback : lastResort, "system", []];
10151
+ const project = [join37(repoDir, ".venv", "bin", bin), join37(repoDir, "venv", "bin", bin), ...venvEnv && inRepo(venvEnv) ? [join37(venvEnv, "bin", bin)] : []].find(existsSync24);
10152
+ return project ? [project, "project", []] : existsSync24(join37(repoDir, "uv.lock")) && onPath("uv") ? ["uv", "project", ["run", "--", bin]] : [onPath(fallback) ? fallback : lastResort, "system", []];
9869
10153
  }
9870
10154
  function runnerCmd(t, repoDir) {
9871
10155
  switch (t.runner) {
@@ -9884,7 +10168,7 @@ function runnerCmd(t, repoDir) {
9884
10168
  case "npm":
9885
10169
  return ["npm", ["test", "--silent"]];
9886
10170
  case "go":
9887
- return ["go", ["test", "-json", `./${dirname14(t.path)}`]];
10171
+ return ["go", ["test", "-json", `./${dirname15(t.path)}`]];
9888
10172
  case "cargo":
9889
10173
  return ["cargo", ["test"]];
9890
10174
  }
@@ -9940,11 +10224,11 @@ async function publishWall(git, runId, repoDir, files, done) {
9940
10224
  for (const f of files) {
9941
10225
  const abs = join37(repoDir, f.rel);
9942
10226
  try {
9943
- if (!realpathSync16(dirname14(abs)).startsWith(realpathSync16(repoDir)))
10227
+ if (!realpathSync16(dirname15(abs)).startsWith(realpathSync16(repoDir)))
9944
10228
  return false;
9945
10229
  } catch {}
9946
10230
  rmSync8(abs, { force: true });
9947
- mkdirSync12(dirname14(abs), { recursive: true });
10231
+ mkdirSync12(dirname15(abs), { recursive: true });
9948
10232
  writeFileSync15(abs, f.bytes);
9949
10233
  }
9950
10234
  if ((await git(["--literal-pathspecs", "add", "--", ...rels])).code !== 0 || (await git(["--literal-pathspecs", "commit", "-q", "-m", "test: loki acceptance checks (Wall)", "-m", `Loki-Wall-Publish: ${runId}
@@ -9960,7 +10244,7 @@ var NO_TESTS_REASON = "no tests executed", GO_EXIT0_REASON = "test count could n
9960
10244
  `), tailLines = (out2) => out2.split(`
9961
10245
  `).filter((x) => x.trim()).slice(-12), GO_PKG_RE, EXIT_CODED_COUNT = "n/a (exit-coded check, not a test runner)", FRAMEWORK_RE, SCRIPT_RE, isExecutedProof = (c) => c.result === "pass" && typeof c.n === "number" && c.n > 0, hasExecutedProof = (checks) => checks.some(isExecutedProof), LLM_JUDGES, NON_RUNNER, normPath = (p) => p.replace(/^(?:\.\/)+/, ""), hasExogenousProof = (checks, ctx) => checks.some((c) => isExecutedProof(c) && ((p) => p !== "agent_authored" && p !== "llm_judge")(checkProvenance(c.name ?? "", ctx))), SENSITIVE, API, TEST_CFG, RANK2, FILES_MEDIUM = 4, FILES_HIGH = 15, LINES_MEDIUM = 100, LINES_HIGH = 500, RAN_ALWAYS, REVIEWER_ITEM = "one reviewer", PLAN, LOW_SKIPPED, deferredOf = (tier, selected, executed) => (tier === "low" ? LOW_SKIPPED : selected).filter((c) => !RAN_ALWAYS.includes(c) && !executed.includes(c)), DEEP_ITEMS, NOT_SELECTED = "not selected by risk tier: ", MANIFEST_LOCKS, dirOf = (p) => p.includes("/") ? p.slice(0, p.lastIndexOf("/")) : "", PKG_DEP_KEYS, PYPROJECT_NONDEP, SEM_RULES, DOC_FILE, readOr = (p) => {
9962
10246
  try {
9963
- return readFileSync29(p, "utf8");
10247
+ return readFileSync30(p, "utf8");
9964
10248
  } catch {
9965
10249
  return null;
9966
10250
  }
@@ -10037,10 +10321,10 @@ var init_check_result = __esm(() => {
10037
10321
 
10038
10322
  // ../../loki-ts/src/util/receipt_signer.ts
10039
10323
  import { createHash as createHash9, randomBytes as randomBytes3, createPrivateKey, createPublicKey as createPublicKey2, generateKeyPairSync, sign, verify as verify2 } from "crypto";
10040
- import { chmodSync as chmodSync4, linkSync, mkdirSync as mkdirSync13, readdirSync as readdirSync14, readFileSync as readFileSync30, renameSync as renameSync8, statSync as statSync15, unlinkSync as unlinkSync5, writeFileSync as writeFileSync16 } from "fs";
10324
+ import { chmodSync as chmodSync4, linkSync, mkdirSync as mkdirSync13, readdirSync as readdirSync14, readFileSync as readFileSync31, renameSync as renameSync8, statSync as statSync15, unlinkSync as unlinkSync5, writeFileSync as writeFileSync16 } from "fs";
10041
10325
  import { homedir as homedir8 } from "os";
10042
10326
  import { spawnSync as spawnSync2 } from "child_process";
10043
- import { dirname as dirname15, join as join38 } from "path";
10327
+ import { dirname as dirname16, join as join38 } from "path";
10044
10328
  function canonicalJson(x) {
10045
10329
  const walk = (v) => {
10046
10330
  if (Array.isArray(v))
@@ -10063,9 +10347,9 @@ function loadSigningKey(generate = true) {
10063
10347
  const given = process.env["LOKI_RECEIPT_SIGNING_KEY_FILE"]?.trim();
10064
10348
  const file = given || join38(process.env["HOME"] || homedir8(), ".loki", "keys", RECEIPT_SIGNER_BASENAME);
10065
10349
  try {
10066
- pem = readFileSync30(file);
10350
+ pem = readFileSync31(file);
10067
10351
  if (!given) {
10068
- for (const [f, m] of [[file, 384], [dirname15(file), 448]])
10352
+ for (const [f, m] of [[file, 384], [dirname16(file), 448]])
10069
10353
  if (statSync15(f).mode & 63)
10070
10354
  chmodSync4(f, m);
10071
10355
  }
@@ -10074,8 +10358,8 @@ function loadSigningKey(generate = true) {
10074
10358
  lastProblem = `signing key file unreadable (${e.code ?? "error"})`;
10075
10359
  if (e.code !== "ENOENT" || !generate)
10076
10360
  return null;
10077
- mkdirSync13(dirname15(dirname15(file)), { recursive: true, mode: 448 });
10078
- mkdirSync13(dirname15(file), { recursive: true, mode: 448 });
10361
+ mkdirSync13(dirname16(dirname16(file)), { recursive: true, mode: 448 });
10362
+ mkdirSync13(dirname16(file), { recursive: true, mode: 448 });
10079
10363
  const tmp = `${file}.${randomBytes3(6).toString("hex")}.tmp`;
10080
10364
  writeFileSync16(tmp, generateKeyPairSync("ed25519").privateKey.export({ type: "pkcs8", format: "pem" }), { flag: "wx", mode: 384 });
10081
10365
  try {
@@ -10086,7 +10370,7 @@ function loadSigningKey(generate = true) {
10086
10370
  } finally {
10087
10371
  unlinkSync5(tmp);
10088
10372
  }
10089
- pem = readFileSync30(file);
10373
+ pem = readFileSync31(file);
10090
10374
  }
10091
10375
  }
10092
10376
  stage = "parse";
@@ -10219,9 +10503,9 @@ var init_stop_restore = __esm(() => {
10219
10503
  });
10220
10504
 
10221
10505
  // ../../loki-ts/src/util/base_guard.ts
10222
- import { existsSync as existsSync24, readdirSync as readdirSync15, readFileSync as readFileSync31, readlinkSync, realpathSync as realpathSync17, symlinkSync } from "fs";
10506
+ import { existsSync as existsSync25, readdirSync as readdirSync15, readFileSync as readFileSync32, readlinkSync, realpathSync as realpathSync17, symlinkSync } from "fs";
10223
10507
  import { basename as basename13, join as join39, relative as relative3, resolve as resolve14, sep as sep11 } from "path";
10224
- import { fileURLToPath as fileURLToPath5 } from "url";
10508
+ import { fileURLToPath as fileURLToPath6 } from "url";
10225
10509
  function insideAny(p, roots) {
10226
10510
  const under = (q) => roots.some((r) => q === r || q.startsWith(r + sep11));
10227
10511
  if (under(resolve14(p)))
@@ -10237,7 +10521,7 @@ function namedPaths(file, text2) {
10237
10521
  if (basename13(file) !== "direct_url.json")
10238
10522
  return out2;
10239
10523
  const url = JSON.parse(text2).url;
10240
- return typeof url === "string" && url.startsWith("file:") ? [...out2, fileURLToPath5(url)] : out2;
10524
+ return typeof url === "string" && url.startsWith("file:") ? [...out2, fileURLToPath6(url)] : out2;
10241
10525
  }
10242
10526
  function depsSeeHead(pkgDir, repoDir) {
10243
10527
  let roots;
@@ -10264,7 +10548,7 @@ function depsSeeHead(pkgDir, repoDir) {
10264
10548
  if (walk(p, own))
10265
10549
  return true;
10266
10550
  } else if (REPO_LINK_FILE.test(e.name)) {
10267
- const text2 = readFileSync31(p, "utf8");
10551
+ const text2 = readFileSync32(p, "utf8");
10268
10552
  if (roots.some((r) => text2.includes(r)) || namedPaths(p, text2).some((n2) => insideAny(n2, roots)))
10269
10553
  return true;
10270
10554
  }
@@ -10286,7 +10570,7 @@ function depsSeeHead(pkgDir, repoDir) {
10286
10570
  return true;
10287
10571
  }
10288
10572
  }
10289
- async function zeroOnBase(cands, baseDir, repoDir, run, note) {
10573
+ async function zeroOnBase(cands, baseDir, repoDir, run2, note) {
10290
10574
  const zero = [];
10291
10575
  for (const c of cands) {
10292
10576
  const src = join39(repoDir, relative3(baseDir, c.cwd));
@@ -10294,11 +10578,11 @@ async function zeroOnBase(cands, baseDir, repoDir, run, note) {
10294
10578
  continue;
10295
10579
  for (const d of ["node_modules", ".venv"]) {
10296
10580
  try {
10297
- if (existsSync24(join39(src, d)) && !existsSync24(join39(c.cwd, d)))
10581
+ if (existsSync25(join39(src, d)) && !existsSync25(join39(c.cwd, d)))
10298
10582
  symlinkSync(join39(src, d), join39(c.cwd, d));
10299
10583
  } catch {}
10300
10584
  }
10301
- if (isZeroRun(c, await run(c))) {
10585
+ if (isZeroRun(c, await run2(c))) {
10302
10586
  zero.push(c.name);
10303
10587
  note(c.name);
10304
10588
  }
@@ -11175,11 +11459,11 @@ var init_state = __esm(() => {
11175
11459
 
11176
11460
  // ../../loki-ts/src/runner/repo_profile.ts
11177
11461
  import { spawnSync as spawnSync3 } from "child_process";
11178
- import { existsSync as existsSync25, lstatSync as lstatSync10, readFileSync as readFileSync32, mkdirSync as mkdirSync14, readdirSync as readdirSync16, renameSync as renameSync9, rmSync as rmSync9, writeFileSync as writeFileSync17 } from "fs";
11462
+ import { existsSync as existsSync26, lstatSync as lstatSync10, readFileSync as readFileSync33, mkdirSync as mkdirSync14, readdirSync as readdirSync16, renameSync as renameSync9, rmSync as rmSync9, writeFileSync as writeFileSync17 } from "fs";
11179
11463
  import { basename as basename14, join as join40, resolve as resolve15, isAbsolute as isAbsolute4 } from "path";
11180
11464
  function detectFormatters(repoDir) {
11181
11465
  const out2 = [];
11182
- const has = (...fs2) => fs2.some((f) => existsSync25(join40(repoDir, f)));
11466
+ const has = (...fs2) => fs2.some((f) => existsSync26(join40(repoDir, f)));
11183
11467
  const pp = read(join40(repoDir, "pyproject.toml")), pj = read(join40(repoDir, "package.json"));
11184
11468
  if (/\[tool\.ruff/.test(pp) || has("ruff.toml", ".ruff.toml"))
11185
11469
  out2.push({ tool: "ruff", argv: ["ruff", "format"], exts: /\.pyi?$/ });
@@ -11188,7 +11472,7 @@ function detectFormatters(repoDir) {
11188
11472
  prettierKey = pj !== "" && "prettier" in JSON.parse(pj);
11189
11473
  } catch {}
11190
11474
  const local = join40(repoDir, "node_modules", ".bin", "prettier");
11191
- if ((prettierKey || readdirSync16(repoDir).some((f) => /^(\.prettierrc(\.[a-z0-9]+)?|prettier\.config\.[cm]?[jt]s)$/.test(f))) && existsSync25(local))
11475
+ if ((prettierKey || readdirSync16(repoDir).some((f) => /^(\.prettierrc(\.[a-z0-9]+)?|prettier\.config\.[cm]?[jt]s)$/.test(f))) && existsSync26(local))
11192
11476
  out2.push({ tool: "prettier", argv: [local, "--write"], exts: /\.(?:[cm]?[jt]sx?|json|css|scss|md|ya?ml|html)$/ });
11193
11477
  if (has("go.mod"))
11194
11478
  out2.push({ tool: "gofmt", argv: ["gofmt", "-w"], exts: /\.go$/ });
@@ -11215,7 +11499,7 @@ function runFormatters(repoDir, files, env) {
11215
11499
  }
11216
11500
  function loadProfile(repoDir) {
11217
11501
  try {
11218
- const p = JSON.parse(readFileSync32(commandProfilePath(repoDir), "utf8"));
11502
+ const p = JSON.parse(readFileSync33(commandProfilePath(repoDir), "utf8"));
11219
11503
  return p?.version === 1 && Array.isArray(p.commands) && p.baseline ? p : null;
11220
11504
  } catch {
11221
11505
  return null;
@@ -11319,7 +11603,7 @@ async function staticPreExisting(tool, prefix, files, io) {
11319
11603
  }
11320
11604
  var commandProfilePath = (repoDir) => join40(repoDir, ".loki", "state", "repo-profile.json"), read = (p) => {
11321
11605
  try {
11322
- return readFileSync32(p, "utf8");
11606
+ return readFileSync33(p, "utf8");
11323
11607
  } catch {
11324
11608
  return "";
11325
11609
  }
@@ -11365,7 +11649,7 @@ var init_context = __esm(() => {
11365
11649
  });
11366
11650
 
11367
11651
  // ../../loki-ts/src/util/steer.ts
11368
- import { appendFileSync as appendFileSync2, closeSync as closeSync8, constants as constants2, fstatSync as fstatSync6, readdirSync as readdirSync17, lstatSync as lstatSync11, mkdirSync as mkdirSync15, linkSync as linkSync2, openSync as openSync8, readFileSync as readFileSync33, readSync as readSync7, renameSync as renameSync10, statSync as statSync16, lutimesSync, rmSync as rmSync10, unlinkSync as unlinkSync6, writeFileSync as writeFileSync18, existsSync as existsSync26 } from "fs";
11652
+ import { appendFileSync as appendFileSync2, closeSync as closeSync8, constants as constants2, fstatSync as fstatSync6, readdirSync as readdirSync17, lstatSync as lstatSync11, mkdirSync as mkdirSync15, linkSync as linkSync2, openSync as openSync8, readFileSync as readFileSync34, readSync as readSync7, renameSync as renameSync10, statSync as statSync16, lutimesSync, rmSync as rmSync10, unlinkSync as unlinkSync6, writeFileSync as writeFileSync18, existsSync as existsSync27 } from "fs";
11369
11653
  import { createHash as createHash10, randomBytes as randomBytes4 } from "crypto";
11370
11654
  import { basename as basename15, join as join41 } from "path";
11371
11655
  function archiveTo(logs, prefix, src, link = linkSync2, onLinked) {
@@ -11402,7 +11686,7 @@ function orphanAlreadyArchived(logs, claim) {
11402
11686
  const s = statSync16(join41(logs, a));
11403
11687
  if (s.ino !== c.ino || s.dev !== c.dev)
11404
11688
  continue;
11405
- if (/^human-input-(ORPHAN|REJECTED)-/.test(a) || existsSync26(appliedMarker(logs, a)))
11689
+ if (/^human-input-(ORPHAN|REJECTED)-/.test(a) || existsSync27(appliedMarker(logs, a)))
11406
11690
  return true;
11407
11691
  } catch {}
11408
11692
  }
@@ -11583,7 +11867,7 @@ function recordRevisions(repoDir, text2, archived, at) {
11583
11867
  const file = join41(repoDir, ".loki", "intent-revisions.jsonl");
11584
11868
  let last = 0;
11585
11869
  try {
11586
- for (const l of readFileSync33(file, "utf8").split(`
11870
+ for (const l of readFileSync34(file, "utf8").split(`
11587
11871
  `)) {
11588
11872
  try {
11589
11873
  last = Math.max(last, Number(JSON.parse(l).rev) || 0);
@@ -11649,7 +11933,7 @@ var init_steer = __esm(() => {
11649
11933
 
11650
11934
  // ../../loki-ts/src/util/run_outputs.ts
11651
11935
  import { createHash as createHash11 } from "crypto";
11652
- import { existsSync as existsSync27, mkdirSync as mkdirSync16, readdirSync as readdirSync18, readFileSync as readFileSync34, statSync as statSync17, writeFileSync as writeFileSync19 } from "fs";
11936
+ import { existsSync as existsSync28, mkdirSync as mkdirSync16, readdirSync as readdirSync18, readFileSync as readFileSync35, statSync as statSync17, writeFileSync as writeFileSync19 } from "fs";
11653
11937
  import { join as join42, resolve as resolve16 } from "path";
11654
11938
  function intentRevisionsBlock(revs) {
11655
11939
  const r = (revs ?? []).filter((r2) => r2.unapplied !== true).map(({ rev, source, actor, sha: sha2 }) => ({ rev, source, actor, sha: sha2 }));
@@ -11658,11 +11942,11 @@ function intentRevisionsBlock(revs) {
11658
11942
  function seededCorpusBlock(env = process.env) {
11659
11943
  const dir = env["LOKI_SEEDED_DEFECTS_DIR"] || join42(REPO_ROOT, "benchmarks", "seeded-defects");
11660
11944
  try {
11661
- const bytes = readFileSync34(join42(dir, "manifest.json")), version2 = createHash11("sha256").update(bytes).digest("hex");
11945
+ const bytes = readFileSync35(join42(dir, "manifest.json")), version2 = createHash11("sha256").update(bytes).digest("hex");
11662
11946
  const ids = (JSON.parse(bytes.toString("utf8")).defects ?? []).map((d) => d.id);
11663
11947
  let rate = null;
11664
11948
  try {
11665
- const res = JSON.parse(readFileSync34(join42(dir, "results", "wrong-pass.json"), "utf8"));
11949
+ const res = JSON.parse(readFileSync35(join42(dir, "results", "wrong-pass.json"), "utf8"));
11666
11950
  const runs2 = res.manifest_sha256 === version2 && Array.isArray(res.runs) ? res.runs : [];
11667
11951
  const complete = (o) => !!o && Object.keys(o).length === ids.length && ids.every((id) => typeof id === "string" && (o[id] === "SEALED" || o[id] === "NOT_SEALED"));
11668
11952
  const top = runs2.filter((r) => r.setup === "top"), floor = runs2.filter((r) => r.setup === "floor");
@@ -11946,7 +12230,7 @@ var init_registry2 = __esm(() => {
11946
12230
 
11947
12231
  // ../../loki-ts/src/features/receipt_dsse.ts
11948
12232
  import { createPublicKey as createPublicKey3, sign as sign2, verify as verify3 } from "crypto";
11949
- import { readFileSync as readFileSync35 } from "fs";
12233
+ import { readFileSync as readFileSync36 } from "fs";
11950
12234
  function pae(payloadType, body) {
11951
12235
  const t = Buffer.from(payloadType, "utf8");
11952
12236
  return Buffer.concat([Buffer.from(`DSSEv1 ${t.length} `), t, Buffer.from(` ${body.length} `), body]);
@@ -12023,7 +12307,7 @@ function verifyDsseReceipt(env, d) {
12023
12307
  }
12024
12308
  function runIdGuard(receiptPath, runId2) {
12025
12309
  try {
12026
- return envelopeRunIdProblem(JSON.parse(readFileSync35(receiptPath, "utf8")), runId2);
12310
+ return envelopeRunIdProblem(JSON.parse(readFileSync36(receiptPath, "utf8")), runId2);
12027
12311
  } catch {
12028
12312
  return null;
12029
12313
  }
@@ -12152,9 +12436,9 @@ var init_run_cap = __esm(() => {
12152
12436
  });
12153
12437
 
12154
12438
  // ../../loki-ts/src/util/mutation_proof.ts
12155
- import { existsSync as existsSync28, mkdirSync as mkdirSync17, mkdtempSync as mkdtempSync3, readFileSync as readFileSync36, rmSync as rmSync11, symlinkSync as symlinkSync2, writeFileSync as writeFileSync20 } from "fs";
12439
+ import { existsSync as existsSync29, mkdirSync as mkdirSync17, mkdtempSync as mkdtempSync3, readFileSync as readFileSync37, rmSync as rmSync11, symlinkSync as symlinkSync2, writeFileSync as writeFileSync20 } from "fs";
12156
12440
  import { tmpdir as tmpdir4 } from "os";
12157
- import { basename as basename16, dirname as dirname16, isAbsolute as isAbsolute6, join as join44, relative as relative5 } from "path";
12441
+ import { basename as basename16, dirname as dirname17, isAbsolute as isAbsolute6, join as join44, relative as relative5 } from "path";
12158
12442
  function mutationProof(i) {
12159
12443
  const rels = i.wallFiles.map((f) => isAbsolute6(f.path) ? relative5(i.repoDir, f.path) : f.path);
12160
12444
  if (rels.length === 0)
@@ -12175,15 +12459,15 @@ function mutationProof(i) {
12175
12459
  parent = mkdtempSync3(join44(tmpdir4(), "loki-mutproof-"));
12176
12460
  wt = join44(parent, "wt");
12177
12461
  const add3 = git(i.repoDir, ["worktree", "add", "--detach", wt, i.baseSha], Math.max(1000, Math.min(30000, remaining())));
12178
- added = existsSync28(wt) || add3.status === 0;
12462
+ added = existsSync29(wt) || add3.status === 0;
12179
12463
  if (add3.status !== 0)
12180
12464
  return np("could not create the base worktree");
12181
12465
  for (const rel of rels) {
12182
- const sealed = join44(i.runDir, "wall", basename16(rel)), src = existsSync28(sealed) ? sealed : join44(i.repoDir, rel);
12183
- if (!existsSync28(src))
12466
+ const sealed = join44(i.runDir, "wall", basename16(rel)), src = existsSync29(sealed) ? sealed : join44(i.repoDir, rel);
12467
+ if (!existsSync29(src))
12184
12468
  return np(`Wall file missing: ${rel}`);
12185
- mkdirSync17(dirname16(join44(wt, rel)), { recursive: true });
12186
- writeFileSync20(join44(wt, rel), readFileSync36(src));
12469
+ mkdirSync17(dirname17(join44(wt, rel)), { recursive: true });
12470
+ writeFileSync20(join44(wt, rel), readFileSync37(src));
12187
12471
  }
12188
12472
  for (const rel of rels) {
12189
12473
  const parts = rel.split("/").slice(0, -1);
@@ -12191,7 +12475,7 @@ function mutationProof(i) {
12191
12475
  const anc = parts.slice(0, n2).join("/");
12192
12476
  for (const d of DEP_DIRS) {
12193
12477
  const src = join44(i.repoDir, anc, d), dst = join44(wt, anc, d);
12194
- if (existsSync28(src) && !existsSync28(dst)) {
12478
+ if (existsSync29(src) && !existsSync29(dst)) {
12195
12479
  try {
12196
12480
  symlinkSync2(src, dst);
12197
12481
  } catch {}
@@ -12199,190 +12483,57 @@ function mutationProof(i) {
12199
12483
  }
12200
12484
  }
12201
12485
  }
12202
- let pass = 0, fail = 0, notRun = 0;
12203
- for (const t of tests) {
12204
- if (remaining() <= 0)
12205
- return np("timeout");
12206
- const r = (typeof i.runner === "function" ? i.runner(remaining()) : i.runner).run(wt, [t]);
12207
- pass += r.pass;
12208
- fail += r.fail;
12209
- notRun += r.not_run ?? 0;
12210
- }
12211
- if (remaining() <= 0 && fail === 0)
12212
- return np("timeout");
12213
- if (fail > 0)
12214
- return { outcome: "yes", line: `${LABEL}yes` };
12215
- if (pass > 0 && notRun === 0)
12216
- return { outcome: "no", line: `${LABEL}no (warning: the Wall tests also pass on the old code)` };
12217
- return np("the Wall command did not execute to a result");
12218
- } catch (e) {
12219
- return np(`error: ${String(e?.message ?? e).replace(/\s+/g, " ").slice(0, 120)}`);
12220
- } finally {
12221
- if (wt && added)
12222
- git(i.repoDir, ["worktree", "remove", "--force", wt]);
12223
- if (parent)
12224
- rmSync11(parent, { recursive: true, force: true });
12225
- }
12226
- }
12227
- var mutationStrict = (env = process.env) => (env["LOKI_MUTATION_STRICT"] ?? "").trim() === "1", mutationEnabled = (env = process.env) => (env["LOKI_MUTATION_PROOF"] ?? "").trim() !== "0", LABEL = "test fails without the fix: ", np = (reason) => ({ outcome: "inconclusive", line: `${LABEL}inconclusive (${reason})` }), MAX_TOTAL_S = 40, envTimeoutS = (raw2) => {
12228
- const n2 = Number(raw2 ?? 30);
12229
- return Number.isFinite(n2) && n2 > 0 ? n2 : 30;
12230
- }, DEP_DIRS, git = (cwd, args, timeout = 30000) => {
12231
- try {
12232
- safeGit(cwd, args, { timeout });
12233
- return { status: 0 };
12234
- } catch {
12235
- return { status: 1 };
12236
- }
12237
- };
12238
- var init_mutation_proof = __esm(() => {
12239
- init_safe_git();
12240
- init_run_cap();
12241
- DEP_DIRS = ["node_modules", ".venv", "venv"];
12242
- });
12243
-
12244
- // ../../loki-ts/src/features/lean_prefix.ts
12245
- var LEAN_PREFIX, PARALLEL_TOOL_CALLS_INSTRUCTION = `PARALLEL_TOOL_CALLS: When issuing independent read-only operations (reads, greps, file lookups, LSP checks) that do not depend on each other, issue them in a single message so they run in parallel; do not serialize independent lookups.`, STAGE_PREFIX, withStagePrefix = (brief) => process.env["LOKI_SPEED"] !== "0" ? `${STAGE_PREFIX}
12246
-
12247
- ${brief}` : brief;
12248
- var init_lean_prefix = __esm(() => {
12249
- LEAN_PREFIX = "You are Loki, an autonomous coding agent. Follow the task prompt exactly " + "and report only what you did.";
12250
- STAGE_PREFIX = "You are Loki, an autonomous coding agent working one stage of a run. " + "Follow the stage prompt exactly, including the role it gives you and the rules it sets, " + "and report only what you did. " + "Never present a behavior as done when this repository's code does not provide it: a plan, a test or a change never substitutes documentation or changelog text for missing code. " + `${PARALLEL_TOOL_CALLS_INSTRUCTION} ` + "Stage-specific instructions and the task follow this block.";
12251
- });
12252
-
12253
- // ../../loki-ts/src/runner/worker_proc.ts
12254
- function killGroup2(pid, sig) {
12255
- if (!pid)
12256
- return;
12257
- try {
12258
- process.kill(-pid, sig);
12259
- } catch {}
12260
- }
12261
- var CANCEL_GRACE_MS;
12262
- var init_worker_proc = __esm(() => {
12263
- CANCEL_GRACE_MS = Number(process.env["LOKI_E10_CANCEL_GRACE_MS"]) > 0 ? Number(process.env["LOKI_E10_CANCEL_GRACE_MS"]) : 1e4;
12264
- });
12265
-
12266
- // ../../loki-ts/src/util/shell.ts
12267
- async function readStreamCapped(stream, maxBytes = MAX_STDOUT_BYTES, onFirstChunk) {
12268
- const reader = stream.getReader();
12269
- let first = onFirstChunk;
12270
- const decoder = new TextDecoder;
12271
- let out2 = "";
12272
- let total = 0;
12273
- try {
12274
- while (total < maxBytes) {
12275
- const { done, value } = await reader.read();
12276
- if (done)
12277
- break;
12278
- if (!value)
12279
- continue;
12280
- if (first && value.byteLength > 0) {
12281
- const cb = first;
12282
- first = undefined;
12283
- try {
12284
- cb();
12285
- } catch {}
12286
- }
12287
- total += value.byteLength;
12288
- if (total > maxBytes) {
12289
- const keep = value.byteLength - (total - maxBytes);
12290
- out2 += decoder.decode(value.subarray(0, keep), { stream: true });
12291
- break;
12292
- }
12293
- out2 += decoder.decode(value, { stream: true });
12294
- }
12295
- out2 += decoder.decode();
12486
+ let pass = 0, fail = 0, notRun = 0;
12487
+ for (const t of tests) {
12488
+ if (remaining() <= 0)
12489
+ return np("timeout");
12490
+ const r = (typeof i.runner === "function" ? i.runner(remaining()) : i.runner).run(wt, [t]);
12491
+ pass += r.pass;
12492
+ fail += r.fail;
12493
+ notRun += r.not_run ?? 0;
12494
+ }
12495
+ if (remaining() <= 0 && fail === 0)
12496
+ return np("timeout");
12497
+ if (fail > 0)
12498
+ return { outcome: "yes", line: `${LABEL}yes` };
12499
+ if (pass > 0 && notRun === 0)
12500
+ return { outcome: "no", line: `${LABEL}no (warning: the Wall tests also pass on the old code)` };
12501
+ return np("the Wall command did not execute to a result");
12502
+ } catch (e) {
12503
+ return np(`error: ${String(e?.message ?? e).replace(/\s+/g, " ").slice(0, 120)}`);
12296
12504
  } finally {
12297
- try {
12298
- await reader.cancel();
12299
- } catch {}
12300
- reader.releaseLock();
12505
+ if (wt && added)
12506
+ git(i.repoDir, ["worktree", "remove", "--force", wt]);
12507
+ if (parent)
12508
+ rmSync11(parent, { recursive: true, force: true });
12301
12509
  }
12302
- return out2;
12303
12510
  }
12304
- async function run(argv, opts = {}) {
12305
- const proc = Bun.spawn({
12306
- cmd: [...argv],
12307
- stdout: "pipe",
12308
- stderr: "pipe",
12309
- env: opts.env ? { ...process.env, ...opts.env } : process.env,
12310
- cwd: opts.cwd,
12311
- ...opts.group ? { detached: true } : {}
12312
- });
12313
- let timer;
12314
- let killTimer;
12315
- const stop = () => {
12316
- try {
12317
- if (opts.group)
12318
- killGroup2(proc.pid, "SIGTERM");
12319
- else
12320
- proc.kill("SIGTERM");
12321
- } catch {}
12322
- killTimer ??= setTimeout(() => {
12323
- try {
12324
- if (opts.group)
12325
- killGroup2(proc.pid, "SIGKILL");
12326
- else
12327
- proc.kill("SIGKILL");
12328
- } catch {}
12329
- }, 2000);
12330
- };
12331
- if (opts.timeoutMs && opts.timeoutMs > 0)
12332
- timer = setTimeout(stop, opts.timeoutMs);
12333
- if (opts.signal) {
12334
- if (opts.signal.aborted)
12335
- stop();
12336
- else
12337
- opts.signal.addEventListener("abort", stop, { once: true });
12338
- }
12511
+ var mutationStrict = (env = process.env) => (env["LOKI_MUTATION_STRICT"] ?? "").trim() === "1", mutationEnabled = (env = process.env) => (env["LOKI_MUTATION_PROOF"] ?? "").trim() !== "0", LABEL = "test fails without the fix: ", np = (reason) => ({ outcome: "inconclusive", line: `${LABEL}inconclusive (${reason})` }), MAX_TOTAL_S = 40, envTimeoutS = (raw2) => {
12512
+ const n2 = Number(raw2 ?? 30);
12513
+ return Number.isFinite(n2) && n2 > 0 ? n2 : 30;
12514
+ }, DEP_DIRS, git = (cwd, args, timeout = 30000) => {
12339
12515
  try {
12340
- const [stdout, stderr, exitCode] = await Promise.all([
12341
- readStreamCapped(proc.stdout, MAX_STDOUT_BYTES, opts.onFirstStdout),
12342
- new Response(proc.stderr).text(),
12343
- proc.exited
12344
- ]);
12345
- return { stdout, stderr, exitCode };
12346
- } finally {
12347
- if (timer)
12348
- clearTimeout(timer);
12349
- if (killTimer)
12350
- clearTimeout(killTimer);
12351
- opts.signal?.removeEventListener("abort", stop);
12352
- if (opts.group)
12353
- killGroup2(proc.pid, "SIGKILL");
12354
- }
12355
- }
12356
- async function commandExists(name) {
12357
- const safe = shEscape(name);
12358
- const r = await run(["sh", "-c", `command -v ${safe}`], { timeoutMs: 5000 });
12359
- if (r.exitCode === 0) {
12360
- const path = r.stdout.trim();
12361
- return path || null;
12362
- }
12363
- return null;
12364
- }
12365
- function shEscape(name) {
12366
- if (!/^[A-Za-z0-9._/-]+$/.test(name)) {
12367
- throw new Error(`refused to shell-escape suspect token: ${name}`);
12516
+ safeGit(cwd, args, { timeout });
12517
+ return { status: 0 };
12518
+ } catch {
12519
+ return { status: 1 };
12368
12520
  }
12369
- return name;
12370
- }
12371
- var MAX_STDOUT_BYTES;
12372
- var init_shell = __esm(() => {
12373
- init_worker_proc();
12374
- MAX_STDOUT_BYTES = 16 * 1024 * 1024;
12521
+ };
12522
+ var init_mutation_proof = __esm(() => {
12523
+ init_safe_git();
12524
+ init_run_cap();
12525
+ DEP_DIRS = ["node_modules", ".venv", "venv"];
12375
12526
  });
12376
12527
 
12377
12528
  // ../../loki-ts/src/util/python.ts
12378
- import { accessSync, constants as constants3, existsSync as existsSync29, mkdtempSync as mkdtempSync4, readFileSync as readFileSync37, realpathSync as realpathSync19, rmSync as rmSync12, statSync as statSync18 } from "fs";
12529
+ import { accessSync, constants as constants3, existsSync as existsSync30, mkdtempSync as mkdtempSync4, readFileSync as readFileSync38, realpathSync as realpathSync19, rmSync as rmSync12, statSync as statSync18 } from "fs";
12379
12530
  import { spawnSync as spawnSync4 } from "child_process";
12380
12531
  import { tmpdir as tmpdir5 } from "os";
12381
12532
  async function findPython3() {
12382
12533
  if (_pythonCache !== undefined)
12383
12534
  return _pythonCache;
12384
12535
  const homebrew = "/opt/homebrew/bin/python3.12";
12385
- if (existsSync29(homebrew)) {
12536
+ if (existsSync30(homebrew)) {
12386
12537
  _pythonCache = homebrew;
12387
12538
  return homebrew;
12388
12539
  }
@@ -12733,7 +12884,7 @@ var init_wall_manifest = __esm(() => {
12733
12884
 
12734
12885
  // ../../loki-ts/src/features/wall_manifest_wire.ts
12735
12886
  import { createHash as createHash13 } from "crypto";
12736
- import { basename as basename17, dirname as dirname17 } from "path";
12887
+ import { basename as basename17, dirname as dirname18 } from "path";
12737
12888
  function blobEntries(ls) {
12738
12889
  const out2 = [];
12739
12890
  for (const raw2 of ls.toString("latin1").split("\x00")) {
@@ -12763,7 +12914,7 @@ function wallManifestFor(repoDir, tree, task, env = process.env) {
12763
12914
  return null;
12764
12915
  const low = task.toLowerCase().replace(/\\/g, "/");
12765
12916
  const token = (n2) => new RegExp(`(?<![A-Za-z0-9_])${n2.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![A-Za-z0-9_])`).test(low);
12766
- const dirModule = (e) => /^(index|__init__|mod|main)\.[^.]+$/.test(basename17(e.path)) && e.path.includes("/") && token(dirname17(e.path));
12917
+ const dirModule = (e) => /^(index|__init__|mod|main)\.[^.]+$/.test(basename17(e.path)) && e.path.includes("/") && token(dirname18(e.path));
12767
12918
  const matched = all.filter((e) => SOURCE.test(e.path) && (token(basename17(e.path)) || token(e.path) || token(basename17(e.path).replace(/\.[^.]*$/, "")) || dirModule(e)));
12768
12919
  const spans = (p) => [...low.matchAll(new RegExp(`(?<![A-Za-z0-9_])${p.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![A-Za-z0-9_])`, "g"))].map((m) => [m.index, m.index + m[0].length]);
12769
12920
  const occ = new Map(matched.map((e) => [e, spans(e.path)]));
@@ -12825,7 +12976,7 @@ Example: test('name', () => { assert.strictEqual(fn(1), 2); }); Run: node --tes
12825
12976
 
12826
12977
  // ../../loki-ts/src/util/holdout.ts
12827
12978
  import { createHash as createHash14 } from "crypto";
12828
- import { appendFileSync as appendFileSync3, copyFileSync as copyFileSync2, existsSync as existsSync30, mkdirSync as mkdirSync18, readFileSync as readFileSync38, rmSync as rmSync13, writeFileSync as writeFileSync21 } from "fs";
12979
+ import { appendFileSync as appendFileSync3, copyFileSync as copyFileSync2, existsSync as existsSync31, mkdirSync as mkdirSync18, readFileSync as readFileSync39, rmSync as rmSync13, writeFileSync as writeFileSync21 } from "fs";
12829
12980
  import { tmpdir as tmpdir6 } from "os";
12830
12981
  import { basename as basename18, join as join45, relative as relative6 } from "path";
12831
12982
  function wallHoldoutRatio(env = process.env) {
@@ -12860,7 +13011,7 @@ function stashHoldout(o) {
12860
13011
  const files = held.map((name) => {
12861
13012
  copyFileSync2(join45(o.srcDir, name), join45(dir, name));
12862
13013
  rmSync13(join45(o.srcDir, name), { force: true });
12863
- return { name, runner: o.runnerOf(name), sha256: sha2(readFileSync38(join45(dir, name), "utf8")) };
13014
+ return { name, runner: o.runnerOf(name), sha256: sha2(readFileSync39(join45(dir, name), "utf8")) };
12864
13015
  });
12865
13016
  writeFileSync21(join45(dir, MANIFEST), JSON.stringify({ targetDir: o.targetDir, files }));
12866
13017
  return { dir, names: new Set(held) };
@@ -12869,14 +13020,14 @@ function stageHoldout(dir, repoDir) {
12869
13020
  const put = [], tests = [], missing = [];
12870
13021
  let man = null;
12871
13022
  try {
12872
- man = JSON.parse(readFileSync38(join45(dir, MANIFEST), "utf8"));
13023
+ man = JSON.parse(readFileSync39(join45(dir, MANIFEST), "utf8"));
12873
13024
  } catch {}
12874
13025
  if (!man)
12875
13026
  return { tests, missing: [`holdout store unreadable: ${basename18(dir)}`], cleanup: () => {} };
12876
13027
  mkdirSync18(man.targetDir, { recursive: true });
12877
13028
  man.files.forEach((f, i) => {
12878
13029
  const src = join45(dir, f.name);
12879
- if (!existsSync30(src) || sha2(readFileSync38(src, "utf8")) !== f.sha256) {
13030
+ if (!existsSync31(src) || sha2(readFileSync39(src, "utf8")) !== f.sha256) {
12880
13031
  missing.push(`holdout ${i + 1} missing or altered`);
12881
13032
  return;
12882
13033
  }
@@ -13204,8 +13355,8 @@ var init_install = __esm(() => {
13204
13355
  });
13205
13356
 
13206
13357
  // ../../loki-ts/src/features/runner_config.ts
13207
- import { readFileSync as readFileSync39 } from "fs";
13208
- import { dirname as dirname18, join as join48, normalize as normalize2 } from "path";
13358
+ import { readFileSync as readFileSync40 } from "fs";
13359
+ import { dirname as dirname19, join as join48, normalize as normalize2 } from "path";
13209
13360
  function tomlKey2(s, i = 0, eq2 = true) {
13210
13361
  const parts = [], ws = () => {
13211
13362
  while (/\s/.test(s[i] ?? "x"))
@@ -13480,7 +13631,7 @@ function referenced(cfg, text2) {
13480
13631
  if (v && !/[$*]/.test(v))
13481
13632
  raw2.push(v);
13482
13633
  }
13483
- const dir = dirname18(cfg), explicit = ROOT_DIR.exec(text2), roots = [dir];
13634
+ const dir = dirname19(cfg), explicit = ROOT_DIR.exec(text2), roots = [dir];
13484
13635
  if (explicit)
13485
13636
  roots.push("", ...explicit[1] ? [join48(dir, explicit[1])] : []);
13486
13637
  return [...raw2.flatMap((r) => r.startsWith("/") ? [normalize2(r.slice(1))] : roots.map((root) => normalize2(join48(root, r.replace(/^<rootDir>\/?/, ""))))), ...patchedTargets(cfg, text2).map((t) => normalize2(join48(dir, t)))];
@@ -13531,7 +13682,7 @@ function runnerConfigNotes(repoDir, baseSha, head, changed, signal) {
13531
13682
  bad = true;
13532
13683
  }
13533
13684
  if (bad) {
13534
- const dir = dirname18(cfg), loaded = [...ch].find((c) => c !== cfg && (dir === "." || c.startsWith(dir + "/")) && !NON_SOURCE.test(c));
13685
+ const dir = dirname19(cfg), loaded = [...ch].find((c) => c !== cfg && (dir === "." || c.startsWith(dir + "/")) && !NON_SOURCE.test(c));
13535
13686
  if (ch.has(cfg) || loaded)
13536
13687
  notes.add(`runner config unparseable, trust capped: ${cfg}${loaded ? ` (${loaded} changed and may be loaded by it)` : ""}`);
13537
13688
  }
@@ -13563,7 +13714,7 @@ var PKG_KEYS, RAW_CONFIGS, RUNNER_CONFIGS, DEP_MAPS, RUNNER_DEP, LOCAL_SPEC, dep
13563
13714
  }
13564
13715
  }, headText = (dir, f) => {
13565
13716
  try {
13566
- return readFileSync39(join48(dir, f), "utf8");
13717
+ return readFileSync40(join48(dir, f), "utf8");
13567
13718
  } catch {
13568
13719
  return "";
13569
13720
  }
@@ -13603,7 +13754,7 @@ var init_runner_config = __esm(() => {
13603
13754
 
13604
13755
  // ../../loki-ts/src/e10ext/assert_delta.ts
13605
13756
  import { execFileSync as execFileSync4 } from "child_process";
13606
- import { mkdtempSync as mkdtempSync6, readFileSync as readFileSync40, rmSync as rmSync15 } from "fs";
13757
+ import { mkdtempSync as mkdtempSync6, readFileSync as readFileSync41, rmSync as rmSync15 } from "fs";
13607
13758
  import { tmpdir as tmpdir8 } from "os";
13608
13759
  import { join as join49 } from "path";
13609
13760
  import { basename as basename20 } from "path";
@@ -13646,7 +13797,7 @@ function assertDeltaNotes(repoDir, baseSha, headRef, path, task, baseCounts, hea
13646
13797
  return null;
13647
13798
  try {
13648
13799
  const show = (ref) => safeGit(repoDir, ["show", `${ref}:${path}`]);
13649
- const head = headRef ? show(headRef) : readFileSync40(join49(repoDir, path), "utf8");
13800
+ const head = headRef ? show(headRef) : readFileSync41(join49(repoDir, path), "utf8");
13650
13801
  const r = classifyTestEdit(path, show(baseSha), head, task, baseCounts, headCounts);
13651
13802
  return r[0]?.kind === "literal-only" ? r.map((e) => `assertion value changed (not shown to be required by the task): ${e.file}:${e.line} ${e.old} -> ${e.new}`) : null;
13652
13803
  } catch {
@@ -13875,11 +14026,11 @@ var init_wall_owned = __esm(() => {
13875
14026
 
13876
14027
  // ../../loki-ts/src/util/app_probe.ts
13877
14028
  import { spawnSync as spawnSync6 } from "child_process";
13878
- import { existsSync as existsSync31, mkdirSync as mkdirSync19, readFileSync as readFileSync41, renameSync as renameSync11, writeFileSync as writeFileSync22 } from "fs";
14029
+ import { existsSync as existsSync32, mkdirSync as mkdirSync19, readFileSync as readFileSync42, renameSync as renameSync11, writeFileSync as writeFileSync22 } from "fs";
13879
14030
  import { join as join51 } from "path";
13880
14031
  function readJson4(p) {
13881
14032
  try {
13882
- const v = JSON.parse(readFileSync41(p, "utf8"));
14033
+ const v = JSON.parse(readFileSync42(p, "utf8"));
13883
14034
  return v && typeof v === "object" ? v : null;
13884
14035
  } catch {
13885
14036
  return null;
@@ -13887,7 +14038,7 @@ function readJson4(p) {
13887
14038
  }
13888
14039
  function stopApp(repoDir, opts = {}) {
13889
14040
  const runner = opts.runnerPath ?? join51(REPO_ROOT, "autonomy", "app-runner.sh");
13890
- if (!existsSync31(runner) || !existsSync31(join51(repoDir, ".loki", "app-runner", "app.pid")))
14041
+ if (!existsSync32(runner) || !existsSync32(join51(repoDir, ".loki", "app-runner", "app.pid")))
13891
14042
  return;
13892
14043
  spawnSync6("bash", ["-c", STOP, "app-probe", repoDir, runner], { cwd: repoDir, env: plainTestEnv(), timeout: opts.timeoutMs ?? 60000, killSignal: "SIGKILL", stdio: "ignore" });
13893
14044
  }
@@ -13901,7 +14052,7 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
13901
14052
  return { out: r.stdout ?? "", status: r.error ? null : r.status };
13902
14053
  };
13903
14054
  let pid = null, url = null;
13904
- if (!existsSync31(runner))
14055
+ if (!existsSync32(runner))
13905
14056
  return { checks: [mk2("app boot", "not_run", "app-runner.sh not found"), mk2("http probe", "not_run", "app not booted")], pid, url };
13906
14057
  try {
13907
14058
  const b = sh(BOOT);
@@ -13911,7 +14062,7 @@ async function appProbe(repoDir, lokiDir2, opts = {}) {
13911
14062
  return { checks, pid, url };
13912
14063
  }
13913
14064
  const ir = Number(m[1]), sr = Number(m[2]), hr = Number(m[3]), noApp = m[4] === "1";
13914
- const pidTxt = existsSync31(join51(dir, "app.pid")) ? readFileSync41(join51(dir, "app.pid"), "utf8").trim() : "";
14065
+ const pidTxt = existsSync32(join51(dir, "app.pid")) ? readFileSync42(join51(dir, "app.pid"), "utf8").trim() : "";
13915
14066
  pid = /^\d+$/.test(pidTxt) && sr >= 0 ? Number(pidTxt) : null;
13916
14067
  const st = readJson4(join51(dir, "state.json"));
13917
14068
  url = typeof st?.["url"] === "string" ? st["url"] : null;
@@ -13938,7 +14089,7 @@ async function functionalVerify(opts, url, dir, lokiDir2, timeoutMs) {
13938
14089
  const t0 = Date.now();
13939
14090
  const res = (result, reason) => ({ name: "functional verify", cmd: "autonomy/lib/functional-verify.py", result, duration_s: (Date.now() - t0) / 1000, reason });
13940
14091
  const py = await findPython3(), script = opts.verifyPath ?? join51(REPO_ROOT, "autonomy", "lib", "functional-verify.py");
13941
- if (!py || !existsSync31(script))
14092
+ if (!py || !existsSync32(script))
13942
14093
  return res("not_run", "python3 or functional-verify.py unavailable");
13943
14094
  const specFile = join51(dir, "spec.txt");
13944
14095
  writeFileSync22(specFile, opts.specText ?? "");
@@ -13988,16 +14139,16 @@ app_runner_stop >/dev/null 2>&1
13988
14139
  });
13989
14140
 
13990
14141
  // ../../loki-ts/src/util/secure_scan.ts
13991
- import { existsSync as existsSync32, mkdirSync as mkdirSync20, mkdtempSync as mkdtempSync7, readFileSync as readFileSync42, realpathSync as realpathSync21, rmSync as rmSync16, statSync as statSync19, writeFileSync as writeFileSync23 } from "fs";
14142
+ import { existsSync as existsSync33, mkdirSync as mkdirSync20, mkdtempSync as mkdtempSync7, readFileSync as readFileSync43, realpathSync as realpathSync21, rmSync as rmSync16, statSync as statSync19, writeFileSync as writeFileSync23 } from "fs";
13992
14143
  import { randomBytes as randomBytes5 } from "crypto";
13993
14144
  import { tmpdir as tmpdir9 } from "os";
13994
- import { basename as basename21, dirname as dirname19, join as join52, resolve as resolve17, sep as sep12 } from "path";
14145
+ import { basename as basename21, dirname as dirname20, join as join52, resolve as resolve17, sep as sep12 } from "path";
13995
14146
  function fail(error) {
13996
14147
  return { ok: false, findings: [], error };
13997
14148
  }
13998
14149
  async function runSecureScan(targetDir, opts = {}) {
13999
14150
  const script = opts.scriptPath ?? join52(REPO_ROOT, "autonomy", "lib", "secure-scan.py");
14000
- if (!existsSync32(script))
14151
+ if (!existsSync33(script))
14001
14152
  return fail(`secure-scan script not found: ${script}`);
14002
14153
  const py = await findPython3();
14003
14154
  if (!py)
@@ -14181,7 +14332,7 @@ async function scanAddedLines(repoDir, opts = {}) {
14181
14332
  continue;
14182
14333
  }
14183
14334
  const lines2 = new Map;
14184
- readFileSync42(join52(repoDir, p), "utf8").split(`
14335
+ readFileSync43(join52(repoDir, p), "utf8").split(`
14185
14336
  `).forEach((t, i) => lines2.set(i + 1, t));
14186
14337
  added.set(p, lines2);
14187
14338
  } catch {}
@@ -14239,7 +14390,7 @@ async function scanAddedLines(repoDir, opts = {}) {
14239
14390
  if (!out2.startsWith(root))
14240
14391
  break;
14241
14392
  chunkMap.set(rel, { file: p, lines: c.orig });
14242
- mkdirSync20(dirname19(out2), { recursive: true });
14393
+ mkdirSync20(dirname20(out2), { recursive: true });
14243
14394
  writeFileSync23(out2, c.body.join(`
14244
14395
  `) + `
14245
14396
  `);
@@ -14289,8 +14440,8 @@ var init_secure_scan = __esm(() => {
14289
14440
  var init_retry_class = () => {};
14290
14441
 
14291
14442
  // ../../loki-ts/src/project_model/conventions.ts
14292
- import { existsSync as existsSync33, readdirSync as readdirSync19, readFileSync as readFileSync43 } from "fs";
14293
- import { basename as basename22, dirname as dirname20, isAbsolute as isAbsolute9, join as join53, relative as relative9, resolve as resolve18 } from "path";
14443
+ import { existsSync as existsSync34, readdirSync as readdirSync19, readFileSync as readFileSync44 } from "fs";
14444
+ import { basename as basename22, dirname as dirname21, isAbsolute as isAbsolute9, join as join53, relative as relative9, resolve as resolve18 } from "path";
14294
14445
  function parseJsonc(text2) {
14295
14446
  let out2 = "", i = 0;
14296
14447
  while (i < text2.length) {
@@ -14325,8 +14476,8 @@ function moduleOf(file, depth = 0) {
14325
14476
  const ext = typeof j.extends === "string" ? j.extends : null;
14326
14477
  if (!ext || !ext.startsWith("."))
14327
14478
  return null;
14328
- const next = join53(dirname20(file), ext.endsWith(".json") ? ext : `${ext}.json`);
14329
- return existsSync33(next) ? moduleOf(next, depth + 1) : null;
14479
+ const next = join53(dirname21(file), ext.endsWith(".json") ? ext : `${ext}.json`);
14480
+ return existsSync34(next) ? moduleOf(next, depth + 1) : null;
14330
14481
  }
14331
14482
  function readPackageConventions(pkgDir, runner = null) {
14332
14483
  let names = [];
@@ -14396,8 +14547,8 @@ function nearestPackageRoot(testDir, repoDir, fileName) {
14396
14547
  }
14397
14548
  };
14398
14549
  let pkg = testDir;
14399
- while (pkg !== repoDir && pkg !== dirname20(pkg) && !shaped(pkg))
14400
- pkg = dirname20(pkg);
14550
+ while (pkg !== repoDir && pkg !== dirname21(pkg) && !shaped(pkg))
14551
+ pkg = dirname21(pkg);
14401
14552
  return pkg;
14402
14553
  }
14403
14554
  function phantomRepoPaths(content, fileName, testDir, repoDir, planText) {
@@ -14449,7 +14600,7 @@ function phantomRepoPaths(content, fileName, testDir, repoDir, planText) {
14449
14600
  };
14450
14601
  const strayInTestDir = (out2) => {
14451
14602
  const first = relative9(testDir, out2).split("/")[0];
14452
- return !!first && first !== "__self__" && !existsSync33(join53(testDir, first)) && [pkg, repoDir].some((d) => d !== testDir && existsSync33(join53(d, first)));
14603
+ return !!first && first !== "__self__" && !existsSync34(join53(testDir, first)) && [pkg, repoDir].some((d) => d !== testDir && existsSync34(join53(d, first)));
14453
14604
  };
14454
14605
  const scan = (cwd) => {
14455
14606
  const vars = new Map, walk = new Set, taint = new Set, reports = new Map, created = [];
@@ -14480,9 +14631,9 @@ function phantomRepoPaths(content, fileName, testDir, repoDir, planText) {
14480
14631
  if (args.some((a) => a === null))
14481
14632
  return null;
14482
14633
  if (call[1] === "dirname")
14483
- return dirname20(args[0]);
14634
+ return dirname21(args[0]);
14484
14635
  const out2 = resolve18(...args);
14485
- const first = parts.slice(1).map((a) => /^\s*["'`]([^"'`]*)["'`]\s*$/.exec(a)?.[1]).find((x) => x), viaWalk = !!first && walk.has(parts[0].trim()) && [pkg, repoDir].some((d) => existsSync33(join53(d, first.split("/").filter(Boolean)[0] ?? "\x00")));
14636
+ const first = parts.slice(1).map((a) => /^\s*["'`]([^"'`]*)["'`]\s*$/.exec(a)?.[1]).find((x) => x), viaWalk = !!first && walk.has(parts[0].trim()) && [pkg, repoDir].some((d) => existsSync34(join53(d, first.split("/").filter(Boolean)[0] ?? "\x00")));
14486
14637
  if (report && (viaWalk || !parts.some((a) => walk.has(a.trim()) || taint.has(a.trim())) && (relative9(testDir, out2).startsWith("..") || strayInTestDir(out2))) && parts.some((a) => /^\s*["'`]/.test(a)))
14487
14638
  reports.set(`${ln}|${e}`, { out: out2, rel: relative9(repoDir, out2), tail: viaWalk ? join53(...args.slice(1)) : undefined });
14488
14639
  return out2;
@@ -14532,21 +14683,21 @@ function phantomRepoPaths(content, fileName, testDir, repoDir, planText) {
14532
14683
  const runs2 = [...new Set([pkg, repoDir])].map(scan);
14533
14684
  const planned = (rel) => !!planText && rel.split("/").some((_, i, a) => {
14534
14685
  const pre = a.slice(0, i + 1).join("/");
14535
- return (i > 0 || a.length === 1) && !existsSync33(join53(repoDir, pre)) && new RegExp(`(?<![\\w-])${pre.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w-])`).test(planText);
14686
+ return (i > 0 || a.length === 1) && !existsSync34(join53(repoDir, pre)) && new RegExp(`(?<![\\w-])${pre.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w-])`).test(planText);
14536
14687
  });
14537
14688
  const phantom = (r, created) => {
14538
14689
  const rel = r.rel;
14539
- if (!rel || rel.startsWith("..") || isAbsolute9(rel) || /(^|\/)(\.git|\.loki|dist|build|coverage|tmp)(\/|$)/.test(rel) || existsSync33(r.out) || planned(rel))
14690
+ if (!rel || rel.startsWith("..") || isAbsolute9(rel) || /(^|\/)(\.git|\.loki|dist|build|coverage|tmp)(\/|$)/.test(rel) || existsSync34(r.out) || planned(rel))
14540
14691
  return false;
14541
14692
  if (r.tail) {
14542
14693
  const seen = (from) => {
14543
14694
  let d = from;
14544
14695
  for (let i = 0;i < 64; i++) {
14545
- if (existsSync33(join53(d, r.tail)))
14696
+ if (existsSync34(join53(d, r.tail)))
14546
14697
  return true;
14547
- if (d === repoDir || d === dirname20(d))
14698
+ if (d === repoDir || d === dirname21(d))
14548
14699
  return false;
14549
- d = dirname20(d);
14700
+ d = dirname21(d);
14550
14701
  }
14551
14702
  return false;
14552
14703
  };
@@ -14584,7 +14735,7 @@ function phantomReason(miss, repoFiles, testDir = "", pkgRoot = "") {
14584
14735
  }
14585
14736
  var readJson5 = (p) => {
14586
14737
  try {
14587
- const v = parseJsonc(readFileSync43(p, "utf8"));
14738
+ const v = parseJsonc(readFileSync44(p, "utf8"));
14588
14739
  return v && typeof v === "object" && !Array.isArray(v) ? v : null;
14589
14740
  } catch {
14590
14741
  return null;
@@ -14623,10 +14774,10 @@ var init_preexisting_dirty = __esm(() => {
14623
14774
  });
14624
14775
 
14625
14776
  // ../../loki-ts/src/e10ext/commit_filter.ts
14626
- import { dirname as dirname21 } from "path";
14777
+ import { dirname as dirname22 } from "path";
14627
14778
  function dropSet(repoDir, staged, preexistingDirty, env = process.env, installCreated) {
14628
14779
  const owned = installOwned(repoDir, installCreated, env), made = installCreated?.files ?? {};
14629
- return staged.concat(untouchedSinceIntake(repoDir, preexistingDirty, env).map((f) => ({ st: "L", f })), staged.filter(({ f }) => owned(f)).map(({ f }) => ({ st: "L", f }))).filter(({ st, f }) => f.startsWith(".loki/") || st === "L" || WALL_FILE.test(f) || st === "A" && !Object.hasOwn(made, f) && !staged.some(({ f: m }) => /(^|\/)(package\.json|pyproject\.toml|requirements\.txt|Cargo\.toml|go\.mod)$/.test(m) && dirname21(m) === dirname21(f)) && /(^|\/)(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|bun\.lockb?|poetry\.lock|Cargo\.lock|go\.sum)$/.test(f));
14780
+ return staged.concat(untouchedSinceIntake(repoDir, preexistingDirty, env).map((f) => ({ st: "L", f })), staged.filter(({ f }) => owned(f)).map(({ f }) => ({ st: "L", f }))).filter(({ st, f }) => f.startsWith(".loki/") || st === "L" || WALL_FILE.test(f) || st === "A" && !Object.hasOwn(made, f) && !staged.some(({ f: m }) => /(^|\/)(package\.json|pyproject\.toml|requirements\.txt|Cargo\.toml|go\.mod)$/.test(m) && dirname22(m) === dirname22(f)) && /(^|\/)(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|bun\.lockb?|poetry\.lock|Cargo\.lock|go\.sum)$/.test(f));
14630
14781
  }
14631
14782
  var WALL_FILE, parseStaged = (out2) => out2.split("\x00").reduce((a, t, i, all) => i % 2 === 0 && t ? [...a, { st: t, f: all[i + 1] }] : a, []), formatChanged = (repoDir, staged, dropped2, env = process.env) => runFormatters(repoDir, staged.filter(({ st, f }) => (st === "A" || st === "M") && !dropped2.has(f) && !f.startsWith(".loki/")).map(({ f }) => f), tokenFreeEnv(env));
14632
14783
  var init_commit_filter = __esm(() => {
@@ -14646,21 +14797,6 @@ var init_reviewer_body = __esm(() => {
14646
14797
  init_commit_filter();
14647
14798
  });
14648
14799
 
14649
- // ../../loki-ts/src/util/update_check.ts
14650
- var CACHE_TTL_MS, NEGATIVE_TTL_MS;
14651
- var init_update_check = __esm(() => {
14652
- init_paths();
14653
- CACHE_TTL_MS = 24 * 60 * 60 * 1000;
14654
- NEGATIVE_TTL_MS = 15 * 60 * 1000;
14655
- });
14656
-
14657
- // ../../loki-ts/src/runner/router/advisor_probe.ts
14658
- var ADVISOR_ERROR_LIMIT = 3;
14659
- var init_advisor_probe = __esm(() => {
14660
- init_claude_model();
14661
- init_update_check();
14662
- });
14663
-
14664
14800
  // ../../loki-ts/src/runner/router/route_block.ts
14665
14801
  function advisorUnavailableReason(env, provider) {
14666
14802
  if (provider !== "claude")
@@ -14748,9 +14884,9 @@ var init_route_block = __esm(() => {
14748
14884
  // ../../loki-ts/src/features/visual_evidence.ts
14749
14885
  import { spawn as spawn8 } from "child_process";
14750
14886
  import { createHash as createHash15, randomBytes as randomBytes6 } from "crypto";
14751
- import { existsSync as existsSync34, lstatSync as lstatSync12, mkdirSync as mkdirSync21, readdirSync as readdirSync20, readFileSync as readFileSync44, writeFileSync as writeFileSync24 } from "fs";
14887
+ import { existsSync as existsSync35, lstatSync as lstatSync12, mkdirSync as mkdirSync21, readdirSync as readdirSync20, readFileSync as readFileSync45, writeFileSync as writeFileSync24 } from "fs";
14752
14888
  import { createServer } from "net";
14753
- import { dirname as dirname22, isAbsolute as isAbsolute10, join as join54, normalize as normalize3, relative as relative10, sep as sep13 } from "path";
14889
+ import { dirname as dirname23, isAbsolute as isAbsolute10, join as join54, normalize as normalize3, relative as relative10, sep as sep13 } from "path";
14754
14890
  function routeFor(file) {
14755
14891
  let r = file.replace(/^(?:.*?\/)?(?:app|pages|src|public)\//, "").replace(/^(?:routes|pages)\//, "");
14756
14892
  r = r.replace(/\.(?:html|jsx|tsx|vue|svelte)$/, "").replace(/\/?(?:page|index|\+page)$/, "");
@@ -14780,7 +14916,7 @@ function checkScreens(runDir, screens) {
14780
14916
  if (isSymlink(cur))
14781
14917
  return `evidence screenshot path is a symlink: ${s.path}`;
14782
14918
  }
14783
- if (!existsSync34(file))
14919
+ if (!existsSync35(file))
14784
14920
  return `evidence screenshot is missing: ${s.path}`;
14785
14921
  if (!isRegularFile(file))
14786
14922
  return `evidence screenshot is not a regular file: ${s.path}`;
@@ -14824,10 +14960,10 @@ async function waitUp(url, ms, signal) {
14824
14960
  function openapiPaths(repoDir) {
14825
14961
  for (const f of ["openapi.json", "openapi.yaml", "openapi.yml", "swagger.json"]) {
14826
14962
  const p = join54(repoDir, f);
14827
- if (!existsSync34(p))
14963
+ if (!existsSync35(p))
14828
14964
  continue;
14829
14965
  try {
14830
- const txt = readFileSync44(p, "utf8");
14966
+ const txt = readFileSync45(p, "utf8");
14831
14967
  const paths = f.endsWith(".json") ? Object.keys(JSON.parse(txt).paths ?? {}) : [...txt.matchAll(/^ {2}(\/[^\s:]*):\s*$/gm)].map((m) => m[1]);
14832
14968
  return paths.filter((x) => !x.includes("{")).slice(0, 10);
14833
14969
  } catch {
@@ -14941,18 +15077,18 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
14941
15077
  const pkgPath = join54(appDir, "package.json");
14942
15078
  let script = null;
14943
15079
  if (!boot) {
14944
- if (!existsSync34(pkgPath)) {
14945
- const subs = ["backend", "frontend"].filter((d) => existsSync34(join54(repoDir, d, "package.json")));
15080
+ if (!existsSync35(pkgPath)) {
15081
+ const subs = ["backend", "frontend"].filter((d) => existsSync35(join54(repoDir, d, "package.json")));
14946
15082
  const has2 = (d) => {
14947
15083
  try {
14948
- return pickScript(JSON.parse(readFileSync44(join54(repoDir, d, "package.json"), "utf8"))) !== null;
15084
+ return pickScript(JSON.parse(readFileSync45(join54(repoDir, d, "package.json"), "utf8"))) !== null;
14949
15085
  } catch {
14950
15086
  return false;
14951
15087
  }
14952
15088
  };
14953
15089
  return skip(noRootReason(subs, subs.filter((d) => !has2(d))));
14954
15090
  }
14955
- script = pickScript(JSON.parse(readFileSync44(pkgPath, "utf8")));
15091
+ script = pickScript(JSON.parse(readFileSync45(pkgPath, "utf8")));
14956
15092
  if (!script)
14957
15093
  return skip("no dev, preview or start script");
14958
15094
  }
@@ -14992,7 +15128,7 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
14992
15128
  break;
14993
15129
  const rel = join54(rel0, `${screenName(route)}.png`);
14994
15130
  const ok = await shoot(pw, ["screenshot", `${base}${route}`, join54(runDir, rel)], appDir, left(), signal);
14995
- if (ok && !aborted() && !isSymlink(join54(runDir, rel)) && existsSync34(join54(runDir, rel)))
15131
+ if (ok && !aborted() && !isSymlink(join54(runDir, rel)) && existsSync35(join54(runDir, rel)))
14996
15132
  rels.push(rel);
14997
15133
  }
14998
15134
  if (aborted())
@@ -15046,14 +15182,14 @@ async function sealEvidence(repoDir, runDir, o, notProven, signal, emit) {
15046
15182
  function receiptScreensProblem(receiptPath, receipt) {
15047
15183
  if (visualGateEnabled() && typeof receipt["evidence_failed"] === "string")
15048
15184
  return `visual evidence failed (LOKI_VISUAL_GATE=1): ${receipt["evidence_failed"]}`;
15049
- return receipt["evidence_screens"] === undefined ? null : checkScreens(dirname22(receiptPath), receipt["evidence_screens"]);
15185
+ return receipt["evidence_screens"] === undefined ? null : checkScreens(dirname23(receiptPath), receipt["evidence_screens"]);
15050
15186
  }
15051
- 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) => createHash15("sha256").update(readFileSync44(p)).digest("hex"), playwrightBin = (repoDir) => {
15187
+ 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) => createHash15("sha256").update(readFileSync45(p)).digest("hex"), playwrightBin = (repoDir) => {
15052
15188
  const bin = join54(repoDir, "node_modules", ".bin", "playwright");
15053
- return existsSync34(bin) ? bin : null;
15189
+ return existsSync35(bin) ? bin : null;
15054
15190
  }, playwrightTestPkg = (repoDir) => {
15055
15191
  const d = join54(repoDir, "node_modules", "@playwright", "test");
15056
- return existsSync34(join54(d, "package.json")) ? d : null;
15192
+ return existsSync35(join54(d, "package.json")) ? d : null;
15057
15193
  }, e2eSpecSource = (pkgDir, base, routes) => `const { test } = require(${JSON.stringify(pkgDir)});
15058
15194
  test("loki e2e walkthrough", async ({ page }) => {
15059
15195
  for (const r of ${JSON.stringify(routes)}) { await page.goto(${JSON.stringify(base)} + r); await page.waitForLoadState("load"); }
@@ -15125,15 +15261,15 @@ var init_pr = __esm(() => {
15125
15261
  });
15126
15262
 
15127
15263
  // ../../loki-ts/src/util/pr_lessons.ts
15128
- import { existsSync as existsSync35, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync8, readFileSync as readFileSync45, rmSync as rmSync17, writeFileSync as writeFileSync25 } from "fs";
15129
- import { dirname as dirname23, join as join56 } from "path";
15264
+ import { existsSync as existsSync36, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync8, readFileSync as readFileSync46, rmSync as rmSync17, writeFileSync as writeFileSync25 } from "fs";
15265
+ import { dirname as dirname24, join as join56 } from "path";
15130
15266
  import { createHash as createHash16 } from "crypto";
15131
15267
  function loadLessons(repoDir) {
15132
15268
  const p = lessonsPath(repoDir);
15133
- if (!existsSync35(p))
15269
+ if (!existsSync36(p))
15134
15270
  return [];
15135
15271
  try {
15136
- const j = JSON.parse(readFileSync45(p, "utf-8"));
15272
+ const j = JSON.parse(readFileSync46(p, "utf-8"));
15137
15273
  return Array.isArray(j.lessons) ? j.lessons : [];
15138
15274
  } catch {
15139
15275
  return [];
@@ -15141,7 +15277,7 @@ function loadLessons(repoDir) {
15141
15277
  }
15142
15278
  function save(repoDir, lessons) {
15143
15279
  const p = lessonsPath(repoDir);
15144
- mkdirSync22(dirname23(p), { recursive: true });
15280
+ mkdirSync22(dirname24(p), { recursive: true });
15145
15281
  atomicWriteJson(p, { version: 2, lessons });
15146
15282
  }
15147
15283
  function appendReceiptFact(repoDir, f, now2 = () => new Date) {
@@ -15197,141 +15333,6 @@ var init_attempts = __esm(() => {
15197
15333
  init_treeswap();
15198
15334
  });
15199
15335
 
15200
- // ../../loki-ts/src/providers/mcp_config.ts
15201
- var init_mcp_config = () => {};
15202
-
15203
- // ../../loki-ts/src/providers/claude_flags.ts
15204
- import { existsSync as existsSync36, readFileSync as readFileSync46 } from "fs";
15205
- import { resolve as resolvePath, dirname as dirname24 } from "path";
15206
- import { fileURLToPath as fileURLToPath6 } from "url";
15207
- function claudeFlagSupported(flag, helpText) {
15208
- const txt = helpText ?? _claudeHelpCache;
15209
- if (txt === null || txt === undefined) {
15210
- return false;
15211
- }
15212
- return txt.includes(flag);
15213
- }
15214
- async function ensureClaudeHelpCache() {
15215
- if (_claudeHelpCache !== null)
15216
- return;
15217
- try {
15218
- const proc = Bun.spawn(["claude", "--help"], {
15219
- stdout: "pipe",
15220
- stderr: "pipe",
15221
- env: { ...process.env }
15222
- });
15223
- const text2 = await new Response(proc.stdout).text();
15224
- await proc.exited;
15225
- _claudeHelpCache = text2 || "";
15226
- } catch {
15227
- _claudeHelpCache = "";
15228
- }
15229
- }
15230
- function leanReviewerFlags(opts = {}) {
15231
- const env = opts.env ?? process.env;
15232
- if (env["LOKI_LEAN_CHILDREN"] === "0")
15233
- return [];
15234
- const ok = opts.flagSupported ?? ((f) => claudeFlagSupported(f));
15235
- const out2 = [];
15236
- if (env["LOKI_BARE_SUBCALLS"] !== "0" && (env["ANTHROPIC_API_KEY"] ?? "").trim() !== "" && ok("--bare")) {
15237
- out2.push("--bare");
15238
- } else {
15239
- if (ok("--setting-sources"))
15240
- out2.push("--setting-sources", opts.settingSources ?? "project");
15241
- if (ok("--strict-mcp-config"))
15242
- out2.push("--strict-mcp-config", "--mcp-config", '{"mcpServers":{}}');
15243
- if (ok("--disable-slash-commands"))
15244
- out2.push("--disable-slash-commands");
15245
- }
15246
- if (ok("--tools"))
15247
- out2.push(`--tools=${opts.tools ?? ""}`);
15248
- return out2;
15249
- }
15250
- function designArchetypesText() {
15251
- try {
15252
- const moduleDir = dirname24(fileURLToPath6(import.meta.url));
15253
- for (const rel of [
15254
- ["..", "..", "..", "references", "design-archetypes.md"],
15255
- ["..", "..", "references", "design-archetypes.md"]
15256
- ]) {
15257
- const p = resolvePath(moduleDir, ...rel);
15258
- if (existsSync36(p))
15259
- return readFileSync46(p, "utf8");
15260
- }
15261
- } catch {}
15262
- return "";
15263
- }
15264
- var REVIEW_GUARD_DENYLIST = "Edit,Write,NotebookEdit,Bash(git commit:*),Bash(git reset:*),Bash(git push:*),Bash(git checkout:*),Bash(git clean:*),Bash(git rm:*),Bash(git stash:*),Bash(git -C:*),Bash(git --git-dir:*),Bash(git -c:*),Bash(git --exec-path:*),Bash(git diff --output:*),Bash(git diff --output=:*),Bash(git diff --ext-diff:*),Bash(git diff --no-index:*),Bash(git log --output:*),Bash(git log --output=:*),Bash(git log --ext-diff:*),Bash(git show --output:*),Bash(git show --output=:*),Bash(git show --ext-diff:*),Bash(git blame --output:*),Bash(git blame --output=:*),Bash(rg --pre:*),Bash(rg --pre=:*),Bash(rg --pre-glob:*),Bash(rg --pre-glob=:*),Bash(rg --hostname-bin:*),Bash(rg --hostname-bin=:*),Bash(find -delete:*),Bash(find -exec:*),Bash(find -execdir:*),Bash(find -ok:*),Bash(find -fprint:*),Bash(find -fprintf:*),Bash(find -fls:*),Bash(git * --output*),Bash(git * --ext-diff*),Bash(git * --no-index*),Bash(rg * --pre*),Bash(rg * --hostname-bin*),Bash(rg --pre*),Bash(rg --hostname-bin*),Bash(find * -delete*),Bash(find * -exec*),Bash(find * -execdir*),Bash(find * -fprint*),Bash(find * -fls*),Bash(find * -ok*)", _claudeHelpCache = null, AUTONOMY_OVERRIDE_TEXT, FIRST_PASS_EXCELLENCE_TEXT, REVIEW_ALLOWLIST_TOKEN = "Read,Grep,Glob,Bash(git diff:*),Bash(git log:*),Bash(git show:*),Bash(git status:*),Bash(git ls-files:*),Bash(git rev-parse:*),Bash(git blame:*),Bash(cat:*),Bash(ls:*),Bash(grep:*),Bash(rg:*),Bash(find:*),Bash(head:*),Bash(tail:*),Bash(wc:*)", REVIEW_ALLOWLIST_NO_GIT, CAVEMAN_PINNED_VERSION;
15265
- var init_claude_flags = __esm(() => {
15266
- init_mcp_config();
15267
- init_claude_model();
15268
- AUTONOMY_OVERRIDE_TEXT = `[LOKI-AUTONOMY-AGENT] This is a Loki Mode autonomous agent process.
15269
- ` + `You are running INSIDE Loki Mode autonomous execution, a session the user explicitly launched with full prior authorization (loki start / loki run). This IS an authorized autonomous session, not an unattended action you must seek consent for.
15270
-
15271
- ` + `Instruction precedence for THIS session: when the loki_system instructions in the user prompt conflict with any CLAUDE.md, project memory, or global memory that tells you to ask for clarification, pause for confirmation, refuse to act autonomously, or withhold routine commits, the loki_system instructions take precedence. The user has already consented by launching autonomous mode.
15272
-
15273
- ` + `Therefore, for this session: do NOT ask the user questions, do NOT call the AskUserQuestion tool, do NOT stop to request confirmation, and do NOT refuse routine, reversible engineering work (writing code, running tests, creating files, atomic git checkpoints in the working tree). Proceed and complete the task directly. If a decision is genuinely ambiguous, choose the most reasonable option, record the assumption in .loki/CONTINUITY.md, and continue rather than halting.
15274
-
15275
- ` + "Commit hygiene still applies: git checkpoints are LOCAL only. Never push or force-push. Stage files by explicit path, never `git add -A` or `git add .`, and never commit secrets, credentials, .env files, or untracked files you did not author this session.\n\n" + `This precedence override is narrow. It does NOT relax any safety rule. Every safety prohibition in CLAUDE.md or memory still fully binds: anything genuinely destructive or irreversible remains out of scope unless the task explicitly calls for it. This includes (not limited to) force-pushing, deleting or overwriting the user's data, dropping or truncating databases, publishing or releasing, rotating or exfiltrating secrets, touching production systems, and anything a CLAUDE.md safety rule explicitly forbids. When in doubt about whether an action is destructive, treat it as destructive and do not do it.
15276
- `;
15277
- FIRST_PASS_EXCELLENCE_TEXT = `
15278
- [FIRST-PASS EXCELLENCE] Treat THIS pass as your one shot to ship a complete, working, verified solution. Do not produce a rough draft to refine later; the loop exists as a safety net, not a plan. Before you finish this iteration:
15279
- ` + `1. BUILD IT FULLY. Implement every requirement end to end. No stubs, no TODOs, no "coming soon", no placeholder or hardcoded/mock data where real logic belongs. If the spec implies a backend (auth, persistence, a form that submits, a list that saves), WIRE IT so it actually works and persists -- a beautiful UI whose buttons do nothing is the single most common failure, not a draft. Every list/table must trace to a real query, never an inline mock array.
15280
- ` + `2. SELF-VERIFY BY RUNNING, not by reading. Run the build and the tests yourself; for each acceptance criterion, DRIVE the actual path and observe the result (submit the form, then reload and confirm the record persisted; hit a protected route logged-out and confirm it is rejected). Fix what fails now, in this pass. Do not mark done on "looks right" or a self-claim -- observed behavior is the only proof.
15281
- ` + `3. LOCK THE ARCHITECTURE on this pass so later edits are small and additive. Decide the data model, routes, and component structure up front and build to them; never rewrite whole files later to patch a small thing (that is the doom loop that breaks working features).
15282
- ` + `4. DESIGN: commit to ONE named aesthetic direction up front (editorial, brutalist, luxury, retro-futuristic, soft/pastel, industrial, etc. -- chosen from the product domain) and hold it on every surface. Use real content (never lorem). AVOID the AI-slop tells that instantly read as machine-generated: NO indigo/blue-to-purple gradient (the #1 tell), NO Inter/Roboto/system-font headlines (pick a real display+body pairing), NO three-equal-rounded-cards-in-a-row skeleton, NO flat 1px gray card borders or colored left-border strips, NO untouched shadcn defaults, NO reflexive dark mode. Cap the palette at ~3 hues (60/30/10), tinted not pure #fff/#000, separate sections by whitespace then a slight background shift before any border. Aim for Linear/Stripe/Duolingo-tier taste: "this does not look AI-generated".
15283
- ` + `5. SATISFY THE GATES THAT WILL JUDGE THIS PASS. Your work is checked by deterministic gates before it can be accepted, and in measured runs EVERY extra iteration was caused by one of these rejecting the work -- never by the model failing to finish. Clear them now, in this pass:
15284
- ` + ` - STATIC ANALYSIS: no syntax errors, no unused/undefined symbols, no lint errors in files you touched.
15285
- ` + ` - TEST SUITE: the existing tests must still pass. Run them; do not assume.
15286
- ` + ` - MUTATION/MOCK INTEGRITY: tests must assert real behaviour. No tautological assertions (expect(true).toBe(true)), no test that passes whether or not the code works, no mocking the very unit under test, no inline mock data standing in for a real query.
15287
- ` + ` - CODE REVIEW: no scope creep beyond the stated task, no dead or commented-out code, no leftover debug output, and follow the conventions already in the surrounding files.
15288
- ` + `Deliver the finished, self-verified, genuinely-designed result in THIS pass. Additional iterations should be the exception, not the plan.
15289
- ` + designArchetypesText();
15290
- REVIEW_ALLOWLIST_NO_GIT = REVIEW_ALLOWLIST_TOKEN.split(",").filter((t) => !t.startsWith("Bash(git ")).join(",");
15291
- CAVEMAN_PINNED_VERSION = process.env["LOKI_CAVEMAN_VERSION"] || "1.9.0";
15292
- });
15293
-
15294
- // ../../loki-ts/src/util/run_identity.ts
15295
- var init_run_identity = __esm(() => {
15296
- init_model_routes();
15297
- });
15298
-
15299
- // ../../loki-ts/src/runner/sdk_stream_parser.ts
15300
- var init_sdk_stream_parser = __esm(() => {
15301
- init_cost();
15302
- init_run_identity();
15303
- init_budget();
15304
- init_advisor_probe();
15305
- });
15306
-
15307
- // ../../loki-ts/src/runner/trim.ts
15308
- var init_trim = () => {};
15309
-
15310
- // ../../loki-ts/src/runner/provider_opencode.ts
15311
- var init_provider_opencode = __esm(() => {
15312
- init_shell();
15313
- init_providers();
15314
- });
15315
-
15316
- // ../../loki-ts/src/runner/providers.ts
15317
- var _installedVersionCache;
15318
- var init_providers = __esm(() => {
15319
- init_shell();
15320
- init_paths();
15321
- init_claude_flags();
15322
- init_mcp_config();
15323
- init_lean_prefix();
15324
- init_sdk_stream_parser();
15325
- init_session_resume();
15326
- init_trim();
15327
- init_advisor_probe();
15328
- init_claude_model();
15329
- init_model_routes();
15330
- init_provider_opencode();
15331
- init_cost_breakdown();
15332
- _installedVersionCache = new Map;
15333
- });
15334
-
15335
15336
  // ../../loki-ts/src/runner/router/route_record.ts
15336
15337
  import { existsSync as existsSync37, lstatSync as lstatSync13, mkdirSync as mkdirSync23, readFileSync as readFileSync47, writeFileSync as writeFileSync26 } from "fs";
15337
15338
  import { join as join57 } from "path";