vyre-conform 0.1.0

Conformance suite for vyre backends — proves byte-identical output to CPU reference
Documentation
# adversarial — Ensures test suites catch intentional sabotage.

The `adversarial` module enforces the theorem that a valid test suite must be capable of rejecting a deliberately broken CPU reference. Passing a correct implementation is insufficient; the gauntlet guarantees that if an adversarial implementor (the "Defender") introduces a plausible, targeted mutation, the test suite (the "Prosecutor") will detect the sabotage and fail.

This module exists to defeat the "tests passed" false-confidence syndrome. Without it, a test suite might achieve 100% code coverage while structurally failing to enforce edge-case invariants. For example, historically, tests for `fnv1a` buffer hashes passed because they only used small inputs; an adversarial implementation hardcoded to fail on buffers >1KB would pass undetected. This module injects known sabotages (like `OffByOne`, `HardcodedZero`, or `DropLsb`) to force the test suite to prove it actually checks boundaries.

```
adversarial/
├── mod.rs               — defines the Implementor/Prosecutor/Defender roles
├── gauntlet.rs          — evaluates Defendants against a target op's law set
├── defender/            — the Defendant struct and built-in mutation classes
│   ├── mod.rs           — defines DefendantClass (HardcodedZero, DropLsb, etc)
│   ├── macros.rs        — helpers for quickly instantiating Defendants
│   └── catalogs/        — directory of hand-crafted sabotages for primitives
└── defenders/           — auto-discovered corpus of adversarial CPU functions
```

The adversarial gauntlet runs during the test evaluation phase (CPU only, no wgpu execution) as part of the overall verification suite. It receives a target `OpSpec` with its declared laws and a catalog of `Defendant` objects (deliberately broken functions). It executes the `algebra::checker::verify_laws` logic against the Defendant. If the test suite fails to detect the break, it emits a `GauntletFinding::Escaped`.

To add a new Defendant (a new type of sabotage), define a function in the CPU reference style that is wrong in a specific way. Add it to `defender/catalogs/<target_op>.rs` or create a new file if it's a new op. Use the `defendant!` macro, specifying the name, the `DefenderClass` (e.g., `DefenderClass::SignFlip`), the broken function pointer, and the exact list of law IDs that this sabotage expects to fail. Finally, register the new catalog in `defender/catalogs/mod.rs` so it is picked up by `full_catalog()`.

Failure Modes:
- **Escaped Defendant**: The malicious CPU reference passed the test suite. Cause: The test suite is weak, missing adversarial inputs or boundary checks. Fix: Write stronger properties in the Prosecutor suite that cover the broken behavior.
- **Over-catch (Informational)**: A law failed that was not in the `fails_laws` list. Cause: The sabotage was broader than expected, or laws overlap. Fix: Informational only, consider refining the `fails_laws` expectation or the sabotage precision.

Example:
```rust
use vyre_conform::adversarial::{Defendant, DefendantCatalog, MutationClass};

// Example of defining a Defendant in a catalog
let catalog = DefendantCatalog {
    target_op_id: "spec:primitive:bitwise:and".into(),
    defendants: vec![
        Defendant {
            id: "and_hardcoded_zero".into(),
            class: MutationClass::HardcodedZero,
            func: |args| vec![Value::U32(0)], // Always returns 0
            fails_laws: vec!["law:and:identity".into()],
        }
    ],
};
```