dream(flywheel-promotion): #422 close canon()'s NaN/Infinity/-Infinity/null collision defeating sealedFieldsAuthentic (evaluated) by ruvnet · Pull Request #423 · ruvnet/metaharness · GitHub
Skip to content

dream(flywheel-promotion): #422 close canon()'s NaN/Infinity/-Infinity/null collision defeating sealedFieldsAuthentic (evaluated) - #423

Draft
ruvnet wants to merge 2 commits into
mainfrom
dream/2026-10-21-flywheel-promotion
Draft

ruvnet wants to merge 2 commits into
mainfrom
dream/2026-10-21-flywheel-promotion

Conversation

@ruvnet

@ruvnet ruvnet commented Oct 21, 2026

Copy link
Copy Markdown
Owner

Closes #422.

Hypothesis

Given a signed PromotionReceipt or sealed-field-authenticity check (sealedFieldsAuthentic
in replay.ts, validAttestation in multigeneration-proof.ts) that compares a live numeric
field against its canon()-encoded signed counterpart, when canon() is hardened to encode
NaN, Infinity, and -Infinity as distinct, unambiguous literal tokens (rather than
collapsing them to null via JSON.stringify), then a live field tampered between a
non-finite value and null (or between two non-finite values) is detected, subject to
byte-identical output for every existing finite/string/bool/null/array/object value and 0
regressions on every legitimately-signed existing receipt. Frozen before implementation.

Candidate

packages/flywheel/src/receipts.ts's canon() fell through to JSON.stringify(v) for
scalars. JSON.stringify(NaN) === JSON.stringify(Infinity) === JSON.stringify(-Infinity) === JSON.stringify(null) === "null" (ECMA-262's own behavior), so any canon-EQUALITY check
inherited a 4-way collision at exactly the values it exists to protect. Fix: encode
NaN/Infinity/-Infinity as distinct unquoted literal tokens before falling through to
JSON.stringify — none of those tokens is valid JSON syntax for any string/number/bool/null,
so none collides with any other value canon() produces. 76 insertions / 1 deletion, 2 files
(receipts.ts + its test file).

Evaluation Receipt

  • Baseline (git stash -- packages/flywheel/src/receipts.ts): 3/60 new assertions fail
    non-vacuously — the exact predicted 4-way-collision and the exact predicted false-
    "authentic" verdicts on two tampered commits (primaryDelta NaN→null, anchorScore
    Infinity→NaN, both with no signing key).
  • Candidate: 60/60 pass. Full @metaharness/flywheel suite 146/146, 0 regressions.
    tsc --noEmit clean.
  • All 7 real committed ReplayBundle/proof-bundle JSON files in-repo re-verify
    ACCEPTANCE: PASS, byte-identical (evals-math ×3, radio, darwin-mode/swebench,
    kimi-k3-harness, experiments/signal-flywheel).
  • Downstream sweep (11 packages): 1465 passed / 16 skipped / 1 failed — the 1 failure
    (avo/__tests__/openrouter-live.test.ts) is a live OpenRouter HTTP 404 on a deprecated
    model ID, confirmed environmental, unrelated to this diff.
  • npm audit --omit=dev --audit-level=high: 0 vulnerabilities.

Baseline Comparison

See Evaluation Receipt above — baseline (main, unpatched canon()) vs. candidate, same
test file, same real-committed bundles, same downstream suite.

Darwin Lineage

DARWIN=not_applicable — a canonicalization-primitive correctness fix has no tunable
parameter space; not one of ADR-071's seven Darwin-eligible mutation surfaces.

Flywheel Evidence

Full OBSERVATION → MEASUREMENT → INFERENCE → HYPOTHESIS → DECISION record:
docs/dream-cycle/2026-10-21-evidence.md.

Reward Hack Check

Clear. Diff is additive-only on the test file; no existing assertion/threshold/gold data
weakened, no test skipped, no cost hidden. Independently confirmed by a fresh adversarial
critic (own reproduction, not taken on faith).

Security Review

This candidate is the security hardening itself — closes a tamper-evidence-defeating value
collision in the package's core signed-receipt trust primitive. RFC 8785 (JSON
Canonicalization Scheme) forbids non-finite numbers in canonical JSON for exactly this
reason; the Rust json-canon crate documents the identical pitfall independently. See
docs/dream-cycle/2026-10-21-gist.md for the full competitor/citation table.

Regression Analysis

0 regressions at every tier measured (package suite, real committed bundles, downstream
11-package sweep, tsc, npm audit). The 1 downstream failure is a live-network
environmental flake in an unrelated file (OpenRouter model deprecation), not caused by this
diff.

ADR

None filed — this is a correctness fix to an existing documented primitive (ADR-274/
ADR-317/ADR-318's canonicalization/receipt model), not a new architectural decision.

Research Gist

docs/dream-cycle/2026-10-21-gist.md — SOTA research, competitor comparison (in-toto/
Sigstore, RFC 8785 reference implementations, Darwin Gödel Machine, LangGraph/Microsoft
Agent Framework/CrewAI, K-Veritas), full citations.

Issue

#422

Witness

session_commit : e0dfd44da72b7adfb7c57fdd42d124be58ed7086
report_sha256   : fd618728ac28bb77bc8ebca54554cf6768c64740ba7a49287e15ebc1eac4d366
witness         : 476f5aa181419efe023134004aed5de00e63c47dcfa42ca8dfd98948cda554bb

Merge Policy

Human review required. Do not self-merge. Do not autonomously promote Flywheel state.

Disclosed, not fixed in this PR (future-night candidates): packages/avo/src/flywheelGate.ts
and packages/turn-credit/src/receipt.ts ship their own separate, still-colliding canon()
duplicates; validate-bundle.ts's fail-closed numeric-domain gate lives only in the CLI path,
not in verifyReplayBundle/verifyMultiGenerationEvidence themselves.



Generated by Claude Code

…y/null collision, which defeated sealedFieldsAuthentic's tamper check (evaluated)

canon() (packages/flywheel/src/receipts.ts) fell through to JSON.stringify for
scalars, which collapses NaN, Infinity, -Infinity, and null to the identical
"null" string. Any canon-equality check that exists to prove a live field
still matches what was signed — sealedFieldsAuthentic in replay.ts,
validAttestation in multigeneration-proof.ts — could not tell "still NaN" from
"silently changed to null/Infinity/-Infinity" with no signing key needed.

Encodes NaN/Infinity/-Infinity as distinct unquoted literal tokens instead,
byte-identical for every other value canon() produces.

60/60 flywheel receipts tests pass (3 fail non-vacuously on baseline); full
flywheel suite 146/146, 0 regressions; all 7 real committed ReplayBundle
files re-verify PASS unchanged; tsc clean; npm audit clean. Independent
adversarial critic: ACCEPT, no blocking caveats.

Disclosed, not fixed: packages/avo/src/flywheelGate.ts and
packages/turn-credit/src/receipt.ts ship their own separate, still-colliding
canon() duplicates.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DduZER9F3YMtyJu5TcgL7D

ruvnet commented Oct 21, 2026

Copy link
Copy Markdown
Owner Author

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants