Skip to content

Nightly fuzzing with a moving seed (#98) - #141

Merged
EONRaider merged 1 commit into
masterfrom
claude/decoder-depth-polish-8m54to
Sep 4, 2026
Merged

Nightly fuzzing with a moving seed (#98)#141
EONRaider merged 1 commit into
masterfrom
claude/decoder-depth-polish-8m54to

Conversation

@EONRaider

Copy link
Copy Markdown
Owner

Summary

Tier 4 (#106), item 2 of 3: replaces the fuzz suite's fixed, deterministic 200-example run with a scheduled nightly run that explores fresh ground every time. Closes #98.

What's included

  • Two Hypothesis profiles in tests/test_fuzz.py: the existing "netprotocols" profile (200 examples, derandomize=True, unchanged — every push/PR stays reproducible) and a new "nightly" profile (10,000 examples, derandomize=False — a real random seed each run). Selected via HYPOTHESIS_PROFILE, read once at import time, so HYPOTHESIS_PROFILE=nightly pytest reproduces a nightly run locally.
  • New .github/workflows/fuzz.yml: schedule (0 3 * * * UTC) + workflow_dispatch, Python 3.12 only (an exploratory job, not a compatibility gate — 3x the interpreters would 3x its cost for no extra coverage of what it's looking for). Kept out of ci.yml deliberately: ci.yml is reused by release.yml via workflow_call specifically so the release gate and the PR gate never drift apart, and a schedule: trigger there would fire that whole ladder on a cron too.
  • Accumulating .hypothesis/ cache: actions/cache, keyed by github.run_id with a hypothesis-nightly- prefix restore-keys fallback. (Note for reviewers: the original plan called for "a cache key that doesn't change per-run" — that doesn't actually accumulate anything, since actions/cache never re-saves once an exact key already exists. The run-id+prefix pattern here is the standard fix and does what was intended: each run restores the most recent cache and saves a new entry.) On failure, .hypothesis/ is additionally uploaded as a workflow artifact so a counterexample is recoverable without repo write access. No custom issue-filing — a failed scheduled run's own red build is GitHub's default notification to watchers, which is the simpler of the two options the issue named.
  • A targeted TCP SYN-options strategy (tcp_syn_options in test_fuzz.py): MSS, window scale, SACK-Permitted, SACK, and timestamps, well-formed and NOP-padded. The real-capture corpus never caught a SYN (tests/fixtures/MANIFEST.md), so unlike NOP/Timestamps (kinds 1, 8, exercised via other captured traffic), these option kinds were otherwise reachable only through test_tcp.py's hand-built single examples — the existing generic fuzz_input strategy essentially never lands on a well-formed multi-option TLV sequence by chance.
  • docs/CLAIMS.md 5.2 flipped from PARTLY TRUE to VERIFIED — both halves of the claim (universally-generated round-trips from Generalize the round-trip property to every protocol #97, and a moving seed here) are now landed.
  • CHANGELOG.md entry under ## [Unreleased].

Not included (used judgment per the handoff, not required): a completeness assertion reconciling test_fuzz.py::ALL_PROTOCOLS against strategies.py::ROUND_TRIP_STRATEGIES — the two lists differ by design (DNSOverTCP is round-trip-tested but deliberately excluded from the chain-walk fuzz properties), so a correct assertion needs more scaffolding than a drive-by warrants; skipped rather than ship something fragile.

Verification

  • uv run ruff check and uv run ruff format --check are clean
  • uv run mypy is clean (strict)
  • uv run pytest passes locally — 1057 passed (200-example profile)
  • CHANGELOG.md has an entry under ## [Unreleased]
  • HYPOTHESIS_PROFILE=nightly uv run pytest — the actual nightly job's workload, run locally end-to-end: full suite, 10,000 examples, real random seed — passes clean in ~7m14s. That's also useful signal on the scheduled job's real runtime.

Notes

fuzz.yml only runs on schedule/workflow_dispatch, so this PR's own CI run will not exercise it — by design, the same reason it isn't folded into ci.yml. It'll get its first real run at 03:00 UTC after merge (or dispatch it manually to check sooner).

Closes #98.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MGDTcK51CWcy6PrNetN213


Generated by Claude Code

tests/test_fuzz.py's "netprotocols" Hypothesis profile is deliberately
deterministic (200 examples, derandomize=True) so a pull request stays
reproducible — but that also means every build since the profile was
written has run the same 200 inputs. Adds a second "nightly" profile
(10,000 examples, a real random seed each run), selected at import
time via HYPOTHESIS_PROFILE, plus a new scheduled workflow
(.github/workflows/fuzz.yml, 03:00 UTC daily + manual dispatch) that
runs the whole suite under it.

Kept out of ci.yml deliberately: ci.yml is reused by release.yml via
workflow_call specifically so the release gate and the PR gate never
drift apart, and a schedule trigger there would fire that whole ladder
on a cron too. .hypothesis/'s example database accumulates across
nightly runs via actions/cache, keyed by run id with a prefix
restore-key (a fixed key would restore forever but never actually save
a new entry, so nothing would accumulate); a failure additionally
uploads it as a workflow artifact so a counterexample is recoverable
without repo write access. A failed scheduled run's own red build is
the notification GitHub already sends by default, so nothing here
auto-files an issue on top of it.

Also adds a targeted Hypothesis strategy building well-formed TCP SYN
options (MSS, window scale, SACK-Permitted, SACK, timestamps): the
real-capture corpus never caught a SYN, so unlike NOP/Timestamps these
option kinds were otherwise exercised only by hand-built examples in
test_tcp.py, dependent on max_examples alone landing on a well-formed
TLV by chance under the generic fuzz strategies.

Flips docs/CLAIMS.md 5.2's "PARTLY TRUE" language now that both halves
of the claim (universal round-trip generation, and a moving seed) are
landed.

Closes #98.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MGDTcK51CWcy6PrNetN213
@EONRaider
EONRaider merged commit d7a73d7 into master Sep 4, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Nightly fuzzing with a moving seed

2 participants