loki-mode 11.17.6 → 11.17.13

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 (84) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/lib/cost-summary.py +5 -2
  4. package/autonomy/lib/efficiency_cost.py +21 -1
  5. package/autonomy/lib/proof-generator.py +5 -0
  6. package/autonomy/lib/proof-template.html +21 -6
  7. package/autonomy/lib/trust_trajectory.py +11 -1
  8. package/autonomy/loki +42 -28
  9. package/completions/_loki +1 -0
  10. package/completions/loki.bash +1 -1
  11. package/dashboard/__init__.py +1 -1
  12. package/docs/CLI-REFERENCE.md +1 -1
  13. package/docs/INSTALLATION.md +1 -1
  14. package/docs/v10/BOARD.md +108 -4
  15. package/docs/v10/FAILURE-CLASSES.md +106 -2
  16. package/docs/v10/MODERNIZE.md +7 -1
  17. package/docs/v10/PROGRESS.md +10 -0
  18. package/loki-ts/dist/loki.js +1014 -999
  19. package/mcp/__init__.py +1 -1
  20. package/package.json +2 -2
  21. package/packages/control-plane/dist/ask-tools-server.js +218 -12
  22. package/packages/control-plane/dist/server.js +719 -593
  23. package/packages/control-plane/src/server/diffstat.ts +2 -2
  24. package/packages/control-plane/src/server/routes/checkpoints.ts +2 -2
  25. package/packages/control-plane/src/server/routes/integrations.ts +1 -1
  26. package/packages/control-plane/src/shipper/discover.ts +2 -2
  27. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  28. package/web-app/dist/assets/{AdminPage-CCedYmn3.js → AdminPage-CwtSZac4.js} +1 -1
  29. package/web-app/dist/assets/{Avatar-DMrDsuGe.js → Avatar-BfguNHDC.js} +1 -1
  30. package/web-app/dist/assets/{Badge-K4Ui2tJz.js → Badge-DQGEOIqb.js} +1 -1
  31. package/web-app/dist/assets/{Button-Bhjts5QZ.js → Button-CRb-wJga.js} +1 -1
  32. package/web-app/dist/assets/{CockpitPage-Be7sEVqh.js → CockpitPage-DnA9wewN.js} +1 -1
  33. package/web-app/dist/assets/{ComparePage-D4ty3jiF.js → ComparePage-DX6F_G0l.js} +1 -1
  34. package/web-app/dist/assets/{ErrorBoundary-Cmt2x_mL.js → ErrorBoundary-VVIdgfkb.js} +1 -1
  35. package/web-app/dist/assets/{EvidenceReceiptPanel-D2IXLnp9.js → EvidenceReceiptPanel-FxknNXxU.js} +1 -1
  36. package/web-app/dist/assets/{GitHubIssuesPanel-CyXitr6h.js → GitHubIssuesPanel-DqiraoJP.js} +1 -1
  37. package/web-app/dist/assets/{GitHubPRsPanel-RRM3H-xd.js → GitHubPRsPanel-BYkTsRfQ.js} +1 -1
  38. package/web-app/dist/assets/{HomePage-CMtrrgfs.js → HomePage-BjpWZdl4.js} +2 -2
  39. package/web-app/dist/assets/{LoginPage-BrzNhnMJ.js → LoginPage-DdBnFY4Y.js} +1 -1
  40. package/web-app/dist/assets/{MagicPage-D7VynOKM.js → MagicPage-ihQmO1wm.js} +1 -1
  41. package/web-app/dist/assets/{MetricsPage-DJ-gDbfP.js → MetricsPage-Dq5YARm1.js} +1 -1
  42. package/web-app/dist/assets/{NotFoundPage-BJh0XVTj.js → NotFoundPage-CLzwsmxk.js} +1 -1
  43. package/web-app/dist/assets/{ProjectPage-CAodVUpE.js → ProjectPage-Dm8X4ntm.js} +3 -3
  44. package/web-app/dist/assets/{ProjectsPage-m3siS0Rf.js → ProjectsPage-DI3PhBwa.js} +1 -1
  45. package/web-app/dist/assets/{SettingsPage-CFGgjOvy.js → SettingsPage-D3bL3Ll-.js} +1 -1
  46. package/web-app/dist/assets/{ShowcasePage-Dd9tpSKJ.js → ShowcasePage-ypNyQAKe.js} +1 -1
  47. package/web-app/dist/assets/{SystemSettingsPage-DXd0PtTI.js → SystemSettingsPage-a9KPi49-.js} +1 -1
  48. package/web-app/dist/assets/{TeamsPage-C5KaLIGW.js → TeamsPage-B2KmQjeS.js} +1 -1
  49. package/web-app/dist/assets/{TemplatesPage-CDbzE0ZZ.js → TemplatesPage-BnK5NB62.js} +1 -1
  50. package/web-app/dist/assets/{TerminalOutput-CKG79r_-.js → TerminalOutput-CYbPu51X.js} +1 -1
  51. package/web-app/dist/assets/{activity-BaQQRhDp.js → activity-DBIfCcER.js} +1 -1
  52. package/web-app/dist/assets/{bell-OeFqvU4e.js → bell-B9HN4QkY.js} +1 -1
  53. package/web-app/dist/assets/{bot-CSxaA0KU.js → bot-DamtEiBN.js} +1 -1
  54. package/web-app/dist/assets/{check-DJml2Xdn.js → check-DXifl-uv.js} +1 -1
  55. package/web-app/dist/assets/{chevron-left-DGnt-DtK.js → chevron-left-BrlJBb8m.js} +1 -1
  56. package/web-app/dist/assets/{circle-alert-BV5rVL7K.js → circle-alert-CVKCTAb9.js} +1 -1
  57. package/web-app/dist/assets/{clock-CZ7SvULz.js → clock-HQ6E5gSp.js} +1 -1
  58. package/web-app/dist/assets/{cloud-lkIzrZps.js → cloud-B15Ysqug.js} +1 -1
  59. package/web-app/dist/assets/{code-xml-DzA2wL8F.js → code-xml-hqFIp0_h.js} +1 -1
  60. package/web-app/dist/assets/{database-CLFG5upC.js → database-CcSm0M_K.js} +1 -1
  61. package/web-app/dist/assets/{dollar-sign-DgWePGsv.js → dollar-sign-acxpddMc.js} +1 -1
  62. package/web-app/dist/assets/{file-code-corner-DGQX2bmv.js → file-code-corner-B5IIv12W.js} +1 -1
  63. package/web-app/dist/assets/{file-plus-LkaXeYd6.js → file-plus-CkbMFWJb.js} +1 -1
  64. package/web-app/dist/assets/{globe-rSsEzPYv.js → globe-CWmZ3xTF.js} +1 -1
  65. package/web-app/dist/assets/{hammer-CPogONt9.js → hammer-BSaCsCAo.js} +1 -1
  66. package/web-app/dist/assets/{index-DpBLuMuz.js → index-BCf0fCNu.js} +3 -3
  67. package/web-app/dist/assets/{layers-CwFaqidn.js → layers-CL82nJ3b.js} +1 -1
  68. package/web-app/dist/assets/{loader-circle-C43izEm5.js → loader-circle-DBhm8R7M.js} +1 -1
  69. package/web-app/dist/assets/{lock-Bc_Uqxpp.js → lock-wWcqImfq.js} +1 -1
  70. package/web-app/dist/assets/{package-BM25lcR-.js → package-BaZa22IO.js} +1 -1
  71. package/web-app/dist/assets/{plus-D0xoiY6N.js → plus-TFOQPEeK.js} +1 -1
  72. package/web-app/dist/assets/{refresh-cw-COI1R5Oo.js → refresh-cw-BOKfYIta.js} +1 -1
  73. package/web-app/dist/assets/{rotate-ccw-BoNZx4xe.js → rotate-ccw-DrH5oGwW.js} +1 -1
  74. package/web-app/dist/assets/{scroll-text-Cakp8XHd.js → scroll-text-aY8_wIJd.js} +1 -1
  75. package/web-app/dist/assets/{server-CjfIlPmE.js → server-C6FQ01rB.js} +1 -1
  76. package/web-app/dist/assets/{shield-alert-BilhziJF.js → shield-alert-DurYyWUo.js} +1 -1
  77. package/web-app/dist/assets/{thumbs-up-CglMrtrt.js → thumbs-up-wUuSs67Q.js} +1 -1
  78. package/web-app/dist/assets/{trash-2-B6zVvnoG.js → trash-2-DAob0LKZ.js} +1 -1
  79. package/web-app/dist/assets/{trending-down-BVhwD9bt.js → trending-down-yKL9mp2O.js} +1 -1
  80. package/web-app/dist/assets/{trending-up-CVJ1ox6c.js → trending-up-BD55eCE3.js} +1 -1
  81. package/web-app/dist/assets/{upload-DmuR09WL.js → upload-0IJxnT31.js} +1 -1
  82. package/web-app/dist/assets/{usePolling-BTALfO91.js → usePolling-DuBiboP5.js} +1 -1
  83. package/web-app/dist/assets/{user-CRdHMZNH.js → user-BDw_rGaY.js} +1 -1
  84. package/web-app/dist/index.html +1 -1
