loki-mode 9.70.0 → 9.71.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/loki +41 -16
  4. package/dashboard/__init__.py +1 -1
  5. package/docs/INSTALLATION.md +1 -1
  6. package/docs/v10/BOARD.md +18 -18
  7. package/docs/v10/TODO.md +18 -28
  8. package/loki-ts/dist/loki.js +2 -2
  9. package/mcp/__init__.py +1 -1
  10. package/package.json +1 -1
  11. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  12. package/web-app/dist/assets/{AdminPage-DNav8k7e.js → AdminPage-5-i7dYRv.js} +1 -1
  13. package/web-app/dist/assets/{Avatar-nQLkS0Rp.js → Avatar-DOgXkiA5.js} +1 -1
  14. package/web-app/dist/assets/{Badge-DTg5sfo8.js → Badge-BBCAEx-v.js} +1 -1
  15. package/web-app/dist/assets/{Button-D2kvFYYU.js → Button-mrjJiIzX.js} +1 -1
  16. package/web-app/dist/assets/{CockpitPage-DtOqSziO.js → CockpitPage-DO1BqQtR.js} +1 -1
  17. package/web-app/dist/assets/{ComparePage-D2K_CaGa.js → ComparePage-CttX-p4A.js} +1 -1
  18. package/web-app/dist/assets/{ErrorBoundary-twJ6L4yY.js → ErrorBoundary-DrXZPl7W.js} +1 -1
  19. package/web-app/dist/assets/{EvidenceReceiptPanel-Bg7hTxYy.js → EvidenceReceiptPanel-DsHfSljL.js} +1 -1
  20. package/web-app/dist/assets/{GitHubIssuesPanel-CM_EQu2h.js → GitHubIssuesPanel-DXDCz06W.js} +1 -1
  21. package/web-app/dist/assets/{GitHubPRsPanel-Buget9GL.js → GitHubPRsPanel-3qECbDiA.js} +1 -1
  22. package/web-app/dist/assets/{HomePage-Bx5BEAwr.js → HomePage-vb55Jnnw.js} +2 -2
  23. package/web-app/dist/assets/{LoginPage-CwKAmgM8.js → LoginPage-C1wouCAg.js} +1 -1
  24. package/web-app/dist/assets/{MagicPage-Cgku5cNq.js → MagicPage-Ccf2TzsX.js} +1 -1
  25. package/web-app/dist/assets/{MetricsPage-BLShZtng.js → MetricsPage-DxpjKBlD.js} +1 -1
  26. package/web-app/dist/assets/{NotFoundPage-CaUVGPU2.js → NotFoundPage-BjesliCI.js} +1 -1
  27. package/web-app/dist/assets/{ProjectPage-CXB847H5.js → ProjectPage-OLJv91Fm.js} +3 -3
  28. package/web-app/dist/assets/{ProjectsPage-CwcUJtbA.js → ProjectsPage-Bd0VWUNT.js} +1 -1
  29. package/web-app/dist/assets/{SettingsPage-B-von8-n.js → SettingsPage-B92ofTn5.js} +1 -1
  30. package/web-app/dist/assets/{ShowcasePage-B85iYuoJ.js → ShowcasePage-Ben4Ud4y.js} +1 -1
  31. package/web-app/dist/assets/{SystemSettingsPage-CiwheY5n.js → SystemSettingsPage-DQ7y1jJw.js} +1 -1
  32. package/web-app/dist/assets/{TeamsPage-Buy0vJD8.js → TeamsPage-DvI2Ysar.js} +1 -1
  33. package/web-app/dist/assets/{TemplatesPage-BKICGf0s.js → TemplatesPage-qkFTI361.js} +1 -1
  34. package/web-app/dist/assets/{TerminalOutput-DYvnz-Yg.js → TerminalOutput-Bbi5Qsu1.js} +1 -1
  35. package/web-app/dist/assets/{activity-Bq5K-M3c.js → activity-B6_UNFP3.js} +1 -1
  36. package/web-app/dist/assets/{bell-B5_seC1_.js → bell-D9bRY83l.js} +1 -1
  37. package/web-app/dist/assets/{bot-DGL2F3r2.js → bot-B9XE8rVE.js} +1 -1
  38. package/web-app/dist/assets/{check-BZXFoANt.js → check-CIlNFVu7.js} +1 -1
  39. package/web-app/dist/assets/{chevron-left-D8SGt8XQ.js → chevron-left-sqTwkCti.js} +1 -1
  40. package/web-app/dist/assets/{circle-alert-CHqNb9E5.js → circle-alert-ClR-8eiz.js} +1 -1
  41. package/web-app/dist/assets/{clock-HlM-bj2D.js → clock-DhrLudbQ.js} +1 -1
  42. package/web-app/dist/assets/{cloud-DIZmF5NU.js → cloud-CbY5ijES.js} +1 -1
  43. package/web-app/dist/assets/{code-xml-6nryqMai.js → code-xml-DGN0zQOT.js} +1 -1
  44. package/web-app/dist/assets/{database-CoDXjNPK.js → database-CFkV71Ae.js} +1 -1
  45. package/web-app/dist/assets/{dollar-sign-CSMVryX2.js → dollar-sign-t0__nc7_.js} +1 -1
  46. package/web-app/dist/assets/{file-code-corner-sHqsudT_.js → file-code-corner-V4yaRoxs.js} +1 -1
  47. package/web-app/dist/assets/{file-plus-BEOH6GEK.js → file-plus-BTdcA9zR.js} +1 -1
  48. package/web-app/dist/assets/{globe-D0_Ot9K-.js → globe-DJ8UlFt2.js} +1 -1
  49. package/web-app/dist/assets/{hammer-J3JpBiCI.js → hammer-DSpaXtqP.js} +1 -1
  50. package/web-app/dist/assets/{index-B_g2Bx7d.js → index-aYgURGFC.js} +2 -2
  51. package/web-app/dist/assets/{layers-DNGnssvt.js → layers-cbPS7UG9.js} +1 -1
  52. package/web-app/dist/assets/{loader-circle-CVx9e9xb.js → loader-circle-CciQSsBx.js} +1 -1
  53. package/web-app/dist/assets/{lock-DPU2NDlh.js → lock-JtWoEayV.js} +1 -1
  54. package/web-app/dist/assets/{package-B8d5XPQp.js → package-Dcv0g9iv.js} +1 -1
  55. package/web-app/dist/assets/{plus-CijNwNZi.js → plus-R_7Xr4PC.js} +1 -1
  56. package/web-app/dist/assets/{refresh-cw-CKKREgGF.js → refresh-cw-6MdZdvHz.js} +1 -1
  57. package/web-app/dist/assets/{rotate-ccw-C_I6h5nb.js → rotate-ccw-Dcteu0jr.js} +1 -1
  58. package/web-app/dist/assets/{scroll-text-_aTmtYKs.js → scroll-text-Xcw2I15b.js} +1 -1
  59. package/web-app/dist/assets/{server-BYEt-t7J.js → server-BhMeLqV8.js} +1 -1
  60. package/web-app/dist/assets/{shield-alert-DZ1ph0ND.js → shield-alert-Y7birYk_.js} +1 -1
  61. package/web-app/dist/assets/{thumbs-up-iPq2uWPB.js → thumbs-up-B9I1RzAj.js} +1 -1
  62. package/web-app/dist/assets/{trash-2-DHMRNLZh.js → trash-2-FrJ_zeQ_.js} +1 -1
  63. package/web-app/dist/assets/{trending-down-BQx0CnpE.js → trending-down-DA-YY1yX.js} +1 -1
  64. package/web-app/dist/assets/{trending-up-exKfFhJX.js → trending-up-CC7ghXOa.js} +1 -1
  65. package/web-app/dist/assets/{upload-JxCmEXS1.js → upload-Btyqt4Cn.js} +1 -1
  66. package/web-app/dist/assets/{usePolling-DGy_8ihj.js → usePolling-CTqGbMeS.js} +1 -1
  67. package/web-app/dist/assets/{user-CqHnVcBI.js → user-AWsEaMJm.js} +1 -1
  68. package/web-app/dist/index.html +1 -1
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: loki-mode
3
3
  description: Autonomous spec-driven build system with a built-in trust layer. It does not call work done until it is verified (RARV-C closure loop, 8 quality gates, completion council, verified-completion evidence gate). Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product with minimal human intervention. Provider-agnostic. Requires --dangerously-skip-permissions flag.
