to-fuzz
Take the current conversation and codebase understanding and produce a fuzzing plan: the set of targets worth fuzzing, each pinned to a concrete failure oracle. Do NOT interview the user — synthesize what you already know. Then write the plan and, when the harness is obvious, scaffold the target stubs.
A fuzz target is three things: an entry point (the function under test), an input model (how bytes become that function's arguments), and an oracle (the check that decides a run failed). The oracle is the whole game — a fuzzer that only catches segfaults wastes most of its runs. If /to-invariants has already produced docs/INVARIANTS.md, mine it: every enforceable invariant is a ready-made oracle.
Process
1. Map the attack surface
Find the code that turns untrusted or complex input into internal state — that's where fuzzing pays. Sweep for:
- Parsers / deserializers / decoders — anything named
parse,decode,from_bytes,read_*, or that takes&[u8]/stringfrom outside. Highest ROI; fuzz these first. - State machines — sequences of operations where the order can violate an invariant (a fuzzer drives random valid-ish op sequences).
- Encoders paired with decoders — candidates for a round-trip oracle.
- Arithmetic / indexing / allocation sized by input — overflow, panic, quadratic blowup, OOM.
- Trust boundaries — any input crossing a network, file, or IPC edge.
2. Choose an oracle per target
Pick the strongest oracle you can compute cheaply. In rough order of value: