loki-mode 9.80.1 → 10.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +19 -0
  2. package/SKILL.md +2 -2
  3. package/VERSION +1 -1
  4. package/dashboard/__init__.py +1 -1
  5. package/docs/INSTALLATION.md +1 -1
  6. package/docs/v10/BOARD.md +128 -83
  7. package/docs/v10/DECISIONS.md +18 -0
  8. package/docs/v10/GUARDS.md +81 -0
  9. package/docs/v10/GUIDE.md +154 -0
  10. package/docs/v10/METRICS.md +17 -0
  11. package/docs/v10/MODERNIZE.md +399 -0
  12. package/docs/v10/PROGRESS.md +39 -0
  13. package/loki-ts/dist/loki.js +650 -476
  14. package/mcp/__init__.py +1 -1
  15. package/package.json +1 -1
  16. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  17. package/web-app/dist/assets/{AdminPage-Brg7_Lyr.js → AdminPage-D4CK9wZS.js} +1 -1
  18. package/web-app/dist/assets/{Avatar-7nY6uJxD.js → Avatar-BLMuC61x.js} +1 -1
  19. package/web-app/dist/assets/{Badge-Cbf2CTvW.js → Badge-kDgO8yAn.js} +1 -1
  20. package/web-app/dist/assets/{Button-CvKmf9hm.js → Button-CxzS2jHa.js} +1 -1
  21. package/web-app/dist/assets/{CockpitPage-wLAuI5UQ.js → CockpitPage-CKfKewh2.js} +1 -1
  22. package/web-app/dist/assets/{ComparePage-CMdzzTeh.js → ComparePage-InmGOS5C.js} +1 -1
  23. package/web-app/dist/assets/{ErrorBoundary-CAIYBXBt.js → ErrorBoundary-tMR2rRSK.js} +1 -1
  24. package/web-app/dist/assets/{EvidenceReceiptPanel-BnrDrzRA.js → EvidenceReceiptPanel-CbbMSEPA.js} +1 -1
  25. package/web-app/dist/assets/{GitHubIssuesPanel-CnWx9CiK.js → GitHubIssuesPanel-BpdPk3B6.js} +1 -1
  26. package/web-app/dist/assets/{GitHubPRsPanel-y8gYUjnH.js → GitHubPRsPanel-DkWNIYXl.js} +1 -1
  27. package/web-app/dist/assets/{HomePage-CqaADKqJ.js → HomePage-CnNit9F3.js} +2 -2
  28. package/web-app/dist/assets/{LoginPage-C4-UpzUT.js → LoginPage-CqshUuFx.js} +1 -1
  29. package/web-app/dist/assets/{MagicPage-CQ7UMIwO.js → MagicPage-DuYwXDLp.js} +1 -1
  30. package/web-app/dist/assets/{MetricsPage-nGehSAp4.js → MetricsPage-DSHxYTg1.js} +1 -1
  31. package/web-app/dist/assets/{NotFoundPage-EkC6K3N-.js → NotFoundPage-BCbJ-HOF.js} +1 -1
  32. package/web-app/dist/assets/{ProjectPage-Cdjs0beW.js → ProjectPage-B1Re9Huw.js} +3 -3
  33. package/web-app/dist/assets/{ProjectsPage-CHcSeyxO.js → ProjectsPage-Cirblyo8.js} +1 -1
  34. package/web-app/dist/assets/{SettingsPage-DDhw0s6W.js → SettingsPage-BZ7q23EF.js} +1 -1
  35. package/web-app/dist/assets/{ShowcasePage-BBxQDg5j.js → ShowcasePage-DSTIjCnB.js} +1 -1
  36. package/web-app/dist/assets/{SystemSettingsPage-Aj91V7Zy.js → SystemSettingsPage-CATfA96_.js} +1 -1
  37. package/web-app/dist/assets/{TeamsPage-H10Qp1fu.js → TeamsPage-CIaF0o9W.js} +1 -1
  38. package/web-app/dist/assets/{TemplatesPage-AcxgsKwZ.js → TemplatesPage-ShWJo0m9.js} +1 -1
  39. package/web-app/dist/assets/{TerminalOutput-O6dQA9Qa.js → TerminalOutput-CcQrj1_2.js} +1 -1
  40. package/web-app/dist/assets/{activity-CMnBtTxM.js → activity-BVtnBEfY.js} +1 -1
  41. package/web-app/dist/assets/{bell-Dseaifqw.js → bell-DBu1CFm4.js} +1 -1
  42. package/web-app/dist/assets/{bot-Bm_xcawB.js → bot-6ZTuUUMp.js} +1 -1
  43. package/web-app/dist/assets/{check-TXNSTOop.js → check-CVN-gaNx.js} +1 -1
  44. package/web-app/dist/assets/{chevron-left-D35Mb_-x.js → chevron-left-Bijd73Wy.js} +1 -1
  45. package/web-app/dist/assets/{circle-alert-Rt6AMJ2V.js → circle-alert-BMHFcde6.js} +1 -1
  46. package/web-app/dist/assets/{clock-Dlc0SEVv.js → clock-6bIhCQRV.js} +1 -1
  47. package/web-app/dist/assets/{cloud-DPd4GLS2.js → cloud-qjV89QLm.js} +1 -1
  48. package/web-app/dist/assets/{code-xml-B_scyMd5.js → code-xml-eXgie64_.js} +1 -1
  49. package/web-app/dist/assets/{database-DuPEBXUA.js → database-CVdvn1bh.js} +1 -1
  50. package/web-app/dist/assets/{dollar-sign-C49nrBOI.js → dollar-sign-Bj8njgBH.js} +1 -1
  51. package/web-app/dist/assets/{file-code-corner-B3wt8I4V.js → file-code-corner-EQhoe2_C.js} +1 -1
  52. package/web-app/dist/assets/{file-plus-CuHHSDVU.js → file-plus-BgbVRLTy.js} +1 -1
  53. package/web-app/dist/assets/{globe-Kl77FTuJ.js → globe-CXt7geT_.js} +1 -1
  54. package/web-app/dist/assets/{hammer-D0LLVOf5.js → hammer-CG25oMdn.js} +1 -1
  55. package/web-app/dist/assets/{index-ufh2YvPO.js → index-CVNF29Aq.js} +2 -2
  56. package/web-app/dist/assets/{layers-C3vb5zor.js → layers-DtbE1x2T.js} +1 -1
  57. package/web-app/dist/assets/{loader-circle-BfFuGacT.js → loader-circle-BUSbPfxc.js} +1 -1
  58. package/web-app/dist/assets/{lock-CicpAGtr.js → lock-DwgGTz0p.js} +1 -1
  59. package/web-app/dist/assets/{package-Bw8snKHr.js → package-BbZAXa7s.js} +1 -1
  60. package/web-app/dist/assets/{plus-KXZkO61K.js → plus-OYQ2xEFD.js} +1 -1
  61. package/web-app/dist/assets/{refresh-cw-CshUF54x.js → refresh-cw-lx_MQBsW.js} +1 -1
  62. package/web-app/dist/assets/{rotate-ccw-S9JJTBcV.js → rotate-ccw-DbqbQvZd.js} +1 -1
  63. package/web-app/dist/assets/{scroll-text-CLOq2Mvg.js → scroll-text-BGZMcNSM.js} +1 -1
  64. package/web-app/dist/assets/{server-ClM4a2Wx.js → server-CECrh_vY.js} +1 -1
  65. package/web-app/dist/assets/{shield-alert-DXhyR0S_.js → shield-alert-CMOPamqF.js} +1 -1
  66. package/web-app/dist/assets/{thumbs-up-CYb6ycQ-.js → thumbs-up-w1t0ZuDt.js} +1 -1
  67. package/web-app/dist/assets/{trash-2-BcHIiT3v.js → trash-2-N1gXTHrf.js} +1 -1
  68. package/web-app/dist/assets/{trending-down-C5eAxnkt.js → trending-down-CfbZNev0.js} +1 -1
  69. package/web-app/dist/assets/{trending-up-m9XmNKav.js → trending-up-Dy5OS7pv.js} +1 -1
  70. package/web-app/dist/assets/{upload-ZYJCPyYM.js → upload-D-AYd3Lw.js} +1 -1
  71. package/web-app/dist/assets/{usePolling-uC-lirzx.js → usePolling-C_MFEfgd.js} +1 -1
  72. package/web-app/dist/assets/{user-C1dyK-6p.js → user-C8-BP2aP.js} +1 -1
  73. package/web-app/dist/index.html +1 -1
