audit every feature against the layer test

Deleting the widows feature answered one question; the human asked the general one.
So every feature built so far is now audited, with the verdicts as a table in
ADR-0046, and each remaining queue entry carries a layer note before anyone writes
code for it.

The codebase turned out to be otherwise clean, and I checked rather than remembered:
no Go file writes a tag, a class or a style. ADR-0036's rule that all markup comes
from a fragment had already forced that.

One real finding. A tag listing received only `.Groups`, so the engine had decided
that a tag listing *looks* grouped — ADR-0032's own reasoning was "so a busy term
stays readable", which is a readability judgement. It now receives both shapes: the
partition, because a template cannot group for itself, and the flat list, because
choosing between them is markup. `Item` gained `.Section` so a flat listing can still
say where an entry came from.

Two judgement calls recorded rather than left implicit. The typographer stays: turning
`--` into an en dash is a character transformation no stylesheet can express. Chrome
strings stay: translations are data, and the alternative is every theme hardcoding
Bengali month names. The inlined stylesheet is accepted with its cost written down —
bytes per page, no caching — and a trigger for revisiting it.

Two patterns worth reusing came out of this: offer the shape rather than choosing it,
and a split feature is normal — search will be an engine-built index queried by the
browser, not one or the other.
This commit is contained in:
2026-08-01 02:23:36 +06:00
parent a2ccb45b0d
commit 959865e334
6 changed files with 109 additions and 12 deletions
+13 -2
View File
@@ -46,10 +46,10 @@ A listing page receives `.Title`, `.Lang`, `.Canonical`, `.Style` as above, plus
| Field | Contents |
|---|---|
| `.Items` | entries on this page: `.Title`, `.Key`, `.URL`, `.Date` |
| `.Items` | entries on this page: `.Title`, `.Key`, `.URL`, `.Date`, `.Section` |
| `.Page`, `.Pages` | 1-based position and total, `Pages` at least 1 |
| `.PrevURL`, `.NextURL` | empty at the ends; *newer* is `prev`, because the order is newest first |
| `.Groups` | set instead of `.Items` when entries are grouped — a tag listing groups by section, each `.Name` and `.Items` |
| `.Groups` | the same entries partitioned by section, each with `.Name` and `.Items`. A tag listing supplies **both** shapes and the theme picks: templates cannot group, so the engine offers the partition, but whether a listing looks grouped is markup (ADR-0046) |
## Chrome text and formatting
@@ -125,6 +125,17 @@ the document head, which is what a reader looks for:
Only with a declared `base`: without one there is no feed to point at.
## What is yours and what is the engine's
The engine supplies facts it alone can produce — which bundles exist, what a picture measures, where a
permalink points, what a month is called in Bengali. Everything about how those facts *look* is yours, and the
engine is audited against that line (ADR-0046, `docs/architecture.md`). Two consequences worth knowing:
- Where a listing offers more than one shape of the same data — `.Items` and `.Groups` — pick one. The engine
is not telling you which.
- If something you want is purely visual, it is CSS or a template, and asking the engine for it is the wrong
request. Widow control used to be an engine feature and is now one line of stylesheet (ADR-0045).
## Typography is the theme's
The engine transforms text where no stylesheet could — smart quotes, dashes, ellipses — and stops there. How