@@ -137,7 +137,7 @@ L0 review rule (ENGINE-LAWS.md L0): a fix that adds an `if` or a regex about the
137
137
  - Mechanism: one verdict-display function that returns TAMPERED whenever the run is tampered or its seal is invalid (CPE-27).
138
138
  - Fixture: an ingested run with tamper.detected never shows VERIFIED in any surface.
139
139
  - Sibling follow-up (EL-FC08b): redact at source in the engine before hashing. Today the shipper (redactEvent) and the server (redactSecrets) rewrite event data before the CP can hash it, so an honest signed run holding a token reads UNVERIFIED ("log redacted before ingest; seal not checkable"), never TAMPERED and never VERIFIED. Redacting before the engine hashes and signs would make such runs checkable end to end.
140
- - Sibling follow-up (deferred, not built in EL-FC08b): the shipper should send the sha256 of each line before redaction (alongside the redacted line). The CP could then check the seal over the original hashes and tell a genuine redaction from a downgrade (a FAILED log edited to PARTIAL plus a planted [REDACTED]); today such a log can only read "<verdict> (unattested)" or UNVERIFIED. This is the lasting fix for placeholder downgrades.
140
+ - Sibling follow-up (deferred, not built in EL-FC08b): the shipper should send the sha256 of each line before redaction (alongside the redacted line). The CP could then check the seal over the original hashes and tell a genuine redaction from a downgrade (a FAILED log edited to PARTIAL plus a planted [REDACTED]); today such a log can only read "<verdict> (unattested)" or UNVERIFIED. This is the lasting fix for placeholder downgrades. REJECTED 2026-10-17 (Q17-05, HIGH r1 on 36524784d): a client-supplied original hash cannot be checked by the server, so a forger copies log.sealed events_sha256 into the shipped chain and a FAILED run displays VERIFIED; the chain is also unbound to the run id, so any signed seal replays onto any log. Rule: the CP never accepts a client-supplied hash in place of recomputing one over the bytes it received. The lasting fix is the line above: redact in the engine before hashing and signing (Q17-05b).
141
141
  - Sibling follow-up: the Slack summary, PR status and `loki status` do not yet read the CP effective_verdict.
142
142
 
143
143
  ## FC-09 A test-config edit outside scope can make broken code VERIFIED
