`design/marketing`'s `.png` re-export is a process this repository documents and cannot perform — every design card here has borrowed a sibling repository's chromium
Split out of MOTIR-4001 when validate_work_item returned likely-over-gate-sizing on the pair (5 points / 90 minutes). The two share ONE devDependency and nothing else; this is the half that is not a guard.
The claim the area note makes, and cannot keep
design/marketing/design-notes.md says it twice, once per asset:
"
landing.png(full-page Playwright chromium export, light theme,deviceScaleFactor: 2)" "design-showcase.png(full-page Playwright chromium export,deviceScaleFactor: 2)"
package.json carries no playwright and no @playwright/test. So the export is performed by
whatever browser the running agent can find — in practice motir-core's installed chromium, reached
by an absolute path into a sibling worktree's node_modules/.pnpm. Both re-exports on
MOTIR-3985 were taken that way, and so was its element scan.
Three things follow, and the third is the one that costs. The viewport is re-derived by hand
every time (1440 for design-showcase, 1320 for landing — recoverable only by reading the
committed PNG's width and halving it); the render options are re-typed from prose; and nothing
reports whether the committed export was even REPRODUCIBLE before the diff, so a height change caused
by a renderer upgrade is indistinguishable from one caused by the edit.
What motir-core already solved
scripts/render-design-mock.mjs (shipped with MOTIR-3054) searches
the viewport width out of the committed PNG — a full-page screenshot is as wide as the DOCUMENT, so an
overflowing mock's viewport is NARROWER than its export — renders the asset AS IT STANDS AT HEAD
first, and reports a per-file verdict:
| verdict | meaning |
|---|---|
EXACT | the baseline render is byte-identical, so the new PNG differs by exactly this diff |
DIMS | same dimensions, different bytes — a renderer-build difference with no reflow |
DRIFT | different height: the committed export predates an environment change |
Measured here on 2026-08-30, by hand, on MOTIR-3985's branch:
design-showcase.png is EXACT (2880×7916, sha f346f7f9… for both the committed file and the
HEAD re-render) and landing.png is DIMS (2640×14762 both ways, 50bbd100… re-rendered
against 7378ea4b… committed). That DIMS is the kind of thing a committed tool states in one line
and an ad-hoc render leaves for the reviewer to wonder about.
Acceptance criteria
- A committed script re-exports any
design/**/*.mock.htmlto its same-basename.png, taking the viewport from the committed export rather than from a remembered number, atdeviceScaleFactor: 2, full-page. - It renders the asset at
HEADfirst and prints theEXACT/DIMS/DRIFTverdict per file, so the diff a reviewer sees is attributable. - It reproduces the two figures above on an unmodified tree:
design-showcaseEXACT,landingDIMS. A run that reportsEXACTfor both is measuring something other than what this card measured, and is a signal to look rather than to update the numbers. design-notes.md's two "asset files" lines name the script, so the documented process is the one that exists.pnpm lint,format:check,typecheck,build,test.
Boundary
Not the guard lane — MOTIR-4001 owns the contrast scan, the
vitest.design.config.ts and the ci.yml job, and it is where the playwright devDependency this
script consumes is added. Not a CI job — this is a tool a design card runs, not a check; nothing
here touches deploy's needs. No asset content changes — a re-export from an unmodified mock
is expected to reproduce the verdicts above, not to alter a pixel.
Advisory dispositions
blocker— MOTIR-4001 attodo— INTENDED. The script needs theplaywrightdevDependency that card adds; building it first would mean adding the dependency twice or in the wrong card. Wired at the split.reference· advisory — names MOTIR-3985 atin_progress— NO EDGE IS OWED. That card is cited as the PROVENANCE of theEXACT/DIMSfigures above, not as substrate this card reads. The figures are re-derivable fromorigin/mainby anyone with a browser — they are a property of the committed PNGs and the renderer, not of that card's diff — so the acceptance criterion asks the script to reproduce them on an unmodified tree rather than to consume anything that card produces. (The one thing that WOULD create an edge is if this card also updateddesign-notes.md's asset-files lines while that card is rewriting the same file; it does, so whoever runs this after the sweep merges should re-read those two lines rather than the ones quoted above.)