# mozz.runner

> A module of mozz_mlake's API.

Main fuzzing loop, configuration, and crash handling.

``fuzz()`` is the primary entry point.  It drives the mutation loop,
classifies exceptions as valid rejections or crashes, grows the corpus
when interesting inputs are found, and saves crashes to disk.

Example:
    ```mojo
    from mozz import fuzz, FuzzConfig

    def target(data: List[UInt8]) raises:
        _ = some_parser(data)   # must raise on bad input, not panic

    def main() raises:
        fuzz(target, FuzzConfig(max_runs=100_000, seed=42))
    ```

## Structs

### `FuzzConfig`

```mojo
struct FuzzConfig
```

Configuration for a fuzzing run.

Fields:
    max_runs:      Total number of mutation iterations (default 100 000).
    max_input_len: Maximum length of a mutated input in bytes
                   (default 65 540 — covers a max-sized WS frame).
    seed:          PRNG seed; 0 picks a non-deterministic seed from a
                   stack address.
    corpus_dir:    If non-empty, load seeds from this directory before
                   the run and save new interesting seeds to it.
    crash_dir:     Directory where crashing inputs are saved
                   (default ``".mozz_crashes"``).
    verbose:       Print progress and final summary to stdout
                   (default ``True``).
    report_file:   If non-empty, write the final summary to this file
                   in addition to stdout (default ``""``).  The file is
                   created or overwritten; intermediate directories must
                   already exist.
    timeout_ms:    Per-iteration timeout in milliseconds; 0 = no timeout
                   (timeout enforcement is not implemented in v0.1.0 —
                   the field is reserved for future use).

Implements: `Movable`

Fields:

- `max_runs: Int`
- `max_input_len: Int`
- `seed: UInt64`
- `corpus_dir: String`
- `crash_dir: String`
- `verbose: Bool`
- `report_file: String`
- `timeout_ms: Int`

#### `__init__`

```mojo
def __init__(out self, max_runs: Int = Int(100000), max_input_len: Int = Int(65540), seed: UInt64 = UInt64(0), corpus_dir: String = "", crash_dir: String = ".mozz_crashes", verbose: Bool = True, report_file: String = "", timeout_ms: Int = Int(0))
```

Create a ``FuzzConfig``.

Args:

- `max_runs`: Number of fuzz iterations.
- `max_input_len`: Maximum mutated input size (bytes).
- `seed`: PRNG seed (0 = non-deterministic).
- `corpus_dir`: Directory for persistent corpus (empty = in-memory
               only).
- `crash_dir`: Directory to save crash inputs.
- `verbose`: Print progress and final summary to stdout.
- `report_file`: Path to write the final report to (empty = no
               file output).
- `timeout_ms`: Per-call timeout (reserved; not enforced in
               v0.1.0).

## Functions

### `fuzz`

```mojo
def fuzz(target: def(List[UInt8]) raises thin -> None, config: FuzzConfig = FuzzConfig(Int(100000), Int(65540), UInt64(0), String(""), String(".mozz_crashes"), True, String(""), Int(0)), seeds: List[List[UInt8]] = List())
```

Run the fuzzing loop against ``target``.

The loop:
1. Picks a seed from the corpus.
2. Applies a random mutator from the default chain.
3. Truncates the result to ``config.max_input_len``.
4. Calls ``target(mutated)``.
5. Classifies the outcome (ok / valid rejection / crash).
6. Adds inputs that reach new heuristic states to the corpus.
7. Saves crashes to ``config.crash_dir``.

Args:

- `target`: The fuzz target function.
- `config`: Run configuration (optional; defaults are sensible).
- `seeds`: Additional initial seeds merged into the corpus.

Raises: Error: If any crashes are detected (summary included in the message).

## Aliases

### `FuzzTarget`

```mojo
comptime FuzzTarget = def(List[UInt8]) raises thin -> None
```
