loki-mode 11.71.0 → 11.71.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/dashboard/__init__.py +1 -1
  4. package/docs/CLI-REFERENCE.md +1 -1
  5. package/docs/INSTALLATION.md +1 -1
  6. package/docs/v10/FAILURE-CLASSES.md +9 -0
  7. package/docs/v10/roadmap-10/README.md +133 -7
  8. package/loki-ts/dist/loki.js +3 -3
  9. package/mcp/__init__.py +1 -1
  10. package/package.json +2 -2
  11. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  12. package/web-app/dist/assets/{AdminPage-BiT0cLwQ.js → AdminPage-CGyy-IXD.js} +1 -1
  13. package/web-app/dist/assets/{Avatar-DSxI4as6.js → Avatar-FWW_Pp5i.js} +1 -1
  14. package/web-app/dist/assets/{Badge-CsNVRGwt.js → Badge-iax5zk8D.js} +1 -1
  15. package/web-app/dist/assets/{Button-Danr8Id8.js → Button-DFCgFerI.js} +1 -1
  16. package/web-app/dist/assets/{CockpitPage-BrH7eKw-.js → CockpitPage-EMIdhN2T.js} +1 -1
  17. package/web-app/dist/assets/{ComparePage-I6o9EapR.js → ComparePage-BB_CDDj0.js} +1 -1
  18. package/web-app/dist/assets/{ErrorBoundary-CrHfaUmC.js → ErrorBoundary-XEDM5Jef.js} +1 -1
  19. package/web-app/dist/assets/{EvidenceReceiptPanel-Bic-zXdJ.js → EvidenceReceiptPanel-CNWSErDp.js} +1 -1
  20. package/web-app/dist/assets/{GitHubIssuesPanel-AsdMasyf.js → GitHubIssuesPanel-CRRJXMWX.js} +1 -1
  21. package/web-app/dist/assets/{GitHubPRsPanel-BDRwwKEv.js → GitHubPRsPanel-wI3c7FXN.js} +1 -1
  22. package/web-app/dist/assets/{HomePage-CJTtOioN.js → HomePage-D0I9ynlm.js} +2 -2
  23. package/web-app/dist/assets/{LoginPage-JIVkLQYa.js → LoginPage-D8LASaQy.js} +1 -1
  24. package/web-app/dist/assets/{MagicPage-BNOu4EI8.js → MagicPage-7pN712yu.js} +1 -1
  25. package/web-app/dist/assets/{MetricsPage-B3zM1C1m.js → MetricsPage-SYE4uoW7.js} +1 -1
  26. package/web-app/dist/assets/{NotFoundPage-DBLh8qXC.js → NotFoundPage-COLnaZjq.js} +1 -1
  27. package/web-app/dist/assets/{ProjectPage-BDFdb9Fj.js → ProjectPage-By5qFEGq.js} +3 -3
  28. package/web-app/dist/assets/{ProjectsPage-D94WjRFa.js → ProjectsPage-Csz7HVHr.js} +1 -1
  29. package/web-app/dist/assets/{SettingsPage-CvkMM5iT.js → SettingsPage-Bq7pcVxt.js} +1 -1
  30. package/web-app/dist/assets/{ShowcasePage-D6O2PqKs.js → ShowcasePage-mXVtkKWQ.js} +1 -1
  31. package/web-app/dist/assets/{SystemSettingsPage-CcNh0RDf.js → SystemSettingsPage-CGQrZ2C1.js} +1 -1
  32. package/web-app/dist/assets/{TeamsPage-BTnlB9vQ.js → TeamsPage-DtZ-QAXz.js} +1 -1
  33. package/web-app/dist/assets/{TemplatesPage-BDVNlobK.js → TemplatesPage-MSw7MEK9.js} +1 -1
  34. package/web-app/dist/assets/{TerminalOutput-BbhmzMWZ.js → TerminalOutput-DtXZZRio.js} +1 -1
  35. package/web-app/dist/assets/{activity-CzpvMfJh.js → activity-BwTdw5jH.js} +1 -1
  36. package/web-app/dist/assets/{bell-CFe5uNCw.js → bell-k9cBjzVC.js} +1 -1
  37. package/web-app/dist/assets/{bot-Co9atvO1.js → bot-tPDhUZdF.js} +1 -1
  38. package/web-app/dist/assets/{check-D3zw6xf0.js → check-55rEw_tX.js} +1 -1
  39. package/web-app/dist/assets/{chevron-left-Crx6bo4v.js → chevron-left-De8fDgTg.js} +1 -1
  40. package/web-app/dist/assets/{circle-alert--XExSKHo.js → circle-alert-C73LIkta.js} +1 -1
  41. package/web-app/dist/assets/{clock-COELjcX4.js → clock-DwN_q_HA.js} +1 -1
  42. package/web-app/dist/assets/{cloud-C1YYttuv.js → cloud-Bf2eze4m.js} +1 -1
  43. package/web-app/dist/assets/{code-xml-Bu_Gz2N-.js → code-xml-DrPbJQRA.js} +1 -1
  44. package/web-app/dist/assets/{database-BtRK0egx.js → database-DTI91kcw.js} +1 -1
  45. package/web-app/dist/assets/{dollar-sign-CaDqc5Da.js → dollar-sign-ZkSJEKpU.js} +1 -1
  46. package/web-app/dist/assets/{file-code-corner-CiDOLyIG.js → file-code-corner-Ms-tOQKC.js} +1 -1
  47. package/web-app/dist/assets/{file-plus-BXY2rccH.js → file-plus-CFYKVztN.js} +1 -1
  48. package/web-app/dist/assets/{globe-CgUnp7ir.js → globe-Bqb_jTXY.js} +1 -1
  49. package/web-app/dist/assets/{hammer-C51wUR1B.js → hammer-DdgoSBL0.js} +1 -1
  50. package/web-app/dist/assets/{index-DkqOX7Z7.js → index-C5bIS38k.js} +3 -3
  51. package/web-app/dist/assets/{layers-B5gYhrpd.js → layers-mX-L1IoG.js} +1 -1
  52. package/web-app/dist/assets/{loader-circle-BeigjxhD.js → loader-circle-BSxzcRoH.js} +1 -1
  53. package/web-app/dist/assets/{lock-BVUQu1ou.js → lock-D9acVIOc.js} +1 -1
  54. package/web-app/dist/assets/{package-C7y3L1uC.js → package-BJHi7Tn6.js} +1 -1
  55. package/web-app/dist/assets/{plus-DFUI0m8Z.js → plus-BH0QfTxz.js} +1 -1
  56. package/web-app/dist/assets/{refresh-cw-Cc5RjW2p.js → refresh-cw-DtvtryKd.js} +1 -1
  57. package/web-app/dist/assets/{rotate-ccw-Bk-kLPsX.js → rotate-ccw-7pZ7tfog.js} +1 -1
  58. package/web-app/dist/assets/{scroll-text-4DceQ6It.js → scroll-text-LEEOPYAl.js} +1 -1
  59. package/web-app/dist/assets/{server-erFY-iD9.js → server-h-gDqp3u.js} +1 -1
  60. package/web-app/dist/assets/{shield-alert-Dh2woWQf.js → shield-alert-WL6uL9Y1.js} +1 -1
  61. package/web-app/dist/assets/{thumbs-up-DFgETaoZ.js → thumbs-up-CsnDxpb3.js} +1 -1
  62. package/web-app/dist/assets/{trash-2-eHsWQHfi.js → trash-2-ChNwPVVE.js} +1 -1
  63. package/web-app/dist/assets/{trending-down-5DwF4BMm.js → trending-down-BHSEDHSP.js} +1 -1
  64. package/web-app/dist/assets/{trending-up-BkjfOvvM.js → trending-up-D1K9uAn2.js} +1 -1
  65. package/web-app/dist/assets/{upload-CSxnKVOV.js → upload-BhYbtn7Q.js} +1 -1
  66. package/web-app/dist/assets/{usePolling-CYmWnlrJ.js → usePolling-DL4MFc7x.js} +1 -1
  67. package/web-app/dist/assets/{user-CAbIEZrD.js → user-CHnU9Yb4.js} +1 -1
  68. package/web-app/dist/index.html +1 -1
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: loki-mode
3
3
  description: Runs an autonomous software factory that knows what it is supposed to deliver and proves it did, with a signed receipt. Use when the user says Loki Mode or asks to build, fix or verify software autonomously.
4
4
  ---
5
5
 
6
- # Loki Mode v11.71.0
6
+ # Loki Mode v11.71.2
7
7
 
8
8
  **Current entry points (Loki 10 engine):** `loki "<task>"`, `loki owner/repo#N` and `loki quick "<task>"` run the Loki 10 engine and end with a signed receipt (`loki verify`). `loki backlog owner/repo --all` runs many issues in parallel. Guide: `docs/v10/GUIDE.md`. The skill instructions below, and `loki start`, describe the previous bash loop. PRD-file starts (`loki start ./prd.md`) and the opencode provider still run on it until FC38-SWEEP ports them; the legacy-engine command and the LOKI_ENGINE switch remain removed. Prefer `loki owner/repo#N` for issues.
9
9
 
@@ -476,4 +476,4 @@ Implemented, planned and deprecated items, with the version each landed in: `ski
476
476
 
477
477
  ---
478
478
 
479
- **v11.71.0 | [Autonomi](https://www.autonomi.dev/) flagship product | core skill**
479
+ **v11.71.2 | [Autonomi](https://www.autonomi.dev/) flagship product | core skill**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 11.71.0
1
+ 11.71.2
@@ -7,6 +7,6 @@ Modules:
7
7
  control: Session control helpers (status, atomic writes, origin check)
8
8
  """
9
9
 
10
- __version__ = "11.71.0"
10
+ __version__ = "11.71.2"
11
11
 
12
12
  __all__ = ["__version__"]
@@ -1,6 +1,6 @@
1
1
  # CLI reference
2
2
 
3
- Generated from `loki-ts/src/cli/registry.ts` by `scripts/generate-stale-zero.sh` for v11.71.0. Do not edit by hand.
3
+ Generated from `loki-ts/src/cli/registry.ts` by `scripts/generate-stale-zero.sh` for v11.71.2. Do not edit by hand.
4
4
  Hidden and legacy-only commands are omitted; see `docs/v10/CLI-MODERN.md` for the full inventory.
5
5
 
6
6
  | Command | Description |
@@ -2,7 +2,7 @@
2
2
 
3
3
  Loki Mode, by [Autonomi](https://www.autonomi.dev/), turns a spec or an issue into a verified pull request with a receipt you can check. This page covers installing it, a first run, and the options around it.
4
4
 
5
- **Version:** v11.71.0
5
+ **Version:** v11.71.2
6
6
 
7
7
  **Engine note:** `loki start` is the primary command. `loki start`, `loki "<task>"`, `loki owner/repo#N` and `loki quick` all run the Loki 10 engine, whatever the flag order or input form (PRD file, issue ref, task or one-word brief). The previous loop runs only on `--engine legacy`, `LOKI_ENGINE=legacy`, or for one call when a flag Loki 10 cannot honor is present. See the [user guide](v10/GUIDE.md) and the [5-minute quickstart](QUICKSTART.md).
8
8
 
@@ -1780,6 +1780,15 @@ L0 review rule (ENGINE-LAWS.md L0): a fix that adds an `if` or a regex about the
1780
1780
  - Mechanism: collectRuns reads join(proj.path, ".loki", "runs") for each registered project and ignores LOKI_DIR.
1781
1781
  - Fixture: loki-ts/tests/commands/run_status.test.ts "LOKI_DIR set across 2 projects lists each run once under its own repo"; a mutant restoring runsRoot(env, proj.path) turns it red.
1782
1782
 
1783
+ ## FC-RUNSH-LINE-CITE-DRIFT Comments in loki-ts/src cite autonomy/run.sh by line number, and the numbers go stale on every run.sh edit
1784
+ - User-visible vs raw: raw (maintainer-facing). A reader following "run.sh:28272" lands on unrelated code and trusts a parity claim that no longer points at its subject. #212 criterion 2 failed twice for this (the PAUSED.md cite was refreshed and went stale again).
1785
+ - Law: a cross-file reference names a thing that survives edits (function, variable or literal string), never a position.
1786
+ - Cause (measured, eng-npm 2026-10-23, origin/main): `git grep -nE 'run\.sh[: (~]+[0-9]{4,}' loki-ts/src` returned 279 lines in 21 files; the cites were already wrong when written against older run.sh (the PAUSED.md cite ~28272 resolved to a different line on 5746a4550).
1787
+ - Siblings swept: the same pattern in loki-ts/src outside runner/ (providers/claude_flags.ts and others, same grep). Cites to other files (manager.ts:1770) and line cites in docs/ are out of scope; they drift the same way and are not guarded here.
1788
+ - Mechanism: one structural check, "no script line cites in loki-ts/src", in scripts/structural-checks.sh (so pre-push and CI run it), scanning loki-ts/src for `(run.sh|autonomy/loki|completion-council.sh)` followed by a 3-or-more digit line number (the siblings were folded in under D86).
1789
+ - Fixture: tests/test-structural-checks.sh T13 plants a `run.sh:12345` cite in a scratch tree (check goes red) and an anchored "autonomy/run.sh (the _resume_line assignment)" cite (stays green).
1790
+ - Remediation: all 279 cite lines were rewritten to name an anchor: `run.sh <function>()` or `run.sh "<unique literal>"`, located from the comment text and the matching TS code via grep on the current run.sh, never from the old numbers (run.sh grew about 2.5x since they were written). 0 cites were unrecoverable. Where the logic is inline in run_autonomous() the anchor is that function. Three header lists (budget.ts, rarv.ts, checkpoint.ts) that cited bare line numbers without the run.sh prefix now list function names only. The 21 sibling cites to autonomy/loki and completion-council.sh (commands/doctor.ts, commands/status.ts, council/voter_agents.ts, runner/council.ts) and 5 three-digit run.sh cites were anchored the same way. Unrecoverable referent: 6 cites in commands/doctor.ts pointed at bash doctor code (_doctor_block, doctor_provider_install_cmd, text-mode cmd_doctor) that no longer exists in autonomy/loki because doctor is Bun-only; they now say so instead of citing a line.
1791
+
1783
1792
  ## FC-PROOF-POINTER-STALE-ON-BUN-ROUTE The Bun route never cleared .loki/state/last-proof-id.txt at run start, so a run that stopped before proof generation left the previous run's id and every reader showed a receipt for different work
1784
1793
 
1785
1794
  - User-visible vs raw: user-visible (receipt and summary sections name the wrong run).
@@ -170,7 +170,7 @@ Tier follows docs/v10/OPERATING-MODEL.md: HIGH touches the moat, verifier, Seal,
170
170
  | 41 | R100-041 | team | Team login for the shared Control Plane | L | HIGH | #188 (existing) |
171
171
  | 42 | R100-042 | team | Bitbucket and Azure DevOps pull requests | M | MEDIUM | #390 |
172
172
  | 43 | R100-043 | team | Release notes written from sealed receipts | S | LOW | #391 |
