Arising from dec-0012 — Surfaces are server-rendered Go templates and static output — no SPA, no dira-operated host
The upheld option is the ruling, not an alternative — the renderer derives, never invents
`docs/design/screens/s1-decision.html` renders **four** alternative cards under "Alternatives on record — 4". Three are refusals. The fourth is the *upheld* option — "Go — one static binary, sub-100 ms cold start" — with its own tag, its own one-line summary and its own grounds paragraph. `entry.schema.json` models `alternatives` as the roads **not** taken: `why_not` is required, and it is documented as "the actual reason" a road was rejected. The chosen option therefore has no field to live in.
**The upheld card is dropped. The ruling carries it.** The chain's matching `✓` row goes with it, for the same reason and one more: `dira why` emits `✗` lines and never a `✓`, and `internal/why` is one producer behind both renderers. A web chain showing a mark the terminal cannot print would make the "same output `dira why` prints" claim marketing.
The rule this establishes
> The renderer derives presentation from recorded prose. It never invents a field, and > where nothing can be derived it renders nothing.
Both halves are load-bearing, and the second one is what makes the first honest.
The **derive** half settles the other gap in the same block. `dec-0017` makes the one-line ground load-bearing — "the summary line carries the grounds, not just the title" — and there is no `summary` field either. There does not need to be one: the first sentence of `why_not` is the one-line ground, and the rest of `why_not` is the detail. Nothing is stored, nothing is duplicated, and a reader scanning twenty summaries is reading the author's own opening sentence rather than an editor's paraphrase.
The **render nothing** half settles the upheld card, because there is no prose to derive it from. And that absence is not a hole in the schema — it is the schema being right. The real `dec-0001` records the grounds the mockup invented a card for:
> Rust — *"Equivalent start-up and single-binary story to Go, with better guarantees, but > slower to write and a smaller pool of contributors for an OSS tool that wants drive-by > PRs. Go's stdlib covers everything dira needs (files, JSON/YAML, an embedded HTTP > server for `dira ui`, SQLite via a single dependency)."*
The mockup's upheld card reads "The standard library already covers files, JSON and YAML, an embedded HTTP server for `dira ui`, and SQLite through a single dependency." That is the same sentence, **moved out of the refusal it answers**. The case for the chosen road is made where it belongs: inside the reasons the other roads lost. Adding a field would have created a second place to put it, and a second place is how the two drift.
Why the struck-refusal device survives, argued rather than assumed
E6-L1 flagged this option as the one that would break the device `DESIGN.md` defends in its r3 → r4 record, and asked for the argument rather than the default. Here it is.
**What r3 → r4 actually defends is the strike with its grounds beneath**, not the strike beside an upheld card. The rejected fix was "collapse the alternatives into a scannable comparison list", and the stated reason is that it "would destroy the struck-through refusal with its grounds beneath". Every refusal keeps both. `dec-0017`'s account is the same and mentions no upheld card at all: "the summary line carries the grounds, not just the title."
**The counterweight is not lost; it gets bigger.** A strike is legible against unstruck type, and after this change the nearest unstruck type is the `h1.ruling` at up to 52px — by the same r3 → r4 record, "one element clearly wins" the frame at a 3.15:1 type ratio against the grounds. That paragraph is the *anchor fix* r3 → r4 chose in place of the comparison list, and its direction was explicitly "reducing element count and strengthening the anchor". Removing a 16.5px card that restates the 52px anchor is that same move, taken once more. Inside each card the strike also sits directly above its own unstruck grounds, so the contrast exists per-row and not only per-page.
**The same record already flags the card as slop-adjacent.** r3 → r4 notes the upheld card's coloured left border as "adjacent to the 'left-border accent stripe' slop tell", kept only because the state was also carried in text (WEB.md 12). That defence needs a state to carry. There is no such state in the data.
**The section stops lying about its own count.** "Alternatives on record — 4" counts three refusals plus a card that is not an alternative. It becomes 3, and the number now matches both the file and `dira why`.
What this costs, stated rather than buried
1. **`dec-0017`'s above-six rule loses its named anchor.** It said: above six alternatives emit only the upheld one open. It now reads **above six, emit every `<details>` closed** — which is `dec-0017`'s own description of the outcome ("the page becomes an index that expands in place") with the exception removed. At or below six, everything stays open exactly as before. Nothing else about `dec-0017` moves. 2. **A twenty-alternative page opens with no prose expanded.** The ruling and the because are still above it at full size, so the page still argues before it indexes. 3. **`.alt.upheld` becomes dead CSS** and is removed from `screens/decision.css` with its comment. Dead rules named after a deleted element are an invitation to restore it. 4. **Three mockups change**, not one: `s1-decision.html`, `s1-decision-long.html` and `s1-decision-withheld.html` are one page with three payloads, and leaving any of them with a card the template cannot emit would leave the disagreement in place. `docs/design/landing/index.html` also refers to the refused/upheld contrast in its copy and is **not** changed here — it is another lane's surface and it is not a route `dira ui` serves.
The check that keeps this true
`fixture-check.mjs` printed this as a FINDING on every run. The finding is replaced by an assertion: no screen may carry an `upheld` state tag or a `✓` mark in an alternatives or chain block, because those are the two shapes of "a card the ledger cannot produce". It is verified in both directions — restoring one card fails the gate.
Alternatives on record — 3
✗Add a field to entry.schema.json so the chosen option can be storedrefused It needs two fields, not one — a way to mark the chosen row and a place for the one-line summary the mockup gives every card — and both of them store facts the entry already carries.
The chosen road is the `title`: dec-0001's title is "Go, not Elixir/OTP, despite kazi's stack", which is the upheld option written as a sentence. A second field naming the same road is two fields that can disagree about one fact, and `dira check` reads the title. The regex tier cannot fill either field — `dira sniff` is lossy by construction (dec-0003) and cannot infer which option won — so a page's composition would vary with how the entry happened to be captured, which turns `source.tier` from an audit trail into a layout input. cst-0002 closed the kind set on the argument that every plausible addition is a tool dira promised not to become; the field-level form of that argument is that every added field must be understandable at every tier, and this one is not.
revisit ifa decision arrives whose chosen option genuinely cannot be stated in its title — at which point the missing field is a title problem, not an alternatives problem
✗Synthesize the upheld card from the decision's title and bodyrefused It reprints, at 16.5px, the two largest elements on the page.
The title is already the `h1.ruling` at up to 52px — DESIGN.md calls it the frame's anchor — and the body is already the `.because` at 19px directly beneath it. The card's one-line summary has no source at all, and its grounds paragraph is not the `because` either: on the mockup those are different content about different things. So this option produces a card that is one part duplication and one part invention.
✗Leave the mockup and the renderer disagreeing, and document the gaprefused The whole point of the fidelity gate is that a pixel diff between a served page and a mockup measures layout.
A mockup carrying an element no ledger can produce makes that comparison permanently red for a reason that is not a regression, and a gate that is expected to be red is a gate nobody reads.