loki-mode 11.0.3 → 11.2.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 (91) hide show
  1. package/README.md +1 -1
  2. package/SKILL.md +2 -2
  3. package/VERSION +1 -1
  4. package/autonomy/run.sh +1 -0
  5. package/dashboard/__init__.py +1 -1
  6. package/docs/CLI-REFERENCE.md +1 -1
  7. package/docs/INSTALLATION.md +1 -1
  8. package/docs/WANG-PRINCIPLES-PLAN.md +1 -1
  9. package/docs/v10/DECISIONS.md +17 -0
  10. package/docs/v10/ENGINE-LAWS.md +13 -5
  11. package/docs/v10/FAILURE-CLASSES.md +8 -0
  12. package/docs/v10/GUIDE.md +85 -0
  13. package/docs/v11/ROUTER-1.md +124 -0
  14. package/loki-ts/data/model-pricing.json +14 -2
  15. package/loki-ts/data/router-shape-defaults.json +1 -0
  16. package/loki-ts/dist/loki.js +685 -681
  17. package/loki-ts/package.json +1 -1
  18. package/mcp/__init__.py +1 -1
  19. package/mcp/cp_tools.py +333 -0
  20. package/mcp/server.py +21 -0
  21. package/mcp/tests/_read_only_wall_probe.py +10 -0
  22. package/mcp/tests/fixtures/cp_api/artifact_report.md +3 -0
  23. package/mcp/tests/fixtures/cp_api/cost.json +1 -0
  24. package/mcp/tests/fixtures/cp_api/repos.json +1 -0
  25. package/mcp/tests/fixtures/cp_api/run_alpha.json +1 -0
  26. package/mcp/tests/fixtures/cp_api/run_beta.json +1 -0
  27. package/mcp/tests/fixtures/cp_api/run_events.json +1 -0
  28. package/mcp/tests/fixtures/cp_api/runs_list.json +1 -0
  29. package/mcp/tests/fixtures/cp_api/stats.json +1 -0
  30. package/mcp/tests/test_cp_tools.py +290 -0
  31. package/mcp/tests/test_read_only.py +6 -3
  32. package/package.json +2 -2
  33. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  34. package/providers/model_catalog.json +23 -8
  35. package/web-app/dist/assets/{AdminPage-DP2sMy9u.js → AdminPage-Bs4Vyd9R.js} +1 -1
  36. package/web-app/dist/assets/{Avatar-1DbWoap6.js → Avatar-Dmf_rtmv.js} +1 -1
  37. package/web-app/dist/assets/{Badge-5pMJ6mml.js → Badge-DCEdgEN8.js} +1 -1
  38. package/web-app/dist/assets/{Button-Wx-P8jv7.js → Button-BpGXXEPk.js} +1 -1
  39. package/web-app/dist/assets/{CockpitPage-BIlVX83h.js → CockpitPage-CzssVmim.js} +1 -1
  40. package/web-app/dist/assets/{ComparePage-Cvc4EHx1.js → ComparePage-BU4XtB9F.js} +1 -1
  41. package/web-app/dist/assets/{ErrorBoundary-DHorOJpG.js → ErrorBoundary-Bkjf4KP2.js} +1 -1
  42. package/web-app/dist/assets/{EvidenceReceiptPanel-ZmcvJuKP.js → EvidenceReceiptPanel-CcGMfaq7.js} +1 -1
  43. package/web-app/dist/assets/{GitHubIssuesPanel-BgnmVSH2.js → GitHubIssuesPanel-D53leEFJ.js} +1 -1
  44. package/web-app/dist/assets/{GitHubPRsPanel-G294TbLr.js → GitHubPRsPanel-UVsPtV3-.js} +1 -1
  45. package/web-app/dist/assets/{HomePage-D64vAIBi.js → HomePage-D9wO-XTX.js} +2 -2
  46. package/web-app/dist/assets/{LoginPage-BIiDZPgB.js → LoginPage-ChxBSele.js} +1 -1
  47. package/web-app/dist/assets/{MagicPage-CpEsWhpQ.js → MagicPage-BqQDKX2L.js} +1 -1
  48. package/web-app/dist/assets/{MetricsPage-GUk6e1c5.js → MetricsPage-CA22NkPl.js} +1 -1
  49. package/web-app/dist/assets/{NotFoundPage-BQSHJtoV.js → NotFoundPage-oYt5qdHQ.js} +1 -1
  50. package/web-app/dist/assets/{ProjectPage-DN-4KK67.js → ProjectPage-tSAdI6A6.js} +3 -3
  51. package/web-app/dist/assets/{ProjectsPage-BSaMMnQz.js → ProjectsPage-Dk22bicF.js} +1 -1
  52. package/web-app/dist/assets/{SettingsPage-DExtgm8G.js → SettingsPage-CwDSvMn6.js} +1 -1
  53. package/web-app/dist/assets/{ShowcasePage-BSosak6N.js → ShowcasePage-By3IMy9k.js} +1 -1
  54. package/web-app/dist/assets/{SystemSettingsPage-euS3jJKW.js → SystemSettingsPage-DcWNR28_.js} +1 -1
  55. package/web-app/dist/assets/{TeamsPage-Coeb6ReN.js → TeamsPage-CFawyYQg.js} +1 -1
  56. package/web-app/dist/assets/{TemplatesPage-Dq-bYUfu.js → TemplatesPage-D7pCD-63.js} +1 -1
  57. package/web-app/dist/assets/{TerminalOutput-4uALK6q2.js → TerminalOutput-CT2v1Vm2.js} +1 -1
  58. package/web-app/dist/assets/{activity-Cl0FSpRO.js → activity-DW6jRbjj.js} +1 -1
  59. package/web-app/dist/assets/{bell-B5J-3wGK.js → bell-CJOu9IIM.js} +1 -1
  60. package/web-app/dist/assets/{bot-BZZlQpuZ.js → bot-dVt0Xw_X.js} +1 -1
  61. package/web-app/dist/assets/{check-BPRzpVuZ.js → check-BVC4A8YK.js} +1 -1
  62. package/web-app/dist/assets/{chevron-left-Bhlk_30m.js → chevron-left-Djgr5pg-.js} +1 -1
  63. package/web-app/dist/assets/{circle-alert-CR58yXay.js → circle-alert-OE2reifn.js} +1 -1
  64. package/web-app/dist/assets/{clock-CJIB2-ZE.js → clock-BUUN5rWU.js} +1 -1
  65. package/web-app/dist/assets/{cloud-ByHrKZe8.js → cloud-CzPIksNz.js} +1 -1
  66. package/web-app/dist/assets/{code-xml-fCp3jILh.js → code-xml-DlE7vlGY.js} +1 -1
  67. package/web-app/dist/assets/{database-BV5Kc63M.js → database-DUauMcIC.js} +1 -1
  68. package/web-app/dist/assets/{dollar-sign-C3dHY0ib.js → dollar-sign-CBx9DWbM.js} +1 -1
  69. package/web-app/dist/assets/{file-code-corner-B8FVLziW.js → file-code-corner-hTmaP9Mz.js} +1 -1
  70. package/web-app/dist/assets/{file-plus-Dp_9XIaL.js → file-plus-DimFEqtO.js} +1 -1
  71. package/web-app/dist/assets/{globe-BIEXRDS6.js → globe-BV7yxcQ_.js} +1 -1
  72. package/web-app/dist/assets/{hammer-vi5VszDe.js → hammer-CW6Ol_ju.js} +1 -1
  73. package/web-app/dist/assets/{index-CNzndqZR.js → index-83w75NC1.js} +3 -3
  74. package/web-app/dist/assets/{layers-DZFYfOHZ.js → layers-DMAqCHxh.js} +1 -1
  75. package/web-app/dist/assets/{loader-circle-OQBo0OBg.js → loader-circle-B-TJNPo5.js} +1 -1
  76. package/web-app/dist/assets/{lock-C3by6YBL.js → lock-DbvZW7dV.js} +1 -1
  77. package/web-app/dist/assets/{package-C5PS9cIt.js → package-BWFcV2kS.js} +1 -1
  78. package/web-app/dist/assets/{plus-SVJHoBTR.js → plus-CjPzASFv.js} +1 -1
  79. package/web-app/dist/assets/{refresh-cw-B7oWjnzo.js → refresh-cw-DJL2nFq0.js} +1 -1
  80. package/web-app/dist/assets/{rotate-ccw-DGdchx3P.js → rotate-ccw-Bq3vK-Tu.js} +1 -1
  81. package/web-app/dist/assets/{scroll-text-Aqh6e_1z.js → scroll-text-CAMgtDYH.js} +1 -1
  82. package/web-app/dist/assets/{server-CtitneTI.js → server-D71_Bywf.js} +1 -1
  83. package/web-app/dist/assets/{shield-alert-CcIZJ2Rd.js → shield-alert-DqQ5wzQ6.js} +1 -1
  84. package/web-app/dist/assets/{thumbs-up-BunczQ1E.js → thumbs-up-DXE_IT36.js} +1 -1
  85. package/web-app/dist/assets/{trash-2-CV8b7Wtu.js → trash-2-VYAPKajq.js} +1 -1
  86. package/web-app/dist/assets/{trending-down-DEme3ONl.js → trending-down-CuE-J2LH.js} +1 -1
  87. package/web-app/dist/assets/{trending-up-S3tAQHKu.js → trending-up-BvdD9XmQ.js} +1 -1
  88. package/web-app/dist/assets/{upload-BkgaNcVn.js → upload-OM2YFziE.js} +1 -1
  89. package/web-app/dist/assets/{usePolling-CT6D0gXi.js → usePolling-Bk39fp_d.js} +1 -1
  90. package/web-app/dist/assets/{user-DyzSScrz.js → user-CWmKQURs.js} +1 -1
  91. package/web-app/dist/index.html +1 -1
package/README.md CHANGED
@@ -17,7 +17,7 @@ CLI reference: [docs/CLI-REFERENCE.md](docs/CLI-REFERENCE.md) (generated from th
17
17
 
18
18
  Loki Mode is a free, source-available autonomous coding agent by [Autonomi](https://www.autonomi.dev/). Hand it a PRD, GitHub issue, OpenAPI doc or one-line brief. It derives a delivery contract (the acceptance criteria), builds against it, and ends with a signed Evidence Receipt that states what was proven and what was not. If the contract cannot be derived, it stops and asks one question instead of guessing.
19
19
 
20
- Before a build counts as done, a review council selects reviewers from a specialist pool (`agents/types.json`, scored by `run.sh:FOCUS_KEYWORDS`). The bundled MCP server exposes 39 tools over stdio (`mcp/server.py`), including `loki_v10_run`, `loki_v10_status` and `loki_v10_verify` to start a Loki 10 run in the background, read its phase, verdict and cost, and verify its receipt (`BLOCKED` runs report their question). Add it with `claude mcp add loki-mode -- python3 -m mcp.server` from the install directory.
20
+ Before a build counts as done, a review council selects reviewers from a specialist pool (`agents/types.json`, scored by `run.sh:FOCUS_KEYWORDS`). The bundled MCP server exposes 47 tools over stdio (`mcp/server.py`), including `loki_v10_run`, `loki_v10_status` and `loki_v10_verify` to start a Loki 10 run in the background, read its phase, verdict and cost, and verify its receipt (`BLOCKED` runs report their question). Add it with `claude mcp add loki-mode -- python3 -m mcp.server` from the install directory.
21
21
 
22
22
  ## Contents
23
23
 
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: loki-mode
3
3
  description: An autonomous software factory that knows what it is supposed to deliver, and proves it did. Use when the user says Loki Mode or asks to build, fix or verify software autonomously.
4
4
  ---
5
5
 
6
- # Loki Mode v11.0.3
6
+ # Loki Mode v11.2.0
7
7
 
8
8
  **Current entry points (Loki 10 engine):** `loki "<task>"`, `loki owner/repo#N` and `loki quick "<task>"` run the Loki 10 engine and end with a signed receipt (`loki verify`). `loki backlog owner/repo --all` runs many issues in parallel. Guide: `docs/v10/GUIDE.md`. The skill instructions below, and `loki start`, describe the legacy engine, which still ships and is being removed (`loki start owner/repo#N` still routes to it; prefer `loki owner/repo#N`).
9
9
 
@@ -483,4 +483,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
483
483
 
484
484
  ---
485
485
 
486
- **v11.0.3 | [Autonomi](https://www.autonomi.dev/) flagship product | core skill**
486
+ **v11.2.0 | [Autonomi](https://www.autonomi.dev/) flagship product | core skill**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 11.0.3
1
+ 11.2.0
package/autonomy/run.sh CHANGED
@@ -7583,6 +7583,7 @@ _write_pricing_json() {
7583
7583
  "opus": {"input": 5.00, "output": 25.00, "label": "Opus (latest)", "provider": "claude"},
7584
7584
  "sonnet": {"input": 2.00, "output": 10.00, "label": "Sonnet (latest)", "provider": "claude"},
7585
7585
  "haiku": {"input": 1.00, "output": 5.00, "label": "Haiku (latest)", "provider": "claude"},
7586
+ "claude-haiku-5-5": {"input": 0.10, "output": 0.50, "over_100k": {"input": 0.50, "output": 2.50}, "label": "Haiku 5.5", "provider": "claude"},
7586
7587
  "gpt-5.3-codex": {"input": 1.75, "output": 14.00, "label": "GPT-5.3 Codex", "provider": "codex"}
7587
7588
  }
7588
7589
  }
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "11.0.3"
10
+ __version__ = "11.2.0"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -1,6 +1,6 @@
1
1
  # CLI reference
2
2
 
3
- Generated from `loki-ts/src/cli/registry.ts` by `scripts/generate-stale-zero.sh` for v11.0.3. Do not edit by hand.
3
+ Generated from `loki-ts/src/cli/registry.ts` by `scripts/generate-stale-zero.sh` for v11.2.0. Do not edit by hand.
4
4
  Hidden and legacy-only commands are omitted; see `docs/v10/CLI-MODERN.md` for the full inventory.
5
5
 
6
6
  | Command | Description |
@@ -2,7 +2,7 @@
2
2
 
3
3
  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:** v11.0.3
5
+ **Version:** v11.2.0
6
6
 
7
7
  **Engine note:** `loki "<task>"`, `loki owner/repo#N` and `loki quick` run the Loki 10 engine. `loki start` still routes to the legacy engine, which is being removed (planned work resumes 2026-10-07); prefer `loki owner/repo#N`. See [docs/v10/GUIDE.md](v10/GUIDE.md).
8
8
 
@@ -53,7 +53,7 @@ Measured on this machine, not asserted.
53
53
  | **1 Systems Thinking** | STRONG | 8 quality gates, RARV-C loop, council, Evidence Receipt, dual-route parity enforced by test |
54
54
  | **2 Speed** | MEASURED, UNOPTIMISED | agent call = **980s = 96%** of iteration; all gates together = 44s |
55
55
  | **3 Reliability** | STRONG, newly so | 73 mutation-proven trust invariants; four gates were shipping broken until v8.38.0 |
56
- | **4 Extensibility** | STRONG | 5 providers, agent type registry, MCP (39 tools), plugin marketplace |
56
+ | **4 Extensibility** | STRONG | 5 providers, agent type registry, MCP (47 tools), plugin marketplace |
57
57
  | **5 Feedback Loops / Evals** | **BROKEN** | `cost_usd == 0` on **3 of 5** efficiency records; no eval score for our own harness |
58
58
 
59
59
  **Principle 5 is the gap, and it is the one Wang weights highest.** He states the
@@ -714,3 +714,20 @@ Source: the founder's words, relayed by the peer session (autonomi-dev-76) at 14
714
714
  3. Never hold completed work. Every green slice ships on the next train, and nobody pushes during a running release.
715
715
  4. Usage readings are logged hourly in usage-readings.tsv from direct /usage readings. The pulse weekly projection is not used as a governor input while it reads 450%+.
716
716
  5. Order: 10.7.1, then 10.8.0 (UI, CPE-24 if green, else 10.8.1), then MW-1 to MW-3, which replace mods M0 to M3 per the research in autonomi-dev/research/2026-10-03-claude-mods, then EL-W1.
717
+
718
+ ## D88 (number reserved, stub recorded 2026-10-07 by the CoS at CTO request): CI waiver cited in PROGRESS.md, never written here
719
+ PROGRESS.md (the FC-25 P9 entry) cites a D88 CI waiver that was never recorded in this log. This stub keeps the number taken, so D89 is unambiguous. The waiver's scope is only what that PROGRESS.md entry states. It never waived P9 on a release commit, and it grants nothing beyond that entry.
720
+
721
+ ## D89 (2026-10-07, founder directive, CoS records): Haiku 5.5 executes, Opus advises, router decides; L1 means outcome parity
722
+ 1. Founder directive, verbatim excerpts: "haiku 5.5 is released today ... it's going to cut down all costs drastically ... opus can be the advisor and haiku doing all the engineering work inside loki mode's engine ... sonnet is optional and routed by opus if haiku isn't performing well enough ... have that router perfectly ... model decides."
723
+ 2. Engine Law L1 is amended (docs/v10/ENGINE-LAWS.md): "never below raw" means OUTCOME parity (solve rate, time and cost on the B9 corpus and the Parity Gate), not model identity.
724
+ 3. A Haiku executor runs only in a configuration with Parity Gate evidence: with the Opus advisor attached, or without it only if the no-advisor arm also meets the Parity Gate. Otherwise the executor is Sonnet 5.5. The executor, the advisor state and any fallback reason are printed on the start line and in the receipt, so nothing is silently reduced.
725
+ 4. The escalation ladder goes up, always before STALLED: Haiku -> Sonnet 5.5 for the rest of the run -> Opus for a repeated failure on Sonnet.
726
+ 5. H4 is defined in ENGINE-LAWS.md: self-improving per-repo, per-shape routing from recorded outcomes. Sonnet becomes the default on a shape where Haiku lost 2 of the last 3 runs (code-owned, per H4).
727
+ 6. Opus makes the routing decision as schema-checked JSON (L0). The harness adds no repo-shape or task-wording logic beyond the H4 evidence lookup, which may only move the executor up.
728
+ 7. Rollback and parity: `LOKI_ROUTER=0` restores the prior behavior exactly. A shape where Haiku fails the Parity Gate runs on Sonnet 5.5. A shape where Sonnet also fails runs on the pre-router default until a Parity Gate row shows the routed executor at parity.
729
+ 8. Implementation: docs/v11/ROUTER-1.md (slices R1-01 to R1-21). This slice is R1-04.
730
+ 9. Default-on only after parity: while slices are built, `LOKI_ROUTER` unset means off. R1-19 flips the default to on only when, on the release candidate SHA, the FireLater#17 gate is green (VERIFIED, ready PR, time within raw + 30s, cost <= raw x 1.2) and the B9 corpus shows correctness parity with raw `claude -p` on every shape not listed in the seeded router-shape-defaults.json. After the flip, `LOKI_ROUTER=0` is the opt-out and restores the exact pre-router model behavior, pins included (R1-21 golden).
731
+ 10. Accepted risk (CTO, 2026-10-07): B9 measures about 5 of the 14 or more Repo Shape Matrix shapes, so an unmeasured shape starts on Haiku without shape-level parity evidence; the backstops are the in-run escalation ladder (Haiku -> Sonnet 5.5 before STALLED, so a miss costs time and money, not correctness) and the H4 history floor, the receipt records shape parity as NOT PROVEN for any shape with no B9 row, and each matrix shape gains a B9 row as it becomes runnable.
732
+
733
+ Amendment to D89 (2026-10-07 21:40Z, CTO decision, refined by the founder at 21:45Z, CoS records). This amends only R1-19, the default-on flip that follows the CTO gate; 11.1.0 and 11.2.0 still ship the router OFF. (1) The default executor is Sonnet 5.5; Haiku 5.5 per work unit when Opus assigns it. (2) Roles: Opus 5.5 is the architect, router and advisor, plans and assigns each unit, and is consulted on hard calls. Sonnet is the senior engineer and the default for implementation and fixes. Haiku does tests, docs and small low-risk changes only when Opus assigns them in the plan. Haiku is never the blanket default. (3) L0 holds: the harness never routes by task type or path regex; it only executes, verifies and escalates. (4) The route schema is `units: [{id, kind, executor, reason}]` plus a run default of sonnet; a missing or invalid unit route goes to sonnet with NOT PROVEN. A haiku unit that fails a code-owned check is redone on sonnet, then escalates to opus; a Wall assigned to haiku gets an Opus review before implement. The receipt lists the executor, assigner and reason per unit. The per-unit schema lands in 11.2.0 or 11.2.1 depending on what is merged. (5) Escalation stays evidence-gated (haiku -> sonnet -> opus, and sonnet -> opus), and `LOKI_ROUTER=0` equals pre-router behavior exactly (the R1-21 golden). (6) The R1-16 shape-defaults semantics are inverted (a shape is listed as `haiku` once it has earned it; an absent listing means Sonnet), and R1-16 history is an input to Opus, not a harness rule. Rationale: a wrong PR costs the user far more than the token savings, B9 covers only about 5 of 14 shapes (item 10), and under L0 a model earns the cheaper tier with evidence. Items 3, 5, 7 and 9 above are read with this amendment; their text is kept as recorded. See docs/v11/ROUTER-1.md sections 4.1, 4.3 and 4.6.
@@ -29,11 +29,12 @@ Each class has a law. Each law has one mechanism, plus one enforcement check tha
29
29
  - Review rule: reject any change that adds an `if` or a regex about the user's repo shape, language, framework or task wording. The fix is a prompt or schema change plus an execution check. Hardcoded tables are deleted once the model path is green on the Repo Shape Matrix. Slices: docs/v10/L0-WAVE1.md.
30
30
 
31
31
  ### L1. Never below raw
32
- A Loki run never gives the user less intelligence, a worse result or a meaningfully slower one than the same provider run raw.
33
- - The default implement model and effort are the provider's best default for the user's account (what bare `claude` would use), or higher. Cheap models are only for mechanical sub-steps (repo map summaries, PR body prose, docs).
34
- - Any downgrade (model, effort, context, time limit) is printed on the start line and recorded in the receipt. Nothing is silently reduced.
35
- - Escalation goes UP: a repeated code failure escalates to the strongest model and effort the provider offers, with the full failure output and the agent's own diagnosis. This happens before STALLED, for every provider.
36
- - Enforcement: the Parity Gate (section 4) blocks promotion to `latest` when Loki is below raw on the corpus.
32
+ A Loki run never gives the user a worse result, or a meaningfully slower or costlier one, than the same provider run raw, as measured by the Parity Gate thresholds in section 4 (correctness at least raw; time within raw + 30s for small tasks and raw x 1.3 otherwise; cost at most raw x 1.2). "Never below raw" means OUTCOME parity (solve rate, wall time and cost on the B9 corpus and the Parity Gate). It does not mean model identity (amended by D89, 2026-10-07).
33
+ - On the Claude engine10 path with the router on, the default implement model and effort are chosen by the router (Opus decides, per ROUTER-1). Everywhere else, and with `LOKI_ROUTER=0`, they are the provider's best default for the user's account (what the bare CLI would use), or higher.
34
+ - A Haiku executor runs only in a configuration with Parity Gate evidence: with the Opus advisor attached, or without it only if the no-advisor arm also meets the Parity Gate. Otherwise the executor is Sonnet 5.5 and the reason is printed on the start line and recorded in the receipt. A shape where Haiku fails the Parity Gate runs on Sonnet 5.5. A shape where Sonnet also fails runs on the pre-router default (the `LOKI_ROUTER=0` behavior) until a Parity Gate row shows the routed executor at parity.
35
+ - Any downgrade (model, effort, context, time limit) is printed on the start line and recorded in the receipt, including the routed executor and the advisor status. Nothing is silently reduced.
36
+ - Escalation goes UP, always before STALLED, for every provider: a repeated code-owned failure escalates to a stronger model, ending at the strongest model and effort the provider offers, with the full failure output and the agent's own diagnosis. On the router path the ladder is Haiku -> Sonnet 5.5 for the rest of the run -> Opus for a repeated failure on Sonnet.
37
+ - Enforcement: the Parity Gate (section 4) blocks promotion to `latest` when Loki is below raw on the corpus. The router is default-on only after this gate passes on the release candidate (D89 item 9).
37
38
 
38
39
  ### L2. Fail closed on trust, fail open on work
39
40
  - Trust surfaces fail CLOSED and may block: signing, receipt integrity, secrets, sandbox and permission boundaries, policy the user configured, and tests or CI config being deleted or weakened.
@@ -80,6 +81,13 @@ Every sink reaches the same terminal state: events, receipt, PR, Control Plane,
80
81
  The PR body, receipt, `--json` envelope and CLI summary have schemas. "not recorded" when the data exists is a test failure.
81
82
  - Golden tests are built from real recorded runs (FireLater#17 included), not hand-made stubs.
82
83
 
84
+ ### H4. Self-improving routing (per repo, per shape; D89)
85
+ An H-law is a harness learning rule: it lets recorded outcome evidence improve a decision over time, and it never overrides L0 to L7.
86
+ - Every sealed run writes a per-repo, per-shape outcome record: executor, verdict, escalated (yes or no), cost in USD and wall time. Records are executed outcome data (L3 rung 1), never a heuristic about repo shape or task wording (L0).
87
+ - The shape key comes from the Project Model (workspaceKind plus the package runner labels, L4), never from a file pattern or regex (L0). It is used only as a lookup key into executed outcome evidence (the per-repo history, or the shipped router-shape-defaults.json seeded from B9 rows), and it may only move the executor up, never down.
88
+ - The history is fed to the Opus routing prompt. As an evidence floor, a shape where Haiku lost 2 of the last 3 runs (a code-owned FAIL or an escalation; harness, env and provider ERRORs and NOT PROVEN outcomes do not count, L5) defaults to Sonnet 5.5 until a B9 row shows Haiku at parity on that shape.
89
+ - History only changes the starting executor. It never removes the advisor requirement, never disables escalation, and a missing or unreadable history yields the router default with a NOT PROVEN line (L2, fail open on work).
90
+
83
91
  ## 3. The learning system (how every future issue is handled at 100k feet)
84
92
 
85
93
  No bug becomes a fix slice until the CoS has written its row in docs/v10/FAILURE-CLASSES.md, answering five questions:
@@ -326,3 +326,11 @@ L0 review rule (ENGINE-LAWS.md L0): a fix that adds an `if` or a regex about the
326
326
  - Siblings: `selectRelevantFiles` still uses substring overlap for plan hints. `namedFiles` still matches a basename written out in the task. FC-27's half-repo drop stays on the same selector.
327
327
  - Mechanism: `selectSpecificFiles` counts a task word only when it equals a path segment or a symbol. A word inside a longer name does not. `speedLikelyFiles` is still the only caller that can skip the Wall.
328
328
  - Fixture: loki-ts/tests/engine10/sizing_lean.test.ts, "FC-28: a word inside a longer symbol is not a relevant test, so the Wall stays".
329
+
330
+ ## FC-29 A test silently depends on the caller's cwd
331
+ - User saw: tests/test-proof-verify-jwks.sh passed 108/0 in 33s in a fresh worktree and hung until killed when run from the main checkout. The CI-style run was green and the founder's own run was red, so the suite read as flaky.
332
+ - Mechanism (measured): `loki proof verify` and `loki_remote_verify_receipt` run `proof-verify.py "$pj" "${TARGET_DIR:-.}"`. With TARGET_DIR unset the verifier runs `compute_tree_digest` on the caller's cwd, whose filesystem walk visited 1,054,266 paths (13.3s just to enumerate, then it hashes them) because `.claude/worktrees` (190 worktrees, 32G) sits inside the checkout. A fresh worktree has a few thousand files.
333
+ - Law: L2 (a verdict is about the tree it names, never an ambient one), and the test hermeticity rule: a test owns its fixture tree.
334
+ - Siblings: swept every tests/*.sh spawn of `proof verify` and `loki_remote_verify_receipt`; only the jwks test lacked TARGET_DIR. Direct `proof-verify.py` runs pass the repo as an argument. Other `${TARGET_DIR:-.}` readers in autonomy/loki (HANDOFF.md, failover.json, .loki dir) are not swept yet.
335
+ - Mechanism of the fix: every verifier spawn in the jwks test sets TARGET_DIR to its fixture; tests/test-verifier-spawn-sets-target-dir.sh fails any test that spawns the verifier without TARGET_DIR or a cd into an owned directory.
336
+ - Fixture: tests/test-verifier-spawn-sets-target-dir.sh, mutated against the pre-fix jwks test (7 hits). tests/test-proof-verify-jwks.sh run with cwd = the main checkout.
package/docs/v10/GUIDE.md CHANGED
@@ -233,6 +233,91 @@ NOT PROVEN line adds the literal entry `kill blocking not enforced`
233
233
  (`loki-ts/src/engine10/stages/seal.ts`). opencode is not one of engine10's
234
234
  provider names (`claude`, `codex`, `cline`, `aider`); it is not supported.
235
235
 
236
+ ## Model routing
237
+
238
+ Model routing picks which Claude model does each stage of a run. It is OFF
239
+ by default in 11.2.0. Set `LOKI_ROUTER=1` to opt in. `LOKI_ROUTER=0` is the
240
+ explicit opt-out and keeps the exact pre-router model behavior, pins
241
+ included (guarded by the opt-out golden test in
242
+ `loki-ts/tests/engine10/router_optout_golden.test.ts`). Explicit
243
+ `LOKI_MODEL_OVERRIDE` and `LOKI_CLAUDE_MODEL_DEVELOPMENT` still win and
244
+ bypass the router. The other knobs are `LOKI_ROUTER_EXECUTOR` (post-flip
245
+ default sonnet; haiku only by earned evidence), `LOKI_ROUTER_ESCALATE` (default sonnet) and `LOKI_ROUTER_ADVISOR`
246
+ (default opus; `off` disables the advisor). The router engine itself lands in
247
+ 11.2.0; the pieces below marked "shipped in 11.1.0" are already in the code.
248
+
249
+ ### Executor and advisor
250
+
251
+ When the router is on, the post-flip default executor is Sonnet 5.5;
252
+ Haiku 5.5 per work unit when Opus assigns it. Opus 5.5 is the architect,
253
+ router and advisor: it plans, assigns each work unit and is consulted on
254
+ hard calls. Sonnet is the senior engineer and the default for
255
+ implementation and fixes. Haiku does tests, docs and small low-risk changes
256
+ only when Opus assigns them in the plan, and is never the blanket default.
257
+ The harness never routes by task type or path regex; it only executes,
258
+ verifies and escalates. Per-repo history is an input to Opus, not a harness
259
+ rule. The per-unit route (`units: [{id, kind, executor, reason}]` plus a run
260
+ default of sonnet) lands in 11.2.0 or 11.2.1 depending on what is merged. A
261
+ missing or invalid unit route goes to Sonnet and is reported as NOT PROVEN.
262
+ The receipt lists the executor, assigner and reason per unit.
263
+ The advisor needs Claude Code 2.1.293 or later,
264
+ which the Agent SDK 0.3.293 bundles (shipped in 11.1.0). If the advisor is
265
+ unavailable, the executor is Sonnet 5.5 and the run is never failed for it.
266
+ The advisor is unavailable when the provider is not
267
+ claude, when `CLAUDE_CODE_USE_BEDROCK`, `CLAUDE_CODE_USE_VERTEX` or
268
+ `CLAUDE_CODE_USE_FOUNDRY` is set, when `ANTHROPIC_BASE_URL` points at a
269
+ non-Anthropic host, when Claude Code is older than 2.1.293, when
270
+ `LOKI_ROUTER_ADVISOR=off`, or after a session reports an advisor tool error
271
+ (remembered for the rest of the run). The probe is
272
+ `loki-ts/src/runner/router/advisor_probe.ts` (shipped in 11.1.0). The
273
+ default-on flip happens after the CTO gate; 11.1.0 and 11.2.0 still ship the
274
+ router off.
275
+
276
+ ### Escalation
277
+
278
+ Escalation is gated on evidence and only moves up: haiku to sonnet to opus,
279
+ and sonnet to opus. A haiku unit that fails a code-owned check is redone on
280
+ Sonnet, then escalates to Opus. A Wall assigned to Haiku gets an Opus review
281
+ before implement. A repeated failure on Sonnet gets a fix round on Opus
282
+ before the run can stall. A failure owned by the harness, the environment or
283
+ the provider causes no transition and is reported as NOT PROVEN.
284
+
285
+ ### Per-repo-shape outcome memory
286
+
287
+ Loki remembers how each kind of repo went. The shape key is the Project
288
+ Model `workspaceKind` plus the sorted runners, for example
289
+ `multi-root:pytest+vitest`; a package with no runner contributes `none`.
290
+ Outcomes are stored in the per-repo cache. The haiku floor moves a shape to
291
+ Sonnet after 2 code-owned losses in the last 3 Haiku runs. Only code-owned
292
+ FAILs and escalations count; harness, environment and provider errors and
293
+ NOT PROVEN outcomes never do. A missing or corrupt history file is a cold
294
+ read, never a crash (shipped in 11.1.0, `loki-ts/src/runner/router/history.ts`).
295
+ The shipped `loki-ts/data/router-shape-defaults.json` is empty in 11.1.0.
296
+ After the flip a shape is listed as `haiku` once it has earned it with a B9
297
+ row, and an absent listing means Sonnet. Shape history and the defaults file
298
+ are inputs to Opus, not harness routing rules.
299
+
300
+ ### Pricing
301
+
302
+ Haiku 5.5 is priced on its exact model id: $0.10 in and $0.50 out per MTok
303
+ for prompts up to 100K tokens, and $0.50 in and $2.50 out over 100K, with
304
+ the cache rates in `loki-ts/data/model-pricing.json`. The `haiku` family
305
+ alias row in that file is still the Haiku 4.5 price of $1 and $5, because
306
+ the exact-id key is matched first (`loki-ts/src/runner/budget.ts`).
307
+
308
+ ### What you see
309
+
310
+ In 11.2.0 the receipt carries a `route` block (initial decision, each
311
+ escalation with its trigger, advisor availability and the share of requests
312
+ above 100K), and `loki doctor` prints an advisor line. The executor and any
313
+ fallback reason are also printed on the start line.
314
+
315
+ ### Comparing models
316
+
317
+ `scripts/b9-scoreboard.sh` is the comparison harness for routed against raw
318
+ runs on the B9 corpus, and it can emit shape defaults from those runs
319
+ (lands in 11.2.0).
320
+
236
321
  ## After the flip
237
322
 
238
323
  D48 made v10 the default for `loki "<task>"`, `loki owner/repo#N` and
@@ -0,0 +1,124 @@
1
+ # ROUTER-1: Sonnet executor, Opus advisor, evidence-earned Haiku, evidence-gated escalation
2
+
3
+ Status: plan (Architect, 2026-10-07; default-on adjustment from steering the same day). CTO decision 2026-10-07 21:40Z, refined by the founder at 21:45Z (D89 amendment), governs R1-19 only: when the default-on flip lands after the CTO gate, the default executor is Sonnet 5.5; Haiku 5.5 per work unit when Opus assigns it. Opus 5.5 is the architect, router and advisor: it plans, assigns each work unit and is consulted on hard calls. Sonnet is the senior engineer and the default for implementation and fixes. Haiku does tests, docs and small low-risk changes only when Opus assigns them in the plan. Haiku is never the blanket default. The per-unit schema (section 4.1) lands in 11.2.0 or 11.2.1 depending on what is merged; the earlier whole-run schema below is superseded. 11.1.0 and 11.2.0 still ship the router OFF. Earlier text below that calls Haiku the default executor describes the superseded plan. While slices are built they merge behind `LOKI_ROUTER` (unset = off). R1-19, the final slice, makes it default ON, gated on steering's FireLater#17 gate plus the B9 scoreboard on the release candidate. After the flip `LOKI_ROUTER=0` is the opt-out and restores the exact pre-router model behavior, pins included (R1-21 test).
4
+ Source: founder directive 2026-10-07 ("Opus is the advisor, Haiku does all engineering work; Sonnet is optional, routed by Opus when Haiku is not performing well enough; model decides").
5
+ Scope: the engine10 path (`loki start <issue|text>`, `loki-ts/src/engine10`). The legacy RARV route (`autonomy/run.sh`, `runner/autonomous.ts`, `runner/capability_router.ts`) keeps its tiers; only its pricing table mirror changes (R1-02).
6
+
7
+ ## 1. Goal
8
+ After the R1-19 flip, every engine10 session runs on Claude Sonnet 5.5 as the default executor with Opus 5.5 attached through the native Claude Code advisor tool, so the model itself decides when it needs stronger judgment. Opus picks the executor at plan time with a recorded reason. Opus may route a task to Haiku 5.5 only when the R1-16 history and a B9 row show Haiku at outcome parity on that repo shape; a shape with no evidence stays on Sonnet. Escalation stays evidence-gated (haiku -> sonnet -> opus, and sonnet -> opus). The outcome (solve rate, time, cost) is never below raw `claude -p`, proven on the B9 scoreboard.
9
+
10
+ ## 2. What already exists (read before building; cite, do not rebuild)
11
+ - Session model plumbing: `engine10/session.ts:25` resolveModel, `:31-60` childEnv (tier pins via `LOKI_CLAUDE_MODEL_<TIER>`, `LOKI_E10_MODEL_DEFAULT` omits `--model`).
12
+ - SDK call site: `runner/providers.ts:507` buildSdkLoopOptions, `:683-735` `query()` options (model, resume, tools, settingSources `["project"]` for engine10 at `:544`, effort, fallbackModel). CLI route argv at `:380-392` (passes `--settings hostGuardSettingsJson()`).
13
+ - Escalation already exists: `engine10/stages/fix.ts:64-71` escalates a repeated test-failure signature to `escalationModel()` = opus (`runner/model_rank.ts:8`). Stall stop: `engine10/machine.ts:186` (same signature 3 verifies). `MAX_FIX_ROUNDS = 2` (`engine10/types.ts:25`).
14
+ - Owner attribution: verify marks harness-owned checks `owner: "harness"` (`engine10/stages/verify.ts:39,144-145,303`); only these never feed fix rounds.
15
+ - Downgrade list: `runner/model_downgrades.ts:6-20` (cascade, plan fast tier, Wall pin, already-done pin), printed on the start line `engine10/supervisor.ts:305-306`, recorded on run.started `:340`.
16
+ - Sonnet pins to remove: `engine10/sizing.ts:62` wallModel (default sonnet), `:64` cascadeImplementModel; used by `stages/wall.ts:174-175`, `already_done.ts:35-36`; plan runs `tier: "fast"` (`stages/plan.ts:68`) which resolves to sonnet unless `LOKI_ALLOW_HAIKU=true` (`runner/model_downgrades.ts:13`, `providers/claude_flags.ts:153-166`).
17
+ - Static L1 guard: `loki-ts/tests/engine10/never_below_raw.test.ts:100-125` allowlists every session model pin; any new pin fails CI until vetted.
18
+ - Resume across a model change is refused by design: `runner/session_resume.ts:41`.
19
+ - Plan scope file: `<runDir>/plan-scope.json` (`util/run_cap.ts:10,25-28`), written by the plan session, read for FC-21b cap resize.
20
+ - Cost: engine10 dollars come from the SDK result `total_cost_usd` (`engine10/cost.ts:74`); `model-pricing.json` prices only killed-session partial streams (`runner/budget.ts:483-500`) and estimates (`tools/estimate-run.py:84`). Per-message usage is already parsed (`runner/sdk_stream_parser.ts:161-213`).
21
+ - Not present: no advisor wiring anywhere (grep of loki-ts/src for "advisor" finds only unrelated text); no Bedrock/Vertex/Foundry detection; no B9 harness script (B9 is a manual row in `docs/v10/RELEASE-11.md:46`; the nearest harness is `scripts/first-run-gate.sh:259-270`).
22
+ - Name collision: `LOKI_ADVISOR_MODEL` already means the legacy council reviewer pin (`runner/quality_gates.ts:1532,1612`). ROUTER-1 must not reuse it; new knobs are `LOKI_ROUTER*`.
23
+
24
+ ## 3. Engine Laws touched
25
+ - L0 (model decides, harness proves): the executor choice is made by Opus (advisor in the plan session, or the plan session itself on Opus when no advisor), returned as schema-checked JSON. The harness adds no regex or `if` about repo shape, language or task wording. Harness-owned logic is limited to mechanism: provider capability detection (env and version), execution-evidence triggers, and recording. `tests/engine10/l0_guard.test.ts` must stay green. The shape key (section 4.6) is a lookup into executed outcome evidence and may only move the executor up (ENGINE-LAWS H4); this is the documented exception to the L0 review rule.
26
+ - L1 amendment (R1-04, founder decision D89): "never below raw" means OUTCOME parity (solve rate, time, cost on the B9 corpus and the Parity Gate), not model identity. A Haiku executor runs only in a configuration with Parity Gate evidence: with the Opus advisor attached, or without it only if arm 4 (section 7) meets the Parity Gate; otherwise the executor is Sonnet 5.5. The executor, advisor state and any fallback reason are printed on the start line and in the receipt (no silent reduction). Escalation still goes UP: Haiku -> Sonnet 5.5 (rest of run) -> Opus for a repeated failure on Sonnet (the existing L1 path, `model_rank.ts:8`), always before STALLED. Non-Claude providers and `LOKI_ROUTER=0` keep the provider's best default and escalate to the strongest model the provider offers.
27
+ - L3 (evidence outranks heuristics): escalation fires only on rung 1/2 evidence (a code-owned FAIL repeating after a fix round, a SPEC_CONFLICT exit, a stall or limit kill) or rung 3 model judgment (the advisor's explicit recommendation). Per-shape history (H4) is executed outcome data, not a heuristic.
28
+ - L5 (every failure has an owner): only `owner` code FAIL (verify.ts) drives escalation. Harness, env and provider ERRORs never escalate and never count; an advisor that is unavailable is NOT PROVEN with owner provider, never a run failure.
29
+ - H4 (self-improving): per-repo, per-shape outcome history (executor, verdict, escalated, usd, wall time) is written at seal and fed to the Opus routing prompt and, as an evidence floor, makes Sonnet the default on a shape where Haiku lost 2 of the last 3 runs (code-owned FAIL or escalation; harness, env and provider ERRORs and NOT PROVEN outcomes do not count, L5). The floor is cleared only by a B9 row showing Haiku at parity on that shape, since Haiku never runs there again while the floor holds. NOTE: "H4" is not defined anywhere in docs/ today; R1-04 defines it in ENGINE-LAWS.md.
30
+ - L7 (outputs are contracts): the route block in the receipt, the start line and the PR line get golden tests (R1-15).
31
+
32
+ ## 4. Architecture
33
+ ### 4.1 Routing decision schema (written into plan-scope.json by the plan session; parsed by `runner/router/decision.ts`)
34
+ ```
35
+ route: { default: "sonnet",
36
+ units: [ { id: string, kind: string, executor: "haiku" | "sonnet", reason: string (<= 200 chars) } ],
37
+ source: "opus-plan" | "advisor" | "default" }
38
+ ```
39
+ Per-unit schema (founder refinement 2026-10-07 21:45Z; lands in 11.2.0 or 11.2.1 depending on what is merged). Opus writes the units into plan-scope.json at plan time, with a run default of sonnet. The harness never routes by task type or path regex (L0): it only executes, verifies and escalates. R1-16 history is an input to the Opus planning prompt, not a harness rule. The receipt lists the executor, the assigner and the reason per unit.
40
+ A missing or invalid unit route goes to sonnet (`{executor: "sonnet", source: "default", reason: "no route returned"}`; the superseded plan returned haiku here) plus a NOT PROVEN line (L2: fail open on work). Aliases resolve through `providers/model_catalog.json` (haiku -> claude-haiku-5-5, sonnet -> claude-sonnet-5-5, opus -> claude-opus-5-5).
41
+
42
+ ### 4.2 Where the decision is made
43
+ 1. Run start: advisor availability is probed (R1-06). Start line: `executor sonnet-5.5, advisor opus` (or `executor haiku-5.5, advisor opus` for a shape with earned Haiku evidence; or `executor sonnet-5.5, advisor unavailable: <reason>`).
44
+ 2. Plan stage runs (normal tasks): the plan session runs on the executor with the Opus advisor attached; its brief asks it to consult the advisor and write `route` into plan-scope.json. With no advisor, the plan session itself is pinned to Opus (the single cheap Opus call) and writes the same field; a `haiku` route is then raised to Sonnet (section 4.4).
45
+ 3. Plan skipped (small task, `plan.ts:55`): no extra call. Executor = history floor or shape default if one applies, else Sonnet with the advisor (post-flip default; Haiku only for a shape listed `haiku` in section 4.6), `source: default`.
46
+ 4. Recorded: a `route` event (implement), run.started `route_initial`, receipt `route` block (initial decision, every escalation with trigger and evidence pointer, advisor availability, share of requests above 100K).
47
+
48
+ ### 4.3 Escalation state machine (pure function in `runner/router/decision.ts`)
49
+ ```
50
+ EXEC(haiku) --a: code-owned FAIL repeats after a fix round------------> EXEC(sonnet, rest of run)
51
+ EXEC(haiku) --b: LOKI_ESCALATE: <reason> marker (advisor recommended)--> EXEC(sonnet, rest of run)
52
+ EXEC(haiku) --c: SPEC_CONFLICT exit | stall | implement limit kill------> EXEC(sonnet) + one retry of that stage
53
+ EXEC(sonnet) --a or stall------------------------------------------------> fix round on opus (existing L1 path) -> STALLED
54
+ any state --harness/env/provider-owned ERROR-----------------------------> no transition (NOT PROVEN path)
55
+ ```
56
+ Per-unit rule (founder refinement 2026-10-07 21:45Z): a haiku unit that fails a code-owned check is redone on sonnet, then escalates to opus; a Wall assigned to haiku gets an Opus review before implement. The state machine above is the whole-run form and is read per unit. At most one Haiku -> Sonnet transition per run (whole-run form). A SPEC_CONFLICT confirmed by Sonnet stays BLOCKED. Resume across the swap: the fix session resumes the prior session id with the new model when the SDK honors `model` on `resume` (verified in R1-12); otherwise it starts fresh with the full brief plus the prior diagnosis and records `fix_resume_why`.
57
+
58
+ ### 4.4 Advisor wiring and fallback detection
59
+ - Wiring: SDK route passes `settings: { advisorModel }` (in SDK 0.3.288 `advisorModel` is a field of `interface Settings`, `sdk.d.ts:6674,8987`, not a top-level Option; R1-07 confirms the 0.3.293 shape). CLI route merges `advisorModel` into the existing `--settings` JSON or uses `--advisor` when `claudeFlagSupported` says so.
60
+ - Unavailable when any of: provider is not claude; `CLAUDE_CODE_USE_BEDROCK`, `CLAUDE_CODE_USE_VERTEX` or `CLAUDE_CODE_USE_FOUNDRY` is set; `ANTHROPIC_BASE_URL` points at a non-Anthropic host; the bundled or installed Claude Code is below 2.1.293; `LOKI_ROUTER_ADVISOR=off`; or a session reports an advisor tool error (sticky for the rest of the run, cached in runDir). Unavailable never fails a run: plan runs on Opus, the cascade still works, the receipt says `advisor: NOT PROVEN (owner provider): <reason>`. With the advisor unavailable, the executor is Sonnet 5.5 unless arm 4 of the B9 parity run shows Haiku without the advisor at parity; 11.1.0 ships Sonnet here (resolved in `decision.ts`, applied by R1-07 and R1-09), and only a later slice citing arm 4 METRICS.md rows may lower it to Haiku.
61
+ - Unknown to verify in R1-07: whether the engine10 `tools` whitelist (`providers.ts:512`, 6 tools) hides the server-side advisor tool.
62
+
63
+ ### 4.5 Context cost guard (keep requests under 100K, where the Haiku price is 5x lower)
64
+ Lean briefs and the cache-stable prefix already exist (`LOKI_E10_PREFIX=lean`, `providers.ts:524`). R1-07 adds `autoCompactWindow: 100000` (the SDK minimum, `sdk.d.ts` Settings) for routed sessions. R1-08 records per request `input+cache_read+cache_creation` and writes `requests_total`, `requests_over_100k` and advisor tokens into each cost event; the receipt shows the share.
65
+
66
+ ### 4.6 Per-shape defaults (a shape that fails parity routes to Sonnet instead of holding the release)
67
+ - Where it lives: `loki-ts/data/router-shape-defaults.json`, shipped in the package next to model-pricing.json. Schema `{"$schema_version":1, "_source":"<B9 run ids + RC version + date>", "shapes":{"<shape_key>":{"executor":"haiku"|"prior-default","evidence":"<METRICS.md row ref>"}}}`. Semantics inverted by the 2026-10-07 21:40Z CTO decision and refined by the founder at 21:45Z (D89 amendment): the default executor is Sonnet 5.5 and Haiku 5.5 is used per work unit when Opus assigns it. A shape is listed as `haiku` once it has earned it with a B9 row showing Haiku at outcome parity on that shape, and an absent listing means Sonnet 5.5. The shipped file and the R1-16 history are inputs to the Opus planning prompt, not harness routing rules; the harness never routes by task type or path regex (L0). `prior-default` (the `LOKI_ROUTER=0` model for that stage) stays legal for a shape where Sonnet also loses. The shipped file is empty (R1-16), so every shape starts on Sonnet.
68
+ - Shape key: Project Model `workspaceKind` plus the sorted, lowercased, de-duplicated package `runner` labels from `.loki/project.json` (both model-derived, L4; the schema has no language field, `project_model/schema.ts:20-30`, decided 2026-10-07 by the CoS after R1-16 found the gap), for example `multi-root:pytest+vitest`. A package with no runner contributes `none`. The same function (`shapeKey()` in history.ts) computes it at runtime and in the receipt (R1-15 writes `route.shape_key`), so B9 rows and runtime agree by construction. No file-pattern regex (L0).
69
+ - Seeding: `scripts/b9-scoreboard.sh --emit-shape-defaults <out.json>` (R1-17) reads each run's receipt `route.shape_key`, compares arm 2 (router) with arm 1 (raw) per shape on correctness, and lists every shape where router solve count < raw. A shape where Sonnet also loses on the confirming rerun is emitted as `prior-default`. R1-19 commits that output as the shipped file, citing the METRICS.md rows. Later B9 runs reseed it in a normal slice; removing a shape, or lowering it from `prior-default` to `sonnet`, needs a B9 row showing the lower executor at parity on it.
70
+ - Read path: `decision.ts` resolves the executor as the strongest of: Opus route, shipped shape default, per-repo history floor (R1-16, local runs; under the inverted semantics Haiku is reachable only when the shape is listed `haiku` and the history does not show Haiku losing 2 of the last 3 by code-owned FAIL or escalation -> Sonnet, cleared only by a B9 row showing Haiku at parity on that shape), the no-advisor floor (section 4.4), then Sonnet unless the shape is listed `haiku`. `prior-default` resolves to the exact `LOKI_ROUTER=0` model for that stage (R1-21 fixture semantics). Explicit `LOKI_MODEL_OVERRIDE`, `LOKI_CLAUDE_MODEL_DEVELOPMENT` or `LOKI_ROUTER_EXECUTOR` still win. Evidence rungs never lower a model: a shape default can only move the executor up. The shape key is a lookup into executed outcome evidence and may only move the executor up (ENGINE-LAWS H4); this is the documented exception to the L0 review rule. The receipt records `source: shape-default` with the evidence ref. Missing or corrupt file = empty map plus a NOT PROVEN line, never a crash.
71
+
72
+ ## 5. Knobs
73
+ `LOKI_ROUTER` (unset = off while building; unset = on after R1-19; `0` = opt-out to pre-router behavior), `LOKI_ROUTER_EXECUTOR` (post-flip default sonnet; haiku only by earned evidence), `LOKI_ROUTER_ESCALATE` (default sonnet), `LOKI_ROUTER_ADVISOR` (default opus; `off` disables). `LOKI_MODEL_OVERRIDE` and explicit `LOKI_CLAUDE_MODEL_DEVELOPMENT` still win and bypass the router (recorded `source: override`).
74
+
75
+ ## 6. Slices
76
+ Tier sets the review (D12): LOW/MEDIUM by Tech Leads, HIGH by opus reviewers, unanimous. Every TS slice rebuilds dist in the main checkout before its train (memory: symlinked node_modules), runs `bash scripts/local-ci.sh`, and keeps `LOKI_ROUTER` unset behavior byte-identical (existing suites green). File sets do not overlap; `runner/router/flag.ts` (created by R1-05) and `loki-ts/data/router-shape-defaults.json` (created empty by R1-16) are edited only by R1-19, after every other slice has merged, so no two slices touch them concurrently.
77
+
78
+ | id | goal | file set | tier | builder | red-then-green test | Wall check | deps |
79
+ |---|---|---|---|---|---|---|---|
80
+ | R1-01 | Agent SDK 0.3.288 -> 0.3.293 (bundled Claude Code >= 2.1.293, needed by the advisor) | package.json, loki-ts/package.json, bun.lock, loki-ts/bun.lock, loki-ts/tests/runner/sdk_version_floor.test.ts | MEDIUM | sonnet | new test asserts installed SDK >= 0.3.293 and its package.json claudeCodeVersion >= 2.1.293 (red today: 0.3.288 / 2.1.288; root node_modules is even 0.3.283) | full bun test + tsc; `bun install` in the main checkout; one real `loki start` smoke on a fixture | none |
81
+ | R1-02 | Haiku 5.5 price, exact-id key, >100K tier | loki-ts/data/model-pricing.json, loki-ts/src/runner/budget.ts, autonomy/run.sh (`_write_pricing_json` only, `:7570-7590`), tools/estimate-run.py, loki-ts/tests/runner/budget_haiku55.test.ts | MEDIUM | sonnet | STEP 1: read the Anthropic pricing page (platform.claude.com/docs/en/about-claude/pricing) and record URL + date in `_source`; if it does not show Haiku 5.5, STOP and report (never write an unverified price). Test: 1M input on `claude-haiku-5-5` prices $0.10 and `claude-haiku-4-5` stays $1.00 (red today: family substring match, `budget.ts:495`); above-100K fields priced | budget suites + estimate-run smoke | none |
82
+ | R1-03 | Catalog: claude-haiku-5-5 and claude-sonnet-5-5, aliases | providers/model_catalog.json, providers/models.sh, loki-ts/tests/providers/model_catalog_router.test.ts | MEDIUM | sonnet | STEP 1: real calls `claude -p --model haiku` and `--model sonnet`, record canonicalModel. Test: aliases resolve to the verified ids via `resolveModelAlias` (`sizing.ts:58`) (red: haiku -> claude-haiku-4-5, no sonnet-5-5 entry) | tests/test-provider-loader.sh, model catalog tests | none |
83
+ | R1-04 | L1 amendment (outcome parity), define H4, record D89 | docs/v10/ENGINE-LAWS.md, docs/v10/DECISIONS.md | HIGH | sonnet | doc lint: no em/en dashes; L1 text names outcome parity, the escalation ladder and the advisor requirement | CTO approval; founder directive quoted in D89; D89 records default-on only after the R1-19 gate | none |
84
+ | R1-05 | Router core: schema, parser, executor resolution, escalation state machine, flag | loki-ts/src/runner/router/decision.ts, loki-ts/src/runner/router/flag.ts, loki-ts/tests/runner/router_decision.test.ts | MEDIUM | sonnet | table test of every transition in 4.3, including harness-owned ERROR = no transition and a single Haiku -> Sonnet swap; invalid JSON -> default + NOT PROVEN; advisor unavailable raises a `haiku` route to sonnet; `prior-default` resolves to the LOKI_ROUTER=0 model | tsc; l0_guard green (no repo-shape regex) | R1-16 |
85
+ | R1-06 | Advisor availability probe | loki-ts/src/runner/router/advisor_probe.ts, loki-ts/tests/runner/advisor_probe.test.ts | MEDIUM | sonnet | each unavailable condition in 4.4 yields `{available:false, reason}`; sticky runtime marker read from runDir | fixtures for Bedrock, Vertex, Foundry, gateway URL, old CLI | none |
86
+ | R1-07 | Wire advisorModel and autoCompactWindow into SDK and CLI sessions | loki-ts/src/runner/providers.ts, loki-ts/tests/runner/providers_advisor.test.ts | HIGH | sonnet | buildSdkLoopOptions under LOKI_ROUTER=1 carries `settings.advisorModel` and `autoCompactWindow`, absent when unavailable or flag off; with the advisor unavailable the routed session model is sonnet, never haiku; CLI argv carries it | STEP: one real `claude -p --model haiku` run with the advisor that consults it; prove advisor usage appears in the stream and the 6-tool whitelist does not hide it; record output | R1-01, R1-06 |
87
+ | R1-08 | Telemetry: per-request size, advisor calls and tokens | loki-ts/src/runner/sdk_stream_parser.ts, loki-ts/src/engine10/cost.ts, loki-ts/tests/runner/sdk_stream_router_usage.test.ts | MEDIUM | sonnet | recorded stream fixture with a 120K request and an advisor call yields requests_over_100k=1 and advisor tokens (red: fields absent) | cost suites; partial-stream path unchanged | R1-01 |
88
+ | R1-09 | Session plumbing: LOKI_ESCALATE marker, cost event fields | loki-ts/src/engine10/session.ts, loki-ts/src/engine10/types.ts, loki-ts/tests/engine10/session_router.test.ts | MEDIUM | sonnet | `LOKI_ESCALATE: <reason>` parses into markers.escalate; cost event carries R1-08 fields; with the advisor unavailable the child env pins the executor tier to sonnet (no-advisor executor is Sonnet, section 4.4); supervisor event validator still accepts | session + supervisor suites | R1-08 |
89
+ | R1-10 | Plan-time route by Opus | loki-ts/src/engine10/stages/plan.ts, loki-ts/tests/engine10/plan_route.test.ts | HIGH | sonnet | flag on: brief asks for `route` JSON after consulting the advisor; advisor unavailable: plan session pinned to opus and a `haiku` route is raised to sonnet; flag off: brief byte-identical | real plan run on FireLater#17 writes a valid route | R1-05, R1-06 |
90
+ | R1-11 | Implement on the routed executor; triggers b and c | loki-ts/src/engine10/stages/implement.ts, loki-ts/tests/engine10/implement_router.test.ts | HIGH | sonnet | route event emitted with source; SPEC_CONFLICT on haiku retries once on sonnet and stays BLOCKED only when sonnet agrees; LOKI_ESCALATE switches the rest of the run | fake-session e2e for each trigger | R1-05, R1-09, R1-10 |
91
+ | R1-12 | Fix rounds: trigger a, ladder haiku -> sonnet -> opus, resume across swap | loki-ts/src/engine10/stages/fix.ts, loki-ts/src/runner/model_rank.ts, loki-ts/src/runner/session_resume.ts, loki-ts/tests/engine10/fix_router.test.ts | HIGH | sonnet | repeated code-owned FAIL on haiku -> sonnet; on sonnet -> opus; harness-owned never escalates; resume keeps the session when the SDK honors the new model (STEP: verify with a real resume) else records why | never_below_raw "escalated model at or above run model" still green | R1-05, R1-11 |
92
+ | R1-13 | Stall and limit-kill escalation before STALLED | loki-ts/src/engine10/machine.ts, loki-ts/tests/engine10/machine_router.test.ts | HIGH | sonnet | a 3x identical code-owned signature on haiku gets one sonnet round instead of STALLED; harness-owned stall unchanged | machine + fatal e2e suites | R1-12 |
93
+ | R1-14 | Replace sonnet pins and the downgrade list with the router | loki-ts/src/runner/model_downgrades.ts, loki-ts/src/engine10/sizing.ts, loki-ts/src/engine10/stages/wall.ts, loki-ts/src/engine10/already_done.ts, loki-ts/tests/engine10/never_below_raw.test.ts | HIGH | sonnet | flag on: Wall, plan, already-done use the routed executor + advisor and the downgrade list is replaced by the route record; guard allowlist adds `routedModel()` with a mutation test (an unconditional haiku pin without the router still fails) | l0_guard and never_below_raw green | R1-04, R1-05 |
94
+ | R1-15 | Start line, receipt route block, PR line | loki-ts/src/engine10/supervisor.ts, loki-ts/src/engine10/stages/seal.ts, loki-ts/src/engine10/pr_body.ts, loki-ts/tests/engine10/route_receipt_golden.test.ts | MEDIUM | sonnet | golden: `executor haiku-5.5, advisor opus: <reason>`; receipt lists `route.shape_key`, escalations with trigger and evidence, advisor NOT PROVEN with owner, >100K share; `route.shape_parity: NOT PROVEN` for a shape with no B9 row (D89 item 10); flag off byte-identical (receipt hash stable) | pr_body_golden, portable_receipt, seal suites | R1-05, R1-06, R1-11 |
95
+ | R1-16 | Per-shape outcome history (H4) | loki-ts/src/runner/router/history.ts, loki-ts/src/e10ext/repomemory.ts, loki-ts/tests/runner/router_history.test.ts | MEDIUM | haiku | append/read in the per-repo cache dir; shape key from Project Model workspaceKind + sorted runner labels (model-derived, L4), never from file regex; floor: haiku lost 2 of last 3 on the shape (code-owned FAIL or escalation; harness, env and provider ERRORs do not count) -> sonnet, cleared only by a B9 row showing Haiku at parity on that shape; fixture: 3 harness-owned FAILs on haiku do NOT trigger the floor. Also creates the empty shipped `loki-ts/data/router-shape-defaults.json` and its reader `shapeDefault(key)` (section 4.6), which accepts `sonnet` and `prior-default` and rejects any other value (cold read + NOT PROVEN) | corrupt file is a cold read, never a crash | none |
96
+ | R1-17 | B9 scoreboard harness | scripts/b9-scoreboard.sh, tests/test-b9-scoreboard.sh, tests/run-all-tests.sh (registration + shard row) | MEDIUM | sonnet | dry-run with a stub `claude` produces one METRICS row per arm with solve, wall seconds, usd, shape_key; `--emit-shape-defaults` on a fixture where the router loses one shape lists exactly that shape as `sonnet`; a fixture where the Sonnet confirming rerun also loses emits it as `prior-default` | shellcheck, `timeout -k`, runner registration guard (memory: new test file structural guards) | none |
97
+ | R1-18 | Docs: GUIDE model-routing section, CHANGELOG | docs/v10/GUIDE.md, CHANGELOG.md | LOW | haiku | doc lint; GUIDE names every knob in section 5 and the fallback | Release Manager reads it against the receipt | R1-15 |
98
+ | R1-19 | Final flip after the CTO gate: LOKI_ROUTER default ON with Sonnet 5.5 + Opus 5.5 advisor as the default executor (11.1.0 and 11.2.0 still ship OFF); Haiku 5.5 per work unit only when Opus assigns it in the plan, per-unit schema `units: [{id, kind, executor, reason}]` (11.2.0 or 11.2.1); ship seeded shape defaults (`haiku` only for earned shapes) | loki-ts/src/runner/router/flag.ts, loki-ts/data/router-shape-defaults.json, loki-ts/tests/runner/router_flag_default.test.ts | HIGH | sonnet | red: unset env resolves off; green: unset resolves on, `0`/`off`/`false` resolve off; R1-21 opt-out golden still green with `LOKI_ROUTER=0` | GATE (all on the release candidate SHA): steering's FireLater#17 gate green (VERIFIED, ready PR, time within raw + 30s, cost <= raw x 1.2); B9 correctness parity with raw `claude -p` on the Sonnet default and on every shape listed `haiku` (a shape with no evidence stays on Sonnet); arm 4 correctness parity, or the Sonnet no-advisor fallback in place (R1-07, R1-09); every shape listed as `prior-default` runs the exact LOKI_ROUTER=0 models (R1-21 golden per listed shape); the seeded file committed with its METRICS.md refs | all |
99
+ | R1-21 | Opt-out golden: `LOKI_ROUTER=0` equals pre-router behavior exactly | loki-ts/tests/engine10/router_optout_golden.test.ts, loki-ts/tests/engine10/fixtures/pre_router_models.json | HIGH | sonnet | fixture captured on 11.0.3 code BEFORE any router slice merges: for an env matrix (default; LOKI_E10_CASCADE=1; LOKI_E10_WALL_TIER=haiku; LOKI_ALLOW_HAIKU=true; LOKI_MODEL_OVERRIDE=sonnet; LOKI_CLAUDE_MODEL_DEVELOPMENT=opus; LOKI_E10_PLAN=always) it records, per stage (plan, wall, already_done, implement, fix round 1 and escalated round 2), the model passed to sessions.run, the child-env LOKI_CLAUDE_MODEL_* values, the SDK query options model/fallbackModel/settings, the downgrade list, the start line and the run.started keys. The test replays the matrix through fake sessions with `LOKI_ROUTER=0` (and unset, until R1-19) and requires deep equality. Mutation: changing wallModel's default or adding `settings.advisorModel` under `0` turns it red | runs in the fast tier; must be green on every slice's train | none (lands first in W1) |
100
+ | R1-20 | `loki doctor` shows advisor availability and bundled CC version | loki-ts/src/commands/doctor.ts, loki-ts/tests/commands/doctor_router.test.ts | LOW | haiku | doctor prints `advisor: available` or the reason from R1-06 | doctor suites | R1-06 |
101
+
102
+ Parallel waves: W1 = R1-21 (merge first, it captures the baseline), R1-01, R1-02, R1-03, R1-04, R1-06, R1-16, R1-17 (8 independent). W2 = R1-05, R1-07, R1-08, R1-20. W3 = R1-09, R1-10, R1-14. W4 = R1-11, then R1-12, R1-15. W5 = R1-13, R1-18. W6 = release candidate built with the flag ON in env, FireLater#17 gate + B9 runs, `--emit-shape-defaults`, then R1-19.
103
+ Critical path: R1-01 -> R1-08 -> R1-09 -> R1-11 -> R1-12 -> R1-13 -> RC + FireLater#17 gate + B9 -> R1-19 (R1-07 and R1-10 join at R1-11; R1-02 price confirmation gates R1-19).
104
+
105
+ ## 7. Whole-feature Wall and B9 parity measurement
106
+ Corpus: B9 rows in RELEASE-11.md (FireLater#17, augmentiq#52, the small fixture) plus one Repo Shape Matrix shape per ENGINE-LAWS section 4 that is already runnable (single npm, python uv). Same base SHA per arm, hidden tests judge correctness.
107
+ Arms (n=3 per repo per arm; a 0/3 needs a positive control first):
108
+ 1. raw `claude -p` on the account default (the L1 baseline).
109
+ 2. Loki 11.1.0, `LOKI_ROUTER=1` (Haiku 5.5 + Opus advisor + cascade).
110
+ 3. Loki 11.1.0, `LOKI_ROUTER=0` (today's behavior, attribution control).
111
+ 4. Loki, `LOKI_ROUTER=1 LOKI_ROUTER_ADVISOR=off` (fallback path, proves "never fail a run for it").
112
+ Metrics per run: solved (hidden tests), wall seconds, usd (SDK total_cost_usd, including advisor tokens), escalations taken, share of requests above 100K, advisor consultations.
113
+ Pass: arm 2 solve rate >= arm 1 on every repo; time within raw + 30s (small) or raw x 1.3; cost <= raw x 1.2 (expected well below); zero harness-owned FAILED/STALLED; arm 4 completes every run with advisor NOT PROVEN recorded, and its solve rate is >= arm 1 on every repo; if not, the no-advisor executor is Sonnet 5.5 (section 4.4). Rows go to docs/v10/METRICS.md with commands and exit codes. A correctness loss on a shape does NOT hold the release: `--emit-shape-defaults` lists it, R1-19 ships it in `router-shape-defaults.json`, and that shape runs on Sonnet (+ Opus advisor) by default (section 4.6). Before R1-19 merges, rerun B9 on the losing shape with the seeded file present to confirm Sonnet reaches parity there; if Sonnet also loses, it ships as `prior-default` in router-shape-defaults.json, plus a FAILURE-CLASSES row; it is not a release blocker for other shapes. Time and cost misses on a shape are recorded and routed the same way. FireLater#17 is binding: it must pass on whatever executor its shape resolves to. The R1-19 gate also requires arm 4 correctness parity (or the Sonnet no-advisor fallback in place) and that every `prior-default` shape runs the exact `LOKI_ROUTER=0` models.
114
+ Budget: B9 runs count inside the 10% measurement budget; the Chief of Staff runs them, not a slice builder.
115
+
116
+ ## 8. Risks and open questions
117
+ 1. Price unverified: $0.10/$0.50 (<=100K) and $0.50/$2.50 (>100K), cache read $0.01/$0.05, are steering-reported. R1-02 step 1 confirms on the Anthropic pricing page or blocks. Engine10 run dollars come from the SDK, so a wrong table only skews partial streams and estimates, but receipts would still be wrong there.
118
+ 2. Advisor via SDK: the 0.3.293 Options shape for advisorModel, whether the engine10 tool whitelist and `settingSources: ["project"]` keep it, and how advisor tokens show in `modelUsage`. R1-07 proves it with a real run before HIGH review.
119
+ 3. Resume across a model swap: refused today (`session_resume.ts:41`); SDK behavior of `resume` + new `model` is unverified (R1-12 step).
120
+ 4. Gateways: a proxy that forwards to the Anthropic API might support the advisor even with a custom `ANTHROPIC_BASE_URL`; the probe treats it as unavailable (safe, costs some quality). Revisit with field data.
121
+ 5. Haiku default reach: `LOKI_ALLOW_HAIKU` gates haiku everywhere else (`providers/claude.sh:47-79`, `claude_flags.ts:153`). The router bypasses it only on the engine10 path under the flag; the legacy route is unchanged. Decide later whether the legacy route follows.
122
+ 6. Cost of advisor at Opus rates on long sessions could erase the Haiku saving; the B9 cost column and >100K share decide. If cost > raw x 1.2 on a shape, `--emit-shape-defaults` lists it (Sonnet, or `prior-default` if Sonnet also misses).
123
+ 7. Rate limits: Haiku 5.5 is one day old; `fallbackForPrimary` (`claude_flags.ts:155`) has no haiku arm, so a haiku 429 has no fallback model. R1-07 adds `fallbackModel: sonnet` for a haiku primary.
124
+ 8. Requested removal of "hand-rolled opus review stages the advisor covers": none exist in engine10 (xreview is an opt-in second provider, `stages/xreview.ts`; the council reviewer runs on the account default). Nothing to delete; the advisor is additive.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema_version": 1,
3
3
  "_comment": "Rolling pricing table consumed by loki-ts/src/runner/budget.ts. Update this file when Anthropic / OpenAI / others publish new prices; no code change required. Pricing is USD per 1 million tokens. Aliases (opus/sonnet/haiku) point to the latest model of that family per providers/model_catalog.json.",
4
- "_updated": "2026-10-03",
5
- "_source": "https://www.anthropic.com/pricing + provider docs. sonnet=claude-sonnet-5 and claude-sonnet-5-5, both $2/$10 per MTok (the Sonnet 5 intro price became the standard price; the 2026-09-01 increase to $3/$15 will not occur), cache write 5m $2.50, cache read $0.20, 1M context at standard pricing (platform.claude.com/docs/en/about-claude/pricing, read 2026-10-03). opus=claude-opus-5. codex=gpt-5.3-codex standard tier. Cache tiers: read 0.1x input, write 1.25x input (Anthropic + OpenAI published multipliers).",
4
+ "_updated": "2026-10-07",
5
+ "_source": "https://www.anthropic.com/pricing + provider docs. sonnet=claude-sonnet-5 and claude-sonnet-5-5, both $2/$10 per MTok (the Sonnet 5 intro price became the standard price; the 2026-09-01 increase to $3/$15 will not occur), cache write 5m $2.50, cache read $0.20, 1M context at standard pricing (platform.claude.com/docs/en/about-claude/pricing, read 2026-10-03). claude-haiku-5-5 (exact-id key; the haiku alias stays Haiku 4.5 at $1/$5): $0.10 in / $0.50 out / cache write 5m $0.125 / cache read $0.01 for prompts up to 100,000 tokens, and $0.50 / $2.50 / $0.625 / $0.05 over 100,000 tokens in over_100k (https://platform.claude.com/docs/en/about-claude/pricing, read 2026-10-07). opus=claude-opus-5. codex=gpt-5.3-codex standard tier. Cache tiers: read 0.1x input, write 1.25x input (Anthropic + OpenAI published multipliers).",
6
6
  "pricing": {
7
7
  "fable": {
8
8
  "input": 10.0,
@@ -28,6 +28,18 @@
28
28
  "cache_read": 0.1,
29
29
  "cache_write": 1.25
30
30
  },
31
+ "claude-haiku-5-5": {
32
+ "input": 0.1,
33
+ "output": 0.5,
34
+ "cache_read": 0.01,
35
+ "cache_write": 0.125,
36
+ "over_100k": {
37
+ "input": 0.5,
38
+ "output": 2.5,
39
+ "cache_read": 0.05,
40
+ "cache_write": 0.625
41
+ }
42
+ },
31
43
  "gpt-5.3-codex": {
32
44
  "input": 1.75,
33
45
  "output": 14.0,
@@ -0,0 +1 @@
1
+ {"$schema_version":1,"_source":"created empty by R1-16; seeded by R1-19 from B9 METRICS.md rows","shapes":{}}