173
- | 44 | R100-044 | ide | VS Code extension: run panel and receipt viewer | L | MEDIUM | #392 |
173
+ | 44 | R100-044 | ide | VS Code access through the shipped MCP server: config doc and tool-list smoke test | S | LOW | #392 |
174
174
  | 45 | R100-045 | ide | Ready-made ACP configs for Zed and JetBrains | S | LOW | #393 |
175
175
  | 46 | R100-046 | ide | Start, status and seal commands in the Claude Code plugin | S | LOW | #394 |
176
176
  | 47 | R100-047 | ide | Full-screen terminal UI with approve, steer and pause keys | M | LOW | #395 |
@@ -255,6 +255,7 @@ Items that reuse an existing issue carry their acceptance criteria in that issue
255
255
  #### R100-003 In-place resume after a human answers a blocked question
256
256
 
257
257
  - Issue: #358. Area: autonomy. Size: L. Tier: MEDIUM. Deps: #278, #353, journal (#283, closed).
258
+ - Already exists (corrected 2026-10-23): `loki answer [<run-id>]` already ships in `loki-ts/src/features/blocked_answer.ts` (D63-C4), but the answer starts a new run. This item is the in-place resume under the same run id.
258
259
  - Problem: Today a BLOCKED engine10 run is terminal; a Slack reply starts a new follow-up run (`loki-ts/src/contrib/slack_inbound.ts` lines 2-4), so completed work is re-done and users abandon blocked runs.
259
260
  - Feature: A blocked run parks with its journal intact. `loki answer <run> "<text>"`, a Slack thread reply, or a PR comment resumes the same run id and skips completed slices.
260
261
  - Acceptance:
@@ -301,6 +302,7 @@ Items that reuse an existing issue carry their acceptance criteria in that issue
301
302
  #### R100-007 Live run view: `loki status --follow` streams stages, edits, tests and cost
302
303
 
303
304
  - Issue: #361. Area: speed. Size: S. Tier: LOW. Deps: event log.
305
+ - Already exists (corrected 2026-10-23): `loki cockpit --follow` already exists as an inline-image multi-repo view. This item is the text and JSONL stream for one run in `loki-ts/src/commands/status.ts`.
304
306
  - Problem: During a long run users see little; they cancel runs that were progressing.
305
307
  - Feature: `loki status --follow [--json]` prints one line per event (stage, file edited, test result, cost) and Ctrl-C detaches without stopping the run (extends `status.ts` and the event log).
306
308
  - Acceptance:
@@ -314,6 +316,7 @@ Items that reuse an existing issue carry their acceptance criteria in that issue
314
316
  #### R100-008 Background runs and one run list across repos
315
317
 
316
318
  - Issue: #362. Area: autonomy. Size: M. Tier: MEDIUM. Deps: #232.
319
+ - Already exists (corrected 2026-10-23): `loki start --bg` and `--detach` already exist in `autonomy/loki`, and `loki projects` lists registered repos. This item is `loki runs`, `loki attach` and `loki runs stop` only.
317
320
  - Problem: A run ties up the terminal; users with several repos cannot see every running build in one place.
318
321
  - Feature: `loki start --bg` returns a run id, `loki runs` lists every run across registered projects (`loki projects`) with state, cost and verdict, and `loki attach <id>` re-joins one.
319
322
  - Acceptance:
@@ -416,6 +419,7 @@ Items that reuse an existing issue carry their acceptance criteria in that issue
416
419
  #### R100-017 Single-binary install with no node or python3 required
417
420
 
418
421
  - Issue: #369. Area: onboarding. Size: M. Tier: MEDIUM. Deps: FR-B.
422
+ - Already exists (corrected 2026-10-23): `build:binary` (`bun build --compile`) already exists in `loki-ts/package.json`. This item is building and attaching the 5 targets in `.github/workflows/release.yml`.
419
423
  - Problem: Install needs node, python3, jq, git and curl plus a provider; each missing tool is a dead end.
420
424
  - Feature: Release attaches compiled binaries (Bun compile) so the v10 path needs only git and a provider CLI (extends FR-B).
421
425
  - Acceptance:
@@ -428,6 +432,7 @@ Items that reuse an existing issue carry their acceptance criteria in that issue
428
432
  #### R100-018 Automatic rollback on all four deploy providers
429
433
 
430
434
  - Issue: #370. Area: deploy. Size: M. Tier: MEDIUM. Deps: DEP-B, DEP-D.
435
+ - Already exists (corrected 2026-10-23): `--auto-rollback` already exists on `loki start` and `loki deploy`, for Vercel and Fly only. This item adds Netlify, Cloudflare and a timed health watch.
431
436
  - Problem: `loki rollback deploy` prints the rollback command but never runs it; a bad deploy stays live until a human acts.
432
437
  - Feature: With `--auto-rollback`, a failed health watch after deploy runs the provider rollback, records it in the receipt, and notifies (DEP-B, DEP-D).
433
438
  - Acceptance:
@@ -527,6 +532,7 @@ Items that reuse an existing issue carry their acceptance criteria in that issue
527
532
  #### R100-027 Desktop and phone push notifications when a run needs you or finishes
528
533
 
529
534
  - Issue: #377. Area: speed. Size: S. Tier: LOW. Deps: notify.
535
+ - Already exists (corrected 2026-10-23): Desktop notifications already exist on the legacy route (`send_notification` in `autonomy/run.sh`), and `loki notify` sends to slack, discord and webhook. This item adds a desktop channel and ntfy to `loki notify` and engine10.
530
536
  - Problem: Users miss a blocked question for hours because notify only covers Slack, Discord and webhooks.
531
537
  - Feature: Add `desktop` (macOS and Linux) and `ntfy` channels to `loki notify`, fired on blocked, done and failed.
532
538
  - Acceptance:
@@ -539,6 +545,7 @@ Items that reuse an existing issue carry their acceptance criteria in that issue
539
545
  #### R100-028 Best-of-N implement for small tasks
540
546
 
541
547
  - Issue: #378. Area: speed. Size: M. Tier: MEDIUM. Deps: M-17 scheduler.
548
+ - Already exists (corrected 2026-10-23): Two parallel attempts already exist behind `LOKI_E10_ATTEMPTS=2` (default off) in `loki-ts/src/features/attempts.ts`. This item makes that the default for small tasks and records the arms in the receipt.
542
549
  - Problem: One unlucky attempt costs a whole retry round.
543
550
  - Feature: `LOKI_BEST_OF=2` runs 2 implementations in parallel worktrees on the cheap tier and keeps the first that seals (extends the modernize best-of-2 scheduler to start).
544
551
  - Acceptance:
@@ -551,6 +558,7 @@ Items that reuse an existing issue carry their acceptance criteria in that issue
551
558
  #### R100-029 Warm engine daemon for sub-second start
552
559
 
553
560
  - Issue: #379. Area: speed. Size: M. Tier: MEDIUM. Deps: SPD-B.
561
+ - Already exists (corrected 2026-10-23): The warm engine already ships (D61): `loki-ts/src/features/warm.ts` and `warm_client.ts`, on by default. This item is limited to measuring startup overhead and a read-only `loki daemon status`; if warm p50 is already at or under 1 s, #379 closes as a duplicate of D61.
554
562
  - Problem: Each `loki start` pays engine boot, repo map and test map cost.
555
563
  - Feature: `loki daemon` keeps the Bun engine, repo map and test map warm per repo; `loki start` attaches when it is running.
556
564
  - Acceptance:
@@ -718,15 +726,15 @@ Items that reuse an existing issue carry their acceptance criteria in that issue
718
726
  - Metric and target: Teams using it per release; week-4 retention.
719
727
  - Competitor baseline: Claude Code: UNKNOWN. Codex CLI: UNKNOWN. Devin: UNKNOWN. Factory droid: UNKNOWN.
720
728
 
721
- #### R100-044 VS Code extension: run panel and receipt viewer
729
+ #### R100-044 VS Code access through the shipped MCP server: config doc and tool-list smoke test
722
730
 
723
- - Issue: #392. Area: ide. Size: L. Tier: MEDIUM. Deps: R100-007.
731
+ - Issue: #392. Area: ide. Size: S. Tier: LOW. Deps: none.
724
732
  - Problem: VS Code users must switch to a terminal to start, steer and read receipts.
725
- - Feature: An extension that starts runs, follows status, answers blocked questions and renders the receipt and clause matrix, talking to the CLI (no new engine).
733
+ - Feature: Rescoped 2026-10-23 by team-lead ruling. The deprecated `vscode-extension/` is not revived. VS Code users reach Loki through the MCP server that already ships (`mcp/server.py`), registered by `loki mcp install --client vscode`. The work is a documented VS Code MCP config and one smoke test that lists the tools over that config.
726
734
  - Acceptance:
727
- - The extension activates in VS Code and lists the current run from `loki status --json` within 2 s.
728
- - Start, steer and answer buttons call the CLI; a fixture asserts 3 CLI invocations.
729
- - Receipt view shows verdict and N of N clauses equal to `loki proof` output.
735
+ - docs/INSTALLATION.md shows the `.vscode/mcp.json` that `loki mcp install --client vscode --project` writes, and names `loki_v10_run`, `loki_v10_status` and `loki_v10_verify`.
736
+ - A smoke test launches the server from the written config and finds those 3 tools by name in `tools/list`.
737
+ - No file under `vscode-extension/` or `scripts/release.sh` changes.
730
738
  - Metric and target: Runs per user per week for VS Code users; week-2 return rate.
