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).
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.
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:
--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:
"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.