ADR-032: The status reports are committed views, and the badges land on them

Status Active · Filed 2026-08-07 · Issue #35

Context

ADR-007 made document status a report rather than an error, and put the full detail in markdown files “because a warning with nowhere to be read is a warning nobody reads”. They were written to build/doc-reports/ and uploaded as a CI artifact — which is somewhere, but behind a login, a run page and a zip download. The README badges (ADR-018) counted the same facts and linked to the decision index, a page that doesn’t explain either number.

So the two halves pointed past each other: the badge had the number without the detail, the artifact had the detail without a reader (#35).

Decision

The reports are generated views, committed like every other view. luria index renders them into the configured reports directory — docs/reports/ by default, under the read side of the ADR-021 boundary — and luria index --check, and therefore the lint, fails when they are stale. The directory is generator-owned: orphans are cleaned, and a hand-written file there is an error like in any view directory.

Each badge links to its report. needs decision lands on pending-decisions.md, cited but retired on reference-status.md — the click answers “which ones?”, and the report’s own links answer “where?“.

A report is a pure function of the record. No generation date, no age-in-days column, no stale-after-N-days marker: a committed view that embeds the clock goes stale at midnight with no record change behind it, failing the staleness check and rewriting the same files on every branch — the shared-file churn DP-2 exists to prevent. Ages are stated as dates (“open since 2026-08-03”); the live arithmetic stays in the lint’s console warnings, which nobody commits.

Everything a report names is a link. The flagged document, every citation site, every pending code — the reader arrived from a badge, and the next question is always “show me”.

The reports directory is excluded from reference scanning (is_generated). A report lists retired and dangling codes; scanning it would count each listing as a new citation site, the next render would include the report’s own rows, and the view could never converge — the report reporting the report.

Alternatives considered

  • Status quo: artifact only. The detail exists and is not read; the issue is the evidence.
  • Committed but date-stamped. The obvious port of the old files, and wrong twice: the staleness check fails every midnight, and every active branch rewrites both files daily — a merge-conflict generator on files nobody edits (DP-2).
  • Serve the artifact via GitHub Pages or a workflow summary. Adds a deployment surface for two markdown files the repo can simply carry, and breaks the ADR-018 property that a branch’s README shows that branch’s numbers — a Pages deployment shows whatever deployed last.
  • Keep badges pointing at the decision index. The index answers a different question (“what was decided”); a badge counting problems should land on the page that lists them.

Consequences

  • luria reports still exists (the CI tier, ADR-030) for writing the files elsewhere — actions/lint regenerates them fresh for its artifact, which matters exactly when the lint failed on staleness and the committed copies are what can’t be trusted. In normal use luria index writes them and nobody runs anything extra.
  • The default reports path changes from build/doc-reports to docs/reports. An adopter who pinned the old path keeps it — and keeps badges pointing at files their repo doesn’t carry, which is their configuration to reconcile.
  • The reports joined the docs-index exemption list as a view directory that indexes itself, and this repo’s docs/README.md links both pages.
  • Report links are computed relative to the configured directory, so moving the directory cannot silently break every link in it (DP-3).