CI resolves playwright but has no downloaded chromium; launch threw instead of falling back to the catalog ranking, and every spec gate downstream failed. Launch failures now return the no-browser path (and the browser test skips instead of asserting).
AI-assisted (Claude Code).
Paul's decision on the tenth sweep's design question: hard vetoes (missing region, contradicted plate or text, SVG illustration, clipped plate, invented ink) stay unconditional; at overall >= HERO_MIN the numeric readings (ink colour, letter-spacing, line pitch, strip heights, box positions) print as advisories with the pass and belong to the polish pass. Every sweep-10 sample closes its hero under this condition, which settles 07 without another paid round.
Ninth-sweep defects: codeDrawn / container / bleed now persist into spec.json with WARN lines (an overridden refusal used to vanish from the record); font-match probes os.tmpdir() and points TMPDIR at .impeccable/tmp when the sandbox /tmp is unwritable (every ninth-sweep rank silently fell back to the catalog).
AI-assisted (Claude Code).
A sol build named its two carburetor drawings 'countable ... geometry' chrome regions, drew them in inline SVG, and the SVG ban never ran because state.artifact was null.
AI-assisted (Claude Code).
A reference, not the page: --r-<id>-x/y/w/h in % of the comp (plus cap height, font-size, family, weight where measured) to bind to any markup, and hero-reference.html with every region at its box and every plate placed with object-fit: contain, as a check on positions. Attacks the most common execution failure of weaker builders (badly positioned, overflowing, pushed below the fold) without dictating structure to strong ones; overlapping boxes are overlapping boxes and the gate reads pixels regardless.
AI-assisted (Claude Code).
From the human review's most repeated pin ('terrible svg instead of asset', on every model) and from sessions that wrote 'ship' with the hero open. Icons, arrows, chevrons, and runtime data charts stay code; diagrams, notation, and leader lines are plates.
AI-assisted (Claude Code).
From the final review batch: 'bad asset crop (crops are never allowed)' twice, 'letter spacing way too wide'. A crop resampled to the region scores 99.8% structure against the raw region; a produced plate scores 30-60.
AI-assisted (Claude Code).
A build reached hero 81% and stalled on eight staff rows read one at a time (and both ways on ink colour). The session asked the user and was told to build as written; the force was legitimate and recorded.
AI-assisted (Claude Code).
A session's own note said its hero sat at 67 because the 10x10 grid boxes straddled two elements each, and it was right: every downstream measurement (cap height, line count, structure) inherited the slop. Text and control regions now snap to the dominant connected ink inside the span (page-ground threshold, dilated cells, masses touching the span's sides lose to inside masses), keep the span on the record for coverage, and can opt out with snap: false.
AI-assisted (Claude Code).
The shifted copy's padding read as a white 'letterbox' on the build in every human review. A vertical spine came back white on red where the comp had black in five builds; its ink colour is now compared even though its type cannot be measured.
AI-assisted (Claude Code).
From the second review batch: the best build of the fifth sweep passed the hero at 87% with the cover arch cut flat on the left (object-fit: cover on a box narrower than the shape), and legends, badges, and extra controls one or two cells wide slipped under the invented-ink floor. comp-spec measures the artwork's contiguous contact with each box edge against the page ground; the spec gate refuses such a box unless bleed is set. Human pass line landed at comp-diff 72-73; HERO_MIN stays 0.72.
AI-assisted (Claude Code).
From the first human review of sweep-3 builds (pins on 12 samples): fonts at the wrong size, weight, colour, or place; nav bars too tall; kickers and dividers the comp does not have; a footer strip pushed off the frame that read as drift on ground colour alone; a drawing filed as chrome with no note to catch it.
- lib/hero-checks.mjs: textRegionCheck (cap height, line count, ink density, ink colour, first-line offset vs the comp crop, measured fresh), chromeStripCheck (first rule row), inventedInk (build energy over a calm comp cell and neighbourhood). Wired into gateHero as reasons; invented ink vetoes at 4% of cells.
- comp-diff verdictFor: detailRaw < 0.15 is missing whatever the palette.
- comp-spec: every region carries a note.
- font-fingerprint: the tall-line filter takes its median over lines with real mass, so two display lines above a small line are not 'tall'.
AI-assisted (Claude Code).
A session named seven regions for a page with three plates, a table, a note, callouts and a spine, so the hero gate could name nothing and the score sat at 70. A code region is one element; a column is a container of several.
AI-assisted (Claude Code).
Staff rules and a black page edge fused eight track rows into one 389px 'line'. A session forced two gates by quoting a brief line ('should feel like an extension of her artwork') as permission; a force now needs the user's words reported or quoted, a downgrade verb, and the comp noun in one reason.
AI-assisted (Claude Code).
A comp region drawn on the 10x10 grid over-covers: a body-copy crop carries the last headline line above it and a drawing beside it, and one session measured 'thread-body' at cap 160px off a carburetor drawing and ranked Londrina Shadow for it. Tall non-text 'lines' leave the mass reference; lines cluster by cap height and the cluster holding the most ink (multi-line first) is measured, re-applied after upsampling.
The plates NEXT line now names generate-image.mjs --plate as the tool (harness image tool only as fallback) after a session spent 25 turns keying plates with magick.
AI-assisted (Claude Code).
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).
lib/font-fingerprint.mjs replaces the three-number fingerprint with
size-invariant shape features (x-height ratio, stroke contrast, stem width,
run-length quantiles, roundness, serif signal, width spread) and a
noise-normalized distance; family recall on a held-out self-test rose from
13% to 72% top-5. data/font-index.json carries the whole Google Fonts
catalog (3,092 faces at two cap sizes, 707 KB); font-match --rank fingerprints
the comp crop, takes the 25 nearest faces from the index (plus the model's
own names), renders them at the comp's cap height, ranks by the same
distance, and prints a proof sheet and the CSS to use. scripts/build-font-
index.mjs rebuilds the index at release time.
AI-assisted (Claude).
Co-Authored-By: Claude <noreply@anthropic.com>
The first paid confirmation sweep showed the failure: models rendered the
three comps first and ran build-phase.mjs start after, so a session cut at
the composition pick carried no state.json and the resumed model followed
the conversation ('translate the comp into HTML now') instead of the
phases. Decision comps (.impeccable/mocks/decision/) are unaffected;
--force-mock overrides.
AI-assisted (Claude).
Co-Authored-By: Claude <noreply@anthropic.com>
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>
The paintedRect clamp landed in 9d2b0556 without a fixture, so nothing
stopped the false positive coming back. This adds the shape that produced
it: a scroll region with an opaque bar directly beneath.
Text scrolled past the panel's bottom edge still reports its full
unclipped rect, and that rect lands on the bar. The probe then samples
coordinates the text is not painted at, finds the bar, and reports the
text as buried under it. Any sticky footer or toolbar under a scroller
has this shape.
Verified red then green: with the clamp reverted to main's version the
fixture reports a fourth finding and the assertion fails; with it in
place the count holds at three.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5 (1M context) <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>