I have written four posts about AI assistants reporting work as finished when it was not. This is the other half of that story. The same tools produce excellent output when the person directing them knows where to intervene, and the interventions that matter are almost never about syntax. They are about shape.

Two recent ones are worth writing down, because both saved a real afternoon and both came from the same instinct.

One: stop measuring, start solving

A full-width band on my site was rendering with a strip of background showing along one edge. The assistant went to work and produced a measurement table: ten viewport widths, hit tests, parent-chain walks, an x-offset recorded for each. It was thorough. It was also aimed at the wrong question.

I stopped it and asked for the arithmetic instead. Two properties were setting the horizontal position:

margin-left: 50%;              /* resolves against the PARENT width */
transform: translateX(-50%);  /* resolves against the ELEMENT's own width */

Different reference boxes. The net offset is a formula, not a mystery:

offset = (0.5 × parentWidth) − (0.5 × viewportWidth)

Zero only when the parent equals the viewport. Every failing row in that measurement table was a width where an ancestor capped the parent, and every passing row was one where it did not. The table was not evidence of a bug. It was a plot of the formula.

This is the pattern worth naming. An assistant asked to investigate will investigate, and it will keep producing plausible next measurements for as long as you let it. Asking for the closed form instead of another data point ends the search in one step. If a layout problem can be written as an equation, write it, because the equation tells you which variable to remove.

Two: a function, not a filing cabinet

I wanted text highlights that deepen slightly on hover, the way a marker looks when you go over it twice. The proposal that came back was a set of CSS variables per colour: a base for each highlight tone and a paired hover value sitting beside it, ready to be swapped in.

That works. It also means every new colour is two declarations, the pair can drift, and nothing stops someone adding a base without its partner. It is a filing cabinet where a function belongs.

The colour and its opacity are separate values. Store the channels and the alpha apart, and hover is arithmetic on one number:

:root {
  --mark-rgb: 74 201 126;
  --mark-alpha: 0.22;
  --mark-alpha-hover: 0.34;
}

.mark {
  background-color: rgb(var(--mark-rgb) / var(--mark-alpha));
  transition: background-color 260ms cubic-bezier(0.4, 0, 0.2, 1);
}

.mark:hover {
  background-color: rgb(var(--mark-rgb) / var(--mark-alpha-hover));
}

Now any colour gets its hover state for free. Pass a new triplet inline, per instance, from a prop, and the feedback follows without a second declaration existing anywhere. One value changes; the relationship is computed. There is no pair to keep in sync because there is no pair.

The same reasoning killed a related suggestion: a component that hardcoded its font sizes at each call site. Three headings that were supposed to match had drifted into three different sizes, because each one had been written separately and nothing tied them together. One shared component with a named scale fixed it permanently. A copy-paste never stays identical for long.

What the two have in common

Both corrections replaced enumeration with a rule. The measurement sweep enumerated widths when one formula covered all of them. The colour variables enumerated states when one subtraction covered all of them.

Enumeration is what a language model produces naturally, because it is trained on examples and examples are enumerable. Compression is the part you supply. That is not a criticism of the tool, it is a description of the division of labour, and knowing which side of it you are on is most of what makes the collaboration fast.

When the output is a list, ask what the list is a list of. Sometimes the answer is one line.