loki-mode 10.11.0 → 11.0.0

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 (119) hide show
  1. package/.github/actions/issue-to-pr/action.yml +17 -0
  2. package/SKILL.md +2 -2
  3. package/VERSION +1 -1
  4. package/autonomy/lib/backlog.py +1 -1
  5. package/autonomy/lib/workspace.py +1 -1
  6. package/autonomy/loki +5 -8
  7. package/bin/loki +21 -18
  8. package/dashboard/__init__.py +1 -1
  9. package/docs/AGENT-CHANGE-RECEIPT.md +47 -0
  10. package/docs/CLI-REFERENCE.md +1 -1
  11. package/docs/INSTALLATION.md +1 -1
  12. package/docs/v10/BOARD.md +3 -3
  13. package/docs/v10/DEPS.md +3 -0
  14. package/docs/v10/FAILURE-CLASSES.md +25 -0
  15. package/docs/v10/GUIDE.md +17 -22
  16. package/docs/v10/PROGRESS.md +13 -0
  17. package/docs/v10/RELEASE-11.md +75 -0
  18. package/docs/v11/C1-multi-user-sso.md +30 -0
  19. package/docs/v11/C10-the-8090-teardown.md +28 -0
  20. package/docs/v11/C11-mcp-modern.md +16 -0
  21. package/docs/v11/C2-hosted-runner.md +30 -0
  22. package/docs/v11/C3-reproducible-environments.md +30 -0
  23. package/docs/v11/C4-bitbucket-azure.md +29 -0
  24. package/docs/v11/C5-open-local-models.md +29 -0
  25. package/docs/v11/C6-secrets-handling.md +31 -0
  26. package/docs/v11/C7-windows.md +30 -0
  27. package/docs/v11/C8-public-benchmark.md +30 -0
  28. package/docs/v11/C9-opt-in-telemetry.md +33 -0
  29. package/docs/v11/README.md +32 -0
  30. package/loki-ts/dist/loki.js +691 -676
  31. package/mcp/__init__.py +1 -1
  32. package/package.json +3 -2
  33. package/packages/control-plane/dist/ask-tools-server.js +41169 -0
  34. package/packages/control-plane/dist/server.js +2343 -1238
  35. package/packages/control-plane/package.json +4 -2
  36. package/packages/control-plane/src/ask/invoke.ts +42 -0
  37. package/packages/control-plane/src/ask/policy.ts +65 -0
  38. package/packages/control-plane/src/ask/prompt.ts +38 -0
  39. package/packages/control-plane/src/ask/store.ts +88 -0
  40. package/packages/control-plane/src/ask/tools.ts +111 -0
  41. package/packages/control-plane/src/ask/tools_server.ts +46 -0
  42. package/packages/control-plane/src/ask/worker.ts +136 -0
  43. package/packages/control-plane/src/db/fixture-cleanup.ts +24 -10
  44. package/packages/control-plane/src/server/app.ts +13 -6
  45. package/packages/control-plane/src/server/ingest.ts +6 -1
  46. package/packages/control-plane/src/server/reconcile.ts +33 -0
  47. package/packages/control-plane/src/server/repos.ts +37 -3
  48. package/packages/control-plane/src/server/routes/artifacts.ts +3 -3
  49. package/packages/control-plane/src/server/routes/ask.ts +139 -0
  50. package/packages/control-plane/src/server/routes/cost.ts +19 -0
  51. package/packages/control-plane/src/server/routes/doctor.ts +67 -0
  52. package/packages/control-plane/src/server/routes/index.ts +7 -3
  53. package/packages/control-plane/src/server/routes/stream.ts +22 -11
  54. package/packages/control-plane/src/server/runs.ts +27 -0
  55. package/packages/control-plane/src/server/spawn.ts +19 -6
  56. package/packages/control-plane/ui/dist/assets/index-CxZWgwie.css +1 -0
  57. package/packages/control-plane/ui/dist/assets/index-DcBJXjCJ.js +190 -0
  58. package/packages/control-plane/ui/dist/index.html +2 -2
  59. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  60. package/web-app/dist/assets/{AdminPage-qTfCHm93.js → AdminPage-Bmmmm2To.js} +1 -1
  61. package/web-app/dist/assets/{Avatar-V5Wfzf34.js → Avatar-63_TXRKt.js} +1 -1
  62. package/web-app/dist/assets/{Badge-B7fNko8Z.js → Badge-x_TAt-df.js} +1 -1
  63. package/web-app/dist/assets/{Button-C_3eInAe.js → Button-AXhA9K5O.js} +1 -1
  64. package/web-app/dist/assets/{CockpitPage-Ir2wag2q.js → CockpitPage-DTLCv1h8.js} +1 -1
  65. package/web-app/dist/assets/{ComparePage-qbC63b0U.js → ComparePage-BYcilVjG.js} +1 -1
  66. package/web-app/dist/assets/{ErrorBoundary-BTEqFTCi.js → ErrorBoundary-BLqm3BId.js} +1 -1
  67. package/web-app/dist/assets/{EvidenceReceiptPanel-CcICm1gj.js → EvidenceReceiptPanel-BceXzz60.js} +1 -1
  68. package/web-app/dist/assets/{GitHubIssuesPanel-CXCWYQqX.js → GitHubIssuesPanel-D8c4JUx5.js} +1 -1
  69. package/web-app/dist/assets/{GitHubPRsPanel-DmzhZYpS.js → GitHubPRsPanel-DUrmma6t.js} +1 -1
  70. package/web-app/dist/assets/{HomePage-BRPspBy7.js → HomePage-DxmEUjq_.js} +2 -2
  71. package/web-app/dist/assets/{LoginPage-C1Nb7Vf9.js → LoginPage-Bgct3T-6.js} +1 -1
  72. package/web-app/dist/assets/{MagicPage-CeXc60VN.js → MagicPage-Bh7ejcHn.js} +1 -1
  73. package/web-app/dist/assets/{MetricsPage-MuDDdqNu.js → MetricsPage-BqPEIiec.js} +1 -1
  74. package/web-app/dist/assets/{NotFoundPage-8iOaj85A.js → NotFoundPage-B2DSNOjE.js} +1 -1
  75. package/web-app/dist/assets/{ProjectPage-DOKcPhxr.js → ProjectPage-Bl0_uWYD.js} +3 -3
  76. package/web-app/dist/assets/{ProjectsPage-CNKaqvuO.js → ProjectsPage-D6ZrFHCy.js} +1 -1
  77. package/web-app/dist/assets/{SettingsPage-uZT6dOT1.js → SettingsPage-DWE92j7N.js} +1 -1
  78. package/web-app/dist/assets/{ShowcasePage-CHzrwMZ3.js → ShowcasePage-Bi1m8Y6y.js} +1 -1
  79. package/web-app/dist/assets/{SystemSettingsPage-DMHj5Xub.js → SystemSettingsPage-DDCPZqns.js} +1 -1
  80. package/web-app/dist/assets/{TeamsPage-IGY1oZ2o.js → TeamsPage-C2PmN2Ok.js} +1 -1
  81. package/web-app/dist/assets/{TemplatesPage-Byxc8XyZ.js → TemplatesPage-CpTFFqSz.js} +1 -1
  82. package/web-app/dist/assets/{TerminalOutput-CRamR4sR.js → TerminalOutput-CNFCZjx4.js} +1 -1
  83. package/web-app/dist/assets/{activity-DQfL1H8b.js → activity-5uiPn7vG.js} +1 -1
  84. package/web-app/dist/assets/{bell-CVksERF2.js → bell-C-xlbVax.js} +1 -1
  85. package/web-app/dist/assets/{bot-jSx_C-35.js → bot-8hOixr10.js} +1 -1
  86. package/web-app/dist/assets/{check-o3bOhMvE.js → check-B59pXlrD.js} +1 -1
  87. package/web-app/dist/assets/{chevron-left-DBhM8Y2E.js → chevron-left-DfvDsieV.js} +1 -1
  88. package/web-app/dist/assets/{circle-alert-vCzO_mB8.js → circle-alert-DMPidduh.js} +1 -1
  89. package/web-app/dist/assets/{clock-Bj125ZaJ.js → clock-XdPeED5-.js} +1 -1
  90. package/web-app/dist/assets/{cloud-DpLr6uQJ.js → cloud-CEM1vME-.js} +1 -1
  91. package/web-app/dist/assets/{code-xml-VuYrHYvT.js → code-xml-BcQSgNZ8.js} +1 -1
  92. package/web-app/dist/assets/{database-DBmPbwaG.js → database-P9maBI33.js} +1 -1
  93. package/web-app/dist/assets/{dollar-sign-DEajFwH1.js → dollar-sign-BrvK3fRq.js} +1 -1
  94. package/web-app/dist/assets/{file-code-corner-BidTyjV_.js → file-code-corner-DAO2Qi8-.js} +1 -1
  95. package/web-app/dist/assets/{file-plus-DJ4dSvxw.js → file-plus-DBAP9mx-.js} +1 -1
  96. package/web-app/dist/assets/{globe-BnGEwsOq.js → globe-DxSEu4Ui.js} +1 -1
  97. package/web-app/dist/assets/{hammer-KCPviXRE.js → hammer-CY7jlobV.js} +1 -1
  98. package/web-app/dist/assets/{index-CdK6NQG3.js → index-Dhcimr1u.js} +3 -3
  99. package/web-app/dist/assets/{layers-7G4hsaDk.js → layers-CsOybYaX.js} +1 -1
  100. package/web-app/dist/assets/{loader-circle-CWVxvRmJ.js → loader-circle-CP-uZ3fl.js} +1 -1
  101. package/web-app/dist/assets/{lock-BEH3dNM0.js → lock-C80-6kWZ.js} +1 -1
  102. package/web-app/dist/assets/{package-DvijfmPC.js → package-B2Opl41-.js} +1 -1
  103. package/web-app/dist/assets/{plus-CEwJzXGx.js → plus-CUNzK4gi.js} +1 -1
  104. package/web-app/dist/assets/{refresh-cw-Ct7rMsNS.js → refresh-cw-C4rz1BZ5.js} +1 -1
  105. package/web-app/dist/assets/{rotate-ccw-CoTyya_B.js → rotate-ccw-VZpqP-O-.js} +1 -1
  106. package/web-app/dist/assets/{scroll-text-CbsOnRXr.js → scroll-text-CpyY8-2b.js} +1 -1
  107. package/web-app/dist/assets/{server-MUPVBbag.js → server-VlQUsZyS.js} +1 -1
  108. package/web-app/dist/assets/{shield-alert-CWwdqRUv.js → shield-alert-CiBUSY3R.js} +1 -1
  109. package/web-app/dist/assets/{thumbs-up-CPVKKyLS.js → thumbs-up-Cir_mvr6.js} +1 -1
  110. package/web-app/dist/assets/{trash-2-BqzCzljk.js → trash-2-D5zmzpia.js} +1 -1
  111. package/web-app/dist/assets/{trending-down-DAo5VuPc.js → trending-down-DUNUrvDV.js} +1 -1
  112. package/web-app/dist/assets/{trending-up-BCUggli9.js → trending-up-BPbDp6kc.js} +1 -1
  113. package/web-app/dist/assets/{upload-iQijlCY2.js → upload-DRshJXd5.js} +1 -1
  114. package/web-app/dist/assets/{usePolling-B6kojZR_.js → usePolling-Bo4k0szY.js} +1 -1
  115. package/web-app/dist/assets/{user-DR3XkyHZ.js → user-nh6_54pL.js} +1 -1
  116. package/web-app/dist/index.html +1 -1
  117. package/autonomy/lib/engine10-legacy-notice.txt +0 -3
  118. package/packages/control-plane/ui/dist/assets/index-BinL6h3i.css +0 -1
  119. package/packages/control-plane/ui/dist/assets/index-D27veKDf.js +0 -152
