loki-mode 11.3.2 → 11.3.4

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 (73) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/loki +7 -0
  4. package/completions/_loki +16 -0
  5. package/completions/loki.bash +15 -1
  6. package/dashboard/__init__.py +1 -1
  7. package/docs/CLI-REFERENCE.md +1 -1
  8. package/docs/INSTALLATION.md +1 -1
  9. package/docs/v10/DECISIONS.md +5 -0
  10. package/docs/v10/FAILURE-CLASSES.md +168 -0
  11. package/docs/v10/PROGRESS.md +6 -0
  12. package/loki-ts/dist/loki.js +719 -719
  13. package/mcp/__init__.py +1 -1
  14. package/package.json +2 -2
  15. package/packages/control-plane/dist/server.js +225 -191
  16. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  17. package/web-app/dist/assets/{AdminPage-DuRQZsF9.js → AdminPage-CKj0pDt0.js} +1 -1
  18. package/web-app/dist/assets/{Avatar-7GtOQvsO.js → Avatar-BOV__pMM.js} +1 -1
  19. package/web-app/dist/assets/{Badge-CYgTnIxj.js → Badge-4a6mAYjU.js} +1 -1
  20. package/web-app/dist/assets/{Button-rYSyIu7X.js → Button-B3GM7oxm.js} +1 -1
  21. package/web-app/dist/assets/{CockpitPage-9adANY4o.js → CockpitPage-Cwge3_kH.js} +1 -1
  22. package/web-app/dist/assets/{ComparePage-DEG2oA-R.js → ComparePage-CBQUGKsm.js} +1 -1
  23. package/web-app/dist/assets/{ErrorBoundary-CwtvY4xs.js → ErrorBoundary-TM7lDjUJ.js} +1 -1
  24. package/web-app/dist/assets/{EvidenceReceiptPanel-DTT73pPB.js → EvidenceReceiptPanel-DUOseTYA.js} +1 -1
  25. package/web-app/dist/assets/{GitHubIssuesPanel-CpWZLz2x.js → GitHubIssuesPanel-hK_uML6T.js} +1 -1
  26. package/web-app/dist/assets/{GitHubPRsPanel-H293R7E2.js → GitHubPRsPanel-Bt0mug-u.js} +1 -1
  27. package/web-app/dist/assets/{HomePage-B11Imp9k.js → HomePage-DcOogAai.js} +2 -2
  28. package/web-app/dist/assets/{LoginPage-BZBgx5Jr.js → LoginPage-D41pjjhF.js} +1 -1
  29. package/web-app/dist/assets/{MagicPage-B27S4_X8.js → MagicPage-iDcdAcL2.js} +1 -1
  30. package/web-app/dist/assets/{MetricsPage-CfbJWNDG.js → MetricsPage-Tt4sfFD1.js} +1 -1
  31. package/web-app/dist/assets/{NotFoundPage-Tp_4zMSm.js → NotFoundPage-DPQMausn.js} +1 -1
  32. package/web-app/dist/assets/{ProjectPage-CM4fgMsV.js → ProjectPage-DdMz4frY.js} +3 -3
  33. package/web-app/dist/assets/{ProjectsPage-DP2Fvsrd.js → ProjectsPage-Be0v4ace.js} +1 -1
  34. package/web-app/dist/assets/{SettingsPage-C4G9-EAy.js → SettingsPage-90yIh-mE.js} +1 -1
  35. package/web-app/dist/assets/{ShowcasePage-Dj-n4dwu.js → ShowcasePage-D5x5eczl.js} +1 -1
  36. package/web-app/dist/assets/{SystemSettingsPage-BqMLpuGt.js → SystemSettingsPage-UWeWT8KX.js} +1 -1
  37. package/web-app/dist/assets/{TeamsPage-mIH8H96m.js → TeamsPage-BtofFlme.js} +1 -1
  38. package/web-app/dist/assets/{TemplatesPage-BagW-v4n.js → TemplatesPage-DwB8Va2Z.js} +1 -1
  39. package/web-app/dist/assets/{TerminalOutput-CTQRHhnK.js → TerminalOutput-CGIgTmby.js} +1 -1
  40. package/web-app/dist/assets/{activity-DNQiBDDL.js → activity-BZ77CO72.js} +1 -1
  41. package/web-app/dist/assets/{bell-Coiwdad1.js → bell-Bzpqv6un.js} +1 -1
  42. package/web-app/dist/assets/{bot-Cou-rTgR.js → bot-yXo1B_-f.js} +1 -1
  43. package/web-app/dist/assets/{check-CsF-XtQp.js → check-BSxGjsta.js} +1 -1
  44. package/web-app/dist/assets/{chevron-left-BJiy55Ht.js → chevron-left-CqTRVUB5.js} +1 -1
  45. package/web-app/dist/assets/{circle-alert-D6-pQQWq.js → circle-alert-88gdjY71.js} +1 -1
  46. package/web-app/dist/assets/{clock-BOGqwgt9.js → clock-XdFXoaJi.js} +1 -1
  47. package/web-app/dist/assets/{cloud-DsxhTtf5.js → cloud-Tx1sJrXz.js} +1 -1
  48. package/web-app/dist/assets/{code-xml-CxJDHUlE.js → code-xml-DaH9CKWy.js} +1 -1
  49. package/web-app/dist/assets/{database-BJePscl_.js → database-BpvOmzij.js} +1 -1
  50. package/web-app/dist/assets/{dollar-sign-6qWGAkZo.js → dollar-sign-VC2UX2UE.js} +1 -1
  51. package/web-app/dist/assets/{file-code-corner-DcOtYeDb.js → file-code-corner--TF3VpoT.js} +1 -1
  52. package/web-app/dist/assets/{file-plus-WuRyLFo0.js → file-plus-DZpwU9pY.js} +1 -1
  53. package/web-app/dist/assets/{globe-r-xCP4DE.js → globe-tbpeHRPV.js} +1 -1
  54. package/web-app/dist/assets/{hammer-DTt0SsCB.js → hammer-CKLXn4vL.js} +1 -1
  55. package/web-app/dist/assets/{index-BkbXyH8y.js → index-DnCsWpCh.js} +3 -3
  56. package/web-app/dist/assets/{layers-BvZhvSMY.js → layers-B0fkGsk8.js} +1 -1
  57. package/web-app/dist/assets/{loader-circle-3gosTei9.js → loader-circle-czscMzmQ.js} +1 -1
  58. package/web-app/dist/assets/{lock-CZZMxP0U.js → lock-CTtO6vc8.js} +1 -1
  59. package/web-app/dist/assets/{package-C5A8CkJr.js → package-DZeSY0-g.js} +1 -1
  60. package/web-app/dist/assets/{plus-Btv7tTIF.js → plus-mE12CJVN.js} +1 -1
  61. package/web-app/dist/assets/{refresh-cw-DsWLXgs_.js → refresh-cw-9DSznasU.js} +1 -1
  62. package/web-app/dist/assets/{rotate-ccw-DOVDjway.js → rotate-ccw-DcHI0M43.js} +1 -1
  63. package/web-app/dist/assets/{scroll-text-smySzlrX.js → scroll-text-BWLthSw-.js} +1 -1
  64. package/web-app/dist/assets/{server-b5PHsqAU.js → server-_I247LrS.js} +1 -1
  65. package/web-app/dist/assets/{shield-alert-BD7FDlh-.js → shield-alert-XRJYD_6c.js} +1 -1
  66. package/web-app/dist/assets/{thumbs-up-CAsFzbyE.js → thumbs-up-CxuTD3eO.js} +1 -1
  67. package/web-app/dist/assets/{trash-2-BJ35qHgl.js → trash-2-DuGxuVt8.js} +1 -1
  68. package/web-app/dist/assets/{trending-down-Ozrd26cZ.js → trending-down-Cg_zGt__.js} +1 -1
  69. package/web-app/dist/assets/{trending-up-BhnMcM32.js → trending-up-DpUJzIrV.js} +1 -1
  70. package/web-app/dist/assets/{upload-JVHfdwoA.js → upload-Db7YZ4zR.js} +1 -1
  71. package/web-app/dist/assets/{usePolling-CTzbDV-e.js → usePolling-BGRYm-vq.js} +1 -1
  72. package/web-app/dist/assets/{user-Bks3-GYv.js → user-CxHrowEP.js} +1 -1
  73. 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.3.2'
