A vocabulary value page shows which documents are under a value, never why
- Dominant language
- Python
- Stars
- 21
- Forks
- 2
- Avg merge
- 4h 13m
- Merged PRs (30d)
- 98
Description
`vocabularies.pages()` renders every value page as `TABLE_HEAD` + `a.row()` — the fixed `# | Title | Summary | Status`. That is right for a browsing index and wrong for the case that motivated vocabularies in the first place: a value whose whole content is a judgement the record made about those documents.
## The case
The anthology assesses practices on a `consensus:` axis (`unassessed | unreplicated | contested | emerging | converged | universal`). A reader who follows **In dispute** from the practices index lands on `docs/practices/consensus/contested.md`:
```
# SOTAs with `consensus` `contested`
**In dispute** — credible groups publicly disagree, now — the fork in a line of work,
whose trunk is agreed and whose branches are not.
2 of 144 SOTA documents. …
| # | Title | Summary | Status |
```
Two practices, and not one word about the dispute. The record *knows* — each assessed practice carries a `consensus_note:` saying what the reading rests on — but that field appears in no generated view at all.
## The second half is the same half
That is also why the codes inside those notes sit bare. `doc_refs.PROSE_KEYS` is a constant, and the comment above it is right about why:
> a key is prose exactly when the generator renders its value as markdown somewhere … a project cannot make a field prose by declaring it so, because the rendering is what makes it true.
`consensus_note:` is rendered nowhere, so it is correctly not prose, so `luria link --fix` correctly leaves `(LIT-151, LIT-181)` unlinked. Nothing here is broken. The rule is doing exactly what it says, and what it is telling us is that the field has no reader.
So this is one change, not two: render the note and it *becomes* prose by the constant's own test. The two must move together or the constant stops being true.
## Sketch, not a proposal
Two candidate shapes, and I do not think the choice is obvious:
1. **The vocabulary declaration names its companions.** `[luria.schemes.SOTA.fields.consensus]` gains something like `note = "consensus_note"` and/or `cite = "contested_by"`, and `pages()` renders them per row. Prose-ness then follows from the declaration rather than being asserted by it — which keeps the constant's rule intact, but does move the decision into config, which is what the constant was written to prevent. Worth thinking about whether "declared as a vocabulary's note field" is genuinely different from "declared prose".
2. **Generic extra columns on a value page**, with no special status for notes. Simpler, weaker, and does not solve the linking half.
Either way it needs a decision document, because the PROSE_KEYS rationale is load-bearing and this walks up to it.
## Why now
The anthology just added `contested_by:` — a checked LIT reference required exactly when `consensus: contested`, on the ground that contested is the only value on that axis asserting a specific other document exists (dmarx/anthology-of-the-sota ADR-016). That makes the opposition **structural and verified**, so the data a value page would need is now guaranteed present rather than optional prose. It does not make it **visible**: the reader following "In dispute" still learns who only by opening the document. That is the half this issue is.
Contributor guide
Research direction
Start with vocabularies.pages() and inspect how value pages use TABLE_HEAD and a.row(); then read doc_refs.PROSE_KEYS and its rationale. Use docs/practices/consensus/contested.md, consensus_note, and contested_by as the concrete case, and write the needed decision document before choosing how the note and references should appear and become linkable.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- documentation, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100