Context
docs/record.md describes a project’s luria.yaml. Until now
record_doc.py built it entirely in Python:
- a
HEADERconstant; - a
SECTIONStuple of eight titles and introductions; - one function per section, each returning finished markdown with its own table, list or empty-state sentence.
Prose and layout were spread across string literals in a dozen places.
Changing the page’s wording meant editing code. A rule about the page as a
whole, such as “a section with nothing to show is left out”, had to be
enforced in render() over strings it could not inspect.
Two reviews on #395 showed what that cost. The first fix printed a remedy
into an empty section. The owner answered that “messages like this belong
in the same communication channel the linter uses”, which led to the
undescribed-schemes class and to the page leaving the section out. Then
the owner asked for the build itself to “use a templated view”. ADR-130
already gives luria a way to hold prose in a template and derive the facts:
a pattern’s page is a template luria ships (luria:pattern.md.j2).
Decision
The page is luria/view_templates/record.md.j2. record_doc.context(cfg)
returns data only:
- rows for the scheme, journal, fragment, remote, filing and settings tables;
- the schemes that describe themselves;
- each scheme’s contract lines;
- the schema URL.
The template holds:
- every heading and introduction;
- a
tablemacro, with*None configured.*for an empty table; - the empty-state lines of the contract and settings sections;
- the rule that “What each family is” renders only when some scheme describes itself.
It renders in the views sandbox (views._environment()): strict about
undefined names, with luria’s luria: loader and the cell filter. A typo
in the template is a render error naming its line, not an empty string.
It is not linked, and that is load-bearing. The page is made of example
codes (LIT-001, ADR-012), and its prose cites luria’s own decisions
(ADR-071, ADR-125) and issues (#279). Passed through the link fixer in a
downstream record, those would resolve to that record’s documents of the
same number, which is wrong, and silently so. Config.is_generated keeps
the page out of the bare-reference lint, as before.
The page did not change. The refactor was checked by rendering before and after, and the two were byte-identical for:
- luria’s own record;
- nucleation’s record;
- a fresh
luria init; - a one-scheme fixture with a vocabulary;
- a bare one-scheme config with every setting at its default;
- a config with a title-only, a blurb-only and a fully described scheme,
compared against the previous module loaded from
HEAD.
A test now fails if a heading or *None configured.* is written back
into the module.
Alternatives considered
- Register the page as a view luria supplies, as pattern pages are,
listed in
cfg.viewsand rendered byviews.render. That would bring pinning andluria viewslisting for free. Butviews.renderlinks its output, which would misdirect the luria citations above. It would also need the context built when the config loads, beforecontractandnewcan be asked. A view option to skip linking, plus a lazy context, would make it possible. That is a change to ADR-130’s machinery for one page, and is left until a second page needs it. - Let a project override the template. That is the obvious next step
once the prose is a template: a project could word its own record
description. But
luria:templates cannot be shadowed by design (a project cannot replace one of luria’s), and no project has asked. If one does, apathsorviewskey naming a project template is the shape. - Keep the strings. Each later change to the page’s wording or layout
would have stayed an edit to Python. The rule about empty sections would
have stayed a
strip()check over finished markdown.
Consequences
- The page’s text is changed by editing one template. A rule about its layout is a template condition over data.
- The empty-state lines are now visible in one file. Two of them still tell
the reader how to configure more: the contract section’s “A scheme asks
for more with
requires…” and the settings section’s “See the schema for what else can be set.” By the reasoning that moved the families remedy to the lint, they are candidates for removal. That is a wording decision, left to the owner. record_doc.pydrops from 345 lines to about 270, and its section functions return lists, which a test can check without parsing markdown.