@@ -1,8 +1,8 @@
1
1
  // Start-a-run planning and spawning for the UI (CPE-07). A run is started by spawning the same `loki start` path an operator would type (argv array, no shell).
2
2
  import { spawn } from "node:child_process";
3
- import { existsSync, readFileSync, statSync } from "node:fs";
3
+ import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
4
4
  import { homedir } from "node:os";
5
- import { basename, join, resolve } from "node:path";
5
+ import { basename, dirname, join, resolve } from "node:path";
6
6
 
7
7
  const ISSUE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,99}\/[A-Za-z0-9._-]{1,100}#[1-9][0-9]{0,8}$/;
8
8
  // A free-text task: letters, digits, spaces and a small punctuation set. No colon, quotes, backticks, $, ;, &, |, <, >, parens, braces, backslash or control chars.
@@ -22,6 +22,17 @@ const MODEL = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
22
22
  const BUDGET = /^(?:[1-9][0-9]{0,5}|0)(?:\.[0-9]{1,2})?$/;
23
23
  const WORKSPACE = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;
24
24
 
25
+ /** A run may only start in a git repo, never in HOME or "/" (a "whats going on" composer message once started a coding run in the home directory). Null = allowed. */
26
+ export function repoRefusal(cwd: string, env: NodeJS.ProcessEnv = process.env): string | null {
27
+ const real = (p: string): string => { try { return realpathSync(p); } catch { return resolve(p); } };
28
+ const dir = real(cwd);
29
+ const home = real(env.HOME || homedir());
30
+ if (dir === "/" || dir === resolve("/")) return "refusing to start a run in the filesystem root; pick a git repository";
31
+ if (dir === home) return "refusing to start a run in your home directory; pick a project repository (a folder with its own .git)";
32
+ for (let d = dir; d !== "/" && d !== home && d !== dirname(d); d = dirname(d)) if (existsSync(join(d, ".git"))) return null;
33
+ return `${cwd} is not a git repository; pick a registered project repository`;
34
+ }
35
+
25
36
  export type StartPlan = { ok: true; argv: string[]; cwd: string; env: Record<string, string> } | { ok: false; error: string };
