loki-mode 11.2.0 → 11.2.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 (77) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/lib/skill-link-heal.sh +54 -0
  4. package/autonomy/loki +156 -1201
  5. package/autonomy/provider-offer.sh +4 -4
  6. package/autonomy/run.sh +11 -3
  7. package/bin/loki +22 -0
  8. package/bin/loki-postinstall.js +3 -1
  9. package/dashboard/__init__.py +1 -1
  10. package/docs/CLI-REFERENCE.md +1 -1
  11. package/docs/INSTALLATION.md +1 -1
  12. package/docs/KNOWN-ISSUES.md +0 -1
  13. package/docs/v10/ADOPTION-PLAN.md +2 -2
  14. package/docs/v10/DECISIONS.md +2 -0
  15. package/docs/v10/FAILURE-CLASSES.md +37 -1
  16. package/loki-ts/dist/loki.js +729 -704
  17. package/mcp/__init__.py +1 -1
  18. package/package.json +1 -1
  19. package/packages/control-plane/dist/server.js +252 -65
  20. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  21. package/web-app/dist/assets/{AdminPage-Bs4Vyd9R.js → AdminPage-C-iMLNxe.js} +1 -1
  22. package/web-app/dist/assets/{Avatar-Dmf_rtmv.js → Avatar-C7VUvwsO.js} +1 -1
  23. package/web-app/dist/assets/{Badge-DCEdgEN8.js → Badge-tGvQEhnw.js} +1 -1
  24. package/web-app/dist/assets/{Button-BpGXXEPk.js → Button-_iHlH_yL.js} +1 -1
  25. package/web-app/dist/assets/{CockpitPage-CzssVmim.js → CockpitPage-J_nNjbcR.js} +1 -1
  26. package/web-app/dist/assets/{ComparePage-BU4XtB9F.js → ComparePage-B05ui6Xt.js} +1 -1
  27. package/web-app/dist/assets/{ErrorBoundary-Bkjf4KP2.js → ErrorBoundary-Bxex6DLn.js} +1 -1
  28. package/web-app/dist/assets/{EvidenceReceiptPanel-CcGMfaq7.js → EvidenceReceiptPanel-BsgWfdD1.js} +1 -1
  29. package/web-app/dist/assets/{GitHubIssuesPanel-D53leEFJ.js → GitHubIssuesPanel-DZBhZ8_X.js} +1 -1
  30. package/web-app/dist/assets/{GitHubPRsPanel-UVsPtV3-.js → GitHubPRsPanel-BaxlAl6R.js} +1 -1
  31. package/web-app/dist/assets/{HomePage-D9wO-XTX.js → HomePage-mVJvzqbF.js} +2 -2
  32. package/web-app/dist/assets/{LoginPage-ChxBSele.js → LoginPage-B0zd4A_G.js} +1 -1
  33. package/web-app/dist/assets/{MagicPage-BqQDKX2L.js → MagicPage-DXLQ-y_R.js} +1 -1
  34. package/web-app/dist/assets/{MetricsPage-CA22NkPl.js → MetricsPage-CLS34Xvr.js} +1 -1
  35. package/web-app/dist/assets/{NotFoundPage-oYt5qdHQ.js → NotFoundPage-BXG8PbNV.js} +1 -1
  36. package/web-app/dist/assets/{ProjectPage-tSAdI6A6.js → ProjectPage-D3kFFC0F.js} +3 -3
  37. package/web-app/dist/assets/{ProjectsPage-Dk22bicF.js → ProjectsPage-2bFn-gnC.js} +1 -1
  38. package/web-app/dist/assets/{SettingsPage-CwDSvMn6.js → SettingsPage-CBM0ziWE.js} +1 -1
  39. package/web-app/dist/assets/{ShowcasePage-By3IMy9k.js → ShowcasePage-BTaXhjI3.js} +1 -1
  40. package/web-app/dist/assets/{SystemSettingsPage-DcWNR28_.js → SystemSettingsPage-BrC2hyAr.js} +1 -1
  41. package/web-app/dist/assets/{TeamsPage-CFawyYQg.js → TeamsPage-oqxdbVbY.js} +1 -1
  42. package/web-app/dist/assets/{TemplatesPage-D7pCD-63.js → TemplatesPage-CEbUIY21.js} +1 -1
  43. package/web-app/dist/assets/{TerminalOutput-CT2v1Vm2.js → TerminalOutput-aIoWLbJA.js} +1 -1
  44. package/web-app/dist/assets/{activity-DW6jRbjj.js → activity-CPyi45gt.js} +1 -1
  45. package/web-app/dist/assets/{bell-CJOu9IIM.js → bell-BhaNBaJp.js} +1 -1
  46. package/web-app/dist/assets/{bot-dVt0Xw_X.js → bot-Da8REaEP.js} +1 -1
  47. package/web-app/dist/assets/{check-BVC4A8YK.js → check-DPj99ArM.js} +1 -1
  48. package/web-app/dist/assets/{chevron-left-Djgr5pg-.js → chevron-left-CkxonN0X.js} +1 -1
  49. package/web-app/dist/assets/{circle-alert-OE2reifn.js → circle-alert-C0JkB1y5.js} +1 -1
  50. package/web-app/dist/assets/{clock-BUUN5rWU.js → clock-COzFIiWi.js} +1 -1
  51. package/web-app/dist/assets/{cloud-CzPIksNz.js → cloud-bjkac4kn.js} +1 -1
  52. package/web-app/dist/assets/{code-xml-DlE7vlGY.js → code-xml-hlKlvXUJ.js} +1 -1
  53. package/web-app/dist/assets/{database-DUauMcIC.js → database-D555S5Km.js} +1 -1
  54. package/web-app/dist/assets/{dollar-sign-CBx9DWbM.js → dollar-sign-CVcApzcD.js} +1 -1
  55. package/web-app/dist/assets/{file-code-corner-hTmaP9Mz.js → file-code-corner-UORaMIcO.js} +1 -1
  56. package/web-app/dist/assets/{file-plus-DimFEqtO.js → file-plus-ALJtDoI2.js} +1 -1
  57. package/web-app/dist/assets/{globe-BV7yxcQ_.js → globe-CPlrM_IC.js} +1 -1
  58. package/web-app/dist/assets/{hammer-CW6Ol_ju.js → hammer-qaGZHpja.js} +1 -1
  59. package/web-app/dist/assets/{index-83w75NC1.js → index-BcXljIAO.js} +3 -3
  60. package/web-app/dist/assets/{layers-DMAqCHxh.js → layers-BV8R9VUK.js} +1 -1
  61. package/web-app/dist/assets/{loader-circle-B-TJNPo5.js → loader-circle-6TlDS9Tu.js} +1 -1
  62. package/web-app/dist/assets/{lock-DbvZW7dV.js → lock-B9t6oWI0.js} +1 -1
  63. package/web-app/dist/assets/{package-BWFcV2kS.js → package-2gEUAtZJ.js} +1 -1
  64. package/web-app/dist/assets/{plus-CjPzASFv.js → plus-DXocxPjU.js} +1 -1
  65. package/web-app/dist/assets/{refresh-cw-DJL2nFq0.js → refresh-cw-D3dWHBd6.js} +1 -1
  66. package/web-app/dist/assets/{rotate-ccw-Bq3vK-Tu.js → rotate-ccw-CvuWqaSB.js} +1 -1
  67. package/web-app/dist/assets/{scroll-text-CAMgtDYH.js → scroll-text-ktmD_xJY.js} +1 -1
  68. package/web-app/dist/assets/{server-D71_Bywf.js → server-E7pZtj5A.js} +1 -1
  69. package/web-app/dist/assets/{shield-alert-DqQ5wzQ6.js → shield-alert-968j9z0V.js} +1 -1
  70. package/web-app/dist/assets/{thumbs-up-DXE_IT36.js → thumbs-up-Tz_8rpU_.js} +1 -1
  71. package/web-app/dist/assets/{trash-2-VYAPKajq.js → trash-2-Drh9IIj8.js} +1 -1
  72. package/web-app/dist/assets/{trending-down-CuE-J2LH.js → trending-down-DCQXtVSL.js} +1 -1
  73. package/web-app/dist/assets/{trending-up-BvdD9XmQ.js → trending-up-BIiwQbWV.js} +1 -1
  74. package/web-app/dist/assets/{upload-OM2YFziE.js → upload-sCbPkfmy.js} +1 -1
  75. package/web-app/dist/assets/{usePolling-Bk39fp_d.js → usePolling-BMIg6ZVT.js} +1 -1
  76. package/web-app/dist/assets/{user-CWmKQURs.js → user-kGzXC3V2.js} +1 -1
  77. package/web-app/dist/index.html +1 -1
