cargo-stern4rust 0.2.0

Cargo subcommand that fails the build when a Rust workspace breaks a house coding rule, such as AAA test structure or one struct per file
Documentation
# Implemented Features

What `cargo-stern4rust` does today. Anything not listed here is not built, and
the known gaps in what *is* built are in [OPEN_POINTS.md](OPEN_POINTS.md).

## Version 0.2.0

### Rules

- **`readable-source`** — every `.rs` file can be read and parsed. Registered
  first, because its failure explains every other rule's silence about the same
  file. [R004]ADRs/R004-ADR-ReadableSourceRule.md
- **`header`** — every `.rs` file opens with the repository's header, supplied
  by `--header-file`. Exact after normalisation; one offence per file, carrying
  the whole expected header. [R001]ADRs/R001-ADR-HeaderRule.md
- **`test-file-structure`** — header, imports, constants, helpers, tests; each
  group alphabetical; spacing part of the shape. `Helpers` defined by exclusion.
  [R002]ADRs/R002-ADR-TestFileStructureRule.md
- **`test-free-source`** — no `#[test]`, `#[cfg(test)]` or `#[cfg_attr(test, …)]`
  outside `tests/`. Feature gates untouched.
  [R005]ADRs/R005-ADR-TestFreeSourceRule.md
- **`tests-layout`** — one `tests/all_tests.rs`, a `mod.rs` in every subfolder
  on the way down, both holding only the header and `pub mod` declarations.
  [R003]ADRs/R003-ADR-TestsLayoutRule.md

### Analysis

- AST-structural via `syn`, with `span-locations` for item positions. No type
  resolution, no build required — the tool runs on any syntactically valid
  source.
- Comment folding: `//` lines above an item count as part of that item, so a
  documented test is not a spacing offence.
- Predicate scanning for `cfg`/`cfg_attr`, by identifier rather than substring,
  so `any(test, …)` and `not(test)` are caught while `feature = "test"` is not.
- Normalisation once, in `SourceFile`: BOM stripped, `\r` stripped, paths
  forward-slashed. No rule can forget it.
- Whole-package read before judging, which the tree-wide rules require and which
  removes any dependence on walker order.

### Resolution

- `--manifest-path` and `--package`, resolved through `cargo_metadata`.
- `target/`, `.git/` and **any directory holding its own `Cargo.toml`** are not
  walked. A nested package is a different package.

### Reporting

- Text table, columns sized to contents, each offence followed by an indented
  `fix:` line.
- `--format json` — the same run as a document: `files_scanned`,
  `offences_found`, `offences_reported`, `offences_omitted`,
  `offence_threshold`, `rules_broken`, and the offence array. Every key always
  present, so the shape never varies.
- Every offence carries a **required** `correction`, plus optional `subject` and
  `expected`.
- `--offence-threshold N` (default 100, `0` for all) caps what is **printed**.
  The summary, the omitted count and the exit code all see every offence.
- Offences sorted by file, then line, then rule.
- Exit codes `0` / `1` / `2`, with `2` distinct from `1` so a wrapper can tell a
  finding from a broken CI step.

### Packaging

- Publishes as `cargo-stern4rust` with a `stern4rust` library, so cargo resolves
  `cargo stern4rust`.
- `Args::without_cargo_subcommand` — the argv fixup every cargo subcommand
  needs, conditional and positional, so a package named `stern4rust` survives.

### Project

- 242 tests, one test file per source file, `autotests = false` with a single
  `[[test]] all_tests`.
- Two gates: stage 1 (fmt, clippy `-D warnings`, tests), stage 2 (`crap4rust`,
  `twin4rust`, `iceberg4rust`, and stern4rust against its own tree).
- Self-gating: a rule that would fail this repository cannot be merged into it.
- Nine ADRs — five `R` rule ADRs, four unnumbered.