731
739
  - Competitor baseline: Claude Code: `--ide` connects to an IDE on startup (`claude --help`, Claude Code 2.1.309, run 2026-10-23). Codex CLI: Codex IDE extension (https://learn.chatgpt.com/docs/codex/cli (fetched 2026-10-23)). Devin: Embedded editor in Devin Session Tools; no VS Code page in the index (https://docs.devin.ai/work-with-devin/devin-session-tools.md, listed in https://docs.devin.ai/llms.txt, fetched 2026-10-23). Factory droid: IDE integrations page (https://docs.factory.com/cli/getting-started/overview (fetched 2026-10-23)).
732
740
 
@@ -1336,3 +1344,121 @@ Items that reuse an existing issue carry their acceptance criteria in that issue
1336
1344
  - Problem: Clauses from documents cannot point back to their source.
1337
1345
  - Metric and target: Clauses traced to source.
1338
1346
  - Competitor baseline: Claude Code: UNKNOWN. Codex CLI: UNKNOWN. Devin: UNKNOWN. Factory droid: UNKNOWN.
1347
+
1348
+ ## Lanes and waves
1349
+
1350
+ This section is the dispatch source for Feature 100 (accepted by team-lead on 2026-10-23). It was built from the file set in every one of the 100 issue cards: the issue body for the 79 new issues, and the issue body plus comments for the 21 reused issues, all read on 2026-10-23. Test files are not counted as shared files.
1351
+
1352
+ Where the "Parallel safety" line inside an issue card disagrees with this section, this section wins. Several of those lines were written before the file sets were narrowed. For example, #357, #339 and #396 name #359 and #362 as start.ts sharers, but neither #359 nor #362 edits start.ts.
1353
+
1354
+ ### Hot-spot lanes
1355
+
1356
+ Rule: each hot-spot file has exactly one live writer. The next issue in a lane starts only after the previous one has merged to main, and it rebases on main before it starts. An issue that sits in two lanes waits until both lanes reach it.
1357
+
1358
+ - `loki-ts/src/commands/start.ts`: #357, then #339, then #396, then #372.
1359
+ - `loki-ts/src/commands/status.ts`: #361, then #359, then #370, then #372, then #395, then #406.
1360
+ - `loki-ts/src/engine10/machine.ts`: #345, then #358, then #235. #345 waits for live branches pd/cw12 and pd/cw12-r2, which edit `machine.ts`, `cli.ts` and `mcp/server.py`. #358 also waits for branch pd/cw04d, which edits `blocked_answer.ts`.
1361
+ - `autonomy/loki` function `cmd_deploy`: #359, then #370, then #382, then #383, then #384, then #385, then #386.
1362
+ - `.github/actions/issue-to-pr/action.yml`: #360, then #365.
1363
+
1364
+ 19 issues edit at least one hot-spot file: #235, #339, #345, #357, #358, #359, #360, #361, #365, #370, #372, #382, #383, #384, #385, #386, #395, #396, #406.
1365
+
1366
+ Three cards name a hot-spot file without editing it, so they are not in a lane. #351 says "do not touch machine.ts". #370 cites `start.ts` only as existing behavior; it is still in the status.ts and cmd_deploy lanes. #398 names `packages/control-plane/src/server/routes/start.ts`, which is a different file.
1367
+
1368
+ ### Parallel-safe with respect to the hot-spot files
1369
+
1370
+ These 81 issues edit none of the five hot-spot files, in rank order: #342, #362, #363, #364, #249, #366, #367, #368, #369, #371, #351, #231, #373, #374, #375, #376, #377, #378, #379, #380, #279, #381, #387, #388, #389, #188, #390, #391, #392, #393, #394, #397, #398, #399, #248, #400, #401, #402, #403, #404, #405, #407, #408, #409, #410, #290, #411, #412, #413, #414, #267, #346, #347, #415, #416, #417, #418, #277, #278, #232, #419, #420, #421, #422, #423, #424, #425, #426, #427, #428, #429, #430, #431, #343, #432, #433, #434, #341, #340, #263, #435.
1371
+
1372
+ Parallel-safe here means safe against the hot-spot lanes only. Two of these issues can still share another file. Before two of them run at the same time, check the other shared-file lanes below.
1373
+
1374
+ ### Other shared-file lanes
1375
+
1376
+ One live writer per file, in the order given.
1377
+
1378
+ - `loki-ts/src/commands/doctor.ts`: #357, #366, #290, #347, #390, #413, #414, #432.
1379
+ - `loki-ts/src/cli/registry.ts`: #362, #375, #379, #395, #400, #401, #430.
1380
+ - `loki-ts/src/engine10/events.ts`: #361, #358, #431.
1381
+ - `loki-ts/src/engine10/session.ts`: #358, #351, #406, #415. If pd/cw04d holds #358 up, #351 goes first.
1382
+ - `loki-ts/src/engine10/pr_body.ts`: #342, #359, #381, #387, #388.
1383
+ - `loki-ts/src/engine10/stages/pr.ts`: #231, #387, #390.
1384
+ - `loki-ts/src/engine10/verify_cmd.ts`: #380, #372, #434.
1385
+ - `loki-ts/src/engine10/supervisor.ts` and `loki-ts/src/util/slack_events.ts`: #427, #411, #406.
1386
+ - `loki-ts/src/runner/build_prompt.ts`: #366, #402, #432. New always-on text goes in the cache-stable prefix.
1387
+ - `.github/workflows/release.yml`: #369, #372.
1388
+ - `blocked_answer.ts`: branch pd/cw04d, #358, #363, #399, #412.
1389
+ - `loki-ts/src/commands/memory.ts`: #364, #389, #400, #401, #402.
1390
+ - `loki-ts/src/util/pr_lessons.ts`: #364, #389, #405.
1391
+ - `loki-ts/src/runner/router/cost_preview.ts`: #367, #374, #407, #412.
1392
+ - `loki-ts/src/commands/proof.ts`: #368, #434, #435.
1393
+ - `loki-ts/src/commands/kpis.ts` and `metrics/kpis.ts`: #371, #411, #424.
1394
+ - `loki-ts/src/features/visual_evidence.ts`: #249, #263, #383.
1395
+ - `loki-ts/src/util/redact.ts`: #384, #389, #421.
1396
+ - `loki-ts/src/runner/budget.ts`: #408, #411, #412.
1397
+ - `loki-ts/src/runner/providers.ts`: #279, #346, #277, #278.
1398
+ - `providers/model_routes.ts`: #267, #346, #414, #415.
1399
+ - `providers/model_catalog.json`: #267, #346, #416.
1400
+ - `providers/model_routes.sh`: #414, #415, #416.
1401
+ - `providers/price_table.ts`: #279, #411, #417.
1402
+ - `mcp/server.py`: #345, #290, #339.
1403
+ - Control Plane `App.tsx`: #363, #403, #423.
1404
+ - Control Plane `pages/run/index.tsx`: #422, #423, #425.
1405
+ - `autonomy/loki` dispatch rows: #367, #232, #379, #418, #419.
1406
+ - `autonomy/loki` `cmd_cost`: #407, #408, #409, #410.
1407
+ - `autonomy/loki` `cmd_next`: #374, #375.
1408
+ - `autonomy/loki` `cmd_template`: #404, #428.
1409
+ - `autonomy/loki` `cmd_notify`: #377, #424.
1410
+ - `autonomy/loki` `cmd_verify` and `fast_verify.py`: #380, #430.
1411
+ - `autonomy/notify.sh`: #377, #427, #406, #399, #424, #431.
1412
+ - Pairs, first one merges first: `decompose.ts` (#235, #419), `unit_mode.ts` (#235, #421), `slack_inbound.ts` (#358, #381), Control Plane `answer.ts` (#363, #399), `schemas/run-event.schema.json` (#431, #433).
1413
+
1414
+ Different functions in `autonomy/loki` can be edited in parallel, because each lane above names its own function.
1415
+
1416
+ ### Waves
1417
+
1418
+ Wave 1 can start now. Each issue heads every lane it is in, and no two share a file. Each one was checked against every live branch (remote pd/* and local branches with a commit in the last 48 hours) with `git cherry origin/main <branch>` and `git log origin/main..<branch> --name-only`, on 2026-10-23. Dispatch in this order as seats free up:
1419
+
1420
+ - #357: already dispatched (pd/r100-001). `doctor_fix.ts` is touched only by its own branch. `doctor.ts` is also touched by 14 live branches (pd/286, pd/315, pd/316, pd/316-rb, pd/329, pd/330, pd/bunentry, pd/bunentry-rb, pd/bunsib, pd/mcpchain, pd/mcpchain-r2, pd/mcpchain-r3, pd/rq04, pd/w2-33), so rebase before review.
1421
+ - #342, #360, #364, #368, #231, #422: no live branch touches any of their files.
1422
+ - #361: no file overlap. Its card names `autonomy/loki` only as existing behavior (`cmd_cockpit`); its edits are in `status.ts` and `events.ts`.
1423
+ - #362: the only overlap is `autonomy/loki`. The live branches there edit `_loki_airgap_audit`, `cmd_bench` and `_loki_start_optval_consumes`. #362 adds dispatch rows and reads `cmd_projects`, so the hunks do not overlap.
1424
+
1425
+ Wave 2. Each issue starts after the merges named:
1426
+
1427
+ - #345: after pd/cw12 and pd/cw12-r2 (`machine.ts`, `cli.ts`, `mcp/server.py`), pd/328 (`cli.ts`), and pd/257p2, pd/257rb, pd/319e, pd/319fix (`mcp/server.py`).
1428
+ - #249: after the live `stages/verify.ts` branches: pd/237r10, pd/237r9, pd/partial-harness, pd/wallfile, pd/wallfile-r2, pd/wallgo, pd/wallgo-r2, pd/wallnorunner, pd/wallrust, pd/wallrust-r2, pd/weaktest.
1429
+ - #367: after the live `benchmarks/bench/run.sh` and `runner.py` branches: pd/246fix2, pd/claim, pd/claim-100x, pd/cw15, pd/fd1b, pd/resumecost, pd/resumecost2, pd/resumecost3, pd/traptasks2, pd/trusttime, pd/trusttime-r2, pd/verifyh2h.
1430
+ - #369: after pd/cw01b and pd/cw01c (`release.yml`).
1431
+ - #371: after pd/252b and pd/252b-r (`metrics/kpis.ts`).
1432
+ - #358: after #345, #361 and branch pd/cw04d.
1433
+ - #359: after #361 and #342.
1434
+ - #365: after #360.
1435
+ - #366: after #357.
1436
+ - #370: after #359.
1437
+ - #235: after #358.
1438
+ - #363: after #358.
1439
+ - #372: after #369, #357 and #370.
1440
+
1441
+ Held: #398 depends on open issue #188 (dashboard authn/authz), so it is not a wave-1 head.
1442
+
1443
+ Before dispatching any wave-2 issue, re-run the live-branch check for its files; branches named above may have merged or new ones may have started.
1444
+
1445
+ After wave 2, pull any issue whose lanes are free, following the lane orders above.
1446
+
1447
+ ### Wave-1 assignments
1448
+
1449
+ Checked on 2026-10-23 at 06:50Z against `gh issue view` comments and origin branches. None of these issues has a GitHub assignee, so claims come from issue comments or team-lead dispatch. "Behind" counts commits on origin/main that the branch lacks.
1450
+
1451
+ | Issue | Item | Engineer | Branch | Reviewer | Tier | State |
1452
+ |---|---|---|---|---|---|---|
1453
+ | #357 | R100-001 | eng-mcpchain | pd/r100-001 9feace648 (1 ahead, 16 behind) | unset | MEDIUM | Needs rebase. Criterion 3 NOT MET on both the branch and its base 3f6e07547 (issue comment 06:39Z); the PARTIAL predates the change. |
1454
+ | #342 | R100-006 | eng-r237 | none | unset | HIGH | Waiting on CW-04 (#337), which is OPEN with no commit on main. Ruling comment 06:39Z. |
1455
+ | #360 | R100-005 | unowned | none | unset | HIGH | No claim comment, no branch. Free to assign. |
1456
+ | #364 | R100-011 | eng-tmo | pd/364a fee344a42 (1 ahead, 8 behind); pd/364b 808c40cab stacked on (a) | tl-324 | MEDIUM | In review. Criteria tally comment 06:45Z; merge-tree rc=0 against origin/main 0a6ae7cb6. |
1457
+ | #368 | R100-016 | eng-318r | none | rev-b | HIGH | Dispatched by team-lead. No claim comment or branch yet. |
1458
+ | #231 | R100-022 | eng-tmo | none | tl-324 | MEDIUM | Dispatched by team-lead. Only the slice card comment (06:14Z); no claim comment or branch yet. |
1459
+ | #422 | R100-082 | eng-351 | none | unset | LOW | Starts after the loadaware fix. No claim comment or branch yet. |
1460
+ | #361 | R100-007 | eng-cw01 | pd/361 ece154741 (1 ahead, 11 behind) | tl-324 | LOW | In review. No claim comment on the issue. |
1461
+ | #362 | R100-008 slice (a) | eng-mcpchain | pd/r100-008a 861656d44 (1 ahead, 8 behind) | unset | MEDIUM | Claimed in comment 06:46Z after eng-r237 released it. Slice (b) unowned. |
1462
+ | #249 | R100-013 slice (a) | eng-r237 | pd/249a 721db86f3 (1 ahead, 0 behind) | rev-c | HIGH | In review. Slice (a) edits only `visual_evidence.ts`, which team-lead cleared out of wave 2. Slice (b) stays in wave 2 behind the `stages/verify.ts` branches. |
1463
+
1464
+ Unowned: #360, #362 slice (b) and #249 slice (b). No reviewer yet: #357, #342, #360, #362 and #422.
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- var dh0=Object.create;var{getPrototypeOf:lh0,defineProperty:pK,getOwnPropertyNames:Mn,getOwnPropertyDescriptor:ah0}=Object,On=Object.prototype.hasOwnProperty;function An(Z){return this[Z]}var ih0,oh0,nh0=(Z,$,J)=>{var X=Z!=null&&typeof Z==="object";if(X){var Y=$?ih0??=new WeakMap:oh0??=new WeakMap,Q=Y.get(Z);if(Q)return Q}J=Z!=null?dh0(lh0(Z)):{};let z=$||!Z||!Z.__esModule?pK(J,"default",{value:Z,enumerable:!0}):J;for(let W of Mn(Z))if(!On.call(z,W))pK(z,W,{get:An.bind(Z,W),enumerable:!0});if(X)Y.set(Z,z);return z},sh0=(Z)=>{var $=(Nn??=new WeakMap).get(Z),J;if($)return $;if($=pK({},"__esModule",{value:!0}),Z&&typeof Z==="object"||typeof Z==="function"){for(var X of Mn(Z))if(!On.call($,X))pK($,X,{get:An.bind(Z,X),enumerable:!(J=ah0(Z,X))||J.enumerable})}return Nn.set(Z,$),$},Nn,UM=(Z,$)=>()=>($||Z(($={exports:{}}).exports,$),$.exports);var rh0=(Z)=>Z;function th0(Z,$){this[Z]=rh0.bind(null,$)}var j0=(Z,$)=>{for(var J in $)pK(Z,J,{get:$[J],enumerable:!0,configurable:!0,set:th0.bind($,J)})};var S=(Z,$)=>()=>(Z&&($=Z(Z=0)),$);var e9=import.meta.require;var jn={};j0(jn,{lokiDirFor:()=>NM,lokiDir:()=>D0,homeLokiDir:()=>T2,findRepoRootForVersion:()=>cK,REPO_ROOT:()=>F0});import{resolve as wZ,dirname as iE}from"path";import{fileURLToPath as eh0}from"url";import{existsSync as BM}from"fs";import{homedir as Zf0}from"os";function $f0(){let Z=Ln;for(let $=0;$<6;$++){if(BM(wZ(Z,"VERSION"))&&BM(wZ(Z,"autonomy/run.sh")))return Z;let J=iE(Z);if(J===Z)break;Z=J}return wZ(Ln,"..","..","..")}function cK(Z){let $=Z;for(let J=0;J<6;J++){if(BM(wZ($,"VERSION"))&&BM(wZ($,"autonomy/run.sh")))return $;let X=iE($);if(X===$)break;$=X}return wZ(Z,"..","..","..")}function NM(Z){return process.env.LOKI_DIR??wZ(Z,".loki")}function D0(){return NM(process.cwd())}function T2(){return wZ(Zf0(),".loki")}var Ln,F0;var s0=S(()=>{Ln=iE(eh0(import.meta.url));F0=$f0()});import{readFileSync as Jf0}from"fs";import{resolve as Xf0,dirname as Yf0}from"path";import{fileURLToPath as Qf0}from"url";function O6(){if(g1!==null)return g1;let Z="11.71.0";if(typeof Z==="string"&&Z.length>0)return g1=Z,g1;try{let $=Yf0(Qf0(import.meta.url)),J=cK($);g1=Jf0(Xf0(J,"VERSION"),"utf-8").trim()}catch{g1="unknown"}return g1}var g1=null;var _Z=S(()=>{s0()});import{mkdirSync as nE,readFileSync as MM,realpathSync as zf0,statSync as Wf0,writeFileSync as sE}from"fs";import{dirname as MY,join as oE,resolve as Cn}from"path";function qf0(){return Cn(T2(),"cache","update-check.json")}function xZ(Z){let $=/^(\d+)\.(\d+)\.(\d+)$/.exec(Z.trim());if(!$)return null;return[Number($[1]),Number($[2]),Number($[3])]}function dK(Z,$){let J=xZ(Z),X=xZ($);if(!J||!X)return!1;let[Y,Q,z]=J,[W,K,V]=X;if(Y!==W)return Y>W;if(Q!==K)return Q>K;return z>V}function Fn(){let Z=(process.env.LOKI_NO_UPDATE_CHECK??"").trim().toLowerCase();if(Z==="1"||Z==="true"||Z==="yes")return!0;if(process.env.CI)return!0;if(!process.stdout.isTTY)return!0;return!1}function In(Z){try{let $=MM(Z,"utf-8"),J=JSON.parse($);if(typeof J.checkedAt==="number"&&typeof J.latest==="string"&&xZ(J.latest)!==null)return{checkedAt:J.checkedAt,latest:J.latest}}catch{}return null}function Uf0(Z){try{let $=JSON.parse(MM(Z,"utf-8")).failedAt;if(typeof $==="number")return $}catch{}return null}function Bf0(Z,$){let J=In(Z);try{nE(MY(Z),{recursive:!0}),sE(Z,JSON.stringify({...J??{},failedAt:$}),"utf-8")}catch{}}function Nf0(Z,$){try{nE(MY(Z),{recursive:!0}),sE(Z,JSON.stringify($),"utf-8")}catch{}}async function Mf0(){try{let Z=await fetch(Kf0,{signal:AbortSignal.timeout(Gf0),headers:{accept:"application/json"}});if(!Z.ok)return null;let $=await Z.json();if(typeof $.version==="string"&&xZ($.version)!==null)return $.version}catch{}return null}async function Of0(Z=Date.now(),$=Mf0,J=qf0()){let X=In(J);if(X&&Z-X.checkedAt<Vf0)return X.latest;let Y=Uf0(J);if(Y!==null&&Z-Y>=0&&Z-Y<Hf0)return null;let Q=await $();if(Q===null)return Bf0(J,Z),null;return Nf0(J,{checkedAt:Z,latest:Q}),Q}function Af0(Z,$=process.env){if(xZ(Z)===null)return null;let X=$.PATH;if(!X)return null;let Y=new Set;for(let Q of X.split(":")){if(!Q)continue;let z=oE(Q,"loki"),W;try{Wf0(z),W=zf0(z)}catch{continue}if(Y.has(W))continue;Y.add(W);try{let K=oE(MY(MY(W)),"package.json"),V=JSON.parse(MM(K,"utf8")).version;if(typeof V!=="string")continue;if(dK(V,Z))return{path:z,version:V}}catch{continue}}return null}function Lf0(){return Cn(T2(),"cache","last-seen-version.json")}function jf0(Z,$={}){try{if(Fn())return!1;if(xZ(Z)===null)return!1;let J=$.seenFile??Lf0(),X=null;try{let Q=JSON.parse(MM(J,"utf-8")).version;if(typeof Q==="string"&&xZ(Q)!==null)X=Q}catch{}if(X!==null&&!dK(Z,X))return!1;try{nE(MY(J),{recursive:!0}),sE(J,JSON.stringify({version:Z}),"utf-8")}catch{return!1}if(X===null)return!1;return($.write??((Q)=>process.stderr.write(Q)))(`Loki Mode upgraded ${X} -> ${Z}. What is new: https://github.com/asklokesh/loki-mode/releases/tag/v${Z}
2
+ var dh0=Object.create;var{getPrototypeOf:lh0,defineProperty:pK,getOwnPropertyNames:Mn,getOwnPropertyDescriptor:ah0}=Object,On=Object.prototype.hasOwnProperty;function An(Z){return this[Z]}var ih0,oh0,nh0=(Z,$,J)=>{var X=Z!=null&&typeof Z==="object";if(X){var Y=$?ih0??=new WeakMap:oh0??=new WeakMap,Q=Y.get(Z);if(Q)return Q}J=Z!=null?dh0(lh0(Z)):{};let z=$||!Z||!Z.__esModule?pK(J,"default",{value:Z,enumerable:!0}):J;for(let W of Mn(Z))if(!On.call(z,W))pK(z,W,{get:An.bind(Z,W),enumerable:!0});if(X)Y.set(Z,z);return z},sh0=(Z)=>{var $=(Nn??=new WeakMap).get(Z),J;if($)return $;if($=pK({},"__esModule",{value:!0}),Z&&typeof Z==="object"||typeof Z==="function"){for(var X of Mn(Z))if(!On.call($,X))pK($,X,{get:An.bind(Z,X),enumerable:!(J=ah0(Z,X))||J.enumerable})}return Nn.set(Z,$),$},Nn,UM=(Z,$)=>()=>($||Z(($={exports:{}}).exports,$),$.exports);var rh0=(Z)=>Z;function th0(Z,$){this[Z]=rh0.bind(null,$)}var j0=(Z,$)=>{for(var J in $)pK(Z,J,{get:$[J],enumerable:!0,configurable:!0,set:th0.bind($,J)})};var S=(Z,$)=>()=>(Z&&($=Z(Z=0)),$);var e9=import.meta.require;var jn={};j0(jn,{lokiDirFor:()=>NM,lokiDir:()=>D0,homeLokiDir:()=>T2,findRepoRootForVersion:()=>cK,REPO_ROOT:()=>F0});import{resolve as wZ,dirname as iE}from"path";import{fileURLToPath as eh0}from"url";import{existsSync as BM}from"fs";import{homedir as Zf0}from"os";function $f0(){let Z=Ln;for(let $=0;$<6;$++){if(BM(wZ(Z,"VERSION"))&&BM(wZ(Z,"autonomy/run.sh")))return Z;let J=iE(Z);if(J===Z)break;Z=J}return wZ(Ln,"..","..","..")}function cK(Z){let $=Z;for(let J=0;J<6;J++){if(BM(wZ($,"VERSION"))&&BM(wZ($,"autonomy/run.sh")))return $;let X=iE($);if(X===$)break;$=X}return wZ(Z,"..","..","..")}function NM(Z){return process.env.LOKI_DIR??wZ(Z,".loki")}function D0(){return NM(process.cwd())}function T2(){return wZ(Zf0(),".loki")}var Ln,F0;var s0=S(()=>{Ln=iE(eh0(import.meta.url));F0=$f0()});import{readFileSync as Jf0}from"fs";import{resolve as Xf0,dirname as Yf0}from"path";import{fileURLToPath as Qf0}from"url";function O6(){if(g1!==null)return g1;let Z="11.71.2";if(typeof Z==="string"&&Z.length>0)return g1=Z,g1;try{let $=Yf0(Qf0(import.meta.url)),J=cK($);g1=Jf0(Xf0(J,"VERSION"),"utf-8").trim()}catch{g1="unknown"}return g1}var g1=null;var _Z=S(()=>{s0()});import{mkdirSync as nE,readFileSync as MM,realpathSync as zf0,statSync as Wf0,writeFileSync as sE}from"fs";import{dirname as MY,join as oE,resolve as Cn}from"path";function qf0(){return Cn(T2(),"cache","update-check.json")}function xZ(Z){let $=/^(\d+)\.(\d+)\.(\d+)$/.exec(Z.trim());if(!$)return null;return[Number($[1]),Number($[2]),Number($[3])]}function dK(Z,$){let J=xZ(Z),X=xZ($);if(!J||!X)return!1;let[Y,Q,z]=J,[W,K,V]=X;if(Y!==W)return Y>W;if(Q!==K)return Q>K;return z>V}function Fn(){let Z=(process.env.LOKI_NO_UPDATE_CHECK??"").trim().toLowerCase();if(Z==="1"||Z==="true"||Z==="yes")return!0;if(process.env.CI)return!0;if(!process.stdout.isTTY)return!0;return!1}function In(Z){try{let $=MM(Z,"utf-8"),J=JSON.parse($);if(typeof J.checkedAt==="number"&&typeof J.latest==="string"&&xZ(J.latest)!==null)return{checkedAt:J.checkedAt,latest:J.latest}}catch{}return null}function Uf0(Z){try{let $=JSON.parse(MM(Z,"utf-8")).failedAt;if(typeof $==="number")return $}catch{}return null}function Bf0(Z,$){let J=In(Z);try{nE(MY(Z),{recursive:!0}),sE(Z,JSON.stringify({...J??{},failedAt:$}),"utf-8")}catch{}}function Nf0(Z,$){try{nE(MY(Z),{recursive:!0}),sE(Z,JSON.stringify($),"utf-8")}catch{}}async function Mf0(){try{let Z=await fetch(Kf0,{signal:AbortSignal.timeout(Gf0),headers:{accept:"application/json"}});if(!Z.ok)return null;let $=await Z.json();if(typeof $.version==="string"&&xZ($.version)!==null)return $.version}catch{}return null}async function Of0(Z=Date.now(),$=Mf0,J=qf0()){let X=In(J);if(X&&Z-X.checkedAt<Vf0)return X.latest;let Y=Uf0(J);if(Y!==null&&Z-Y>=0&&Z-Y<Hf0)return null;let Q=await $();if(Q===null)return Bf0(J,Z),null;return Nf0(J,{checkedAt:Z,latest:Q}),Q}function Af0(Z,$=process.env){if(xZ(Z)===null)return null;let X=$.PATH;if(!X)return null;let Y=new Set;for(let Q of X.split(":")){if(!Q)continue;let z=oE(Q,"loki"),W;try{Wf0(z),W=zf0(z)}catch{continue}if(Y.has(W))continue;Y.add(W);try{let K=oE(MY(MY(W)),"package.json"),V=JSON.parse(MM(K,"utf8")).version;if(typeof V!=="string")continue;if(dK(V,Z))return{path:z,version:V}}catch{continue}}return null}function Lf0(){return Cn(T2(),"cache","last-seen-version.json")}function jf0(Z,$={}){try{if(Fn())return!1;if(xZ(Z)===null)return!1;let J=$.seenFile??Lf0(),X=null;try{let Q=JSON.parse(MM(J,"utf-8")).version;if(typeof Q==="string"&&xZ(Q)!==null)X=Q}catch{}if(X!==null&&!dK(Z,X))return!1;try{nE(MY(J),{recursive:!0}),sE(J,JSON.stringify({version:Z}),"utf-8")}catch{return!1}if(X===null)return!1;return($.write??((Q)=>process.stderr.write(Q)))(`Loki Mode upgraded ${X} -> ${Z}. What is new: https://github.com/asklokesh/loki-mode/releases/tag/v${Z}
3
3
  `),!0}catch{return!1}}function Cf0(Z){let $=Z.replace(/\\/g,"/");if($.includes("/Cellar/"))return"brew upgrade loki-mode";if(/\/pnpm\//.test($)||$.includes("/.pnpm/"))return"pnpm add -g loki-mode (or npm i -g loki-mode)";if($.includes("/yarn/global/")||$.includes("/.yarn/"))return"yarn global add loki-mode (or npm i -g loki-mode)";if($.includes("/.bun/"))return"bun install -g loki-mode (or npm i -g loki-mode)";if($.includes("/lib/node_modules/"))return"npm i -g loki-mode (or bun install -g loki-mode)";if($.includes("/homebrew/"))return"brew upgrade loki-mode";return"bun install -g loki-mode (or npm i -g loki-mode)"}async function Tn(Z,$={}){try{if(Fn())return;if(xZ(Z)===null)return;let J=$.write??((Q)=>process.stderr.write(Q));jf0(Z,{write:J,...$.cacheFile?{seenFile:oE(MY($.cacheFile),"last-seen-version.json")}:{}});let X=Af0(Z,$.env??process.env);if(X!==null){J(`Loki Mode ${X.version} is installed but not the one running (you are running ${Z}).
4
4
  Another loki earlier on PATH is winning. Newer copy: ${X.path}
5
5
  Run \`which -a loki\` to see the order, then remove or re-point the earlier entry.
@@ -156,7 +156,7 @@ print(json.dumps(out))
156
156
  `),$}catch(J){if($!==null){try{jY($)}catch{}try{Ts(Z)}catch{}}if(J?.code==="EEXIST")return null;throw J}}function _s(Z,$){let J;try{J=zm0(Z)}catch{return!0}if(J.isSymbolicLink())try{return Ts(Z),!0}catch{return!1}let X;try{X=SM(Z,"r")}catch{return!0}try{let Y=Qm0(X);if(Date.now()-Y.mtimeMs<$)return!1;let z=NaN;try{let W=Buffer.alloc(64),K=Wm0(X,W,0,64,0);z=Number.parseInt(W.subarray(0,K).toString("utf-8").trim(),10)}catch{}if(Number.isFinite(z)&&Hm0(z))return!1;try{if(Km0(Z).mtimeMs>Y.mtimeMs)return!1}catch{return!0}try{FD(Z,{force:!0})}catch{}return!0}finally{try{jY(X)}catch{}}}async function ZV(Z,$,J={}){let X=J.timeoutMs??1e4,Y=J.pollMs??25,Q=J.staleMs??30000,z=Ds(Z),W=Date.now()+X,K=null,V=0;while(K===null){if(K=ws(z),K!==null)break;if(Date.now()>W)throw Error(`withFileLock: timed out after ${X}ms acquiring ${z}`);if(_s(z,Q))continue;let G=Math.min(Y*2**Math.min(V,4),Es);V+=1,await new Promise((H)=>setTimeout(H,G))}try{return await $()}finally{try{jY(K)}catch{}try{FD(z,{force:!0})}catch{}}}function o6(Z,$,J={}){let X=J.timeoutMs??1e4,Y=J.pollMs??25,Q=J.staleMs??30000,z=Ds(Z),W=Date.now()+X,K=null,V=0,G=new Int32Array(new SharedArrayBuffer(4));while(K===null){if(K=ws(z),K!==null)break;if(Date.now()>W)throw Error(`withFileLockSync: timed out after ${X}ms acquiring ${z}`);if(_s(z,Q))continue;let H=Math.min(Y*2**Math.min(V,4),Es);V+=1,Atomics.wait(G,0,0,H)}try{return $()}finally{try{jY(K)}catch{}try{FD(z,{force:!0})}catch{}}}var Gm0=0,kM,Es=50;var S9=S(()=>{kM=new Map});function ID(Z,$){let J=`${Z}=${$}`;if(xs.has(J))return;xs.add(J),process.stderr.write(`loki: ignoring invalid ${Z}="${$}" (need a number > 0); using the default cap of 900s
157
157
  `)}function FY(Z){if(Z===void 0||Z.trim()==="")return null;let $=Number(Z);if(Number.isFinite($)&&$>0)return $;return ID("LOKI_E10_CAP_S",Z),null}function c1(Z,$=fM){return Z-Math.min($,Z/30)}function T3(Z){switch(Z.cmd){case"push-pr":return["push-pr",Z.repoDir,Z.branch,Z.title,Z.bodyFile,Z.draft?"1":"0"];case"comment":return["comment",Z.runId,Z.prUrl,Z.file];case"status":return["status",Z.sha,Z.state,Z.description];case"issue-comment":return Z.update?["issue-comment","--update",Z.issueRef,Z.bodyFile]:["issue-comment",Z.issueRef,Z.bodyFile]}}function R2(Z){return["Task (untrusted, quoted verbatim):","<<<TASK",Z,"TASK"]}var y9,vZ=900,hM=2700,xs,fM=30,ks=1800,gM=2,Ss;var Z5=S(()=>{y9={intake:{targetS:15,limitS:60},plan:{targetS:45,limitS:90},wall:{targetS:45,limitS:90},implement:{targetS:180,limitS:480},verify:{targetS:60,limitS:120},fix:{targetS:90,limitS:180},commit:{targetS:5,limitS:30},seal:{targetS:15,limitS:60},pr:{targetS:15,limitS:60},deep:{targetS:null,limitS:2700}},xs=new Set;Ss=["requests_total","requests_over_100k","advisor_calls","advisor_input_tokens","advisor_output_tokens"]});import{closeSync as qm0,openSync as Um0,readSync as Bm0}from"fs";import{join as Nm0}from"path";function d1(Z,$=bs()){let J;try{J=e(Z,["ls-files"],{stdio:["ignore","pipe","pipe"]})}catch{return{files:[],truncated:!1}}let X=J.split(`
158
158
  `).filter((Y)=>Y.length>0);if(X.length>$){let Y=(Q)=>/(^|\/)(vendor|node_modules|dist|build|third_party)\//.test(Q);X=[...X.filter((Q)=>!Y(Q)),...X.filter(Y)]}return{files:X.slice(0,$),truncated:X.length>$}}function Lm0(Z,$){let J,X=-1;try{let W=Buffer.allocUnsafe(ys);X=Um0(Z,"r"),J=W.toString("utf8",0,Bm0(X,W,0,ys,0))}catch{return[]}finally{if(X>=0)try{qm0(X)}catch{}}let Y=[],Q="",z="";for(let W of J.matchAll($)){if(Y.length>=Mm0)break;if($!==vs){if(W[1])Y.push(W[1]);continue}if(W[1]||W[2]){Q=W[2]??"",z="",Y.push(W[1]??W[2]);continue}if(Q&&(z||=W[3])===W[3])Y.push(`${Q}.${W[4]}`)}return Y}function hZ(Z,$=bs()){let{files:J,truncated:X}=d1(Z,$),Y=[];for(let Q of J){if(!Om0.test(Q))continue;let z=Lm0(Nm0(Z,Q),Q.endsWith(".py")?vs:Am0);if(z.length>0)Y.push({path:Q,symbols:z})}return{files:J,entries:Y,truncated:X}}var bs=()=>{let Z=process.env.LOKI_E10_REPOMAP_MAX_FILES,$=Number(Z);if(Number.isInteger($)&&$>0)return $;if(Z)process.stderr.write(`loki: ignoring invalid LOKI_E10_REPOMAP_MAX_FILES=${JSON.stringify(Z)}; using default 2000
159
- `);return 2000},ys=256000,Mm0=300,Om0,Am0,vs;var fZ=S(()=>{w0();Om0=/\.(ts|tsx|js|jsx|mjs|cjs|py)$/,Am0=/^export\s+(?:default\s+)?(?:async\s+)?(?:function|class|const|let|interface|type|enum)\s+([A-Za-z0-9_$]+)/gm,vs=/^(?:(?:async\s+)?def\s+(\w+)|class\s+(\w+))|^([ \t]+)(?:async\s+)?def\s+(\w+)/gm});import{createHash as hs}from"crypto";import{readdirSync as jm0,readFileSync as Cm0}from"fs";import{relative as Fm0,resolve as fs}from"path";function Im0(Z){let $=hs("sha256"),J=(X)=>{for(let Y of jm0(X,{withFileTypes:!0}).sort((Q,z)=>Q.name<z.name?-1:1)){let Q=fs(X,Y.name);if(Y.isDirectory()){if(Y.name!=="node_modules")J(Q)}else if(Y.isFile()&&Y.name.endsWith(".ts"))$.update(`${Fm0(Z,Q)}\x00`).update(Cm0(Q)).update("\x00")}};return J(Z),$.digest("hex")}function Pm0(Z=fs(import.meta.dir,".."),$="e9f7d4b4155cbf602f7e1419d5fbacb378b06fdd8a70e302fb145612761f1817"){if(typeof $==="string"&&/^[0-9a-f]{64}$/.test($))return $;try{return Im0(Z)}catch{return hs("sha256").update(`unbound:${process.pid}:${Date.now()}:${Math.random()}`).digest("hex")}}function l1(){return Tm0??=Pm0()}var Tm0=null;var gs=()=>{};import{createHash as cs}from"crypto";import{chmodSync as ms,existsSync as Rm0,mkdirSync as Em0,readdirSync as Dm0,readFileSync as wm0,renameSync as _m0,statSync as xm0,unlinkSync as ds,writeFileSync as km0}from"fs";import{basename as Sm0,resolve as o7}from"path";function n6(Z,$){let J=Z&&Z.trim()!==""?Z:o7($);return cs("sha256").update(J).digest("hex")}function ym0(){return o7(T2(),"cache","v10")}function T4(Z,$=ym0()){return o7($,Z)}function mM(Z,$=(J)=>!0){if(!Rm0(Z))return null;try{let J=JSON.parse(wm0(Z,"utf8"));return $(J)?J:null}catch{return null}}function bm0(Z){return typeof Z==="object"&&Z!==null&&Array.isArray(Z.files)&&Array.isArray(Z.entries)}function vm0(Z){return typeof Z==="object"&&Z!==null&&Array.isArray(Z.runners)&&Array.isArray(Z.tests)}function ls(Z,$,J){Em0($,{recursive:!0,mode:448}),ms($,448);let X=`${Z}.${process.pid}.${hm0++}.tmp`;try{km0(X,JSON.stringify(J),{mode:384}),ms(X,384),_m0(X,Z)}catch(Y){try{ds(X)}catch{}throw Y}}function us(Z,$,J,X=$==="slice-"?500:5){let Y=(Q)=>{try{return xm0(o7(Z,Q)).mtimeMs}catch{return 0}};try{Dm0(Z).filter((Q)=>Q.startsWith($)&&Q.endsWith(".json")&&Q!==Sm0(J)).sort((Q,z)=>Y(z)-Y(Q)||(Q<z?1:-1)).slice(X-1).forEach((Q)=>{try{ds(o7(Z,Q))}catch{}})}catch{}}function mm0(Z,$,J){if(Z)return ps.hits++,Z;ps.misses++;let X=$();try{J(X)}catch{}return X}var hm0=0,fm0,TD=(Z,$,J,X)=>{ls(Z,$,X),us($,J,Z);let Y=fm0[J];if(Y)us($,Y,Z,1)},uM=(Z,$,J=l1())=>`${Z}-${J.slice(0,16)}-${$}.json`,$V=(Z,$,J=l1())=>mM(o7(Z,uM("repomap",$,J)),bm0),gm0=(Z,$,J,X=l1())=>TD(o7(Z,uM("repomap",$,X)),Z,"repomap-",J),as=(Z,$,J=l1())=>mM(o7(Z,uM("testmap",$,J)),vm0),is=(Z,$,J,X=l1())=>TD(o7(Z,uM("testmap",$,X)),Z,"testmap-",J),ps,os=(Z,$,J,X=l1())=>mm0($V(Z,$,X),J,(Y)=>gm0(Z,$,Y,X)),ns=(Z,$)=>cs("sha256").update(`${Z.length}:${Z}\x00${$}`).digest("hex"),um0=(Z)=>{let $=Z;return typeof $==="object"&&$!==null&&typeof $.gid==="string"&&typeof $.id==="string"&&typeof $.head==="string"&&Number.isInteger($.n)},ss=(Z,$)=>mM(o7(Z,`slice-${$}.json`),um0),rs=(Z,$,J)=>TD(o7(Z,`slice-${$}.json`),Z,"slice-",J);var E2=S(()=>{s0();gs();fm0={"repomap-":"repomap2-"},ps={hits:0,misses:0}});function pM(Z){return Z.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1 $2").toLowerCase().match(/[a-z0-9]+/g)??[]}function dm0(Z){return Array.from(new Set(pM(Z).filter(($)=>$.length>2&&!pm0.has($))))}function ts(Z,$){let J=new Map,X=Z.match(/[A-Za-z0-9_@.\-/]+/g)??[];for(let Y of X){let Q=Y.replace(/^\.\//,"").replace(/[.:]+$/,"");if(Q.length<3)continue;if(PD.test(Q)||Q.includes("/")){for(let z of $)if(z.path===Q||z.path.endsWith(`/${Q}`))J.set(z.path,`path: ${Q}`)}if(!Q.includes("/")&&Q.includes(".")){let z=Q.split(".");for(let W=z.length;W>=2;W--){let K=z.slice(0,W).join("/"),V=$.filter((G)=>{let H=G.path.replace(PD,"");return H===K||H.endsWith(`/${K}`)||H===`${K}/index`||H===`${K}/__init__`});if(V.length>0){for(let G of V)J.set(G.path,`module: ${Q}`);break}}}}return J}function lm0(Z,$,J){let X=new Set($.files),Y=d1(J,Number.MAX_SAFE_INTEGER).files.filter((z)=>!X.has(z)).map((z)=>({path:z,symbols:[]}));if(Y.length===0)return $.entries;let Q=ts(Z,Y);return Q.size===0?$.entries:[...$.entries,...Y.filter((z)=>Q.has(z.path))]}function es(Z,$,J,X){let Y=$.truncated&&X?lm0(Z,$,X):$.entries,Q=dm0(Z),z=ts(Z,Y);if(Q.length===0&&z.size===0)return[];return Y.map((K,V)=>{let G=K.path.split("/"),H=new Set(pM((G[G.length-1]??"").replace(PD,""))),q=new Set(K.symbols.flatMap(pM)),U=new Set(G.slice(0,-1).flatMap(pM)),B=0,N=[];for(let j of Q){let C=H.has(j)?3:q.has(j)?2:U.has(j)?1:0;if(C>0)B+=C,N.push(j)}let O=z.get(K.path);if(O)B+=cm0;let M=N.length?`matched: ${N.join(", ")}`:"",A=O?M?`${O}; ${M}`:O:M;return{path:K.path,score:B,idx:V,reason:A}}).filter((K)=>K.score>0).sort((K,V)=>V.score-K.score||K.idx-V.idx).slice(0,J).map((K)=>({path:K.path,reason:K.reason}))}var pm0,cm0=1000,PD;var Zr=S(()=>{fZ();pm0=new Set(["the","and","for","with","that","this","from","into","onto","are","was","were","will","can","should","would","could","add","fix","make","use","new","get","set","all","any","not","but","has","have","its","our","your","when","then","than","also","each","must","need","needs","file","files","code","update","change","implement","create","support","line","error","test","tests","bug","issue","task","feature","please"]),PD=/\.(?:py|ts|tsx|js|jsx|mjs|cjs|go|rs|java|rb|sh|c|cc|cpp|h|hpp|cs|kt|swift|php|md|json|ya?ml|toml)$/});function $r(Z){return Array.from(new Set((Z.toLowerCase().match(/[a-z0-9_]+/g)??[]).filter(($)=>$.length>2)))}function a1(Z,$,J=RD,X){return es(Z,$,J,X).map((Y)=>Y.path)}var RD=8,Jr=(Z)=>`${Z.path} ${Z.symbols.join(" ")}`.toLowerCase();var cM=S(()=>{Zr()});function im0(Z,$,J=RD){let X=$.entries;if(X.length===0)return[];let Y=X.map((W)=>new Set(am0(Jr(W)))),Q=$r(Z).filter((W)=>{let K=Y.reduce((V,G)=>V+(G.has(W)?1:0),0);return K>0&&K*2<=Y.length});if(Q.length===0)return[];return Y.map((W,K)=>({path:X[K].path,score:Q.reduce((V,G)=>V+(W.has(G)?1:0),0),idx:K})).filter((W)=>W.score>0).sort((W,K)=>K.score-W.score||W.idx-K.idx).slice(0,J).map((W)=>W.path)}function Xr(Z,$,J=process.env){if(J.LOKI_SPEED==="0"||!$)return[];try{return im0(Z,$)}catch{return[]}}var am0=(Z)=>Z.toLowerCase().match(/[a-z0-9_]+/g)??[];var Yr=S(()=>{cM()});import{readFileSync as dM}from"fs";import{resolve as lM}from"path";function t5(Z){try{let $=process.env.LOKI_MODEL_CATALOG||lM(F0,"providers/model_catalog.json");return JSON.parse(dM($,"utf8")).providers?.claude?.cli_aliases?.[Z]??Z}catch{return Z}}function ED(Z){return om0.has(Z)}function DD(Z){try{let $=process.env.LOKI_MODEL_CATALOG||lM(F0,"providers/model_catalog.json"),J=JSON.parse(dM($,"utf8")).providers?.claude?.models;if(!Array.isArray(J))return null;let X=[];for(let W of J)if(W.tier!=="legacy"&&!X.includes(W.tier))X.push(W.tier);let Y=t5(Z),Q=J.find((W)=>W.id===Y||W.alias===Z),z=Q?X.indexOf(Q.tier):-1;return z>=0?z:null}catch{return null}}function Qr(Z){try{let $=process.env.LOKI_MODEL_CATALOG||lM(F0,"providers/model_catalog.json"),J=JSON.parse(dM($,"utf8")).providers?.claude?.models;if(!Array.isArray(J))return null;let X=t5(Z),Y=J.find((Q)=>Q.id===X||Q.alias===Z)?.effort?.levels;return Array.isArray(Y)?Y:null}catch{return null}}function aM(Z){try{let $=process.env.LOKI_MODEL_CATALOG||lM(F0,"providers/model_catalog.json"),J=JSON.parse(dM($,"utf8")).providers?.claude?.models;if(!Array.isArray(J))return null;let X=t5(Z);return J.find((Y)=>Y.id===X||Y.alias===Z)?.thinking??null}catch{return null}}function iM(Z,$){let J=aM(Z)?.max_effort?.[$];return typeof J==="string"?J:null}function oM(Z,$){let J=aM(Z)?.substitute?.[$];return typeof J==="string"?J:null}function JV(Z,$){let J=aM(Z);if(!J||!Array.isArray(J.types))return!0;return J.types.includes($)||typeof J.substitute?.[$]==="string"}function zr(Z){let $=aM(Z)?.types;return Array.isArray($)&&$.includes("adaptive")}function nM(Z){let $=(Z??"").trim().toLowerCase();if(!$)return;let J=_D[$]??$;if(!wD.has(J))throw Error(`unknown LOKI_SESSION_MODEL '${(Z??"").trim()}' (small|medium|high, planning|development|fast, or opus|sonnet|haiku|fable)`);return J}var s6="claude (provider default)",om0,wD,_D;var P4=S(()=>{s0();om0=new Set(["haiku","sonnet","opus","fable"]);wD=new Set(["planning","development","fast","opus","sonnet","haiku","fable"]),_D={small:"fast",medium:"development",high:"planning"}});function nm0(Z,$,J){let X=`${Z}=${$}`;if(Wr.has(X))return;Wr.add(X),process.stderr.write(`loki: ignoring invalid ${Z}="${$}" (need a number > 0); using ${J}${J===0?" (off)":"s"}
159
+ `);return 2000},ys=256000,Mm0=300,Om0,Am0,vs;var fZ=S(()=>{w0();Om0=/\.(ts|tsx|js|jsx|mjs|cjs|py)$/,Am0=/^export\s+(?:default\s+)?(?:async\s+)?(?:function|class|const|let|interface|type|enum)\s+([A-Za-z0-9_$]+)/gm,vs=/^(?:(?:async\s+)?def\s+(\w+)|class\s+(\w+))|^([ \t]+)(?:async\s+)?def\s+(\w+)/gm});import{createHash as hs}from"crypto";import{readdirSync as jm0,readFileSync as Cm0}from"fs";import{relative as Fm0,resolve as fs}from"path";function Im0(Z){let $=hs("sha256"),J=(X)=>{for(let Y of jm0(X,{withFileTypes:!0}).sort((Q,z)=>Q.name<z.name?-1:1)){let Q=fs(X,Y.name);if(Y.isDirectory()){if(Y.name!=="node_modules")J(Q)}else if(Y.isFile()&&Y.name.endsWith(".ts"))$.update(`${Fm0(Z,Q)}\x00`).update(Cm0(Q)).update("\x00")}};return J(Z),$.digest("hex")}function Pm0(Z=fs(import.meta.dir,".."),$="ba7ea625fa0ee0a0888df197085e01bf48d617681ef43bdee73771a6d5e85b9d"){if(typeof $==="string"&&/^[0-9a-f]{64}$/.test($))return $;try{return Im0(Z)}catch{return hs("sha256").update(`unbound:${process.pid}:${Date.now()}:${Math.random()}`).digest("hex")}}function l1(){return Tm0??=Pm0()}var Tm0=null;var gs=()=>{};import{createHash as cs}from"crypto";import{chmodSync as ms,existsSync as Rm0,mkdirSync as Em0,readdirSync as Dm0,readFileSync as wm0,renameSync as _m0,statSync as xm0,unlinkSync as ds,writeFileSync as km0}from"fs";import{basename as Sm0,resolve as o7}from"path";function n6(Z,$){let J=Z&&Z.trim()!==""?Z:o7($);return cs("sha256").update(J).digest("hex")}function ym0(){return o7(T2(),"cache","v10")}function T4(Z,$=ym0()){return o7($,Z)}function mM(Z,$=(J)=>!0){if(!Rm0(Z))return null;try{let J=JSON.parse(wm0(Z,"utf8"));return $(J)?J:null}catch{return null}}function bm0(Z){return typeof Z==="object"&&Z!==null&&Array.isArray(Z.files)&&Array.isArray(Z.entries)}function vm0(Z){return typeof Z==="object"&&Z!==null&&Array.isArray(Z.runners)&&Array.isArray(Z.tests)}function ls(Z,$,J){Em0($,{recursive:!0,mode:448}),ms($,448);let X=`${Z}.${process.pid}.${hm0++}.tmp`;try{km0(X,JSON.stringify(J),{mode:384}),ms(X,384),_m0(X,Z)}catch(Y){try{ds(X)}catch{}throw Y}}function us(Z,$,J,X=$==="slice-"?500:5){let Y=(Q)=>{try{return xm0(o7(Z,Q)).mtimeMs}catch{return 0}};try{Dm0(Z).filter((Q)=>Q.startsWith($)&&Q.endsWith(".json")&&Q!==Sm0(J)).sort((Q,z)=>Y(z)-Y(Q)||(Q<z?1:-1)).slice(X-1).forEach((Q)=>{try{ds(o7(Z,Q))}catch{}})}catch{}}function mm0(Z,$,J){if(Z)return ps.hits++,Z;ps.misses++;let X=$();try{J(X)}catch{}return X}var hm0=0,fm0,TD=(Z,$,J,X)=>{ls(Z,$,X),us($,J,Z);let Y=fm0[J];if(Y)us($,Y,Z,1)},uM=(Z,$,J=l1())=>`${Z}-${J.slice(0,16)}-${$}.json`,$V=(Z,$,J=l1())=>mM(o7(Z,uM("repomap",$,J)),bm0),gm0=(Z,$,J,X=l1())=>TD(o7(Z,uM("repomap",$,X)),Z,"repomap-",J),as=(Z,$,J=l1())=>mM(o7(Z,uM("testmap",$,J)),vm0),is=(Z,$,J,X=l1())=>TD(o7(Z,uM("testmap",$,X)),Z,"testmap-",J),ps,os=(Z,$,J,X=l1())=>mm0($V(Z,$,X),J,(Y)=>gm0(Z,$,Y,X)),ns=(Z,$)=>cs("sha256").update(`${Z.length}:${Z}\x00${$}`).digest("hex"),um0=(Z)=>{let $=Z;return typeof $==="object"&&$!==null&&typeof $.gid==="string"&&typeof $.id==="string"&&typeof $.head==="string"&&Number.isInteger($.n)},ss=(Z,$)=>mM(o7(Z,`slice-${$}.json`),um0),rs=(Z,$,J)=>TD(o7(Z,`slice-${$}.json`),Z,"slice-",J);var E2=S(()=>{s0();gs();fm0={"repomap-":"repomap2-"},ps={hits:0,misses:0}});function pM(Z){return Z.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1 $2").toLowerCase().match(/[a-z0-9]+/g)??[]}function dm0(Z){return Array.from(new Set(pM(Z).filter(($)=>$.length>2&&!pm0.has($))))}function ts(Z,$){let J=new Map,X=Z.match(/[A-Za-z0-9_@.\-/]+/g)??[];for(let Y of X){let Q=Y.replace(/^\.\//,"").replace(/[.:]+$/,"");if(Q.length<3)continue;if(PD.test(Q)||Q.includes("/")){for(let z of $)if(z.path===Q||z.path.endsWith(`/${Q}`))J.set(z.path,`path: ${Q}`)}if(!Q.includes("/")&&Q.includes(".")){let z=Q.split(".");for(let W=z.length;W>=2;W--){let K=z.slice(0,W).join("/"),V=$.filter((G)=>{let H=G.path.replace(PD,"");return H===K||H.endsWith(`/${K}`)||H===`${K}/index`||H===`${K}/__init__`});if(V.length>0){for(let G of V)J.set(G.path,`module: ${Q}`);break}}}}return J}function lm0(Z,$,J){let X=new Set($.files),Y=d1(J,Number.MAX_SAFE_INTEGER).files.filter((z)=>!X.has(z)).map((z)=>({path:z,symbols:[]}));if(Y.length===0)return $.entries;let Q=ts(Z,Y);return Q.size===0?$.entries:[...$.entries,...Y.filter((z)=>Q.has(z.path))]}function es(Z,$,J,X){let Y=$.truncated&&X?lm0(Z,$,X):$.entries,Q=dm0(Z),z=ts(Z,Y);if(Q.length===0&&z.size===0)return[];return Y.map((K,V)=>{let G=K.path.split("/"),H=new Set(pM((G[G.length-1]??"").replace(PD,""))),q=new Set(K.symbols.flatMap(pM)),U=new Set(G.slice(0,-1).flatMap(pM)),B=0,N=[];for(let j of Q){let C=H.has(j)?3:q.has(j)?2:U.has(j)?1:0;if(C>0)B+=C,N.push(j)}let O=z.get(K.path);if(O)B+=cm0;let M=N.length?`matched: ${N.join(", ")}`:"",A=O?M?`${O}; ${M}`:O:M;return{path:K.path,score:B,idx:V,reason:A}}).filter((K)=>K.score>0).sort((K,V)=>V.score-K.score||K.idx-V.idx).slice(0,J).map((K)=>({path:K.path,reason:K.reason}))}var pm0,cm0=1000,PD;var Zr=S(()=>{fZ();pm0=new Set(["the","and","for","with","that","this","from","into","onto","are","was","were","will","can","should","would","could","add","fix","make","use","new","get","set","all","any","not","but","has","have","its","our","your","when","then","than","also","each","must","need","needs","file","files","code","update","change","implement","create","support","line","error","test","tests","bug","issue","task","feature","please"]),PD=/\.(?:py|ts|tsx|js|jsx|mjs|cjs|go|rs|java|rb|sh|c|cc|cpp|h|hpp|cs|kt|swift|php|md|json|ya?ml|toml)$/});function $r(Z){return Array.from(new Set((Z.toLowerCase().match(/[a-z0-9_]+/g)??[]).filter(($)=>$.length>2)))}function a1(Z,$,J=RD,X){return es(Z,$,J,X).map((Y)=>Y.path)}var RD=8,Jr=(Z)=>`${Z.path} ${Z.symbols.join(" ")}`.toLowerCase();var cM=S(()=>{Zr()});function im0(Z,$,J=RD){let X=$.entries;if(X.length===0)return[];let Y=X.map((W)=>new Set(am0(Jr(W)))),Q=$r(Z).filter((W)=>{let K=Y.reduce((V,G)=>V+(G.has(W)?1:0),0);return K>0&&K*2<=Y.length});if(Q.length===0)return[];return Y.map((W,K)=>({path:X[K].path,score:Q.reduce((V,G)=>V+(W.has(G)?1:0),0),idx:K})).filter((W)=>W.score>0).sort((W,K)=>K.score-W.score||W.idx-K.idx).slice(0,J).map((W)=>W.path)}function Xr(Z,$,J=process.env){if(J.LOKI_SPEED==="0"||!$)return[];try{return im0(Z,$)}catch{return[]}}var am0=(Z)=>Z.toLowerCase().match(/[a-z0-9_]+/g)??[];var Yr=S(()=>{cM()});import{readFileSync as dM}from"fs";import{resolve as lM}from"path";function t5(Z){try{let $=process.env.LOKI_MODEL_CATALOG||lM(F0,"providers/model_catalog.json");return JSON.parse(dM($,"utf8")).providers?.claude?.cli_aliases?.[Z]??Z}catch{return Z}}function ED(Z){return om0.has(Z)}function DD(Z){try{let $=process.env.LOKI_MODEL_CATALOG||lM(F0,"providers/model_catalog.json"),J=JSON.parse(dM($,"utf8")).providers?.claude?.models;if(!Array.isArray(J))return null;let X=[];for(let W of J)if(W.tier!=="legacy"&&!X.includes(W.tier))X.push(W.tier);let Y=t5(Z),Q=J.find((W)=>W.id===Y||W.alias===Z),z=Q?X.indexOf(Q.tier):-1;return z>=0?z:null}catch{return null}}function Qr(Z){try{let $=process.env.LOKI_MODEL_CATALOG||lM(F0,"providers/model_catalog.json"),J=JSON.parse(dM($,"utf8")).providers?.claude?.models;if(!Array.isArray(J))return null;let X=t5(Z),Y=J.find((Q)=>Q.id===X||Q.alias===Z)?.effort?.levels;return Array.isArray(Y)?Y:null}catch{return null}}function aM(Z){try{let $=process.env.LOKI_MODEL_CATALOG||lM(F0,"providers/model_catalog.json"),J=JSON.parse(dM($,"utf8")).providers?.claude?.models;if(!Array.isArray(J))return null;let X=t5(Z);return J.find((Y)=>Y.id===X||Y.alias===Z)?.thinking??null}catch{return null}}function iM(Z,$){let J=aM(Z)?.max_effort?.[$];return typeof J==="string"?J:null}function oM(Z,$){let J=aM(Z)?.substitute?.[$];return typeof J==="string"?J:null}function JV(Z,$){let J=aM(Z);if(!J||!Array.isArray(J.types))return!0;return J.types.includes($)||typeof J.substitute?.[$]==="string"}function zr(Z){let $=aM(Z)?.types;return Array.isArray($)&&$.includes("adaptive")}function nM(Z){let $=(Z??"").trim().toLowerCase();if(!$)return;let J=_D[$]??$;if(!wD.has(J))throw Error(`unknown LOKI_SESSION_MODEL '${(Z??"").trim()}' (small|medium|high, planning|development|fast, or opus|sonnet|haiku|fable)`);return J}var s6="claude (provider default)",om0,wD,_D;var P4=S(()=>{s0();om0=new Set(["haiku","sonnet","opus","fable"]);wD=new Set(["planning","development","fast","opus","sonnet","haiku","fable"]),_D={small:"fast",medium:"development",high:"planning"}});function nm0(Z,$,J){let X=`${Z}=${$}`;if(Wr.has(X))return;Wr.add(X),process.stderr.write(`loki: ignoring invalid ${Z}="${$}" (need a number > 0); using ${J}${J===0?" (off)":"s"}
160
160
  `)}function Kr(Z,$,J){if($===void 0||$.trim()==="")return J;let X=Number($);if(Number.isFinite(X)&&X>0)return X;return nm0(Z,$,J),J}function xD(Z=process.env.LOKI_E10_STALL_S){return Kr("LOKI_E10_STALL_S",Z,900)}function Vr(Z=process.env.LOKI_E10_STALL_KILL_S){return Kr("LOKI_E10_STALL_KILL_S",Z,0)}function Gr(Z,$=xD()){let J=0,X="",Y=Z(),Q=0,z=!1;return{tick(W,K){let V=Z(),G=W>J,H=K!==X;if(J=W,H)X=K,Q=0,Y=V,z=!1;else if(G)Q++,Y=V,z=!1;else Q=0;let q=(V-Y)/1000;if(q>=$){let U=!z;return z=!0,{cls:"stalled",idleS:q,stalledNow:U}}if(Q>=3)return{cls:"looping",idleS:q,stalledNow:!1};if(!G&&!H&&q>=120)return{cls:"idle",idleS:q,stalledNow:!1};return{cls:"progressing",idleS:q,stalledNow:!1}}}}var Wr;var Hr=S(()=>{Wr=new Set});function XV(Z){let $=Z??"";if($.trim()==="")return{klass:"transient",reason:"empty_output"};if(tm0.test($))return{klass:"non_retryable",reason:"quota_exhausted"};if(rm0.test($))return{klass:"transient",reason:"transient_marker"};for(let[J,X]of sm0)if(X.test($))return{klass:"non_retryable",reason:J};return{klass:"transient",reason:"unrecognized"}}function qr(Z,$=process.env){if($.LOKI_SMART_RETRY==="0")return!1;return Z.klass==="non_retryable"}function r6(Z){return Z.replaceAll("[sdk-loop error:","[agent-text sdk-loop error:")}function Ur(Z){let $=/^\[sdk-loop error: Failed to authenticate(?: \([a-z_]+\))?(?:: ([^\n]*))?\]$/m.exec(Z);return $?l9(($[1]??"").trim()):null}function kD(Z){if(Z.exit===0)return null;let $=Z.stderrTail??"",J=em0.exec($);return J?J[1]?"auth":"quota_exhausted":XV($).reason}async function Br(Z,$,J,X,Y,Q){let z=J.sleep??Ju0,W=await Z(),K=J.now(),V=0,G=()=>Math.max(J.now(),K+V);for(let H=0;$(W)==="quota_exhausted"&&!X?.aborted&&!Q?.();H++){let q=Y-G(),U=Math.min(Zu0*2**H,$u0);if(U>=q){for(let B=0;B<5&&J.now()<Y&&!X?.aborted;B++)await z(Math.max(0,Y-J.now()),X);return W}if(await z(U,X),V+=U,X?.aborted||Q?.())return W;W=await Z()}return W}var sm0,rm0,tm0,em0,Zu0=30000,$u0=300000,Ju0=(Z,$)=>new Promise((J)=>{let X=setTimeout(J,Math.max(0,Z));$?.addEventListener("abort",()=>{clearTimeout(X),J()},{once:!0})});var i1=S(()=>{K7();sm0=[["auth",/\b(?:invalid[_ -]?api[_ -]?key|invalid[_ -]?x-api-key|authentication[_ -]?(?:failed|error))/i],["unknown_model",/\b(?:model[_ -]?not[_ -]?found|unknown[_ -]?model|does not exist.{0,20}model)/i],["bad_request",/\b(?:invalid[_ -]?request[_ -]?error|malformed[_ -]?request)/i],["quota_exhausted",/\b(?:insufficient[_ -]?(?:quota|credit|funds)|billing[_ -]?(?:hard[_ -]?limit|issue)|credit[_ -]?balance[_ -]?(?:is[_ -]?)?too[_ -]?low|exceeded your current quota|check your plan and billing details)/i]],rm0=/\b(?:rate[_ -]?limit|429\b|overloaded|please try again|temporarily unavailable|timeout|timed out|ETIMEDOUT|ECONNRESET|ECONNREFUSED|EAI_AGAIN|socket hang up|502\b|503\b|504\b|529\b|bad gateway|gateway time-?out|service unavailable)/i,tm0=/\b(?:insufficient_quota|check your plan and billing details)/i;em0=/\[sdk-loop error: [^\n]*?(?:(Failed to authenticate|API key is invalid|Not logged in)|(credit balance))/});import{execFileSync as Xu0}from"child_process";import{chmodSync as Yu0,readFileSync as SD,renameSync as Qu0,rmSync as zu0,writeFileSync as Nr}from"fs";import{join as Mr}from"path";function Ar(Z){if(!Number.isInteger(Z)||Z<=1)return null;try{return Xu0("ps",["-o","lstart=","-p",String(Z)],{encoding:"utf8",timeout:5000,env:{...process.env,LC_ALL:"C"},stdio:["ignore","pipe","ignore"]}).trim().replace(/\s+/g," ")||null}catch{return null}}function Lr(Z,$,J=process.pid,X=process.argv){let Y=Or(Z);try{let Q=Ar(J);if(Q){let z=`${Y}.${process.pid}.tmp`;Nr(z,JSON.stringify({pid:J,start:Q,argv:X,run_id:$})+`
161
161
  `,{mode:384}),Yu0(z,384),Qu0(z,Y)}}catch{}return()=>{try{if(JSON.parse(SD(Y,"utf8")).pid===J)zu0(Y,{force:!0})}catch{}}}function yD(Z){try{let $=JSON.parse(SD(Or(Z),"utf8"));if(!Number.isInteger($.pid)||$.pid<=1||typeof $.start!=="string"||typeof $.run_id!=="string"||!Array.isArray($.argv))return null;return{pid:$.pid,start:$.start,argv:$.argv.map(String),run_id:$.run_id}}catch{return null}}function IY(Z){let $=yD(Z);return $!==null&&Ar($.pid)===$.start}function Ir(Z){return YV.add(Z),()=>{if(YV.delete(Z),YV.size===0)for(let $ of Cr.splice(0))$()}}function sM(Z=8000){jr=!0;for(let $ of[...YV])$();if(YV.size===0)return Promise.resolve();return new Promise(($)=>{Cr.push($),setTimeout($,Z).unref()})}function bD(Z,$=Date.now()){try{Nr(Tr(Z),`${$}
162
162
  `)}catch{}}function Pr(Z){try{let $=Number(SD(Tr(Z),"utf8").trim());return Number.isFinite($)&&$>0&&$<=Math.min(Date.now()+60000,8640000000000000)?$:null}catch{return null}}var Or=(Z)=>Mr(Z,"run.pid"),YV,jr=!1,Cr,Fr=()=>jr,Tr=(Z)=>Mr(Z,"alive");var TY=S(()=>{YV=new Set,Cr=[]});import{createHash as Wu0}from"crypto";function wr(Z,$=[]){let J={usd:$.length>0?null:0,per_stage:{},retry_usd:$.length>0?null:0,retry_sessions:0};for(let{rec:X}of Z){let Y=typeof X.stage==="string"&&X.stage?X.stage:tM,Q=J.per_stage[Y]??={usd:0,sessions:0,cache_read_tokens:0,cache_creation_tokens:0,cache_hit_ratio:null},z=Dr(X.total_cost_usd)&&!Ku0(X)?X.total_cost_usd:null;Q.sessions++,Q.cache_read_tokens+=Math.max(0,RY(X.cache_read_tokens)),Q.cache_creation_tokens+=Math.max(0,RY(X.cache_creation_tokens));let W=Q.cache_read_tokens+Q.cache_creation_tokens;if(Q.cache_hit_ratio=W>0?Q.cache_read_tokens/W:null,Q.usd=vD(Q.usd,z),J.usd=vD(J.usd,z),Vu0(X))J.retry_sessions++,J.retry_usd=vD(J.retry_usd,z)}return J}function fD(Z){let $=Gu0(Z),J=[Hu0(Z),Bu0(Z)].filter((X)=>X!==null);return[...$?[$]:[],...J].join(`
@@ -3307,4 +3307,4 @@ Unknown commands exit 2 with a suggestion; run 'loki help' for the full list.
3307
3307
  `);{let{suggestCommand:X}=await Promise.resolve().then(() => (W7(),Ys)),Y=$===void 0?void 0:X($);if(Y)process.stderr.write(`Did you mean 'loki ${Y}'?
3308
3308
  `)}return process.stderr.write(hh0),2}}LT0();var fh0=()=>globalThis[Symbol.for("loki.ownsStopSignals")]===!0;process.on("SIGINT",()=>{if(!fh0())process.exit(130)});process.on("SIGTERM",()=>{if(!fh0())process.exit(143)});var PM9=await TM9(Bun.argv.slice(2));process.exit(PM9);
3309
3309
 
3310
- //# debugId=B0A8705AC90A1A1A77C6B4D237F661D3
3310
+ //# debugId=FB5A79A1D5A6F72D6BD0D13C760033DE
package/mcp/__init__.py CHANGED
@@ -75,4 +75,4 @@ try:
75
75
  except ImportError:
76
76
  __all__ = ['mcp']
77
77
 
78
- __version__ = '11.71.0'
78
+ __version__ = '11.71.2'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "loki-mode",
3
3
  "mcpName": "io.github.asklokesh/loki-mode",
4
- "version": "11.71.0",
4
+ "version": "11.71.2",
5
5
  "description": "An autonomous software factory that knows what it is supposed to deliver, and proves it did.",
6
6
  "keywords": [
7
7
  "agent",
@@ -160,5 +160,5 @@
160
160
  "dependencies": {
161
161
  "@resvg/resvg-wasm": "^2.6.2"
162
162
  },
163
- "gitHead": "59b049d5f3dc655ae22d513b29197279c1b28ba5"
163
+ "gitHead": "de6f7f68758771633ae315ea3118106cacb77cea"
164
164
  }
@@ -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.71.0",
5
+ "version": "11.71.2",
6
6
  "description": "Autonomous spec-to-product build system with a built-in trust layer (RARV-C closure loop, 8 quality gates, completion council). Ships Loki's spec-hardening, drift-detection, and deterministic PR verification commands plus the Loki MCP server.",
7
7
  "author": {
8
8
  "name": "Autonomi",
@@ -1,4 +1,4 @@
1
- import{c as L,r as x,j as e,w as re,Z as ne,m as le,h as ie,p as P,F as ye,U as I,X as ce,L as de,x as oe,M as Ae,T as Z,S as we,l as xe,k as me,y as Ce,E as Fe,a0 as Se,a as U,a2 as he}from"./index-DkqOX7Z7.js";import{B as C}from"./Button-Danr8Id8.js";import{T as $e}from"./trending-up-BkjfOvvM.js";import{C as z}from"./clock-COELjcX4.js";import{A as Be,U as ue,M as De}from"./Avatar-DSxI4as6.js";import{A as J}from"./activity-CzpvMfJh.js";import{R as pe}from"./refresh-cw-Cc5RjW2p.js";import{G as ze}from"./globe-CgUnp7ir.js";import{C as Le}from"./chevron-left-Crx6bo4v.js";import{C as je}from"./check-D3zw6xf0.js";import{D as Y}from"./dollar-sign-CaDqc5Da.js";import{U as Te}from"./user-CAbIEZrD.js";import{D as Me}from"./database-BtRK0egx.js";import{L as Ue}from"./lock-BVUQu1ou.js";import{S as Re}from"./scroll-text-4DceQ6It.js";import{S as Ie}from"./shield-alert-Dh2woWQf.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-C5bIS38k.js";import{B as C}from"./Button-DFCgFerI.js";import{T as $e}from"./trending-up-D1K9uAn2.js";import{C as z}from"./clock-DwN_q_HA.js";import{A as Be,U as ue,M as De}from"./Avatar-FWW_Pp5i.js";import{A as J}from"./activity-BwTdw5jH.js";import{R as pe}from"./refresh-cw-DtvtryKd.js";import{G as ze}from"./globe-Bqb_jTXY.js";import{C as Le}from"./chevron-left-De8fDgTg.js";import{C as je}from"./check-55rEw_tX.js";import{D as Y}from"./dollar-sign-ZkSJEKpU.js";import{U as Te}from"./user-CHnU9Yb4.js";import{D as Me}from"./database-DTI91kcw.js";import{L as Ue}from"./lock-D9acVIOc.js";import{S as Re}from"./scroll-text-LEEOPYAl.js";import{S as Ie}from"./shield-alert-WL6uL9Y1.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-DkqOX7Z7.js";/**
1
+ import{c as l,j as s}from"./index-C5bIS38k.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-DkqOX7Z7.js";import{C as r}from"./clock-COELjcX4.js";import{C as a}from"./circle-alert--XExSKHo.js";import{C as l}from"./check-D3zw6xf0.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-C5bIS38k.js";import{C as r}from"./clock-DwN_q_HA.js";import{C as a}from"./circle-alert-C73LIkta.js";import{C as l}from"./check-55rEw_tX.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-DkqOX7Z7.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-C5bIS38k.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-DkqOX7Z7.js";import{P as K,S as He,E as Be}from"./ErrorBoundary-CrHfaUmC.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-DFgETaoZ.js";import{C as oe}from"./check-D3zw6xf0.js";import{C as Ye}from"./clock-COELjcX4.js";import{D as Xe}from"./dollar-sign-CaDqc5Da.js";import{U as Ze}from"./upload-CSxnKVOV.js";import{L as V}from"./loader-circle-BeigjxhD.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-C5bIS38k.js";import{P as K,S as He,E as Be}from"./ErrorBoundary-XEDM5Jef.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-CsnDxpb3.js";import{C as oe}from"./check-55rEw_tX.js";import{C as Ye}from"./clock-DwN_q_HA.js";import{D as Xe}from"./dollar-sign-ZkSJEKpU.js";import{U as Ze}from"./upload-BhYbtn7Q.js";import{L as V}from"./loader-circle-BSxzcRoH.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{r as o,j as e}from"./index-DkqOX7Z7.js";function f({value:r,prefix:t="",suffix:s=""}){const[u,n]=o.useState(0),c=o.useRef(0);return o.useEffect(()=>{const a=c.current,h=r-a;if(h===0)return;const i=600,d=performance.now();function l(b){const v=b-d,m=Math.min(v/i,1),N=1-Math.pow(1-m,3),p=Math.round(a+h*N);n(p),c.current=p,m<1&&requestAnimationFrame(l)}requestAnimationFrame(l)},[r]),e.jsxs("span",{className:"tabular-nums",children:[t,u.toLocaleString(),s]})}function g(){const[r,t]=o.useState(5),[s,u]=o.useState(30),[n,c]=o.useState(75),a=.4,i=Math.round(r*s*a*4.33),d=Math.round(i*n);return e.jsxs("div",{className:"bg-white border border-[#ECEAE3] rounded-xl p-6 shadow-sm",children:[e.jsx("h3",{className:"text-lg font-bold text-[#36342E] mb-1",children:"ROI Calculator"}),e.jsx("p",{className:"text-sm text-[#6B6960] mb-6",children:"Estimate how much your team could save with autonomous development."}),e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("label",{className:"text-sm font-medium text-[#36342E]",children:"Team size"}),e.jsxs("span",{className:"text-sm font-semibold text-[#553DE9] tabular-nums",children:[r," developers"]})]}),e.jsx("input",{type:"range",min:1,max:50,value:r,onChange:l=>t(Number(l.target.value)),className:"w-full h-2 bg-[#ECEAE3] rounded-full appearance-none cursor-pointer accent-[#553DE9]"}),e.jsxs("div",{className:"flex justify-between text-xs text-[#939084] mt-1",children:[e.jsx("span",{children:"1"}),e.jsx("span",{children:"50"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("label",{className:"text-sm font-medium text-[#36342E]",children:"Hours coding per week"}),e.jsxs("span",{className:"text-sm font-semibold text-[#553DE9] tabular-nums",children:[s,"h"]})]}),e.jsx("input",{type:"range",min:5,max:60,value:s,onChange:l=>u(Number(l.target.value)),className:"w-full h-2 bg-[#ECEAE3] rounded-full appearance-none cursor-pointer accent-[#553DE9]"}),e.jsxs("div",{className:"flex justify-between text-xs text-[#939084] mt-1",children:[e.jsx("span",{children:"5h"}),e.jsx("span",{children:"60h"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("label",{className:"text-sm font-medium text-[#36342E]",children:"Average hourly rate"}),e.jsxs("span",{className:"text-sm font-semibold text-[#553DE9] tabular-nums",children:["$",n,"/hr"]})]}),e.jsx("input",{type:"range",min:25,max:250,step:5,value:n,onChange:l=>c(Number(l.target.value)),className:"w-full h-2 bg-[#ECEAE3] rounded-full appearance-none cursor-pointer accent-[#553DE9]"}),e.jsxs("div",{className:"flex justify-between text-xs text-[#939084] mt-1",children:[e.jsx("span",{children:"$25"}),e.jsx("span",{children:"$250"})]})]})]}),e.jsxs("div",{className:"mt-6 pt-6 border-t border-[#ECEAE3]",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4 text-center",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-2xl font-bold text-[#553DE9]",children:e.jsx(f,{value:i,suffix:"h"})}),e.jsx("div",{className:"text-xs text-[#6B6960] mt-1",children:"Est. hours saved / month"})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-2xl font-bold text-[#1FC5A8]",children:e.jsx(f,{value:d,prefix:"$"})}),e.jsx("div",{className:"text-xs text-[#6B6960] mt-1",children:"Est. cost saved / month"})]})]}),e.jsxs("div",{className:"mt-4 p-3 rounded-lg bg-[#553DE9]/5 border border-[#553DE9]/10",children:[e.jsxs("p",{className:"text-sm text-[#36342E] text-center",children:["If Loki Mode saved ",Math.round(a*100),"% of coding time, your team could save"," ",e.jsxs("span",{className:"font-bold text-[#553DE9]",children:[i.toLocaleString()," hours"]})," ","and"," ",e.jsxs("span",{className:"font-bold text-[#1FC5A8]",children:["$",d.toLocaleString()]})," ","per month."]}),e.jsxs("p",{className:"mt-2 text-xs text-[#6B6960] text-center",children:["The ",Math.round(a*100),"% is an assumption, not a measurement. Model and API spend is not included."]})]})]})]})}const j=[{feature:"Claude (Opus/Sonnet/Haiku)",category:"AI Models",lokiMode:!0,boltNew:!1,replit:!1,lovable:!0},{feature:"GPT-4o / Codex",category:"AI Models",lokiMode:!0,boltNew:!0,replit:!0,lovable:!1},{feature:"5-provider auto-failover",category:"AI Models",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"8 automated quality gates",category:"Quality",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"Blind 3-reviewer code review",category:"Quality",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"Anti-sycophancy checks",category:"Quality",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"Automated test generation",category:"Quality",lokiMode:!0,boltNew:!1,replit:"Partial",lovable:!1},{feature:"Docker container generation",category:"Deployment",lokiMode:!0,boltNew:!1,replit:!0,lovable:!1},{feature:"CI/CD pipeline generation",category:"Deployment",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"One-click cloud deploy",category:"Deployment",lokiMode:"Planned",boltNew:!0,replit:!0,lovable:!0},{feature:"Self-hosted (your keys)",category:"Cost",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"Free tier available",category:"Cost",lokiMode:"Source-available (BUSL-1.1)",boltNew:!0,replit:!0,lovable:!0},{feature:"No vendor lock-in",category:"Cost",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"SSO / OIDC authentication",category:"Enterprise",lokiMode:!0,boltNew:!1,replit:!0,lovable:!1},{feature:"RBAC access control",category:"Enterprise",lokiMode:!0,boltNew:!1,replit:!0,lovable:!1},{feature:"Audit logging",category:"Enterprise",lokiMode:!0,boltNew:!1,replit:!0,lovable:!1},{feature:"Air-gapped deployment",category:"Enterprise",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1}];function y(){return e.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",className:"text-[#1FC5A8]",children:e.jsx("path",{d:"M20 6L9 17l-5-5",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function w(){return e.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",className:"text-[#C45B5B]/40",children:e.jsx("path",{d:"M18 6L6 18M6 6l12 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function x({value:r}){return typeof r=="string"?e.jsx("span",{className:"text-xs text-[#6B6960] font-medium",children:r}):r?e.jsx(y,{}):e.jsx(w,{})}const k=[{title:"Full Autonomy",description:"Describe what you want. Loki Mode handles planning, coding, testing, and verification automatically.",icon:e.jsx("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",className:"text-[#553DE9]",children:e.jsx("path",{d:"M13 2L3 14h9l-1 8 10-12h-9l1-8z",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})},{title:"Production Quality",description:"8 quality gates, blind code review, and anti-sycophancy checks ensure code that actually works.",icon:e.jsx("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",className:"text-[#1FC5A8]",children:e.jsx("path",{d:"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})},{title:"Your Infrastructure",description:"Self-hosted, source-available (BUSL-1.1), no data leaves your network. Use your own API keys across 5 providers.",icon:e.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",className:"text-[#2F71E3]",children:[e.jsx("rect",{x:"2",y:"2",width:"20",height:"8",rx:"2",stroke:"currentColor",strokeWidth:"2"}),e.jsx("rect",{x:"2",y:"14",width:"20",height:"8",rx:"2",stroke:"currentColor",strokeWidth:"2"}),e.jsx("circle",{cx:"6",cy:"6",r:"1",fill:"currentColor"}),e.jsx("circle",{cx:"6",cy:"18",r:"1",fill:"currentColor"})]})},{title:"Built for Teams",description:"Enterprise auth, RBAC, audit logs, and parallel workflows for teams of any size.",icon:e.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",className:"text-[#E93D82]",children:[e.jsx("path",{d:"M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"}),e.jsx("circle",{cx:"9",cy:"7",r:"4",stroke:"currentColor",strokeWidth:"2"}),e.jsx("path",{d:"M23 21v-2a4 4 0 00-3-3.87M16 3.13a4 4 0 010 7.75",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})]})}];function C(){const r=[...new Set(j.map(t=>t.category))];return e.jsx("div",{className:"min-h-screen bg-[#FAF9F6]",children:e.jsxs("div",{className:"max-w-6xl mx-auto px-6 py-8",children:[e.jsxs("div",{className:"mb-8",children:[e.jsx("h1",{className:"text-2xl font-bold text-[#36342E]",children:"Compare"}),e.jsx("p",{className:"text-[#6B6960] mt-1",children:"See how Loki Mode stacks up against other AI development platforms."})]}),e.jsx("div",{className:"bg-white border border-[#ECEAE3] rounded-xl overflow-hidden shadow-sm",children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-[#ECEAE3]",children:[e.jsx("th",{className:"text-left px-4 py-3 font-medium text-[#6B6960] w-[240px]",children:"Feature"}),e.jsx("th",{className:"text-center px-4 py-3 font-bold text-[#553DE9] bg-[#553DE9]/5 w-[130px]",children:"Loki Mode"}),e.jsx("th",{className:"text-center px-4 py-3 font-medium text-[#6B6960] w-[130px]",children:"bolt.new"}),e.jsx("th",{className:"text-center px-4 py-3 font-medium text-[#6B6960] w-[130px]",children:"Replit"}),e.jsx("th",{className:"text-center px-4 py-3 font-medium text-[#6B6960] w-[130px]",children:"Lovable"})]})}),e.jsx("tbody",{children:r.map(t=>e.jsxs(e.Fragment,{children:[e.jsx("tr",{className:"bg-[#FAF9F6]",children:e.jsx("td",{colSpan:5,className:"px-4 py-2 text-xs font-bold text-[#939084] uppercase tracking-wider",children:t})},`cat-${t}`),j.filter(s=>s.category===t).map(s=>e.jsxs("tr",{className:"border-b border-[#ECEAE3] last:border-b-0",children:[e.jsx("td",{className:"px-4 py-2.5 text-[#36342E]",children:s.feature}),e.jsx("td",{className:"px-4 py-2.5 text-center bg-[#553DE9]/5",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(x,{value:s.lokiMode})})}),e.jsx("td",{className:"px-4 py-2.5 text-center",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(x,{value:s.boltNew})})}),e.jsx("td",{className:"px-4 py-2.5 text-center",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(x,{value:s.replit})})}),e.jsx("td",{className:"px-4 py-2.5 text-center",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(x,{value:s.lovable})})})]},s.feature))]}))})]})})}),e.jsxs("div",{className:"mt-12",children:[e.jsx("h2",{className:"text-xl font-bold text-[#36342E] mb-6",children:"Why developers choose Loki Mode"}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-5",children:k.map(t=>e.jsxs("div",{className:"bg-white border border-[#ECEAE3] rounded-xl p-5 shadow-sm hover:shadow-md transition-shadow",children:[e.jsx("div",{className:"mb-3",children:t.icon}),e.jsx("h3",{className:"text-base font-bold text-[#36342E] mb-1",children:t.title}),e.jsx("p",{className:"text-sm text-[#6B6960]",children:t.description})]},t.title))})]}),e.jsx("div",{className:"mt-12 max-w-xl mx-auto",children:e.jsx(g,{})})]})})}export{C as default};
1
+ import{r as o,j as e}from"./index-C5bIS38k.js";function f({value:r,prefix:t="",suffix:s=""}){const[u,n]=o.useState(0),c=o.useRef(0);return o.useEffect(()=>{const a=c.current,h=r-a;if(h===0)return;const i=600,d=performance.now();function l(b){const v=b-d,m=Math.min(v/i,1),N=1-Math.pow(1-m,3),p=Math.round(a+h*N);n(p),c.current=p,m<1&&requestAnimationFrame(l)}requestAnimationFrame(l)},[r]),e.jsxs("span",{className:"tabular-nums",children:[t,u.toLocaleString(),s]})}function g(){const[r,t]=o.useState(5),[s,u]=o.useState(30),[n,c]=o.useState(75),a=.4,i=Math.round(r*s*a*4.33),d=Math.round(i*n);return e.jsxs("div",{className:"bg-white border border-[#ECEAE3] rounded-xl p-6 shadow-sm",children:[e.jsx("h3",{className:"text-lg font-bold text-[#36342E] mb-1",children:"ROI Calculator"}),e.jsx("p",{className:"text-sm text-[#6B6960] mb-6",children:"Estimate how much your team could save with autonomous development."}),e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("label",{className:"text-sm font-medium text-[#36342E]",children:"Team size"}),e.jsxs("span",{className:"text-sm font-semibold text-[#553DE9] tabular-nums",children:[r," developers"]})]}),e.jsx("input",{type:"range",min:1,max:50,value:r,onChange:l=>t(Number(l.target.value)),className:"w-full h-2 bg-[#ECEAE3] rounded-full appearance-none cursor-pointer accent-[#553DE9]"}),e.jsxs("div",{className:"flex justify-between text-xs text-[#939084] mt-1",children:[e.jsx("span",{children:"1"}),e.jsx("span",{children:"50"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("label",{className:"text-sm font-medium text-[#36342E]",children:"Hours coding per week"}),e.jsxs("span",{className:"text-sm font-semibold text-[#553DE9] tabular-nums",children:[s,"h"]})]}),e.jsx("input",{type:"range",min:5,max:60,value:s,onChange:l=>u(Number(l.target.value)),className:"w-full h-2 bg-[#ECEAE3] rounded-full appearance-none cursor-pointer accent-[#553DE9]"}),e.jsxs("div",{className:"flex justify-between text-xs text-[#939084] mt-1",children:[e.jsx("span",{children:"5h"}),e.jsx("span",{children:"60h"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("label",{className:"text-sm font-medium text-[#36342E]",children:"Average hourly rate"}),e.jsxs("span",{className:"text-sm font-semibold text-[#553DE9] tabular-nums",children:["$",n,"/hr"]})]}),e.jsx("input",{type:"range",min:25,max:250,step:5,value:n,onChange:l=>c(Number(l.target.value)),className:"w-full h-2 bg-[#ECEAE3] rounded-full appearance-none cursor-pointer accent-[#553DE9]"}),e.jsxs("div",{className:"flex justify-between text-xs text-[#939084] mt-1",children:[e.jsx("span",{children:"$25"}),e.jsx("span",{children:"$250"})]})]})]}),e.jsxs("div",{className:"mt-6 pt-6 border-t border-[#ECEAE3]",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4 text-center",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-2xl font-bold text-[#553DE9]",children:e.jsx(f,{value:i,suffix:"h"})}),e.jsx("div",{className:"text-xs text-[#6B6960] mt-1",children:"Est. hours saved / month"})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-2xl font-bold text-[#1FC5A8]",children:e.jsx(f,{value:d,prefix:"$"})}),e.jsx("div",{className:"text-xs text-[#6B6960] mt-1",children:"Est. cost saved / month"})]})]}),e.jsxs("div",{className:"mt-4 p-3 rounded-lg bg-[#553DE9]/5 border border-[#553DE9]/10",children:[e.jsxs("p",{className:"text-sm text-[#36342E] text-center",children:["If Loki Mode saved ",Math.round(a*100),"% of coding time, your team could save"," ",e.jsxs("span",{className:"font-bold text-[#553DE9]",children:[i.toLocaleString()," hours"]})," ","and"," ",e.jsxs("span",{className:"font-bold text-[#1FC5A8]",children:["$",d.toLocaleString()]})," ","per month."]}),e.jsxs("p",{className:"mt-2 text-xs text-[#6B6960] text-center",children:["The ",Math.round(a*100),"% is an assumption, not a measurement. Model and API spend is not included."]})]})]})]})}const j=[{feature:"Claude (Opus/Sonnet/Haiku)",category:"AI Models",lokiMode:!0,boltNew:!1,replit:!1,lovable:!0},{feature:"GPT-4o / Codex",category:"AI Models",lokiMode:!0,boltNew:!0,replit:!0,lovable:!1},{feature:"5-provider auto-failover",category:"AI Models",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"8 automated quality gates",category:"Quality",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"Blind 3-reviewer code review",category:"Quality",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"Anti-sycophancy checks",category:"Quality",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"Automated test generation",category:"Quality",lokiMode:!0,boltNew:!1,replit:"Partial",lovable:!1},{feature:"Docker container generation",category:"Deployment",lokiMode:!0,boltNew:!1,replit:!0,lovable:!1},{feature:"CI/CD pipeline generation",category:"Deployment",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"One-click cloud deploy",category:"Deployment",lokiMode:"Planned",boltNew:!0,replit:!0,lovable:!0},{feature:"Self-hosted (your keys)",category:"Cost",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"Free tier available",category:"Cost",lokiMode:"Source-available (BUSL-1.1)",boltNew:!0,replit:!0,lovable:!0},{feature:"No vendor lock-in",category:"Cost",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"SSO / OIDC authentication",category:"Enterprise",lokiMode:!0,boltNew:!1,replit:!0,lovable:!1},{feature:"RBAC access control",category:"Enterprise",lokiMode:!0,boltNew:!1,replit:!0,lovable:!1},{feature:"Audit logging",category:"Enterprise",lokiMode:!0,boltNew:!1,replit:!0,lovable:!1},{feature:"Air-gapped deployment",category:"Enterprise",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1}];function y(){return e.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",className:"text-[#1FC5A8]",children:e.jsx("path",{d:"M20 6L9 17l-5-5",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function w(){return e.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",className:"text-[#C45B5B]/40",children:e.jsx("path",{d:"M18 6L6 18M6 6l12 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function x({value:r}){return typeof r=="string"?e.jsx("span",{className:"text-xs text-[#6B6960] font-medium",children:r}):r?e.jsx(y,{}):e.jsx(w,{})}const k=[{title:"Full Autonomy",description:"Describe what you want. Loki Mode handles planning, coding, testing, and verification automatically.",icon:e.jsx("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",className:"text-[#553DE9]",children:e.jsx("path",{d:"M13 2L3 14h9l-1 8 10-12h-9l1-8z",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})},{title:"Production Quality",description:"8 quality gates, blind code review, and anti-sycophancy checks ensure code that actually works.",icon:e.jsx("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",className:"text-[#1FC5A8]",children:e.jsx("path",{d:"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})},{title:"Your Infrastructure",description:"Self-hosted, source-available (BUSL-1.1), no data leaves your network. Use your own API keys across 5 providers.",icon:e.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",className:"text-[#2F71E3]",children:[e.jsx("rect",{x:"2",y:"2",width:"20",height:"8",rx:"2",stroke:"currentColor",strokeWidth:"2"}),e.jsx("rect",{x:"2",y:"14",width:"20",height:"8",rx:"2",stroke:"currentColor",strokeWidth:"2"}),e.jsx("circle",{cx:"6",cy:"6",r:"1",fill:"currentColor"}),e.jsx("circle",{cx:"6",cy:"18",r:"1",fill:"currentColor"})]})},{title:"Built for Teams",description:"Enterprise auth, RBAC, audit logs, and parallel workflows for teams of any size.",icon:e.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",className:"text-[#E93D82]",children:[e.jsx("path",{d:"M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"}),e.jsx("circle",{cx:"9",cy:"7",r:"4",stroke:"currentColor",strokeWidth:"2"}),e.jsx("path",{d:"M23 21v-2a4 4 0 00-3-3.87M16 3.13a4 4 0 010 7.75",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})]})}];function C(){const r=[...new Set(j.map(t=>t.category))];return e.jsx("div",{className:"min-h-screen bg-[#FAF9F6]",children:e.jsxs("div",{className:"max-w-6xl mx-auto px-6 py-8",children:[e.jsxs("div",{className:"mb-8",children:[e.jsx("h1",{className:"text-2xl font-bold text-[#36342E]",children:"Compare"}),e.jsx("p",{className:"text-[#6B6960] mt-1",children:"See how Loki Mode stacks up against other AI development platforms."})]}),e.jsx("div",{className:"bg-white border border-[#ECEAE3] rounded-xl overflow-hidden shadow-sm",children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-[#ECEAE3]",children:[e.jsx("th",{className:"text-left px-4 py-3 font-medium text-[#6B6960] w-[240px]",children:"Feature"}),e.jsx("th",{className:"text-center px-4 py-3 font-bold text-[#553DE9] bg-[#553DE9]/5 w-[130px]",children:"Loki Mode"}),e.jsx("th",{className:"text-center px-4 py-3 font-medium text-[#6B6960] w-[130px]",children:"bolt.new"}),e.jsx("th",{className:"text-center px-4 py-3 font-medium text-[#6B6960] w-[130px]",children:"Replit"}),e.jsx("th",{className:"text-center px-4 py-3 font-medium text-[#6B6960] w-[130px]",children:"Lovable"})]})}),e.jsx("tbody",{children:r.map(t=>e.jsxs(e.Fragment,{children:[e.jsx("tr",{className:"bg-[#FAF9F6]",children:e.jsx("td",{colSpan:5,className:"px-4 py-2 text-xs font-bold text-[#939084] uppercase tracking-wider",children:t})},`cat-${t}`),j.filter(s=>s.category===t).map(s=>e.jsxs("tr",{className:"border-b border-[#ECEAE3] last:border-b-0",children:[e.jsx("td",{className:"px-4 py-2.5 text-[#36342E]",children:s.feature}),e.jsx("td",{className:"px-4 py-2.5 text-center bg-[#553DE9]/5",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(x,{value:s.lokiMode})})}),e.jsx("td",{className:"px-4 py-2.5 text-center",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(x,{value:s.boltNew})})}),e.jsx("td",{className:"px-4 py-2.5 text-center",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(x,{value:s.replit})})}),e.jsx("td",{className:"px-4 py-2.5 text-center",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(x,{value:s.lovable})})})]},s.feature))]}))})]})})}),e.jsxs("div",{className:"mt-12",children:[e.jsx("h2",{className:"text-xl font-bold text-[#36342E] mb-6",children:"Why developers choose Loki Mode"}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-5",children:k.map(t=>e.jsxs("div",{className:"bg-white border border-[#ECEAE3] rounded-xl p-5 shadow-sm hover:shadow-md transition-shadow",children:[e.jsx("div",{className:"mb-3",children:t.icon}),e.jsx("h3",{className:"text-base font-bold text-[#36342E] mb-1",children:t.title}),e.jsx("p",{className:"text-sm text-[#6B6960]",children:t.description})]},t.title))})]}),e.jsx("div",{className:"mt-12 max-w-xl mx-auto",children:e.jsx(g,{})})]})})}export{C as default};
@@ -1,4 +1,4 @@
1
- import{c as o,r as a,j as e,T as n,h as i,p as c}from"./index-DkqOX7Z7.js";/**
1
+ import{c as o,r as a,j as e,T as n,h as i,p as c}from"./index-C5bIS38k.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.