package/mcp/__init__.py CHANGED
@@ -75,4 +75,4 @@ try:
75
75
  except ImportError:
76
76
  __all__ = ['mcp']
77
77
 
78
- __version__ = '11.2.0'
78
+ __version__ = '11.2.2'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "loki-mode",
3
3
  "mcpName": "io.github.asklokesh/loki-mode",
4
- "version": "11.2.0",
4
+ "version": "11.2.2",
5
5
  "description": "An autonomous software factory that knows what it is supposed to deliver, and proves it did.",
6
6
  "keywords": [
7
7
  "agent",
@@ -6959,8 +6959,8 @@ var require_public_api = __commonJS((exports) => {
6959
6959
  });
6960
6960
 
6961
6961
  // src/server/app.ts
6962
- import { existsSync as existsSync24, readFileSync as readFileSync30, statSync as statSync15 } from "fs";
6963
- import { join as join39, resolve as resolve8, sep as sep14 } from "path";
6962
+ import { existsSync as existsSync24, readFileSync as readFileSync31, statSync as statSync15 } from "fs";
6963
+ import { join as join40, resolve as resolve8, sep as sep14 } from "path";
6964
6964
 
6965
6965
  // node_modules/hono/dist/request/constants.js
6966
6966
  var GET_MATCH_RESULT = Symbol();
@@ -17519,13 +17519,13 @@ function mount20(ctx) {
17519
17519
  }
17520
17520
 
17521
17521
  // src/server/routes/verify.ts
17522
- import { readFileSync as readFileSync28, realpathSync as realpathSync17 } from "fs";
17522
+ import { readFileSync as readFileSync29, realpathSync as realpathSync17 } from "fs";
17523
17523
  import { createPublicKey as createPublicKey5 } from "crypto";
17524
- import { join as join37, sep as sep13 } from "path";
17524
+ import { join as join38, sep as sep13 } from "path";
17525
17525
 
17526
17526
  // ../../loki-ts/src/engine10/verify_cmd.ts
17527
- import { existsSync as existsSync22, readdirSync as readdirSync12, readFileSync as readFileSync27, statSync as statSync14 } from "fs";
17528
- import { dirname as dirname14, join as join36 } from "path";
17527
+ import { existsSync as existsSync22, readdirSync as readdirSync13, readFileSync as readFileSync28, statSync as statSync14 } from "fs";
17528
+ import { dirname as dirname14, join as join37 } from "path";
17529
17529
  import { createHash as createHash10, createPublicKey as createPublicKey4, verify as verify3 } from "crypto";
17530
17530
 
17531
17531
  // ../../loki-ts/src/util/paths.ts
@@ -17550,9 +17550,9 @@ var REPO_ROOT = findRepoRoot();
17550
17550
 
17551
17551
  // ../../loki-ts/src/engine10/stages/seal.ts
17552
17552
  import { createHash as createHash9, randomBytes as randomBytes3, createPrivateKey, createPublicKey as createPublicKey2, generateKeyPairSync, sign } from "crypto";
17553
- import { chmodSync as chmodSync5, existsSync as existsSync21, readdirSync as readdirSync11, linkSync, mkdirSync as mkdirSync9, readFileSync as readFileSync25, statSync as statSync13, unlinkSync as unlinkSync4, writeFileSync as writeFileSync12 } from "fs";
17553
+ import { chmodSync as chmodSync5, existsSync as existsSync21, readdirSync as readdirSync12, linkSync, mkdirSync as mkdirSync10, readFileSync as readFileSync26, statSync as statSync13, unlinkSync as unlinkSync4, writeFileSync as writeFileSync13 } from "fs";
17554
17554
  import { homedir as homedir7 } from "os";
17555
- import { basename as basename11, dirname as dirname13, join as join35 } from "path";
17555
+ import { basename as basename11, dirname as dirname13, join as join36 } from "path";
17556
17556
 
17557
17557
  // ../../loki-ts/src/e10ext/assert_delta.ts
17558
17558
  import { execFileSync as execFileSync4 } from "child_process";
@@ -18797,6 +18797,187 @@ async function crossReview(ctx, verdict, head) {
18797
18797
  }
18798
18798
  }
18799
18799
 