@@ -152,6 +152,7 @@ L0 review rule (ENGINE-LAWS.md L0): a fix that adds an `if` or a regex about the
152
152
  - Status (FC-09r): mechanism in `loki-ts/src/features/runner_config.ts`, read by verify.ts (testConfigChanged, base vs working tree) and seal.ts (runnerConfigNotes, base vs head, adds a NOT PROVEN line so the verdict cannot be VERIFIED). Fixtures: `loki-ts/tests/engine10/runner_config.test.ts` (real commit + seal stages).
153
153
  - Covered: bunfig.toml; vitest, vite, jest config and vitest.workspace; .mocharc; pytest.ini, tox.ini, conftest.py; pyproject.toml and setup.cfg pytest sections; .cargo/config.toml; preload, setupFiles, globalSetup and exact-file moduleNameMapper targets (jest rootDir resolved, explicit rootDir fails closed); `__mocks__/`; package.json scripts and resolution redirects; go.mod and go.work replace; Cargo.toml patch and replace; tsconfig paths; a changed config that fails to parse is capped, an unchanged broken one is not.
154
154
  - Deferred: transitive imports of setup files, pytest `-p` plugins and `pytest_plugins`, .mocharc `require`/`spec` targets, setupFiles given as identifiers or globs, Makefile go test flags.
155
+ - FC-09w (P1, reproduced 2026-10-17 by the FC-09v r2 HIGH review): every RUNNER_CONFIGS pattern is case-sensitive, but macOS filesystems are case-insensitive, so adding `PNPM-Workspace.yaml` or `.YARNRC.yml` is not capped (notes 0) while real pnpm 11.1.3 reads the capitalized file. Siblings: every registry row (jest, vitest, bunfig, conftest and the rest). Mechanism: match case-insensitively across the whole registry in one place. Fixture: capitalized variants of each row cap in loki-ts/tests/engine10 runner_config tests. Also open (P2): patchedDependencies targets outside patches/ with non-.patch names, and .npmrc (registry=) are not in the registry.
155
156
 
156
157
  ## FC-10 Live line truncated to ~20 columns on a pty with no size
157
158
  - User saw: on a pty with no column size (script -q, CI, tmux before a resize, IDE terminals) the quiet-mode live status line was cut to about 20 characters, for example "[implement] implemen". Raw: the stage events were complete; only the rendering was wrong.
@@ -642,6 +643,7 @@ L0 review rule (ENGINE-LAWS.md L0): a fix that adds an `if` or a regex about the
642
643
  - Law: evidence or it did not happen; a green that cannot go red is not a gate. Guard class: the root cause is FC-67 (WALL-NOTRUN holds that row); this row is the detection layer.
643
644
  - Siblings: any other check a receipt could lose without a failing exit (lint, mutation proof, cross review) is not yet counted; the guard asserts only checks[] executed >= 2 and the Wall test.
644
645
  - Mechanism: scripts/assert-wall-executed.sh reads the keys seal.ts writes (checks[].result, wall.files, wall.passed, not_proven[]). scripts/real-run.sh applies it to scenarios with SC_WALL_EXECUTED=1 (trivial-sum, two-bug). Post-Release Smoke npm-smoke runs it as a blocking step.
646
+ - Q17-04 sibling guard: a scenario sets SC_EXPECT_CHECKS=lint,mutation,review and assert-wall-executed.sh (3rd arg) fails when a named check is absent or not_run in checks[]; unset keeps today's behavior.
645
647
  - Limit: the real trivial-sum and two-bug runs are billed and CI has no provider key, so Post-Release Smoke cannot run them unattended; the blocking step proves the guard logic on the released commit and runs the real scenario when a key is supplied.
646
648
  - Fixture: tests/test-wall-executed-guard.sh (11.3.1 shape passes, 11.3.2 shape fails, each leg alone fails).
647
649
 
@@ -853,7 +855,7 @@ L0 review rule (ENGINE-LAWS.md L0): a fix that adds an `if` or a regex about the
853
855
  - Siblings swept: verify.ts already reruns once and marks fail-then-pass "flaky" (the evidence source); retry_class.ts classifyFailure is unchanged; the permanent-failure stop and the repeated-signature breaker still run before any new class.
854
856
  - Mechanism: recovery_policy.ts adds RecoverySignals rerun (same non-empty tree on fail and pass), protocolError and conflictingRequirements. Results: flaky -> retry, protocol_error -> revise, conflicting_requirements -> escalate. util/failure_memory.ts recordFingerprints (extends the existing failure-memory owner; flaky.json and failures.jsonl keep no per-run rows) appends fingerprints to .loki/state/fingerprints.jsonl (append-only, newest 200 kept) and supervisor.ts feeds verify's flaky list into it and the summary.
855
857
  - Fixture: loki-ts/tests/runner/harness_intelligence.test.ts "P12-11 recovery classes (FC-REQ)" (classifier table, fingerprints across two runs, bound).
856
- - Known limits: protocolError and conflictingRequirements have no producer wired yet (callers must set them from structured signals); fingerprints are recorded for flaky only and not yet read back by a policy rule; verify's flaky list is not yet fed to decideRecovery as a rerun signal (follow-up); engine10 renderMainOutput still passes flaky: [] (names reach the user via seal notProven); the bounding rewrite is best effort and a concurrent append can lose a row.
858
+ - Known limits: protocolError and conflictingRequirements have no producer wired yet (callers must set them from structured signals); fingerprints are recorded for flaky only and not yet read back by a policy rule; verify's flaky list reaches decideRecovery as the rerun signal (P12-11b) and Q17-03 adds failedChecks so a real failure beside a flaky check still revises (failedChecks has no production producer yet, so absent data keeps flaky-wins); engine10 renderMainOutput still passes flaky: [] (names reach the user via seal notProven); the bounding rewrite is best effort and a concurrent append can lose a row.
857
859
 
858
860
  ## FC-P12-32 Router cost objective is built but dark in production (RESOLVED by P12-32b)
859
861
  - User-visible vs raw: no route decision changes today; the expected accepted-outcome cost ranking (history.ts routeScore, rankExecutorsByCost, haikuFloorExecutor) has no production caller.
