ADR-073: A finding names the key that declared its obligation; the record page lists the contract; no explain verb

Status Active · Filed 2026-09-03 · Issue #141

Context

The proposal in #141 asked for luria explain CODE early — before any new semantics — as the test of whether a compiled contract stays comprehensible. The instinct is right: distributed obligations are only ergonomic if the tool can always answer why does this rule apply? The verb is the wrong shape for it.

Two facts from this record decide that. ADR-030 retired luria ref-status and luria pending, standalone report commands whose information had already moved into luria lint and luria reports, on the finding that a command nobody runs is a surface nobody maintains. And the findings the contract pass already printed carried provenance — but only as the word “luria.toml”, which names one file and no key. With one authoring surface that is harmless. The proposal’s later phases would add a second, and “declared in luria.toml” would then send a reader to the wrong table.

Decision

Provenance lives in the finding. Every contract finding cites the key that declared the obligation, every key when more than one did:

no `source:` in frontmatter — the SOTA scheme declares it a LIT reference
  (luria.toml: schemes.SOTA.requires, schemes.SOTA.references.source)
`primary_topic` wants exactly one of … — has none
  (luria.toml: schemes.SOTA.tag_groups.primary_topic; members from `record/topics.yaml` `primary_for`)

The whole contract renders on the record page. docs/record.md gains a section, What an entry must carry, listing each scheme’s obligations with the same citations — generated by luria index like the rest of that page, so a project that declares a table gets the description for free.

One renderer. The finding’s citation and the page’s line come from the same functions in luria/contract.py. The page cannot say one thing and the lint another, which is the DP-4 requirement and the reason the second consumer was cheap.

No luria explain. Whole-entry explanation, if it ever proves wanted, hangs off an existing workflow. Nothing today asks for it: a surprised author meets the finding, and a reader wanting the whole picture has the page.

Alternatives considered

  • luria explain CODE, as proposed. A verb that renders one entry’s contract with provenance. It is ADR-030’s retired shape exactly — a report nobody runs, because the moment a rule surprises someone they are looking at a lint line, not typing a command. Its content is now split between the finding (the rule that fired) and the record page (all of them).
  • A verbose lint mode (luria lint --explain). Keeps the CLI surface flat and still asks the author to re-run. The finding is the one output they already have; making it self-explanatory costs a parenthetical.
  • Leave “(luria.toml)“. Enough while there is one file. The proposal’s own gate says no second authoring surface without a measured failure, and if that failure arrives the citation has to already be key-precise or every existing finding gets rewritten at the same time as the semantics change.
  • A separate description renderer for the page. Prettier prose, written once, and the first change to a finding’s wording leaves the page describing a rule the lint no longer states that way.

Consequences

Findings are longer by one parenthetical. Existing tests matched on the wording before the citation and were unchanged; the citation is appended.

The record page for this repository says nothing beyond the standard fields, truthfully, and names the three tables that would change that. The knowledge-base example, which declares all three, renders a full section — and its source is now a declared LIT reference rather than a bare requires, which #141 named as the second dogfooding experiment: the untyped form accepted a decision’s code and a sentence as a paper (ADR-060), and the example was still teaching it.

When a second source of obligations arrives, Field.because is where it goes, and the citation renders it without this decision being reopened.