18800
+ // ../../loki-ts/src/runner/router/flag.ts
18801
+ function routerMode(env = process.env) {
18802
+ const v = (env.LOKI_ROUTER ?? "").trim().toLowerCase();
18803
+ if (v === "0" || v === "false" || v === "off")
18804
+ return "opt-out";
18805
+ if (v === "1" || v === "true" || v === "on")
18806
+ return "on";
18807
+ return "off";
18808
+ }
18809
+ var routerEnabled = (env = process.env) => routerMode(env) === "on";
18810
+
18811
+ // ../../loki-ts/src/runner/router/route_block.ts
18812
+ var ALIAS = { haiku: "haiku-5.5", sonnet: "sonnet-5.5", opus: "opus-5.5" };
18813
+ var modelLabel = (m) => ALIAS[m] ?? m;
18814
+ function advisorUnavailableReason(env, provider) {
18815
+ if (provider !== "claude")
18816
+ return `provider ${provider} has no advisor tool`;
18817
+ if (env["CLAUDE_CODE_USE_BEDROCK"] || env["CLAUDE_CODE_USE_VERTEX"] || env["CLAUDE_CODE_USE_FOUNDRY"])
18818
+ return "advisor tool is unsupported on Bedrock, Vertex and Foundry";
18819
+ if ((env["LOKI_ROUTER_ADVISOR"] ?? "").trim().toLowerCase() === "off")
18820
+ return "LOKI_ROUTER_ADVISOR=off";
18821
+ return null;
18822
+ }
18823
+ var nN = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
18824
+ var rec = (v) => v === null ? "not recorded" : String(v);
18825
+ var s0 = (v) => typeof v === "string" && v.trim() ? v.trim() : null;
18826
+ function toEsc(raw2) {
18827
+ const esc2 = Array.isArray(raw2) ? raw2 : [];
18828
+ return esc2.map((e) => ({ trigger: s0(e["trigger"]) ?? "unknown", from: modelLabel(s0(e["from"]) ?? "?"), to: modelLabel(s0(e["to"]) ?? "?"), evidence: s0(e["evidence"]) ?? "none recorded" }));
18829
+ }
18830
+ var assignedBy = (src, explicit) => s0(explicit) ?? (src === null || src === "opus" ? "opus" : src);
18831
+ function buildRouteBlock(env, provider, route, telemetry) {
18832
+ if (!routerEnabled(env))
18833
+ return null;
18834
+ const executor = s0(route?.["executor"]);
18835
+ const unavailable = s0(route?.["advisor_unavailable_reason"]) ?? advisorUnavailableReason(env, provider);
18836
+ const total = nN(telemetry?.requests_total);
18837
+ const over = nN(telemetry?.requests_over_100k);
18838
+ const shape = s0(route?.["shape_key"]);
18839
+ const escalations = toEsc(route?.["escalations"]);
18840
+ const source = s0(route?.["source"]);
18841
+ const reason = s0(route?.["reason"]) ?? (executor ? "no reason recorded" : "no route recorded by implement");
18842
+ const rawUnits = Array.isArray(route?.["units"]) ? route["units"] : [];
18843
+ const units = rawUnits.length > 0 ? rawUnits.map((u, i) => ({ id: s0(u["id"]) ?? String(i + 1), executor: modelLabel(s0(u["executor"]) ?? "unknown"), assigned_by: assignedBy(s0(u["source"]) ?? source, u["assigned_by"]), reason: s0(u["reason"]) ?? "no reason recorded", escalations: toEsc(u["escalations"]) })) : executor ? [{ id: "run", executor: modelLabel(executor), assigned_by: assignedBy(source, route?.["assigned_by"]), reason, escalations }] : [];
18844
+ return {
18845
+ routed: executor !== null || units.length > 0,
18846
+ units,
18847
+ executor: executor ? modelLabel(executor) : units[0]?.executor ?? null,
18848
+ advisor: unavailable ? null : modelLabel(s0(route?.["advisor"]) ?? "opus"),
18849
+ advisor_unavailable_reason: unavailable,
18850
+ reason,
18851
+ source,
18852
+ shape_key: shape,
18853
+ shape_parity: shape ? `NOT PROVEN (no B9 row for shape ${shape})` : "NOT PROVEN (no shape key recorded)",
18854
+ escalations: units.length > 0 ? units.flatMap((u) => u.escalations) : escalations,
18855
+ requests_total: total,
18856
+ requests_over_100k: over,
18857
+ over_100k_share: total !== null && over !== null && total > 0 ? Math.round(over / total * 1e4) / 1e4 : null,
18858
+ advisor_calls: nN(telemetry?.advisor_calls),
18859
+ advisor_input_tokens: nN(telemetry?.advisor_input_tokens),
18860
+ advisor_output_tokens: nN(telemetry?.advisor_output_tokens)
18861
+ };
18862
+ }
18863
+ var over = (r, unit) => r.requests_total === null || r.requests_over_100k === null ? "not recorded" : `${r.requests_over_100k} of ${r.requests_total}${unit} (${pct(r)})`;
18864
+ var pct = (r) => r.over_100k_share === null ? "n/a (no requests)" : `${(r.over_100k_share * 100).toFixed(1)}%`;
18865
+ function routePrLine(r) {
18866
+ if (!r.routed)
18867
+ return `Route: not routed (${r.reason})`;
18868
+ const adv = r.advisor ? `advisor ${r.advisor}` : "advisor unavailable";
18869
+ return `Route: executor ${r.executor}, ${adv}; advisor tokens ${rec(r.advisor_input_tokens)} in / ${rec(r.advisor_output_tokens)} out; over 100K: ${over(r, " requests")}`;
18870
+ }
18871
+ function routeReceiptLines(r) {
18872
+ if (!r.routed)
18873
+ return [`- Route: not routed (${r.reason})`, `- Route shape_parity: ${r.shape_parity}`];
18874
+ return [
18875
+ `- Route: executor ${r.executor}, ${r.advisor ? `advisor ${r.advisor}` : `advisor unavailable: ${r.advisor_unavailable_reason}`}: ${r.reason}`,
18876
+ `- Route shape_key: ${r.shape_key ?? "unknown"} shape_parity: ${r.shape_parity}`,
18877
+ `- Route escalations: ${r.escalations.length === 0 ? "none" : r.escalations.map((e) => `${e.from} -> ${e.to} (${e.trigger}; evidence ${e.evidence})`).join("; ")}`,
18878
+ `- Route advisor: ${rec(r.advisor_calls)} calls, ${rec(r.advisor_input_tokens)} in / ${rec(r.advisor_output_tokens)} out tokens`,
18879
+ ...r.units.map((u) => `- Route unit ${u.id}: executor ${u.executor}, assigned by ${u.assigned_by}: ${u.reason}; escalation: ${u.escalations.length === 0 ? "none" : u.escalations.map((e) => `${e.from} -> ${e.to} (${e.trigger})`).join(", ")}`),
18880
+ `- Route requests over 100K: ${over(r, "")}`
18881
+ ];
18882
+ }
18883
+ function routeNotProven(r) {
18884
+ return [
18885
+ ...r.advisor_unavailable_reason ? [`advisor: NOT PROVEN (owner provider): ${r.advisor_unavailable_reason}`] : [],
18886
+ `route.shape_parity: ${r.shape_parity}`
18887
+ ];
18888
+ }
18889
+
18890
+ // ../../loki-ts/src/engine10/cost.ts
18891
+ import { mkdirSync as mkdirSync8, readdirSync as readdirSync10, readFileSync as readFileSync23, writeFileSync as writeFileSync11 } from "fs";
18892
+ import { join as join33 } from "path";
18893
+ var UNMETERED = "cli-invoker-unmetered";
18894
+ function routerTelemetryOn(env = process.env) {
18895
+ return routerEnabled(env);
18896
+ }
18897
+ function num3(v) {
18898
+ return typeof v === "number" && Number.isFinite(v) ? v : 0;
18899
+ }
18900
+ function resultCostPath(lokiRoot, iteration) {
18901
+ return join33(lokiRoot, "metrics", `result-cost-${iteration}.json`);
18902
+ }
18903
+ function sumResultCosts(lokiRoot, iterations) {
18904
+ const out2 = {
18905
+ usd: null,
18906
+ partialUsd: 0,
18907
+ measuredCount: 0,
18908
+ totalCount: iterations.length,
18909
+ input_tokens: 0,
18910
+ output_tokens: 0,
18911
+ cache_read_tokens: 0,
18912
+ cache_creation_tokens: 0,
18913
+ ...routerTelemetryOn() ? { router: {
18914
+ requests_total: 0,
18915
+ requests_over_100k: 0,
18916
+ over_100k_input_tokens: 0,
18917
+ over_100k_output_tokens: 0,
18918
+ advisor_calls: 0,
18919
+ advisor_input_tokens: 0,
18920
+ advisor_output_tokens: 0
18921
+ } } : {},
18922
+ model: null,
18923
+ source: "",
18924
+ missing: []
18925
+ };
18926
+ const sources2 = [];
18927
+ let usd = 0;
18928
+ for (const iter of iterations) {
18929
+ const path = resultCostPath(lokiRoot, iter);
18930
+ let rec2;
18931
+ try {
18932
+ rec2 = JSON.parse(readFileSync23(path, "utf8"));
18933
+ } catch {
18934
+ out2.missing.push(iter);
18935
+ continue;
18936
+ }
18937
+ const inTok = num3(rec2["input_tokens"]);
18938
+ const outTok = num3(rec2["output_tokens"]);
18939
+ const cacheR = num3(rec2["cache_read_tokens"]);
18940
+ const cacheC = num3(rec2["cache_creation_tokens"]);
18941
+ out2.input_tokens += inTok;
18942
+ out2.output_tokens += outTok;
18943
+ out2.cache_read_tokens += cacheR;
18944
+ out2.cache_creation_tokens += cacheC;
18945
+ if (out2.router)
18946
+ out2.router["requests_total"] += num3(rec2["requests_total"]);
18947
+ if (out2.router)
18948
+ out2.router["requests_over_100k"] += num3(rec2["requests_over_100k"]);
18949
+ if (out2.router)
18950
+ out2.router["over_100k_input_tokens"] += num3(rec2["over_100k_input_tokens"]);
18951
+ if (out2.router)
18952
+ out2.router["over_100k_output_tokens"] += num3(rec2["over_100k_output_tokens"]);
18953
+ if (out2.router)
18954
+ out2.router["advisor_calls"] += num3(rec2["advisor_calls"]);
18955
+ if (out2.router)
18956
+ out2.router["advisor_input_tokens"] += num3(rec2["advisor_input_tokens"]);
18957
+ if (out2.router)
18958
+ out2.router["advisor_output_tokens"] += num3(rec2["advisor_output_tokens"]);
18959
+ if (typeof rec2["model"] === "string" && rec2["model"])
18960
+ out2.model = rec2["model"];
18961
+ sources2.push(path);
18962
+ const c = rec2["total_cost_usd"];
18963
+ const unmetered = rec2["source"] === UNMETERED;
18964
+ if (unmetered)
18965
+ out2.unmetered = true;
18966
+ const noUsage = !unmetered && inTok === 0 && outTok === 0 && cacheR === 0 && cacheC === 0;
18967
+ if (typeof c !== "number" || !Number.isFinite(c) || noUsage) {
18968
+ out2.missing.push(iter);
18969
+ continue;
18970
+ }
18971
+ usd += c;
18972
+ out2.partialUsd += c;
18973
+ out2.measuredCount++;
18974
+ }
18975
+ out2.source = sources2.join(",");
18976
+ if (iterations.length > 0 && out2.missing.length === 0)
18977
+ out2.usd = usd;
18978
+ return out2;
18979
+ }
18980
+
18800
18981
  // ../../loki-ts/src/util/check_result.ts
