> ## Documentation Index
> Fetch the complete documentation index at: https://docs.whyfile.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Gates — audit, intent-diff, and check

> The hostile-enumeration audit panel's convergence gate, and the intent-diff/check conformance gates.

## Audit (hostile-enumeration panel + convergence gate)

`whyfile audit` runs the C1 refuter roster over the enriched graph — each lens tries to *refute* a
reconstructed intent node against the real tool output (`explain`/`why`/`list-intent`/`coverage`)
and its source span — then converges each node's findings into one verdict (ADR-0026/0028). It is
LLM-using (unlike the query commands) and read-only by default; the panel model defaults to
`sonnet` (`WHYFILE_PANEL_MODEL` to override).

```bash theme={null}
whyfile audit --dry-run                                  # project the node x lens matrix, no calls
whyfile audit --lens grounding-fidelity --node i_d1       # re-audit one lens on one node
whyfile audit --record --trust-log intent-trust.json     # write panel verdicts to the trust log
whyfile audit --gate --ledger intent-affirmations.json    # exit 5 on unresolved structural disputes
whyfile audit --format markdown                           # human-readable table
```

Each node's output carries a `converged` envelope (`verdict`, `tier`, `needs_human`); the report
summary adds `by_tier` (a count per tier, including `degraded` — a node the panel couldn't fully
review, e.g. a backend outage, distinct from a clean node), `disputed` (structural dispute node
ids), and `auto_verdicts` (the verdicts eligible to record). `--record` appends those auto verdicts
to `--trust-log` (default `intent-trust.json`) via the same path `trust --set` uses — it never
overwrites a verdict a human already set by hand, and skips authored nodes. `--gate` exits 5
(`EXIT_POLICY`) when a structural dispute is not yet resolved by a human `trust --set` or `affirm`
(`--ledger`, default `intent-affirmations.json`); a human resolution — verdict or affirmation —
always clears it. Neither flag runs without being asked: a plain `whyfile audit` never touches the
trust log. See [ADR-0028](../adr/0028-c3-convergence-gate.md).

## Conformance: `intent-diff` and `check`

Two commands make "no unexplained change" (ADR-0021) enforceable, not just informational.

**`intent-diff`** classifies a changeset (same `--base`/`--files`/stdin resolution as `changed`)
into four buckets: `introduces` (decision records the PR adds), `supersedes` (the supersession
those records declare), `governed` (changed code linked to a recorded decision), and
`constraint_review` (changed code linked to a `constraint`-kind node — touches a constraint, not a
proven violation; that call is the reviewer's). `--format markdown` renders a PR-ready paragraph:

```bash theme={null}
whyfile intent-diff --base main --format markdown
```

Add `--gate` to make it load-bearing: `status` becomes `"conformance_required"` (exit 5) unless
every touched constraint is cleared — cleared by the *same changeset* adding a decision record
whose `supersedes ADR-NNNN` names that constraint's governing ADR. A constraint whose source
document has no ADR number in its filename is fail-closed: it can only clear by a reviewer's
explicit supersession, never automatically.

**`check`** enforces *compiled* constraints — the ladder's final rung, prose → structured →
checkable. It reads `intent-rules.json` (default path, `--rules` to override), a small
human-reviewed set of rules; this repo's own compiles [ADR-0016](../adr/0016-intent-query-layer.md):

```json theme={null}
{
  "rules": [
    { "decision": "ADR-0016", "constraint": "No mutation, traversal, or embeddings",
      "type": "forbidden-import", "files": ["src/whyfile/query.py"],
      "forbid": ["numpy", "model2vec", "networkx", "torch", "sentence_transformers"],
      "reason": "the read-only query layer stays lexical" }
  ]
}
```

A violation exits 5, citing the decision by name: `"src/q.py imports 'numpy': violates ADR-0016
(No mutation, traversal, or embeddings). Disagree? Supersede the record, do not fight the
linter."` A rule whose glob matches no file is reported `unenforced` (a stale glob), not silently
passed. `check --propose <constraint>` uses the LLM in its only sanctioned authoring role —
proposer, never certifier: it drafts a `forbidden-import` rule from a constraint node's prose and
prints it for a human to review and commit; it never writes `intent-rules.json` itself.

```bash theme={null}
whyfile check                                    # enforce intent-rules.json, exit 5 on violation
whyfile check --propose "No mutation, traversal, or embeddings"   # draft a rule, print only
```