@@ -872,3 +874,105 @@ L0 review rule (ENGINE-LAWS.md L0): a fix that adds an `if` or a regex about the
872
874
  - Siblings to sweep: every name in the modernize types.ts event list must have at least one producer in loki-ts/src; cost has no per-unit producer either (only budget.hit spent_usd at scheduler.ts:203).
873
875
  - Mechanism: the coordinator (loki-ts/src/util/modernize_coordinator.ts) calls writeReport once at the end of a run; reslice.ts appends unit.resliced; a guard test asserts every declared event name has a producer.
874
876
  - Fixture: loki-ts/tests/engine10/modernize/e2e.test.ts asserts report.json exists after the stub run; a new producer-coverage case in the existing modernize test file.
877
+
878
+ ## FC-M25W-b Modernize events unit.planned and codemod.skipped are declared with no producer (MODERNIZE-EVENT-DARK)
879
+ - User-visible vs raw: the modernize event log never shows which units were planned or why a codemod was skipped, so a user cannot see the plan or a missing-tool reason; the raw cause is two names in the types.ts event list with no append call.
880
+ - Law broken: a control nobody reads is theatre (event declared with no producer).
881
+ - Cause (measured 2026-10-16, M-25w build): `grep -rn "unit.planned\|codemod.skipped" loki-ts/src` finds only types.ts:8-9 and comments in codemod.ts:4,10; the M-25w producer guard allowlists both names.
882
+ - Siblings to sweep: every name in the modernize types.ts event list; the allowlist in the M-25w producer guard must shrink to empty.
883
+ - Mechanism: the planner appends unit.planned once per unit; the codemod caller appends codemod.skipped with the reason codemod.ts already returns; then delete both allowlist entries so the existing guard covers them.
884
+ - Fixture: the M-25w producer-coverage case with an empty allowlist.
885
+
886
+ ## FC-COST-PARTIAL A cost total built from ledger lines alone is reported as complete when the main records carry tokens but no dollar figure (COST-PARTIAL-HIDDEN)
887
+ - User-visible vs raw: `loki` cost and the C-F1 benchmark show a small total with cost_partial false, so a run looks cheaper than it was and the 2x cost claim could rest on an understated number.
888
+ - Law broken: a total that omits unpriced spend must say it is a lower bound.
889
+ - Cause (measured 2026-10-17, COST-WALL HIGH review F1): autonomy/lib/efficiency_cost.py lines 316-325; a main efficiency record with tokens and no cost_usd plus one priced child-ledger line gives usd 0.01, cost_partial False. engine10 omits cost_usd when a session reports no dollar figure.
890
+ - Siblings to sweep: every reader of cost_partial (autonomy/lib/cost-summary.py, the C-F1 benchmark row_true_spend, dashboard cost views).
891
+ - Mechanism: when main records exist and cost_available is false, set cost_partial true in the one reader; siblings consume that flag.
892
+ - Fixture: tests/test_efficiency_cost_availability.py case with token-only main record plus a priced ledger line asserts cost_partial true.
893
+
894
+ ## FC-REALRUN-FIXTURE A pinned scenario expectation changed without the fixture receipt that the harness self-test checks it against (REALRUN-FIXTURE-DRIFT)
895
+ - User-visible vs raw: v11.17.8 never published; Tests run 38986362613 failed only "real-run harness scenarios, dry install, doctored receipt" with `FAIL wall-guard: expected check "node:sum.test.js" executed in checks[]`.
896
+ - Law broken: a change to an expectation must update every fixture that exercises it in the same slice.
897
+ - Cause (measured 2026-10-17): Q17-04b (e1bdde7d3) set SC_EXPECT_CHECKS=node:sum.test.js in tests/real-run/scenarios/trivial-sum.sh; tests/test-real-run.sh good.json still named its checks "a" and "b". The slice gate ran tests/test-wall-executed-guard.sh but not tests/test-real-run.sh.
898
+ - Siblings to sweep: every user of --check-receipt or SC_EXPECT_CHECKS (grep finds only tests/test-real-run.sh, tests/test-wall-executed-guard.sh, scripts/real-run.sh).
899
+ - Mechanism: the fixture names the pinned check; slice cards touching tests/real-run/scenarios list tests/test-real-run.sh in their commands.
900
+ - Fixture: tests/test-real-run.sh good receipt passes (13 PASS, rc=0 locally after the fix).
901
+
902
+ ## FC-COST-PARTIAL-b Partial cost still readable as complete in sibling consumers (COST-PARTIAL-SIBLINGS)
903
+ - User-visible vs raw: a run whose cost is only partly measured can still be shown as a complete number in the runner equivalence report, the bench-run report, or a spend-cap message without its lower-bound label.
904
+ - Law broken: one shared mechanism (FC-COST-PARTIAL fixed attribution.py only; siblings read cost without the partial flag).
905
+ - Cause (COST-WALL-d HIGH reviews 2026-10-17): equivalence_report.py:334-374 and report.py:280 ignore adapter.provenance.cost_partial; row_spend_is_partial returns False for cost_usd None with true_cost_usd set; efficiency_cost.py counts ledger_invalid_lines without setting cost_partial; a stored cost_usd 0.0 with a larger true_cost_usd renders complete.
906
+ - Mechanism: one helper decides partial (null cost, cost below ledger or true cost, invalid ledger lines, unpriced lines) and every cost consumer calls it.
907
+ - Fixture: cases in benchmarks/bench/tests/test_attribution.py and tests/test_efficiency_cost_availability.py for each sibling.
908
+
909
+ ## FC-25c-ci Git env overrides leaked by an earlier suite silence repo-config controls (GIT-ENV-LEAK)
910
+ - User-visible vs raw: v11.17.9 never published; Tests run 38988194257 failed 2 FC-25c(a) controls on ubuntu while they passed locally per file.
911
+ - Law broken: a test must be hermetic; a control that depends on process-wide state is not a control.
912
+ - Cause (reproduced 2026-10-17): runAutonomous (autonomous.ts:448) and issues_run.ts:512 call withholdGithubTokens on process.env inside the shared bun process, leaving GIT_SSH_COMMAND=false and a GIT_CONFIG_COUNT credential.helper reset; both override repo config. Running the old file with those four variables set reproduces exactly the 2 CI failures.
913
+ - Siblings to sweep: every test that asserts a repo-local git config value runs (fsmonitor, filter, ssh, credential, uploadpack).
914
+ - Mechanism: hermeticGit wrapper in fc25_safe_git.test.ts removes GIT_SSH, GIT_SSH_COMMAND, GIT_CONFIG_PARAMETERS and GIT_CONFIG_COUNT/KEY/VALUE for the test and restores them after.
915
+ - Fixture: the same file run with GIT_SSH_COMMAND=false GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=credential.helper GIT_CONFIG_VALUE_0= passes 14/0.
916
+
917
+ ## FC-TEN-QUALITY-01 The fix session gets a bare check name with no assertion text (FIX-BRIEF-BLIND)
918
+ - User-visible vs raw: the user saw fix rounds repeat or stall on a failing test. Raw pytest printed `E assert 4 == 5`; the fix brief carried only the check name and the rerun command.
919
+ - Law broken: L4 (the fixer must see the evidence the verifier saw).
920
+ - Siblings: every runner whose decisive block differs: pytest `E ` lines, jest/vitest Expected/Received, node AssertionError, go `--- FAIL`, tsc/ruff diagnostics; holdout checks must stay hidden.
921
+ - Mechanism: one failureExcerpt() in util/check_result.ts (redacted, repo-relative, at most 1500 bytes per check, 6 KB total), held in a stage-local map in verify.ts. It is never part of the check signature, never emitted in test.result, never computed for holdout checks.
922
+ - Fixture: fix.test.ts (failing pytest `assert add(2,2) == 5`), check_result.test.ts (one fixture per runner plus size cap and AKIA redaction), wall_holdout.test.ts (holdout text absent from failures_grouped, events and brief).
923
+
924
+ ## FC-TEN-QUALITY-02 Pre-existing lint cannot be told apart from lint the change introduced (LINT-NO-BASELINE)
925
+ - User-visible vs raw: the user saw a fix loop spending rounds on lint that was already in the repo. Raw base output showed the same diagnostics before the change.
926
+ - Law broken: L4 (attribution must compare head to base, as tests already do via attribute()).
927
+ - Siblings: ruff concise, shellcheck gcc, eslint unix parsers; tsc is out of scope; a file new on head has no base.
928
+ - Mechanism: one pure attributeStatic(tool, headOut, baseOut) in runner/repo_profile.ts next to attribute() and attributeFullSuite(). Multiset keyed path/code/message (line and column dropped). Fails closed: unparseable head, empty parse with non-zero exit, missing base and unknown tool all count as introduced.
929
+ - Fixture: harness_intelligence.test.ts cases for same, extra, changed-message, shifted-line, garbage and null-base inputs, plus a recorded real sample per parser.
930
+
931
+ ## FC-TEN-QUALITY-03 A pre-existing lint failure drives fix rounds because verify never asks the baseline (LINT-DRIVES-FIX)
932
+ - User-visible vs raw: the user saw lint:ruff in failures_grouped for a file whose base already failed it. Raw base content run through the same tool gave the same diagnostics.
933
+ - Law broken: L4, and the one-mechanism rule (tests already excuse pre-existing failures via attr.preExistingChecks / preRed.names).
934
+ - Siblings: ruff, shellcheck, eslint per-file checks; tsc stays untouched; files new on head are never excused.
935
+ - Mechanism: runLintChecks in verify.ts feeds base content on stdin to the tool and calls attributeStatic from QUALITY-02, joining the existing preExistingChecks path (at most 4 core lines).
936
+ - Fixture: verify_lint.test.ts with a repo fixture and a stub ruff: base has the unused import (excused), head adds a new one (still reported), a new-file F401 (never excused).
937
+
938
+ ## FC-TEN-QUALITY-07 The fix brief says the diff is unavailable because its only reader has no writer (DEAD-DIFF-STAT)
939
+ - User-visible vs raw: every real fix brief read "(diff stat is not available)". The working tree had the changed files.
940
+ - Law broken: reader/writer key contract: fix.ts:62 reads prior.implement.diff_stat and no stage writes it.
941
+ - Siblings: buildFixBrief and buildFixResumeBrief both consume the diff; any other reader of implement.diff_stat.
942
+ - Mechanism: one currentDiff(repoDir, baseSha, maxBytes=6000) in runner/session_resume.ts via safeGit, computed fresh each fix round; excludes .loki/, names untracked files without touching the index, truncates with an explicit note.
943
+ - Fixture: fix.test.ts and fix_resume.test.ts: temp repo with a modified file and no diff_stat shows "1 file changed"; round 2 shows the hunk; .loki/ never appears; a 50 KB diff cuts at 6000 bytes with the note.
944
+
945
+ ## FC-TEN-COST-06 The xreview claude judge spends tokens with lean flags off and no ledger line (XREVIEW-UNMETERED)
946
+ - User-visible vs raw: cost totals omitted the cross-review judge. Raw claude calls ran with full settings and no child-session line.
947
+ - Law broken: cost accounting must cover every model call (see FC-COST-PARTIAL).
948
+ - Siblings: the codex argv (unchanged); other stages that spawn claude children and already use withChildLedger.
949
+ - Mechanism: reviewArgv adds leanReviewerFlags() and --output-format json for claude; the run is wrapped in withChildLedger(run, lokiDir, 'xreview'). Verdict rules unchanged: no VERDICT line or bad JSON is not_run, never PASS.
950
+ - Fixture: xreview.test.ts: argv contains the lean flags and json format; a stubbed run writes a phase xreview line to .loki/metrics/child-sessions.jsonl; JSON `VERDICT: BLOCK` parses to block; non-JSON gives not_run.
951
+
952
+ ## FC-TEN-DEPLOY-08 The web app reports a deployed URL it never obtained and stages everything on push (DEPLOY-FABRICATED-URL)
953
+ - User-visible vs raw: a deploy with no URL in its output returned `https://vercel.app` as success. Raw provider output had no URL, and no receipt gate ran.
954
+ - Law broken: a success claim must key on a parsed confirmation (fallback success is a false ack); the CLI deploy gate is the only path.
955
+ - Siblings: deploy_session and github_push_session in web-app/server.py; hardcoded netlify.app and github.io fallbacks; the bulk-stage and `--public` push path; web-app consumers of url.
956
+ - Mechanism: both handlers call the gated CLI (`loki deploy --execute --dir <dir>`, `loki github publish`) as argv lists and read the newest .loki/deploys record; url is deployed_url or null; refusals return 4xx with reasons.
957
+ - Fixture: web-app/tests/test_server.py with monkeypatched subprocess; a grep for the three fallback URLs in server.py must exit 1.
958
+
959
+ ## FC-TEN-STABILITY-01 bench-suite builds VAR=1 hyperfine commands that hyperfine 1.20 refuses (BENCH-ARGV-ENV)
960
+ - User-visible vs raw: the v11.17.6 backstop went red. Raw hyperfine 1.20 refused any positional command matching ^[A-Z_]+=, and the script skipped those commands without failing.
961
+ - Law broken: a gate that skips its own work must fail, not pass quietly.
962
+ - Siblings: benchPair and benchRoute call sites in loki-ts/scripts/bench-suite.ts; fixed /tmp/bench-*.json export paths; partial SKIP exit code.
963
+ - Mechanism: one exported pure argv builder emits `env LOKI_LEGACY_BASH=1 <shim> <cmd>` (works on hyperfine 1.18 and 1.20); exports go under a mkdtemp dir; any SKIPPED command exits non-zero.
964
+ - Fixture: loki-ts/tests/scripts/bench_suite_argv.test.ts with a fake hyperfine on PATH that exits 1 with the 1.20 message on a VAR= command.
965
+
966
+ ## FC-TEN-STABILITY-05 wall_concurrent races the 5s bun test timeout (WC-TIMEOUT-RACE)
967
+ - User-visible vs raw: nightly 38938949858 failed. Raw duration was 5004.82ms against the 5000ms default; assertions were correct.
968
+ - Law broken: a test must be hermetic and not depend on machine speed.
969
+ - Siblings: other engine10 suites that init, add and commit a repo per test.
970
+ - Mechanism: build the repo fixture once in beforeAll and copy it per test; give the concurrency case an explicit timeout sized from measured CI duration; every assertion unchanged.
971
+ - Fixture: `bun test --timeout 1500 tests/engine10/wall_concurrent.test.ts` under CPU load, and a 20-run loop of the plain command.
972
+
973
+ ## FC-TEN-UX-02 Every failed start prints the same generic Next line (NEXT-NOT-SPECIFIC)
974
+ - User-visible vs raw: auth failure, credit exhaustion, a failed check, a spec conflict and a stall all told the user `loki doctor` or `loki undo`. Raw reason strings from output.ts reasonOf name the actual cause.
975
+ - Law broken: the failure message must name the exact fix for the cause that happened.
976
+ - Siblings: every literal reason produced by reasonOf (output.ts:74); the supervisor call site that passes the reason.
977
+ - Mechanism: nextOf in util/run_summary.ts takes reason and outcome and maps each failure class to one command; verified, done-unverified, budget and stopped output stays byte-identical.
978
+ - Fixture: run_summary.test.ts table rows copied from the real reason literals, a pin of the old outputs, and a source scan that every reasonOf literal has a mapping; tests/features/contract.test.ts covers fatal:auth end to end.
@@ -327,6 +327,7 @@ The report never states more than the equivalence data proves. It is sealed and
327
327
  - V10-RESEARCH cites Legacy-Bench only through a vendor report.