78
+ __version__ = '11.3.4'
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.3.2",
4
+ "version": "11.3.4",
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": "75bbbb9465e6b2b80dc8b05a012a6d0eec576005"
163
+ "gitHead": "5377b0721e892e6245630986b77c2ad2ae6fb01f"
164
164
  }
@@ -9482,7 +9482,7 @@ function validateAnswer(repoDir, raw2) {
9482
9482
  root,
9483
9483
  runner: isStr(p.runner) ? p.runner.trim() : null,
9484
9484
  commands,
9485
- ui: { present: ui.present === true, boot: checkCommand(repoDir, ui.boot, `${w}.ui.boot`, errs), cite: checkCites(repoDir, ui.cite, `${w}.ui.cite`, errs) },
9485
+ ui: { present: ui.present === true, boot: checkCommand(repoDir, ui.boot, `${w}.ui.boot`, errs), cite: ui.present === true || Array.isArray(ui.cite) && ui.cite.length > 0 ? checkCites(repoDir, ui.cite, `${w}.ui.cite`, errs) : [] },
9486
9486
  cite: checkCites(repoDir, p.cite, `${w}.cite`, errs),
9487
9487
  ...p.install === undefined ? {} : { install: checkCommand(repoDir, p.install, `${w}.install`, errs) },
9488
9488
  ...p.dependsOn === undefined ? {} : { dependsOn: rawDeps(p.dependsOn, `${w}.dependsOn`, errs) }
@@ -10013,186 +10013,18 @@ var init_runner_errors = __esm(() => {
10013
10013
  ];
10014
10014
  });
10015
10015
 
