Mostly Done.
Contents

12 Machine-checked taste

Some judgments have proxies. The rest still need the critic.

Rendering systems turn structured input into geometry and pixels. Their hardest defects pass type checking and look plausible in data. A label sits on a bend. Two words crowd each other. A glyph is present but shifted. A render harness declares a colored equation blank.

The defense is layered: separate layout from rendering, then give each layer its own proof. Some perceptual judgments can become executable rules. Knowing which ones is an engineering skill in its own right.

12.1 Keep layout platform free

Strong rendering systems share a shape: frontends that parse languages into a shared representation, a platform-free layout layer, and backends that render scenes.

The boundary makes several things cheap:

Without the split, a visual bug collapses into a platform screenshot. With it, the agent can ask whether the wrong box was generated or the correct box was drawn wrong.

Platform free deserves a precise reading. Your layout layer can import no platform UI and still consume platform ink metrics through an injected measurer, and a clamp on a font’s ink ascent can dominate the constants around it. Expect the test doubles to lie about this. A mock measurer with generous ink can hide the very clamp a test means to exercise, so proving the clamp works may take a special low-ink mock. Substitute metrics injected for headless runs can be wrong for most of the fonts they stand in for. The core is portable and headless. Its output still differs by platform, and separate goldens per platform are the honest way to say so.

12.2 Convert a perceptual complaint into geometry

The complaint usually arrives as a sentence that cannot be unit tested:

The agent’s job is to find the stable geometric rule underneath. Consider a diagram engine that centers each edge label on its arrow, and a complaint that one label sits on an arrow too short to see. The rule that comes out is a product decision, not a coordinate: a label belongs to the visible shaft, so the midpoint is computed after subtracting an 11.5-point arrowhead inset from each end, and if too little shaft remains, the layout extends the segment.

The durable rules in this family involve:

Fix the generator and add a linter rule. The generator stops producing the bad geometry; the linter catches any other route that reintroduces it. Give the two different constants on purpose. In the diagram engine above, the generator reserves a 14-point label stub while the linter fails below 10 points, so the aim point has headroom over the ratchet.

This turns one act of taste into a permanent floor. You remain responsible for noticing new ugliness. The machine remembers old ugliness.

12.3 Use exact geometry before pixels

Geometry tests are fast, deterministic, and easy to localize. They should assert domain concepts, not incidental coordinates.

A weak test says a label’s x coordinate is 143.5. A stronger test says the label does not intersect a fixture and is centered on the usable shaft. The coordinate changes with font metrics. The rule stands.

Property tests cover whole classes:

These checks do not prove the render looks good. They remove many ways it can look predictably bad.

12.4 Add pixel proof where geometry stops

Fonts, antialiasing, clipping, color, and backend behavior live below geometry. Golden images or render signatures can catch failures there, but only if the detector has proved it can see. The quiet failures are the dangerous ones: an ink signature that averages thin strokes into invisibility, a golden file of zeros that still passes, a red-channel metric that calls a red glyph blank. Test the harness with fixtures that vary:

The harness may use exact pixel diffs, perceptual metrics, ink bounds, or structural signatures. Whatever the metric, it should follow the contract and reject a known-bad probe.

12.5 Compare against an independent renderer

The strongest reference is a system that shares none of your implementation. Your layout code and your tests can repeat the same wrong assumption, and a separate renderer gives that assumption a chance to disagree. Publishing your output beside the established engine, same input, matched height, puts the disagreement where anyone can see it. But a side-by-side supports visual judgment, not an equivalence claim. State which differences matter, and until a tolerance exists, do not call the comparison a test.

Independence can also come from inside the system: a full-render path checked against a patch-render path, multiple backends, structural linting against the generated scene.

12.6 Generate the documentation

Rendered documentation should come from the live engine. A gallery that regenerates in CI on every push cannot freeze a changed example inside a stale screenshot, and it exposes the marketing to the same failures as the product, which is exactly the point.

Watch for the assets that sit outside the loop. A wordmark your engine typeset once and you then committed as a static image proves nothing about today’s build. Typeset by the engine itself is historically true and verifies nothing. Provenance and verification are different properties, and a documentation pipeline should know which one each figure has.

Generation alone is not enough. The figure pipeline needs tamper tests, calibrated captures, and review. The proof should be easier to inspect than the claim it supports.

12.7 Know where the proxy stops

The hardest defect to encode is label-to-edge association: a label can clear every geometric fixture and still appear to annotate the wrong one of two near-parallel edges. The judgment is semantic, and no lint rule expresses it yet.

The constants have a domain too. A minimum-clearance floor is a proxy for perceived crowding, and perception moves with font, scale, line weight, and neighboring geometry while the constant stands still. Every proxy has a range where it stops matching experience.

Trust in a renderer is layered: exact structure, tested pixels, independent comparison, and a human who still notices when the composition feels wrong.

use ← and → to turn pages