# `mix adr.check`
[🔗](https://github.com/riddler/statifier-ex/blob/v2.0.0/lib/mix/tasks/adr.check.ex#L1)

Reports lines the branch adds that look like violations of ADR-0002 (Appendix
D naming), ADR-0003 (pure core with effects), ADR-0004 (predicator as the
datamodel), ADR-0008 (generated identifier formats), or ADR-0018 (process
artifacts are not code comments) - plus, since ADR-0058, three checks that
are not about the diff at all: `docs/adr/` numbers colliding,
`docs/adr/README.md`'s table falling out of bijection with the directory,
and a branch-added ADR number that already exists on the base ref under a
different filename.

It runs as the `ADR guard` custom stage of `mix quality`, so drift from an
accepted decision is a named gate failure rather than something review has to
catch. Every finding names the ADR it is about. The ADR-0002/0003/0004/0008
findings clear with an inline comment on or above the line citing that ADR or
the word "deviation" - the same justification CLAUDE.md already asks for. The
ADR-0018 bead-ID finding does not: an ADR citation is exactly what it is
checking against, so it clears only with its own marker, `ADR-0018-exempt`,
placed on or above the line.

The ADR-0058 numbering findings (`adr-0058-duplicate-number`,
`adr-0058-readme-index`, `adr-0058-base-number`) clear on neither escape
hatch. They carry no line number - they are invariants over the working
tree's filenames and README table, or a comparison against the base ref's
`docs/adr/` listing, not patterns over an added line - and there is no
comment that makes a duplicate ADR number or a missing table row correct.
The fix is a renumber and a README row move.

`adr-0058-base-number` is the odd one out: a finding from it is always real,
but **a pass promises nothing when `origin/main` is stale.** ADR-0058
decision 2 is explicit that this half "exists for early warning only" and
that "no document, skill, or report may cite a bare-gate ADR guard pass as
evidence that no collision exists on the remote" - the actual guarantee is
`adr-0058-duplicate-number` and `adr-0058-readme-index`, which run
tree-locally and therefore bite once `wurk:mr`'s post-fetch rebase has
materialized a colliding file into the working tree.

## Usage

    mix adr.check
    mix adr.check --base upstream/trunk
    mix adr.check --format json

## Options

  * `--base` - ref to diff against, tried before `origin/main` and `main`
  * `--format json` - print the ExQuality finding contract instead of prose

Exit status is 0 when nothing looks off, 1 when something does, and 2 when no
base ref resolves - **but 2 no longer means nothing ran.** The
`docs/adr/` numbering invariant needs no base ref, so it runs regardless; 2
means only that the diff-based and base-ref checks had no base ref to run
against, and that the numbering invariant ran and was clean. Exit 1 is
possible with no base ref at all, when the numbering invariant itself finds
a collision - a duplicate number or a README bijection failure sitting in
the tree fails the stage whether or not `origin/main` resolves. The
`skip_exit_code: 2` stage config turns a real exit-2 skip into a reasoned
skip rather than a pass; a diff that simply touches no `lib/` file is a
pass, not a skip, since there was something to check and nothing was wrong
with it.

# `execute`

```elixir
@spec execute(argv :: [String.t()], opts :: keyword()) ::
  {:ok, iodata()} | {:skip, String.t()} | {:error, iodata()}
```

Runs the guard and reports the outcome instead of halting.

`opts` are passed through to `Mix.Statifier.AdrGuard.collect/1`, so
`opts[:runner]` drives this without a real git history.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