26
37
 
27
38
  /** Registered project paths from ~/.loki/dashboard/projects.json (the `loki projects` registry), existing directories only. */
@@ -33,7 +44,7 @@ export function registryRepos(env: NodeJS.ProcessEnv = process.env): string[] {
33
44
  }
34
45
 
35
46
  /** Validate a start request. The repo must be one the server already knows (registry or cwd), never an arbitrary path. */
36
- export function planStart(body: unknown, known: string[], bin = "loki"): StartPlan {
47
+ export function planStart(body: unknown, known: string[], bin = "loki", env: NodeJS.ProcessEnv = process.env): StartPlan {
37
48
  const b = (body && typeof body === "object" ? body : {}) as { target?: unknown; repo?: unknown; model?: unknown; provider?: unknown; budget?: unknown; workspace?: unknown };
38
49
  if (typeof b.target !== "string") return { ok: false, error: "target must be a string" };
39
50
  const target = b.target.trim();
@@ -51,6 +62,8 @@ export function planStart(body: unknown, known: string[], bin = "loki"): StartPl
51
62
  if (!hit) return { ok: false, error: named.length > 1 ? "repo name is ambiguous" : "repo is not a known project" };
52
63
  cwd = hit;
53
64
  }
65
+ const refusal = repoRefusal(cwd, env);
66
+ if (refusal) return { ok: false, error: refusal };
54
67
  const opt = (v: unknown): string | undefined => (v === undefined || v === null || v === "" ? undefined : typeof v === "number" && Number.isFinite(v) ? String(v) : typeof v === "string" ? v : "\0bad");
55
68
  const provider = opt(b.provider), model = opt(b.model), budget = opt(b.budget), workspace = opt(b.workspace);
56
69
  if (provider !== undefined && !PROVIDERS.has(provider)) return { ok: false, error: "provider must be one of: " + [...PROVIDERS].join(", ") };
@@ -58,11 +71,11 @@ export function planStart(body: unknown, known: string[], bin = "loki"): StartPl
58
71
  if (budget !== undefined && (!BUDGET.test(budget) || Number(budget) <= 0)) return { ok: false, error: "budget must be a positive USD amount such as 5 or 5.00" };
59
72
  if (workspace !== undefined && !WORKSPACE.test(workspace)) return { ok: false, error: "workspace must be a workspace name from loki.yaml (letters, digits, _ -)" };
60
73
  if (workspace !== undefined && (provider !== undefined || budget !== undefined)) return { ok: false, error: "workspace runs do not take provider or budget; set them per repo in loki.yaml" };
61
- const env: Record<string, string> = model !== undefined ? { LOKI_SESSION_MODEL: model } : {};
74
+ const runEnv: Record<string, string> = model !== undefined ? { LOKI_SESSION_MODEL: model } : {};
62
75
  // A workspace run is `loki workspace run <name> <ref>` (the existing multi-repo path). Otherwise free text goes as an explicit brief, never auto-detected as a PRD path.
63
- if (workspace !== undefined) return { ok: true, argv: [bin, "workspace", "run", workspace, target], cwd, env };
76
+ if (workspace !== undefined) return { ok: true, argv: [bin, "workspace", "run", workspace, target], cwd, env: runEnv };
64
77
  const flags = [...(provider !== undefined ? ["--provider", provider] : []), ...(budget !== undefined ? ["--budget", budget] : [])];
65
- return { ok: true, argv: issue ? [bin, "start", target, ...flags] : [bin, "start", "--brief", target, ...flags], cwd, env };
78
+ return { ok: true, argv: issue ? [bin, "start", target, ...flags] : [bin, "start", "--brief", target, ...flags], cwd, env: runEnv };
66
79
  }
