# sweep-doctrine — TCRAUDT reducer library

**Test-Case Reducers Are Underappreciated Debugging Tools.** Source: Laurie Tratt 2026-01 essay, building on Zeller delta-debugging + Regehr C-reducer. Reduce a failing probe to a 5-line test, commit it as institutional memory. Tests outlive every sweep agent's working memory.

## Discipline

5 phases (mandatory for every defect):

1. **Reproduce** at full production scope first — verify defect, capture failing output.
2. **Reduce** inputs to smallest case that still triggers — peel flags, widths, iters, params.
3. **Commit reducer to `tests/sweep-doctrine/`** — NEVER in `runs/` (runs/ stays ephemeral; reducers outlive sweeps).
4. **Fix** defect.
5. **Verify** reducer flips EXPECTED-FAIL → PASS. `make sweep-doctrine` exits 0.

## Test format

Each `test-*.lsp` prints exactly one verdict line:

```
DOCTRINE <name> PASS got=<actual> expected=<expected>
DOCTRINE <name> EXPECTED-FAIL got=<actual> expected=<expected>  ; known open defect, alarm acknowledged
DOCTRINE <name> FAIL got=<actual> expected=<expected>  ; regression — gate fails
```

Shared helpers in `lib.lsp` — assertions, fresh-register builders, expected-truth-table comparators.

## Runner

```bash
make -C ~/git/lumbda sweep-doctrine           # local, all reducers
make -C ~/git/lumbda sweep-doctrine REMOTE=user@host  # via SSH
```

Backed by `run.sh` (serial) + `run-parallel.sh` (xargs -P fan-out).

## When reduction stops shrinking, escalate

Reducer that pins a trigger pair without root cause = building on sand — gate stays green while wrong-output ships. Escalate:

- **Unit** — fire suspect primitive on register state mimicking callsite geometry. Compare bits to reference.
- **Integration** — emit one iter of suspect operation, read every intermediate register. First divergent register names broken step.
- **Functional** — full operation at small width with `record-register-state!` at iter N. Iter where divergence first appears names failure mode.

Reducer = alarm. EXPECTED-FAIL = alarm acknowledged, not silenced. Don't promote any change touching a primitive whose reducer stays EXPECTED-FAIL.

## Hard rules

- Reducers belong in `tests/sweep-doctrine/`; ephemeral sweep artifacts (probe scratch, dispatched cells, per-sweep RESULTS) belong in consumer-side `runs/` directories. Never invert.
- `make sweep-doctrine` exit 0 iff every test produced expected outcome (PASS for positive controls, EXPECTED-FAIL for known open defects).

## License

AGPLv3.