@@ -238,3 +238,21 @@ One entry per decision: context, choice, why, how to reverse. Newest last.
238
238
  - Deadline: if the gate is not met by 23:00 ET (03:00 UTC), release v10.0.0 with the default still legacy, v10 opt-in, and the measured gap stated plainly.
239
239
  - All non-P0 backlog paused at 21:43Z: batch 10 stopped with every builder's commit kept on its branch (list in ~/loki-ci-logs/paused-branches.txt and the BOARD rows); ready rows parked.
240
240
  - Orphan: `timeout 240 bash .../worktrees/agent-afe77b46fbe4962fa/autonomy/run.sh` (PID 22960, child 22986, running 1 day 00:17) ignored SIGTERM and was stopped with SIGKILL by PID at 21:42Z (`ps -o pid= -p 22960` and `-p 22986` both empty afterwards). ORPHAN guard slice E-00 in flight.
241
+
242
+ ## D30. 2026-09-28: Loki directive -- any size in one run; accuracy is the lever; 2x gate; modernization program
243
+
244
+ - Supersedes the D29 gate and keeps everything in it. North star: Loki 10 completes work of any size in one autonomous run, from a one-line issue to a million-line modernization, with no back-and-forth. Moat order holds; nothing weakens the Seal, the Wall, Rule of Two or honest verdicts.
245
+ - Part 1 gate (v10.0.0, small-task engine), against raw `claude -p`, same tasks and model family, all numbers published: at least 2x fewer failures (96.5% or higher vs raw 93.1%; stretch 98.6%); cost per completed task at least 2x lower ($0.118 or less vs $0.2363); time to a correct result at most 1x raw on small tasks and at least 2x faster on medium and large; never worse than raw on any axis in any tier.
246
+ - Eval tiers: small (29 tasks, done), medium (15 multi-file, EV-11), large (10 feature or legacy, EV-12); arms raw, v10, legacy.
247
+ - v10.0.0 ships tonight. The default flips only if v10 beats raw on the measured tiers; otherwise opt-in with the numbers. No public "2-5x" claim until all three tiers are measured.
248
+ - Part 2 (v10.x): `loki modernize <repo> --to "<target>"`; design in docs/v10/MODERNIZE.md (CTO and Architect), Part 2 slices M-01.. cut from it; engineers take them when Part 1 slices stop filling the queue. PROGRESS.md every 30 minutes with Part 1 gate numbers, Part 2 slices done, top blocker; pulse enforces it (E-63 STALE_PROGRESS, over 35 minutes).
249
+
250
+ ## D31. 2026-09-28: small tasks must be leaner than raw
251
+
252
+ - For tasks sizing.ts rates small: one sonnet implement session with the cached repo map, then impacted tests, then PR. No separate plan or Wall call; the Wall stays for medium and large tasks, or when the repo has no relevant tests. Escalate to opus only on a test failure (E-64).
253
+ - Measured before this rule (EV-8, 5 tasks, raw opus 5/5 $0.2161 per completed, p50 41s): full design 4/5 $0.5954; Wall off 5/5 $0.3976; all-sonnet no plan no Wall 4/5 $0.294 p50 44s (~/loki-ci-logs/ev8r-{A,B,C}/results.jsonl). One sonnet session costing more than raw opus's whole task means the per-session overhead is the cost driver; E-65 measures and cuts it.
254
+
255
+ ## D32. 2026-09-28: augmentiq #52 user report fixed in v10 only
256
+
257
+ - Built into the v10 engine, no legacy fixes: "already implemented" is a first-class outcome with evidence, receipt and issue comment, no PR (E-66; aiq-52 expected outcome in the eval, EV-13); no pause state, anything unfinishable ends as a draft PR or an issue comment with the reason within the 15-minute cap (E-67); per-call deadline, progress every 30s, every exit code classified including 125 and 143 (E-68); cost shows "not measured", never $0 when unmeasured (E-69); the dashboard shows its version and the CLI's, warns on mismatch, and replaces an older dashboard on its port (E-70).
258
+ - Legacy stays as it is until v10 becomes the default; then legacy is deleted.
@@ -450,3 +450,84 @@ previously mismarked two merged guards (S-16, S-74) as PENDING.
450
450
  (S-139) asserts the VIOLATION fires for a `released@` row stamped after
