feat(stardust): 0.26.0 — published-origin gate hardened with element-level criteria (#125) - #397
Conversation
…level criteria (#125) A 96-page rollout passed /offers/offers at 6.7 % pixel while all 284 coupon cards were clipped and their "View details" links pushed under the Clip button: pixel PASS meant "right shapes", not "every element present and legible". New replica/scripts/gate-all.mjs runs every deployed page through stitched captures + pixel-compare AND two symmetric DOM probes, verdict = pixel ≤ 10 % AND |Δh| ≤ 5 % AND clipped = 0 AND MISSING+HIDDEN links/headings = 0 (+ required repeated units within 4 px); the pixel-only verdict is kept beside it as calibration data. New diff probes: clip-probe (D1), content-presence (D2, content-diff --published hands over), unit-geometry + measure-live (D3); pixel-compare --text-boxes / --pad auxiliary (D4); sbs-crop folds the crop helpers. Upstreamed walgreens feedback A1 (window-free real Chrome by default), A2 (Akamai 400 as challenge), A3 (devDependencies, never --no-save), B1, B7, and the DA 200-image cap via the admin x-error header. Docs: gate doc § all-pages gate, replica Phase 5, deploy Step 10, rollout Phase E, diff SKILL, scripts index. Tests for the four instruments. Calibration on the walgreens roster: 66 pixel-only PASS → 28 full PASS. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…alve the prose, configurable word lists Site name and URL removed everywhere; the recorded coupon-page example is told once in the gate doc and referenced by finding number elsewhere. SKILL and reference prose cut from 177 to 125 lines, the CHANGELOG entry from 91 to 51, script doc headers to usage plus a short why. The two English heuristics are flags (clip-probe --more-words, content-presence --count-words / --more-words). Fixes a real bug: the "read more" regex lived inside the injected template literal, so \b and \s were consumed by the string; the collapsible check also scanned the whole parent scope and read every box collapsible on a page with one toggle — now the box, its siblings, or a ≤ 3-child wrapper. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Tessl Plugin Lint
|
…gate.sh --full round
Rule: every crafted prototype and every deployed page is a row in a pixel
table — gate-all --stage prototype writes gates/prototypes-<w>/summary.*
(build = the served prototype, origin = the archetype round's cached
live.png), the default stage writes gates/all-<w>/. gate-evidence.mjs reads
the tables as the source of record (--tables): with a table for the width
the row decides pixel-gate-<w> and a page without a row is OPEN: no table
row; without any table the log rule stands and --check names the gap. The
eval requires the prototype table; rollout Phase H reports both totals.
gate.sh --full now runs clip-probe on the build side in every regime,
content-presence live vs build in the published regime (GATE_REGIME
overrides the URL heuristic) and unit-geometry when
stardust/replica/units.json declares a repeated-unit family for the slug
({ family: { origin, build, n, required, pages[], templates[] } }, also read
by gate-all); a clipped count, a MISSING/HIDDEN link or heading or a
required unit off fails the round, and outranks a pixel PASS in
gate-evidence the way the overflow assert does.
Compensation: pixel-compare --pad (the rejected union metric) is removed.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Read against the shape of our recorded hands-off runs (36- and 64-page rosters, delivery fanned out to one subagent per template cluster). The four criteria are the right bar — hidden links and clipped chrome are exactly what those runs shipped while the pixel gate said PASS — and window-free real Chrome fixes a real problem: the old headed tier needed a display, which a container never has. Six notes, none blocking; happy to follow up in a PR if you would rather keep this one focused.
Not yet exercised in a run on our side — these are reading notes; the first run on 0.26.0 will be calibration for the tolerances you list as open. 🤖 Generated with Claude Code |
… evidence The probes elect real Chrome (window-free) and fall back to bundled Chromium when it is not installed; every probe records the tier it actually ran (chrome | chromium-fallback | chromium) in its JSON, gate-all's summary.md gains a `browser` column and its calibration line counts degraded pages, so a run that lost its origin measurements on a bot-managed site is visible in the artifact (review note 5). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… a recorded unit; probe deps before install Review notes 1–4 on the PR. update-coverage.mjs --gate <summary.json> writes each pixel-table row into delivery.gate and flips a failing page (no documented override) to failed; verify.mjs never marks a page verified while delivery.gate.pass is false, so completion derives from one place. Handoff contract § 3: each cluster subagent runs gate-all --only over its own pages inside the fan-out; C-final's roster run is the recorded unit `gate-all` (--skip-existing over the clusters' captures, resumable at its boundary) followed by --gate. Replica Setup probes the probe deps before installing them as devDependencies. Compensation: sbs-crop.mjs removed (any image tool crops), measure-live is a library (no CLI; measure.mjs measures selectors), content-diff --published handoff removed (the docs name content-presence) — net −96 code lines in this increment. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Thanks Karl — 1 to 5 are in ( |
Why
A 96-page rollout gated every deployed page on stitched 1440 captures and pixel-compare. Its coupon-listing page PASSED at 6.7 % / Δh 69 px while all 284 cards were visibly broken: a fixed-height card with
overflow: hidden, the body ~30 px too low, the description clipped mid-glyph, the details link pushed under the primary button, the sort control on another default. The links were in the served DOM — pure CSS geometry, which pixelmatch underweights (16.5 % over the text boxes alone). "PASS" meant "right shapes at the right places", not "every element present and legible". Element presence and legibility are checkable, so the gate now checks them — and the same run showed that only 5 of 96 pages had ever been in a pixel table at all.What
The rule. Every crafted prototype and every deployed page is a row in a pixel table:
gate-all.mjs --stage prototypewritesstardust/replica/gates/prototypes-<w>/summary.{json,md}at the end of Phase 4 (build = the served prototype, origin = the archetype round's cachedlive.png), the default stage writesgates/all-<w>/.gate-evidence.mjsreads the tables as the source of record: with a table for a width the row decidespixel-gate-<w>, a page without a row isOPEN: no table row; without any table thegate.shlogs stand in and--checknames the gap. The eval requires the prototype table.Coverage carries the verdict.
update-coverage.mjs --gate <summary.json>writes each row intodelivery.gateand flips a failing page (no documented override) tofailed;verify.mjsnever marks a pageverifiedwhiledelivery.gate.passis false. Completion derives from one place. Rollout Phase H reports both table totals.Four criteria per row: pixel % ≤ 10 AND |Δh| ≤ 5 % of origin height AND clipped = 0 (+ documented allowance) AND content MISSING + HIDDEN links / headings = 0, plus required repeated units within 4 px. The pixel-only verdict is kept beside the full one as calibration data.
Where the probes run:
gate.sh --full, prototype regimeunits.jsondeclares a familygate.sh --full, published regime (pub<N>)gate-all --stage prototypegate-all(deployed, default)Element lines fail a
--fullround and outrank a pixel PASS ingate-evidencethe way the overflow assert does. In C-deliver each cluster subagent runsgate-all --onlyover its own pages inside the fan-out; C-final's roster run is the recorded unitgate-all(--skip-existingover the clusters' captures, resumable at its boundary) followed by--gate(handoff contract § 3, row C).Browser tier: best available, registered. The probes elect real Chrome (window-free) and fall back to bundled Chromium when it is not installed; every probe records the tier it ran,
summary.mdhas abrowsercolumn and the calibration line counts degraded pages. Sites without bot management measure identically on both tiers; on the recorded Akamai site, Chromium got HTTP 400 on every origin page and Chrome 200 on 59 of 96.New scripts:
replica/gate-all.mjs(the tables);diff/clip-probe.mjs(D1),diff/content-presence.mjs(D2),diff/unit-geometry.mjs(D3,--families stardust/replica/units.json --slug <s>),diff/measure-live.mjs(library: the shared settle / session / shadow-DOM measurement).pixel-compare.mjs --text-boxes(D4, auxiliary). Repeated-unit families are declared once per project:{ "<family>": { origin, build, n, required, pages[], templates[] } }(recreation-procedure § Repeated-unit families).Upstreamed field feedback: window-free real Chrome as the escalation tier (
STARDUST_HEADED_WINDOW=1opts into a window); Akamai's HTTP 400 escalation as a challenge marker; setup steps probe the probe deps first and install them as devDependencies only on failure, never--no-save;deploy-batch.mjssurfaces the adminx-errorheader (the 200-images-per-document cap).Docs: gate doc § The all-pages published-origin gate + pass-bar item 7, replica Phase 4 / 5 / Setup, recreation-procedure § Repeated-unit families, handoff contract § 3 rows C and E, deploy Step 10 item 7, rollout Phase E / H, diff SKILL § The published-origin probes, eval criteria, scripts index. Tests for the four instruments plus the extended
gate.sh(62 checks),gate-evidence(32) andupdate-coveragecontracts.Calibration (96-page roster, same captures)
all-1440)prototypes-1440, 5 archetypes)Failing by criterion on the deployed table: pixel 30, height 6, clip 23, content 31; content n/a on 37 pages whose origin is edge-blocked from the probing network.
Review notes (karlpauls)
1 recorded unit, 2 coverage verdict, 3 per cluster first, 4 import before install, 5 tier in the evidence — done in the last three commits. 6 (version bump via
plugin-version.mjs) waits for #396; this branch sets.claude-plugin/plugin.jsonto 0.26.0 and will be rebased on that field once #396 lands.Size
Versus
main: code +1705 / −36, tests +472 / −4, skill prose +188 / −17, CHANGELOG +71. Removed as compensation along the way:pixel-compare --pad(the rejected union metric),sbs-crop.mjs, themeasure-liveCLI (library only), thecontent-diff --publishedhandoff.Open questions
Default tolerances (
--clip-max 0,--unit-tol 4, the 25 % count tolerance); whether buttons and control state should join the blocking set once session-variable labels are modelled; the English word lists behind the count and "read more" heuristics are flags (--count-words,--more-words), not yet per-locale defaults.Verification
npm run lint:stardustclean; airbnb eslint clean on the new scripts; all affected test suites pass.🤖 Generated with Claude Code