328
328
  - The slice first confirms that a public task set exists and records its URL and license. If none exists, the pilot uses 10 public py2 and Java 8 repos under 20K lines, each with a suite, and says so.
329
329
  - Gate: the equivalence rate on the pilot is published, and the sizing cap is calibrated from it.
330
+ - Calibration factors (eval/modernize/pilot-manifest.json): raise x1.25 at 90% or higher, lower x0.75 below, clamp 300-6000 lines, round to 50; hold when any run failed or was skipped.
330
331
 
331
332
  **2. 200K-line scale test (M-28)**
332
333
  - Chosen candidate: Mercurial at its last Python 2 only release, 4.x (py2 to 3).
@@ -337,6 +338,11 @@ The report never states more than the equivalence data proves. It is sealed and
337
338
  - the license (GPL) allows running it.
338
339
  - Why: it is a real Python 2 codebase with a large suite of its own (`run-tests.py`), and upstream later completed the Python 3 port, so a human reference exists.
339
340
  - The line count is UNVERIFIED offline. M-28 measures it first with `--dry-run` inventory and `cloc`. If the count is under 200K or the suite is unbounded, the named fallback is Calibre before its Python 3 port, and the choice is recorded again.
341
+ - Operator notes (`eval/modernize/scale.py`, M-28; extends pilot.py, no separate SCALE.md):
342
+ - `python3 eval/modernize/scale.py --target hg --dry-run-first [--source PATH] [--fallback-source PATH]` is the default and spends nothing. It resolves the source (a local `--source` is read in place and copied for the estimate; otherwise it clones Mercurial 4.9.1 with `hg` or Calibre v3.48.0 with the Git CLI; both refs UNVERIFIED offline), counts lines per language excluding vendored directories, runs `loki modernize --to python3 --dry-run`, and prints JSON: planned units, waves, estimated cost, the unit line cap (pilot manifest `cap.start_lines`), the spend cap (null until `--budget-usd`), and a suggested budget of 1.5x the estimate.
343
+ - Selection: hg unavailable (no `hg`, clone failure, bad `--source`) or under `--min-lines` (default 200000) falls back to Calibre. Each step is logged to stderr and to `selection_log`. If no candidate meets the floor the run exits 2.
344
+ - The paid run needs `--execute` AND `--budget-usd` greater than 0, else exit 2 before any clone or spend. It runs through `pilot.execute_repo`, so cost, status and calibration follow the M-27b rules (cost is a lower bound; unmeasured spend is charged at the full budget). Results: `eval/modernize/results/pilot-scale-<ts>.json`.
345
+ - Known limit: `source_lines` in the paid result comes from pilot's counter and includes vendored code, so cost per 1K lines is understated against the measured plan figure.
340
346
 
