The current navigation item in Form Logic’s light theme measured 1.004:1 against the surface behind it. By the numbers, it was effectively invisible.
It survived one release candidate after another because every review depended on a person looking at a rendered screen. Most of those reviews happened in dark mode, where the same item looked right.
Fixing the value was easy. The important part was what the defect exposed: judgment can only review the render in front of it. When a design system depends on someone checking the right screen, theme, and state at the right moment, its quality becomes partly a sampling artifact.
Form Logic is an attempt to reduce that dependency. The question is not whether taste can be automated. It cannot. The question is how much of a visual ruling can be converted into an executable constraint, and what must remain with the person looking at the render.
The system and the seat I keep
Form Logic is a design system I own end to end. It consists of five packages distributed as tarballs, a component catalog, and a governance pack that encodes its rules and enforces them through Strict Mode.
This site uses Form Logic as its foundation. Its color, spacing, typography roles, radii, shadows, and motion resolve through the same release that renders the live figures below. When the release changes, both change together.
The catalog is evidence, not marketing. What it renders must be what the packages ship. If the catalog fixes a package defect with private CSS, it stops proving anything about the system itself.
That rule was broken for six release candidates. The package shipped no document font and no canvas material. The catalog restated both privately in its own stylesheet, so the catalog rendered correctly while every consumer inherited the browser's default serif on a white page. The one surface anyone looked at was the one surface that had been repaired by hand.
The correction is the rule stated as an instruction rather than a principle. When the catalog carries something the package should own, the treatment moves into the package and the copy is deleted.
The working arrangement is similarly explicit. One AI agent handles implementation. A second rebuilds a reference application against every release candidate using only the public API. That application acts as a consumer test. Missing capabilities and awkward interfaces must surface as findings rather than disappear behind local workarounds.
I keep one specific role. I inspect the rendered screens, make the visual rulings, and approve the commit. No visual baseline can be regenerated before I have accepted the render it records.
That seat carries more weight than I would like, because the automated visual layer beneath it is the weakest gate in the system. The suite captures the top of each route and tolerates 120 differing pixels so that antialiasing never fails a run. It cannot see a version label change or a subtle tonal shift. A green visual run is not evidence that a color change landed.
Everything that layer cannot see is still mine.
The project keeps asking the same question in different forms: which parts of my judgment can become something that fails a build, and which parts still require me to sit in front of the result?
Turning rulings into tests
The fix for the 1.004:1 contrast ratio was not simply a better token value. It was a rule with a test attached.
Every ink role and border role now has an allowed contrast band against every surface on which it can legally appear, in both themes. The suite recomputes those relationships directly from the source tokens on every run, 88 cells at the time of writing. Any cell outside its permitted band fails the build.
Exceptions are also executable.
When I decided that tertiary text on selection planes could remain below the essential-text floor, the ledger recorded the exception by name and pinned its measured value. It was not a general waiver. It described one accepted condition.
Later, a separate ruling lightened the selection plane. Tertiary text rose to 5.47:1, and the suite failed. The original exception no longer matched the condition that had justified it.
Nothing was visually wrong. The failure existed because an exception whose reason had disappeared was still present in the system. I had to remove it deliberately.
That is the property I want from every governed rule: a ruling should expire when the conditions beneath it change. Acceptance should not transfer automatically from one visual state to another.
Measuring reference systems instead of admiring them
Partway through the work, I had an agent audit a product that designers often cite when they mean “premium.”
The instruction was to measure it rather than admire it. The agent inspected computed styles, contrast ratios, DOM semantics, and keyboard behavior across the marketing site, documentation, and authenticated application.
The audit produced two useful findings.
The first was confirmation with numbers attached. Its border hierarchy sat between 1.30:1 and 1.88:1 against the canvas. Most structure came from alignment, spacing, and disciplined use of ink rather than strong outlines. Its own design writing expressed the same principle directly: elements should not compete for attention they have not earned.
I adopted the test, not the values.
Form Logic’s borders now derive from an authored ink wash governed by the same kind of restraint, but the actual values are ours. I selected them in rendered comparisons. The ledger now enforces the bands they must remain within.
The second finding was more useful because it showed the boundary of visual polish.
The audit found heading structures that skipped levels, a disclosure button nested inside a navigation link, and a drawer that did not respond to Escape. These were defects that Form Logic’s gates would reject.
The reference product’s polish is real. It is also maintained through continued attention. My constraint is different. I am one person, and attention does not scale. The system therefore has to retain more of the judgment in executable form.
What remains taste
Compiling judgment does not mean automating taste. The work repeatedly demonstrated the difference.
When the light theme needed to become a composed theme rather than an inversion of the dark one, the agent staged four variants of the same real screen.
My ruling was not a variant name. It was a sentence.
I preferred the metric strip in one version, the form fields in another, and the table in a third.
The agent’s job was to determine what that sentence meant in tokens. The fields I thought I was comparing turned out to be byte-identical in two variants. What I was actually responding to was the border around them.
The separator treatment I preferred could be reproduced by drawing the border family from a cooler rung of the neutral scale.
The judgment was human. Once the source of that judgment was identified, the result became arithmetic.
The clearest example involved a border in the composite that looked too thick. I reported it as a thickness problem.
It was not a thickness problem, and the token itself was not wrong.
The metric strip painted its internal seams by exposing the border token through gaps in its background. The outer border then drew the same translucent ink over that background a second time. At the edge, the two layers combined into nearly twice the intended visual weight.
The defect had also been present in dark mode, but the alpha was low enough that no one had noticed it.
My taste report was still a bug report. It had simply used the wrong noun.
That distinction matters. A person can identify that something is wrong without correctly identifying the mechanism. The system’s job is not to dismiss the judgment because its vocabulary is imprecise. Its job is to locate the rule, token, or rendering behavior that produced the reaction.
The overnight test
Near the end of the work, I went to sleep and gave the agent the remainder of the plan with one instruction: make the decisions, and I would review them when I returned.
Whether that was reckless depended on what the repository could refuse.
Overnight, the agent implemented a view-options block, a filter builder, a shared keycap treatment, collapsible navigation, nested destinations, motion tiers, and a redesigned overview page.
The important result was not the amount of output. It was the record of the system rejecting its own author.
The spacing-rhythm gate refused a raw spacing value. The motion contract rejected a transition declared outside the motion layer. A component contract rejected an ambiguous option. One test the agent wrote to falsify its own implementation was itself caught proving nothing, so it was replaced with a test that performed the interaction and clicked the control.
Every guard in the repository has been broken deliberately at least once. A rule that has never been observed failing may still be decoration.
In the morning, I reviewed the renders, worked through a short punch list, approved the result, and authorized the commit.
The full gate stopped it.
The public token boundary is watched by three independent witnesses:
- A token count.
- A frozen fixture.
- A pin inside the packed-package consumer check.
Across two governed changes, the public boundary had legitimately grown from 352 to 357 tokens. The agent had updated two of the three witnesses each time. The third still contained the old value.
Nothing was wrong with the new tokens. The problem was that the public boundary had moved without every witness recording the change.
That is exactly the condition the architecture is designed to refuse.
The count has since moved. Six witnesses watch that boundary now, not three: the registry constant, the frozen fixture, a count assertion inside the packed consumer check, that check's schema bounds, a mode-varying count, and a count of resolved color triples.
The repository had been counting four. The last time the boundary moved, five were updated correctly and the sixth was caught by the check that runs outside the repository, against the packed tarball, where the system cannot consult its own source.
The lesson is not that a witness was missed. It is that the number of witnesses was itself wrong, and the thing that found the error was the one gate with no access to the repository's assumptions about itself.
The same distinction applies beyond this design system. Advisory rules scale with human attention. Structural rules continue to operate without it.
I did not set out to turn Form Logic into a demonstration of that claim. It became one through a sequence of defects that were caught before they became accepted behavior.
That claim outgrew the repository it was made in. The engine underneath these gates came out on August 22, and Strict Mode is its own product now with its own study. What it costs to make a rule mandatory across five codebases belongs there. This one stays with the earlier question, which is how much of a ruling can become a rule at all.
Breaking a test is not the same as proving it works
No guard in this repository is trusted until it has been watched failing. Break the rule, see the assertion fail, restore it, see it pass.
Twice in one release, the break did not land. An edit written to violate a rule was conditioned on a pattern that did not match, so the file was never modified. The suite ran and reported green. Green is also what a working guard reports.
A falsification that does not falsify is worse than none, because it converts an unchecked assumption into a checked one without checking anything.
The second version of this failure is harder to see, and I have now made it twice. A guard can break correctly and still sit where the condition it tests cannot occur.
One guard asserted that a disclosure control was absent at desktop width. It asserted that at a point where the navigation rail had already collapsed, so the control was absent for a reason unrelated to the rule. It passed against a build with the defect deliberately restored.
It happened again this week, on a guard written for a defect a consumer had just reported. The test clicked a button and asserted the effect went dark afterward. It passed against the broken build, because clicking with a mouse does not put a browser into the focus state the guard existed to catch. Only the keyboard does.
So the standard has to be stricter than watching a test fail. The falsification has to reach the condition. A guard placed where the condition cannot occur tests nothing, and it reads exactly like one that does.
Documentation is not enforcement
The most expensive defect in this system was not a token, a component, or a test. It was a rule that was written down and never ran.
The governance layer shipped as one of the five packages. For more than thirty release candidates, the guide inside the distribution told the consuming product to install that package and wire it into the same gate as its typecheck and lint. The drop it actually received contained the runtime packages only. The instruction was correct. The code that would have executed it was not in the box.
Nothing detected this. Not a gate, not a test, not a release check. It surfaced because the engineer building on the system asked why the same drift kept returning across releases, and the honest answer was that nothing had ever refused it. The cost was rounds of redesign, spent correcting drift a check would have rejected on the way in.
Documented is worse than absent. Absent is visible. Documented reads as covered.
A smaller version of the same failure taught it at a legible scale. The guide told that consumer to install using a specific package manager. Their project is a workspace that manager does not read, so it installed the root only, set the framework aside, wrote a stray lockfile, and reported success. The failure surfaced days later as components behaving like the previous release.
I fixed the instance. They found a second. A third was sitting in a section neither pass had looked at. The guide now names no package manager anywhere, and a check fails the build if one appears.
Correcting instances of a wrong default is not the same as changing the default.
Where the human remains
The ledger can enforce contrast bands. It cannot choose the cooler gray.
It can verify that a meter conforms to its component contract. It cannot decide that the threshold ticks I specified no longer look right once they are rendered.
It does not feel anything when I remove them.
The system’s contribution is to make that reversal cheap and safe. It can record the scope of the decision without automatically promoting one local preference into a universal law.
A ruling made while looking at one screen governs that context. It becomes a broader rule only when the evidence supports one.
Those are questions of preference, and preference is the easy case for this argument. The harder case arrived this week, and it is not a matter of taste at all.
A decorative effect on the system's cards and buttons leaves its light behind after the pointer moves away, roughly one time in three. I can see it in a second. Three fixes have shipped for it. Each named a plausible mechanism, and each was wrong.
It has resisted about 120 scripted reproductions across three different ways of leaving the element, measured first by reading the computed style and then, when that proved too coarse to see the effect at all, by comparing rendered pixels against a resting capture. Not one attempt reproduced it. The working hypothesis is that it is not a style at all but a frame the graphics layer is holding after the style has already changed, which no automated check can observe, because automation re-renders the page in order to look at it.
That defect is open as I write this, and it belongs here for that reason. The compiled layer has not merely failed to decide the question. It may be structurally unable to see it.
So the seat in front of the render is not only where preference lives. It is sometimes the only working instrument in the building.
That is the division of responsibility I want.
I keep the seat in front of the render. I decide whether the result is right.
The system keeps the durable part of that decision: what was accepted, under which conditions, and what must fail when those conditions change.
It enforces that record against the agent, but also against me.
The purpose is not to remove taste from the process. It is to stop depending on memory and attention to reproduce it.
