loki-mode 11.17.6 → 11.17.13

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 (84) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/lib/cost-summary.py +5 -2
  4. package/autonomy/lib/efficiency_cost.py +21 -1
  5. package/autonomy/lib/proof-generator.py +5 -0
  6. package/autonomy/lib/proof-template.html +21 -6
  7. package/autonomy/lib/trust_trajectory.py +11 -1
  8. package/autonomy/loki +42 -28
  9. package/completions/_loki +1 -0
  10. package/completions/loki.bash +1 -1
  11. package/dashboard/__init__.py +1 -1
  12. package/docs/CLI-REFERENCE.md +1 -1
  13. package/docs/INSTALLATION.md +1 -1
  14. package/docs/v10/BOARD.md +108 -4
  15. package/docs/v10/FAILURE-CLASSES.md +106 -2
  16. package/docs/v10/MODERNIZE.md +7 -1
  17. package/docs/v10/PROGRESS.md +10 -0
  18. package/loki-ts/dist/loki.js +1014 -999
  19. package/mcp/__init__.py +1 -1
  20. package/package.json +2 -2
  21. package/packages/control-plane/dist/ask-tools-server.js +218 -12
  22. package/packages/control-plane/dist/server.js +719 -593
  23. package/packages/control-plane/src/server/diffstat.ts +2 -2
  24. package/packages/control-plane/src/server/routes/checkpoints.ts +2 -2
  25. package/packages/control-plane/src/server/routes/integrations.ts +1 -1
  26. package/packages/control-plane/src/shipper/discover.ts +2 -2
  27. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  28. package/web-app/dist/assets/{AdminPage-CCedYmn3.js → AdminPage-CwtSZac4.js} +1 -1
  29. package/web-app/dist/assets/{Avatar-DMrDsuGe.js → Avatar-BfguNHDC.js} +1 -1
  30. package/web-app/dist/assets/{Badge-K4Ui2tJz.js → Badge-DQGEOIqb.js} +1 -1
  31. package/web-app/dist/assets/{Button-Bhjts5QZ.js → Button-CRb-wJga.js} +1 -1
  32. package/web-app/dist/assets/{CockpitPage-Be7sEVqh.js → CockpitPage-DnA9wewN.js} +1 -1
  33. package/web-app/dist/assets/{ComparePage-D4ty3jiF.js → ComparePage-DX6F_G0l.js} +1 -1
  34. package/web-app/dist/assets/{ErrorBoundary-Cmt2x_mL.js → ErrorBoundary-VVIdgfkb.js} +1 -1
  35. package/web-app/dist/assets/{EvidenceReceiptPanel-D2IXLnp9.js → EvidenceReceiptPanel-FxknNXxU.js} +1 -1
  36. package/web-app/dist/assets/{GitHubIssuesPanel-CyXitr6h.js → GitHubIssuesPanel-DqiraoJP.js} +1 -1
  37. package/web-app/dist/assets/{GitHubPRsPanel-RRM3H-xd.js → GitHubPRsPanel-BYkTsRfQ.js} +1 -1
  38. package/web-app/dist/assets/{HomePage-CMtrrgfs.js → HomePage-BjpWZdl4.js} +2 -2
  39. package/web-app/dist/assets/{LoginPage-BrzNhnMJ.js → LoginPage-DdBnFY4Y.js} +1 -1
  40. package/web-app/dist/assets/{MagicPage-D7VynOKM.js → MagicPage-ihQmO1wm.js} +1 -1
  41. package/web-app/dist/assets/{MetricsPage-DJ-gDbfP.js → MetricsPage-Dq5YARm1.js} +1 -1
  42. package/web-app/dist/assets/{NotFoundPage-BJh0XVTj.js → NotFoundPage-CLzwsmxk.js} +1 -1
  43. package/web-app/dist/assets/{ProjectPage-CAodVUpE.js → ProjectPage-Dm8X4ntm.js} +3 -3
  44. package/web-app/dist/assets/{ProjectsPage-m3siS0Rf.js → ProjectsPage-DI3PhBwa.js} +1 -1
  45. package/web-app/dist/assets/{SettingsPage-CFGgjOvy.js → SettingsPage-D3bL3Ll-.js} +1 -1
  46. package/web-app/dist/assets/{ShowcasePage-Dd9tpSKJ.js → ShowcasePage-ypNyQAKe.js} +1 -1
  47. package/web-app/dist/assets/{SystemSettingsPage-DXd0PtTI.js → SystemSettingsPage-a9KPi49-.js} +1 -1
  48. package/web-app/dist/assets/{TeamsPage-C5KaLIGW.js → TeamsPage-B2KmQjeS.js} +1 -1
  49. package/web-app/dist/assets/{TemplatesPage-CDbzE0ZZ.js → TemplatesPage-BnK5NB62.js} +1 -1
  50. package/web-app/dist/assets/{TerminalOutput-CKG79r_-.js → TerminalOutput-CYbPu51X.js} +1 -1
  51. package/web-app/dist/assets/{activity-BaQQRhDp.js → activity-DBIfCcER.js} +1 -1
  52. package/web-app/dist/assets/{bell-OeFqvU4e.js → bell-B9HN4QkY.js} +1 -1
  53. package/web-app/dist/assets/{bot-CSxaA0KU.js → bot-DamtEiBN.js} +1 -1
  54. package/web-app/dist/assets/{check-DJml2Xdn.js → check-DXifl-uv.js} +1 -1
  55. package/web-app/dist/assets/{chevron-left-DGnt-DtK.js → chevron-left-BrlJBb8m.js} +1 -1
  56. package/web-app/dist/assets/{circle-alert-BV5rVL7K.js → circle-alert-CVKCTAb9.js} +1 -1
  57. package/web-app/dist/assets/{clock-CZ7SvULz.js → clock-HQ6E5gSp.js} +1 -1
  58. package/web-app/dist/assets/{cloud-lkIzrZps.js → cloud-B15Ysqug.js} +1 -1
  59. package/web-app/dist/assets/{code-xml-DzA2wL8F.js → code-xml-hqFIp0_h.js} +1 -1
  60. package/web-app/dist/assets/{database-CLFG5upC.js → database-CcSm0M_K.js} +1 -1
  61. package/web-app/dist/assets/{dollar-sign-DgWePGsv.js → dollar-sign-acxpddMc.js} +1 -1
  62. package/web-app/dist/assets/{file-code-corner-DGQX2bmv.js → file-code-corner-B5IIv12W.js} +1 -1
  63. package/web-app/dist/assets/{file-plus-LkaXeYd6.js → file-plus-CkbMFWJb.js} +1 -1
  64. package/web-app/dist/assets/{globe-rSsEzPYv.js → globe-CWmZ3xTF.js} +1 -1
  65. package/web-app/dist/assets/{hammer-CPogONt9.js → hammer-BSaCsCAo.js} +1 -1
  66. package/web-app/dist/assets/{index-DpBLuMuz.js → index-BCf0fCNu.js} +3 -3
  67. package/web-app/dist/assets/{layers-CwFaqidn.js → layers-CL82nJ3b.js} +1 -1
  68. package/web-app/dist/assets/{loader-circle-C43izEm5.js → loader-circle-DBhm8R7M.js} +1 -1
  69. package/web-app/dist/assets/{lock-Bc_Uqxpp.js → lock-wWcqImfq.js} +1 -1
  70. package/web-app/dist/assets/{package-BM25lcR-.js → package-BaZa22IO.js} +1 -1
  71. package/web-app/dist/assets/{plus-D0xoiY6N.js → plus-TFOQPEeK.js} +1 -1
  72. package/web-app/dist/assets/{refresh-cw-COI1R5Oo.js → refresh-cw-BOKfYIta.js} +1 -1
  73. package/web-app/dist/assets/{rotate-ccw-BoNZx4xe.js → rotate-ccw-DrH5oGwW.js} +1 -1
  74. package/web-app/dist/assets/{scroll-text-Cakp8XHd.js → scroll-text-aY8_wIJd.js} +1 -1
  75. package/web-app/dist/assets/{server-CjfIlPmE.js → server-C6FQ01rB.js} +1 -1
  76. package/web-app/dist/assets/{shield-alert-BilhziJF.js → shield-alert-DurYyWUo.js} +1 -1
  77. package/web-app/dist/assets/{thumbs-up-CglMrtrt.js → thumbs-up-wUuSs67Q.js} +1 -1
  78. package/web-app/dist/assets/{trash-2-B6zVvnoG.js → trash-2-DAob0LKZ.js} +1 -1
  79. package/web-app/dist/assets/{trending-down-BVhwD9bt.js → trending-down-yKL9mp2O.js} +1 -1
  80. package/web-app/dist/assets/{trending-up-CVJ1ox6c.js → trending-up-BD55eCE3.js} +1 -1
  81. package/web-app/dist/assets/{upload-DmuR09WL.js → upload-0IJxnT31.js} +1 -1
  82. package/web-app/dist/assets/{usePolling-BTALfO91.js → usePolling-DuBiboP5.js} +1 -1
  83. package/web-app/dist/assets/{user-CRdHMZNH.js → user-BDw_rGaY.js} +1 -1
  84. 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.17.6'