341
347
  **3. 1M lines (M-29)**
342
348
  - Chosen candidate: Apache Hadoop 2.x (Java 8 to 21). It is Java 8, multi-module, and has an extensive JUnit suite.
@@ -386,7 +392,7 @@ The report never states more than the equivalence data proves. It is sealed and
386
392
  | M-25 | Final report and verdict (COMPLETE only if all proven), sealed | mod/report.ts, T/report.test.ts | HIGH | Wb T/report.test.ts | M-13, M-21 |
387
393
  | M-26 | End-to-end: py2 fixture repo modernized with stub provider | T/e2e.test.ts, T/fixtures/e2e_py2/ | MEDIUM | Wb T/e2e.test.ts | M-08, M-22, M-25 |
388
394
  | M-27 | Legacy-Bench pilot harness; confirm public set; calibrate cap | eval/modernize/pilot.py, eval/modernize/test-pilot.sh | HIGH | bash eval/modernize/test-pilot.sh | M-26 |
389
- | M-28 | 200K scale run (Mercurial 4.x, measured first, fallback Calibre) | eval/modernize/scale.py, eval/modernize/SCALE.md | HIGH | python3 eval/modernize/scale.py --target hg --dry-run-first | M-27 |
395
+ | M-28 | 200K scale run (Mercurial 4.x, measured first, fallback Calibre) | eval/modernize/scale.py (notes in section 12) | HIGH | python3 eval/modernize/scale.py --target hg --dry-run-first | M-27 |
390
396
  | M-29 | 1M scale run (Hadoop 2.x Java 8 to 21, measured first) | eval/modernize/scale_1m.py, eval/modernize/SCALE-1M.md | HIGH | python3 eval/modernize/scale_1m.py --dry-run-first | M-28, M-11 |
