Shopify product ID in. Finished 9:16 Meta Story ad out.
Two models touch each ad: one paints the gradient, one drafts the headline and then reads the result back. Everything between them is measured or ruled. Type size is fixed. Line fit is measured in the real font. The claim has to be quoted from the product page. The wordmark colour comes from sampled brightness. If a product sits too high for the rules to hold, nothing gets squeezed; the ad goes back.
Generative tools make the imagery. A deterministic renderer sets the type and the mark.




Blue marks the steps where a model decides. The other steps are a rule or a person. Three of the line's steps are blue.
The review pass is a model, so it is blue, and its verdict is still subject to the three-attempt limit. Segmentation is a model, drawn as a rule: it returns a box and a rule reads it.

Each rendered ad carries a JSON spec. Nothing on the image is unexplained. These values are copied from specs/poc_7968200130623.json and the run manifest.

"500mg nitrate / in a 60ml shot." The model may only claim what it can quote. The quote has to appear verbatim on thefeed.com.
One size for every ad in the batch. Copy has to fit it; nothing auto-shrinks. The 9:16 headline is 10.2% of the short edge, which reads at about 40px on a phone.
The vendor name goes on only when the label is too small to read on a phone and there is room above the product. Here the product is 39.3% of the frame height.
The same background-removal model already cached on the Mac finds the product. The type block ends at y560; the product starts at y714; the rule needs 60.
The pixels under the wordmark are averaged. Below 128 the mark is white, above it navy. No lime, by my call on 22 Oct.
Two sources, labelled. The first set is a proof of concept from 22 Oct where an assistant wrote the headlines and layout by hand. Those renders are superseded. The second set is what the finished process caught on its own during the real run, straight from copy_log.jsonl.

It is a sachet. "bottle" is now only allowed when it matches the form in describers.csv.

Flagged in review. The lint regex now lists the phrase by name.

A category claim with nothing to quote. The real run wrote "Real-time heart rate tracking" from the product page.

The shorter line must be at least 55% the width of the longer, measured in Futura.

Same rule. Also the headline was set at a different size from its neighbours.

Type on the pouch. Position now comes from u2net, with 60px of air required.

Same failure. The edge heuristic missed low-contrast packs; segmentation does not.

Type over the product. The real run refused this one entirely; see below.


Attempt 1 was quoted correctly from the product page and still failed. The reviewer flagged a second reading. Attempt 2 passed.

Two pixels over the line limit, as the log recorded it. The rule does not round.

Same width, same rule. The rewrite moved from a benefit claim to a spec claim with a quote behind it. All three rejections are in the log at the end of the page.

Not rendered. Routed back.
Carbs Fuel Original Mini. Segmentation put the product top at y426. At 110px, not even one headline line fits above it with 60px of air. The gradient pipeline's own placement rule says the product top stays below 25% of the frame, y480, so this is the gradient's error, and the fix belongs there.
The rule is that products that sit too high are not squeezed. The product went to copy_needs_review.json with a note to regenerate the gradient lower. 19 of 20 rendered.
Manifest order. Every headline below was written by the process, from a quote, and checked the same way. Type size is identical on all nineteen.



















About $0.15 per gradient image, plus a few cents of copy per product. Copy ran one attempt for 16 products and two for 3. Carbs Fuel never reached the copy step.
gemini-3.6-flash because Pro was not available on the key.Fixes for all three are specced in the prompt and lint rules and have not yet been run. The manifest records model, prompt version and attempts for every ad, so the next run can be compared to this one line by line.
top20.txt is the first 20 top-100 SKUs with a QA-passed gradient, in manifest order.Carbs Fuel 7265399603263 never reached the copy step; it is in copy_needs_review.json.
