ADR-031: A fact the tree already states is populated, not demanded

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

Context

A journal entry’s identity is its timestamp: the path is derived from created: and the lint checks the two agree (ADR-020). luria journal new writes both at once, so entries filed through it are never wrong.

Entries filed any other way — by hand, by a tool that copies the template — can carry an empty created:, and the lint’s answer was an error asking the author to type in a timestamp that the path already states. The rendering pipeline didn’t even need it: journal.read() has always fallen back to the path when the field is missing. The record’s one witness was being treated as insufficient by the check and as sufficient by the renderer (#33).

Decision

luria index populates a missing or empty created: from the entry’s path, in write mode only. The same generation job that commits the views (ADR-029) therefore repairs the field — push a hand-filed entry and the bot fills it in.

The lint error names the remedy it now has. When the path parses, the message says luria index populates the field; when the path implies nothing (a stray notes.md in the journal tree), it says the author must answer, because no witness remains to populate from.

Disagreement is never resolved mechanically. An entry whose created: and path conflict is two witnesses telling different stories — the existing error stands, and nothing overwrites either side.

Alternatives considered

  • Have luria lint write the field — the issue’s literal phrasing. Rejected: the lint is the check, and checks don’t write (the same split that keeps luria link beside it, ADR-005). A lint that edits the tree makes “run it twice” a different question the second time.
  • A dedicated fix command. Rejected on ADR-030’s grounds the week they were established: the surface is workflows, and “repair the derived field” is not a workflow — it is a step of regeneration, which already has a command.
  • Leave it an error. The status quo demanded a human transcribe 2026/08/03/211926.md into created: '2026-08-03T21:19:26' by hand, with a typo introducing exactly the disagreement the check exists to catch.
  • Populate from git history instead of the path. The path was chosen over commit time as the identity precisely because a rebase can’t move it (ADR-020); reaching back to git here would reintroduce the dependency that scheme removed.

Consequences

  • A hand-filed entry heals on the next luria index — locally or by CI’s generation job — and the lint stays a read-only check.
  • --check mode never writes, so the staleness gate is unchanged.
  • The _template.md in both trees documents the behavior where the field is defined.