loki-mode 10.5.19 → 10.5.20

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 (69) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/run.sh +8 -3
  4. package/autonomy/verify.sh +1 -1
  5. package/dashboard/__init__.py +1 -1
  6. package/docs/INSTALLATION.md +1 -1
  7. package/docs/v10/BOARD.md +5 -5
  8. package/docs/v10/PROGRESS.md +7 -0
  9. package/loki-ts/dist/loki.js +2 -2
  10. package/mcp/__init__.py +1 -1
  11. package/package.json +1 -1
  12. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  13. package/web-app/dist/assets/{AdminPage-BH_7fpoz.js → AdminPage-HjtApbcL.js} +1 -1
  14. package/web-app/dist/assets/{Avatar-BzyhrX0s.js → Avatar-BcwLENsU.js} +1 -1
  15. package/web-app/dist/assets/{Badge-CL05xwgC.js → Badge-DjJhHJj0.js} +1 -1
  16. package/web-app/dist/assets/{Button-BVHrGLGH.js → Button-CSMstrCz.js} +1 -1
  17. package/web-app/dist/assets/{CockpitPage-B9BAEqD-.js → CockpitPage-BHihN-aq.js} +1 -1
  18. package/web-app/dist/assets/{ComparePage-D4grckhY.js → ComparePage-_6JtexDp.js} +1 -1
  19. package/web-app/dist/assets/{ErrorBoundary-Bg52u7eg.js → ErrorBoundary-Cx2fnw3q.js} +1 -1
  20. package/web-app/dist/assets/{EvidenceReceiptPanel-B15kRZbJ.js → EvidenceReceiptPanel-DcUQAnju.js} +1 -1
  21. package/web-app/dist/assets/{GitHubIssuesPanel-DP_BhJSC.js → GitHubIssuesPanel-1dYpQ5Rx.js} +1 -1
  22. package/web-app/dist/assets/{GitHubPRsPanel-DJBu83u9.js → GitHubPRsPanel-BPdDD1kX.js} +1 -1
  23. package/web-app/dist/assets/{HomePage-6mw4uvLs.js → HomePage-JfmwLGnQ.js} +2 -2
  24. package/web-app/dist/assets/{LoginPage-BWWzFHif.js → LoginPage-7SnMHzPc.js} +1 -1
  25. package/web-app/dist/assets/{MagicPage-CSyo7k5t.js → MagicPage-C0IkoOzD.js} +1 -1
  26. package/web-app/dist/assets/{MetricsPage-Buq03cch.js → MetricsPage-BJOZ0L3F.js} +1 -1
  27. package/web-app/dist/assets/{NotFoundPage-BG8vuV4g.js → NotFoundPage-S49UjLyW.js} +1 -1
  28. package/web-app/dist/assets/{ProjectPage-D7eJn--6.js → ProjectPage-Dj_nv2kT.js} +3 -3
  29. package/web-app/dist/assets/{ProjectsPage-DXPycvjA.js → ProjectsPage-C7thLjOm.js} +1 -1
  30. package/web-app/dist/assets/{SettingsPage-Blvav87U.js → SettingsPage-DEcJyfsU.js} +1 -1
  31. package/web-app/dist/assets/{ShowcasePage-ZCAKRsNN.js → ShowcasePage-B5PshXNg.js} +1 -1
  32. package/web-app/dist/assets/{SystemSettingsPage-ClzjKfI4.js → SystemSettingsPage-Cnp4BkN7.js} +1 -1
  33. package/web-app/dist/assets/{TeamsPage-CKp1-WGX.js → TeamsPage-1ImpgMzs.js} +1 -1
  34. package/web-app/dist/assets/{TemplatesPage-C0yAp2Yl.js → TemplatesPage-BOYKrPX8.js} +1 -1
  35. package/web-app/dist/assets/{TerminalOutput-C3KbV8E7.js → TerminalOutput-LPxzwfwm.js} +1 -1
  36. package/web-app/dist/assets/{activity-CG5PtpVI.js → activity-Hl7iDpX_.js} +1 -1
  37. package/web-app/dist/assets/{bell-CyLp--NR.js → bell-DrBfjAq4.js} +1 -1
  38. package/web-app/dist/assets/{bot-Dp0zY9t7.js → bot-6SoklKaZ.js} +1 -1
  39. package/web-app/dist/assets/{check-ipranz8L.js → check-DhHuZH8k.js} +1 -1
  40. package/web-app/dist/assets/{chevron-left-DhYs9D3t.js → chevron-left-BUERGaLO.js} +1 -1
  41. package/web-app/dist/assets/{circle-alert-BLAxBNgz.js → circle-alert-D7UOw5bc.js} +1 -1
  42. package/web-app/dist/assets/{clock-DzocnapF.js → clock-t3v_i7fP.js} +1 -1
  43. package/web-app/dist/assets/{cloud-B3YsIUwq.js → cloud-CP3eLZts.js} +1 -1
  44. package/web-app/dist/assets/{code-xml-BPcy_Eqm.js → code-xml-DU-CmwVx.js} +1 -1
  45. package/web-app/dist/assets/{database-DOuuclZf.js → database-J27fE_Ot.js} +1 -1
  46. package/web-app/dist/assets/{dollar-sign-o77cj-xB.js → dollar-sign-BdU_HR9C.js} +1 -1
  47. package/web-app/dist/assets/{file-code-corner-BZ2VMnYA.js → file-code-corner-Cu4A1aIH.js} +1 -1
  48. package/web-app/dist/assets/{file-plus-DeHfGncj.js → file-plus-BTli76r5.js} +1 -1
  49. package/web-app/dist/assets/{globe-DmIW-phf.js → globe-Bz3m1c_-.js} +1 -1
  50. package/web-app/dist/assets/{hammer-CoW8R8V5.js → hammer-HNN6jr92.js} +1 -1
  51. package/web-app/dist/assets/{index-5rCTAnsF.js → index-CgK4xqUy.js} +3 -3
  52. package/web-app/dist/assets/{layers-DGEk-2RQ.js → layers-DhuXUuM6.js} +1 -1
  53. package/web-app/dist/assets/{loader-circle-DXn-F-H5.js → loader-circle-CeBjdh2y.js} +1 -1
  54. package/web-app/dist/assets/{lock-D5nAjeUu.js → lock-DjSqmIVZ.js} +1 -1
  55. package/web-app/dist/assets/{package-D8Drpzi8.js → package-NL0AdpIi.js} +1 -1
  56. package/web-app/dist/assets/{plus-C-0T9dAu.js → plus-Lbz3hom-.js} +1 -1
  57. package/web-app/dist/assets/{refresh-cw-AyYQQPZG.js → refresh-cw-uKARwuER.js} +1 -1
  58. package/web-app/dist/assets/{rotate-ccw-DYbslLfT.js → rotate-ccw-ByA6XJq1.js} +1 -1
  59. package/web-app/dist/assets/{scroll-text-CQFQhF_6.js → scroll-text-BV8Blxig.js} +1 -1
  60. package/web-app/dist/assets/{server-DxNytQEJ.js → server-Cy3R5hde.js} +1 -1
  61. package/web-app/dist/assets/{shield-alert-Xj5wGUSK.js → shield-alert-rE_xXx7r.js} +1 -1
  62. package/web-app/dist/assets/{thumbs-up-DW0j9Yxz.js → thumbs-up-CNMITZHD.js} +1 -1
  63. package/web-app/dist/assets/{trash-2-VOdpiJ1e.js → trash-2-BP3Rr5SU.js} +1 -1
  64. package/web-app/dist/assets/{trending-down-eTizH4_b.js → trending-down-BE_8lCjD.js} +1 -1
  65. package/web-app/dist/assets/{trending-up-agYVl7bU.js → trending-up-CF6E9-9a.js} +1 -1
  66. package/web-app/dist/assets/{upload-DQ3NfXA_.js → upload-D-Ui4N6K.js} +1 -1
  67. package/web-app/dist/assets/{usePolling-BKETnkDT.js → usePolling-DIVX97OV.js} +1 -1
  68. package/web-app/dist/assets/{user-Cv6BNmOT.js → user-7rTiTfDj.js} +1 -1
  69. package/web-app/dist/index.html +1 -1
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: loki-mode
3
3
  description: An autonomous software factory that knows what it is supposed to deliver, and proves it did. Use when the user says Loki Mode or asks to build, fix or verify software autonomously.
4
4
  ---
5
5
 
6
- # Loki Mode v10.5.19
6
+ # Loki Mode v10.5.20
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -470,4 +470,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
470
470
 
471
471
  ---
472
472
 