67
80
 
68
81
  /** Spawn detached with no shell; resolves with the pid once the process exists, or an error if it cannot be launched. */
@@ -0,0 +1 @@
1
+ @import"https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap";:root,[data-theme=light]{--cp-bg: #F2EEE7;--cp-bg-2: #EBE6DC;--cp-bg-3: #E4DFD4;--cp-card: #FFFEFB;--cp-hover: #EBE6DC;--cp-glass: rgba(255,254,251,.82);--cp-glass-border: rgba(32,21,21,.08);--cp-glass-shadow: 0 4px 24px rgba(0,0,0,.06), 0 1px 2px rgba(0,0,0,.04);--cp-text: #201515;--cp-text-2: #36342E;--cp-text-muted: #6B675C;--cp-text-inverse: #ffffff;--cp-border: #E2DDD2;--cp-border-light: #ECEAE3;--cp-accent: #553DE9;--cp-accent-hover: #4432c4;--cp-accent-active: #3828a0;--cp-accent-glow: rgba(85,61,233,.15);--cp-accent-muted: rgba(85,61,233,.1);--cp-success: #1f8a52;--cp-warning: #9a6a12;--cp-error: #b23a3a;--cp-info: #2F71E3;--cp-success-fill: #1FC5A8;--cp-success-muted: rgba(31,197,168,.12);--cp-warning-fill: #D4A03C;--cp-warning-muted: rgba(212,160,60,.12);--cp-error-fill: #C45B5B;--cp-error-muted: rgba(196,91,91,.12);--cp-info-muted: rgba(47,113,227,.12);--cp-accent-solid: #553DE9;--cp-accent-ink: #553DE9;--cp-error-ink: #b23a3a;--cp-success-ink: #1a7546;--cp-warning-ink: #895e10;--cp-info-ink: #2963c8;--cp-text-subtle: #5f5b52;--cp-opus: #d97706;--cp-sonnet: #553DE9;--cp-haiku: #1FC5A8;--cp-shadow-sm: 0 1px 2px rgba(32,21,21,.04);--cp-shadow-md: 0 4px 6px rgba(32,21,21,.06);--cp-shadow-lg: 0 10px 15px rgba(32,21,21,.08);--cp-focus: 0 0 0 3px rgba(85,61,233,.25)}[data-theme=dark]{--cp-bg: #0F0B16;--cp-bg-2: #17121F;--cp-bg-3: #211A2C;--cp-card: #17121F;--cp-hover: #211A2C;--cp-glass: rgba(15,11,22,.82);--cp-glass-border: rgba(255,255,255,.08);--cp-glass-shadow: 0 4px 24px rgba(0,0,0,.25), 0 1px 2px rgba(0,0,0,.12);--cp-text: #F6F2EA;--cp-text-2: #CFC9BD;--cp-text-muted: #968F84;--cp-text-inverse: #0F0B16;--cp-border: rgba(255,255,255,.08);--cp-border-light: rgba(255,255,255,.04);--cp-accent: #8b7bf5;--cp-accent-hover: #9c8ff7;--cp-accent-active: #6258D0;--cp-accent-glow: rgba(139,123,245,.2);--cp-accent-muted: rgba(123,107,240,.18);--cp-success: #2ED8B6;--cp-warning: #E8B84A;--cp-error: #E07070;--cp-info: #5A9CF5;--cp-success-fill: #2ED8B6;--cp-success-muted: rgba(46,216,182,.18);--cp-warning-fill: #E8B84A;--cp-warning-muted: rgba(232,184,74,.18);--cp-error-fill: #E07070;--cp-error-muted: rgba(224,112,112,.18);--cp-info-muted: rgba(90,156,245,.18);--cp-success-ink: #2ED8B6;--cp-warning-ink: #E8B84A;--cp-info-ink: #6DA8F6;--cp-accent-solid: #6a55f2;--cp-accent-ink: #9c8ef6;--cp-error-ink: #E58989;--cp-text-subtle: #968F84;--cp-opus: #f59e0b;--cp-sonnet: #8b7bf5;--cp-haiku: #2ED8B6;--cp-shadow-sm: 0 1px 2px rgba(0,0,0,.4);--cp-shadow-md: 0 4px 12px rgba(0,0,0,.5);--cp-shadow-lg: 0 10px 25px rgba(0,0,0,.6);--cp-focus: 0 0 0 3px rgba(123,107,240,.3)}@media(prefers-color-scheme:dark){:root:not([data-theme=light]){--cp-bg: #0F0B16;--cp-bg-2: #17121F;--cp-bg-3: #211A2C;--cp-card: #17121F;--cp-hover: #211A2C;--cp-glass: rgba(15,11,22,.82);--cp-glass-border: rgba(255,255,255,.08);--cp-glass-shadow: 0 4px 24px rgba(0,0,0,.25), 0 1px 2px rgba(0,0,0,.12);--cp-text: #F6F2EA;--cp-text-2: #CFC9BD;--cp-text-muted: #968F84;--cp-text-inverse: #0F0B16;--cp-border: rgba(255,255,255,.08);--cp-border-light: rgba(255,255,255,.04);--cp-accent: #8b7bf5;--cp-accent-hover: #9c8ff7;--cp-accent-active: #6258D0;--cp-accent-glow: rgba(139,123,245,.2);--cp-accent-muted: rgba(123,107,240,.18);--cp-success: #2ED8B6;--cp-warning: #E8B84A;--cp-error: #E07070;--cp-info: #5A9CF5;--cp-success-fill: #2ED8B6;--cp-success-muted: rgba(46,216,182,.18);--cp-warning-fill: #E8B84A;--cp-warning-muted: rgba(232,184,74,.18);--cp-error-fill: #E07070;--cp-error-muted: rgba(224,112,112,.18);--cp-info-muted: rgba(90,156,245,.18);--cp-success-ink: #2ED8B6;--cp-warning-ink: #E8B84A;--cp-info-ink: #6DA8F6;--cp-accent-solid: #6a55f2;--cp-accent-ink: #9c8ef6;--cp-error-ink: #E58989;--cp-text-subtle: #968F84;--cp-opus: #f59e0b;--cp-sonnet: #8b7bf5;--cp-haiku: #2ED8B6;--cp-shadow-sm: 0 1px 2px rgba(0,0,0,.4);--cp-shadow-md: 0 4px 12px rgba(0,0,0,.5);--cp-shadow-lg: 0 10px 25px rgba(0,0,0,.6);--cp-focus: 0 0 0 3px rgba(123,107,240,.3)}}:root{--cp-font-serif: "Inter", system-ui, -apple-system, BlinkMacSystemFont, sans-serif;--cp-font-sans: "Inter", system-ui, -apple-system, BlinkMacSystemFont, sans-serif;--cp-font-mono: "JetBrains Mono", "Fira Code", "SF Mono", Menlo, monospace;--cp-text-xs: 10px;--cp-text-sm: 11px;--cp-text-base: 12px;--cp-text-md: 13px;--cp-text-lg: 14px;--cp-text-xl: 16px;--cp-text-2xl: 18px;--cp-text-3xl: 24px;--cp-space-xs: 4px;--cp-space-sm: 8px;--cp-space-md: 12px;--cp-space-lg: 16px;--cp-space-xl: 24px;--cp-space-2xl: 32px;--cp-space-3xl: 48px;--cp-radius-sm: 6px;--cp-radius-md: 12px;--cp-radius-lg: 16px;--cp-radius-nav: 9999px;--cp-radius-full: 9999px;--cp-ease: cubic-bezier(.4,0,.2,1);--cp-dur-fast: .1s;--cp-dur: .2s;--cp-dur-slow: .3s;--cp-sidebar-w: 264px;--cp-detail-w: 288px;--cp-rail-w: 48px;--cp-main-pad: 28px 32px;--cp-thread-max: 820px;--cp-term-bg: #0B0B0B;--cp-term-bar: #111111;--cp-term-side: #0D0D0D;--cp-term-line: #1D1D1D;--cp-term-card: #101010;--cp-term-text: #E8E4DA;--cp-term-strong: #F6F2EA;--cp-term-muted: #968F84;--cp-term-dim: #7A716A;--cp-term-purple: #7E74EE;--cp-term-lilac: #C8BEFF;--cp-term-green: #26C39B;--cp-term-amber: #F0B84A;--cp-term-red: #F07A7A;--cp-z-dropdown: 100;--cp-z-sticky: 200;--cp-z-modal: 300;--cp-z-popover: 400;--cp-z-toast: 600}.cp-root{background:var(--cp-bg);color:var(--cp-text);font-family:var(--cp-font-sans);font-size:var(--cp-text-md);line-height:1.5;-webkit-font-smoothing:antialiased;font-feature-settings:"cv02","cv03","cv04","cv11"}@keyframes cp-pulse{0%,to{opacity:1}50%{opacity:.4}}@keyframes cp-spin{to{transform:rotate(360deg)}}@keyframes cp-fade-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}.cp-fade-in{animation:cp-fade-in var(--cp-dur) var(--cp-ease)}.cp-pulse{animation:cp-pulse 2s var(--cp-ease) infinite}.cp-spinner{animation:cp-spin .8s linear infinite}@media(prefers-reduced-motion:reduce){.cp-fade-in,.cp-pulse,.cp-spinner{animation:none}}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:var(--cp-font-sans);font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--cp-font-mono);font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.collapse{visibility:collapse}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.ml-2{margin-left:.5rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.min-h-11{min-height:2.75rem}.min-h-screen{min-height:100vh}.w-full{width:100%}.min-w-0{min-width:0px}.flex-1{flex:1 1 0%}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.resize{resize:both}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-\[auto_1fr\]{grid-template-columns:auto 1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-1{row-gap:.25rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.overflow-x-auto{overflow-x:auto}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.border{border-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-amber-400{--tw-border-opacity: 1;border-color:rgb(251 191 36 / var(--tw-border-opacity, 1))}.border-red-500\/50{border-color:#ef444480}.border-slate-200{--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity, 1))}.border-slate-300{--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1))}.bg-amber-50{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.bg-amber-500\/15{background-color:#f59e0b26}.bg-emerald-500\/15{background-color:#10b98126}.bg-red-500\/15{background-color:#ef444426}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.bg-red-600\/20{background-color:#dc262633}.bg-sky-500\/15{background-color:#0ea5e926}.bg-sky-600{--tw-bg-opacity: 1;background-color:rgb(2 132 199 / var(--tw-bg-opacity, 1))}.bg-sky-700{--tw-bg-opacity: 1;background-color:rgb(3 105 161 / var(--tw-bg-opacity, 1))}.bg-slate-100{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.bg-slate-200{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.bg-slate-500\/15{background-color:#64748b26}.bg-violet-500\/15{background-color:#8b5cf626}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-8{padding:2rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.pl-5{padding-left:1.25rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:var(--cp-font-mono)}.font-sans{font-family:var(--cp-font-sans)}.font-serif{font-family:var(--cp-font-serif)}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.text-amber-600{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity, 1))}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-amber-900{--tw-text-opacity: 1;color:rgb(120 53 15 / var(--tw-text-opacity, 1))}.text-emerald-600{--tw-text-opacity: 1;color:rgb(5 150 105 / var(--tw-text-opacity, 1))}.text-emerald-700{--tw-text-opacity: 1;color:rgb(4 120 87 / var(--tw-text-opacity, 1))}.text-inverse{color:var(--cp-text-inverse)}.text-muted{color:var(--cp-text-muted)}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.text-sky-600{--tw-text-opacity: 1;color:rgb(2 132 199 / var(--tw-text-opacity, 1))}.text-sky-700{--tw-text-opacity: 1;color:rgb(3 105 161 / var(--tw-text-opacity, 1))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.text-slate-600{--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.text-violet-700{--tw-text-opacity: 1;color:rgb(109 40 217 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.accent-hover{accent-color:var(--cp-hover)}.accent-muted{accent-color:var(--cp-text-muted)}.shadow-lg{--tw-shadow: var(--cp-shadow-lg);--tw-shadow-colored: var(--cp-shadow-lg);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: var(--cp-shadow-md);--tw-shadow-colored: var(--cp-shadow-md);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: var(--cp-shadow-sm);--tw-shadow-colored: var(--cp-shadow-sm);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-amber-500\/30{--tw-ring-color: rgb(245 158 11 / .3)}.ring-emerald-500\/30{--tw-ring-color: rgb(16 185 129 / .3)}.ring-red-500\/30{--tw-ring-color: rgb(239 68 68 / .3)}.ring-red-600\/50{--tw-ring-color: rgb(220 38 38 / .5)}.ring-sky-500\/30{--tw-ring-color: rgb(14 165 233 / .3)}.ring-slate-500\/30{--tw-ring-color: rgb(100 116 139 / .3)}.ring-violet-500\/30{--tw-ring-color: rgb(139 92 246 / .3)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}body{margin:0;background:var(--cp-bg);color:var(--cp-text);font-family:var(--cp-font-sans)}.cp-term{background:var(--cp-term-bg);color:var(--cp-term-text);border:1px solid #1A1A1A;border-radius:20px;overflow:hidden;box-shadow:0 40px 80px -40px #0a0a0a80}.cp-term-bar{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 20px;background:var(--cp-term-bar);border-bottom:1px solid var(--cp-term-line);font-family:var(--cp-font-mono);font-size:12px;color:var(--cp-term-muted)}.cp-term-body{display:grid;grid-template-columns:1fr;min-height:320px}@media(min-width:768px){.cp-term-body{grid-template-columns:220px minmax(0,1fr)}}.cp-term-side{padding:16px;background:var(--cp-term-side);border-bottom:1px solid var(--cp-term-line);font-family:var(--cp-font-mono);font-size:12px}@media(min-width:768px){.cp-term-side{border-bottom:0;border-right:1px solid var(--cp-term-line)}}.cp-term-main{padding:20px 24px;min-width:0}.cp-term-foot{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 24px;border-top:1px solid var(--cp-term-line);font-family:var(--cp-font-mono);font-size:11px;color:var(--cp-term-muted)}.cp-tl-row{display:grid;grid-template-columns:64px 96px minmax(0,1fr);gap:4px 12px;padding:8px 0;border-bottom:1px solid var(--cp-term-line);font-size:12px;line-height:1.55}.cp-tl-meta{grid-column:3;display:flex;flex-wrap:wrap;gap:4px 14px;font-family:var(--cp-font-mono);font-size:11px;color:var(--cp-term-muted)}.cp-trunc{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.cp-eyebrow{font-family:var(--cp-font-mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--cp-text-muted)}.cp-display{font-family:var(--cp-font-sans);font-weight:650;letter-spacing:-.025em;line-height:1.12}.cp-pill-btn{border-radius:9999px}.hover\:underline:hover{text-decoration-line:underline}.disabled\:opacity-50:disabled{opacity:.5}.dark\:border-slate-700:is([data-theme=dark] *){--tw-border-opacity: 1;border-color:rgb(51 65 85 / var(--tw-border-opacity, 1))}.dark\:border-slate-800:is([data-theme=dark] *){--tw-border-opacity: 1;border-color:rgb(30 41 59 / var(--tw-border-opacity, 1))}.dark\:bg-amber-950:is([data-theme=dark] *){--tw-bg-opacity: 1;background-color:rgb(69 26 3 / var(--tw-bg-opacity, 1))}.dark\:bg-slate-800:is([data-theme=dark] *){--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1))}.dark\:bg-slate-900:is([data-theme=dark] *){--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity, 1))}.dark\:text-amber-200:is([data-theme=dark] *){--tw-text-opacity: 1;color:rgb(253 230 138 / var(--tw-text-opacity, 1))}.dark\:text-amber-300:is([data-theme=dark] *){--tw-text-opacity: 1;color:rgb(252 211 77 / var(--tw-text-opacity, 1))}.dark\:text-emerald-300:is([data-theme=dark] *){--tw-text-opacity: 1;color:rgb(110 231 183 / var(--tw-text-opacity, 1))}.dark\:text-emerald-400:is([data-theme=dark] *){--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity, 1))}.dark\:text-red-300:is([data-theme=dark] *){--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.dark\:text-sky-300:is([data-theme=dark] *){--tw-text-opacity: 1;color:rgb(125 211 252 / var(--tw-text-opacity, 1))}.dark\:text-sky-400:is([data-theme=dark] *){--tw-text-opacity: 1;color:rgb(56 189 248 / var(--tw-text-opacity, 1))}.dark\:text-slate-300:is([data-theme=dark] *){--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity, 1))}.dark\:text-slate-400:is([data-theme=dark] *){--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.dark\:text-violet-300:is([data-theme=dark] *){--tw-text-opacity: 1;color:rgb(196 181 253 / var(--tw-text-opacity, 1))}@media(min-width:640px){.sm\:flex{display:flex}.sm\:flex-wrap{flex-wrap:wrap}.sm\:items-end{align-items:flex-end}}@media(min-width:768px){.md\:flex{display:flex}.md\:table-cell{display:table-cell}.md\:hidden{display:none}.md\:min-h-0{min-height:0px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:p-6{padding:1.5rem}.md\:px-3{padding-left:.75rem;padding-right:.75rem}.md\:py-0{padding-top:0;padding-bottom:0}.md\:py-1{padding-top:.25rem;padding-bottom:.25rem}}