18801
18982
  var NO_TESTS_REASON = "no tests executed";
18802
18983
  var UNCONFIRMED_REASON = "test count could not be confirmed";
@@ -18805,8 +18986,8 @@ var isExecutedProof = (c) => c.result === "pass" && typeof c.n === "number" && c
18805
18986
  var hasExecutedProof = (checks) => checks.some(isExecutedProof);
18806
18987
 
18807
18988
  // ../../loki-ts/src/features/contract.ts
18808
- import { existsSync as existsSync19, lstatSync as lstatSync8, mkdirSync as mkdirSync8, readFileSync as readFileSync23, writeFileSync as writeFileSync11 } from "fs";
18809
- import { dirname as dirname11, join as join33 } from "path";
18989
+ import { existsSync as existsSync19, lstatSync as lstatSync8, mkdirSync as mkdirSync9, readFileSync as readFileSync24, writeFileSync as writeFileSync12 } from "fs";
18990
+ import { dirname as dirname11, join as join34 } from "path";
18810
18991
  import { createHash as createHash7 } from "crypto";
18811
18992
  var MAX_CRITERIA = 50;
18812
18993
  var MAX_TEXT = 500;
@@ -18841,7 +19022,7 @@ function untracedLines(trace) {
18841
19022
  return trace.criteria.filter((c) => c.status === "no_match").map((c) => `contract ${sanitizeCriterion(c.id)} untraced (no keyword match in changed files): ${sanitizeCriterion(c.text)}`);
18842
19023
  }
18843
19024
  function contractPath(repoDir) {
18844
- return join33(repoDir, ".loki", "contract.json");
19025
+ return join34(repoDir, ".loki", "contract.json");
18845
19026
  }
18846
19027
  var MAX_CONTRACT_BYTES = 1024 * 1024;