4
4
  ---
5
5
 
6
- # Loki Mode v9.70.0
6
+ # Loki Mode v9.71.0
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
- **v9.70.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
473
+ **v9.71.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 9.70.0
1
+ 9.71.0
package/autonomy/loki CHANGED
@@ -28664,6 +28664,8 @@ def load_json(path):
28664
28664
  return None
28665
28665
 
28666
28666
  def fmt_number(n):
28667
+ if n is None:
28668
+ return "N/A"
28667
28669
  return f"{n:,}"
28668
28670
 
28669
28671
  def load_queue(path):
@@ -28702,7 +28704,8 @@ if os.path.isfile(checkpoint_index):
28702
28704
  pass
28703
28705
 
28704
28706
  # Orchestrator state
28705
- orch = load_json(os.path.join(loki_dir, "state", "orchestrator.json")) or {}
28707
+ orch_raw = load_json(os.path.join(loki_dir, "state", "orchestrator.json"))
28708
+ orch = orch_raw or {}
28706
28709
  current_phase = orch.get("currentPhase", "N/A")
28707
28710
  orch_metrics = orch.get("metrics", {})
28708
28711
  tasks_completed_orch = orch_metrics.get("tasksCompleted", 0)
@@ -28721,7 +28724,19 @@ if os.path.isdir(eff_dir):
28721
28724
  if last_n > 0 and len(iterations) > last_n:
28722
28725
  iterations = iterations[-last_n:]
28723
28726
 
28724
- total_iterations = len(iterations) if iterations else max(orch.get("currentIteration", 0), 0)
28727
+ # BACKLOG 118 / S-147: a fresh .loki with no efficiency files and no
28728
+ # orchestrator state has nothing to count. total_iterations (and the
28729
+ # time_saved estimate derived from it) must come back null, not a
28730
+ # fabricated 0, so callers can tell "never ran" from "ran zero".
28731
+ if iterations:
28732
+ total_iterations = len(iterations)
28733
+ iterations_known = True
28734
+ elif orch_raw is not None and "currentIteration" in orch:
28735
+ total_iterations = max(orch.get("currentIteration", 0), 0)
28736
+ iterations_known = True
28737
+ else:
28738
+ total_iterations = None
28739
+ iterations_known = False
28725
28740
 
28726
28741
  # Gather agent types from iterations and agents.json
28727
28742
  for it in iterations:
@@ -28829,19 +28844,26 @@ except Exception:
28829
28844
  total_cost = sum(it.get("cost_usd", 0) for it in iterations)
28830
28845
  total_input_tokens = sum(it.get("input_tokens", 0) for it in iterations)
28831
28846
  total_output_tokens = sum(it.get("output_tokens", 0) for it in iterations)
28847
+ tokens_known = bool(iterations)
28832
28848
 
28833
28849
  # Also check context tracking for cost data
28834
28850
  ctx_file = os.path.join(loki_dir, "context", "tracking.json")
28835
28851
  ctx = load_json(ctx_file)
28836
- if ctx and total_cost == 0:
28837
- totals = ctx.get("totals", {})
28838
- total_cost = totals.get("total_cost_usd", 0)
28839
- total_input_tokens = totals.get("total_input", 0)
28840
- total_output_tokens = totals.get("total_output", 0)
28852
+ # context-tracker.py seeds tracking.json with all-zero totals, so the file
28853
+ # existing is not a measurement: only real (nonzero) totals count (S-147).
28854
+ if isinstance(ctx, dict) and not tokens_known:
28855
+ totals = ctx.get("totals")
28856
+ if isinstance(totals, dict) and (totals.get("total_input") or totals.get("total_output")
28857
+ or totals.get("total_cost_usd") or totals.get("iterations_tracked")):
28858
+ total_cost = totals.get("total_cost_usd") or 0
28859
+ total_input_tokens = totals.get("total_input") or 0
28860
+ total_output_tokens = totals.get("total_output") or 0
28861
+ tokens_known = True
28841
28862
 
28842
28863
  # --- Time saved estimate ---
28843
- # Each Loki iteration replaces ~15min of manual work
28844
- time_saved_hours = round(total_iterations * 15 / 60, 2)
28864
+ # Each Loki iteration replaces ~15min of manual work. Null (not a computed
28865
+ # number) when no iteration was ever recorded (BACKLOG 118 / S-147).
28866
+ time_saved_hours = round(total_iterations * 15 / 60, 2) if iterations_known else None
28845
28867
 
28846
28868
  # --- Memory stats ---
28847
28869
  episodic_count = 0
@@ -28891,10 +28913,10 @@ data = {
28891
28913
  "tests_written": tests_written
28892
28914
  },
28893
28915
  "tokens": {
28894
- "input": total_input_tokens,
28895
- "output": total_output_tokens,
28896
- "total": total_input_tokens + total_output_tokens,
28897
- "cost_usd": round(total_cost, 2)
28916
+ "input": total_input_tokens if tokens_known else None,
28917
+ "output": total_output_tokens if tokens_known else None,
28918
+ "total": (total_input_tokens + total_output_tokens) if tokens_known else None,
28919
+ "cost_usd": round(total_cost, 2) if tokens_known else None
28898
28920
  },