10016
- // ../../loki-ts/src/runner/load_owner.ts
10017
- import { spawnSync as spawnSync3 } from "child_process";
10018
- import { mkdtempSync as mkdtempSync4, realpathSync as realpathSync15, rmSync as rmSync7 } from "fs";
10019
- import { tmpdir as tmpdir6 } from "os";
10020
- import { basename as basename12, extname, join as join37 } from "path";
10021
- function changedFilesNamed(out2, repoDir, changed) {
10022
- return changed.filter((f) => {
10023
- if (out2.includes(f) || out2.includes(join37(repoDir, f)))
10024
- return true;
10025
- const segs = f.split("/");
10026
- if (suffixes(segs, 2).some((x) => x !== f && bounded(out2, x, "(?![\\w-])")))
10027
- return true;
10028
- if (extname(f) === ".go" && segs.length > 1 && suffixes(segs.slice(0, -1), 1).some((d) => new RegExp(`(?<=[\\w-])/${esc(d)}(?![\\w./-])`).test(out2)))
10029
- return true;
10030
- const stem = basename12(f, extname(f));
10031
- if (stem.length < 2 || stem === "index" || stem === "__init__")
10032
- return false;
10033
- return new RegExp(`(?<![\\w-])${esc(stem)}(?![\\w-])`).test(out2);
10034
- });
10035
- }
10036
- function loadSignature(out2, roots) {
10037
- let o = out2;
10038
- for (const r of roots.flatMap((x) => {
10039
- try {
10040
- return [x, realpathSync15(x)];
10041
- } catch {
10042
- return [x];
10043
- }
10044
- }).sort((a, b) => b.length - a.length))
10045
- o = o.split(r).join("<repo>");
10046
- const keys = new Set;
10047
- for (const m of o.matchAll(/Cannot find (?:module|package) '([^']+)'/g))
10048
- keys.add(`mod:${m[1]}`);
10049
- for (const m of o.matchAll(/([\w.-]+): command not found/g))
10050
- keys.add(`cmd:${m[1]}`);
10051
- return { keys, reason: (classifyRunnerOutput(o).reason ?? "").replace(/:\d+(?::\d+)?/g, "") };
10052
- }
10053
- function sameLoadError(head, base, headRoots, baseRoots) {
10054
- const h = loadSignature(head, headRoots), b = loadSignature(base, baseRoots);
10055
- if (b.keys.size)
10056
- return h.keys.size > 0 && [...b.keys].every((k) => h.keys.has(k));
10057
- return h.keys.size === 0 && h.reason === b.reason;
10058
- }
10059
- function killTree(pid) {
10060
- const all = [pid];
10061
- for (let k = 0;k < all.length; k++) {
10062
- const kids = spawnSync3("pgrep", ["-P", String(all[k])], { encoding: "utf8", env: process.env }).stdout.split(/\s+/).filter(Boolean).map(Number);
10063
- all.push(...kids.filter((x) => Number.isInteger(x) && !all.includes(x)));
10064
- }
10065
- try {
10066
- if (Number.isInteger(pid) && pid > 1)
10067
- process.kill(-pid, "SIGKILL");
10068
- } catch {}
10069
- for (const p of all.reverse()) {
10070
- try {
10071
- process.kill(p, "SIGKILL");
10072
- } catch {}
10073
- }
10074
- }
10075
- async function runOnBase(i, dir) {
10076
- const sub = (s) => s.split(i.repoDir).join(dir);
10077
- const stop = AbortSignal.any([i.signal, AbortSignal.timeout(i.timeoutMs ?? 60000)]);
10078
- try {
10079
- const proc = Bun.spawn([sub(i.cmd), ...i.args.map(sub)], {
10080
- cwd: sub(i.cwd ?? i.repoDir),
10081
- stdin: "ignore",
10082
- stdout: "pipe",
10083
- stderr: "pipe",
10084
- detached: true,
10085
- env: { ...process.env, ...i.env ?? {} }
10086
- });
10087
- let tail = "";
10088
- const rs = [proc.stdout, proc.stderr].map((x) => x.getReader());
10089
- const pumps = rs.map(async (r) => {
10090
- const d = new TextDecoder;
10091
- for (;; ) {
10092
- const c = await r.read().catch(() => ({ done: true, value: undefined }));
10093
- if (c.done)
10094
- return;
10095
- tail = (tail + d.decode(c.value, { stream: true })).slice(-65536);
10096
- }
10097
- });
10098
- const cut = new Promise((res) => {
10099
- if (stop.aborted)
10100
- res(null);
10101
- else
10102
- stop.addEventListener("abort", () => res(null), { once: true });
10103
- });
10104
- const code = await Promise.race([proc.exited, cut]);
10105
- if (code === null) {
10106
- killTree(proc.pid);
10107
- return null;
10108
- }
10109
- await Promise.race([Promise.all(pumps), new Promise((r) => setTimeout(r, 300))]);
10110
- rs.forEach((r) => r.cancel().catch(() => {}));
10111
- return stop.aborted || code === 0 ? null : tail;
10112
- } catch {
10113
- return null;
10114
- }
10115
- }
10116
- function changedSince(repoDir, baseSha) {
10117
- const g = (a) => safeGit(repoDir, a).split(`
10118
- `).map((l) => l.trim()).filter(Boolean);
10119
- return [...new Set([...g(["diff", "--name-only", baseSha]), ...g(["ls-files", "--others", "--exclude-standard"])])].filter((f) => !f.startsWith(".loki/"));
10120
- }
10121
- async function loadErrorIsHarnessOwned(i) {
10122
- if (i.protect || !i.baseSha || i.signal.aborted)
10123
- return false;
10124
- let changed;
10125
- try {
10126
- changed = changedSince(i.repoDir, i.baseSha);
10127
- } catch {
10128
- return false;
10129
- }
10130
- if (changedFilesNamed(i.out, i.repoDir, changed).length > 0)
10131
- return false;
10132
- if (i.args.some((a) => changed.includes(a.replace(/^\.\//, ""))))
10133
- return false;
10134
- const dir = mkdtempSync4(join37(tmpdir6(), "e10-loadown-"));
10135
- const git3 = (args) => {
10136
- safeGit(i.repoDir, args, { stdio: "ignore" });
10137
- };
10138
- try {
10139
- git3(["worktree", "add", "--detach", dir, i.baseSha]);
10140
- const base = await runOnBase(i, dir);
10141
- return base !== null && classifyRunnerOutput(base).kind === "load_error" && sameLoadError(i.out, base, [i.repoDir, ...i.cwd ? [i.cwd] : []], [dir]);
10142
- } catch {
10143
- return false;
10144
- } finally {
10145
- try {
10146
- git3(["worktree", "remove", "--force", dir]);
10147
- } catch {}
10148
- rmSync7(dir, { recursive: true, force: true });
10149
- try {
10150
- git3(["worktree", "prune"]);
10151
- } catch {}
10152
- }
10153
- }
10154
- async function harnessLoadReason(i) {
10155
- const c = classifyRunnerOutput(i.out);
10156
- return c.kind === "load_error" && await loadErrorIsHarnessOwned(i) ? c.reason : undefined;
10157
- }
10158
- var esc = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), suffixes = (segs, min) => segs.map((_, k) => segs.slice(k).join("/")).filter((x) => x.split("/").length >= min), bounded = (out2, tok, tail) => new RegExp(`(?<![\\w.-])${esc(tok)}${tail}`).test(out2);
10159
- var init_load_owner = __esm(() => {
10160
- init_runner_errors();
10161
- init_safe_git();
10162
- });
10163
-
10164
- // ../../loki-ts/src/engine10/testmap.ts
10165
- import { basename as basename13, extname as extname2, join as join38, relative as relative3, sep as sep10 } from "path";
10166
- function isTestFile(rel) {
10167
- const name = basename13(rel);
10168
- return JS_TEST_RE.test(name) || PY_TEST_RE.test(name) || GO_TEST_RE.test(name);
10169
- }
10170
- var SKIP_DIRS, JS_TEST_RE, PY_TEST_RE, GO_TEST_RE;
10171
- var init_testmap = __esm(() => {
10172
- init_resolve();
10173
- init_scope();
10174
- SKIP_DIRS = new Set([
10175
- ".git",
10176
- "node_modules",
10177
- "dist",
10178
- "build",
10179
- "target",
10180
- "coverage",
10181
- ".venv",
10182
- "venv",
10183
- "__pycache__",
10184
- ".tox",
10185
- ".pytest_cache",
10186
- ".loki",
10187
- ".next"
10188
- ]);
10189
- JS_TEST_RE = /\.(test|spec)\.[cm]?[jt]sx?$/;
10190
- PY_TEST_RE = /^(test_.+|.+_test)\.py$/;
10191
- GO_TEST_RE = /_test\.go$/;
10192
- });
10193
-
10194
10016
  // ../../loki-ts/src/util/check_result.ts
10195
- import { basename as basename14 } from "path";
10017
+ import { basename as basename12 } from "path";
10018
+ function plainTestEnv(base = process.env) {
10019
+ const e = {};
10020
+ for (const [k, v] of Object.entries(tokenFreeEnv(base)))
10021
+ if (typeof v === "string")
10022
+ e[k] = v;
10023
+ e["FORCE_COLOR"] = "0";
10024
+ e["NO_COLOR"] = "1";
10025
+ delete e["CLICOLOR_FORCE"];
10026
+ return e;
10027
+ }
10196
10028
  function ran(raw2, path, ok) {
10197
10029
  const out2 = stripAnsi(raw2);
10198
10030
  const n2 = (s, re) => +(s.match(re)?.[1] ?? 0);
@@ -10200,7 +10032,7 @@ function ran(raw2, path, ok) {
10200
10032
  if (blk) {
10201
10033
  const c = n2(blk, /(?:#|\u2139) pass (\d+)/) + n2(blk, /(?:#|\u2139) fail (\d+)/);
10202
10034
  const nm = out2.match(/^(?:ok \d+ - |\u2714 )(\S+\.[cm]?[jt]s)(?: \(|$)/m)?.[1];
10203
- return c === 1 && nm && (!path || basename14(nm) === basename14(path)) ? 0 : c;
10035
+ return c === 1 && nm && (!path || basename12(nm) === basename12(path)) ? 0 : c;
10204
10036
  }
10205
10037
  const cg = cargoTrailer(out2);
10206
10038
  if (cg.length)
@@ -10291,16 +10123,16 @@ function goRunner(cmd, args) {
10291
10123
  let k = 0;
10292
10124
  for (;k < t.length; k++) {
10293
10125
  const x = t[k];
10294
- if (/^[A-Za-z_]\w*=/.test(x) || /^(?:env|command|exec|time|nohup)$/.test(basename14(x)))
10126
+ if (/^[A-Za-z_]\w*=/.test(x) || /^(?:env|command|exec|time|nohup)$/.test(basename12(x)))
10295
10127
  continue;
10296
- if (/^-/.test(x) && k > 0 && basename14(t[k - 1]) === "env") {
10128
+ if (/^-/.test(x) && k > 0 && basename12(t[k - 1]) === "env") {
10297
10129
  if (x === "-u" || x === "-C" || x === "-S")
10298
10130
  k++;
10299
10131
  continue;
10300
10132
  }
10301
10133
  break;
10302
10134
  }
10303
- if (t[k] !== undefined && basename14(t[k]) === "go")
10135
+ if (t[k] !== undefined && basename12(t[k]) === "go")
10304
10136
  return { runner: "go" };
10305
10137
  }
10306
10138
  return {};
@@ -10385,11 +10217,191 @@ var NO_TESTS_REASON = "no tests executed", GO_EXIT0_REASON = "test count could n
10385
10217
  `), tailLines = (out2) => out2.split(`
10386
10218
  `).filter((x) => x.trim()).slice(-12), GO_PKG_RE, isExecutedProof = (c) => c.result === "pass" && typeof c.n === "number" && c.n > 0, hasExecutedProof = (checks) => checks.some(isExecutedProof);
10387
10219
  var init_check_result = __esm(() => {
10220
+ init_safe_git();
10388
10221
  FAIL_EVIDENCE = /\[(?:build|setup) failed\]|^--- FAIL|^[\w./-]+\.go:\d+:\d+: \S|\b[1-9]\d* (?:failed|errors?)\b/m;
10389
10222
  GO_FAIL_EVIDENCE = /^FAIL\t\S+\t[\d.]+s$|^panic: /m;
10390
10223
  GO_PKG_RE = /^(?:ok|FAIL|\?)\s+\S+\s+(?:\(cached\)|[\d.]+s\b|\[(?:no test files|build failed|setup failed)\])/;
10391
10224
  });
10392
10225
 
10226
+ // ../../loki-ts/src/runner/load_owner.ts
10227
+ import { spawnSync as spawnSync3 } from "child_process";
10228
+ import { mkdtempSync as mkdtempSync4, realpathSync as realpathSync15, rmSync as rmSync7 } from "fs";
10229
+ import { tmpdir as tmpdir6 } from "os";
10230
+ import { basename as basename13, extname, join as join37 } from "path";
10231
+ function changedFilesNamed(out2, repoDir, changed) {
10232
+ return changed.filter((f) => {
10233
+ if (out2.includes(f) || out2.includes(join37(repoDir, f)))
10234
+ return true;
10235
+ const segs = f.split("/");
10236
+ if (suffixes(segs, 2).some((x) => x !== f && bounded(out2, x, "(?![\\w-])")))
10237
+ return true;
10238
+ if (extname(f) === ".go" && segs.length > 1 && suffixes(segs.slice(0, -1), 1).some((d) => new RegExp(`(?<=[\\w-])/${esc(d)}(?![\\w./-])`).test(out2)))
10239
+ return true;
10240
+ const stem = basename13(f, extname(f));
10241
+ if (stem.length < 2 || stem === "index" || stem === "__init__")
10242
+ return false;
10243
+ return new RegExp(`(?<![\\w-])${esc(stem)}(?![\\w-])`).test(out2);
10244
+ });
10245
+ }
10246
+ function loadSignature(out2, roots) {
10247
+ let o = out2;
10248
+ for (const r of roots.flatMap((x) => {
10249
+ try {
10250
+ return [x, realpathSync15(x)];
10251
+ } catch {
10252
+ return [x];
10253
+ }
10254
+ }).sort((a, b) => b.length - a.length))
10255
+ o = o.split(r).join("<repo>");
10256
+ const keys = new Set;
10257
+ for (const m of o.matchAll(/Cannot find (?:module|package) '([^']+)'/g))
10258
+ keys.add(`mod:${m[1]}`);
10259
+ for (const m of o.matchAll(/([\w.-]+): command not found/g))
10260
+ keys.add(`cmd:${m[1]}`);
10261
+ return { keys, reason: (classifyRunnerOutput(o).reason ?? "").replace(/:\d+(?::\d+)?/g, "") };
10262
+ }
10263
+ function sameLoadError(head, base, headRoots, baseRoots) {
10264
+ const h = loadSignature(head, headRoots), b = loadSignature(base, baseRoots);
10265
+ if (b.keys.size)
10266
+ return h.keys.size > 0 && [...b.keys].every((k) => h.keys.has(k));
10267
+ return h.keys.size === 0 && h.reason === b.reason;
10268
+ }
10269
+ function killTree(pid) {
10270
+ const all = [pid];
10271
+ for (let k = 0;k < all.length; k++) {
10272
+ const kids = spawnSync3("pgrep", ["-P", String(all[k])], { encoding: "utf8", env: process.env }).stdout.split(/\s+/).filter(Boolean).map(Number);
10273
+ all.push(...kids.filter((x) => Number.isInteger(x) && !all.includes(x)));
10274
+ }
10275
+ try {
10276
+ if (Number.isInteger(pid) && pid > 1)
10277
+ process.kill(-pid, "SIGKILL");
10278
+ } catch {}
10279
+ for (const p of all.reverse()) {
10280
+ try {
10281
+ process.kill(p, "SIGKILL");
10282
+ } catch {}
10283
+ }
10284
+ }
10285
+ async function runOnBase(i, dir) {
10286
+ const sub = (s) => s.split(i.repoDir).join(dir);
10287
+ const stop = AbortSignal.any([i.signal, AbortSignal.timeout(i.timeoutMs ?? 60000)]);
10288
+ try {
10289
+ const proc = Bun.spawn([sub(i.cmd), ...i.args.map(sub)], {
10290
+ cwd: sub(i.cwd ?? i.repoDir),
10291
+ stdin: "ignore",
10292
+ stdout: "pipe",
10293
+ stderr: "pipe",
10294
+ detached: true,
10295
+ env: { ...plainTestEnv(), ...i.env ?? {} }
10296
+ });
10297
+ let tail = "";
10298
+ const rs = [proc.stdout, proc.stderr].map((x) => x.getReader());
10299
+ const pumps = rs.map(async (r) => {
10300
+ const d = new TextDecoder;
10301
+ for (;; ) {
10302
+ const c = await r.read().catch(() => ({ done: true, value: undefined }));
10303
+ if (c.done)
10304
+ return;
10305
+ tail = (tail + d.decode(c.value, { stream: true })).slice(-65536);
10306
+ }
10307
+ });
10308
+ const cut = new Promise((res) => {
10309
+ if (stop.aborted)
10310
+ res(null);
10311
+ else
10312
+ stop.addEventListener("abort", () => res(null), { once: true });
10313
+ });
10314
+ const code = await Promise.race([proc.exited, cut]);
10315
+ if (code === null) {
10316
+ killTree(proc.pid);
10317
+ return null;
10318
+ }
10319
+ await Promise.race([Promise.all(pumps), new Promise((r) => setTimeout(r, 300))]);
10320
+ rs.forEach((r) => r.cancel().catch(() => {}));
10321
+ return stop.aborted || code === 0 ? null : stripAnsi(tail);
10322
+ } catch {
10323
+ return null;
10324
+ }
10325
+ }
10326
+ function changedSince(repoDir, baseSha) {
10327
+ const g = (a) => safeGit(repoDir, a).split(`
10328
+ `).map((l) => l.trim()).filter(Boolean);
10329
+ return [...new Set([...g(["diff", "--name-only", baseSha]), ...g(["ls-files", "--others", "--exclude-standard"])])].filter((f) => !f.startsWith(".loki/"));
10330
+ }
10331
+ async function loadErrorIsHarnessOwned(i) {
10332
+ if (i.protect || !i.baseSha || i.signal.aborted)
10333
+ return false;
10334
+ let changed;
10335
+ try {
10336
+ changed = changedSince(i.repoDir, i.baseSha);
10337
+ } catch {
10338
+ return false;
10339
+ }
10340
+ if (changedFilesNamed(i.out, i.repoDir, changed).length > 0)
10341
+ return false;
10342
+ if (i.args.some((a) => changed.includes(a.replace(/^\.\//, ""))))
10343
+ return false;
10344
+ const dir = mkdtempSync4(join37(tmpdir6(), "e10-loadown-"));
10345
+ const git3 = (args) => {
10346
+ safeGit(i.repoDir, args, { stdio: "ignore" });
10347
+ };
10348
+ try {
10349
+ git3(["worktree", "add", "--detach", dir, i.baseSha]);
10350
+ const base = await runOnBase(i, dir);
10351
+ return base !== null && classifyRunnerOutput(base).kind === "load_error" && sameLoadError(i.out, base, [i.repoDir, ...i.cwd ? [i.cwd] : []], [dir]);
10352
+ } catch {
10353
+ return false;
10354
+ } finally {
10355
+ try {
10356
+ git3(["worktree", "remove", "--force", dir]);
10357
+ } catch {}
10358
+ rmSync7(dir, { recursive: true, force: true });
10359
+ try {
10360
+ git3(["worktree", "prune"]);
10361
+ } catch {}
10362
+ }
10363
+ }
10364
+ async function harnessLoadReason(i) {
10365
+ const c = classifyRunnerOutput(i.out);
10366
+ return c.kind === "load_error" && await loadErrorIsHarnessOwned(i) ? c.reason : undefined;
10367
+ }
10368
+ var esc = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), suffixes = (segs, min) => segs.map((_, k) => segs.slice(k).join("/")).filter((x) => x.split("/").length >= min), bounded = (out2, tok, tail) => new RegExp(`(?<![\\w.-])${esc(tok)}${tail}`).test(out2);
10369
+ var init_load_owner = __esm(() => {
10370
+ init_runner_errors();
10371
+ init_safe_git();
10372
+ init_check_result();
10373
+ });
10374
+
10375
+ // ../../loki-ts/src/engine10/testmap.ts
10376
+ import { basename as basename14, extname as extname2, join as join38, relative as relative3, sep as sep10 } from "path";
10377
+ function isTestFile(rel) {
10378
+ const name = basename14(rel);
10379
+ return JS_TEST_RE.test(name) || PY_TEST_RE.test(name) || GO_TEST_RE.test(name);
10380
+ }
10381
+ var SKIP_DIRS, JS_TEST_RE, PY_TEST_RE, GO_TEST_RE;
10382
+ var init_testmap = __esm(() => {
10383
+ init_resolve();
10384
+ init_scope();
10385
+ SKIP_DIRS = new Set([
10386
+ ".git",
10387
+ "node_modules",
10388
+ "dist",
10389
+ "build",
10390
+ "target",
10391
+ "coverage",
10392
+ ".venv",
10393
+ "venv",
10394
+ "__pycache__",
10395
+ ".tox",
10396
+ ".pytest_cache",
10397
+ ".loki",
10398
+ ".next"
10399
+ ]);
10400
+ JS_TEST_RE = /\.(test|spec)\.[cm]?[jt]sx?$/;
10401
+ PY_TEST_RE = /^(test_.+|.+_test)\.py$/;
10402
+ GO_TEST_RE = /_test\.go$/;
10403
+ });
10404
+
10393
10405
  // ../../loki-ts/src/util/wall_owned.ts
10394
10406
  import { isAbsolute as isAbsolute4, join as join39, relative as relative4 } from "path";
10395
10407
  function failingLocations(raw2, cwd, repoDir) {
@@ -10502,7 +10514,7 @@ async function runOnce(cmd, args, cwd, signal, opts) {
10502
10514
  stdout: "pipe",
10503
10515
  stderr: "pipe",
10504
10516
  signal: AbortSignal.any([signal, timeout]),
10505
- env: opts.path ? { ...process.env, PATH: opts.path } : process.env
10517
+ env: opts.path ? { ...plainTestEnv(), PATH: opts.path } : plainTestEnv()
10506
10518
  });
10507
10519
  let tail = "";
10508
10520
  const rs = [proc.stdout, proc.stderr].map((s) => s.getReader());
@@ -10519,7 +10531,7 @@ async function runOnce(cmd, args, cwd, signal, opts) {
10519
10531
  await Promise.race([Promise.all(pumps), new Promise((r) => setTimeout(r, 300))]);
10520
10532
  rs.forEach((r) => r.cancel().catch(() => {}));
10521
10533
  const cut = timeout.aborted || signal.aborted;
10522
- return { ok: exitCode === 0 && !cut, missing: false, cut, out: cut ? "" : tail };
10534
+ return { ok: exitCode === 0 && !cut, missing: false, cut, out: cut ? "" : stripAnsi(tail) };
10523
10535
  }
10524
10536
  function firstError(out2) {
10525
10537
  const goOut = (l2) => {
@@ -10880,9 +10892,19 @@ function nodeIsRed(f, raw2) {
10880
10892
  const named = [...o.matchAll(/^(?:\u2716|\s*not ok \d+ -) (?!failing tests:)(.+?)(?: \(|$)/gm)].some((m) => !f.path.endsWith(m[1]) && !m[1].endsWith(f.path)), blk = o.split("failing tests:")[1] ?? "", esm = /^SyntaxError: The requested module '([^']+)' does not provide an export named/m.exec(o), errs = [...blk.matchAll(/^ {2}(\w+Error): .*\n\s+at (?:.*\()?([^\s()]+?):\d+:\d+/gm), ...o.matchAll(/^ +name: '(\w+Error)'\n(?:.*\n)*? +stack: \|-\n\s+(?:.*\()?([^\s()]+?):\d+:\d+/gm)];
10881
10893
  return /^(?:#|\u2139) fail [1-9]/m.test(raw2) && (/^ {2}AssertionError\b/m.test(blk) || /^ +name: 'AssertionError'/m.test(o) || (mod && !named ? /^[./]/.test(mod[1]) : esm ? /^[./]/.test(esm[1]) : top ? !top[1].endsWith(f.path) : !errs.length || errs.some((e) => !/^(?:Reference|Syntax)Error$/.test(e[1]) || !(e[2].startsWith("node:") || e[2].endsWith(f.path)))));
10882
10894
  }
10895
+ function notRunReason(status, interpreter) {
10896
+ if (interpreter === "system")
10897
+ return "ran under the system interpreter, not the project's, so the result proves nothing";
10898
+ if (status === null)
10899
+ return "the test runner did not start or timed out";
10900
+ if (status === 126 || status === 127)
10901
+ return `the test runner command was not found or not executable (exit ${status})`;
10902
+ return status === 0 ? "exit 0 but no executed test count could be confirmed" : `exit ${status} but the runner output showed no readable failing test`;
10903
+ }
10883
10904
  function classify(f, status, output, repoDir, interpreter) {
10884
10905
  if (interpreter === "system")
10885
10906
  return "not_run";
10907
+ output = stripAnsi(output);
10886
10908
  if (status === null || status === 126 || status === 127)
10887
10909
  return "not_run";
10888
10910
  if (status === 0)
@@ -10897,26 +10919,32 @@ function classify(f, status, output, repoDir, interpreter) {
10897
10919
  class RealBaseTestRunner {
10898
10920
  api;
10899
10921
  timeoutMs;
10922
+ lastNotRunFiles = [];
10900
10923
  constructor(api, timeoutMs = BASE_RUN_TIMEOUT_MS) {
10901
10924
  this.api = api;
10902
10925
  this.timeoutMs = timeoutMs;
10903
10926
  }
10904
10927
  run(repoDir, files) {
10928
+ this.lastNotRunFiles = [];
10905
10929
  let pass = 0, fail = 0, not_run = 0;
10930
+ const not_run_files = [];
10906
10931
  const api = this.api === undefined ? loadProjectApi(repoDir) : this.api;
10907
10932
  for (const f of files) {
10908
10933
  const { cmd, args, interpreter, cwd } = commandFor(f, repoDir, api);
10909
- const r = spawnSync4(cmd, f.runner === "pytest" ? [...args, "-rfE"] : args, { cwd, encoding: "utf8", timeout: Math.max(1000, this.timeoutMs), env: process.env });
10934
+ const r = spawnSync4(cmd, f.runner === "pytest" ? [...args, "-rfE"] : args, { cwd, encoding: "utf8", timeout: Math.max(1000, this.timeoutMs), env: plainTestEnv() });
10910
10935
  const status = r.error ? null : r.status;
10911
- const result = classify(f, status, `${r.stdout ?? ""}
10912
- ${r.stderr ?? ""}`, repoDir, interpreter);
10936
+ const result = classify(f, status, stripAnsi(`${r.stdout ?? ""}
10937
+ ${r.stderr ?? ""}`), repoDir, interpreter);
10913
10938
  if (result === "pass")
10914
10939
  pass++;
10915
10940
  else if (result === "fail")
10916
10941
  fail++;
10917
- else
10942
+ else {
10918
10943
  not_run++;
10944
+ not_run_files.push({ file: f.path, reason: notRunReason(status, interpreter) });
10945
+ }
10919
10946
  }
10947
+ this.lastNotRunFiles = not_run_files;
10920
10948
  return { pass, fail, not_run };
10921
10949
  }
10922
10950
  }
@@ -11039,12 +11067,13 @@ function installWall(ctx, a, baseDir, opts = {}) {
11039
11067
  wallTests.push({ runner, path: relative6(ctx.repoDir, dest) });
11040
11068
  }
11041
11069
  ctx.emit("wall.sealed", "wall", { files: sealedFiles, ...a.manifestSha256 ? { manifest_sha256: a.manifestSha256 } : {} });
11042
- const baseRunner = opts.baseRunner ?? new RealBaseTestRunner, baseRun = { pass: 0, fail: 0, not_run: discarded.length };
11070
+ const baseRunner = opts.baseRunner ?? new RealBaseTestRunner, baseRun = { pass: 0, fail: 0, not_run: discarded.length }, notRunFiles = [];
11043
11071
  for (const t of wallTests) {
11044
11072
  const r = baseRunner.run(baseDir, [t]), abs = join42(ctx.repoDir, t.path);
11045
11073
  baseRun.pass += r.pass;
11046
11074
  baseRun.fail += r.fail;
11047
11075
  baseRun.not_run += r.not_run ?? 0;
11076
+ notRunFiles.push(...baseRunner.lastNotRunFiles ?? []);
11048
11077
  if (r.pass + r.fail === 0) {
11049
11078
  rmSync9(abs, { force: true });
11050
11079
  for (const l of [sealedFiles, readOnlyFiles])
@@ -11059,6 +11088,7 @@ function installWall(ctx, a, baseDir, opts = {}) {
11059
11088
  files: sealedFiles,
11060
11089
  readOnlyFiles,
11061
11090
  base_run: baseRun,
11091
+ ...notRunFiles.length ? { not_run_files: notRunFiles } : {},
11062
11092
  iteration_ids: [`${ctx.runId}-wall`],
11063
11093
  already_satisfied: alreadySatisfied,
11064
11094
  ...discarded.length ? { discarded } : {}
@@ -12625,6 +12655,10 @@ var init_seal = __esm(() => {
12625
12655
  notProven.add(`wall base run not_run: ${wallNotRun}`);
12626
12656
  for (const d of Array.isArray(o.wall?.discarded) ? o.wall.discarded : [])
12627
12657
  notProven.add(`wall test discarded: ${String(d.file)} (${String(d.reason)})`);
12658
+ for (const d of Array.isArray(o.wall?.not_run_files) ? o.wall.not_run_files : [])
12659
+ notProven.add(`Wall test not executed: ${String(d.file)}: ${String(d.reason)}`);
12660
+ if (wallNotRun > 0 && ![...notProven].some((n2) => n2.startsWith("Wall test not executed:") || n2.startsWith("wall test discarded:")) && !(Array.isArray(o.wall?.discarded) && o.wall.discarded.length > 0))
12661
+ notProven.add(`Wall test not executed: ${wallNotRun} file(s), no reason recorded`);
12628
12662
  if (wallNotRun > 0) {
12629
12663
  try {
12630
12664
  const kept = new Set((Array.isArray(o.wall?.files) ? o.wall.files : []).map((f) => basename18(String(f.path))));
@@ -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.3.2",
5
+ "version": "11.3.4",
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-BkbXyH8y.js";import{B as C}from"./Button-rYSyIu7X.js";import{T as $e}from"./trending-up-BhnMcM32.js";import{C as z}from"./clock-BOGqwgt9.js";import{A as Be,U as ue,M as De}from"./Avatar-7GtOQvsO.js";import{A as J}from"./activity-DNQiBDDL.js";import{R as pe}from"./refresh-cw-DsWLXgs_.js";import{G as ze}from"./globe-r-xCP4DE.js";import{C as Le}from"./chevron-left-BJiy55Ht.js";import{C as je}from"./check-CsF-XtQp.js";import{D as Y}from"./dollar-sign-6qWGAkZo.js";import{U as Te}from"./user-Bks3-GYv.js";import{D as Me}from"./database-BJePscl_.js";import{L as Ue}from"./lock-CZZMxP0U.js";import{S as Re}from"./scroll-text-smySzlrX.js";import{S as Ie}from"./shield-alert-BD7FDlh-.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-DnCsWpCh.js";import{B as C}from"./Button-B3GM7oxm.js";import{T as $e}from"./trending-up-DpUJzIrV.js";import{C as z}from"./clock-XdFXoaJi.js";import{A as Be,U as ue,M as De}from"./Avatar-BOV__pMM.js";import{A as J}from"./activity-BZ77CO72.js";import{R as pe}from"./refresh-cw-9DSznasU.js";import{G as ze}from"./globe-tbpeHRPV.js";import{C as Le}from"./chevron-left-CqTRVUB5.js";import{C as je}from"./check-BSxGjsta.js";import{D as Y}from"./dollar-sign-VC2UX2UE.js";import{U as Te}from"./user-CxHrowEP.js";import{D as Me}from"./database-BpvOmzij.js";import{L as Ue}from"./lock-CTtO6vc8.js";import{S as Re}from"./scroll-text-BWLthSw-.js";import{S as Ie}from"./shield-alert-XRJYD_6c.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-BkbXyH8y.js";/**
1
+ import{c as l,j as s}from"./index-DnCsWpCh.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{j as e}from"./index-BkbXyH8y.js";import{C as r}from"./clock-BOGqwgt9.js";import{C as a}from"./circle-alert-D6-pQQWq.js";import{C as l}from"./check-CsF-XtQp.js";const i={completed:"bg-[#1FC5A8]/10 text-[#1FC5A8]",running:"bg-[#553DE9]/10 text-[#553DE9]",failed:"bg-[#C45B5B]/10 text-[#C45B5B]",started:"bg-[#D4A03C]/10 text-[#D4A03C]",empty:"bg-[#F8F4F0] text-[#6B6960]",version:"bg-[#553DE9]/10 text-[#553DE9]"};function o({status:t}){switch(t){case"completed":return e.jsx(l,{size:12});case"running":return e.jsxs("span",{className:"relative flex h-2 w-2",children:[e.jsx("span",{className:"animate-ping motion-reduce:animate-none absolute inline-flex h-full w-full rounded-full bg-current opacity-75"}),e.jsx("span",{className:"relative inline-flex rounded-full h-2 w-2 bg-current"})]});case"failed":return e.jsx(a,{size:12});case"started":return e.jsx(r,{size:12});default:return null}}function f({status:t,children:n,className:s=""}){return e.jsxs("span",{className:["inline-flex items-center gap-1 rounded-btn px-2.5 py-0.5 text-xs font-semibold",i[t],s].filter(Boolean).join(" "),children:[e.jsx(o,{status:t}),n]})}export{f as B};
1
+ import{j as e}from"./index-DnCsWpCh.js";import{C as r}from"./clock-XdFXoaJi.js";import{C as a}from"./circle-alert-88gdjY71.js";import{C as l}from"./check-BSxGjsta.js";const i={completed:"bg-[#1FC5A8]/10 text-[#1FC5A8]",running:"bg-[#553DE9]/10 text-[#553DE9]",failed:"bg-[#C45B5B]/10 text-[#C45B5B]",started:"bg-[#D4A03C]/10 text-[#D4A03C]",empty:"bg-[#F8F4F0] text-[#6B6960]",version:"bg-[#553DE9]/10 text-[#553DE9]"};function o({status:t}){switch(t){case"completed":return e.jsx(l,{size:12});case"running":return e.jsxs("span",{className:"relative flex h-2 w-2",children:[e.jsx("span",{className:"animate-ping motion-reduce:animate-none absolute inline-flex h-full w-full rounded-full bg-current opacity-75"}),e.jsx("span",{className:"relative inline-flex rounded-full h-2 w-2 bg-current"})]});case"failed":return e.jsx(a,{size:12});case"started":return e.jsx(r,{size:12});default:return null}}function f({status:t,children:n,className:s=""}){return e.jsxs("span",{className:["inline-flex items-center gap-1 rounded-btn px-2.5 py-0.5 text-xs font-semibold",i[t],s].filter(Boolean).join(" "),children:[e.jsx(o,{status:t}),n]})}export{f as B};
@@ -1 +1 @@
1
- import{r as p,j as t}from"./index-BkbXyH8y.js";const m={primary:"bg-[#553DE9] text-white hover:bg-[#4432c4] shadow-button rounded-btn",secondary:"border border-[#553DE9] text-[#553DE9] hover:bg-[#E8E4FD] bg-transparent rounded-btn",ghost:"text-[#36342E] hover:bg-[#F8F4F0] rounded-btn",danger:"bg-[#C45B5B]/10 text-[#C45B5B] border border-[#C45B5B]/20 hover:bg-[#C45B5B]/20 rounded-btn"},b={sm:"px-3 py-1.5 text-xs",md:"px-4 py-2 text-sm",lg:"px-6 py-3 text-base"},u={sm:14,md:16,lg:18};function h({size:e}){return t.jsxs("svg",{className:"animate-spin",width:e,height:e,viewBox:"0 0 24 24",fill:"none",children:[t.jsx("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"4"}),t.jsx("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"})]})}const B=p.forwardRef(({variant:e="primary",size:o="md",icon:n,iconRight:i,loading:r=!1,disabled:a,className:c="",children:l,...x},d)=>{const s=u[o];return t.jsxs("button",{ref:d,disabled:a||r,className:["inline-flex items-center justify-center gap-2 font-medium transition-colors",m[e],b[o],(a||r)&&"opacity-60 cursor-not-allowed",c].filter(Boolean).join(" "),...x,children:[r?t.jsx(h,{size:s}):n?t.jsx(n,{size:s}):null,l,i&&!r&&t.jsx(i,{size:s})]})});B.displayName="Button";export{B};
1
+ import{r as p,j as t}from"./index-DnCsWpCh.js";const m={primary:"bg-[#553DE9] text-white hover:bg-[#4432c4] shadow-button rounded-btn",secondary:"border border-[#553DE9] text-[#553DE9] hover:bg-[#E8E4FD] bg-transparent rounded-btn",ghost:"text-[#36342E] hover:bg-[#F8F4F0] rounded-btn",danger:"bg-[#C45B5B]/10 text-[#C45B5B] border border-[#C45B5B]/20 hover:bg-[#C45B5B]/20 rounded-btn"},b={sm:"px-3 py-1.5 text-xs",md:"px-4 py-2 text-sm",lg:"px-6 py-3 text-base"},u={sm:14,md:16,lg:18};function h({size:e}){return t.jsxs("svg",{className:"animate-spin",width:e,height:e,viewBox:"0 0 24 24",fill:"none",children:[t.jsx("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"4"}),t.jsx("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"})]})}const B=p.forwardRef(({variant:e="primary",size:o="md",icon:n,iconRight:i,loading:r=!1,disabled:a,className:c="",children:l,...x},d)=>{const s=u[o];return t.jsxs("button",{ref:d,disabled:a||r,className:["inline-flex items-center justify-center gap-2 font-medium transition-colors",m[e],b[o],(a||r)&&"opacity-60 cursor-not-allowed",c].filter(Boolean).join(" "),...x,children:[r?t.jsx(h,{size:s}):n?t.jsx(n,{size:s}):null,l,i&&!r&&t.jsx(i,{size:s})]})});B.displayName="Button";export{B};
@@ -1,4 +1,4 @@
1
- import{c as $,r as l,j as e,G as we,Q as Se,F as Ce,h as Re,T as U,Z as Ee,a as S,V as Me,S as $e,Y as Te,X as Pe,P as ie,i as Ae,g as ze,C as Ie,l as Le,N as I,J as _e,K as De,O as Fe,u as Oe}from"./index-BkbXyH8y.js";import{P as K,S as He,E as Be}from"./ErrorBoundary-CwtvY4xs.js";import{C as qe,F as Ge,M as Ue,H as Ke,a as We,G as Ve,T as Qe}from"./thumbs-up-CAsFzbyE.js";import{C as oe}from"./check-CsF-XtQp.js";import{C as Ye}from"./clock-BOGqwgt9.js";import{D as Xe}from"./dollar-sign-6qWGAkZo.js";import{U as Ze}from"./upload-JVHfdwoA.js";import{L as V}from"./loader-circle-3gosTei9.js";/**
1
+ import{c as $,r as l,j as e,G as we,Q as Se,F as Ce,h as Re,T as U,Z as Ee,a as S,V as Me,S as $e,Y as Te,X as Pe,P as ie,i as Ae,g as ze,C as Ie,l as Le,N as I,J as _e,K as De,O as Fe,u as Oe}from"./index-DnCsWpCh.js";import{P as K,S as He,E as Be}from"./ErrorBoundary-TM7lDjUJ.js";import{C as qe,F as Ge,M as Ue,H as Ke,a as We,G as Ve,T as Qe}from"./thumbs-up-CxuTD3eO.js";import{C as oe}from"./check-BSxGjsta.js";import{C as Ye}from"./clock-XdFXoaJi.js";import{D as Xe}from"./dollar-sign-VC2UX2UE.js";import{U as Ze}from"./upload-Db7YZ4zR.js";import{L as V}from"./loader-circle-czscMzmQ.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.