Ported CUBIC, DRR, and WFQ checkers onto the generic TraceSpec interface.#99
Merged
Conversation
Replace the hand-rolled checkRowsWithCoverage replay loop with a ReplayState wrapper and a TraceSpec instantiation, mirroring the DCQCN port (#98). The existing step/recordCover/key/canonicalizeRows semantics are reused unchanged, and the per-row global-key monotonicity check is preserved inside stepRow. Soundness and preservation lemmas delegate to the generic TraceSpec proofs, so no new proof obligations are introduced; the build elaborates them. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the checkRowsWithCoverage replay loop with a ReplayState wrapper and a TraceSpec instantiation, following the DCQCN template. step is fed via toEvent and recordCover reads the pre-step Global, exactly as before; the global-key monotonicity check moves into stepRow. Soundness/preservation lemmas delegate to the generic TraceSpec proofs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the checkRowsWithCoverage replay loop with a ReplayState wrapper and a TraceSpec instantiation. WFQ's coverage observer previously threaded a distinct-class accumulator (seenClasses) that lived outside both Global and CoverageState. To keep observeCoverage self-contained and uniform with the other five checkers, thread it through a generic 'seen : Std.HashSet Nat' scratch field added to the shared CoverageState (with covSeen and a covMerge union). The field is never serialized, so coverage reports and golden fixtures are unchanged. class_count_ge_2 now gates on cov.seen.size >= 2, equivalent to the old distinct-list length; the now-dead listContains helper is removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
baochunli
added a commit
that referenced
this pull request
Jul 6, 2026
* Add DRR and WFQ golden fixtures and wire them into CI The lean-fixtures CI job built drr_check and wfq_check but never ran them on golden fixtures — only AQM and CUBIC had fixture scripts, so DRR/WFQ were exercised solely by the accept-only conformance matrix. In particular WFQ's class_count_ge_2 coverpoint (the ported `seen` accumulator path from #99) was not golden-tested anywhere. Add fixtures/drr and fixtures/wfq mirroring the CUBIC/AQM layout: an accept trace (captured verbatim from the CI conformance run) plus reject cases per checker, and --coverage-out golden fixtures. A hand-verified 2-class WFQ trace (simulator-generated, accept-by-construction) golden-tests class_count_ge_2. All .expected/.coverage.expected files are snapshots of real checker runs, not hand-written. Add run-{drr,wfq}[-coverage]-fixtures.sh (clones of the cubic/aqm runners) and four CI steps. No Lean source changes; checker behavior is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Harden coverage fixture runners against restrictive TMPDIR Use `mktemp -p .` (repo-local temp file) instead of the default `mktemp`, which honors $TMPDIR and fails with "Operation not permitted" under sandboxes that deny writes to the system temp dir. Applied to all three coverage runners (aqm/drr/wfq) for consistency. Works on both BSD (macOS) and GNU (CI) mktemp; temp files are removed each iteration and never land in the repo tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ports the remaining three LeanGuard checkers — CUBIC, DRR, and WFQ — onto the generic
LeanGuard.Shared.TraceSpecinterface, matching AQM, PFC, and DCQCN (the latter merged in #98). This closes the mechanization item called out in the paper's conclusion — "extending per-protocol mechanization from AQM, PFC, and DCQCN to the CUBIC, WFQ, and DRR checkers" — so all six protocol checkers now share the same replay interface and delegate their soundness/preservation lemmas to the once-and-for-all generic proofs inTraceSpec.lean.This is a behavior-preserving structural refactor, not new proof work. Each checker's hand-rolled recursive
goloop is replaced by aReplayState/TraceSpecinstantiation. The hard semantic content —step(transition semantics),recordCover(coverage),key, andcanonicalizeRowsordering — is reused unchanged. No protocol instantiates the preservation lemma with a concrete invariant, so there are no bespoke proofs to discharge; a greenlake buildis the proof check (the theorems elaborate at build time).Commits (one per protocol)
steptakesRowdirectly;recordCover(cov, r). Simplest case.stepfed viatoEvent;recordCover(cov, g, r)reads the pre-stepGlobal.Coverage.lean) — see design note below.All three follow the DCQCN
ReplayState { g, lastKey }template rather than the AQM/PFC no-wrapper template, because each currently performs a per-rowkeyLt"global key went backwards" monotonicity check; that check is preserved insidestepRow.Design note: WFQ's observer accumulator →
CoverageStateWFQ's coverage observer threads a distinct-class accumulator (
seenClasses) that lived outside bothGlobalandCoverageState, returningCoverageState × List Nat. The generic observer signatureCoverageState → State → Row → CoverageStatehas no room for it. Rather than putting coverage bookkeeping into the trusted replay state, this PR adds a genericseen : Std.HashSet Natscratch field to the sharedCoverageState(pluscovSeenand acovMergeunion). This keeps WFQ'sobserveCoverageself-contained and itsstepRowuniform with the other five checkers, and preserves the observation-vs-replay separation thatreplayWithObserverM_agreesformalizes.The field is never serialized (
covList/CoverageReport.toJsononly emitpoints/counts), so coverage reports and golden fixtures are unchanged, and the cross-layeraqm_dcqcn_checkmerge is unaffected (AQM/DCQCN leaveseenempty).class_count_ge_2now gates oncov.seen.size >= 2, equivalent to the old distinct-list length; the now-deadlistContainshelper is removed.Preserved (no external change)
checkRowsWithCoverage/checkRowskeep their signatures, soCubicMain/DrrMain/WfqMain, the compositeAqmDcqcnMain,lakefile.lean, CI,configs/ci/*.toml, and all fixtures/golden files are untouched.Verification
lake buildof all 7 checkers — green, no warnings /sorry/ errors. Since Coverage.lean is shared, this recompiles every protocol +aqm_dcqcn_check, and elaborates all soundness/preservation proofs.Coverage.leanedit; confirmsseenis not leaked into reports).leanguard-rundrives the Days simulator, then runs the checkers on emitted traces — the only end-to-end coverage DRR/WFQ have):leanguard_cubic.toml→accept: true(aqm_check, cubic_check)leanguard_drr.toml→accept: true(aqm_check, drr_check)leanguard_wfq.toml→accept: true(aqm_check, wfq_check)Out of scope (possible follow-ups)
run-drr-fixtures.sh/run-wfq-fixtures.sh+ CI steps for DRR/WFQ (they have none today; only the conformance matrix exercises them).keyLtcheck across all six checkers (AQM/PFC dropped it and rely oncanonicalizeRowssorting alone).replayM_preserves(a much larger effort that no existing checker attempts).🤖 Generated with Claude Code