28899
28921
  "time_saved": {
28900
28922
  "hours": time_saved_hours,
@@ -28935,15 +28957,18 @@ else:
28935
28957
  lines.append(f" Commits: {fmt_number(commits_made)}")
28936
28958
  lines.append(f" Tests written: {fmt_number(tests_written)}")
28937
28959
  lines.append("")
28938
- if total_cost > 0 or total_input_tokens > 0:
28960
+ if tokens_known and (total_cost > 0 or total_input_tokens > 0):
28939
28961
  lines.append("TOKEN USAGE")
28940
28962
  lines.append(f" Input tokens: {fmt_number(total_input_tokens)}")
28941
28963
  lines.append(f" Output tokens: {fmt_number(total_output_tokens)}")
28942
28964
  lines.append(f" Estimated cost: ${total_cost:.2f}")
28943
28965
  lines.append("")
28944
28966
  lines.append("TIME SAVED")
28945
- lines.append(f" Estimated: {time_saved_hours} hours")
28946
- lines.append(f" (based on {fmt_number(total_iterations)} iterations x 15min each)")
28967
+ if iterations_known:
28968
+ lines.append(f" Estimated: {time_saved_hours} hours")
28969
+ lines.append(f" (based on {fmt_number(total_iterations)} iterations x 15min each)")
28970
+ else:
28971
+ lines.append(" Estimated: unknown (no iterations recorded)")
28947
28972
  lines.append("")
28948
28973
  if episodic_count > 0 or semantic_count > 0:
28949
28974
  lines.append("MEMORY")
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "9.70.0"
10
+ __version__ = "9.71.0"
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:** v9.70.0
5
+ **Version:** v9.71.0
6
6
 
7
7
  ---
8
8
 
package/docs/v10/BOARD.md CHANGED
@@ -66,7 +66,7 @@ set is declared to avoid overlap with those and with each other.
66
66
  | S-47 | BACKLOG 116: key misreads hide or zero real data (GitHubPRsPanel statusCheckRollup/state case, EvidenceReceiptPanel cost_usd/files_changed keys, memory-browser camelCase mismatch) | web-app/src/components/GitHubPRsPanel.tsx, web-app/src/components/EvidenceReceiptPanel.tsx, dashboard-ui/components/loki-memory-browser.js, dashboard-ui/components/loki-overview.js | MEDIUM | red: each named field misreads and shows a false empty/zero; green: each reads the real emitted key, one test per site | released@2026-09-27T15:00Z | EvidenceReceiptPanel.tsx already touched by GF-5 (merged) for a different concern (classify()); this slice is the cost_usd/files_changed key-path only, disjoint lines. Merged 11a3e7fb (auto-merged onto loki-overview.js cleanly, different function), 34/34 reconfirmed on main; builder verified every key against the real writer/API source, not the backlog description alone. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
67
67
  | S-48 | BACKLOG 128: stale docs assert a `{"runner":"none","pass":true}` writer shape that does not exist (D20 already corrected the real shape) | references/core-workflow.md, docs/VERIFIED-COMPLETION-PLAN.md, tests/test-council-devils-advocate.sh, tests/test-da-veto.sh, tests/test-council-convergence-floor.sh | LOW | docs describe the real writer shape (`pass:"inconclusive"` string); the 3 named test fixtures use the real shape instead of a synthetic `pass:true` | released@2026-09-27T10:58Z | STALE DUPLICATE, already fixed: builder found all 5 target locations already correct (commit c06b50ee, "S-33"), verified directly against `enforce_test_coverage` in run.sh and re-ran all 3 test suites clean (6/6, 9/9, 40/40). No new commit needed. Marking released since the underlying fix already shipped in main. One non-blocking follow-up noted: `test-council-convergence-floor.sh` NEGATIVE-B passes even without the `runner!='none'` guard, since `pass:"inconclusive"` alone already fails `pass===True` -- candidate for a future assertion-hardening slice, not filed as a new backlog item yet. |
68
68
  | S-49 | BACKLOG 134: completion-council.sh's 3 test-result readers use bare PATH python3 -E -c with no -I/-S/fixed-path resolution (same bypass class BACKLOG 129 already closed for run.sh) | autonomy/completion-council.sh (council_heuristic_review, council_evaluate_member, council_devils_advocate_review only), new moat case planting a user-site .pth | HIGH | red: a planted .pth flips a genuinely-failing test-results.json to CONFIRMED_COMPLETE; green: routed through a resolved-interpreter helper matching `_loki_snapshot_py_tool`'s pattern, .pth has no effect | released@2026-09-27T16:40Z | Disjoint from S-18/BACKLOG 149's run.sh GH-token work and from S-17's vote-text assertions (already merged, different lines in the same file -- verify no line-range collision before editing). Dispatched 15:00 (workflow wf_29a75a9c-652, slice-card brief). Built 6b276aaf (wf_29a75a9c-652-1): 3 readers via _loki_snapshot_py_tool -I -S, new P2 case red pre-fix and green after, mutation red. 2 HIGH reviewers dispatched 15:16. Reviewer B APPROVE; reviewer A CONCERN (reproduced): queue readers at ~3769/~4050 still use bare python3 -E, so a .pth flips the verdict. Rework sent 15:28. Rework 17eeb940+8ce7f1b1: queue and convergence readers isolated and fail closed, no-interpreter veto, byte-identity test. Re-review (HIGH) dispatched 15:40. Round 2: HIGH reviewer A APPROVE (the .pth attack fails on every reader in the 3 functions; 7 of 8 mutations red; M3b checklist leg is a test gap, fix holds on a direct probe). Reviewer B approved round 1. Train 4. Follow-up: council readers outside the 3 functions (~1425, ~1564, ~4215-4245). Cherry-picked onto main for train 4 (3 commits); D27 checks green except tests/test-select-tests.sh, which hit the 60s cap (rc=124; CI runs it in full; reviewer ran 38/38). Train 4 release commit 08d64f4e (v9.59.0) pushed 16:07:02Z, ls-remote verified. Released in v9.59.0 (Release run 36332036567 publish-npm success; v9.58.0 itself never published, superseded). |
69
- | S-50 | BACKLOG 137: S-02's dynamic-repo-root fix breaks P7's own sed-workaround for the same bug | tests/moat/p7-no-fabricated-data.sh (lines 477-501, the client-route helper invocation only) | MEDIUM | red: P7.webapp-client-routes-exist fails post-S-02 because the sed target no longer exists; green: helpers run in place or receive the root explicitly, case passes again | ready@2026-09-27T10:50Z | NARROW SCOPE WARNING: this file is the most contended file this session (S-27/S-29/S-30/S-31/S-32 lineage). Builder must rebase onto main AFTER the S-29 merge-pass lands and touch ONLY the named 477-501 invocation block, nothing else in the file. Coordinate with Captain before starting if S-29's merge is still in flight. |
69
+ | S-50 | BACKLOG 137: S-02's dynamic-repo-root fix breaks P7's own sed-workaround for the same bug | tests/moat/p7-no-fabricated-data.sh (lines 477-501, the client-route helper invocation only) | MEDIUM | red: P7.webapp-client-routes-exist fails post-S-02 because the sed target no longer exists; green: helpers run in place or receive the root explicitly, case passes again | building@2026-09-27T19:10Z | NARROW SCOPE WARNING: this file is the most contended file this session (S-27/S-29/S-30/S-31/S-32 lineage). Builder must rebase onto main AFTER the S-29 merge-pass lands and touch ONLY the named 477-501 invocation block, nothing else in the file. Coordinate with Captain before starting if S-29's merge is still in flight. Batch 5 build (wf_38d4e17c-211). |
70
70
  | S-51 | BACKLOG 117: stale or false static copy (version numbers, license, Gemini support, gate counts, invented testimonial) | web-app/src/components/WhatsNew.tsx (actual path, not pages/ as originally listed), web-app/src/components/Footer.tsx, web-app/src/pages/SettingsPage.tsx, web-app/src/pages/ComparePage.tsx, web-app/src/components/BenefitCards.tsx, web-app/src/components/TrustedBy.tsx | LOW | grep confirms each named false claim is gone (version bumped to current, MIT replaced with BUSL-1.1, Gemini removed, gate count corrected to 8, invented testimonial line removed) | released@2026-09-27T15:00Z | Merged 7ad546a7, clean cherry-pick, direct Captain review (LOW tier, pure copy diff, verified against VERSION/LICENSE/CLAUDE.md source of truth). TrustedBy.tsx reviewed and left unchanged (no fabricated content found). BenefitCards.tsx's Gemini removal also dropped it from Multi-AI copy (not just the gate count). Follow-ups flagged, not filed as new backlog yet: SettingsPage.tsx build date still hardcoded (2026-03-24, out of scope for a copy-only slice since deriving it live is a logic change); PROVIDERS array still lists Gemini as active (behavior, not copy); DocsSidebar.tsx/ContextualHelp.tsx/CostEstimator.tsx/ProjectWorkspace.tsx/SystemSettingsPage.tsx also reference Gemini or stale gate counts, out of this slice's file set; WhatsNew.tsx/Footer.tsx versions are not in CLAUDE.md's release version-bump checklist so will drift stale again next release. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
71
71
  | S-52 | BACKLOG 122: receipt field `first_result_verified_patch` is True for any first code change, naming a verification that did not run | autonomy/lib/proof-generator.py (the named field only) | LOW | field is renamed additively (`first_result_kind` already exists) or set only from an actually-verified result, with a test; no consumer of the old field silently breaks | released@2026-09-27T15:00Z | Direct fix chosen over additive rename (advisor-caught: a new field would duplicate first_result_kind byte-for-byte, since no producer anywhere ever sets this field True). Full consumer survey done; found and fixed a real bug the fix would otherwise have caused (loki-overview.js's "Plan only" label, repointed at first_result_kind). Merged 0380ad6f, 21/21 + 11/11 reconfirmed on main. Direct Captain review (LOW tier). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
72
72
  | S-53 | BACKLOG 138 fix direction: trusted git push/PR calls should ignore agent-controlled hooks/config (planted pre-push hook, credential.helper, core.fsmonitor, core.sshCommand can see GH_TOKEN during Loki's own trusted push) | autonomy/run.sh (create_session_pr / the trusted push call sites only, not the withhold function itself which S-18/BACKLOG-149's rework owns) | HIGH | red: a planted `.git/hooks/pre-push` sees GH_TOKEN during Loki's trusted push (reproduce reviewer 3's GF-3 finding); green: the trusted push explicitly neutralizes hooksPath/credential.helper/sshCommand for that one invocation, hook sees nothing | parked@2026-09-27T17:14Z | Sequencing note: wait for S-18/BACKLOG 149's rework to land first (touches nearby withhold/re-grant code in the same file); rebase onto that before starting to avoid a conflict. Do not touch the withhold function itself, only the push-call invocation. Delivered by S-18 round 5 (trusted push from a fresh temp repo; the agent repo config is never loaded with credentials). |
@@ -148,28 +148,28 @@ set is declared to avoid overlap with those and with each other.
148
148
  | S-129 | BACKLOG 93: hard-deadline zero-exit leader waits only 0.2s for the PID file | tests/test-hard-deadline-confinement.sh | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | released@2026-09-27T18:12Z | Batch 2, dispatched 17:14. Train 4, pushed 08e4a7d4 at 17:48:38Z (ls-remote verified); approved by review (1/1; HIGH for S-116). P2.council-inconclusive-cannot-exit-zero removed from pending.txt (proven). Quarantine list now empty. Released in v9.66.0 (release commit 0a69d19b, pushed 18:03:32Z). |
149
149
  | S-130 | BACKLOG 117: SettingsPage lists deprecated Gemini and a hardcoded build date | web-app/src/pages/SettingsPage.tsx | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | released@2026-09-27T18:12Z | Batch 2, dispatched 17:14. Train 5, pushed 51ae52fe at 17:52:16Z (ls-remote verified); approved by review. S-88: P9 4/4 in 43s (was about 90s). S-130: web-app dist rebuilt. S-111: pytest -n auto back on after S-102. Released in v9.66.0 (release commit 0a69d19b, pushed 18:03:32Z). |
150
150
  | S-131 | BACKLOG 106 (Bun): budget warns when capped and spend is unmeasured | loki-ts/src/runner/budget.ts, loki-ts/tests/runner/budget.test.ts | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | released@2026-09-27T17:53Z | Batch 2, dispatched 17:14; CEO note: warn-never-pause default. In v9.65.0 (release commit 0103adfa, pushed 17:45:33Z; required-ci success). |
151
- | S-132 | Velocity: skip heavy Tests jobs on a version-bump-only commit whose parent Tests run succeeded (eligibility no looser than release.yml STEP 1) | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | HIGH | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T18:37Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). |
151
+ | S-132 | Velocity: skip heavy Tests jobs on a version-bump-only commit whose parent Tests run succeeded (eligibility no looser than release.yml STEP 1) | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | HIGH | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE (HIGH); cherry-picked 7b328b1f+c50efd15 into train 9, main a39c4995 pushed 19:06:25 (`git ls-remote origin refs/heads/main` = a39c4995). Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
152
152
  | S-133 | Velocity: release.yml required-ci poll 30s to 10s; fix stale publish-npm comment | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T18:55Z | Batch 4 (build then review), dispatched 18:17. Review APPROVE; train 7 pushed aada49d8 (main b7a8dd50 at 18:45:14Z, ls-remote verified). In v9.68.0 (release commit 8d17be2b, pushed 18:54:35Z); released when publish-npm succeeds. |