18847
19028
  function readContract(repoDir) {
@@ -18858,7 +19039,7 @@ function readContract(repoDir) {
18858
19039
  return { contract: null, notes: ["contract unreadable: too large"], sha256: null };
18859
19040
  let raw2;
18860
19041
  try {
18861
- raw2 = readFileSync23(p);
19042
+ raw2 = readFileSync24(p);
18862
19043
  } catch {
18863
19044
  return { contract: null, notes: ["contract unreadable: read failed"], sha256: null };
18864
19045
  }
@@ -18922,31 +19103,31 @@ function sealContract(repoDir, body, rawDiff, checks, env = process.env, snap) {
18922
19103
 
18923
19104
  // ../../loki-ts/src/features/speed/seal_group.ts
18924
19105
  import { createHash as createHash8 } from "crypto";
18925
- import { existsSync as existsSync20, readdirSync as readdirSync10, readFileSync as readFileSync24, statSync as statSync12 } from "fs";
18926
- import { dirname as dirname12, join as join34 } from "path";
19106
+ import { existsSync as existsSync20, readdirSync as readdirSync11, readFileSync as readFileSync25, statSync as statSync12 } from "fs";
19107
+ import { dirname as dirname12, join as join35 } from "path";
18927
19108
  var ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
18928
19109
  var PASSING = new Set(["VERIFIED", "ALREADY_SATISFIED"]);
18929
19110
  var sha2 = (b) => createHash8("sha256").update(b).digest("hex");
18930
19111
  var isObj10 = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
18931
19112
  var text2 = (v, cap) => typeof v === "string" ? v.replace(/[\x00-\x1f\x7f]+/g, " ").trim().slice(0, cap) : "";
18932
- var num3 = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : 0;
18933
- var unitsDir = (runDir) => join34(runDir, "group", "units");
19113
+ var num4 = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : 0;
19114
+ var unitsDir = (runDir) => join35(runDir, "group", "units");
18934
19115
  var readJson3 = (p) => {
18935
19116
  try {
18936
- return JSON.parse(readFileSync24(p, "utf8"));
19117
+ return JSON.parse(readFileSync25(p, "utf8"));
18937
19118
  } catch {
18938
19119
  return;
18939
19120
  }
18940
19121
  };
18941
19122
  var dirNames = (d) => {
18942
19123
  try {
18943
- return readdirSync10(d).filter((n2) => !n2.startsWith(".")).sort();
19124
+ return readdirSync11(d).filter((n2) => !n2.startsWith(".")).sort();
18944
19125
  } catch {
18945
19126
  return null;
18946
19127
  }
18947
19128
  };
18948
19129
  function sealGroup(runDir, rh) {
18949
- const manifestPath = join34(runDir, "group", "manifest.json");
19130
+ const manifestPath = join35(runDir, "group", "manifest.json");
18950
19131
  if (!existsSync20(manifestPath))
18951
19132
  return { section: undefined, notProven: [], problems: 0, allUnitsPass: true };
18952
19133
  const notProven = [];
@@ -18971,10 +19152,10 @@ function sealGroup(runDir, rh) {
18971
19152
  return fail(`unit ${index2} has an invalid, duplicate or case-colliding id`);
18972
19153
  seen.add(id);
18973
19154
  seenLower.add(id.toLowerCase());
18974
- const dir = join34(unitsDir(runDir), id), rp = join34(dir, "receipt.json"), ep = join34(dir, "events.jsonl");
19155
+ const dir = join35(unitsDir(runDir), id), rp = join35(dir, "receipt.json"), ep = join35(dir, "events.jsonl");
18975
19156
  let bytes;
18976
19157
  try {
18977
- bytes = readFileSync24(rp);
19158
+ bytes = readFileSync25(rp);
18978
19159
  } catch {
18979
19160
  return fail(`unit ${id} sub-receipt missing`);
18980
19161
  }
@@ -18991,12 +19172,12 @@ function sealGroup(runDir, rh) {
18991
19172
  unit_id: id,
18992
19173
  sub_receipt_sha256: sha2(bytes),
18993
19174
  receipt_sha256: sub["receipt_sha256"],
18994
- events_file_sha256: existsSync20(ep) ? sha2(readFileSync24(ep)) : null,
19175
+ events_file_sha256: existsSync20(ep) ? sha2(readFileSync25(ep)) : null,
18995
19176
  verdict,
18996
19177
  goal: text2(u["goal"], 200),
18997
19178
  files: (Array.isArray(u["files"]) ? u["files"] : []).map((f) => text2(f, 200)).filter(Boolean).slice(0, 50),
18998
- tests: num3(u["tests"]),
18999
- tokens: num3(u["tokens"]),
19179
+ tests: num4(u["tests"]),
19180
+ tokens: num4(u["tokens"]),
19000
19181
  model: text2(u["model"], 64)
19001
19182
  });
19002
19183
  });
@@ -19016,7 +19197,7 @@ async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
19016
19197
  const bad = (reason) => ({ verdict: "TAMPERED", reason: `group: ${reason}` });
19017
19198
  const g = receipt["group"];
19018
19199
  if (g === undefined)
19019
- return existsSync20(join34(runDir, "group", "manifest.json")) ? bad("group directory present but the receipt has no group section") : null;
19200
+ return existsSync20(join35(runDir, "group", "manifest.json")) ? bad("group directory present but the receipt has no group section") : null;
19020
19201
  if (!isObj10(g) || !ID_RE.test(String(g["group_id"] ?? "")) || !Array.isArray(g["units"]) || g["units"].length === 0)
19021
19202
  return bad("group section malformed");
19022
19203
  const entries = g["units"];
@@ -19028,20 +19209,20 @@ async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
19028
19209
  return bad("unit directories do not match the receipt (missing or extra unit)");
19029
19210
  let unchecked = null;
19030
19211
  for (let i = 0;i < entries.length; i++) {
19031
- const e = entries[i], id = ids[i], dir = join34(unitsDir(runDir), id), rp = join34(dir, "receipt.json"), ep = join34(dir, "events.jsonl");
19212
+ const e = entries[i], id = ids[i], dir = join35(unitsDir(runDir), id), rp = join35(dir, "receipt.json"), ep = join35(dir, "events.jsonl");
19032
19213
  if (e["index"] !== i)
19033
19214
  return bad(`unit ${id} is out of order (index ${String(e["index"])} at position ${i})`);
19034
19215
  let bytes;
19035
19216
  try {
19036
19217
  if (!statSync12(dir).isDirectory())
19037
19218
  return bad(`unit ${id} is not a directory`);
19038
- bytes = readFileSync24(rp);
19219
+ bytes = readFileSync25(rp);
19039
19220
  } catch {
19040
19221
  return bad(`unit ${id} sub-receipt missing`);
19041
19222
  }
19042
19223
  if (sha2(bytes) !== e["sub_receipt_sha256"])
19043
19224
  return bad(`unit ${id} sub-receipt does not match its recorded hash`);
19044
- const evSha = existsSync20(ep) ? sha2(readFileSync24(ep)) : null;
19225
+ const evSha = existsSync20(ep) ? sha2(readFileSync25(ep)) : null;
19045
19226
  if (evSha !== (e["events_file_sha256"] ?? null))
19046
19227
  return bad(`unit ${id} events.jsonl does not match its recorded hash`);
19047
19228
  const sub = readJson3(rp);
@@ -19096,9 +19277,9 @@ function loadSigningKey(generate = true) {
19096
19277
  let pem = inline ?? "";
19097
19278
  if (!inline) {
19098
19279
  const given = process.env["LOKI_RECEIPT_SIGNING_KEY_FILE"]?.trim();
19099
- const file = given || join35(process.env["HOME"] || homedir7(), ".loki", "keys", RECEIPT_SIGNER_BASENAME);
19280
+ const file = given || join36(process.env["HOME"] || homedir7(), ".loki", "keys", RECEIPT_SIGNER_BASENAME);
19100
19281
  try {
19101
- pem = readFileSync25(file);
19282
+ pem = readFileSync26(file);
19102
19283
  if (!given) {
19103
19284
  for (const [f, m] of [[file, 384], [dirname13(file), 448]])
19104
19285
  if (statSync13(f).mode & 63)
@@ -19107,10 +19288,10 @@ function loadSigningKey(generate = true) {
19107
19288
  } catch (e) {
19108
19289
  if (e.code !== "ENOENT" || !generate)
19109
19290
  return null;
19110
- mkdirSync9(dirname13(dirname13(file)), { recursive: true, mode: 448 });
19111
- mkdirSync9(dirname13(file), { recursive: true, mode: 448 });
19291
+ mkdirSync10(dirname13(dirname13(file)), { recursive: true, mode: 448 });
19292
+ mkdirSync10(dirname13(file), { recursive: true, mode: 448 });
19112
19293
  const tmp = `${file}.${randomBytes3(6).toString("hex")}.tmp`;
19113
- writeFileSync12(tmp, generateKeyPairSync("ed25519").privateKey.export({ type: "pkcs8", format: "pem" }), { flag: "wx", mode: 384 });
19294
+ writeFileSync13(tmp, generateKeyPairSync("ed25519").privateKey.export({ type: "pkcs8", format: "pem" }), { flag: "wx", mode: 384 });
19114
19295
  try {
19115
19296
  linkSync(tmp, file);
19116
19297
  } catch (l) {
@@ -19119,7 +19300,7 @@ function loadSigningKey(generate = true) {
19119
19300
  } finally {
19120
19301
  unlinkSync4(tmp);
19121
19302
  }
19122
- pem = readFileSync25(file);
19303
+ pem = readFileSync26(file);
19123
19304
  }
19124
19305
  }
19125
19306
  const k = createPrivateKey(pem);
@@ -19215,6 +19396,7 @@ function renderReceiptMd(r) {
19215
19396
  `- receipt_sha256: ${r.receipt_sha256}`,
19216
19397
  `- Signature: ${sig}`,
19217
19398
  `- Provider: ${r.provider} (${r.model}) Cost: ${usd} Wall: ${r.time.wall_s}s`,
19399
+ ...r.route ? routeReceiptLines(r.route) : [],
19218
19400
  "",
19219
19401
  "### Checks",
19220
19402
  ...r.checks.length ? r.checks.map((c) => `- ${c.result}: ${c.name} (\`${c.cmd}\`, ${c.duration_s}s)`) : ["- none"],
@@ -19263,7 +19445,7 @@ var sealStage = {
19263
19445
  if (wallNotRun > 0) {
19264
19446
  try {
19265
19447
  const kept = new Set((Array.isArray(o.wall?.files) ? o.wall.files : []).map((f) => basename11(String(f.path))));
19266
- for (const n2 of readdirSync11(join35(ctx.runDir, "wall")).sort())
19448
+ for (const n2 of readdirSync12(join36(ctx.runDir, "wall")).sort())
19267
19449
  if (!kept.has(n2))
19268
19450
  notProven.add(`wall test discarded: ${n2} (not_run)`);
19269
19451
  } catch {}
@@ -19326,11 +19508,15 @@ var sealStage = {
19326
19508
  const cost = ctx.cost.read(ctx.repoDir, iterIds);
19327
19509
  if (cost.unmetered)
19328
19510
  notProven.add("cost unmetered (CLI invoker; recorded as 0)");
19329
- const eventsPath = join35(ctx.runDir, "events.jsonl");
19511
+ const eventsPath = join36(ctx.runDir, "events.jsonl");
19330
19512
  const wallFiles = Array.isArray(o.wall?.files) ? o.wall.files : [];
19331
19513
  const wallPassed = typeof o.verify?.wall_passed === "boolean" ? o.verify.wall_passed : null;
19332
19514
  if (wallFiles.length > 0 && wallPassed === null)
19333
19515
  notProven.add("wall result not recorded by verify");
19516
+ const routeBlock = buildRouteBlock(process.env, ctx.provider, o.implement?.route, cost.router ?? (routerEnabled(process.env) ? sumResultCosts(join36(ctx.repoDir, ".loki"), iterIds).router : undefined));
19517
+ if (routeBlock)
19518
+ for (const l of routeNotProven(routeBlock))
19519
+ notProven.add(l);
19334
19520
  const body = {
19335
19521
  schema: "loki.v10.receipt/1",
19336
19522
  run_id: ctx.runId,
@@ -19363,9 +19549,10 @@ var sealStage = {
19363
19549
  provider: ctx.provider,
19364
19550
  model: ctx.model,
19365
19551
  resumed: o.intake?.resumed === true,
19366
- events_sha256: sha2562(existsSync21(eventsPath) ? readFileSync25(eventsPath) : ""),
19552
+ events_sha256: sha2562(existsSync21(eventsPath) ? readFileSync26(eventsPath) : ""),
19367
19553
  ...await sealEvidence(ctx.repoDir, ctx.runDir, o, notProven, signal, ctx.emit),
19368
- log_seal: true
19554
+ log_seal: true,
19555
+ ...routeBlock ? { route: routeBlock } : {}
19369
19556
  };
19370
19557
  for (const l of sealContract(ctx.repoDir, body, rawDiff, checks, process.env, o.intake?.contract_snapshot))
19371
19558
  notProven.add(l);
@@ -19377,21 +19564,21 @@ var sealStage = {
19377
19564
  hash = receiptSha256(body);
19378
19565
  }
19379
19566
  const receipt = { ...body, receipt_sha256: hash, verification: { jwt: sig.jwt, kid: sig.kid } };
19380
- mkdirSync9(ctx.runDir, { recursive: true });
19381
- const path = join35(ctx.runDir, "receipt.json");
19382
- writeFileSync12(path, JSON.stringify(receipt, null, 2) + `
19567
+ mkdirSync10(ctx.runDir, { recursive: true });
19568
+ const path = join36(ctx.runDir, "receipt.json");
19569
+ writeFileSync13(path, JSON.stringify(receipt, null, 2) + `
19383
19570
  `);
19384
- writeFileSync12(join35(ctx.runDir, "receipt.md"), renderReceiptMd(receipt));
19571
+ writeFileSync13(join36(ctx.runDir, "receipt.md"), renderReceiptMd(receipt));
19385
19572
  const signed = sig.jwt !== null;
19386
- const data = { receipt_path: path, receipt_sha256: hash, signed, kid: sig.kid, verdict, not_proven: receipt.not_proven };
19387
- ctx.emit("receipt.sealed", "seal", { path, receipt_sha256: hash, signed, kid: sig.kid, verdict, not_proven: receipt.not_proven });
19573
+ const data = { receipt_path: path, receipt_sha256: hash, signed, kid: sig.kid, verdict, not_proven: receipt.not_proven, ...routeBlock ? { route_line: routePrLine(routeBlock) } : {} };
19574
+ ctx.emit("receipt.sealed", "seal", { path, receipt_sha256: hash, signed, kid: sig.kid, verdict, not_proven: receipt.not_proven, ...routeBlock ? { route_line: routePrLine(routeBlock) } : {} });
19388
19575
  return { status: "completed", data: { ...data, summary: `${verdict} receipt ${hash.slice(0, 12)} ${signed ? `SIGNED kid ${sig.kid}` : "UNSIGNED"}` } };
19389
19576
  }
19390
19577
  };
19391
19578
 
19392
19579
  // ../../loki-ts/src/features/receipt_dsse.ts
19393
19580
  import { createPublicKey as createPublicKey3, sign as sign2, verify as verify2 } from "crypto";
19394
- import { readFileSync as readFileSync26 } from "fs";
19581
+ import { readFileSync as readFileSync27 } from "fs";
19395
19582
  var DSSE_PAYLOAD_TYPE = "application/vnd.in-toto+json";
19396
19583
  var STATEMENT_TYPE = "https://in-toto.io/Statement/v1";
19397
19584
  var PREDICATE_TYPE = "https://autonomi.dev/loki/receipt/v10";
@@ -19472,7 +19659,7 @@ function verifyDsseReceipt(env, d) {
19472
19659
  }
19473
19660
  function runIdGuard(receiptPath, runId) {
19474
19661
  try {
19475
- return envelopeRunIdProblem(JSON.parse(readFileSync26(receiptPath, "utf8")), runId);
19662
+ return envelopeRunIdProblem(JSON.parse(readFileSync27(receiptPath, "utf8")), runId);
19476
19663
  } catch {
19477
19664
  return null;
19478
19665
  }
@@ -19486,7 +19673,7 @@ function pubFor(kid, given) {
19486
19673
  const active = loadSigningKey(false);
19487
19674
  const pubs = (process.env["LOKI_RECEIPT_RETIRED_PUBKEYS"] ?? "").split(":").map((f) => f.trim()).filter(Boolean).flatMap((f) => {
19488
19675
  try {
19489
- return [createPublicKey4(readFileSync27(f))];
19676
+ return [createPublicKey4(readFileSync28(f))];
19490
19677
  } catch {
19491
19678
  return [];
19492
19679
  }
@@ -19518,10 +19705,10 @@ function checkEventLog(receiptPath, receipt) {
19518
19705
  const bound = receipt["events_sha256"];
19519
19706
  if (typeof bound !== "string" || bound === createHash10("sha256").digest("hex"))
19520
19707
  return null;
19521
- const path = join36(dirname14(receiptPath), "events.jsonl");
19708
+ const path = join37(dirname14(receiptPath), "events.jsonl");
19522
19709
  if (!existsSync22(path))
19523
19710
  return "events.jsonl is missing";
19524
- const raw2 = readFileSync27(path, "utf8"), events2 = readEvents(path), lines = raw2.split(`
19711
+ const raw2 = readFileSync28(path, "utf8"), events2 = readEvents(path), lines = raw2.split(`
19525
19712
  `).filter((l) => l.trim() !== "");
19526
19713
  if (events2.length !== lines.length || events2.some((e, i) => e.seq !== i))
19527
19714
  return "events.jsonl has a forged, edited or missing line";
@@ -19537,7 +19724,7 @@ function checkEventLog(receiptPath, receipt) {
19537
19724
  return h.digest("hex") === bound ? null : "events.jsonl does not match the hash recorded at seal";
19538
19725
  }
19539
19726
  function checkLogSeal(receiptPath, hash, kid, given) {
19540
- const path = join36(dirname14(receiptPath), "events.jsonl"), events2 = readEvents(path), done = events2.findIndex((e) => e.type === "run.completed");
19727
+ const path = join37(dirname14(receiptPath), "events.jsonl"), events2 = readEvents(path), done = events2.findIndex((e) => e.type === "run.completed");
19541
19728
  if (!events2.some((e) => e.type === "receipt.sealed" && e.data["receipt_sha256"] === hash))
19542
19729
  return { verdict: "TAMPERED", reason: "events.jsonl has no receipt.sealed event for this receipt" };
19543
19730
  if (done < 0)
@@ -19545,7 +19732,7 @@ function checkLogSeal(receiptPath, hash, kid, given) {
19545
19732
  const seal = events2[done + 1], d = seal?.type === "log.sealed" ? seal.data : null;
19546
19733
  if (!d)
19547
19734
  return { verdict: "TAMPERED", reason: "events.jsonl has no signed log.sealed line after run.completed" };
19548
- const lines = readFileSync27(path, "utf8").split(`
19735
+ const lines = readFileSync28(path, "utf8").split(`
19549
19736
  `).filter((l) => l.trim() !== ""), sha3 = createHash10("sha256").update(lines.slice(0, done + 1).join(`
19550
19737
  `) + `
19551
19738
  `).digest("hex");
@@ -19559,7 +19746,7 @@ async function verifyReceipt(receiptPath, deps = {}) {
19559
19746
  return { verdict: "UNCHECKED", reasons: [`receipt not found: ${receiptPath}`] };
19560
19747
  let receipt;
19561
19748
  try {
19562
- receipt = JSON.parse((deps.read ?? ((p) => readFileSync27(p, "utf8")))(receiptPath));
19749
+ receipt = JSON.parse((deps.read ?? ((p) => readFileSync28(p, "utf8")))(receiptPath));
19563
19750
  } catch {
19564
19751
  return { verdict: "UNCHECKED", reasons: ["receipt.json is not valid JSON"] };
19565
19752
  }
@@ -19627,11 +19814,11 @@ function mount21(ctx) {
19627
19814
  return done(404, "receipt not available", "not_found");
19628
19815
  let runDir, file;
19629
19816
  try {
19630
- const root = realpathSync17(join37(repo.p, ".loki", "runs"));
19631
- runDir = realpathSync17(join37(root, run2));
19632
- if (runDir !== join37(root, run2))
19817
+ const root = realpathSync17(join38(repo.p, ".loki", "runs"));
19818
+ runDir = realpathSync17(join38(root, run2));
19819
+ if (runDir !== join38(root, run2))
19633
19820
  return done(404, "receipt not found", "not_found");
19634
- file = realpathSync17(join37(runDir, "receipt.json"));
19821
+ file = realpathSync17(join38(runDir, "receipt.json"));
19635
19822
  } catch {
19636
19823
  return done(404, "receipt not found", "not_found");
19637
19824
  }
@@ -19650,7 +19837,7 @@ function mount21(ctx) {
19650
19837
  sha3 = r.receiptSha256 ?? null;
19651
19838
  }
19652
19839
  try {
19653
- outcome = outcomeOf(JSON.parse(readFileSync28(file, "utf8")));
19840
+ outcome = outcomeOf(JSON.parse(readFileSync29(file, "utf8")));
19654
19841
  } catch {
19655
19842
  outcome = "UNREADABLE";
19656
19843
  }
@@ -19712,8 +19899,8 @@ function ttlCache(ttlMs = PROBE_CACHE_MS, now2 = Date.now) {
19712
19899
  }
19713
19900
 
19714
19901
  // src/server/legacy/shim.ts
19715
- import { existsSync as existsSync23, readFileSync as readFileSync29 } from "fs";
19716
- import { join as join38 } from "path";
19902
+ import { existsSync as existsSync23, readFileSync as readFileSync30 } from "fs";
19903
+ import { join as join39 } from "path";
19717
19904
 
19718
19905
  // src/server/legacy/routes.ts
19719
19906
  var LEGACY_ROUTES = [
@@ -20085,10 +20272,10 @@ var logged = new Set;
20085
20272
  var toHono = (p) => p.replace(/\{([A-Za-z_]+):path\}/g, ":$1{.+}").replace(/\{([A-Za-z_]+)\}/g, ":$1");
20086
20273
  var NOT_SUPPORTED = "not yet supported by the Control Plane";
20087
20274
  var repoVersion = () => {
20088
- for (const f of [join38(import.meta.dir, "../../../../../VERSION")]) {
20275
+ for (const f of [join39(import.meta.dir, "../../../../../VERSION")]) {
20089
20276
  try {
20090
20277
  if (existsSync23(f))
20091
- return readFileSync29(f, "utf8").trim();
20278
+ return readFileSync30(f, "utf8").trim();
20092
20279
  } catch {}
20093
20280
  }
20094
20281
  return "unknown";
@@ -20270,7 +20457,7 @@ function legacyShim(opts) {
20270
20457
 
20271
20458
  // src/server/app.ts
20272
20459
  var MAX_BODY2 = 1e6;
20273
- var defaultUiDir = () => [join39(import.meta.dir, "../../ui/dist"), join39(import.meta.dir, "../ui/dist")].find((d) => existsSync24(join39(d, "index.html")));
20460
+ var defaultUiDir = () => [join40(import.meta.dir, "../../ui/dist"), join40(import.meta.dir, "../ui/dist")].find((d) => existsSync24(join40(d, "index.html")));
20274
20461
  function createApp(opts) {
20275
20462
  const uiDir = opts.uiDir ?? defaultUiDir();
20276
20463
  const { db, sqlite } = openDb(opts.dbPath);
@@ -20299,10 +20486,10 @@ function createApp(opts) {
20299
20486
  await next();
20300
20487
  });
20301
20488
  const readInstalled = () => {
20302
- for (const f of [process.env.LOKI_VERSION_FILE, join39(import.meta.dir, "../../../../VERSION")]) {
20489
+ for (const f of [process.env.LOKI_VERSION_FILE, join40(import.meta.dir, "../../../../VERSION")]) {
20303
20490
  try {
20304
20491
  if (f)
20305
- return readFileSync30(f, "utf8").trim() || "unknown";
20492
+ return readFileSync31(f, "utf8").trim() || "unknown";
20306
20493
  } catch {}
20307
20494
  }
20308
20495
  return "unknown";
@@ -20417,7 +20604,7 @@ function createApp(opts) {
20417
20604
  return new Response(Bun.file(f));
20418
20605
  if (/\.[a-z0-9]+$/i.test(p))
20419
20606
  return c.json({ error: "not found" }, 404);
20420
- return new Response(Bun.file(join39(root, "index.html")));
20607
+ return new Response(Bun.file(join40(root, "index.html")));
20421
20608
  });
20422
20609
  return { app, db, close: () => {
20423
20610
  clearInterval(reconciler);
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
3
3
  "name": "loki-mode",
4
4
  "displayName": "Loki Mode",
5
- "version": "11.2.0",
5
+ "version": "11.2.2",
6
6
  "description": "Autonomous spec-to-product build system with a built-in trust layer (RARV-C closure loop, 8 quality gates, completion council). Ships Loki's spec-hardening, drift-detection, and deterministic PR verification commands plus the Loki MCP server.",
7
7
  "author": {
8
8
  "name": "Autonomi",
@@ -1,4 +1,4 @@
1
- import{c as L,r as x,j as e,w as re,Z as ne,m as le,h as ie,p as P,F as ye,U as I,X as ce,L as de,x as oe,M as Ae,T as Z,S as we,l as xe,k as me,y as Ce,E as Fe,a0 as Se,a as U,a2 as he}from"./index-83w75NC1.js";import{B as C}from"./Button-BpGXXEPk.js";import{T as $e}from"./trending-up-BvdD9XmQ.js";import{C as z}from"./clock-BUUN5rWU.js";import{A as Be,U as ue,M as De}from"./Avatar-Dmf_rtmv.js";import{A as J}from"./activity-DW6jRbjj.js";import{R as pe}from"./refresh-cw-DJL2nFq0.js";import{G as ze}from"./globe-BV7yxcQ_.js";import{C as Le}from"./chevron-left-Djgr5pg-.js";import{C as je}from"./check-BVC4A8YK.js";import{D as Y}from"./dollar-sign-CBx9DWbM.js";import{U as Te}from"./user-CWmKQURs.js";import{D as Me}from"./database-DUauMcIC.js";import{L as Ue}from"./lock-DbvZW7dV.js";import{S as Re}from"./scroll-text-CAMgtDYH.js";import{S as Ie}from"./shield-alert-DqQ5wzQ6.js";/**
1
+ import{c as L,r as x,j as e,w as re,Z as ne,m as le,h as ie,p as P,F as ye,U as I,X as ce,L as de,x as oe,M as Ae,T as Z,S as we,l as xe,k as me,y as Ce,E as Fe,a0 as Se,a as U,a2 as he}from"./index-BcXljIAO.js";import{B as C}from"./Button-_iHlH_yL.js";import{T as $e}from"./trending-up-BIiwQbWV.js";import{C as z}from"./clock-COzFIiWi.js";import{A as Be,U as ue,M as De}from"./Avatar-C7VUvwsO.js";import{A as J}from"./activity-CPyi45gt.js";import{R as pe}from"./refresh-cw-D3dWHBd6.js";import{G as ze}from"./globe-CPlrM_IC.js";import{C as Le}from"./chevron-left-CkxonN0X.js";import{C as je}from"./check-DPj99ArM.js";import{D as Y}from"./dollar-sign-CVcApzcD.js";import{U as Te}from"./user-kGzXC3V2.js";import{D as Me}from"./database-D555S5Km.js";import{L as Ue}from"./lock-B9t6oWI0.js";import{S as Re}from"./scroll-text-ktmD_xJY.js";import{S as Ie}from"./shield-alert-968j9z0V.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as l,j as s}from"./index-83w75NC1.js";/**
1
+ import{c as l,j as s}from"./index-BcXljIAO.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.