Commit c5bc20e
test(realtime): RG2 — silent-gap property fuzzer (trichotomy: append | reorg/dup | fatal, never silent-skip) (#165)
* test(realtime): RG2 — silent-gap property fuzzer (trichotomy: append|reorg/dup|fatal, never silent-skip)
Property fuzzer for the realtime campaign plan item (e).2. Feeds randomized adversarial
block-delivery sequences (dropped / duplicated / out-of-order / mutated hash|parentHash,
interleaved 204-idle & 409-fork phases) through the REAL realtime consumer
`portalRealtimeEvents` and asserts the trichotomy: every delivery is APPENDED (realized chain
matches the model), RECONCILED (reorg rolled back to the right ancestor / duplicate no-op), or
FATAL (a `gap` throws) — NEVER silently skipped.
The reference model is derived PURELY from hash/parentHash relationships (it never calls
`reconcile`, so the check is not circular); the code's realized chain is reconstructed from the
consumer's own emitted event stream and asserted equal to the model or the consumer must have
thrown. Seeded mulberry32 PRNG (not Math.random); the failing seed is printed on any violation.
Default N=2500 (~1s); heavy/nightly acceptance via FUZZ_N=100000 (>= 10^5, verified zero
violations). Finality held inert so the fuzzer isolates the append|reorg|dup|gap decision.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* test(realtime): RG2 fuzzer revision — reorgedBlocks payload assertion + honest scope + non-vacuity floors
Committee revision (glm/codex/reviewer) on the RG2 silent-gap fuzzer, turning three review
findings into real coverage and candor:
1. REORG PAYLOAD assertion (was a false-green). `ChainModel.apply` now returns the model's
rolled-back suffix on a reorg; the harness asserts the emitted `reorgedBlocks` (by hash, in
order) EQUALS that suffix. Closes the gap where the right `commonAncestor` was emitted with an
empty/mis-sized `reorgedBlocks` — the chain reconstruction (ancestor-keyed) passed while
downstream rollback would break. Mutation-verified: reconcile `reorgedBlocks -> []` now FAILS
here (`expected [ [] ] to deeply equal [ Array(1) ]`) though it stays invisible to the chain
equality check.
2. Header candor. The header claimed a 204/409 interleave that never happened. The generator now
really prefixes a server-concurs 409 (previousBlocks == the seeded ring anchor) on ~1/4 of
sequences, driving the shell's parsePreviousBlocks -> ring-match rewind -> reconnect path on the
wire while leaving the delivered sequence (and the model's prediction) unchanged — zero
model-fidelity risk. Genuine fork-rewind 409 and same-block child redelivery are now explicitly
OUT OF SCOPE with cross-refs to the wire tests that cover them. Finality is documented as a
deliberate isolation, "NOT the full realtime trichotomy".
3. Non-vacuity FLOORS. Per-class + per-wire-shape coverage tallies with lower-bound assertions, so
a future generator edit that collapsed to all-append (or dropped the 409/204 interleave) fails
loudly instead of passing vacuously. Verified green at FUZZ_N=100000.
CONTRACT vs OBEDIENCE caveat added: this proves the consumer OBEYS reconcile's contract in its
event loop, not that the contract itself is correct (reconcile's spec is pinned by the pure-function
unit tests). No production change. Both-version gates green (0.16.8 / 0.16.9, 362 each), biome clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>1 parent afc5c4a commit c5bc20e
1 file changed
Lines changed: 669 additions & 0 deletions
0 commit comments