391
397
  | M-30 | User docs for loki modernize, no dashes, commands match USAGE | docs/v10/GUIDE-MODERNIZE.md, tests/test-modernize-docs.sh | LOW | bash tests/test-modernize-docs.sh | M-07 |
392
398
 
@@ -2400,3 +2400,13 @@ The swarm is stopped: .loki/V10-STOP exists, the loop has no wake-ups, and the c
2400
2400
  - 2026-10-16T23:05Z M-27 parked per D98: round 2 opus HIGH review BLOCK on fc2a7e90 (test-pilot.sh 26 passed 0 failed, but repro of a 10-unit plan with 1 PROVEN unit then budget.hit gave status ok, equivalence 1.0, calibrate_cap action raise). Carried as M-27b (building). FC-09u built as 12a4c80a (runner_config.test.ts 135 pass 0 fail, typecheck no error TS), in opus HIGH review. v11.17.5 (99b96ffcc) Tests and Release running.
2401
2401
  - 2026-10-16T23:15Z drift audit (last 6h vs CONTROL.md): 299 commits, 6 release cuts (v11.17.0-v11.17.5), but `npm view loki-mode dist-tags` shows next=11.17.1 only; 11.17.2, 11.17.3 and 11.17.4 never published, each red on a CI-only guard that release.sh skips under LOKI_RELEASE_ALLOW_RED=1. Drift: cut cadence met, publish cadence 1 of 6. Fix dispatched as REL-GUARD (release.sh runs the select-tests.sh --guards-only rows even under ALLOW_RED). Also: S11 run2 measured stale global v11.3.9; stopped, rerun as run3 on repo bin (v11.17.5); COST-BIN merged a05462951.
2402
2402
  - 2026-10-16T23:25Z v11.17.6: v11.17.5 published (npm next 11.17.5, gh release v11.17.5 draft=false, Tests and Release completed success on 99b96ffcc). Ships COST-BIN (bench tests 79 pass) and D101. Drift audit vs CONTROL.md: M-27b round 1 BLOCK (F1 no modernize.completed producer), round 2 fix 7fc7c886 test-pilot 32/0 in HIGH review; FC-09v round 1 BLOCK cebe5641 (block-scalar bypass reproduced with pnpm install), round 2 fail-closed per D101 building; REL-GUARD and M-25w in flight; S11 run3 on repo v11.17.5 in progress. Cost goal still unproven.
