dev-chaos 0.9.2

Failure injection and recovery testing for Rust. Disk faults, network failures, panics. Part of the dev-* verification suite.
Documentation
# dev-chaos — Project Specification (REPS)

> Rust Engineering Project Specification.
> Normative language follows RFC 2119.

## 1. Purpose

`dev-chaos` MUST inject controlled failures into a system under test
and provide primitives to verify recovery. Output MUST be
`dev-report::CheckResult` or `Report`.

## 2. Scope

This crate MUST provide:

- A `FailureMode` enum for common failure types.
- A `FailureSchedule` for deterministic, attempt-based injection.
- A recovery-verification helper (`assert_recovered`).

This crate SHOULD provide (later versions):

- IO wrappers (`ChaosFile`, `ChaosReader`, `ChaosWriter`) that inject
  failures into real Read/Write types.
- Async equivalents for `tokio::io`.
- Process kill simulators paired with `dev-fixtures`.
- Latency injection.
- Crash-restart helpers for WAL recovery testing.

This crate MUST NOT:

- Inject failures probabilistically by default. Determinism is the
  contract.
- Replace mutation testing crates (`mutagen`, etc.).
- Run the system under test. Composition with the user's harness
  is the user's responsibility.

## 3. Determinism

A given `FailureSchedule` MUST produce the same sequence of failures
for the same sequence of attempts. This MUST hold across runs and
across machines.

If randomness is later added, it MUST be opt-in, seeded, and
reproducible from the seed.

## 4. Recovery contract

`assert_recovered(name, expected_failures, actual_failures, final_state_ok)`
returns a `CheckResult` tagged `chaos` and `recovery`:

- `Pass` when `actual_failures >= expected_failures` AND `final_state_ok`.
- `Warn` (Warning) when `actual_failures < expected_failures` AND
  `final_state_ok` (under-injection: schedule fired fewer times than
  expected).
- `Fail` (Critical) when `final_state_ok` is false, regardless of
  failure counts. Additionally tagged `regression`.

### 4.1 Required evidence

Every `CheckResult` from `assert_recovered` MUST carry numeric
`Evidence` for:

- `expected_failures`
- `actual_failures`
- `final_state_ok` (1.0 = true, 0.0 = false)

## 5. IO wrappers

`dev_chaos::io` provides synchronous wrappers around `Read`/`Write`:

- `ChaosReader<R>` and `ChaosWriter<W>` consume a `FailureSchedule`
  and inject `io::Error` per [`FailureMode`] mapping.
- `ChaosFile = ChaosWriter<File>` for filesystem writes.
- On non-failing attempts, behavior MUST be byte-identical to the
  underlying reader/writer.
- `PartialWrite` MUST emit exactly one byte (when the caller asked
  for at least one) before returning the error, so the caller
  observes a torn-write state.

The `async-io` feature pulls in `tokio::io` and adds
`AsyncChaosReader<R>` and `AsyncChaosWriter<W>` with the same
contract.

## 6. Latency injection

`dev_chaos::latency::LatencyInjector` returns deterministic per-attempt
delays via `LatencyProfile::{Constant, LinearRamp, StepSchedule}`. The
type is intentionally side-effect-free: `delay_for(attempt)` returns
the duration; the caller decides when to sleep.

## 7. Crash-restart helpers

`dev_chaos::crash::CrashPoint::after_byte(N)` wraps a `Write` so that
the underlying writer receives at most `N` bytes cumulatively before
all subsequent writes return `WriteZero`. This models "process
crashed mid-write" without actually crashing the process.

## 8. Producer integration

This crate MUST provide `ChaosProducer<F>` implementing
`dev_report::Producer`. Given a closure returning
`Vec<CheckResult>`, the producer emits a finalized `Report` with
`producer = "dev-chaos"`.

## 9. Safety

This crate MUST NOT execute any failure injection that requires
elevated privileges. Disk-full simulation, kernel-level fault
injection, and similar are out of scope.

This crate MUST NOT modify the user's filesystem or process state
outside of types the user explicitly hands it.