153
- | S-134 | Velocity: rebuild shard-durations.tsv from a recent successful run; drift test | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T18:37Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). |
154
- | S-135 | Velocity: parallelize trust-core probe mutations (130s) | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | ready@2026-09-27T18:47Z | Batch 4 (build then review), dispatched 18:17. Blocked as scoped: probe_case mutates the shared repo in place (50 of 91 sites target autonomy/run.sh); reviewer reproduced the race. Re-scope: a private repo copy per worker plus a target override. |
155
- | S-136 | Velocity: tests/test-select-tests.sh under 30s, same 38 cases | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T18:55Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). 7fc63d5b REJECT (mapfile crashes under /bin/bash 3.2); rework dispatched 18:53. |
156
- | S-137 | S-81 follow-up: shard-coverage T4 enumerates the real runner | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T18:37Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). |
157
- | S-138 | GUARDS 12: lint so test fixtures never write the real ~/.gitconfig | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T18:47Z | Batch 4 (build then review), dispatched 18:17. 849b655e review REJECT; rework pending. |
158
- | S-139 | GUARDS 13 + BACKLOG 136: RELEASED_AHEAD_OF_NPM; UNKNOWN on tag/npm disagreement | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T18:37Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). |
159
- | S-140 | BACKLOG 103: jest "Test Suites N failed" / vitest "Test Files N failed" count as failures | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | review@2026-09-27T18:47Z | Batch 4 (build then review), dispatched 18:17. Built 6dbfc1e6; review pending. |
160
- | S-141 | S-49 follow-up: remaining council readers (~1425, ~1564, ~4232) use -I -S | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | HIGH | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T18:37Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). |
161
- | S-142 | S-48 follow-up: convergence-floor NEGATIVE-C for the runner guard | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T18:37Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). |
162
- | S-143 | BACKLOG 117: drop Gemini/Railway/stale gate counts from 6 web-app files | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T18:37Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). |
153
+ | S-134 | Velocity: rebuild shard-durations.tsv from a recent successful run; drift test | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; abe6a7ae into train 9 (a39c4995). Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
154
+ | S-135 | Velocity: parallelize trust-core probe mutations (130s) | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T19:10Z | Batch 4 (build then review), dispatched 18:17. Blocked as scoped: probe_case mutates the shared repo in place (50 of 91 sites target autonomy/run.sh); reviewer reproduced the race. Re-scope: a private repo copy per worker plus a target override. Batch 5 build, re-scoped to a private repo copy per worker (wf_38d4e17c-211). |
155
+ | S-136 | Velocity: tests/test-select-tests.sh under 30s, same 38 cases | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). 7fc63d5b REJECT (mapfile crashes under /bin/bash 3.2); rework dispatched 18:53. cafbf57c re-review APPROVE (38/38 under /bin/bash 3.2, 25.6s); lands after the release 10 bump. Note: two builders converged on the same fix. 7fc63d5b+cafbf57c onto main b61045fd pushed 19:19:39 (`/bin/bash tests/test-select-tests.sh` = 38 passed, 0 failed, 33.6s). Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
156
+ | S-137 | S-81 follow-up: shard-coverage T4 enumerates the real runner | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; 4107e16f into train 9 (a39c4995). Fix-forward 6e48decb: T4 unsharded run inherited LOKI_TEST_SHARD in CI (Tests run 36343130286 shard 7/8: "unsharded real run selected 41 of 564"); `LOKI_TEST_SHARD=6/8 bash tests/test-shard-coverage.sh` 18/1 before, 19/0 after. Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
157
+ | S-138 | GUARDS 12: lint so test fixtures never write the real ~/.gitconfig | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T19:10Z | Batch 4 (build then review), dispatched 18:17. 849b655e review REJECT; rework pending. 2f29ad49 re-review REJECT (2nd); rework in batch 5 (wf_38d4e17c-211). |
158
+ | S-139 | GUARDS 13 + BACKLOG 136: RELEASED_AHEAD_OF_NPM; UNKNOWN on tag/npm disagreement | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; 28d18393 onto main 06bf5406 pushed 19:08:09. Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
159
+ | S-140 | BACKLOG 103: jest "Test Suites N failed" / vitest "Test Files N failed" count as failures | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Built 6dbfc1e6; review pending. Review APPROVE; 6dbfc1e6 onto main e952e1ae pushed 19:09:04. Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
160
+ | S-141 | S-49 follow-up: remaining council readers (~1425, ~1564, ~4232) use -I -S | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | HIGH | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE (HIGH); 001576f3+958f6548 onto main 06bf5406 pushed 19:08:09. Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
161
+ | S-142 | S-48 follow-up: convergence-floor NEGATIVE-C for the runner guard | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; 59e32d75 into train 9 (a39c4995). Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
162
+ | S-143 | BACKLOG 117: drop Gemini/Railway/stale gate counts from 6 web-app files | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; 6f901f91 into train 9 (a39c4995). Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
163
163
  | S-144 | Footer.tsx version joins release.sh --bump-only | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T18:55Z | Batch 4 (build then review), dispatched 18:17. Review APPROVE; train 7 pushed edb706ed (main b7a8dd50 at 18:45:14Z, ls-remote verified). In v9.68.0 (release commit 8d17be2b, pushed 18:54:35Z); released when publish-npm succeeds. |
164
164
  | S-145 | BACKLOG 118: GET /api/checklist/waivers returns 500 on a corrupt file | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T18:55Z | Batch 4 (build then review), dispatched 18:17. Review APPROVE; train 7 pushed 2ef38a2f (main b7a8dd50 at 18:45:14Z, ls-remote verified). In v9.68.0 (release commit 8d17be2b, pushed 18:54:35Z); released when publish-npm succeeds. |
165
- | S-146 | BACKLOG 118: one id="budget-banner" in the dashboard build | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T18:37Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). |
166
- | S-147 | BACKLOG 118: loki metrics --json reports null for unmeasured, no invented time_saved | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T18:37Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). |
167
- | S-148 | BACKLOG 118: trust.html says "Not enough history yet" when every axis is insufficient | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | merged@2026-09-27T18:55Z | Batch 4 (build then review), dispatched 18:17. Built 92c0f9d8; review pending. Review APPROVE; cherry-picked for train 8. |
165
+ | S-146 | BACKLOG 118: one id="budget-banner" in the dashboard build | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T19:10Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). 569e8cf4 review CONCERN; rework in batch 5 (wf_38d4e17c-211). |
166
+ | S-147 | BACKLOG 118: loki metrics --json reports null for unmeasured, no invented time_saved | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T19:10Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). f82eeda0 review CONCERN; rework in batch 5 (wf_38d4e17c-211). |
167
+ | S-148 | BACKLOG 118: trust.html says "Not enough history yet" when every axis is insufficient | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:05Z | Batch 4 (build then review), dispatched 18:17. Built 92c0f9d8; review pending. Review APPROVE; cherry-picked for train 8. Released in v9.69.0 (b2444763, `git ls-remote origin refs/tags/v9.69.0^{}` = b2444763). |
168
168
  | S-149 | BACKLOG 118: prompt_optimizer never-ran vs corrupt markers | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T18:55Z | Batch 4 (build then review), dispatched 18:17. Review APPROVE; train 7 pushed 06eea9ea (main b7a8dd50 at 18:45:14Z, ls-remote verified). In v9.68.0 (release commit 8d17be2b, pushed 18:54:35Z); released when publish-npm succeeds. |
169
169
  | S-150 | BACKLOG 118: migration progress null (not 0/0) on a corrupt/missing file | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T18:55Z | Batch 4 (build then review), dispatched 18:17. Review APPROVE; train 7 pushed b7a8dd50 (main b7a8dd50 at 18:45:14Z, ls-remote verified). In v9.68.0 (release commit 8d17be2b, pushed 18:54:35Z); released when publish-npm succeeds. |
170
- | S-151 | BACKLOG 118: analytics heatmap shows no-data before the activity window | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T18:37Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). |
171
- | S-152 | Incident guard: only the Chief of Staff pushes main. A worktree agent pushed 28926937 at 18:35Z. Block `git push` and any commit on main from inside .claude/worktrees (guard hook or a pre-push check in .githooks/pre-push that refuses unless LOKI_RELEASE_MANAGER=1 is set by the orchestrator) | scripts/v10-guard.sh and/or .githooks/pre-push, tests | HIGH | a push from a worktree path is refused with a clear reason; the orchestrator push with the marker still works; fixture per case | ready@2026-09-27T18:36Z | Evidence: `git log -1 28926937` author asklokesh 14:35:11; `git ls-remote origin refs/heads/main` = 28926937. |
172
- | S-153 | Release reuse: add web-app/src/components/Footer.tsx to release.yml required-ci ALLOWLIST with the same version-only compare, so a version-bump commit that now rewrites the Footer (S-144) can still reuse its parent verdict; also rebuild web-app/dist on --bump-only so the shipped footer shows the version | .github/workflows/release.yml (ALLOWLIST), scripts/release.sh, tests/test_release_required_ci.py | HIGH | a bump touching only allowlisted files incl. Footer.tsx is eligible; a Footer change beyond the version string is not; replay of 8d17be2b is eligible | ready@2026-09-27T18:55Z | Evidence: v9.68.0 bump 8d17be2b touches Footer.tsx (git show --stat 8d17be2b). |
170
+ | S-151 | BACKLOG 118: analytics heatmap shows no-data before the activity window | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; 97f8b6c5 into train 9 (a39c4995). Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
171
+ | S-152 | Incident guard: only the Chief of Staff pushes main. A worktree agent pushed 28926937 at 18:35Z. Block `git push` and any commit on main from inside .claude/worktrees (guard hook or a pre-push check in .githooks/pre-push that refuses unless LOKI_RELEASE_MANAGER=1 is set by the orchestrator) | scripts/v10-guard.sh and/or .githooks/pre-push, tests | HIGH | a push from a worktree path is refused with a clear reason; the orchestrator push with the marker still works; fixture per case | building@2026-09-27T19:10Z | Evidence: `git log -1 28926937` author asklokesh 14:35:11; `git ls-remote origin refs/heads/main` = 28926937. f02bcbde review CONCERN (no allowed non-main case); rework in batch 5 (wf_38d4e17c-211). |
172
+ | S-153 | Release reuse: add web-app/src/components/Footer.tsx to release.yml required-ci ALLOWLIST with the same version-only compare, so a version-bump commit that now rewrites the Footer (S-144) can still reuse its parent verdict; also rebuild web-app/dist on --bump-only so the shipped footer shows the version | .github/workflows/release.yml (ALLOWLIST), scripts/release.sh, tests/test_release_required_ci.py | HIGH | a bump touching only allowlisted files incl. Footer.tsx is eligible; a Footer change beyond the version string is not; replay of 8d17be2b is eligible | building@2026-09-27T19:10Z | Evidence: v9.68.0 bump 8d17be2b touches Footer.tsx (git show --stat 8d17be2b). Batch 5 build (wf_38d4e17c-211). |
173
173
  | S-01 | BACKLOG 22: orphaned `sleep 300` resource monitor | autonomy/run.sh (resource-monitor spawn/cleanup only, not kill_provider_child), one new test | MEDIUM | red: `loki start` then interrupt leaves a `sleep 300` orphan (ps shows it after exit); green: it is reaped or never orphaned, by PID recorded at spawn | released@2026-09-27T01:33Z | 027ec085 confirmed ancestor of origin/main; note corrected, was stale. |
