Redesign an existing website to make it better. Built on top of impeccable.
71
89%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
The gate proves an archetype matches the LIVE site — three instruments, per breakpoint, with a hard iteration cap. It replaces the redesign pipeline's craft gates entirely: an archetype ships because it measured true, never because it looked right. Every fix in the loop comes off the instruments; eyeballing is not an input.
Validated (UC1-E1, a typographic retail home page): 8.31% → 2.93% → 1.31% pixel diff across exactly 3 iterations, 0 structural 🔴, height Δ 0 — and the two defects the capture phase missed (span font fork, hero scrim) were both found only by these instruments.
| Probe | Script | Catches | Blind to |
|---|---|---|---|
| Structural content + type | ../../diff/scripts/content-diff.mjs (project copy) | dropped/mis-slotted headings·eyebrows·CTAs, invented/dropped copy, rendered-face font forks (width probe) | geometry |
| Visual heuristics | ../../diff/scripts/visual-diff.mjs (project copy) | stretched images, dropped wraps, blank renders, surface/ground flips | "right text, wrong slot" |
| Pixel (replica-owned) | ../scripts/stitch-shot.mjs + ../scripts/pixel-compare.mjs | everything the other two abstract away: paint effects, scrims, exact geometry, image crops | semantics (a wrong-but-same-colored word) |
Run ALL three — they catch disjoint failure classes; any one alone gives a false "looks fine".
Breakpoints: 1440 AND 360 by default (--breakpoints). Mobile is not
free: UC1-E1's gate-passing 1440 prototype measured 24.2% / height Δ
−1572px at 360. Each breakpoint is its own full gate pass with its own
iteration budget. Gate 1440 first (the geometry lifted from desktop CSS),
then 360.
# Serve the prototype from its own dir so relative assets resolve. Verify the
# port is YOURS first (lsof -nP -iTCP:8791 -sTCP:LISTEN); prefer a per-project
# port — a stale server from another stardust project on the shared suggested
# port silently serves a foreign site into the gate (recorded twice, 2026-08).
# On shared machines run gate.sh with --marker "<brand string>": the slug
# default can false-pass against another stardust project sharing the slug
# (both serving a home-proposed.html that contains "home").
(cd stardust/prototypes && python3 -m http.server 8791 &)
PROTO="http://localhost:8791/<slug>-proposed.html"
LIVE="https://<site>/<path>"
W=1440 # then 360
GATE="stardust/replica/gates/<slug>-$W"
# 1. structural — --dismiss keeps consent + timed marketing modals out of the
# inventory on both sides; add extra selectors for non-standard closers
node scripts/diff/content-diff.mjs "$LIVE" "$PROTO" --profile generic --width $W \
--main "<content-root>" --dismiss | tee "$GATE/content-diff-iter<N>.txt"
# 2. visual heuristics — --main is a real flag here too (live sites often
# have no <main>; without it both sides false-flag BLANK RENDER)
node scripts/diff/visual-diff.mjs "$LIVE" "$PROTO" --profile generic --width $W \
--main "<content-root>" --dismiss --out "$GATE/vdiff" | tee "$GATE/visual-diff-iter<N>.txt"
# 3. pixel — stitched captures on BOTH sides (never fullPage:true)
node scripts/replica/stitch-shot.mjs "$LIVE" "$GATE/live.png" --width $W --settle
node scripts/replica/stitch-shot.mjs "$PROTO" "$GATE/proto.png" --width $W
node scripts/replica/pixel-compare.mjs "$GATE/live.png" "$GATE/proto.png" \
--out "$GATE/diff-iter<N>.png" --threshold 10On a geo-redirecting site add --locale <tag> to all three (a live side that
redirects to a different locale per run is a nondeterministic source); on a
bot-managed site that exits 3, escalate with --headed (§ Hardening rule 1).
The live capture is taken ONCE per breakpoint per full gate run and reused across iterations — re-take it only if it is genuinely stale (site changed, capture hardening changed). This is a bot-block control, not just a cost note: content-diff + visual-diff each navigate the live URL per run, so a full 3-iter, 2-breakpoint gate is already ≈12–18 live hits, and hard-CDN sites (recorded: an Akamai-defended luggage retailer) escalate to an IP block after a handful. The prototype capture is re-taken every iteration.
content-diff: 0 structural 🔴. 🟡 (body/EXTRA) and 🟠 (font fork) confirmed intended — a substituted licensed font is a permanent justified 🟠; record it once in the ledger.
visual-diff: flags none or justified. A live page's own quirks are justified when the prototype mirrors them (e.g. a 1×1 SEO h1 at x0, a carousel tile at a negative offset — both real UC1-E1 justifications).
pixel diff ≤ 10% full-page — AND no band left unexplained (§ Band breakdown). 10% is the ship bar, not the target; the validated run landed at 1.31%.
height delta: |Δ| ≤ 8px — pixel-compare's own warning threshold is the bar (it prints ⚠ above 8px), so a −9px result is unambiguously a residual, not a pass. A large delta invalidates the % — the overlap crop silently discards the tail, so a short prototype can score deceptively well. Fix heights before trusting anything else.
Chrome crop gate: header band AND footer band each ≤ 2% diff (≥98%
match, #115). The full-page bar dilutes the chrome — header/footer are
a small share of page pixels but carry disproportionate visual weight
and repeat on every page of a rollout. Two field runs shipped
full-page-green pages whose chrome measured only 93–97% (lookalike
icons, wrong micro-weights, off-by-10px nav rows all fit inside a ≤10%
full-page bar). Run ../scripts/crop-compare.mjs over the SAME stitched
captures the pixel probe used — no extra live hit:
node scripts/replica/crop-compare.mjs "$GATE/live.png" "$GATE/proto.png" \
--y 0 --height <nav-height> --out "$GATE/chrome-header-diff.png"
node scripts/replica/crop-compare.mjs "$GATE/live.png" "$GATE/proto.png" \
--y <liveDocH - footerH> --y-b <protoDocH - footerH> --height <footerH> \
--out "$GATE/chrome-footer-diff.png"--y-b gives the footer crop a per-side offset so a small doc-height
delta doesn't contaminate it with a false full-band diff. Read the band
heights off the section-anchor probe (anchor.mjs prints the footer's
[y, height] on both sides).
Styles diagnose, pixels confirm — run the computed-style parity probe
BEFORE any pixel iteration on chrome. ../scripts/chrome-parity.mjs
probes the same regions on live and build (default header + footer;
add sticky strips with --region strip=<liveSel>|<buildSel>), pairs
every text-bearing element by its text, and prints only what differs:
family / size / weight / style / line-height / letter-spacing /
transform / colour / background / padding / radius, the element rect,
the clickable box of links and buttons, and the icon inventory
(count + size + signature, paired by order). Recorded: one run found
what many pixel-band rounds had not — an italic-vs-normal note, a
regular-vs-bold link, a wrong nav link colour, 12px row offsets, a 97×40
vs 71×32 button, six missing icons. Fix every delta, re-run until it is
quiet (exit 0), THEN crop-compare — a pixel loop on chrome with parity
deltas outstanding is wasted iterations. Each run is one live
navigation (budget it like any live probe); --json records both
sides as the round's evidence.
node scripts/replica/chrome-parity.mjs "$LIVE" "$PROTO" --width $W \
--region header=header --region footer=footer # + --region strip=<sel>|<sel>Glyph-dense chrome has a pixel noise floor — the ONE justified way past
the 2% bar, and it is evidence-gated three ways. A footer of ~50 links
bottomed out at ~5% pixel diff with family, size, line-height, weight,
colour, pitch and positions all numerically identical (recorded): per-glyph
antialiasing between a hinted licensed face and the self-hosted webfont
dominates, and raw pixel bars over-iterate against noise. A chrome band
that FAILS crop-compare may be logged as a justified residual —
never a pass — only when ALL three hold, and each is an artifact in the
residual entry (§ Residual logging format, cause: "glyph-antialiasing"):
(1) chrome-parity.mjs exits 0 for that region at tolerance 1px — every
paired text's metrics and position match, no MISSING/EXTRA, icons paired;
(2) crop-compare.mjs reports the diff texture as thin-edge (≤15% of
differing pixels have ≥5 differing neighbours) — glyph antialiasing is
thin, misalignment and missing paint are thick; (3) the region is
text-dense (link columns, nav rows) — a band with imagery or icons never
qualifies (parity's ICONS finding would not be quiet anyway). One or two
of the three is not enough: a quiet parity probe with a THICK texture is
a paint defect the probe does not model; a thin texture with parity
deltas is a real metric error hiding in noise. The 2% bar itself is
unchanged, and the residual is re-verified every gate round like any
other justified flag.
Chrome crops are ELEMENT-ANCHORED per side, never fixed-y — and
"chrome" means every site-wide repeating band: header, sticky/quick-link
strips, footer. Recorded: the header measured 33.9% and a quick-links
strip 19.2% while the full page passed at 6.5% — chrome is small-area,
highest-salience and repeats on every page. Two traps: (a) a fixed-y crop
produces FALSE reads the moment either side's rhythm shifts — a 35px nav
fix moved everything below it and the strip crop read 66% while the strip
itself, re-anchored to its own band edges, was at 1.6%. Locate each
region on EACH side (its element rect via anchor.mjs, or its band
edges via row-profile.mjs's column scan) and pass both anchors
(--y/--y-b); every gate round re-reads the anchors. (b) Regions whose
live content is authored-volatile — campaign heroes, promo creatives that
change between capture and gate — are masked out of the fidelity number
with pixel-compare.mjs --mask <yA:h[@yB]> (printed on the verdict line,
never silent): they are authored content, not conversion fidelity, and
chasing them burns iterations on a moving target.
Applied inconsistency-register entries create expected deltas: cross-
reference the entry ID (R-<nn>) when justifying a flag over its zone
(preserve-direction.md § Gate interaction).
Calibration honesty — two fidelity regimes, one bar. The validated numbers above (1.31%, Δ0) describe the prototype regime: a standalone prototype gated against the live page, on a typographic page. Pages converted to the delivery platform and gated against the published origin (§ The published-origin gate) carry justified block-model deltas — control UI, split anchors, nondeterministic elements — and landed at 6.9–9.9% in the field while visually faithful. The ≤10% bar covers both regimes; what burns iteration caps is chasing prototype-regime numbers on a published-origin gate. Record which regime a number belongs to in the ledger, and judge each against its own regime's precedent.
The overall % hides WHERE drift starts. pixel-compare.mjs prints per-500px
bands (--band to change); read them top-down:
The section-anchor probe names the section the band table only points
at. ../scripts/anchor.mjs prints [y, height] per top-level section
(+ footer + doc height), same shape on both sides:
node scripts/replica/anchor.mjs "$LIVE" --width $W # once per fix round at most (live hit)
node scripts/replica/anchor.mjs "$PROTO" --width $W # free — build-side onlyDiff the two outputs, fix the FIRST section whose [y, height] disagrees
(top-down — everything below it is offset-contaminated, the same rule as
the band table), re-run pixels. Field-validated (a financial-services site, 8 pages): this
loop roughly halved iterations vs band-reading alone. ../scripts/gate.sh
wraps one full pixel round (stitch both sides — live cached — + compare +
verdict) in one command.
Section-level compare (crops) is the escalation when a band stays hot and
the cause isn't visible in diff-iter<N>.png — in the validated run it was
prepared and never needed, because re-authoring hit exact section heights.
crop-compare.mjs (the chrome-gate script, pass-bar item 5) does exactly
this for any y-band, not just chrome.
Two row-level instruments replace eyeballing crops (../scripts/row-profile.mjs,
runs over the same stitched PNGs — no live hit):
node scripts/replica/row-profile.mjs live.png proto.png --columns 7. Recorded: a stacked-crop visual read suggested a 415px photo
with a white band under it; the scan of the same capture proved the photo
full-bleed to 499px with the "white band" being an overlapping card — the
wrong read cost two build/measure cycles. Crop eyeballing is hypothesis;
the scan is the measurement.--color <#rrggbb> lists every row run dominated by it on both sides and
pairs them in order: the per-pair delta is each landmark's offset, and the
CHANGE in delta between consecutive pairs (gapShift) names the one
inter-landmark CSS gap that absorbed the shift. Patch that gap, re-measure,
top-down — the same contamination rule as the band table. Recorded: three
passes driven this way took a page 16.9% → 11.05% and a 1559px height
delta → 48px. Do not tune margins by eye against crops. (Crop with pngjs;
macOS sips --cropOffset is unreliable for band crops.)Both gate breakpoints render a frozen width: 720px and an authored
width: 50% byte-identically at 1440 — and 360 collapses both — so a
computed-style lift that recorded the resolved px instead of the sizing
MODEL passes every gate and diverges only on wider screens (recorded: a
live hero card 940px at 1920 vs a frozen 720px; the CTA row wrapped as a
side effect). After the 1440 pass, run a cheap box-map spot check at
≥1920: sample the text-bearing elements' x/width on both sides (the
anchor-probe technique at --width 1920, or one extra stitched capture)
and compare — a box whose width scales on live but not on the prototype is
a frozen fluid value. No full pixel gate is needed at 1920; the box map
alone catches the mismatch class. Two rules when reading it: compare the
same DOM tier (EDS/section wrappers are full-width by design and
false-flag against live INNER containers), and fix upstream — re-lift the
authored rule per recreation-procedure.md § Lift the sizing MODEL, don't
nudge the px. Sample heights as well as widths, and take one extra sample
at an intermediate width (1280 or 1680) when the live layout is fluid: a
hero that scales with the viewport on live and is fixed-px on the prototype
is identical at 1440 and visibly off at 1512 (recorded).
Hard cap: 3 iterations per breakpoint. Matching the validated run's discipline — convergence happened within 3 with the recreation procedure followed; more loops mean the inputs were wrong (values eyeballed instead of lifted, capture unhardened), and the fix is upstream, not a fourth loop.
chrome-parity.mjs and clear its deltas (§ Pass bar,
item 5); style deltas are named in one pass, pixels only say where.curl --compressed <css-url> | grep '<new-rule>'; the CSS is
gzip-encoded, a bare curl | grep scans binary and silently matches
nothing) and re-render in a fresh headless context; and a reviewer's
screenshot encodes their zoom — back-compute their CSS viewport from any
element with a known percentage rule (a card at 851px under width: 50%
→ viewport 1702px) and reproduce THAT viewport headlessly before letting
their numbers overturn a fix.anchor.mjs, § Band
breakdown): run it on both sides, fix the first mismatched section
top-down, re-run pixels. Build-side anchor/computed-style passes never
navigate the live origin and are FREE — the cap governs live-gate cycles,
not measurement.--headed and treat further
live hits as spent budget — the recorded failure mode (luggage retailer) was an
IP-level block escalating within ~3–4 automated requests, after which
iteration 2's numbers measure the block, not the site. A challenged
headless run costs exactly 1 hit: gotoLive throws
BotChallengeError on the first challenge-classified response (the
wait+reload solve window runs only under --headed, where clearance can
actually land) — so the block budget is still intact when you escalate.Each of these was hit live; skipping one silently corrupts the measurement rather than erroring.
Accept, Accept-Language,
Upgrade-Insecure-Requests, sec-ch-ua*) produced HTTP 200 — Akamai
bot-manager fingerprints on the absence of those headers, not just the
UA. All three instruments now send both by default via the shared
diff/scripts/live-session.mjs; --ua overrides the UA string only.
The header set rides document requests only (F-B2, financial-services site):
forcing it on every request makes cross-origin CORS-mode webfont fetches
non-simple and kills them with net::ERR_FAILED — the capture then
silently renders fallback type (see rule 14); bot managers fingerprint
the navigation request, which still carries the full set. Sanity check
when numbers shift inexplicably between runs: grep the content-diff
inventory for challenge-page strings.domcontentloaded, never networkidle, on live targets. Live sites
with analytics beacons never reach networkidle — hard timeout. Built in:
the diff scripts default domcontentloaded for non-localhost http(s)
URLs (decided per side; EDS build/preview origins — *.aem.page,
*.aem.live, *.hlx.page, *.hlx.live — are the exception and get
networkidle, they decorate async) and keep networkidle for local
prototypes; --wait-until overrides. stitch-shot is always
domcontentloaded.--main scoping — and never body. Live <main> often
contains header nav + hidden mega-menu; unscoped, those diff as ~dozens
of missing CTAs (UC1-E1 iteration 1: 41 of 50 reds were scoping
artifacts). Scope BOTH sides with the same selector — have the prototype
adopt the live content-root class so one --main value fits both. Both
diff scripts take --main (visual-diff's is the upstreamed flag: on
sites without a <main>, both sides otherwise false-flag BLANK RENDER
while the main-scoped checks silently no-op). Two guardrails:
--main body is NEVER a valid replica scope. A too-broad root
self-poisons the instrument regardless of symmetry: reproduced
(a furniture retailer), content-diff run live-vs-ITSELF with --main body
produced 103 structural 🔴 and asymmetric node counts (461 vs 73)
from analytics/inline-script text plus a nondeterministic
cookie-settings panel pulled into the inventory. The content root must
exclude consent/analytics chrome.fullPage:true. Chromium's
captureBeyondViewport renders lazy-decoded images as gray placeholders
even when the DOM says loaded. Stitch on BOTH sides — the instrument
must be symmetric.dismissOverlays (stitch-shot always; diff probes via
--dismiss): (a) cookie consent (clicked accept; --consent <sel> /
--dismiss <sel,...> for non-standard banners); (b) timed
marketing/newsletter interstitials — recorded (fashion retailer): an
undismissed "Sign up, stay updated!" modal fired ~5–9s after load and
baked a pixel-diff contributor into the LIVE capture, repeated at every
chunk seam, that no prototype fidelity could null out. These fire on a
timer, so the dismissal polls for late arrivals and stitch-shot sweeps
again after the settle pass.recreation-procedure.md § Granularity parity.recreation-procedure.md § Capture-state); a probe flag
over a logged capture-state zone is justified.recreation-procedure.md.:hover-styled element under the resting cursor is silently captured
in HOVER state (recorded: a hero's a.box-hover:hover img{opacity:.4}
shipped the live capture dimmed — measured 0.4 in capture, 1.0 in
reality). The shared dismissOverlays parks the mouse (bottom-left)
after every dismissal pass — all three instruments inherit it; mirror
it in any ad-hoc capture that clicks anything.recreation-procedure.md § Fixed and sticky chrome.cf-mitigated: challenge, or
403/429/503 with a Cloudflare/Akamai/F5/Imperva edge signature) and
exit 3 with a BotChallengeError naming the URL and the marker.
Recorded (luggage retailer): Akamai served "Access Denied" to the headless
instruments — which, without this rule, would have silently measured
the block page as the source and diffed it cleanly, wrongly. The
escalation ladder: default (UA + standard headers) → --headed
(stealth real Chrome, same tier as crawl.mjs's fallback) → if STILL
blocked, the site needs crawl.mjs-class capture and the gate must
not silently degrade — record the breakpoint as gate-blocked in the
ledger and surface it to the user; a gate that can't read the live
source has no pass to report.html/body are
overflow:hidden and an inner container scrolls, the document reports
the full content height but window.scrollTo is a no-op — every chunk
would capture the top viewport and the rows below would stitch as
zero-filled black: a silently fictitious pixel diff. stitch-shot now
detects the stall and exits 1 with the signature stitch-shot error: scroll stall at chunk target …px: window scroll is a no-op (window.scrollY stuck at …px) while the document reports …px.
Capturing the inner scroller is future work; for now record the page as
gate-blocked for the pixel probe and rely on content-diff/visual-diff.document.fonts.ready for declared faces with FontFace status error
and warns loudly with the family names; mirror the check in any ad-hoc
capture. On the warning, decide before gating: load the face in a real
browser — if it loads there, the failure is instrument-induced (a
capture defect: fix the instrument, and the poisoned runs don't consume
the iteration cap per § Iteration discipline); if it fails there too,
fallback type is the truthful capture (capture-state — log it).The four manual adaptations this section used to prescribe are upstreamed
into the shipped scripts. All live-target hardening lives in one shared
module — diff/scripts/live-session.mjs (UA + standard headers, challenge
fail-loud, overlay dismissal, headed-stealth escalation) — and the diff
scripts expose it as flags:
# content-diff against a live source: no source edits, flags only
node scripts/diff/content-diff.mjs "$LIVE" "$PROTO" --profile generic \
--width 1440 --main "<content-root>" --dismiss
# visual-diff: --main is a real flag (rule 3), same live hardening
node scripts/diff/visual-diff.mjs "$LIVE" "$PROTO" --profile generic \
--width 1440 --main "<content-root>" --dismiss
# non-standard overlay closer / pinned locale / bot-managed site:
# --dismiss "#custom-close" --locale en-GB --headedDefaults when no flags are passed: real-Chrome UA + standard headers on
every context; domcontentloaded for non-localhost http(s) URLs and
networkidle for local ones (per side); no overlay dismissal (pass
--dismiss for live pairs); exit 3 on a challenge (rule 12).
A project copy re-implementing retired adaptations is a defect, not
diligence: the edits were 10 distinct changes across 2 files, and a partial
application silently mis-measured (e.g. one main-scoped selector left
hardcoded in visual-diff). If you find // replica ADAPTATION: copies from
an older run, re-copy the shipped scripts and pass flags instead.
The narrow exception: a documented instrument-bug fix is the correct move when the shipped instrument measures falsely — fail-loud outranks script immutability. The rule above exists to kill stale re-implementations of upstreamed flags, not to force gating on an instrument known to lie (recorded, F-B2: the shipped header delivery silently killed live webfont loads; the session's most important fix was a hand-edit to the project's live-session.mjs). A legitimate instrument fix is (a) commented in the script with the defect it corrects, (b) recorded in the ledger with the runs it invalidates, and (c) flagged for upstreaming into the plugin. An uncommented, unledgered edit is still a defect.
The prototype gate above proves the RECREATION; it does not prove the DELIVERED page. Local render harnesses systematically understate deltas because the real delivery pipeline transforms the markup — field rule (financial-services site, 8 pages published): a page gating at X% on the harness lands at X±(large) on the published origin until the transforms below are handled. Only the published-origin number counts as the final gate for a platform-delivered page: re-run the full gate (same instruments, same pass bar, same iteration discipline) with the live site as source and the published page — preview or live origin — as build. Judge the result in the published-origin regime (§ Pass bar, calibration honesty), not against prototype-regime numbers.
Two rules for that final run:
<p><picture>,
fragment chrome): a gate-passed 8.4% prototype first published at 11.75%,
and two text-anchor rounds (anchor probe live-vs-published, patch section
paddings in block CSS, re-measure) brought it to 6.5% with exact anchor
parity (recorded). Treat the pre-publish harness number as provisional
and the reconcile round as expected work, not a regression.Recurring EDS pipeline transforms that move the number (each recorded; none visible on a local harness):
<p><picture>. The pipeline emits every
authored image inside a paragraph. If any base rule makes that <p>
positioned, absolutely-positioned imgs inside it collapse to 0×0
(backgrounds vanish) and the now-empty paragraph box distorts flex/grid
flow. Style p:has(picture) as the media layer, and expect specificity
fights with :not()-heavy base selectors — junction/override rules must
match or exceed them..section divs carrying full
section padding — a ~96px phantom band, typically at the page tail (the
same class as deploy's emptySectionCollapse; the fix there is
main .section:empty { display: none }, see
../../deploy/SKILL.md § Runtime-detection probe)./media_<hash> renditions with width
params — size/ratio assumptions lifted from the authored URL don't
survive; read dimensions from the delivered rendition, not the authored
asset..section:has(.some-block)) can silently never match the delivered
page (recorded). Verify every :has() / block-class selector against the
delivered .plain.html and rendered DOM, not the authored file.Per archetype per breakpoint, in stardust/replica/progress.json:
{
"pageType": "landing",
"archetype": "home",
"breakpoints": {
"1440": {
"iterations": 3,
"result": { "structuralRed": 0, "visualFlags": "3 justified",
"pixelPct": 1.31, "heightDelta": 0, "pass": true },
"justified": [
{ "probe": "visual", "flag": "1x1 h1 at x0", "why": "mirrors live SEO h1" },
{ "probe": "content", "flag": "🟠 font fork ×2", "why": "licensed kit substituted, R-policy fonts", "permanent": true }
],
"residuals": [
{ "band": "y 4500–5000", "pct": 6.2, "cause": "capture-state: 3 CDN-403 placeholder tiles", "flaggedFor": "delivery" },
{ "region": "footer", "pct": 4.8, "cause": "glyph-antialiasing", "parity": "gates/home-1440/chrome-parity-iter3.json", "texture": { "thickPct": 6.1 }, "flaggedFor": "user" }
],
"captureState": [ { "what": "product tiles 4–6 on placeholder data-URIs", "where": "carousel-2" } ]
},
"360": { "...": "..." }
}
}Rules: every residual names its band, its %, its cause, and who inherits it
(delivery for capture-state items, user for accepted trade-offs). A
residual without a cause is not a residual — it's an unfinished iteration;
either diagnose it or spend the remaining budget on it. The rollout phase's
final report surfaces the residual list per page type so "gate passed"
can't hide "passed with 6% unexplained".
.tessl-plugin
skills
audit
reference
deploy
diff
direct
extract
migrate
prepare-migration
prototype
replica
reskin
rollout
stardust
uplift
reference