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
stardust/reskin/mapping.md is the decision record between the two
captures: every content slot from the content model assigned to a
donor module from the enumerated vocabulary. It is authored in
Phase 3, before any rendering, and it gates rendering: a page
whose brief fails the bars below is not rendered.
The brief exists because the alternative — deciding layout slot by
slot mid-render — is where silent improvisation happens. The
validation experiment (H5) showed every mapping decision is decidable
from the two artifacts alone: slot anatomy
(content-model/<slug>/content-model.json) vs module anatomy
(stardust/reskin/donor-modules.md). No render context needed, no
judgment arbitrary enough to require a human.
One table row (or block) per slot, for every slot in the content model — no slot may be absent from the brief:
| Field | Contract |
|---|---|
# / slot id | The content-model slot (s01), or split sub-slot (s07-news, s07-events) |
| Content | One-line anatomy: what the slot carries (eyebrow / h-level / body / CTAs / media) |
| Donor module | A module id from donor-modules.md (M4), or — for new-module |
| Rationale | One line grounding the assignment: slot anatomy vs module anatomy |
| Status | mapped | new-module | chrome | carried-invisible |
Plus a Stats block (mapped ratio, new-modules list), a Deltas block (chrome swaps + the normalization ledger entries), and a Judgment calls list. See the worked example that validated this contract: the experiment's mapping of 12 slots onto a 16-module donor vocabulary at 91% mapped, 1 new-module, 1 chrome swap.
mapped — the slot renders as a named donor module, possibly
with a module transformation noted in the rationale (e.g.
carousel slides → static card grid when the donor has no carousel
vocabulary — a layout decision, not a content delta; the
slides' text and images are all carried).new-module — the donor vocabulary has no module for this
anatomy (the experiment's case: a search form on a donor with no
search anywhere). Requirements:
chrome — nav / footer swapped for donor chrome carrying the
source's links (labels and destinations preserved — the
../../migrate/reference/content-preservation.md rules apply to
chrome too). Chrome slots are excluded from the content-gate
scope and each swap is a documented delta (D1, D2, …) in the
Deltas block.carried-invisible — non-visual content inside the byte
scope: sr-only / visually-hidden a11y landmarks, skip-target
headings. Real sites keep their only h1 here. None of the other
statuses fit: it isn't chrome (it is inside the gate scope, so
its bytes must survive), mapped is wrong (no donor module has an
anatomy for invisible text), and new-module is wrong (a
new-module entry must compose donor tokens; this composes none).
Contract: the slot is carried verbatim into an equivalent
visually-hidden element (the rendered page's own sr-only
utility), stays inside the content-gate scope, and adopts no donor
tokens. Note the heading level carried — an sr-only h1 is still
the page's h1.Gate: mapped ratio ≥ 80% over content slots (chrome and
carried-invisible both excluded from the denominator — one is out
of scope, the other has no module to map to by definition). Below
80% the donor vocabulary doesn't cover this content — stop per
SKILL.md § Stop conditions: widen the donor capture (more donor
pages usually means more modules) or get explicit sign-off on a
larger new-module list. Do not lower the bar silently.
Section ≠ slot. When one captured slot holds two logical regions (the
experiment's single fullwidth div holding News and Events), split
it into sub-slots in the brief (s07-news, s07-events) so each
mapping decision is atomic. The split is a brief-level construct —
the content model is not edited — and slot-coverage still asserts the
parent slot's full text, so a split can't shed content.
Declare it once in the brief; it binds the renderer:
innerText reflects
text-transform — see reference/content-model.md
§ Rendered-case text). The byte gate compares rendered text on
both sides.text-transform only, mirroring what the
source rendered.Icon fonts of the Material Symbols family put the ligature name
in the DOM as text — a source "more" link is literally
chevron_right Read more in innerText, so the ligature name is in
the content model, in the byte-gate reference, and (via the ordered
stream's text nodes) in whatever the renderer emits. Decide its
treatment in the brief, per ligature family, one of:
N*) that strips
the icon text nodes on the source side — then the renderer must
not emit them either. This is a content removal, so it takes an
explicit ledger entry with a why; never just edit the strings.What is never allowed: silently dropping or rewording the ligature
text in the renderer — that is a byte-gate failure by construction
(reference/gates.md § Failure modes).
The single audit surface for every deviation between the live source page and the gated comparison:
D* chrome swaps (what was swapped, what carries over, why it is
out of gate scope);N* normalization ledger entries, copied from the page ledger
(stardust/reskin/normalize/<slug>.mjs) — the brief cites them,
the ledger executes them.If a delta is not in this block, it does not exist: any other source↔render difference is a gate failure, not a delta.
Source garbage discovered while mapping — broken JSON-LD URLs, wrong-locale labels, duplicated links — is carried verbatim (fidelity over repair) and flagged in the brief's judgment-calls list for the human. Silently fixing it breaks the byte gate; silently keeping it without a flag ships a known defect unreviewed.
.tessl-plugin
skills
audit
reference
deploy
diff
direct
extract
migrate
prepare-migration
prototype
replica
reskin
rollout
stardust
uplift
reference