174
174
  | S-02 | BACKLOG 23: client-route test hardcodes main checkout path | tests/lib-extract-client-paths.mjs, tests/lib-match-client-routes.py, tests/test-verify-client-routes.sh | LOW | released@2026-09-27T15:00Z | 1/1 APPROVE: reviewer reproduced from 2 independent real worktrees, mutation-tested both new WORKTREE GUARD assertions independently, confirmed the disclosed BACKLOG 137 interaction (P7's own sed-workaround breaking) is expected, not a surprise. **Merged to main.** S-39/BACKLOG 137 now unblocked -- but note: this merge makes `tests/moat/run.sh` read a live FAIL on `P7.webapp-client-routes-exist` until S-39 lands (an unlisted-in-pending.txt regression per the ratchet), since P7's own copy-and-sed workaround can no longer find the literal it targets. S-39 should be prioritized promptly to close this gap, or a temporary pending.txt entry considered if S-39 doesn't land quickly. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
175
175
  | S-03 | BACKLOG 25: `loki ci --report` "Argument list too long" on a large diff | autonomy/loki (cmd_ci report path only), one new test | MEDIUM | red: a synthetic diff over the ARG_MAX threshold, exit 126; green: same diff passed via stdin/file, exit 0 | rejected@2026-09-27T01:33Z | Real crash site (export-based ARG_MAX) misdiagnosed and left unfixed; sent back to builder. |
package/docs/v10/TODO.md CHANGED
@@ -7,37 +7,27 @@ docs/v10/BOARD.md; this file is the per-person view.
7
7
 
8
8
  Target: 3-5 releases per hour (CEO 2026-09-27 17:05Z), 60 per day.
9
9
 
10
- ## Chief of Staff (orchestrator)
11
-
12
- 1. [done 17:05:02Z] Release v9.63.0 from green tree 1bc02bce (release.sh --bump-only guard passed; tag and main pushed, ls-remote verified).
13
- 2. [pending] Confirm v9.63.0 publish-npm success (Release run 36335603628).
14
- 3. [pending] Release 2: cc105687 (S-104 cache + S-109 violations) -> Tests green -> release.sh --bump-only -> push + tag.
15
- 4. [pending] Release 3: next green content push (batch-1 slices as each is approved).
16
- 5. [running] Keep 10+ builders busy: batch-1 pipeline (S-30, S-88, S-94, S-96, S-99, S-100, S-105, S-106, S-110, S-111), each build then review.
17
- 6. [running] Architect cutting S-112..S-131 to keep the ready queue at 2x builders.
18
- 7. [pending] Cherry-pick each approved slice onto main within the same turn it is approved; push content immediately (Tests start at once).
19
- 8. [pending] Every green main SHA with unreleased code gets a --bump-only release; never bump on red (D28).
10
+ ## Chief of Staff (orchestrator), 19:10Z
11
+
12
+ 1. [done 19:05:43Z] Release v9.69.0 from green 7ef5ca28 (main and tag both b2444763 by ls-remote).
13
+ 2. [done] v9.68.0 on npm (`npm view loki-mode version` = 9.68.0; Release run 36342384478 success).
14
+ 3. [done] v9.69.0 on npm (`npm view loki-mode version` = 9.69.0).
15
+ 4. [done 19:06-19:09Z] Train 9 content: S-132, S-134, S-137, S-142, S-143, S-151 (a39c4995), S-139, S-141 (06bf5406), S-140 (e952e1ae).
16
+ 5. [done 19:28:09Z] Release 10 = v9.70.0 from green b61045fd (main and tag 6c459dfa by ls-remote).
17
+ 6. [done 19:19Z] S-136 landed (b61045fd); S-137 fix-forward 6e48decb.
18
+ 7. [running] Batch 5 (wf_38d4e17c-211): reworks S-138, S-146, S-147, S-152; builds S-50, S-153, S-135; Architect cut S-154..S-173.
19
+ 8. [pending] Prune each worktree once its slice is merged (count now 7 of 15).
20
20
  9. [pending] Drift audit every 6 turns; guard review every 50 turns.
21
21
 
22
- ## Release cadence loop (the mechanism for 3-5 per hour)
23
-
24
- - Content push: every approved slice lands on main as soon as it is approved (no batching wait).
25
- - Tier B (Tests, about 6-15 min with 8 shards) runs per SHA; nothing is cancelled on main (S-80).
26
- - As soon as any main SHA with unreleased code is green: `bash scripts/release.sh minor --bump-only`, commit, tag, push. The bump reuses the parent's verdict (S-84), so publish follows in minutes.
27
- - Pipelined: content N+1 is in Tier B while release N publishes.
28
-
29
22
  ## Team members
30
23
 
31
24
  | Agent | Slice | Role | TODO |
32
25
  |---|---|---|---|
33
- | Engineer | S-30 | P7 ternary-null bypass | build, red/green, mutate, commit; then Tech Lead review |
34
- | Engineer | S-88 | parallelize moat P5/P6/P9 | measure before/after, identical CASE lines, commit; then review |
35
- | Engineer | S-94 | WORKTREE_COUNT pulse violation | fixtures 15/16, commit; then review |
36
- | Engineer | S-96 | Tier A caches + 10-commit METRICS table | commit; then review |
37
- | Engineer | S-99 | guard follow-ups (4 fixes) | fixtures per repro, commit; then review |
38
- | Engineer (opus) | S-100 | refuse the repo default branch in trusted push | test develop/feature, commit; then HIGH review |
39
- | Engineer (opus) | S-105 | release.yml tag step: reuse a pre-pushed tag, fail loudly otherwise | stub-driven test, commit; then HIGH review |
40
- | Engineer | S-106 | runtime-gate port race, unquarantine | 20/20 in capped Linux, commit; then review |
41
- | Engineer | S-110 | fix the 3 suites S-93 registered, unquarantine | per-suite root cause, commit; then review |
42
- | Engineer | S-111 | bring back pytest -n auto after proving S-102 | 10 runs 0 failures in capped container, then test.yml; then review |
43
- | Architect (opus) | S-112..S-131 | cut 20 ready slices | read-only; returns 20 BOARD rows |
26
+ | Engineer (opus) | S-152 | pre-push: only the Release Manager pushes main | add allowed non-main case, fix commit message; then HIGH re-review |
27
+ | Engineer | S-146 | one id="budget-banner" in the dashboard build | fix review CONCERN, rebuild static; then re-review |
28
+ | Engineer | S-147 | loki metrics --json nulls for unmeasured values | fix review CONCERN; then re-review |
29
+ | Engineer | S-138 | lint: fixtures never write the real ~/.gitconfig | fix 2nd REJECT findings; then re-review |
30
+ | Engineer | S-50 | P7 sed workaround vs dynamic repo root | build, red/green, mutate; then review |
31
+ | Engineer (opus) | S-153 | Footer.tsx on the release reuse allowlist | stub test reuse/no-reuse; then HIGH review |
32
+ | Engineer | S-135 | parallel trust-core probe mutations, private copy per worker | before/after wall time, same CASE lines; then review |
33
+ | Architect (opus) | S-154..S-173 | cut 20 ready slices | read-only; returns 20 BOARD rows |
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- var at=Object.create;var{getPrototypeOf:ot,defineProperty:OG,getOwnPropertyNames:st}=Object;var nt=Object.prototype.hasOwnProperty;function rt($){return this[$]}var tt,et,$e=($,X,Q)=>{var z=$!=null&&typeof $==="object";if(z){var Z=X?tt??=new WeakMap:et??=new WeakMap,K=Z.get($);if(K)return K}Q=$!=null?at(ot($)):{};let J=X||!$||!$.__esModule?OG(Q,"default",{value:$,enumerable:!0}):Q;for(let q of st($))if(!nt.call(J,q))OG(J,q,{get:rt.bind($,q),enumerable:!0});if(z)Z.set($,J);return J};var Zq=($,X)=>()=>(X||$((X={exports:{}}).exports,X),X.exports);var Xe=($)=>$;function Qe($,X){this[$]=Xe.bind(null,X)}var B1=($,X)=>{for(var Q in X)OG($,Q,{get:X[Q],enumerable:!0,configurable:!0,set:Qe.bind(X,Q)})};var s=($,X)=>()=>($&&(X=$($=0)),X);var w5=import.meta.require;var WR={};B1(WR,{lokiDir:()=>h0,homeLokiDir:()=>GQ,findRepoRootForVersion:()=>LG,REPO_ROOT:()=>O1});import{resolve as h2,dirname as jG}from"path";import{fileURLToPath as ze}from"url";import{existsSync as Kq}from"fs";import{homedir as Ze}from"os";function Ke(){let $=HR;for(let X=0;X<6;X++){if(Kq(h2($,"VERSION"))&&Kq(h2($,"autonomy/run.sh")))return $;let Q=jG($);if(Q===$)break;$=Q}return h2(HR,"..","..","..")}function LG($){let X=$;for(let Q=0;Q<6;Q++){if(Kq(h2(X,"VERSION"))&&Kq(h2(X,"autonomy/run.sh")))return X;let z=jG(X);if(z===X)break;X=z}return h2($,"..","..","..")}function h0(){return process.env.LOKI_DIR??h2(process.cwd(),".loki")}function GQ(){return h2(Ze(),".loki")}var HR,O1;var k1=s(()=>{HR=jG(ze(import.meta.url));O1=Ke()});import{readFileSync as Je}from"fs";import{resolve as qe,dirname as Ve}from"path";import{fileURLToPath as Ye}from"url";function L9(){if(t3!==null)return t3;let $="9.70.0";if(typeof $==="string"&&$.length>0)return t3=$,t3;try{let X=Ve(Ye(import.meta.url)),Q=LG(X);t3=Je(qe(Q,"VERSION"),"utf-8").trim()}catch{t3="unknown"}return t3}var t3=null;var Jq=s(()=>{k1()});var LR={};B1(LR,{runOrThrow:()=>Re,run:()=>X1,readStreamCapped:()=>qq,commandVersion:()=>we,commandExists:()=>g5,ShellError:()=>CG,MAX_STDOUT_BYTES:()=>jR});async function qq($,X=jR){let Q=$.getReader(),z=new TextDecoder,Z="",K=0;try{while(K<X){let{done:J,value:q}=await Q.read();if(J)break;if(!q)continue;if(K+=q.byteLength,K>X){let V=q.byteLength-(K-X);Z+=z.decode(q.subarray(0,V),{stream:!0});break}Z+=z.decode(q,{stream:!0})}Z+=z.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return Z}async function X1($,X={}){let Q=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:X.env?{...process.env,...X.env}:process.env,cwd:X.cwd}),z,Z;if(X.timeoutMs&&X.timeoutMs>0)z=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}Z=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},X.timeoutMs);try{let[K,J,q]=await Promise.all([qq(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:K,stderr:J,exitCode:q}}finally{if(z)clearTimeout(z);if(Z)clearTimeout(Z)}}async function Re($,X={}){let Q=await X1($,X);if(Q.exitCode!==0)throw new CG(`command failed (${Q.exitCode}): ${$.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function g5($){let X=Ie($),Q=await X1(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Ie($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function we($,X="--version"){if(!await g5($))return null;let z=await X1([$,X],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var jR=16777216,CG;var y8=s(()=>{CG=class CG extends Error{message;exitCode;stdout;stderr;constructor($,X,Q,z){super($);this.message=$;this.exitCode=X;this.stdout=Q;this.stderr=z;this.name="ShellError"}}});function g2($){return Pe?"":$}var Pe,p0,$5,Z1,l61,A1,f1,m5,n;var e7=s(()=>{Pe=(process.env.NO_COLOR??"").length>0;p0=g2("\x1B[0;31m"),$5=g2("\x1B[0;32m"),Z1=g2("\x1B[1;33m"),l61=g2("\x1B[0;34m"),A1=g2("\x1B[0;36m"),f1=g2("\x1B[1m"),m5=g2("\x1B[2m"),n=g2("\x1B[0m")});import{existsSync as he}from"fs";async function Z2(){if(BQ!==void 0)return BQ;let $="/opt/homebrew/bin/python3.12";if(he($))return BQ=$,$;let X=await g5("python3.12");if(X)return BQ=X,X;let Q=await g5("python3");return BQ=Q,Q}async function I4($,X={}){let Q=await Z2();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return X1([Q,"-c",$],X)}var BQ;var m2=s(()=>{y8()});var gR={};B1(gR,{runStatus:()=>Y00});import{existsSync as u5,readFileSync as T9,readdirSync as kR,statSync as SR}from"fs";import{resolve as A5,basename as $00}from"path";import{homedir as X00}from"os";function yR($){let X=Math.trunc($);if(X>=1e6)return`${(Math.trunc(X/1e6*10)/10).toFixed(1)}M`;if(X>=1000)return`${(Math.trunc(X/1000*10)/10).toFixed(1)}K`;return String(X)}function bR($,X,Q){if(X===0)return null;let z=Math.trunc($*100/X),Z=Math.trunc($*Yq/X);if(Z>Yq)Z=Yq;let K=Yq-Z,J=$5;if(z>=80)J=p0;else if(z>=50)J=Z1;let q="=".repeat(Math.max(0,Z))+" ".repeat(Math.max(0,K)),V=yR($),Y=yR(X);return` ${f1}${Q}${n} ${J}[${q}]${n} ${z}% (${V} / ${Y})`}async function z00(){if(await g5("jq"))return!0;return process.stdout.write(`${p0}Error: jq is required but not installed.${n}
2
+ var at=Object.create;var{getPrototypeOf:ot,defineProperty:OG,getOwnPropertyNames:st}=Object;var nt=Object.prototype.hasOwnProperty;function rt($){return this[$]}var tt,et,$e=($,X,Q)=>{var z=$!=null&&typeof $==="object";if(z){var Z=X?tt??=new WeakMap:et??=new WeakMap,K=Z.get($);if(K)return K}Q=$!=null?at(ot($)):{};let J=X||!$||!$.__esModule?OG(Q,"default",{value:$,enumerable:!0}):Q;for(let q of st($))if(!nt.call(J,q))OG(J,q,{get:rt.bind($,q),enumerable:!0});if(z)Z.set($,J);return J};var Zq=($,X)=>()=>(X||$((X={exports:{}}).exports,X),X.exports);var Xe=($)=>$;function Qe($,X){this[$]=Xe.bind(null,X)}var B1=($,X)=>{for(var Q in X)OG($,Q,{get:X[Q],enumerable:!0,configurable:!0,set:Qe.bind(X,Q)})};var s=($,X)=>()=>($&&(X=$($=0)),X);var w5=import.meta.require;var WR={};B1(WR,{lokiDir:()=>h0,homeLokiDir:()=>GQ,findRepoRootForVersion:()=>LG,REPO_ROOT:()=>O1});import{resolve as h2,dirname as jG}from"path";import{fileURLToPath as ze}from"url";import{existsSync as Kq}from"fs";import{homedir as Ze}from"os";function Ke(){let $=HR;for(let X=0;X<6;X++){if(Kq(h2($,"VERSION"))&&Kq(h2($,"autonomy/run.sh")))return $;let Q=jG($);if(Q===$)break;$=Q}return h2(HR,"..","..","..")}function LG($){let X=$;for(let Q=0;Q<6;Q++){if(Kq(h2(X,"VERSION"))&&Kq(h2(X,"autonomy/run.sh")))return X;let z=jG(X);if(z===X)break;X=z}return h2($,"..","..","..")}function h0(){return process.env.LOKI_DIR??h2(process.cwd(),".loki")}function GQ(){return h2(Ze(),".loki")}var HR,O1;var k1=s(()=>{HR=jG(ze(import.meta.url));O1=Ke()});import{readFileSync as Je}from"fs";import{resolve as qe,dirname as Ve}from"path";import{fileURLToPath as Ye}from"url";function L9(){if(t3!==null)return t3;let $="9.71.0";if(typeof $==="string"&&$.length>0)return t3=$,t3;try{let X=Ve(Ye(import.meta.url)),Q=LG(X);t3=Je(qe(Q,"VERSION"),"utf-8").trim()}catch{t3="unknown"}return t3}var t3=null;var Jq=s(()=>{k1()});var LR={};B1(LR,{runOrThrow:()=>Re,run:()=>X1,readStreamCapped:()=>qq,commandVersion:()=>we,commandExists:()=>g5,ShellError:()=>CG,MAX_STDOUT_BYTES:()=>jR});async function qq($,X=jR){let Q=$.getReader(),z=new TextDecoder,Z="",K=0;try{while(K<X){let{done:J,value:q}=await Q.read();if(J)break;if(!q)continue;if(K+=q.byteLength,K>X){let V=q.byteLength-(K-X);Z+=z.decode(q.subarray(0,V),{stream:!0});break}Z+=z.decode(q,{stream:!0})}Z+=z.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return Z}async function X1($,X={}){let Q=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:X.env?{...process.env,...X.env}:process.env,cwd:X.cwd}),z,Z;if(X.timeoutMs&&X.timeoutMs>0)z=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}Z=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},X.timeoutMs);try{let[K,J,q]=await Promise.all([qq(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:K,stderr:J,exitCode:q}}finally{if(z)clearTimeout(z);if(Z)clearTimeout(Z)}}async function Re($,X={}){let Q=await X1($,X);if(Q.exitCode!==0)throw new CG(`command failed (${Q.exitCode}): ${$.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function g5($){let X=Ie($),Q=await X1(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Ie($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function we($,X="--version"){if(!await g5($))return null;let z=await X1([$,X],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var jR=16777216,CG;var y8=s(()=>{CG=class CG extends Error{message;exitCode;stdout;stderr;constructor($,X,Q,z){super($);this.message=$;this.exitCode=X;this.stdout=Q;this.stderr=z;this.name="ShellError"}}});function g2($){return Pe?"":$}var Pe,p0,$5,Z1,l61,A1,f1,m5,n;var e7=s(()=>{Pe=(process.env.NO_COLOR??"").length>0;p0=g2("\x1B[0;31m"),$5=g2("\x1B[0;32m"),Z1=g2("\x1B[1;33m"),l61=g2("\x1B[0;34m"),A1=g2("\x1B[0;36m"),f1=g2("\x1B[1m"),m5=g2("\x1B[2m"),n=g2("\x1B[0m")});import{existsSync as he}from"fs";async function Z2(){if(BQ!==void 0)return BQ;let $="/opt/homebrew/bin/python3.12";if(he($))return BQ=$,$;let X=await g5("python3.12");if(X)return BQ=X,X;let Q=await g5("python3");return BQ=Q,Q}async function I4($,X={}){let Q=await Z2();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return X1([Q,"-c",$],X)}var BQ;var m2=s(()=>{y8()});var gR={};B1(gR,{runStatus:()=>Y00});import{existsSync as u5,readFileSync as T9,readdirSync as kR,statSync as SR}from"fs";import{resolve as A5,basename as $00}from"path";import{homedir as X00}from"os";function yR($){let X=Math.trunc($);if(X>=1e6)return`${(Math.trunc(X/1e6*10)/10).toFixed(1)}M`;if(X>=1000)return`${(Math.trunc(X/1000*10)/10).toFixed(1)}K`;return String(X)}function bR($,X,Q){if(X===0)return null;let z=Math.trunc($*100/X),Z=Math.trunc($*Yq/X);if(Z>Yq)Z=Yq;let K=Yq-Z,J=$5;if(z>=80)J=p0;else if(z>=50)J=Z1;let q="=".repeat(Math.max(0,Z))+" ".repeat(Math.max(0,K)),V=yR($),Y=yR(X);return` ${f1}${Q}${n} ${J}[${q}]${n} ${z}% (${V} / ${Y})`}async function z00(){if(await g5("jq"))return!0;return process.stdout.write(`${p0}Error: jq is required but not installed.${n}
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)
@@ -1349,4 +1349,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
1349
1349
  `),2}case"start":{let{runStart:z}=await Promise.resolve().then(() => (ct(),pt));return z(Q)}default:return process.stderr.write(`Unknown command: ${X}
1350
1350
  `),process.stderr.write(lt),2}}ER();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var w61=await I61(Bun.argv.slice(2));process.exit(w61);
1351
1351
 
1352
- //# debugId=AA74507A8CC8C20F348862A56E8828E6
1352
+ //# debugId=F73C88AAE3F1C113C39D0218FE920A8B
package/mcp/__init__.py CHANGED
@@ -75,4 +75,4 @@ try:
75
75
  except ImportError:
76
76
  __all__ = ['mcp']
77
77
 
78
- __version__ = '9.70.0'
78
+ __version__ = '9.71.0'
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": "9.70.0",
4
+ "version": "9.71.0",
5
5
  "description": "Loki Mode by Autonomi. Autonomous spec-to-product system: takes a PRD, GitHub issue, OpenAPI/JSON/YAML, or one-line brief to a deployed app via the RARV-C closure loop with 8 quality gates. Provider-agnostic (Claude Code, OpenAI Codex, Cline, Aider, opencode).",
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": "9.70.0",
5
+ "version": "9.71.0",
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-B_g2Bx7d.js";import{B as C}from"./Button-D2kvFYYU.js";import{T as $e}from"./trending-up-exKfFhJX.js";import{C as z}from"./clock-HlM-bj2D.js";import{A as Be,U as ue,M as De}from"./Avatar-nQLkS0Rp.js";import{A as J}from"./activity-Bq5K-M3c.js";import{R as pe}from"./refresh-cw-CKKREgGF.js";import{G as ze}from"./globe-D0_Ot9K-.js";import{C as Le}from"./chevron-left-D8SGt8XQ.js";import{C as je}from"./check-BZXFoANt.js";import{D as Y}from"./dollar-sign-CSMVryX2.js";import{U as Te}from"./user-CqHnVcBI.js";import{D as Me}from"./database-CoDXjNPK.js";import{L as Ue}from"./lock-DPU2NDlh.js";import{S as Re}from"./scroll-text-_aTmtYKs.js";import{S as Ie}from"./shield-alert-DZ1ph0ND.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-aYgURGFC.js";import{B as C}from"./Button-mrjJiIzX.js";import{T as $e}from"./trending-up-CC7ghXOa.js";import{C as z}from"./clock-DhrLudbQ.js";import{A as Be,U as ue,M as De}from"./Avatar-DOgXkiA5.js";import{A as J}from"./activity-B6_UNFP3.js";import{R as pe}from"./refresh-cw-6MdZdvHz.js";import{G as ze}from"./globe-DJ8UlFt2.js";import{C as Le}from"./chevron-left-sqTwkCti.js";import{C as je}from"./check-CIlNFVu7.js";import{D as Y}from"./dollar-sign-t0__nc7_.js";import{U as Te}from"./user-AWsEaMJm.js";import{D as Me}from"./database-CFkV71Ae.js";import{L as Ue}from"./lock-JtWoEayV.js";import{S as Re}from"./scroll-text-Xcw2I15b.js";import{S as Ie}from"./shield-alert-Y7birYk_.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-B_g2Bx7d.js";/**
1
+ import{c as l,j as s}from"./index-aYgURGFC.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-B_g2Bx7d.js";import{C as r}from"./clock-HlM-bj2D.js";import{C as a}from"./circle-alert-CHqNb9E5.js";import{C as l}from"./check-BZXFoANt.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-aYgURGFC.js";import{C as r}from"./clock-DhrLudbQ.js";import{C as a}from"./circle-alert-ClR-8eiz.js";import{C as l}from"./check-CIlNFVu7.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-B_g2Bx7d.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-aYgURGFC.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 T,r as l,j as e,G as ye,Q as je,F as Ne,h as we,T as U,Z as Se,a as N,V as Ce,S as Re,Y as Ee,X as Me,P as re,i as $e,g as Te,C as Pe,l as Ae,N as L,J as ze,K as Ie,O as _e,u as Le}from"./index-B_g2Bx7d.js";import{P as K,S as De,E as Fe}from"./ErrorBoundary-twJ6L4yY.js";import{C as Oe,F as He,M as Be,H as qe,a as Ge,G as Ue,T as Ke}from"./thumbs-up-iPq2uWPB.js";import{C as ie}from"./check-BZXFoANt.js";import{C as Ve}from"./clock-HlM-bj2D.js";import{D as We}from"./dollar-sign-CSMVryX2.js";import{U as Qe}from"./upload-JxCmEXS1.js";import{L as V}from"./loader-circle-CVx9e9xb.js";/**
1
+ import{c as T,r as l,j as e,G as ye,Q as je,F as Ne,h as we,T as U,Z as Se,a as N,V as Ce,S as Re,Y as Ee,X as Me,P as re,i as $e,g as Te,C as Pe,l as Ae,N as L,J as ze,K as Ie,O as _e,u as Le}from"./index-aYgURGFC.js";import{P as K,S as De,E as Fe}from"./ErrorBoundary-DrXZPl7W.js";import{C as Oe,F as He,M as Be,H as qe,a as Ge,G as Ue,T as Ke}from"./thumbs-up-B9I1RzAj.js";import{C as ie}from"./check-CIlNFVu7.js";import{C as Ve}from"./clock-DhrLudbQ.js";import{D as We}from"./dollar-sign-t0__nc7_.js";import{U as Qe}from"./upload-Btyqt4Cn.js";import{L as V}from"./loader-circle-CciQSsBx.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-B_g2Bx7d.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-aYgURGFC.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-B_g2Bx7d.js";/**
1
+ import{c as o,r as a,j as e,T as n,h as i,p as c}from"./index-aYgURGFC.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-B_g2Bx7d.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-aYgURGFC.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 _,J as v,N as h,a5 as B,M,l as H}from"./index-B_g2Bx7d.js";import{B as N}from"./Button-D2kvFYYU.js";import{C as y}from"./thumbs-up-iPq2uWPB.js";import{R as S}from"./refresh-cw-CKKREgGF.js";import{C as z}from"./circle-alert-CHqNb9E5.js";import{U as q}from"./user-CqHnVcBI.js";import{L as D}from"./loader-circle-CVx9e9xb.js";import{R as G}from"./rotate-ccw-C_I6h5nb.js";/**
1
+ import{c as $,r as o,a as k,j as e,m as _,J as v,N as h,a5 as B,M,l as H}from"./index-aYgURGFC.js";import{B as N}from"./Button-mrjJiIzX.js";import{C as y}from"./thumbs-up-B9I1RzAj.js";import{R as S}from"./refresh-cw-6MdZdvHz.js";import{C as z}from"./circle-alert-ClR-8eiz.js";import{U as q}from"./user-AWsEaMJm.js";import{L as D}from"./loader-circle-CciQSsBx.js";import{R as G}from"./rotate-ccw-Dcteu0jr.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.