dream(flywheel-promotion): verifyReplayBundle didn't verify the full diagnostic ledger (evaluated) - #205
dream(flywheel-promotion): verifyReplayBundle didn't verify the full diagnostic ledger (evaluated)#205ruvnet wants to merge 1 commit into
Conversation
…full diagnostic ledger, critic caught a verdict-flip gap too (evaluated) verifyReplayBundle() verified receipts and gate re-execution only across the promoted chain, never all_commits (the full diagnostic ledger of promoted + rejected candidates) even though run.ts signs every commit regardless of verdict. A PROMOTED commit missing sealed scores was also silently skipped by gate re-execution instead of failed. An independent adversarial critic then found the first-drafted fix was itself incomplete: neither the new all_commits check nor the pre-existing chain check cross-verified a commit's own id/verdict against its signed payload, so a REJECTED commit's outer verdict could be flipped to PROMOTED (receipt splicing) without invalidating anything. Both closed pre-ship. 52/52 tests green (was 47), 0 regressions, 4 new tests confirmed non-vacuous via before/after repro, all 4 real committed ReplayBundles in the repo re-verified PASS. Anchor re-verification and Score-field signing are disclosed, still-open follow-ups (need larger schema changes), not fixed tonight. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013mrEQ8CUwiKQTsBGjA7c1G
…dd 08-17 Ledger on main only had 08-13/08-14 despite 4 nights of runs (08-15 generator-genome PR #200, 08-16 flywheel-promotion PR #205 both exist, open, non-stale, with their own ledger rows sitting on unmerged branches). Backfilled those two rows from their PR bodies (verified, not guessed) and appended tonight's 08-17 darwin-evolution row with the real issue #206 / PR #207 numbers.
…eplay-trust gap (evaluated) (#258) * dream(flywheel-promotion): #257 consolidate #205/#231/#255 + close a 4th replay-trust gap MetaHarness Dream Cycle, 2026-09-01. Deep surface: flywheel-promotion (slot 1). Hand-merges three semantically-compatible but git-conflicting unmerged Dream Cycle PRs (#205, #231, #255) into one clean diff on verifyReplayBundle/gateReExecutes in packages/flywheel/src/replay.ts, since all three independently rewrote the same code region against different stale bases. An independent adversarial critic then found a 4th, undisclosed gap: BOUND_KEYS (from #255's sealedFieldsAuthentic check) did not bind `parents`/`generation`, so two genuinely, independently signed PROMOTED commits could be spliced into a fabricated multi-generation chain by rewriting only those two unsigned fields. Closed in the same diff with a regression test reproducing the exact exploit. 72/72 flywheel unit tests pass; 18/41 new-test assertions verified to fail against unpatched main (non-vacuous); all 7 real committed ReplayBundle/ proof-bundle files in the repo re-verified unchanged PASS; full monorepo build + 716/716 non-skipped tests across flywheel/evals-math/darwin-mode green. Full detail: issue #257, docs/dream-cycle/2026-09-01-gist.md, docs/dream-cycle/2026-09-01-evidence.md, ADR-272. Human review required. Do not self-merge. Do not autonomously promote Flywheel state. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012NE5wk64pND2VpBZmGGkQq * dream(flywheel-promotion): record PR #258 in the ledger row Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012NE5wk64pND2VpBZmGGkQq * chore(flywheel): 0.1.10 -> 0.1.11 — shipped code changed in this PR packages/flywheel/src/{cli,replay,run}.ts change here, but the version stayed at 0.1.10, which is already published. Merging that would put different content behind a version the registry already serves — the #261 divergence class, and the second time today a dream PR has done it (see the avo 0.1.4 bump on #220). This is exactly the case the registry preflight gate proposed in #262 would catch automatically. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01G2iAKhp4FGq2Ty5CFnj8mT --------- Co-authored-by: stack-check <test@test.local> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: ruv <ruvnet@gmail.com>
|
Superseded by #258, merged as I verified the subsumption rather than taking the consolidation claim at face value — by running this PR's own test file against #258's source:
Those five are fixture drift, not lost fixes. #258 adds Net: 72 passing across 35 tests on Closing as superseded. If you think a specific assertion from this PR did not survive into #258, reopen and point at it — I checked by execution, but execution only covers what the tests actually assert. |
…luated) (#207) * dream(darwin-evolution): #206 wire ADR-249's dangling cost seam into evolve() EvolutionConfig gains optional costBudgetBytes; evaluateVariant now feeds the existing variantBytes(variant.dir) parsimony signal through scoreVariant's opt-in signals.cost seam when set, and stays byte-identical when omitted (every current caller). Closes the gap between ADR-249 (2026-08-10, seam shipped) and evolve()'s only call site, which never had a way to reach it. Deterministic before/after repro: 4 new evolve.test.ts tests fail exactly as predicted pre-fix, package suite 632/632 passed (0 regressions) post-fix. Independent adversarial critic: ACCEPT, two disclosed non-blocking caveats. Full receipt, competitor research, and witness: docs/dream-cycle/2026-08-17-gist.md, issue #206. * dream(darwin-evolution): #206 update ledger — backfill 08-15/08-16, add 08-17 Ledger on main only had 08-13/08-14 despite 4 nights of runs (08-15 generator-genome PR #200, 08-16 flywheel-promotion PR #205 both exist, open, non-stale, with their own ledger rows sitting on unmerged branches). Backfilled those two rows from their PR bodies (verified, not guessed) and appended tonight's 08-17 darwin-evolution row with the real issue #206 / PR #207 numbers. --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: ruv <ruvnet@gmail.com>
MetaHarness Dream Cycle, 2026-08-16. Deep surface:
flywheel-promotion(slot 1). Full detail, receipts, candidate-selection scoring, adversarial-critique writeup, and evals-verticals/bench scan findings: #204.Hypothesis
Given
@metaharness/flywheel'sverifyReplayBundle, which verified Ed25519 receipts and gate re-execution only across the promotedchain, when receipt verification (including an id+verdict cross-check against the signed payload) is extended to every entry inall_commits, and a PROMOTED commit missing sealedbaselineScore/candidateScoreis treated as agateReExecutesfailure instead of a silent skip, then a bundle carrying a tampered/spliced/unauditable ledger entry should FAIL replay (pass: false) where it previously passed, while every honestly-produced bundle continues to PASS unchanged, subject to: (a) zero regression in the existing suite, (b) purely additiveReplayVerdict.checks, (c)meetsPromotionRuleitself untouched, (d) diff materially under 300 lines.Candidate
verifyReplayBundle()(the function an external reviewer uses to establish trust in a promotion run "with no trust in the producer") only verified receipts on the promotedchain, never onall_commits— the "full diagnostic ledger" of every candidate tried, promoted and rejected, thatanalyzeBundle's rejection-reason/cost-per-win reporting reads — even thoughrun.tssigns every commit it mints regardless of verdict. Separately,gateReExecutessilently skipped (rather than failed) a PROMOTED commit missing sealed scores. Fixed: added anallCommitsReceiptscheck; hardenedgateReExecutesto fail on unauditable promotions. An independent adversarial critic then found the first-drafted fix was itself incomplete: a verified signature only proves a payload is internally consistent, not that it's attached to the right commit — neither the new check nor the pre-existingchaincheck cross-verified a commit's ownid/verdictagainst its signed payload, so a REJECTED commit's outerverdictcould be flipped toPROMOTED(receipt splicing). Fixed pre-ship with areceiptMatchesCommit()cross-check applied to both checks. 3 files, 132 insertions / 5 deletions (well under the 300-line target).Evaluation Receipt
Deterministic reproduction (not sampled):
packages/flywheelunit suite: baseline 47 → candidate 52/52 passed, 0 regressions.tsc --noEmit: clean. Full reponpm run build: clean (no wasm/NAPI degradation tonight).ReplayBundlein the repo re-verified against the hardened logic:packages/radio/.radio-flywheel/replay-bundle.json,kimi-k3-harness/.harness/flywheel/replay-bundle.json,packages/darwin-mode/bench/swebench/proof-bundle-swebench.json,experiments/signal-flywheel/bundle.json(via its ownverify.mjs) — all four still PASS,allCommitsReceipts: trueon every one.Baseline Comparison
No behavioral change for any honestly-produced bundle —
run.tsalways signs{kind, id, verdict, ...}and always seals scores on non-root commits, so no legitimate producer output is affected. Confirmed directly against 4 real committed bundles, not just synthetic test fixtures.Darwin Lineage
Not run — verification/security-correctness fix to library code, not a tunable routing/topology/prompt/tool/tier parameter; no Darwin mutation surface applies (ADR-071 mutation allowlist).
Flywheel Evidence
Not applicable in the "ran a flywheel evolution" sense — this candidate modifies
@metaharness/flywheel's own verification code. Durable evidence is the deterministic test repro + real-bundle regression check above, committed todocs/dream-cycle/2026-08-16-gist.md.Reward Hack Check
Purely additive diff (no existing assertion removed/weakened); no benchmark/gold-data touched; no hardcoded outputs, metric substitution, seed manipulation, or hidden preprocessing.
Security Review
This is itself a security-hardening change to a promotion-audit trust boundary — no credential/shell/network surface touched, no new dependency. Closes a receipt-splicing/verdict-flip forgery path present in both the pre-existing
chaincheck and the newly-addedall_commitscheck. Two related gaps are explicitly disclosed, not fixed tonight: (1)gateReExecutesstill can't re-check the anchor (anti-Goodhart) clause —ReplayBundledoesn't carryrootAnchorat all; (2)failureReasons/Score fields beyondprimaryDeltaaren't part of the signed payload, so a bundle editor who cannot forge signatures could still alter a rejected candidate's displayed cost/reason without failing replay.Regression Analysis
Zero regression: 52/52 flywheel tests (up from 47),
tscand full repo build clean, all 4 real committed replay bundles still verify PASS.ADR
ADR-252 — extends ADR-235's replay-verification discipline to the full diagnostic ledger and to verdict/id authentication.
Research Gist
No gist-creation tool available in this session's toolset — committed instead:
docs/dream-cycle/2026-08-16-gist.md(GIST=LOCAL).Issue
#204 (full findings, candidate-selection scoring table, evals-verticals/bench scan results, competitor review).
Witness
Verifier procedure is in the gist's Witness section and was independently self-verified (round-trip reproduced) before this PR was opened.
Merge Policy
Human review required. Do not self-merge. Do not autonomously promote Flywheel state.
Recommendation: ACCEPT-WITH-CAVEATS — real, independently-critiqued, reproducible fix to a real (if narrow) trust-model gap. Two comparable-severity gaps (anchor re-verification, Score-field signing) are explicitly disclosed as still-open, natural next-night follow-ups — not silently fixed under review pressure, not silently left undisclosed.
Generated by Claude Code