78
+ __version__ = '11.17.13'
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.17.6",
4
+ "version": "11.17.13",
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",
@@ -160,5 +160,5 @@
160
160
  "dependencies": {
161
161
  "@resvg/resvg-wasm": "^2.6.2"
162
162
  },
163
- "gitHead": "d84ef95684aa4aaf504f382d61688ec4868dbf11"
163
+ "gitHead": "850b7f67c8d0127282fb62751003071a8201a6e8"
164
164
  }
@@ -38908,7 +38908,7 @@ var askEvents = sqliteTable("ask_events", {
38908
38908
 
38909
38909
  // src/ask/tools.ts
38910
38910
  import { realpathSync as realpathSync3 } from "fs";
38911
- import { join as join4, sep as sep3 } from "path";
38911
+ import { join as join5, sep as sep3 } from "path";
38912
38912
 
38913
38913
  // node_modules/hono/dist/request/constants.js
38914
38914
  var GET_MATCH_RESULT = Symbol();
@@ -40694,6 +40694,213 @@ function computeStats(db, since) {
40694
40694
  };
40695
40695
  }
40696
40696
 
40697
+ // ../../loki-ts/src/util/credential_env.ts
40698
+ import { mkdtempSync, rmSync, statSync, lstatSync } from "fs";
40699
+ import { tmpdir } from "os";
40700
+ import { join as join3 } from "path";
40701
+ import { randomBytes } from "crypto";
40702
+ var GITHUB_TOKEN_VARS = ["GH_TOKEN", "GITHUB_TOKEN", "GH_ENTERPRISE_TOKEN", "GITHUB_ENTERPRISE_TOKEN"];
40703
+ var SENTINEL_PREFIX = "ghp_LOKIWITHHELDsentinel";
40704
+ var sentinel = null;
40705
+ var configDir = null;
40706
+ var exitHooked = false;
40707
+ var sigtermHooked = false;
40708
+ function withheldSentinel(fresh = false) {
40709
+ if (fresh)
40710
+ sentinel = null;
40711
+ return sentinel ??= `${SENTINEL_PREFIX}${process.pid}${randomBytes(8).toString("hex")}INVALID`;
40712
+ }
40713
+ var isDir = (p) => {
40714
+ try {
40715
+ return !lstatSync(p).isSymbolicLink() && statSync(p).isDirectory();
40716
+ } catch {
40717
+ return false;
40718
+ }
40719
+ };
40720
+ function removeConfigDir() {
40721
+ if (configDir)
40722
+ try {
40723
+ rmSync(configDir, { recursive: true, force: true });
40724
+ } catch {}
40725
+ }
40726
+ function emptyGhConfigDir(env = process.env) {
40727
+ if (configDir && isDir(configDir))
40728
+ return configDir;
40729
+ const runTmp = env["LOKI_RUN_TMP"] ?? "";
40730
+ const root = runTmp !== "" && isDir(runTmp) ? runTmp : tmpdir();
40731
+ try {
40732
+ configDir = mkdtempSync(join3(root, "loki-gh-config-"));
40733
+ } catch {
40734
+ return null;
40735
+ }
40736
+ if (!exitHooked) {
40737
+ exitHooked = true;
40738
+ process.once("exit", removeConfigDir);
40739
+ }
40740
+ if (!sigtermHooked) {
40741
+ sigtermHooked = true;
40742
+ process.prependListener("SIGTERM", () => {
40743
+ removeConfigDir();
40744
+ if (process.listenerCount("SIGTERM") === 1)
40745
+ process.exit(143);
40746
+ });
40747
+ }
40748
+ return configDir;
40749
+ }
40750
+ function hardenCredentialEnv(env, fresh = false) {
40751
+ const s = withheldSentinel(fresh);
40752
+ for (const v of GITHUB_TOKEN_VARS)
40753
+ env[v] = s;
40754
+ const dir = emptyGhConfigDir(env);
40755
+ if (dir)
40756
+ env["GH_CONFIG_DIR"] = dir;
40757
+ const existing = Number(env["GIT_CONFIG_COUNT"]);
40758
+ const n = Number.isInteger(existing) && existing >= 0 ? existing : 0;
40759
+ const alreadyLast = n > 0 && env[`GIT_CONFIG_KEY_${n - 1}`] === "credential.helper" && env[`GIT_CONFIG_VALUE_${n - 1}`] === "";
40760
+ if (!alreadyLast) {
40761
+ env[`GIT_CONFIG_KEY_${n}`] = "credential.helper";
40762
+ env[`GIT_CONFIG_VALUE_${n}`] = "";
40763
+ env["GIT_CONFIG_COUNT"] = String(n + 1);
40764
+ }
40765
+ const params = env["GIT_CONFIG_PARAMETERS"];
40766
+ if (params && !params.trimEnd().endsWith("'credential.helper'=''"))
40767
+ env["GIT_CONFIG_PARAMETERS"] = `${params} 'credential.helper'=''`;
40768
+ env["GIT_TERMINAL_PROMPT"] = "0";
40769
+ env["GCM_INTERACTIVE"] = "never";
40770
+ }
40771
+
40772
+ // ../../loki-ts/src/util/safe_git.ts
40773
+ import { execFileSync, spawnSync } from "child_process";
40774
+ var SAFE_GIT_CONFIG = ["-c", "core.fsmonitor=", "-c", "core.hooksPath=/dev/null", "-c", "core.sshCommand=", "-c", "protocol.ext.allow=never", "-c", "credential.helper="];
40775
+ var CREDENTIAL_CONFIG = ["-c", "core.fsmonitor=", "-c", "core.hooksPath=/dev/null", "-c", "protocol.ext.allow=never"];
40776
+ var DRIVER_CONFIG = ["-c", "diff.external=", "-c", "commit.gpgSign=false", "-c", "core.attributesFile=/dev/null"];
40777
+ var ATTRS_OFF = "core.attributesFile=/dev/null";
40778
+ var HOOKS_OFF = "core.hooksPath=/dev/null";
40779
+ var SIGN_OFF = "commit.gpgSign=false";
40780
+ var REPO_SCOPES = new Set(["local", "worktree", "command"]);
40781
+ var DRIVER_KEY_RE = "^(filter\\..*\\.(clean|smudge|process)|diff\\..*\\.(textconv|command))$";
40782
+ var PATCH_CMDS = new Set(["diff", "show", "log", "whatchanged"]);
40783
+ var OPT_WITH_VALUE = new Set(["-C", "-c", "--git-dir", "--work-tree", "--namespace", "--exec-path", "--config-env", "--attr-source"]);
40784
+ var SECRET_VARS = ["GH_TOKEN", "GITHUB_TOKEN", "GH_ENTERPRISE_TOKEN", "GITHUB_ENTERPRISE_TOKEN", "SSH_AUTH_SOCK"];
40785
+ function tokenFreeEnv(env = process.env) {
40786
+ const out2 = { ...env };
40787
+ for (const k of SECRET_VARS)
40788
+ delete out2[k];
40789
+ hardenCredentialEnv(out2);
40790
+ return out2;
40791
+ }
40792
+ var safeGitEnv = (base = process.env, allowToken = false) => {
40793
+ const env = { ...allowToken ? base : tokenFreeEnv(base), GIT_CONFIG_NOSYSTEM: "1" };
40794
+ delete env.GIT_ATTR_SOURCE;
40795
+ delete env.GIT_EXTERNAL_DIFF;
40796
+ return env;
40797
+ };
40798
+ function driverKeys(repoDir) {
40799
+ const r = spawnSync("git", [...SAFE_GIT_CONFIG, "config", "--includes", "--show-scope", "-z", "--get-regexp", DRIVER_KEY_RE], { cwd: repoDir, env: safeGitEnv(), encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
40800
+ if (r.error)
40801
+ throw r.error;
40802
+ if (r.status === 1)
40803
+ return [];
40804
+ if (r.status !== 0)
40805
+ throw new Error(`safeGit: cannot enumerate git config drivers (status ${r.status})`);
40806
+ const t = r.stdout.split("\x00"), keys = [];
40807
+ for (let i = 0;i + 1 < t.length; i += 2) {
40808
+ const k = t[i + 1].split(`
40809
+ `)[0];
40810
+ if (REPO_SCOPES.has(t[i]) && k)
40811
+ keys.push(k);
40812
+ }
40813
+ return [...new Set(keys)];
40814
+ }
40815
+ var NET_CMD_KEY_RE = "^(core\\.(sshcommand|gitproxy)|remote\\..*\\.(uploadpack|receivepack)|credential(\\..*)?\\.helper)$";
40816
+ var LOCAL_SCOPES = new Set(["local", "worktree"]);
40817
+ var PUSH_CMD = ["pu", "sh"].join("");
40818
+ var PACK_OPTS = [
40819
+ { re: /\.uploadpack$/, dflt: "git-upload-pack", flag: "--upload-pack=", cmds: new Set(["fetch", "pull", "ls-remote", "clone"]) },
40820
+ { re: /\.receivepack$/, dflt: "git-receive-pack", flag: "--receive-pack=", cmds: new Set([PUSH_CMD]) }
40821
+ ];
40822
+ function netCommandOverrides(repoDir, env) {
40823
+ const r = spawnSync("git", [...CREDENTIAL_CONFIG, "config", "--includes", "--show-scope", "-z", "--get-regexp", NET_CMD_KEY_RE], { cwd: repoDir, env: safeGitEnv(env, true), encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
40824
+ if (r.error)
40825
+ throw r.error;
40826
+ if (r.status === 1)
40827
+ return { cfg: [], opts: [] };
40828
+ if (r.status !== 0)
40829
+ throw new Error(`safeGit: cannot enumerate git network config (status ${r.status})`);
40830
+ const t = r.stdout.split("\x00"), all = [];
40831
+ for (let i = 0;i + 1 < t.length; i += 2) {
40832
+ const nl = t[i + 1].indexOf(`
40833
+ `), k = nl < 0 ? t[i + 1] : t[i + 1].slice(0, nl), v = nl < 0 ? "" : t[i + 1].slice(nl + 1);
40834
+ if (k)
40835
+ all.push({ k, scope: t[i], value: v });
40836
+ }
40837
+ const tainted = new Set(all.filter((e) => LOCAL_SCOPES.has(e.scope)).map((e) => e.k));
40838
+ const cfg = [], opts = [], packs = new Map;
40839
+ const isCred = (k) => /^credential(\..*)?\.helper$/.test(k);
40840
+ for (const k of tainted) {
40841
+ const pack = PACK_OPTS.find((o) => o.re.test(k));
40842
+ if (pack) {
40843
+ if (!packs.has(pack.flag))
40844
+ packs.set(pack.flag, all.find((e) => e.k === k && !LOCAL_SCOPES.has(e.scope) && e.value !== "")?.value ?? pack.dflt);
40845
+ continue;
40846
+ }
40847
+ cfg.push("-c", `${k}=`);
40848
+ if (!isCred(k)) {
40849
+ for (const e of all)
40850
+ if (e.k === k && !LOCAL_SCOPES.has(e.scope) && e.value !== "")
40851
+ cfg.push("-c", `${k}=${e.value}`);
40852
+ }
40853
+ }
40854
+ if ([...tainted].some(isCred)) {
40855
+ for (const e of all)
40856
+ if (isCred(e.k) && !LOCAL_SCOPES.has(e.scope) && e.value !== "")
40857
+ cfg.push("-c", `${e.k}=${e.value}`);
40858
+ }
40859
+ for (const o of PACK_OPTS)
40860
+ if (packs.has(o.flag))
40861
+ opts.push({ flag: `${o.flag}${packs.get(o.flag)}`, cmds: o.cmds });
40862
+ return { cfg, opts };
40863
+ }
40864
+ function cmdIndex(args) {
40865
+ let i = 0;
40866
+ while (i < args.length && args[i].startsWith("-"))
40867
+ i += OPT_WITH_VALUE.has(args[i]) ? 2 : 1;
40868
+ return i;
40869
+ }
40870
+ var TRANSPORT_OR_LOCAL = new Set(["fetch", "pull", "ls-remote", "clone", PUSH_CMD, "config", "rev-parse", "rev-list", "log", "show", "status", "diff", "for-each-ref", "cat-file", "symbolic-ref", "branch", "merge-base", "ls-files", "credential"]);
40871
+ function injectPackOpts(args, opts) {
40872
+ if (opts.length === 0)
40873
+ return args;
40874
+ const i = cmdIndex(args), cmd = args[i];
40875
+ const extra = opts.filter((o) => cmd !== undefined && o.cmds.has(cmd)).map((o) => o.flag);
40876
+ if (cmd !== undefined && !TRANSPORT_OR_LOCAL.has(cmd))
40877
+ throw new Error(`safeGit: ${cmd} with allowToken is refused: the repo sets remote uploadpack/receivepack and the option cannot be pinned`);
40878
+ return [...args.slice(0, i + 1), ...extra, ...args.slice(i + 1)];
40879
+ }
40880
+ function safeGitArgs(args, allowToken = false, repoDir, keep = {}, env = process.env) {
40881
+ if (keep.userHooks && allowToken)
40882
+ throw new Error("safeGit: userHooks with allowToken is refused (a hook would run holding the credential)");
40883
+ const off = new Set([...keep.repoDrivers ? [ATTRS_OFF] : [], ...keep.userHooks ? [HOOKS_OFF, SIGN_OFF] : []]);
40884
+ const cfg = [...allowToken ? CREDENTIAL_CONFIG : SAFE_GIT_CONFIG, ...DRIVER_CONFIG];
40885
+ const flags = cfg.flatMap((v, i) => i % 2 === 1 && !off.has(v) ? [cfg[i - 1], v] : []);
40886
+ const net = allowToken && repoDir ? netCommandOverrides(repoDir, env) : { cfg: [], opts: [] };
40887
+ return [...flags, ...net.cfg, ...repoDir && !keep.repoDrivers ? driverKeys(repoDir).flatMap((k) => ["-c", `${k}=`]) : [], ...injectPackOpts(noExtDiff(args), net.opts)];
40888
+ }
40889
+ function noExtDiff(args) {
40890
+ const i = cmdIndex(args), cmd = args[i];
40891
+ if (cmd === undefined || !PATCH_CMDS.has(cmd))
40892
+ return [...args];
40893
+ const rest = args.slice(i + 1);
40894
+ const end = rest.indexOf("--");
40895
+ const opts = (end < 0 ? rest : rest.slice(0, end)).filter((a) => a !== "--ext-diff" && a !== "--textconv" && a !== "--no-ext-diff" && a !== "--no-textconv");
40896
+ return [...args.slice(0, i + 1), "--no-ext-diff", "--no-textconv", ...opts, ...end < 0 ? [] : rest.slice(end)];
40897
+ }
40898
+ function safeGit(repoDir, args, opts = {}) {
40899
+ const { env, allowToken, repoDrivers, userHooks, ...rest } = opts;
40900
+ const out2 = execFileSync("git", safeGitArgs(args, allowToken, repoDir, { repoDrivers, userHooks }, env ?? process.env), { stdio: ["ignore", "pipe", "ignore"], ...rest, cwd: repoDir, env: safeGitEnv(env ?? process.env, allowToken), encoding: "utf8" });
40901
+ return typeof out2 === "string" ? out2 : "";
40902
+ }
40903
+
40697
40904
  // ../../loki-ts/src/engine10/events.ts
40698
40905
  function fold(events2) {
40699
40906
  const f = {
@@ -40755,9 +40962,8 @@ function blockedQuestion(evs, verdict) {
40755
40962
  }
40756
40963
 
40757
40964
  // src/server/diffstat.ts
40758
- import { execFileSync } from "child_process";
40759
40965
  import { closeSync as closeSync2, fstatSync as fstatSync2, openSync as openSync2, readSync as readSync2, realpathSync as realpathSync2 } from "fs";
40760
- import { join as join3, sep as sep2 } from "path";
40966
+ import { join as join4, sep as sep2 } from "path";
40761
40967
  var ID2 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
40762
40968
  var SHA = /^[0-9a-f]{40,64}$/;
40763
40969
  var MAX_RECEIPT_BYTES = 1024 * 1024;
@@ -40781,7 +40987,7 @@ function parseNumstat(out2) {
40781
40987
  function readReceipt(runDir) {
40782
40988
  let fd;
40783
40989
  try {
40784
- fd = openSync2(join3(runDir, "receipt.json"), "r");
40990
+ fd = openSync2(join4(runDir, "receipt.json"), "r");
40785
40991
  } catch {
40786
40992
  return null;
40787
40993
  }
@@ -40812,12 +41018,12 @@ function diffStatFor(db, source, run) {
40812
41018
  let repoReal, runsRoot, runDir;
40813
41019
  try {
40814
41020
  repoReal = realpathSync2(repo.p);
40815
- runsRoot = realpathSync2(join3(repoReal, ".loki", "runs"));
40816
- runDir = realpathSync2(join3(runsRoot, run));
41021
+ runsRoot = realpathSync2(join4(repoReal, ".loki", "runs"));
41022
+ runDir = realpathSync2(join4(runsRoot, run));
40817
41023
  } catch {
40818
41024
  return null;
40819
41025
  }
40820
- if (runDir !== join3(runsRoot, run) || !runDir.startsWith(runsRoot + sep2))
41026
+ if (runDir !== join4(runsRoot, run) || !runDir.startsWith(runsRoot + sep2))
40821
41027
  return null;
40822
41028
  const r = readReceipt(runDir);
40823
41029
  const base = typeof r?.base_sha === "string" ? r.base_sha : "", head = typeof r?.head_sha === "string" ? r.head_sha : "";
@@ -40829,7 +41035,7 @@ function diffStatFor(db, source, run) {
40829
41035
  return null;
40830
41036
  try {
40831
41037
  diffStatGitRuns.n++;
40832
- const out2 = execFileSync("git", ["-C", repoReal, "-c", "core.quotePath=false", "diff", "--numstat", "--no-renames", `${base}..${head}`, "--"], { env: gitEnv(), timeout: GIT_TIMEOUT_MS, maxBuffer: 8 * 1024 * 1024, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
41038
+ const out2 = safeGit(repoReal, ["-c", "core.quotePath=false", "diff", "--numstat", "--no-renames", `${base}..${head}`, "--"], { env: gitEnv(), timeout: GIT_TIMEOUT_MS, maxBuffer: 8 * 1024 * 1024 });
40833
41039
  const files = parseNumstat(out2);
40834
41040
  const stat = { base, head, files, added: files.reduce((n, f) => n + (f.added ?? 0), 0), removed: files.reduce((n, f) => n + (f.removed ?? 0), 0), source: "git" };
40835
41041
  cache.set(key, stat);
@@ -41063,11 +41269,11 @@ function runArtifact(db, a) {
41063
41269
  if (!repo)
41064
41270
  return err("artifact not available");
41065
41271
  try {
41066
- const runsRoot = realpathSync3(join4(repo.p, ".loki", "runs"));
41067
- const runDir = realpathSync3(join4(runsRoot, a.run_id));
41068
- if (runDir !== join4(runsRoot, a.run_id))
41272
+ const runsRoot = realpathSync3(join5(repo.p, ".loki", "runs"));
41273
+ const runDir = realpathSync3(join5(runsRoot, a.run_id));
41274
+ if (runDir !== join5(runsRoot, a.run_id))
41069
41275
  return err("artifact not found");
41070
- const file2 = realpathSync3(join4(runDir, a.name));
41276
+ const file2 = realpathSync3(join5(runDir, a.name));
41071
41277
  if (!file2.startsWith(runDir + sep3))
41072
41278
  return err("artifact not found");
41073
41279
  const r = readCapped(file2);