font-match / catalog index
- Index schema 2 adds a third render, 48c (48px cap, ALL CAPS text). Caps headline crops have no x-height band and ranked against mixed-case renders as barcode faces; they now route to the caps render.
- Non-text families (barcodes, redacted, flow, dingbats, effect faces) are excluded from candidates.
- The distance adds a gross width and weight gap (log ratio of advance and ink density) so a face 50% wider or 35% lighter cannot rank first on run-length detail alone; the index stores those readings.
- Multi-line all-caps crops vote on x-height across lines: one line's crossbars no longer give the crop a spurious x band.
- With no browser, --rank records the catalog's nearest face (source catalog, size estimated) so the spec gate can close; the NEXT line and new-work.md say not to install a browser or hand-write a choice.
- font-match stamps the choice it writes; the spec gate refuses a chosen face it did not write (sessions typed Arial Narrow into spec.json to pass).
- IMPECCABLE_NODE_MODULES lets a harness lend a playwright.
comp-spec
- A region note that describes painted material (diagram, drawing, photo, texture...) under a code kind is refused at the spec unless codeDrawn is set: the exploded carburetor filed as chrome is a plate about to be redrawn in SVG.
build-phase
- The control ink-box veto applies only when the comp's ink is a discrete element and the build's box is too; a full-width bar told one session six times that 1376x87 was 1382x102 with no edit able to move it.
AI-assisted (Claude Code).
comp-spec, comp-diff, build-phase, font-match, and generate-image now decode any comp raster via loadRaster(), converting non-PNG input to <file>.png next to the source. Sessions used to hit 'not a PNG' and rewrite the .webp in place with PNG bytes, which broke transcript replay (a later step rewrites the comp beyond the cut) and left a mislabeled file.
AI-assisted (Claude Code).
The first paid confirmation run hit a TypeError in the ink-box check
(report regions carry normalized w/h at the top level, not under box);
runGate now catches a throwing gate and returns a one-line refusal with
an explicit force path so the run is not lost to a tool bug.
AI-assisted (Claude).
Co-Authored-By: Claude <noreply@anthropic.com>
font-match.mjs fingerprints a text region's lettering in the comp (cap
height, glyph advance per cap = width class, ink fraction = weight class,
tracking), renders candidate faces at that cap height in a headless
browser (yours plus a shortlist for the width class), and ranks them by
distance with a proof sheet; the spec gate refuses to close until the lead
text region is measured and ranked. generate-image --plate keys ink-on-
ground plates to alpha (chroma) so the drawing sits on the page's own
ground; the plates gate scores keyed plates composited over the region's
ground. comp-diff reports each region's ink box; the hero gate names a
control whose box height or width differs from the comp. The hero
instruction copies the comp's words verbatim; rewording is a stated
decision after the hero passes.
Driven by a human review of the r3 side-by-sides: face width and weight,
plate ground, control row height, and content substitution.
AI-assisted (Claude).
Co-Authored-By: Claude <noreply@anthropic.com>
plateVerdict() is shared by the plates gate and generate-image's PLATE-WARN
so they cannot disagree; --plate picks a frame that clears the 1.5x width
floor (a square region wider than 682px takes the 1536 landscape frame);
'missing' on text/chrome/control regions requires the build region to be
near-empty, so a 12px rule a few pixels off reads as contradicted or drift,
not missing; the responsive gate does not re-litigate a plate that passed
the hero; record hero after close does not inflate the attempt count.
AI-assisted (Claude).
Co-Authored-By: Claude <noreply@anthropic.com>
Round-1 simulated builds passed the hero at 1536 and shipped a page whose
first viewport collapsed to one column at 1440 (comp-diff 50% on the
final capture, 82% on the hero). The responsive phase now requires
desktop.png and mobile.png and diffs desktop.png against the comp at 65%
with no region missing.
AI-assisted (Claude).
Co-Authored-By: Claude <noreply@anthropic.com>
Three simulated builds under the previous gate reached 78-83% overall with
the exploded plate placed and the table right, then spent 12-20 attempts
chasing 'contradicted' verdicts on a headline set in a substitute face and
on 50px chrome strips whose detail was paper grain. Text with structure
above the floor and its palette intact is drift; chrome and controls with
structure and palette held are drift. The adversarial set (swapped
columns, mirror, sepia, noise plate, tile shuffle) still fails.
isMain uses realpath on both sides so a skill mounted through a symlink
(Cursor, worktrees, staged evals) still runs its CLIs.
AI-assisted (Claude).
Co-Authored-By: Claude <noreply@anthropic.com>
From a forensics pass over twelve runs and two adversarial passes over
the metrics:
- comp-diff: detail is signed and penalizes invented energy; regions with
structure under 0.3 (or painted regions under 0.45 / added detail over
0.4) are contradicted whatever the mean says; palette ramp tightened;
region crops inherit the whole-image best translation so a shifted page
is not eight contradicted regions.
- hero gate: fails on any contradicted plate/image/text region (chrome and
controls keep the one-third allowance), on a capture that is not the
comp's frame, on a palette that is not the comp's, and on an organic
clip-path drawn inside a raster region's box.
- plates gate: scored against the comp crop with overlapping text/chrome
painted out (comp-spec plateReference; generate-image uses it too), with
a structure floor and an added-detail veto; the real plate passes, noise,
mirrors, mosaics, and other regions do not.
- comp-spec refuses a regions file that leaves comp ink unnamed.
- The direction-choice ping is folded into build-phase.mjs start
--direction --kind; the roll writes .impeccable/build/pending.json and
context.mjs / detect.mjs report COMP_ROUND_OPEN until the hero gate
passes. A code-led config makes start print the contract step and stop.
AI-assisted (Claude).
Co-Authored-By: Claude <noreply@anthropic.com>
concept-seed's choice ping now prints the next mandatory step from the
recorded build path (comp-led: build-phase.mjs start --direction <key>),
because every run that skipped the comp round did so right after that
ping. build-phase gains a comps phase ahead of spec (three sidecar'd comps
under .impeccable/mocks/, one approved) and records the approved comp on
close. The hero gate lists the worst region crops first with the fix class
per verdict, and refuses a third value-only attempt on the same stuck
region. Hero instruction is plates first, then the semantic layer. The
finish reviewer treats a comp-led build with no closed comps phase as a
material finding.
AI-assisted (Claude).
Co-Authored-By: Claude <noreply@anthropic.com>
The first live run produced a faithful carburetor plate, then drew the
region in SVG and left the plate on disk. Before diffing, the hero gate
now walks the artifact (or a bounded source tree) for every plate's file
name or a data URI named for it.
AI-assisted (Claude).
Co-Authored-By: Claude <noreply@anthropic.com>
The first live run forced past the plates gate with 'single-file HTML
delivery requires embedded CSS/SVG'. That is not a reason the comp's
authority moves for; the script now refuses a --force whose reason does
not quote the user, and new-work.md says a single-file deliverable inlines
the plate as a data URI. Texture plates are judged on palette and grain,
not size or structure, since they tile.
AI-assisted (Claude).
Co-Authored-By: Claude <noreply@anthropic.com>
generate-image.mjs --plate produces one raster region of the measured spec
from the comp crop, scores it against the crop, and refuses under --min.
The asset producer's job becomes producing the spec's plates. Detector
gains organic-clip-path (many-vertex polygon / curved path() clips) and
buried-raster (raster under a near-opaque wash or at near-zero opacity),
wired into both engines with fixtures.
AI-assisted (Claude).
Co-Authored-By: Claude <noreply@anthropic.com>
Dependency-free PNG codec, perceptual metrics (structure / color / detail /
bands), side-by-side + heatmap + per-region crops, a measured spec from the
approved comp (grid overlay, sampled palette, plate list), and a phase state
machine whose spec / plates / hero gates run the diff instead of asking the
model to remember the image.
AI-assisted (Claude).
Co-Authored-By: Claude <noreply@anthropic.com>