473
- **v10.5.19 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
473
+ **v10.5.20 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 10.5.19
1
+ 10.5.20
package/autonomy/run.sh CHANGED
@@ -256,7 +256,10 @@ if [ -z "${LOKI_QUICK_INNER:-}" ] && [ "${LOKI_VERBOSE:-0}" != "1" ] && [ "${BAS
256
256
  if command -v python3 >/dev/null 2>&1 && python3 -c 'import os,signal' >/dev/null 2>&1; then
257
257
  _qexec=(python3 -c 'import os,signal,sys;signal.signal(signal.SIGPIPE,signal.SIG_DFL);os.execv(sys.argv[1],sys.argv[1:])' "${_qexec[@]}")
258
258
  fi
259
- ( trap - INT QUIT; LOKI_QUICK_DIR="$_qd" LOKI_QUICK_OUTER_PID=$$ LOKI_QUICK_INNER=1 exec "${_qexec[@]}" >"$_qd/quick-run.log" ) &
259
+ # A background job gets stdin=/dev/null. Only a TTY needs it back (pause-mode
260
+ # keypress resume); a pipe would block the provider, which reads inherited stdin.
261
+ if [ -t 0 ]; then exec 3<&0; else exec 3</dev/null; fi
262
+ ( trap - INT QUIT; LOKI_QUICK_DIR="$_qd" LOKI_QUICK_OUTER_PID=$$ LOKI_QUICK_INNER=1 exec "${_qexec[@]}" >"$_qd/quick-run.log" <&3 3<&- ) &
260
263
  _qpid=$!
261
264
  trap 'kill -INT "$_qpid" 2>/dev/null' INT
262
265
  trap 'kill -TERM "$_qpid" 2>/dev/null' TERM HUP
@@ -265,8 +268,10 @@ if [ -z "${LOKI_QUICK_INNER:-}" ] && [ "${LOKI_VERBOSE:-0}" != "1" ] && [ "${BAS
265
268
  trap - INT TERM HUP
266
269
  _qw=$(grep -cF '[WARN]' "$_qd/quick-run.log" 2>/dev/null); _qw="${_qw:-0}"
267
270
  if [ "$_qrc" -ne 0 ] || [ ! -s "$_qd/quick-receipt.txt" ]; then
268
- _qr=$(grep -E '\[(ERROR|WARN)\]|[Ss]topped|[Ff]ailed' "$_qd/quick-run.log" 2>/dev/null | tail -n 3)
269
- echo "${_qr:-$(tail -n 3 "$_qd/quick-run.log" 2>/dev/null)}"
271
+ # Anchored to log_error/log_warn lines (optional ANSI prefix) and capped at 200
272
+ # chars so a long prompt line mentioning "failed" is never dumped.
273
+ _qr=$(grep -E $'^(\033\\[[0-9;]*m)?\\[(ERROR|WARN)\\]' "$_qd/quick-run.log" 2>/dev/null | tail -n 3 | cut -c1-200)
274
+ echo "${_qr:-$(tail -n 3 "$_qd/quick-run.log" 2>/dev/null | cut -c1-200)}"
270
275
  fi
271
276
  [ "$_qw" -gt 0 ] && echo "Warnings: $_qw (see $_qd/quick-run.log)"
272
277
  cat "$_qd/quick-receipt.txt" 2>/dev/null
@@ -3071,7 +3071,7 @@ sys.exit(0 if ok else 3)" "$lib" "$pj" 2>/dev/null || rc=$?
3071
3071
  # Provenance: the deploy gate's own verdict (Ed25519 attestation against the local
3072
3072
  # key plus LOKI_RECEIPT_RETIRED_PUBKEYS; unknown kid or no key is UNCHECKED).
3073
3073
  # Defined in autonomy/loki, so it is absent when verify.sh runs standalone.
3074
- declare -f _deploy_receipt_verdict >/dev/null 2>&1 || return 0
3074
+ declare -f _deploy_receipt_verdict >/dev/null 2>&1 || { echo "attestation: UNCHECKED (run via loki verify)"; return 0; }
3075
3075
  local att
3076
3076
  att="$(_deploy_receipt_verdict "$pj")"
3077
3077
  # D47: UNSIGNED is never a pass; --allow-unsigned / LOKI_VERIFY_ALLOW_UNSIGNED=1 accepts it, said aloud.
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "10.5.19"
10
+ __version__ = "10.5.20"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -2,7 +2,7 @@
2
2
 
3
3
  The flagship product of [Autonomi](https://www.autonomi.dev/). Loki Mode is a spec-driven autonomous builder with a built-in trust layer that takes any spec to a deployed product and verifies completion with evidence (quality gates plus a completion council), not just a "done" claim. Complete installation instructions for all platforms and use cases.
4
4
 
5
- **Version:** v10.5.19
5
+ **Version:** v10.5.20
6
6
 
7
7
  ---
8
8
 
package/docs/v10/BOARD.md CHANGED
@@ -629,7 +629,7 @@ Source: ~/git/autonomi-dev/research/2026-09-30-adoption/SWARM-PROMPT-ADOPTION.md
629
629
  | E-159 | Pre-existing secret-scan gaps found by the E-157 r2 opus reviewer: (a) an evil merge, a merge commit whose OWN content adds a secret (merge -s ours --no-commit, token in the merge commit), is invisible to both the PARENT..SHA range scan and the --all scan (only `gitleaks dir` found it); (b) pinned gitleaks 8.30.0 exits 0 when its internal git log fails (invalid range), a latent fail-open. Fix: --diff-merges=first-parent (or -m) in --log-opts for both modes or a working-tree scan at the release SHA; guard `git rev-list RANGE` success or treat `[git] fatal` as failure | scripts/security-audit-gitleaks.sh, workflows, tests | HIGH | evil-merge and bad-range fixtures fail the scan | merged@2026-10-01T03:03Z | CI-health engineer after E-157 r3; r1 opus REJECT 5f33451d: stdin merge scan false-positives on real history (v10.5.13..14 rc 1), Wall checks skip in CI |
630
630
  | E-160 | D46 runner contention (peer steer 02:11Z): a green train SHA fast-forwarded to main re-runs Tests (8 shards), Bun Parity, Security Audit and First-run gate on the identical SHA, doubling runner load and queueing the next train. Proposal: on push to main, a first job checks for a successful run of the same workflow at the same SHA from a train/** push and, if found, exits success recording the reused run id (D28: same SHA = same tree); any SHA not train-tested runs in full. CTO call FIRST: OPERATING-MODEL says "Tier B full verification on every main commit (never cancelled on main)"; confirm reuse does not weaken Release required-ci, branch-conditional steps (train vs main), or the Security Audit range (base tag config). Sequence after E-157 r4 (same files) | .github/workflows/test.yml, bun-parity.yml, security-audit.yml, tests/test_release_required_ci.py | HIGH | main push of a train-green SHA records reuse and finishes in under 1 min; an untested SHA runs in full; a train-red SHA is not reused | ready@2026-10-01T02:10Z | CTO decision first; after E-157 |
631
631
  | E-161 | INCIDENT 02:46Z: an opus reviewer ran `git checkout --detach <tag>` x7 plus a `.gitleaksignore` overwrite in the SHARED main checkout (reflog 02:46:04Z to 02:46:38Z). Cause: its run-owned clone dir was deleted, the next `cd` into a new clone failed, and the shell cwd fell back to the main checkout; every later command ran there. Restored by the Chief of Staff (`git checkout main`, fafe50dd, clean). Guard: v10-guard.sh (PreToolUse) blocks `git checkout`/`git switch`/`git reset`/`git worktree remove` and writes to tracked files when cwd resolves to the main checkout and the caller is an agent (not the leader session); agent prompts use `cd DIR` followed by an exit-on-failure check. Test: a hook test with cwd=main checkout blocks a detached checkout and allows it in a worktree | scripts/v10-guard.sh, tests | HIGH | detached checkout in main checkout blocked; same in a worktree allowed | ready@2026-10-01T02:47Z | GUARDS.md entry |
632
- | E-162 | Founder "faster" (03:05Z): slice CI runs only Tier A plus diff-selected suites (the existing Tier A selection), Bun Parity and the structural guards; the full 8-shard Tests stays on train/** and main, and the train stays the release verdict. Frees runners and targets about 2 min slice CI | .github/workflows/test.yml (slice-* job matrix only), tests | HIGH | slice-* push runs no 8-shard matrix; train/** and main still run all 8 shards; a slice touching a suite runs that suite | ready@2026-10-01T03:01Z | after E-157 r4 (same file) |
632
+ | E-162 | Founder "faster" (03:05Z): slice CI runs only Tier A plus diff-selected suites (the existing Tier A selection), Bun Parity and the structural guards; the full 8-shard Tests stays on train/** and main, and the train stays the release verdict. Frees runners and targets about 2 min slice CI | .github/workflows/test.yml (slice-* job matrix only), tests | HIGH | slice-* push runs no 8-shard matrix; train/** and main still run all 8 shards; a slice touching a suite runs that suite | merged@2026-10-01T05:22Z | after E-157 r4 (same file) |
633
633
  | E-165 | tests/test-mirofish-integration.sh line 413 runs `autonomy/loki start --no-mirofish` in the repo root: a live autonomous build that ran about 45 min, switched a worktree branch to loki/session-* and committed a docs change (found by DOC-02). Guard: the test must run against a run-owned fixture repo with a stub provider and LOKI_NO_BROWSER=1, never the repo root; add a structural guard that no test launches start/run against REPO_ROOT | tests/test-mirofish-integration.sh, a structural guard | HIGH | the test never runs loki start in the repo root; guard catches a planted case | ready@2026-10-01T04:07Z | P0 guard (D26) |
634
634
  | E-166 | Jira auto-sync never starts: src/integrations/sync-subscriber.js builds JiraApiClient without the required email and apiToken, so LOKI_JIRA_URL plus LOKI_JIRA_TOKEN do nothing (DOC-02 added a known-issue note to the setup docs). Fix the wiring or remove the advertised auto-sync | src/integrations/sync-subscriber.js, tests | MEDIUM | with env set, the subscriber constructs a working client (mocked API) | ready@2026-10-01T04:07Z | none |
635
635
  | D49-auto | Auto-promote to latest on Post-Release Smoke success (founder D49) | .github/workflows/promote.yml, tests/test_release_next_tag.py | HIGH | smoke-success from Release promotes; manual smoke never promotes; not-lower guard | merged@2026-10-01T03:03Z | opus APPROVE 5510b8c8. Follow-ups (D49-auto-b): not-lower guard fails OPEN on an npm error (make it fail closed); loki-mode-sdk latest has no not-lower guard; a newer queued promote can replace a pending one in a release burst |
@@ -642,20 +642,20 @@ Source: ~/git/autonomi-dev/research/2026-09-30-adoption/SWARM-PROMPT-ADOPTION.md
642
642
  | A-115 | TIER 0 (steer 22:50Z). FALSE VERIFIED ON MAIN (A-112 opus reviewer, c10 on 275b4fc0): a conftest.py that skips the target test (and the unrelated red one) seals VERIFIED rc=0, "2 passed, 2 skipped", nothing disclosed. Seal accuracy: a relevant check with more skipped tests than base, or a diff touching conftest.py / pytest.ini / pyproject [tool.pytest] / jest or node test config, must not count as a pass or as progress; list it in NOT PROVEN | loki-ts/src/engine10/stages/verify.ts, failures.ts, tests | HIGH | c10 and e9 fixtures seal FAILED or NOT VERIFIED | released@2026-10-01T00:52Z | core at the 5000 cap: needs an offset (A-150) Released in v10.5.13 (merge bdb332e3 is an ancestor of v10.5.13). |
643
643
  | A-115b | A-115 opus notes: (1) an honest fix that also appends a new test to a relevant test file, in a repo with an unrelated red test, ends STALLED/FAILED instead of PARTIAL: the edited file is excluded from progress so the unrelated red is never subtracted; allow progress when the file's pre-existing target ids went red to green; (2) the node base-count fallback sums every `pass N`/`fail N` line, so a base test printing them inflates the count (safe-direction false PARTIAL); take the last pass and last fail lines | loki-ts/src/engine10/stages/verify.ts, verify_weak.test.ts | HIGH | both fixtures | released@2026-10-01T01:53Z | Released in v10.5.15 (merge 945f58ec is an ancestor of v10.5.15). |
644
644
  | A-119 | P0 FALSE VERIFIED ON MAIN (A-115b opus reviewer, reproduced on bba2e5ec): rename the target test file and weaken its expectation (sum.test.js => sum.spec.test.js with 6 changed to 5), add a comment to sum.js: rc=0 Outcome VERIFIED, receipt shows node:sum.spec.test.js pass, sum.js still buggy. verify only sees relevant test files that still exist on head; seal writes `weakened test: sum.test.js` (seal.ts:205) but that line never downgrades the verdict. Fix: seal's `weakened test:` downgrades to PARTIAL like verify's not_proven | loki-ts/src/engine10/stages/seal.ts, tests | HIGH | rename-and-weaken fixture: not VERIFIED, rc!=0 | released@2026-10-01T01:53Z | Tier 0 Released in v10.5.15 (merge c41a2b83 is an ancestor of v10.5.15). |
645
- | A-119b | A-119 opus review (REJECT on pre-existing holes, A-119 landed as a strict improvement): weakening still ends VERIFIED via (1) a helper file a base test imports (eq=()=>{}), (2) snapshot or fixture edits (__snapshots__/*.snap, tests/fixtures/*.json), (3) tests isTestFile (testmap.ts:51) does not recognise: __tests__/*.js, mocha test/*.js, cargo tests/*.rs, including rename to .bak. Also: verdictOf returns ALREADY_SATISFIED before the weakened downgrade when implement says already_done; package.json jest testPathIgnorePatterns and vite.config.ts test.exclude skip config detection. Fix: widen the seal.ts weakTests predicate to any changed/deleted base path under test/, tests/, __tests__/, __snapshots__/, fixtures dirs plus non-test files a base test imports; check weakened before the already_done early return; add vite.config and in-block jest keys to CFG detection | loki-ts/src/engine10/stages/seal.ts, verify.ts (CFG only), tests | HIGH | each repro gives not-VERIFIED; source-only fix and new test stay VERIFIED | building@2026-10-01T02:18Z | |
645
+ | A-119b | A-119 opus review (REJECT on pre-existing holes, A-119 landed as a strict improvement): weakening still ends VERIFIED via (1) a helper file a base test imports (eq=()=>{}), (2) snapshot or fixture edits (__snapshots__/*.snap, tests/fixtures/*.json), (3) tests isTestFile (testmap.ts:51) does not recognise: __tests__/*.js, mocha test/*.js, cargo tests/*.rs, including rename to .bak. Also: verdictOf returns ALREADY_SATISFIED before the weakened downgrade when implement says already_done; package.json jest testPathIgnorePatterns and vite.config.ts test.exclude skip config detection. Fix: widen the seal.ts weakTests predicate to any changed/deleted base path under test/, tests/, __tests__/, __snapshots__/, fixtures dirs plus non-test files a base test imports; check weakened before the already_done early return; add vite.config and in-block jest keys to CFG detection | loki-ts/src/engine10/stages/seal.ts, verify.ts (CFG only), tests | HIGH | each repro gives not-VERIFIED; source-only fix and new test stay VERIFIED | rejected@2026-10-01T05:12Z | |
646
646
  | A-117 | FALSE VERIFIED IN `loki verify` (A-130 r2 opus reviewer): on a run whose events.jsonl was tampered (append, edit, truncate, delete), the run now ends FAILED (A-130) but the receipt on disk still says VERIFIED with no tamper mark, because the worker sealed it before the supervisor detected the tamper; `loki verify` prints verdict: VERIFIED rc=0. Fix: record the tamper on the receipt via the registered receipt.addendum event (hash-chained) or have verify check the event log hash; verify must say TAMPERED and exit non-zero | loki-ts/src/engine10/verify_cmd.ts, supervisor.ts or seal.ts, tests | HIGH | tampered-log fixture: loki verify TAMPERED rc!=0 | merged@2026-10-01T02:50Z | after A-130 (supervisor.ts); r2: opus REJECT, tail truncation erases post-seal tamper, fix = signed final log line |
647
- | A-118 | Exit-honest policy gap on the DEFAULT path (A-115 r2 finding): legacy `loki quick` prints `Evidence Receipt: NOT VERIFIED` yet exits rc 0 on a run whose target test was skipped; G1 exit-honest counts a skipped test as green, so it does not catch this. CTO call: should legacy quick exit non-zero on NOT VERIFIED when a relevant test was skipped/weakened, and should G1 count skipped as not-green? | autonomy/run.sh (quick exit path), scripts/first-run-gate.sh G1 | HIGH | skipped-target legacy run exits non-zero; G1 treats skipped as not green | building@2026-10-01T02:15Z | D47 decided: rc 3 on tests_integrity failed (skip added, runner config changed, test file deleted/renamed); assertion edits disclosed rc 0; G1 green needs pass 2 fail 0, 9b asserts rc 3. Files: proof-generator.py, run.sh after generate_proof_of_run, first-run-gate.sh, docs/exit-codes.md. Blocks promote of `latest`; built df404970, opus review |
647
+ | A-118 | Exit-honest policy gap on the DEFAULT path (A-115 r2 finding): legacy `loki quick` prints `Evidence Receipt: NOT VERIFIED` yet exits rc 0 on a run whose target test was skipped; G1 exit-honest counts a skipped test as green, so it does not catch this. CTO call: should legacy quick exit non-zero on NOT VERIFIED when a relevant test was skipped/weakened, and should G1 count skipped as not-green? | autonomy/run.sh (quick exit path), scripts/first-run-gate.sh G1 | HIGH | skipped-target legacy run exits non-zero; G1 treats skipped as not green | merged@2026-10-01T05:12Z | D47 decided: rc 3 on tests_integrity failed (skip added, runner config changed, test file deleted/renamed); assertion edits disclosed rc 0; G1 green needs pass 2 fail 0, 9b asserts rc 3. Files: proof-generator.py, run.sh after generate_proof_of_run, first-run-gate.sh, docs/exit-codes.md. Blocks promote of `latest`; built df404970, opus review |
648
648
  | A-112b | A-112 readability debt: subtractBase in verify.ts was folded to reach 4999 of 5000 core lines (9 lines over 200 chars, longest 347; un/progress/base-run loop each on one line). Unfold when A-150 frees budget; no behaviour change | loki-ts/src/engine10/stages/verify.ts | MEDIUM | budget test plus verify_prered unchanged | ready@2026-09-30T22:37Z | after A-150 |
649
649
  | A-113b | A-110 opus notes on A-113: (1) under the CLI invoker (LOKI_E10_INVOKER=cli) the provider child stderr never reaches the fatal classifier (the *-impl.stderr.log is empty), so a credit/auth failure printed on plain stderr gives stop:null and burns the fix rounds; (2) machine.ts re-records the previous signature when a verify crashes, so a crashed verify counts toward a stall. Fix both in session.ts/machine.ts, with end-to-end tests through the real worker | loki-ts/src/engine10/session.ts, machine.ts, tests | HIGH | CLI stderr credit line stops fatal; crashed verify does not count as a stall repeat | released@2026-10-01T01:19Z | keep the A-110 escalated emit; the A-110 reviewer plugin probe is a good e2e template Released in v10.5.14 (merge 0377398d is an ancestor of v10.5.14). |
650
650
  | A-121 | v10 signs and verifies natively (item 3) | see plan A-121 | HIGH | first-run-gate assertion per plan card | released@2026-10-01T00:52Z | Wave per plan section 5; one writer per file. Released in v10.5.13 (merge 08b31271 is an ancestor of v10.5.13). |
651
651
  | A-122 | Delete the GPG signing layer (item 3, deletion) | see plan A-122 | HIGH | first-run-gate assertion per plan card | released@2026-10-01T00:52Z | Wave per plan section 5; one writer per file. Released in v10.5.13 (merge cb738c36 is an ancestor of v10.5.13). |
652
- | A-121b | A-121 opus note: a receipt downgrade exits 0. Anyone can edit the body, recompute receipt_sha256 and null the jwt to get UNSIGNED rc 0 on `loki verify`, and the legacy deploy gate refuses UNSIGNED but the v10 verify does not. Decide the signed-by-default policy: once a local key exists, UNSIGNED on a receipt from this machine exits non-zero (or the receipt records its kid outside the hashed body) | loki-ts/src/engine10/verify_cmd.ts, stages/seal.ts, tests | HIGH | downgrade fixture exits non-zero | building@2026-10-01T02:33Z | D47 decided: UNSIGNED exits 3 on both engines (verify_cmd.ts EXIT_BY_VERDICT, autonomy/verify.sh _verify_receipt_digest), --allow-unsigned / LOKI_VERIFY_ALLOW_UNSIGNED=1 accepts with explicit line; update tests/test-engine10-live-pr.sh 115-122; verify never creates a key |
652
+ | A-121b | A-121 opus note: a receipt downgrade exits 0. Anyone can edit the body, recompute receipt_sha256 and null the jwt to get UNSIGNED rc 0 on `loki verify`, and the legacy deploy gate refuses UNSIGNED but the v10 verify does not. Decide the signed-by-default policy: once a local key exists, UNSIGNED on a receipt from this machine exits non-zero (or the receipt records its kid outside the hashed body) | loki-ts/src/engine10/verify_cmd.ts, stages/seal.ts, tests | HIGH | downgrade fixture exits non-zero | released@2026-10-01T03:00Z | D47 decided: UNSIGNED exits 3 on both engines (verify_cmd.ts EXIT_BY_VERDICT, autonomy/verify.sh _verify_receipt_digest), --allow-unsigned / LOKI_VERIFY_ALLOW_UNSIGNED=1 accepts with explicit line; update tests/test-engine10-live-pr.sh 115-122; verify never creates a key |
653
653
  | A-121c | A-121b opus finding B: legacy `loki verify` passes a WELL-FORMED token with an unknown kid at rc 0 (`attestation: UNCHECKED`, `VERDICT: VERIFIED`) with or without the local key; engine10 gives rc 2. A forger can always mint such a token, so on legacy a downgrade-to-foreign-kid is a pass. D47 kept legacy UNCHECKED unchanged because it also covers honest cross-machine verification. CTO call: make legacy UNCHECKED non-zero (parity with engine10 rc 2), now that D48 row 2 adds `loki verify --pubkey` as the honest cross-machine path? Also: a missing .loki/state/last-proof-id.txt makes legacy verify skip the receipt check entirely and pass (pre-existing, A-134) | autonomy/loki (_deploy_receipt_verdict, verify), tests | HIGH | unknown-kid forged token exits non-zero on legacy; honest cross-machine path documented | ready@2026-10-01T02:33Z | CTO decision first; after A-121b |
654
654
  | A-110 | One named outcome, fixed exit ladder, --json (items 1 and 5) | see plan A-110 | HIGH | first-run-gate assertion per plan card | released@2026-10-01T00:52Z | Wave per plan section 5; one writer per file. Released in v10.5.13 (merge 47ac1ccc is an ancestor of v10.5.13). |
655
655
  | A-112 | Baseline subtract: judge only the delta (item 5) | see plan A-112 | HIGH | first-run-gate assertion per plan card | released@2026-10-01T00:52Z | Wave per plan section 5; one writer per file. Released in v10.5.13 (merge 69f1a910 is an ancestor of v10.5.13). |
656
656
  | A-123 | Doctor: only the selected provider blocks, one Ready line (item 3) | see plan A-123 | MEDIUM | first-run-gate assertion per plan card | released@2026-10-01T00:52Z | Wave per plan section 5; one writer per file. Released in v10.5.13 (merge 275b4fc0 is an ancestor of v10.5.13). |
657
657
  | A-134 | Legacy: receipt after the final commit, chatter behind --verbose (item 2) | see plan A-134 | MEDIUM | first-run-gate assertion per plan card | released@2026-10-01T00:52Z | Wave per plan section 5; one writer per file. Released in v10.5.13 (merge 7d3edf96 is an ancestor of v10.5.13). |
658
- | A-134b | A-134 opus notes: (1) standalone autonomy/verify.sh prints no attestation line (only `loki verify` has _deploy_receipt_verdict); print `attestation: UNCHECKED (run via loki verify)` instead of silence; (2) the quiet failure tail grep `[Ff]ailed` matched the RALPH system-prompt line and printed ~1.5k chars; anchor to `^\[(ERROR|WARN)\]` or cap line length; (3) the quiet inner run starts as a background job so its stdin is /dev/null even from a TTY: pause-mode keypress resume changes for quiet runs; (4) `loki quick --verbose` is also the A-122 cmd_quick flag, done | autonomy/verify.sh, autonomy/run.sh | MEDIUM | each note has a test | building@2026-10-01T02:24Z | |
658
+ | A-134b | A-134 opus notes: (1) standalone autonomy/verify.sh prints no attestation line (only `loki verify` has _deploy_receipt_verdict); print `attestation: UNCHECKED (run via loki verify)` instead of silence; (2) the quiet failure tail grep `[Ff]ailed` matched the RALPH system-prompt line and printed ~1.5k chars; anchor to `^\[(ERROR|WARN)\]` or cap line length; (3) the quiet inner run starts as a background job so its stdin is /dev/null even from a TTY: pause-mode keypress resume changes for quiet runs; (4) `loki quick --verbose` is also the A-122 cmd_quick flag, done | autonomy/verify.sh, autonomy/run.sh | MEDIUM | each note has a test | merged@2026-10-01T05:22Z | |
659
659
  | A-134c | A-134b r1 review finding: provider call sites in autonomy/run.sh (mainline claude -p at about 25455/25460, provider_invoke_argv about 1050/1053) do not redirect stdin, so under LOKI_VERBOSE=1 (and any non-quiet path) a parent stdin pipe that never closes blocks `claude -p` reading stdin (pre-existing). Fix: `< /dev/null` at provider invocations that pass the prompt as an argument | autonomy/run.sh (provider call sites only), providers/*.sh, tests | MEDIUM | never-closing stdin pipe: verbose `loki quick` completes under timeout 60 | ready@2026-10-01T01:37Z | |
660
660
  | A-130 | v10 quiet by default (item 2) | see plan A-130 | MEDIUM | first-run-gate assertion per plan card | released@2026-10-01T01:19Z | Wave per plan section 5; one writer per file. Released in v10.5.14 (merge a518bfea is an ancestor of v10.5.14). |
661
661
  | A-130b | A-130 Reason line prints first_error from a failing check verbatim (capped at 200 chars, control chars stripped) but unredacted: a `ghp_` token in a test failure line reaches the terminal. No TS redactor is reachable from engine10 core (only autonomy/lib/proof_redact.py). Port the token patterns to a small TS helper outside core or redact first_error where it is captured in verify | loki-ts/src (util), verify.ts or output.ts, tests | MEDIUM | ghp_/sk- token in first_error prints redacted | released@2026-10-01T02:27Z | ; sonnet APPROVE be50510f (redaction before cap, parity with proof_redact.py) Released in v10.5.16 (merge f214a0fa is an ancestor of v10.5.16). |
@@ -1740,3 +1740,10 @@ The swarm is stopped: .loki/V10-STOP exists, the loop has no wake-ups, and the c
1740
1740
  - Fix forward (main already contains it): slice-P0-codeql (constant allowlists for the provider binary and secret file names) in progress; then train with it, then re-cut the release.
1741
1741
  - train/31 731a335d is green on Tests/Parity/Coverage but its Security Audit fails on the same alert; it will not release until the fix lands.
1742
1742
  - D48-flip rejected by opus (bare loki verify still legacy after a default v10 run: FAILED run reads VERIFIED); r2 in progress.
1743
+
1744
+ ## 2026-10-01T05:22Z v10.5.19 cut (CodeQL fix forward), train/33 pushed
1745
+ - train/32 aad61f9a green: Tests, Bun Parity, Coverage (baseline), Security Audit all completed success (watcher bs3ybh02p). main fast-forwarded to aad61f9a.
1746
+ - v10.5.19 release commit 47050d65 pushed by SHA (parent == origin/main; --check-clean rc=0). It carries the unpublished 10.5.18 content plus the CodeQL 604-607 fix, A-118 r5 and DOC-01. Release run and auto-promote watcher: bqimqxkgo.
1747
+ - Merged on local main: D48-flip r3 (opus APPROVE: FAILED receipt exits 4 with or without --allow-unsigned; dispatch 56/0; gate --stub 0 failed), A-134b r4 (sonnet APPROVE; registration rc=0, shard rc=0, own test 6/0), E-162 (opus APPROVE as CTO call).
1748
+ - train/33 63db8710 pushed. Guards: registration rc=0, shard-coverage rc=0 (E2e Features row 19 -> 20 to keep the five heaviest suites in distinct shards), v10-ops rc=0, run-shellcheck rc=0, docs-cli-drift rc=0, release-dist-guard rc=0, budget.test 24 pass.
1749
+ - REJECTED, fix rounds building: E-163 (live /usage timeout has no process-group kill), D48-r2 (unsigned receipt exits 0 under --pubkey; merge conflicts with the exit-4 change).
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- var rs=Object.create;var{getPrototypeOf:ts,defineProperty:pG,getOwnPropertyNames:es}=Object;var $r=Object.prototype.hasOwnProperty;function Zr($){return this[$]}var Qr,Xr,Jr=($,Z,Q)=>{var X=$!=null&&typeof $==="object";if(X){var J=Z?Qr??=new WeakMap:Xr??=new WeakMap,K=J.get($);if(K)return K}Q=$!=null?rs(ts($)):{};let Y=Z||!$||!$.__esModule?pG(Q,"default",{value:$,enumerable:!0}):Q;for(let z of es($))if(!$r.call(Y,z))pG(Y,z,{get:Zr.bind($,z),enumerable:!0});if(X)J.set($,Y);return Y};var MK=($,Z)=>()=>(Z||$((Z={exports:{}}).exports,Z),Z.exports);var Kr=($)=>$;function Yr($,Z){this[$]=Kr.bind(null,Z)}var w0=($,Z)=>{for(var Q in Z)pG($,Q,{get:Z[Q],enumerable:!0,configurable:!0,set:Yr.bind(Z,Q)})};var v=($,Z)=>()=>($&&(Z=$($=0)),Z);var E4=import.meta.require;var uT={};w0(uT,{lokiDir:()=>T0,homeLokiDir:()=>h7,findRepoRootForVersion:()=>cG,REPO_ROOT:()=>i0});import{resolve as k4,dirname as dG}from"path";import{fileURLToPath as zr}from"url";import{existsSync as jK}from"fs";import{homedir as Vr}from"os";function Wr(){let $=mT;for(let Z=0;Z<6;Z++){if(jK(k4($,"VERSION"))&&jK(k4($,"autonomy/run.sh")))return $;let Q=dG($);if(Q===$)break;$=Q}return k4(mT,"..","..","..")}function cG($){let Z=$;for(let Q=0;Q<6;Q++){if(jK(k4(Z,"VERSION"))&&jK(k4(Z,"autonomy/run.sh")))return Z;let X=dG(Z);if(X===Z)break;Z=X}return k4($,"..","..","..")}function T0(){return process.env.LOKI_DIR??k4(process.cwd(),".loki")}function h7(){return k4(Vr(),".loki")}var mT,i0;var J8=v(()=>{mT=dG(zr(import.meta.url));i0=Wr()});import{readFileSync as qr}from"fs";import{resolve as Gr,dirname as Hr}from"path";import{fileURLToPath as Br}from"url";function x4(){if(g7!==null)return g7;let $="10.5.19";if(typeof $==="string"&&$.length>0)return g7=$,g7;try{let Z=Hr(Br(import.meta.url)),Q=cG(Z);g7=qr(Gr(Q,"VERSION"),"utf-8").trim()}catch{g7="unknown"}return g7}var g7=null;var h$=v(()=>{J8()});var oT={};w0(oT,{runOrThrow:()=>Er,run:()=>D0,readStreamCapped:()=>LK,commandVersion:()=>xr,commandExists:()=>O9,ShellError:()=>iG,MAX_STDOUT_BYTES:()=>aT});async function LK($,Z=aT){let Q=$.getReader(),X=new TextDecoder,J="",K=0;try{while(K<Z){let{done:Y,value:z}=await Q.read();if(Y)break;if(!z)continue;if(K+=z.byteLength,K>Z){let V=z.byteLength-(K-Z);J+=X.decode(z.subarray(0,V),{stream:!0});break}J+=X.decode(z,{stream:!0})}J+=X.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return J}async function D0($,Z={}){let Q=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:Z.env?{...process.env,...Z.env}:process.env,cwd:Z.cwd}),X,J;if(Z.timeoutMs&&Z.timeoutMs>0)X=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}J=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},Z.timeoutMs);try{let[K,Y,z]=await Promise.all([LK(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:K,stderr:Y,exitCode:z}}finally{if(X)clearTimeout(X);if(J)clearTimeout(J)}}async function Er($,Z={}){let Q=await D0($,Z);if(Q.exitCode!==0)throw new iG(`command failed (${Q.exitCode}): ${$.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function O9($){let Z=kr($),Q=await D0(["sh","-c",`command -v ${Z}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function kr($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function xr($,Z="--version"){if(!await O9($))return null;let X=await D0([$,Z],{timeoutMs:5000});if(X.exitCode!==0)return null;return((X.stdout||X.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var aT=16777216,iG;var J9=v(()=>{iG=class iG extends Error{message;exitCode;stdout;stderr;constructor($,Z,Q,X){super($);this.message=$;this.exitCode=Z;this.stdout=Q;this.stderr=X;this.name="ShellError"}}});function S4($){return Sr?"":$}var Sr,k0,P8,p0,a$8,K8,L8,K9,c;var o5=v(()=>{Sr=(process.env.NO_COLOR??"").length>0;k0=S4("\x1B[0;31m"),P8=S4("\x1B[0;32m"),p0=S4("\x1B[1;33m"),a$8=S4("\x1B[0;34m"),K8=S4("\x1B[0;36m"),L8=S4("\x1B[1m"),K9=S4("\x1B[2m"),c=S4("\x1B[0m")});import{accessSync as pr,constants as dr,existsSync as cr,statSync as lr}from"fs";async function n5(){if(g$!==void 0)return g$;let $="/opt/homebrew/bin/python3.12";if(cr($))return g$=$,$;let Z=await O9("python3.12");if(Z)return g$=Z,Z;let Q=await O9("python3");return g$=Q,Q}async function T6($,Z={}){let Q=await n5();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return D0([Q,"-c",$],Z)}async function rT(){let $=(process.env.PATH??"").split(":").filter((Z)=>Z.startsWith("/"));for(let Z of[...ar,...$.map((Q)=>`${Q}/python3`)])try{if(!lr(Z).isFile())continue;if(pr(Z,dr.X_OK),(await D0([Z,"-I","-S","-c",""],{timeoutMs:1e4})).exitCode===0)return Z}catch{}return null}var g$,ir,ar;var D6=v(()=>{J9();ir=["/usr/bin/python3","/bin/python3"],ar=ir});var OD={};w0(OD,{runStatus:()=>jt});import{existsSync as Y9,readFileSync as z2,readdirSync as zD,statSync as VD}from"fs";import{resolve as u8,basename as Wt}from"path";import{homedir as qt}from"os";function WD($){let Z=Math.trunc($);if(Z>=1e6)return`${(Math.trunc(Z/1e6*10)/10).toFixed(1)}M`;if(Z>=1000)return`${(Math.trunc(Z/1000*10)/10).toFixed(1)}K`;return String(Z)}function qD($,Z,Q){if(Z===0)return null;let X=Math.trunc($*100/Z),J=Math.trunc($*CK/Z);if(J>CK)J=CK;let K=CK-J,Y=P8;if(X>=80)Y=k0;else if(X>=50)Y=p0;let z="=".repeat(Math.max(0,J))+" ".repeat(Math.max(0,K)),V=WD($),W=WD(Z);return` ${L8}${Q}${c} ${Y}[${z}]${c} ${X}% (${V} / ${W})`}async function Ht(){if(await O9("jq"))return!0;return process.stdout.write(`${k0}Error: jq is required but not installed.${c}
2
+ var rs=Object.create;var{getPrototypeOf:ts,defineProperty:pG,getOwnPropertyNames:es}=Object;var $r=Object.prototype.hasOwnProperty;function Zr($){return this[$]}var Qr,Xr,Jr=($,Z,Q)=>{var X=$!=null&&typeof $==="object";if(X){var J=Z?Qr??=new WeakMap:Xr??=new WeakMap,K=J.get($);if(K)return K}Q=$!=null?rs(ts($)):{};let Y=Z||!$||!$.__esModule?pG(Q,"default",{value:$,enumerable:!0}):Q;for(let z of es($))if(!$r.call(Y,z))pG(Y,z,{get:Zr.bind($,z),enumerable:!0});if(X)J.set($,Y);return Y};var MK=($,Z)=>()=>(Z||$((Z={exports:{}}).exports,Z),Z.exports);var Kr=($)=>$;function Yr($,Z){this[$]=Kr.bind(null,Z)}var w0=($,Z)=>{for(var Q in Z)pG($,Q,{get:Z[Q],enumerable:!0,configurable:!0,set:Yr.bind(Z,Q)})};var v=($,Z)=>()=>($&&(Z=$($=0)),Z);var E4=import.meta.require;var uT={};w0(uT,{lokiDir:()=>T0,homeLokiDir:()=>h7,findRepoRootForVersion:()=>cG,REPO_ROOT:()=>i0});import{resolve as k4,dirname as dG}from"path";import{fileURLToPath as zr}from"url";import{existsSync as jK}from"fs";import{homedir as Vr}from"os";function Wr(){let $=mT;for(let Z=0;Z<6;Z++){if(jK(k4($,"VERSION"))&&jK(k4($,"autonomy/run.sh")))return $;let Q=dG($);if(Q===$)break;$=Q}return k4(mT,"..","..","..")}function cG($){let Z=$;for(let Q=0;Q<6;Q++){if(jK(k4(Z,"VERSION"))&&jK(k4(Z,"autonomy/run.sh")))return Z;let X=dG(Z);if(X===Z)break;Z=X}return k4($,"..","..","..")}function T0(){return process.env.LOKI_DIR??k4(process.cwd(),".loki")}function h7(){return k4(Vr(),".loki")}var mT,i0;var J8=v(()=>{mT=dG(zr(import.meta.url));i0=Wr()});import{readFileSync as qr}from"fs";import{resolve as Gr,dirname as Hr}from"path";import{fileURLToPath as Br}from"url";function x4(){if(g7!==null)return g7;let $="10.5.20";if(typeof $==="string"&&$.length>0)return g7=$,g7;try{let Z=Hr(Br(import.meta.url)),Q=cG(Z);g7=qr(Gr(Q,"VERSION"),"utf-8").trim()}catch{g7="unknown"}return g7}var g7=null;var h$=v(()=>{J8()});var oT={};w0(oT,{runOrThrow:()=>Er,run:()=>D0,readStreamCapped:()=>LK,commandVersion:()=>xr,commandExists:()=>O9,ShellError:()=>iG,MAX_STDOUT_BYTES:()=>aT});async function LK($,Z=aT){let Q=$.getReader(),X=new TextDecoder,J="",K=0;try{while(K<Z){let{done:Y,value:z}=await Q.read();if(Y)break;if(!z)continue;if(K+=z.byteLength,K>Z){let V=z.byteLength-(K-Z);J+=X.decode(z.subarray(0,V),{stream:!0});break}J+=X.decode(z,{stream:!0})}J+=X.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return J}async function D0($,Z={}){let Q=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:Z.env?{...process.env,...Z.env}:process.env,cwd:Z.cwd}),X,J;if(Z.timeoutMs&&Z.timeoutMs>0)X=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}J=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},Z.timeoutMs);try{let[K,Y,z]=await Promise.all([LK(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:K,stderr:Y,exitCode:z}}finally{if(X)clearTimeout(X);if(J)clearTimeout(J)}}async function Er($,Z={}){let Q=await D0($,Z);if(Q.exitCode!==0)throw new iG(`command failed (${Q.exitCode}): ${$.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function O9($){let Z=kr($),Q=await D0(["sh","-c",`command -v ${Z}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function kr($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function xr($,Z="--version"){if(!await O9($))return null;let X=await D0([$,Z],{timeoutMs:5000});if(X.exitCode!==0)return null;return((X.stdout||X.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var aT=16777216,iG;var J9=v(()=>{iG=class iG extends Error{message;exitCode;stdout;stderr;constructor($,Z,Q,X){super($);this.message=$;this.exitCode=Z;this.stdout=Q;this.stderr=X;this.name="ShellError"}}});function S4($){return Sr?"":$}var Sr,k0,P8,p0,a$8,K8,L8,K9,c;var o5=v(()=>{Sr=(process.env.NO_COLOR??"").length>0;k0=S4("\x1B[0;31m"),P8=S4("\x1B[0;32m"),p0=S4("\x1B[1;33m"),a$8=S4("\x1B[0;34m"),K8=S4("\x1B[0;36m"),L8=S4("\x1B[1m"),K9=S4("\x1B[2m"),c=S4("\x1B[0m")});import{accessSync as pr,constants as dr,existsSync as cr,statSync as lr}from"fs";async function n5(){if(g$!==void 0)return g$;let $="/opt/homebrew/bin/python3.12";if(cr($))return g$=$,$;let Z=await O9("python3.12");if(Z)return g$=Z,Z;let Q=await O9("python3");return g$=Q,Q}async function T6($,Z={}){let Q=await n5();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return D0([Q,"-c",$],Z)}async function rT(){let $=(process.env.PATH??"").split(":").filter((Z)=>Z.startsWith("/"));for(let Z of[...ar,...$.map((Q)=>`${Q}/python3`)])try{if(!lr(Z).isFile())continue;if(pr(Z,dr.X_OK),(await D0([Z,"-I","-S","-c",""],{timeoutMs:1e4})).exitCode===0)return Z}catch{}return null}var g$,ir,ar;var D6=v(()=>{J9();ir=["/usr/bin/python3","/bin/python3"],ar=ir});var OD={};w0(OD,{runStatus:()=>jt});import{existsSync as Y9,readFileSync as z2,readdirSync as zD,statSync as VD}from"fs";import{resolve as u8,basename as Wt}from"path";import{homedir as qt}from"os";function WD($){let Z=Math.trunc($);if(Z>=1e6)return`${(Math.trunc(Z/1e6*10)/10).toFixed(1)}M`;if(Z>=1000)return`${(Math.trunc(Z/1000*10)/10).toFixed(1)}K`;return String(Z)}function qD($,Z,Q){if(Z===0)return null;let X=Math.trunc($*100/Z),J=Math.trunc($*CK/Z);if(J>CK)J=CK;let K=CK-J,Y=P8;if(X>=80)Y=k0;else if(X>=50)Y=p0;let z="=".repeat(Math.max(0,J))+" ".repeat(Math.max(0,K)),V=WD($),W=WD(Z);return` ${L8}${Q}${c} ${Y}[${z}]${c} ${X}% (${V} / ${W})`}async function Ht(){if(await O9("jq"))return!0;return process.stdout.write(`${k0}Error: jq is required but not installed.${c}
3
3
  `),process.stdout.write(`Install with:
4
4
  `),process.stdout.write(` brew install jq (macOS)
5
5
  `),process.stdout.write(` apt install jq (Debian/Ubuntu)
@@ -1558,4 +1558,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
1558
1558
  `),2}case"start":{let{runStart:X}=await Promise.resolve().then(() => (Qa(),Za));return X(Q)}case"engine10":{let{runEngine10:X}=await Promise.resolve().then(() => (Ka(),Ja)),{registryLoader:J}=await Promise.resolve().then(() => (JG(),ps));return X(Q,J)}default:return process.stderr.write(`Unknown command: ${Z}
1559
1559
  `),process.stderr.write(ds),2}}KD();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var E$8=await P$8(Bun.argv.slice(2));process.exit(E$8);
1560
1560
 
1561
- //# debugId=6ED4090DB968F42DDF9EACC8F04645B9
1561
+ //# debugId=B29910C55431271B7487E9159E099291
package/mcp/__init__.py CHANGED
@@ -75,4 +75,4 @@ try:
75
75
  except ImportError:
76
76
  __all__ = ['mcp']
77
77
 
78
- __version__ = '10.5.19'
78
+ __version__ = '10.5.20'
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": "10.5.19",
4
+ "version": "10.5.20",
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",
@@ -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": "10.5.19",
5
+ "version": "10.5.20",
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-5rCTAnsF.js";import{B as C}from"./Button-BVHrGLGH.js";import{T as $e}from"./trending-up-agYVl7bU.js";import{C as z}from"./clock-DzocnapF.js";import{A as Be,U as ue,M as De}from"./Avatar-BzyhrX0s.js";import{A as J}from"./activity-CG5PtpVI.js";import{R as pe}from"./refresh-cw-AyYQQPZG.js";import{G as ze}from"./globe-DmIW-phf.js";import{C as Le}from"./chevron-left-DhYs9D3t.js";import{C as je}from"./check-ipranz8L.js";import{D as Y}from"./dollar-sign-o77cj-xB.js";import{U as Te}from"./user-Cv6BNmOT.js";import{D as Me}from"./database-DOuuclZf.js";import{L as Ue}from"./lock-D5nAjeUu.js";import{S as Re}from"./scroll-text-CQFQhF_6.js";import{S as Ie}from"./shield-alert-Xj5wGUSK.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-CgK4xqUy.js";import{B as C}from"./Button-CSMstrCz.js";import{T as $e}from"./trending-up-CF6E9-9a.js";import{C as z}from"./clock-t3v_i7fP.js";import{A as Be,U as ue,M as De}from"./Avatar-BcwLENsU.js";import{A as J}from"./activity-Hl7iDpX_.js";import{R as pe}from"./refresh-cw-uKARwuER.js";import{G as ze}from"./globe-Bz3m1c_-.js";import{C as Le}from"./chevron-left-BUERGaLO.js";import{C as je}from"./check-DhHuZH8k.js";import{D as Y}from"./dollar-sign-BdU_HR9C.js";import{U as Te}from"./user-7rTiTfDj.js";import{D as Me}from"./database-J27fE_Ot.js";import{L as Ue}from"./lock-DjSqmIVZ.js";import{S as Re}from"./scroll-text-BV8Blxig.js";import{S as Ie}from"./shield-alert-rE_xXx7r.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-5rCTAnsF.js";/**
1
+ import{c as l,j as s}from"./index-CgK4xqUy.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-5rCTAnsF.js";import{C as r}from"./clock-DzocnapF.js";import{C as a}from"./circle-alert-BLAxBNgz.js";import{C as l}from"./check-ipranz8L.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-CgK4xqUy.js";import{C as r}from"./clock-t3v_i7fP.js";import{C as a}from"./circle-alert-D7UOw5bc.js";import{C as l}from"./check-DhHuZH8k.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-5rCTAnsF.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-CgK4xqUy.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-5rCTAnsF.js";import{P as K,S as He,E as Be}from"./ErrorBoundary-Bg52u7eg.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-DW0j9Yxz.js";import{C as oe}from"./check-ipranz8L.js";import{C as Ye}from"./clock-DzocnapF.js";import{D as Xe}from"./dollar-sign-o77cj-xB.js";import{U as Ze}from"./upload-DQ3NfXA_.js";import{L as V}from"./loader-circle-DXn-F-H5.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-CgK4xqUy.js";import{P as K,S as He,E as Be}from"./ErrorBoundary-Cx2fnw3q.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-CNMITZHD.js";import{C as oe}from"./check-DhHuZH8k.js";import{C as Ye}from"./clock-t3v_i7fP.js";import{D as Xe}from"./dollar-sign-BdU_HR9C.js";import{U as Ze}from"./upload-D-Ui4N6K.js";import{L as V}from"./loader-circle-CeBjdh2y.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-5rCTAnsF.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-CgK4xqUy.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-5rCTAnsF.js";/**
1
+ import{c as o,r as a,j as e,T as n,h as i,p as c}from"./index-CgK4xqUy.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 l,a as x,j as e}from"./index-5rCTAnsF.js";const N={verified:{badge:"bg-success/10 text-success border-success/20",dot:"bg-success",label:"Verified",proven:"The server recomputed the integrity hash and it matches, and the gpg signature verified against its keyring.",notProven:"That the code is correct, or that the recorded diff still matches your repo. A receipt records which checks ran, not that the result is right."},unsigned:{badge:"bg-warning/10 text-warning border-warning/20",dot:"bg-warning",label:"Unsigned",proven:"The server recomputed the integrity hash and it matches these receipt bytes.",notProven:"Who produced it. An unsigned receipt is forgeable: whoever controls the builder can rewrite the facts and recompute the hash."},unchecked:{badge:"bg-warning/10 text-warning border-warning/20",dot:"bg-warning",label:"Not checked",proven:"The server recomputed the integrity hash and it matches.",notProven:"Provenance. A signature is present but was not evaluated here, which is not the same as a bad signature."},tampered:{badge:"bg-danger/10 text-danger border-danger/20",dot:"bg-danger",label:"Tampered",proven:"Nothing. The server recomputed the integrity hash and it does not match the contents.",notProven:"Anything at all. This receipt was edited after it was written. Do not trust this build."},failed:{badge:"bg-danger/10 text-danger border-danger/20",dot:"bg-danger",label:"Failed verification",proven:"Nothing. A verification check ran on the server and said no.",notProven:"Anything the receipt claims. Read the reason below."},not_verified:{badge:"border-muted/20 text-muted",dot:"bg-muted/40",label:"Not verified here",proven:"Nothing. No verification result was computed for this receipt here.",notProven:"Integrity or provenance. Run the command below to check it yourself."}};function w(t){const n=t==null?void 0:t.integrity_check,r=t==null?void 0:t.verification;return n?n.status==="tampered"?"tampered":n.status==="failed"?"failed":n.status!=="verified"?"not_verified":n.gpg_ok===!0?"verified":r!=null&&r.attestation||r!=null&&r.gpg_signature?"unchecked":"unsigned":"not_verified"}const v=[{key:"verified",label:"Verified",bar:"bg-success",text:"text-success"},{key:"with_gaps",label:"With gaps",bar:"bg-warning",text:"text-warning"},{key:"not_verified",label:"Not verified",bar:"bg-danger",text:"text-danger"},{key:"unknown",label:"Unknown",bar:"bg-muted/40",text:"text-muted"}];function y({summary:t}){const n=t.total_receipts;return n?e.jsxs("div",{className:"space-y-2",children:[e.jsx("div",{className:"flex h-1.5 rounded-full overflow-hidden bg-muted/10",children:v.map(({key:r,bar:s})=>{const i=t[r];return i?e.jsx("div",{className:s,style:{width:`${i/n*100}%`},title:`${i} ${r}`},r):null})}),e.jsx("div",{className:"flex flex-wrap gap-x-4 gap-y-1 text-xs",children:v.map(({key:r,label:s,text:i})=>{const c=t[r];return c?e.jsxs("span",{className:i,children:[e.jsx("span",{className:"font-semibold",children:c})," ",s.toLowerCase()]},r):null})}),e.jsxs("p",{className:"text-muted text-xs",children:["Recorded verdicts across ",n," receipt",n===1?"":"s",", not re-verified here."]})]}):null}function u({label:t,value:n}){return e.jsxs("div",{className:"flex items-baseline gap-2 text-xs",children:[e.jsx("span",{className:"text-muted w-28 flex-shrink-0",children:t}),e.jsx("span",{className:"font-mono truncate",title:n,children:n})]})}function k({proof:t}){var m,p,g,f,b;const[n,r]=l.useState(!1),[s,i]=l.useState(null),[c,d]=l.useState(null);l.useEffect(()=>{if(!n||s||c)return;let o=!1;return x.getProof(t.run_id).then(h=>{o||i(h)}).catch(h=>{o||d((h==null?void 0:h.message)||"could not load this receipt")}),()=>{o=!0}},[n,t.run_id,s,c]);const a=N[w(s)],j=t.generated_at?new Date(t.generated_at).toLocaleString():"unknown";return e.jsxs("div",{className:`border rounded-card overflow-hidden ${s?a.badge:"border-muted/20"}`,children:[e.jsxs("button",{type:"button",className:"w-full flex items-center gap-3 px-3 py-2.5 text-left",onClick:()=>r(!n),"aria-expanded":n,children:[e.jsx("span",{className:`w-2 h-2 rounded-full flex-shrink-0 ${s?a.dot:"bg-muted/40"}`}),e.jsx("span",{className:"text-sm font-medium flex-1 truncate",children:t.headline?`Recorded: ${t.headline}`:t.run_id}),t.final_verdict&&e.jsxs("span",{className:"text-xs font-mono uppercase tracking-wider flex-shrink-0 text-muted",children:["council ",t.final_verdict]}),e.jsx("span",{className:"text-muted text-xs flex-shrink-0",children:n?"−":"+"})]}),n&&e.jsxs("div",{className:"px-3 pb-3 space-y-3 border-t border-current/10 pt-3",children:[c&&e.jsxs("p",{className:"text-xs text-danger",children:["Could not load this receipt: ",c]}),!c&&!s&&e.jsx("p",{className:"text-xs text-muted",children:"Loading receipt…"}),s&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(u,{label:"Run",value:s.run_id}),e.jsx(u,{label:"Generated",value:j}),e.jsx(u,{label:"Loki version",value:s.loki_version||"unknown"}),e.jsx(u,{label:"Cost",value:typeof((m=s.cost)==null?void 0:m.usd)=="number"?`$${s.cost.usd.toFixed(2)}`:"unknown"}),e.jsx(u,{label:"Files changed",value:typeof((p=s.files_changed)==null?void 0:p.count)=="number"?String(s.files_changed.count):"unknown"}),((g=s.verification)==null?void 0:g.hash)&&e.jsx(u,{label:"Recorded hash",value:s.verification.hash})]}),e.jsxs("div",{className:`rounded-card border px-3 py-2 ${a.badge}`,children:[e.jsx("p",{className:"text-xs font-semibold uppercase tracking-wider mb-1",children:a.label}),e.jsxs("p",{className:"text-xs mb-1",children:[e.jsx("span",{className:"font-semibold",children:"Proven: "}),a.proven]}),e.jsxs("p",{className:"text-xs opacity-80",children:[e.jsx("span",{className:"font-semibold",children:"Not proven: "}),a.notProven]}),(((f=s.integrity_check)==null?void 0:f.reasons)||[]).slice(0,2).map(o=>e.jsx("p",{className:"text-xs opacity-80 mt-1",children:o},o))]}),e.jsxs("p",{className:"text-xs text-muted",children:["Verify it yourself (also re-derives the diff against your repo):"," ",e.jsxs("code",{className:"font-mono",children:["loki proof verify ",s.run_id,(b=s.verification)!=null&&b.attestation?" --jwks <url|file>":""]})]}),t.pr_url&&e.jsx("a",{href:t.pr_url,target:"_blank",rel:"noreferrer noopener",className:"text-xs text-primary underline",children:"View the pull request"})]})]})]})}function P(){const[t,n]=l.useState(null),[r,s]=l.useState(null),[i,c]=l.useState(null);return l.useEffect(()=>{let d=!1;return x.listProofs().then(a=>{d||n(a.proofs||[])}).catch(a=>{d||c((a==null?void 0:a.message)||"could not load receipts")}),x.proofsSummary().then(a=>{d||s(a)}).catch(()=>{}),()=>{d=!0}},[]),e.jsxs("section",{className:"space-y-3",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-sm font-semibold",children:"Evidence Receipts"}),e.jsx("p",{className:"text-muted text-xs mt-1",children:"What each build actually checked, recorded so you can verify it yourself."})]}),i&&e.jsxs("p",{className:"text-xs text-danger",children:["Could not load receipts: ",i]}),!i&&t===null&&e.jsx("p",{className:"text-xs text-muted",children:"Loading…"}),r&&e.jsx(y,{summary:r}),t!==null&&t.length===0&&e.jsxs("p",{className:"text-xs text-muted",children:["No receipts yet. One is written at the end of each run (set ",e.jsx("code",{className:"font-mono",children:"LOKI_PROOF=0"})," to opt out)."]}),e.jsx("div",{className:"space-y-2",children:t==null?void 0:t.map(d=>e.jsx(k,{proof:d},d.run_id))})]})}export{P as E};
1
+ import{r as l,a as x,j as e}from"./index-CgK4xqUy.js";const N={verified:{badge:"bg-success/10 text-success border-success/20",dot:"bg-success",label:"Verified",proven:"The server recomputed the integrity hash and it matches, and the gpg signature verified against its keyring.",notProven:"That the code is correct, or that the recorded diff still matches your repo. A receipt records which checks ran, not that the result is right."},unsigned:{badge:"bg-warning/10 text-warning border-warning/20",dot:"bg-warning",label:"Unsigned",proven:"The server recomputed the integrity hash and it matches these receipt bytes.",notProven:"Who produced it. An unsigned receipt is forgeable: whoever controls the builder can rewrite the facts and recompute the hash."},unchecked:{badge:"bg-warning/10 text-warning border-warning/20",dot:"bg-warning",label:"Not checked",proven:"The server recomputed the integrity hash and it matches.",notProven:"Provenance. A signature is present but was not evaluated here, which is not the same as a bad signature."},tampered:{badge:"bg-danger/10 text-danger border-danger/20",dot:"bg-danger",label:"Tampered",proven:"Nothing. The server recomputed the integrity hash and it does not match the contents.",notProven:"Anything at all. This receipt was edited after it was written. Do not trust this build."},failed:{badge:"bg-danger/10 text-danger border-danger/20",dot:"bg-danger",label:"Failed verification",proven:"Nothing. A verification check ran on the server and said no.",notProven:"Anything the receipt claims. Read the reason below."},not_verified:{badge:"border-muted/20 text-muted",dot:"bg-muted/40",label:"Not verified here",proven:"Nothing. No verification result was computed for this receipt here.",notProven:"Integrity or provenance. Run the command below to check it yourself."}};function w(t){const n=t==null?void 0:t.integrity_check,r=t==null?void 0:t.verification;return n?n.status==="tampered"?"tampered":n.status==="failed"?"failed":n.status!=="verified"?"not_verified":n.gpg_ok===!0?"verified":r!=null&&r.attestation||r!=null&&r.gpg_signature?"unchecked":"unsigned":"not_verified"}const v=[{key:"verified",label:"Verified",bar:"bg-success",text:"text-success"},{key:"with_gaps",label:"With gaps",bar:"bg-warning",text:"text-warning"},{key:"not_verified",label:"Not verified",bar:"bg-danger",text:"text-danger"},{key:"unknown",label:"Unknown",bar:"bg-muted/40",text:"text-muted"}];function y({summary:t}){const n=t.total_receipts;return n?e.jsxs("div",{className:"space-y-2",children:[e.jsx("div",{className:"flex h-1.5 rounded-full overflow-hidden bg-muted/10",children:v.map(({key:r,bar:s})=>{const i=t[r];return i?e.jsx("div",{className:s,style:{width:`${i/n*100}%`},title:`${i} ${r}`},r):null})}),e.jsx("div",{className:"flex flex-wrap gap-x-4 gap-y-1 text-xs",children:v.map(({key:r,label:s,text:i})=>{const c=t[r];return c?e.jsxs("span",{className:i,children:[e.jsx("span",{className:"font-semibold",children:c})," ",s.toLowerCase()]},r):null})}),e.jsxs("p",{className:"text-muted text-xs",children:["Recorded verdicts across ",n," receipt",n===1?"":"s",", not re-verified here."]})]}):null}function u({label:t,value:n}){return e.jsxs("div",{className:"flex items-baseline gap-2 text-xs",children:[e.jsx("span",{className:"text-muted w-28 flex-shrink-0",children:t}),e.jsx("span",{className:"font-mono truncate",title:n,children:n})]})}function k({proof:t}){var m,p,g,f,b;const[n,r]=l.useState(!1),[s,i]=l.useState(null),[c,d]=l.useState(null);l.useEffect(()=>{if(!n||s||c)return;let o=!1;return x.getProof(t.run_id).then(h=>{o||i(h)}).catch(h=>{o||d((h==null?void 0:h.message)||"could not load this receipt")}),()=>{o=!0}},[n,t.run_id,s,c]);const a=N[w(s)],j=t.generated_at?new Date(t.generated_at).toLocaleString():"unknown";return e.jsxs("div",{className:`border rounded-card overflow-hidden ${s?a.badge:"border-muted/20"}`,children:[e.jsxs("button",{type:"button",className:"w-full flex items-center gap-3 px-3 py-2.5 text-left",onClick:()=>r(!n),"aria-expanded":n,children:[e.jsx("span",{className:`w-2 h-2 rounded-full flex-shrink-0 ${s?a.dot:"bg-muted/40"}`}),e.jsx("span",{className:"text-sm font-medium flex-1 truncate",children:t.headline?`Recorded: ${t.headline}`:t.run_id}),t.final_verdict&&e.jsxs("span",{className:"text-xs font-mono uppercase tracking-wider flex-shrink-0 text-muted",children:["council ",t.final_verdict]}),e.jsx("span",{className:"text-muted text-xs flex-shrink-0",children:n?"−":"+"})]}),n&&e.jsxs("div",{className:"px-3 pb-3 space-y-3 border-t border-current/10 pt-3",children:[c&&e.jsxs("p",{className:"text-xs text-danger",children:["Could not load this receipt: ",c]}),!c&&!s&&e.jsx("p",{className:"text-xs text-muted",children:"Loading receipt…"}),s&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(u,{label:"Run",value:s.run_id}),e.jsx(u,{label:"Generated",value:j}),e.jsx(u,{label:"Loki version",value:s.loki_version||"unknown"}),e.jsx(u,{label:"Cost",value:typeof((m=s.cost)==null?void 0:m.usd)=="number"?`$${s.cost.usd.toFixed(2)}`:"unknown"}),e.jsx(u,{label:"Files changed",value:typeof((p=s.files_changed)==null?void 0:p.count)=="number"?String(s.files_changed.count):"unknown"}),((g=s.verification)==null?void 0:g.hash)&&e.jsx(u,{label:"Recorded hash",value:s.verification.hash})]}),e.jsxs("div",{className:`rounded-card border px-3 py-2 ${a.badge}`,children:[e.jsx("p",{className:"text-xs font-semibold uppercase tracking-wider mb-1",children:a.label}),e.jsxs("p",{className:"text-xs mb-1",children:[e.jsx("span",{className:"font-semibold",children:"Proven: "}),a.proven]}),e.jsxs("p",{className:"text-xs opacity-80",children:[e.jsx("span",{className:"font-semibold",children:"Not proven: "}),a.notProven]}),(((f=s.integrity_check)==null?void 0:f.reasons)||[]).slice(0,2).map(o=>e.jsx("p",{className:"text-xs opacity-80 mt-1",children:o},o))]}),e.jsxs("p",{className:"text-xs text-muted",children:["Verify it yourself (also re-derives the diff against your repo):"," ",e.jsxs("code",{className:"font-mono",children:["loki proof verify ",s.run_id,(b=s.verification)!=null&&b.attestation?" --jwks <url|file>":""]})]}),t.pr_url&&e.jsx("a",{href:t.pr_url,target:"_blank",rel:"noreferrer noopener",className:"text-xs text-primary underline",children:"View the pull request"})]})]})]})}function P(){const[t,n]=l.useState(null),[r,s]=l.useState(null),[i,c]=l.useState(null);return l.useEffect(()=>{let d=!1;return x.listProofs().then(a=>{d||n(a.proofs||[])}).catch(a=>{d||c((a==null?void 0:a.message)||"could not load receipts")}),x.proofsSummary().then(a=>{d||s(a)}).catch(()=>{}),()=>{d=!0}},[]),e.jsxs("section",{className:"space-y-3",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-sm font-semibold",children:"Evidence Receipts"}),e.jsx("p",{className:"text-muted text-xs mt-1",children:"What each build actually checked, recorded so you can verify it yourself."})]}),i&&e.jsxs("p",{className:"text-xs text-danger",children:["Could not load receipts: ",i]}),!i&&t===null&&e.jsx("p",{className:"text-xs text-muted",children:"Loading…"}),r&&e.jsx(y,{summary:r}),t!==null&&t.length===0&&e.jsxs("p",{className:"text-xs text-muted",children:["No receipts yet. One is written at the end of each run (set ",e.jsx("code",{className:"font-mono",children:"LOKI_PROOF=0"})," to opt out)."]}),e.jsx("div",{className:"space-y-2",children:t==null?void 0:t.map(d=>e.jsx(k,{proof:d},d.run_id))})]})}export{P as E};
@@ -1,4 +1,4 @@
1
- import{c as _,r as o,a as k,j as e,m as B,J as v,N as h,a5 as H,M as L,l as q}from"./index-5rCTAnsF.js";import{B as N}from"./Button-BVHrGLGH.js";import{C as y}from"./thumbs-up-DW0j9Yxz.js";import{R as S}from"./refresh-cw-AyYQQPZG.js";import{C as z}from"./circle-alert-BLAxBNgz.js";import{U as D}from"./user-Cv6BNmOT.js";import{L as G}from"./loader-circle-DXn-F-H5.js";import{R as T}from"./rotate-ccw-DYbslLfT.js";/**
1
+ import{c as _,r as o,a as k,j as e,m as B,J as v,N as h,a5 as H,M as L,l as q}from"./index-CgK4xqUy.js";import{B as N}from"./Button-CSMstrCz.js";import{C as y}from"./thumbs-up-CNMITZHD.js";import{R as S}from"./refresh-cw-uKARwuER.js";import{C as z}from"./circle-alert-D7UOw5bc.js";import{U as D}from"./user-7rTiTfDj.js";import{L as G}from"./loader-circle-CeBjdh2y.js";import{R as T}from"./rotate-ccw-ByA6XJq1.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 I,r as c,a as b,j as e,G as me,A as ue,S as Z,k as ee,m as pe,h as he,p as fe,X as te,M as be}from"./index-5rCTAnsF.js";import{B as y}from"./Button-BVHrGLGH.js";import{C as ge}from"./chevron-left-DhYs9D3t.js";import{G as P}from"./thumbs-up-DW0j9Yxz.js";import{R as $}from"./refresh-cw-AyYQQPZG.js";import{C as Ne}from"./circle-alert-BLAxBNgz.js";import{L as Q,S as je}from"./ProjectPage-D7eJn--6.js";import{S as se}from"./shield-alert-Xj5wGUSK.js";import{F as ye}from"./file-code-corner-BZ2VMnYA.js";import{C as V}from"./clock-DzocnapF.js";import{C as re}from"./check-ipranz8L.js";import"./ErrorBoundary-Bg52u7eg.js";import"./TerminalOutput-C3KbV8E7.js";import"./lock-D5nAjeUu.js";import"./package-D8Drpzi8.js";import"./file-plus-DeHfGncj.js";import"./activity-CG5PtpVI.js";import"./scroll-text-CQFQhF_6.js";import"./bot-Dp0zY9t7.js";import"./loader-circle-DXn-F-H5.js";import"./hammer-CoW8R8V5.js";import"./dollar-sign-o77cj-xB.js";import"./globe-DmIW-phf.js";import"./trash-2-VOdpiJ1e.js";import"./upload-DQ3NfXA_.js";import"./plus-C-0T9dAu.js";import"./rotate-ccw-DYbslLfT.js";import"./code-xml-BPcy_Eqm.js";import"./trending-up-agYVl7bU.js";import"./layers-DGEk-2RQ.js";import"./trending-down-eTizH4_b.js";import"./server-DxNytQEJ.js";/**
1
+ import{c as I,r as c,a as b,j as e,G as me,A as ue,S as Z,k as ee,m as pe,h as he,p as fe,X as te,M as be}from"./index-CgK4xqUy.js";import{B as y}from"./Button-CSMstrCz.js";import{C as ge}from"./chevron-left-BUERGaLO.js";import{G as P}from"./thumbs-up-CNMITZHD.js";import{R as $}from"./refresh-cw-uKARwuER.js";import{C as Ne}from"./circle-alert-D7UOw5bc.js";import{L as Q,S as je}from"./ProjectPage-Dj_nv2kT.js";import{S as se}from"./shield-alert-rE_xXx7r.js";import{F as ye}from"./file-code-corner-Cu4A1aIH.js";import{C as V}from"./clock-t3v_i7fP.js";import{C as re}from"./check-DhHuZH8k.js";import"./ErrorBoundary-Cx2fnw3q.js";import"./TerminalOutput-LPxzwfwm.js";import"./lock-DjSqmIVZ.js";import"./package-NL0AdpIi.js";import"./file-plus-BTli76r5.js";import"./activity-Hl7iDpX_.js";import"./scroll-text-BV8Blxig.js";import"./bot-6SoklKaZ.js";import"./loader-circle-CeBjdh2y.js";import"./hammer-HNN6jr92.js";import"./dollar-sign-BdU_HR9C.js";import"./globe-Bz3m1c_-.js";import"./trash-2-BP3Rr5SU.js";import"./upload-D-Ui4N6K.js";import"./plus-Lbz3hom-.js";import"./rotate-ccw-ByA6XJq1.js";import"./code-xml-DU-CmwVx.js";import"./trending-up-CF6E9-9a.js";import"./layers-DhuXUuM6.js";import"./trending-down-BE_8lCjD.js";import"./server-Cy3R5hde.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.