451
451
  npm's newest publish; T39b asserts it stays silent for a row stamped
452
452
  before it.
453
+
454
+ ## 14. Eval harness orphans survived the arm's process-group KILL (EV-10)
455
+
456
+ - **Incident:** 00:08Z, pulse ORPHAN_WORKTREE flagged 6 orphaned processes
457
+ left running after `eval/loki10/harness.py` runs against the legacy arm;
458
+ all 6 were stopped by PID once found. Each was a detached
459
+ `/tmp/loki-run-*.sh` loop legacy loki spawns via `setsid`, which had
460
+ reparented to launchd (ppid 1) once the arm process it came from exited.
461
+ - **Root cause with evidence:** `kill_orphans()` only ever did
462
+ `os.killpg(timeout_pid, SIGKILL)` -- correct for anything still in the
463
+ `timeout` process group the arm ran under, but a `setsid`'d child
464
+ deliberately leaves that group and gets its own pgid, so the group KILL
465
+ can never reach it once the escape has completed. Reproduced locally: a
466
+ script that setsid-spawns a sleeper, confirms (by polling its pgid) that
467
+ the escape finished, then exits still leaves the sleeper running after
468
+ `capped_run()` returns and `kill_orphans()` has already run.
469
+ - **The guard:** `kill_orphans()` now also reaps by two signals that are
470
+ never a process name or pattern: any PID recorded in a `*.pid` file under
471
+ the run's own clone (`<work>/.loki/**/*.pid`, one per line, never through
472
+ a symlinked `.loki/` or a non-regular/oversized file), and any process
473
+ anywhere on the box whose cwd (`/proc/<pid>/cwd` where present, else one
474
+ system-wide `lsof -a -d cwd -Fpn` call, resolved with `os.path.realpath`)
475
+ is that same clone directory or a path inside it. Both are scoped to
476
+ `cwd`, the exact per-run clone `capped_run()` was given. Every candidate
477
+ PID is vetted by `_pid_is_ours()` before it ever reaches `os.kill`: never
478
+ `<= 1` (kill(2) treats -1/0 as "every process the caller may signal," not
479
+ a single-PID cleanup), never this process or its parent, and never older
480
+ than the run's own start (a stale or forged `.pid` entry naming an
481
+ unrelated, longer-lived process is left alone).
482
+ - **The test that proves it fires:** `eval/loki10/test-harness.sh`, EV-10.
483
+ Leg Rj: the `setsidorphan` stub-arm mode setsid-spawns a sleeper in its
484
+ own clone, polls until the sleeper's pgid equals its own pid and only
485
+ then records an "escaped" marker (ruling out a vacuous pass from a spawn
486
+ that never actually left the group), then exits; the leg asserts the
487
+ marker is present and the sleeper is dead once the harness run returns.
488
+ Leg Rk: the same escape, chdir'd out of the clone first so the cwd path
489
+ cannot see it, reaped instead from its own PID in a `.loki/*.pid` file; a
490
+ decoy PID that predates the run, planted in the same file (plus a literal
491
+ `-1`), is asserted to survive. Leg Rl exercises `_clone_orphan_pids`
492
+ directly to assert `-1`/`0`/`1` and a pre-run PID are filtered before any
493
+ kill is attempted, without ever risking a live `kill(-1, SIGKILL)`.
494
+ Mutation-tested: disabling the cwd path fails only Rj, disabling the
495
+ pidfile path fails only Rk, and bypassing `_pid_is_ours` (checked offline
496
+ against a throwaway copy of the module, never run against a live process)
497
+ lets `-1` through, which Rl's assertion catches.
498
+ ## 15. Two releases pushed with unbaselined secret-shaped fixtures never reached npm (E-60)
499
+
500
+ - **Incident:** Security Audit (the `secret-scan` job in
501
+ `.github/workflows/security-audit.yml`, a required-ci gate) failed on the
502
+ release SHAs for v9.79.0 (`9dc0b1d3`, 2026-09-27) and v9.80.0 (`085306ae`,
503
+ same day). Both pushes landed on main, but `publish-npm` never ran because
504
+ the required Security Audit conclusion was red, so npm latest stayed at
505
+ 9.78.0 through both releases -- 00:45Z is when the fix (`5190756f`) landed
506
+ and unblocked v9.80.1.
507
+ - **Root cause with evidence:** `5190756f`'s own commit message names the
508
+ findings exactly: "a planted AWS-shaped string for the deep-verify
509
+ secret-scan test and two CANARY/WITHHELD token canaries." Three new Loki 10
510
+ test fixtures were secret-shaped (matched gitleaks' built-in rules) and
511
+ landed on main across the two releases without a matching
512
+ `.gitleaksignore` entry, so gitleaks' full-history scan in CI reported
513
+ three new, unreviewed findings and blocked exactly as designed -- the gate
514
+ worked; nothing local had run the same scan before push to catch it there
515
+ instead of at CI, so two releases went out DOA on the fastest-available
516
+ feedback channel (CI, not a local gate).
517
+ - **The guard:** E-60 adds a fast-tier gitleaks step to `scripts/local-ci.sh`
518
+ (`_FAST_KEEP` entry `"gitleaks (secrets, origin/main..HEAD)"`): when a
519
+ `gitleaks` binary is on PATH, every pre-push run scans just the commits the
520
+ branch adds on top of `origin/main` against the same reviewed
521
+ `.gitleaksignore` baseline CI uses, so an unbaselined secret-shaped fixture
522
+ is caught before push, not after a release SHA is already tagged. Fails
523
+ closed the other way too: an absent binary prints an explicit SKIP line
524
+ (never a silent PASS), matching this file's shellcheck-absent posture.
525
+ - **The test that proves it fires:** `tests/test-local-ci-gitleaks.sh`
526
+ (registered in `tests/run-all-tests.sh` and `tests/shard-durations.tsv`).
527
+ Static assertions confirm the skip-not-pass path, the `.gitleaksignore`
528
+ baseline, the `origin/main..HEAD` scope, and `_FAST_KEEP` membership; when
529
+ a gitleaks binary is present, two live temp-repo scenarios drive the exact
530
+ command shape `scripts/local-ci.sh` runs: a commit adding a literal
531
+ AKIA-shaped token fails the step, and a commit adding the identical
532
+ characters via source-level concatenation (never contiguous in the
533
+ committed bytes) passes it.
@@ -0,0 +1,154 @@
1
+ # Loki 10 engine guide
2
+
3
+ Opt-in: set LOKI_ENGINE=v10 <!-- loki10-default -->
4
+
5
+ Loki 10 is the rewritten engine (docs/v10/ENGINE.md). It is not the default
6
+ yet. Every command below only runs when LOKI_ENGINE=v10 is set; leave it
7
+ unset and `loki` keeps using the current (legacy) engine exactly as before.
8
+
9
+ Some pieces named in this guide are still being built. Each one below says
10
+ so plainly instead of describing a finished feature.
11
+
12
+ ## Quickstart
13
+
14
+ Put the task first, as a quoted multi-word string, so bin/loki's router
15
+ sends it to the v10 engine instead of the legacy one. A one-word argument
16
+ that is not an issue ref, or any first argument starting with `-`, stays
17
+ on the legacy engine.
18
+
19
+ ```
20
+ LOKI_ENGINE=v10 loki "fix the login redirect loop" --no-pr
21
+ ```
22
+
23
+ Issue refs work the same way:
24
+
25
+ ```
26
+ LOKI_ENGINE=v10 loki owner/repo#123
27
+ LOKI_ENGINE=v10 loki https://github.com/owner/repo/issues/123
28
+ ```
29
+
30
+ bin/loki routes GitHub, GitLab (`.../-/issues/N`) and Jira
31
+ (`.../browse/KEY`) issue URLs to the v10 engine, and the issue-fetch step
32
+ (autonomy/issue-providers.sh) fetches title/body/labels from all three.
33
+ Only the extra already-done check (an issue's `state` and whether it was
34
+ closed by a merged PR) is GitHub-only; a GitLab or Jira issue still runs,
35
+ just without that extra signal.
36
+
37
+ Flags, from the engine's own `--help`:
38
+
39
+ - `--no-pr`: build and verify, but skip opening a pull request.
40
+ - `--deep`: request the deep verify pass; the implement time budget goes
41
+ from 480s to 1800s (`loki-ts/src/engine10/types.ts`).
42
+ - `--provider <name>`: pick the coding provider for this run. See the
43
+ provider table below.
44
+ - `--resume <run-id>`: continue a run that was interrupted.
45
+
46
+ `--no-pr`, `--deep` and `--provider` are parsed by the supervisor
47
+ (`loki-ts/src/engine10/supervisor.ts`) and take effect on a real run.
48
+ `--resume` is not wired yet: passing it prints `engine10: --resume is not
49
+ wired yet` and exits 2. Its shape is documented here because it is already
50
+ fixed in `--help`.
51
+
52
+ `loki status`, `loki verify` and `loki dashboard` are all built on main
53
+ (status.ts, verify_cmd.ts, dashboard/server.ts) and route through cli.ts's
54
+ table like any other subcommand.
55
+
56
+ The free-text and issue-ref run itself (the supervisor that plans, builds
57
+ and verifies) is wired into the CLI on main: `loki "<task>"` and `loki
58
+ <issue-ref>` run the full worker flow (intake, plan, wall, implement,
59
+ verify, seal) and then, in the supervisor, the pr stage, ending in the
60
+ 5-line summary below.
61
+
62
+ Slack is not part of the v10 engine surface (no command, no notification
63
+ hook) and is in progress, tracked with the other wave 3 items.
64
+
65
+ ## The 5-line summary
66
+
67
+ A finished run prints five lines, one label each:
68
+
69
+ ```
70
+ PR: https://github.com/owner/repo/pull/1
71
+ Verdict: VERIFIED
72
+ NOT PROVEN: full suite, app boot, council, security scan
73
+ Cost: $0.42 (claude, 212k tokens)
74
+ Time: 4m12s (intake 11s, plan 20s, implement 3m10s, verify 31s)
75
+ ```
76
+
77
+ - **PR**: the opened pull request URL, or `none` when the run used
78
+ `--no-pr` or never got that far. A draft PR adds the draft reason in
79
+ parentheses.
80
+ - **Verdict**: one of VERIFIED, PARTIAL, ALREADY_SATISFIED, SPEC_CONFLICT or
81
+ FAILED.
82
+ - **NOT PROVEN**: everything the run did not check, comma-joined. Never
83
+ empty by omission: a check that was skipped or deferred is always listed
84
+ here, not silently dropped. A flaky test found during verify appears as a
85
+ separate `; flaky ...` clause on the same line.
86
+ - **Cost**: the provider-reported dollar figure and token count. When the
87
+ provider does not report cost, this line reads `not measured` instead of
88
+ `$0.00`; a missing cost is never rendered as free.
89
+ - **Time**: total wall time, then each stage's own duration in parentheses.
90
+
91
+ This formatter (`loki-ts/src/engine10/output.ts`, `formatSummary`) is
92
+ called by the supervisor at the end of every run, so a real `loki "<task>"`
93
+ or `loki <issue-ref>` run prints this block on completion. The block above
94
+ is that function's real output, not a mockup.
95
+
96
+ ## NOT PROVEN
97
+
98
+ NOT PROVEN lists what a run did not verify, so a passing run is never read
99
+ as more thorough than it was. One entry is unconditional, written by Seal
100
+ every time:
101
+
102
+ - **The deep checks**: `full suite, app boot, council, security scan`.
103
+ They are deferred to a separate deep-verify pass, so Seal always lists
104
+ all four at seal time.
105
+
106
+ Seal also adds an entry whenever it applies, for example: `cost not
107
+ measured (no iteration ids recorded)`, `kill blocking not enforced` for
108
+ any provider other than claude, `worker killed by the supervisor backstop
109
+ (cap plus grace)`, `event log modified outside the engine`, a flaky test,
110
+ a reverted test edit, a model override a non-claude provider could not
111
+ honor, a task source the intake step did not record, an uncomputable
112
+ diff, an individual check that did not run, or a failed receipt signature.
113
+ The Cost line above separately reads `not measured` (never `$0.00`)
114
+ whenever the provider reported no dollar figure.
115
+
116
+ ## Receipts
117
+
118
+ A run writes `.loki/runs/<run-id>/receipt.json` and a matching
119
+ `receipt.md`. The JSON receipt's `receipt_sha256` hashes the canonical JSON
120
+ without the `verification` block, so verifying a receipt never has to trust
121
+ its own signature field to compute the hash it is checking.
122
+
123
+ `loki verify [run-id]` re-hashes the receipt and checks its signature. A
124
+ receipt with no signing key configured (or a key that failed to load) reads
125
+ `UNSIGNED` and is never presented as attested; a signed receipt reads
126
+ `SIGNED (kid ...)`.
127
+
128
+ ## Provider table
129
+
130
+ | Provider | Cost measured | Kill blocking enforced |
131
+ |----------|----------------|--------------------------|
132
+ | claude | yes | yes |
133
+ | codex | no | no |
134
+ | cline | no | no |
135
+ | aider | no | no |
136
+ | opencode | not supported | n/a |
137
+
138
+ For codex, cline and aider, a run's Cost line reads `not measured` and the
139
+ NOT PROVEN line adds the literal entry `kill blocking not enforced`
140
+ (`loki-ts/src/engine10/stages/seal.ts`). opencode is not one of engine10's
141
+ provider names (`claude`, `codex`, `cline`, `aider`); it is not supported.
142
+
143
+ ## After the flip
144
+
145
+ Once v10 becomes the default (docs/v10/DECISIONS.md, D29), `loki`, `loki
146
+ status`, `loki verify` and `loki dashboard` with no `LOKI_ENGINE` set will
147
+ mean the v10 commands described above. The previous engine stays fully
148
+ reachable: `loki legacy <args>` and `LOKI_ENGINE=legacy` both route to it,
149
+ unchanged. Nothing is removed at the flip.
150
+
151
+ That flip has not happened on main as of this guide. The opt-in line near
152
+ the top of this file and of README.md's section is the one place that
153
+ records which state we are in; it changes in the same commit as the flip
154
+ itself.
@@ -243,3 +243,20 @@ Misses: pub-click-3059 (hidden tests failed: wrong metavar bracketing), pub-huma
243
243
  ## Loki 10 engine: first real run (E-14 smoke, not the gate)
244
244
 
245
245
  pub-more-itertools-1192 through the E-14 glue entry, real claude, --no-pr: 30s wall (intake 0s, plan 16s, implement 12s, verify 3s, commit and seal under 1s), hidden test passes, $0.4486 over 2 sessions (plan $0.2264, implement $0.2223), verdict PARTIAL only because ruff is not installed. Raw claude on the same task: 15s, $0.1290. The planner session costs as much as the implement session.
246
+
247
+ ## Loki 10 gate report, small tier (2026-09-28, D30; v10.0.0 decision)
248
+
249
+ All arms on claude-opus-5-5, 29 small tasks with hidden tests, fresh clone per run, provider-sourced cost only. D30 targets vs raw: completion 96.5% or higher, cost per completed task $0.118 or lower, time to a correct result at most raw.
250
+
251
+ | arm | completed | cost per completed | p50 / p90 time to PR | source |
252
+ |---|---|---|---|---|
253
+ | raw `claude -p` | 27/29 (93.1%) | $0.2363 | 39s / 68s | ~/loki-ci-logs/eval-raw-claude-20260927T231653Z/results.jsonl |
254
+ | legacy (global loki v9.78.0) | 15/29 (51.7%); hidden tests pass 26/29, no PR opened | not measured (0/29 provider-sourced) | 190s / 441s | ~/loki-ci-logs/ev5-legacy/results.jsonl |
255
+ | v10 default knobs (main 8b76fd9a: E-45 cost path, E-65 lean sessions) | 26/29 (89.7%) | $0.3946 (2 runs unmeasured) | 85.5s / 133s | ~/loki-ci-logs/ev9-v10-small/results.jsonl |
256
+ | v10 lean configuration, not the default (same build, LOKI_E10_PLAN=0 LOKI_E10_WALL=0) | 27/29 (93.1%) | $0.1616 (1 run unmeasured) | 40s / 67s | ~/loki-ci-logs/ev9-v10-small-lean/results.jsonl |
257
+
258
+ - v10 misses: aiq-52-searchbar (the feature already exists; the no-change outcome is E-66/EV-13, in rework), pub-click-3059, pub-humanize-174 (raw missed the same two pub tasks).
259
+ - Gate: NOT MET on any axis for the default configuration. Default stays legacy; v10 ships opt-in (LOKI_ENGINE=v10).
260
+ - Lean configuration misses: aiq-52-searchbar, pub-humanize-174. It matches raw on completion and time and is 32% cheaper; it does not meet the 2x targets and is not the default until E-64 lands and is re-measured.
261
+ - Lean-session evidence, 5 tasks (EV-8 D/E, not the full arm): opus lean 4/5 at $0.1571 per completed, p50 28s; sonnet lean 4/5 at $0.1519, p50 27.5s; raw opus on the same 5: 5/5, $0.2161, p50 41s (~/loki-ci-logs/ev8r-{D,E}/results.jsonl). The lean small path is not the default yet (E-64 in rework).
262
+ - Medium and large tiers: not built (EV-11 3 of 15 verified, EV-12 in rework). No "2-5x" claim.