name the layer, not only the primitive

The constitution asks which primitive a feature is. It never asked *where* the
feature belongs, and that let a whole feature get built at the wrong layer.

Four layers, outermost wins: content on disk, engine (facts only the engine can
produce), theme (markup), browser (CSS, then JS). Two rules fall out — the engine
never edits authored text to change how it looks, and a feature needing no engine
fact is not an engine feature. architecture.md carries the table and the test;
CLAUDE.md carries the one-line version, since it is the file always loaded.

The example is named in the docs on purpose. A rule with a scar attached is one an
agent can apply; a rule stated in the abstract gets reasoned around.
This commit is contained in:
2026-07-31 12:46:41 +06:00
parent 7eb0bcdffe
commit cf398af725
3 changed files with 34 additions and 0 deletions
+21
View File
@@ -70,6 +70,27 @@ URL shape so the mux has one entry.
---
## Layers — build at the outermost one that can do the job
A primitive says *what* a feature is. This says *where* it belongs, and it is the question that catches a
feature nothing else does (ADR-0045).
| Layer | Owns | Test |
|---|---|---|
| Content | bytes an author wrote | Would a reader's own words change? Then only the author may touch it |
| Engine | facts only the engine can produce — which bundles exist, an image's size, a derivative's name, a permalink | Could anything downstream work this out for itself? If yes, it does not belong here |
| Theme | markup and which fields go where | Is the answer "how it looks"? Then it is a template, not Go |
| Browser | line breaking, spacing, colour, motion — CSS, and only then JS | Does the browser already know something the engine cannot, like the line box? Then leave it there |
Two rules fall out. **The engine never edits authored text to change how it looks**: it may transform text
(`--` into an en dash is a transformation no stylesheet can express) but never lay it out. And **a feature
that needs no engine fact is not an engine feature** — it is a stylesheet, a template, or nothing.
The failure this exists to prevent: widow prevention was built as a Markdown transform that inserted a
non-breaking space into an author's prose. It worked, it had tests, and it was wrong at the layer —
`text-wrap: pretty` does it better with no bytes in the content, and the engine could never see the line box
it was guessing about.
## Invariants — violating one is a stop condition
1. **Open page object.** Known fields as struct members plus a `Meta`/`Extra` bag. Absence equals