2403
+ - 2026-10-16T23:31Z drift audit vs CONTROL.md: v11.17.6 pushed d84ef9568 (COST-BIN, REL-GUARD, D101), Tests/Release in flight. M-27b APPROVE round 2 7fc7c886 merged aa0bb8971 (ships 11.17.7). In flight: FC-09v round 2 (D101 fail-closed), M-25w HIGH review of 8836ea62, REL-GUARD-b, run3 diagnosis. S11 run3 result: loki about 0.57x raw-configured per accepted task but 24/24 loki runs rc 1, coord-1 and longspec-1 fail in 0.2s, raw-bare 24/24 unmeasured; cost goal stays unproven. Pruned 4 merged clean worktrees.
2404
+ - 2026-10-16T23:37Z run3 diagnosis (read-only, no spend): loki rc 1 on every run because seeds have no executable test, so FC-16 gives PARTIAL (exit 1) even when the held-out test accepts; coord-1 and longspec-1 fail in 0.2s at run_group.ts:177/216 (materialize_seed adds no origin remote); raw-bare unmeasured (no ANTHROPIC_API_KEY); loki cost omits v10 Wall-stage child sessions (18 loki-e15-wall-* transcripts, about $1.18). Corrected loki about $0.184 per accepted vs raw-configured $0.195: the 2x cost goal is NOT proven. Dispatched COST-HARN (bench rc, remote, v10 evidence) and COST-WALL (child-session ledger).
2405
+ - 2026-10-17T00:05Z v11.17.7: ships M-27b pilot accounting, COST-HARN benchmark fixes, M-25w sealed modernize report and producer guard, REL-GUARD-b/c release guard worktree. Bump via scripts/release.sh patch --bump-only rc=0 (~/loki-ci-logs/bump-11177.log).
2406
+ - 2026-10-17T00:22Z drift audit (last 6h vs CONTROL.md): 281 commits, releases 11.17.6 and 11.17.7 only, so the :00/:20/:40 cadence (D37) is missed; cause is serial HIGH review rounds, not red CI. D12/D98 held: Q17-04 parked after HIGH r2 BLOCK (B2 reproduced) and re-sliced as Q17-04b; M-28 merged only after HIGH r2 APPROVE. Ready queue 8, at the CONTROL floor but under the OPERATING-MODEL 30; PO refill dispatched. M-28 and Q17-06 merged-unreleased; v11.17.8 cut follows the v11.17.7 publish.
2407
+ - 2026-10-17T00:22Z v11.17.8: v11.17.7 never published (Tests run 38984591460 red on e66c51a09, sole failing suite Tier A test selector FC-89: log.test.ts walks loki-ts/src without the walk-all-src marker; Release failed at required-ci). Fixed in c6faaa885 (test-select-tests.sh 95 passed, 0 failed). Ships v11.17.7 content plus M-28, Q17-06, Q17-04b, Q18-09. Bumped with LOKI_RELEASE_ALLOW_RED=1 because HEAD had no Tests run yet; global guard rows ran in the clean worktree (bump rc=0).
2408
+ - 2026-10-17T00:50Z v11.17.9: v11.17.8 never published (Tests run 38986362613 red on 7fc08f186, only suite tests/test-real-run.sh, fixture receipt lacked the pinned node:sum.test.js check). Fixed in 500b71e85; test-real-run.sh rc=0 (13 PASS), test-wall-executed-guard.sh rc=0. Also merges Q17-03 (TL APPROVE 3dec444fa, 4157 pass 0 fail), COST-WALL-b (HIGH APPROVE ddab3e714, pytest 15 passed, mutation caught) and Q18-01 (HIGH APPROVE dbb93205a, bun test 289 pass, guard mutations 6/6 caught). Bumped with LOKI_RELEASE_ALLOW_RED=1 (HEAD had no green Tests run). C-F1 2x cost claim still unproven: benchmark adapter ignores cost_partial (follow-up COST-WALL-d).
2409
+ - 2026-10-17T01:10Z v11.17.10: v11.17.9 never published (Tests run 38988194257 red on bf3d2ae24: 2 FC-25c(a) controls failed because withholdGithubTokens callers left GIT_SSH_COMMAND=false and a GIT_CONFIG_COUNT credential.helper reset in process.env). Fixed in 3c3f2c9e0 (hermeticGit wrapper); old file under those 4 vars reproduces 2 fail, fixed file 14 pass 0 fail. Ships Q17-01, COST-WALL-c, COST-WALL-d, M-25w-b, M-25w-c, FC-09w, Q18-06 (HIGH r2 APPROVE), Q18-05 (HIGH APPROVE). Pending: Q18-03b and FC-09x approved, merge next; COST-WALL-e and Q17-02 blocked r1, fixing; 2x cost claim still unproven.
2410
+ - 2026-10-17T01:30Z v11.17.11: ships Q18-03b (merge 31e4f4b47) FC-09x (merge b97c1e635, dist 2eeec3851) and COST-WALL-e (HIGH r2 APPROVE 439ed90e3, 132 passed). Founder asked for 10/10 on every competitive axis; architect workflow wrixi4afj is slicing COST, QUALITY, DEPLOY, UX, GATES, STABILITY and ADOPTION into board rows. Q17-02 r1 fix 11eac46fa in TL r2 review.
2411
+ - 2026-10-17T02:00Z v11.17.12: v11.17.11 published (npm next 11.17.11, Tests and Release green on df98addc8). Ships Q18-05b (TL APPROVE 82058ff97, merge ae90c2875) and COST-WALL-f (HIGH r2 APPROVE ef9979ad8, merge 3d0587f4f). Q18-03c parked after 2 rounds (regex-literal strip regression), continued as Q18-03d. 64 TEN rows on BOARD; wave 1 batches A and B building.
2412
+ - 2026-10-17T02:30Z v11.17.13: v11.17.12 (42315dc52) Tests red on one stale assertion in tests/test_cost_summary.py (1 failed, 3825 passed on Python 3.10 and 3.13), so Release skipped publish; fix-forward f5b1d1681. First v11.17.13 bump refused on 2 red global guard rows (l0 allowlist after CORE-TRIM, completions coverage newly promoted by STABILITY-04), fixed 6f2355aa7. TEN-UX-02b merged 672b74c79; TEN-DEPLOY-01b conflicts with DEPLOY-01, back to ready. Ships v11.17.12 content plus Q18-07, Q18-11, Q17-02, Q18-03d and 12 TEN wave 1 rows (DEPLOY-01, UX-02, COST-02, COST-03, STABILITY-01/04/05/08, FC-ROWS, CORE-TRIM, SECURE-SCAN-UTIL, BADGE-UTIL), each with a TL or HIGH APPROVE. Batches E, F, G and Q18-04/Q18-02b r2 building.