stardust:direct
Resolve the user's freeform redesign intent into a complete target
specification: project-root PRODUCT.md and DESIGN.md (impeccable
format), a DESIGN.json sidecar with the divergence audit trail, and a
stardust/direction.md with the full reasoning trace.
direct produces the spec against which prototype and migrate
operate. It never writes prototypes or migrates pages — those are
downstream sub-commands.
Inputs
<phrase>— optional positional. The user's freeform intent ("make it better", "more Linear less Salesforce", "feel more premium on a small screen"). If omitted, ask the user for one.--re-direct— optional. Replace the current direction with a new one. Triggers stale-flagging on prototyped / approved / migrated pages perskills/stardust/reference/state-machine.md. Default behaviour without the flag is additive: if a direction already exists, the agent asks before replacing.--rebrand— optional. Force rebrand mode (full divergence-seed roll, no Mode A inheritance) regardless of whether the captured brand surface has signal. The default mode is brand-faithful whenever_brand-extraction.jsonissignal-strong(see § Setup step 5 and Phase 2 § Mode-detection precedence); pass--rebrandto opt out explicitly when the user's phrase is ambiguous about whether they want a refresh or a clean-slate redesign.--prep— optional. Run in migrate-prep mode: confirm the type catalog, finalize the module catalog, capture color reservations and brand-level metadata defaults, re-evaluate direction against the wider crawl. See § Prep mode below. Typically invoked via theprepare-migrationorchestrator.--add-variant <name>— optional. Add a new variant against the existing direction without re-running intent reasoning or mode detection. WritesDESIGN-<name>.{md,json}at the project root and appends a per-variant section tostardust/direction.md. The previous direction stays authoritative; existing prototypes are not stale-flagged. Used when variants are spec'd incrementally — typical workflow: render variant A, review, then ask for B and C as "the alternatives we discussed earlier." See § Add-variant mode below for the per-field inheritance rules.
Setup
- Run the master skill's setup
(
skills/stardust/SKILL.md§ Setup) — hard impeccable dep check, context loader, state read. - Verify
stardust/state.jsonexists and contains at least oneextractedpage. If not, stop and recommend$stardust extract <url>first. - Read
stardust/current/_brand-extraction.json. If absent, stop — extract did not complete brand-surface extraction; re-run extract. 3b. Cross-site brand inputs (when present). Two extract-written signals widen the brand surface beyond the primary origin:state.json.designSource— design-donor mode (extract ran with--design-source <url>). The donor's derived system atstardust/canon-source/DESIGN.{md,json}becomes the target the Mode A pins bind to: palette and type pin to the donor surface while content, IA priorities, and per-page evidence stay with the primary origin. Surface in the plan: "Design-donor mode — target system inherited from ."_brand-extraction.json.origins[]— sibling-property evidence captured via--brand-source. Traits captured on a sibling origin count as captured evidence for trait amplification (variant B/C briefs, improvements items) exactly like primary-origin evidence; cite the origin in the evidence citation. Under Mode A the pins still come from the primary origin unless designSource says otherwise — sibling evidence widens what can be amplified, not what is pinned.
- Read
stardust/direction.mdif present. If a prior direction exists and--re-directwas not passed, ask whether the user wants to refine the existing direction or replace it. - Validate provenance on every in-scope page (prep mode only).
When
--prepis active, callvalidateProvenance(page)perskills/stardust/reference/state-machine.md§ Provenance validation on everyextractedpage instate.jsonbefore typing or module detection. Abort with the helper's error when any page lacks live-render evidence. SurfaceProvenance OK on N pagesin the prep summary. Discovery- modedirectdoes not validate (it operates on a 5-page sample for which extract's own write-time refusal is sufficient). - Classify the captured brand signal. Read
_brand-extraction.jsonand stamp one of:signal-strong— palette has ≥ 3 distinct colors (after near-duplicate clustering and excluding pure black/white if they are the only entries) AND at least one captured type family is named intype.headingFamily.nameortype.bodyFamily.name. This is the common case for any extracted commercial site.signal-thin— palette has 2 colors OR no captured type family ORtype.scaleAudit.kind === "ad-hoc"with fewer than 3 distinct heading sizes. The brand exists but cannot fully anchor a refresh.signal-absent— palette has 1 color or 0, or_brand-extraction.json._provenance.notesflags the extraction as failed / login-walled / iframe-dominated. The classification feeds the Mode-detection precedence in Phase 2. Surface the classification in the plan when it would change the default mode.
Procedure
Phase 1 — Reasoning
Run the full intent-reasoning procedure from
skills/stardust/reference/intent-reasoning.md. Steps 1-6: restate
the phrase in dimensional vocabulary, identify movement, identify
gaps, ask at most two clarifying questions, map to an impeccable
command sequence, show the plan to the user.
Worked examples in
skills/stardust/reference/intent-examples.md calibrate the style.
Hard ceiling on questions: two per turn, no exceptions.
Hands-off mode (per skills/stardust/SKILL.md § Hands-off mode,
state.json.handsOff: true): ask nothing and wait for nothing.
Derive every answer the questions would have collected from the
captured evidence — density and ia-fidelity from their documented
defaults and trigger conditions, audience and register from the
captured surface — and record each as a named assumption in
direction.md § Movements (e.g. density: balanced (hands-off default — multi-audience floor fired)). The plan is still written;
execution proceeds without the confirmation gate. Question budgets
and gates below that say "ask the user" resolve the same way: derive,
stamp the assumption, proceed.
Density tuning (one-shot, only when unmoved)
When the user's phrase does not move the density axis (per
reference/intent-dimensions.md § 4), and the resolved register is
brand, ask one short follow-up — count it within the two-question
ceiling:
Density tuning — (a) airy (NYT-Opinion-tier breathing, ~96px section padding), (b) balanced (calm but compact, ~64–72px), (c) packed (data-dense, ~40–48px). Default for brand-register sites with multi-audience IA is (b) balanced; pick (a) only when the page is editorial-led with deep per-section density.
If the user answers, stamp the chosen tier in direction.md §
Movements as density: <tier>. If unanswered, default to
balanced (not airy) for brand register and stamp
density: balanced (default).
Skip this question entirely when:
- The user's phrase already moved
density(any of "make it denser", "more breathing room", "compact", "tight", "spacious" count as movement). - The register is
product(defaultpackedper § 4). - The register is
ambiguousand resolving it earlier in the reasoning is the higher-value question — defer density to the next turn rather than burning a question slot.
The tier propagates to DESIGN.md's spacing.sectionPadding
deterministically per intent-dimensions.md § 4: airy = 96px,
balanced = 64px, packed = 48px. Phase 4 picks the value from this
stamp without re-asking.
IA-fidelity tuning (one-shot, only when unmoved)
When the user's phrase does not auto-pin ia-fidelity (per
reference/intent-dimensions.md § 9 — i.e. none of "verbatim",
"same IA", "keep the structure", "swap the surface",
"don't rethink the IA" and none of "reimagine", "rethink",
"deeper redesign", "what if" appear), ask one short follow-up
— count it within the two-question ceiling:
IA fidelity — (a) verbatim (same section sequence, same content beats; variants explore surface only: color, type, density, motion), or (b) reimagined (variants may demote / promote / drop sections, move IA priorities, take "what if" positions on the spine of the page). Default (b) for the typical refresh; pick (a) when the customer asked to keep their site structurally identical and only swap the surface.
If the user answers, stamp the chosen tier in direction.md §
Movements as ia-fidelity: <tier>. If unanswered, default to
reimagined and stamp ia-fidelity: reimagined (default).
Skip this question entirely when:
- The user's phrase already auto-pinned the axis (any trigger phrase in § 9 — "same IA, swap the surface" → verbatim; "what if we rethought the home page" → reimagined).
- An existing
direction.mdis being refined (the active tier holds unless the user explicitly re-pins).
The tier propagates to DESIGN.json.extensions.iaPriorities[].mutability:
locked under verbatim, movable under reimagined. Phase 4 stamps
the field; downstream prototype reads it.
Pair this question with the density-tuning question when both are unmoved — "two things to pin before we resolve: (1) density …, (2) IA fidelity …" — to stay within the two-question ceiling. If resolving register (brand vs product) is also outstanding, prioritise register first; defer one of density / ia-fidelity to the next turn.
Wait for the user's confirmation ("go", or a correction to the
plan) before moving on.
Phase 2 — Resolve the divergence inputs
Once the plan is confirmed, resolve the divergence-toolkit inputs
from skills/stardust/reference/divergence-toolkit.md. Before
rolling the seed, run the mode-detection precedence below to decide
whether the seed needs rolling at all.
Mode-detection precedence (run first)
The default mode for direct is determined by whether an extracted
brand surface exists with usable signal — not by the user's
freeform phrase alone. Stardust's primary use case is migrating an
existing site with a design refresh; "make it modern" / "stunning new
version" / "design fatigue cure" are migration-shaped asks. Treating
those phrases as rebrand triggers (rolling a fresh divergence seed)
produces output that is recognisably a different brand from the one
that asked for the refresh — a published failure mode. The
precedence below catches the common case as the default and reserves
divergence-seed rolls for explicit rebrand requests.
The precedence is asymmetric on purpose: the safer mode (Mode A — brand-faithful) catches ambiguous phrases, and the riskier mode (rebrand / full divergence-seed) requires the user to name it.
Site migration / refresh — DEFAULT. When the captured brand signal stamped in § Setup step 6 is
signal-strong, Mode A is active by default. The user's phrase moves expressive, distinctiveness, tone, and density axes inside Mode A — but palette and type are pinned to the captured surface, and the image-reuse contract (below) holds. Signature preservation also holds: a captured signature hero medium (background video / canvas / Lottie / scroll-motion, elevated as_brand-extraction.json#voice.heroMedium) or a site-wide motif is reproduced, not flattened — perskills/stardust/reference/ intent-dimensions.md§ 8b, and exempt from thesurprisebudget. Surface in the plan: "Brand-faithful mode active — palette and type pinned to the captured brand surface. Pass--rebrandto override."Rebrand — explicit opt-in. Mode A is overridden when any of the following triggers fire:
- The user's phrase contains an explicit rebrand signal: any of
rebrand,new brand,clean slate,start over,from scratch,replace the brand,not brand-faithful,editorial reimagination,completely new,redo the brand. - The
--rebrandflag is passed. - Captured signal is
signal-absent(no usable inheritance). Surface this case as an automatic switch with reason; the user can correct.
In rebrand mode, run the standard divergence-seed roll per "Default mode (no constraints)" below. Surface in the plan: "Rebrand mode active — full divergence-seed roll. Mode A bypassed because ."
- The user's phrase contains an explicit rebrand signal: any of
Brand-faithful + targeted exploration. When the user requests N variants (e.g. "3 variants", "4 directions") and Mode A is active, the variant role contract in § Multi-variant fork applies. Variant A is locked to strict Mode A (palette and type pinned, IA preserved, every improvements-list item applied). Variants B+ may amplify one captured trait (a motif, a photo treatment, an IA priority the current site underplays) but cannot:
- introduce a font outside the captured surface,
- introduce a color outside the captured palette,
- shift the register from PRODUCT.md.
Signal-thin fallback. When captured signal is
signal-thin, Mode A activates but warns: "Captured brand surface is thin — {reason}. Variants will inherit what is available; some dimensions will need to be filled by the divergence toolkit." The user may either re-run extract with a wider crawl (--cap 25) or proceed with reduced fidelity.
After mode-detection completes, run the existing mode definitions below (Mode A procedure, Mode B anchor-reference precedence, Mode C ground-family override) as applicable.
Mode A — Brand-faithful mode
Triggered automatically when the captured brand signal is
signal-strong and no rebrand-mode override fired (see
§ Mode-detection precedence above), OR when the user pinned both
type and palette (via explicit phrase: "keep typography and palette",
"preserve the existing brand", "brand-faithful redesign"; or via
constraints listing both as anchors).
In this mode, direct does not roll the type or palette
dimensions of the seed — they are already locked. Going through
the motions of font-deck and palette picks would be ceremony,
producing picked_by = "user-constraint" records that don't
reflect any real choice.
The mode procedure:
Record
font_deck.name = "brand-inherited"andfont_deck.picked_by = "user-constraint". Do not invokereference/palette-picker.md.Record
palette.source = "inherited from _brand-extraction.json"andpalette.picked_by = "user-constraint". Apply role-renaming per toolkit § 4 if the inherited names violate the brand-native rule (this is still useful — role renaming is presentational, not a divergence choice).Still roll the seed for the non-locked dimensions (decade, register, ground-family-as-applicable per Mode C below). These dimensions still drive divergence — the visual register and the era can shift even when type and palette are pinned.
Auto-emit the
brand_faithful_inversions[]block inextensions.divergenceperreference/direction-format.md§ Brand-faithful inversions. The list is mostly mechanical (see § Brand-faithful inversions in direction-format.md for the canonical patterns).Surface in the user report which dimensions had teeth and which were inert:
Divergence (brand-faithful mode): decade ✓ rolled → 2025-now craft ✓ rolled → Riso print register ✓ rolled → Memoir-adjacent ground-family inherited → stark-white (brand-native) font deck inherited → existing site stack palette inherited → existing 5-color setImage-reuse contract. Captured images are reused via their public URLs (or the local copies in
stardust/current/assets/media/written by extract Phase 2) at the same semantic position as on the source site. Hero stays hero. Story-tile portrait stays story-tile portrait. Program-card image stays program-card image. Background-motif image stays background motif.This is part of brand-faithful inheritance, not a separate content rule. A variant that swaps a captured subject portrait for a gradient placeholder, or moves the captured hero photo to a card thumbnail, erases the brand's most load-bearing trust signal — the named-people stories that almost every nonprofit / service-led site has spent years building.
The only legitimate ways to deviate from semantic position-preservation under Mode A:
- The captured image is broken (404, blocked by
referrer-policy, CORS-walled, or recorded withlocalPath: nulland adownloadError). - The brand-review surfaced the image as a tension (e.g.
T-stock-photographywhen added — flagging the captured image as obviously templated stock that the brand team would replace anyway). - The improvements list (Phase 2.5) explicitly notes a crop or positioning fix for that image — in which case the same image is reused at the corrected crop or position.
Synthesised placeholders are forbidden under Mode A. When a captured image cannot be reused, the prototype shape brief declares the gap explicitly and the rendered prototype shows a placeholder-with-signature element so reviewers see the gap rather than a fabricated photo.
- The captured image is broken (404, blocked by
Mode A is the default whenever § Mode-detection precedence step 1
applies (captured signal is signal-strong and no rebrand override
fires). It also activates explicitly when the resolved direction's
constraints list contains brand-faithful AND explicit type AND
palette anchors, OR when the user's phrase contains "keep
typography" / "preserve the palette" / equivalent. The agent
surfaces "Brand-faithful mode active" in the plan it shows the
user before executing — the user can correct (e.g. "actually let
me move the palette" or "actually rebrand it") before it locks.
Mode A+ — Brand-adjacent refinement (bounded, evidence-gated)
The middle tier between Mode A's hard pins and --rebrand. It exists
because the median redesign candidate is a site whose brand is right
but whose execution of that brand is part of the problem — a
generic system body face, a palette whose only accent fails contrast
on half its surfaces. Strict Mode A reproduces those weaknesses;
rebrand throws away the brand. Mode A+ authorizes bounded
upgrades, each gated on evidence:
- Same-classification type upgrade. When the improvements list (Phase 2.5) names the captured body or system face as a weakness with evidence (illegibility at captured sizes, a generic system stack where the brand deserves a voice, missing weights/axes the layout needs), the body face may be upgraded to a same-classification, deliverable face (humanist sans → humanist sans; grotesque → grotesque). The display face stays pinned — it carries the brand's recognition.
- Single-role palette recolor. When a specific captured color
fails contrast or hierarchy as evidenced (computed ratio cited,
or a
T-color-imbalancetension), that one role may be re-derived (deepened, re-weighted) while every other role stays pinned. New hues from outside the captured family remain forbidden.
Contract: each refinement is recorded in
DESIGN.json.extensions.divergence.brand_adjacent_refinements[] as
{ kind, captured, replacement, evidence, improvementsItem } — an
inversion-style audit entry citing the improvements-list item that
authorizes it. No evidence citation → no refinement. Mode A+ never
activates by default: it requires the qualifying improvements-list
item, and the plan surfaces each refinement explicitly ("body face
upgraded Arial → Hanken Grotesk per improvements #3; display face
pinned") so the user (or the hands-off record) sees exactly what
moved. Refinements do not run through reference research — their
justification is the captured weakness, not an external anchor.
Mode B — Anchor-reference precedence
When the user provides anchor references (Q1/Q2 answers like
"Pentagram nonprofits, This American Life, NYT Opinion longform"),
those references already imply seed dimensions. Pentagram
implies decade 2025-now editorial. This American Life implies
register Memoir-adjacent. Rolling those dimensions
deterministically and getting an accidental alignment is fragile —
the agent then has to retro-justify the alignment in
direction.md.
Agent-sourced anchors (default when the user provides none).
Mode B no longer waits for the user to name references: run the
reference-research procedure
(skills/stardust/reference/reference-research.md) to source 3–5
real-world anchors matched to the brand's category, register, and the
resolved direction movement. Researched anchors carry the same
implied-dimension weight as user-provided ones and are recorded as
picked_by: "reasoned: <anchor>" with the full citation in
extensions.divergence.references_used[]. User-provided references
always outrank researched ones on conflict. When research is
unavailable (ladder exhausted per reference-research.md § 1), Mode B
degrades to the deterministic roll for the un-implied dimensions.
Precedence rule:
- If anchor references are present, extract their implied
dimensions:
- Decade from era of the references (Pentagram → 2025-now; vintage Penguin → 1960s).
- Craft from medium of the references (TAL → audio editorial ≠ a craft per se, but Bandcamp → web-print hybrid; Riso-print anthology → Riso).
- Register from cultural reference set (Memoir, Tabloid, Catalogue, etc.).
- Ground-family from typical ground of those references (NYT Opinion → cream/parchment; Pentagram nonprofit → stark-white or monochrome-tint).
- Mark each implied dimension as
picked_by = "anchor-reference: <ref-name>". - Roll the seed only for un-implied dimensions.
- Record the anchor → dimension mapping in
extensions.divergence.seed.anchors[].
Mode B can compose with Mode A: anchor-references narrow the seed, brand-faithful constraints lock type/palette, the remaining roll is whatever the anchors didn't already imply.
Mode C — Brand-faithful ground-family override
When Mode A is active and the seed's ground_family roll
disagrees with the brand's existing ground (e.g. seed rolled
monochrome-tint but the brand's captured background is
#ffffff stark-white), the brand's ground wins. The seed roll is
not discarded — it informs the alt-section surface instead
(per divergence-toolkit.md § 4 Color roles). Record the override
in extensions.divergence.seed.ground_family.override with one
of three reasons:
brand-faithful— Mode A active and brand has a fixed ground.print-paper— manual override for print/paper categories (existing toolkit rule).direction-driven— seed wins (default; no override).
The three reasons are mutually exclusive; surface the chosen one in the user report.
Default mode (no constraints)
When neither Mode A nor Mode B applies (rebrand or thin-signal runs with no user anchors), the procedure is research-first, roll as fallback:
- Reference research first. Run
skills/stardust/reference/reference-research.mdto source anchors for the brand's category and the resolved direction, and derive the dimensions they imply (picked_by: "reasoned: <basis>"). This is Mode B's machinery applied to agent-sourced anchors — see § Mode B above. - Seed as fallback + tiebreaker. Roll the 4-dimension seed
(decade × craft × register × ground-family) per § 2 of the toolkit
only for dimensions research left un-implied, or entirely when
research is unavailable. The roll also remains available as a
deliberate convergence-breaker when the self-audit catches the
model reproducing its defaults despite research. Record
picked_byper dimension. - Font deck. Pick from the 10 named decks per § 3, letting the
researched anchors inform the pick the same way a seed implication
would (e.g. an editorial-serif anchor set →
serif-luxury). When neither research nor seed implies a deck, pick deterministically from the hash. - Palette. If the resolved direction moves the color-energy
axis or names the existing palette as part of the problem: derive
a full role-ramped palette (text, grounds, borders, accents,
states) from the primary researched anchor or a library candidate
— the library (
skills/direct/reference/palette-picker.md) is an anchor bank, not a closed menu; the model designs the ramp and validates every text-on-ground pair for WCAG AA before it lands in tokens (deterministic where it matters — math — not where it hurts — taste). Record the derivation basis inextensions.divergence.palette_source. Otherwise inherit the existing palette fromstardust/current/_brand-extraction.json, applying role-renaming per toolkit § 4 if the inherited names violate the brand-native rule.
Always run
- Anti-toolbox audit. Regardless of mode, run the self-audit (toolkit § 1 Enforcement + Self-audit) on the resolved direction. Each anti-toolbox hit needs a brand-specific justification or it is removed.
Record every resolution in DESIGN.json.extensions.divergence per
the v2 storage shape at the bottom of divergence-toolkit.md.
Phase 2.5 — Improvements list (Mode A only)
Before any variant is rendered downstream, write
stardust/prototypes/<slug>-improvements.md listing 3–5 specific
weaknesses observed in the captured site. This is the load-bearing
artifact for variant A: without it, "make it better" has no claim
the agent can defend, and each variant ends up inventing its own
"better" — producing rebrand-shaped output even with Mode A active.
The improvements list is the brief variant A renders against. It is not prescriptive (it does not declare visual targets); it is descriptive of the gap between the existing site and a competent 2026 execution of the same brand. Variant A's job is to close the gap; variants B+ honor the list as a floor (they may go further but not contradict it).
Skip this phase when the resolved mode is rebrand — the improvements list assumes brand-faithful inheritance, and a rebrand replaces the site rather than fixing it.
Audit reuse. When stardust/audit/<domain-slug>/audit.json
exists for this origin (written by stardust:audit), consume its
design findings as candidate improvements instead of re-deriving from
scratch — carry the finding IDs into each item's evidence citation.
The specificity bar below still applies to every carried item.
What goes in the list
The list draws from five categories. Items should be specific enough
that a downstream prototype shape brief can cite them by number.
- Dated patterns the design world has moved past. Specific: "centered hero with stock photo + double CTA in primary blue is the SaaS template circa 2019" — not "the hero feels dated."
- Cluttered IA, unclear hierarchy, weak CTAs, redundant sections. E.g. "home page has 4 different donor CTAs, each with a different verb (DONATE / GIVE / SUPPORT / CONTRIBUTE), fragmenting the conversion funnel."
- Contrast failures, accessibility gaps, density issues. Pull
from
brand-review.htmlTensions when present (T-color-imbalance,T-img-alt-empty, etc.). E.g. "Primary CTA#008192on white passes AA at 4.6:1 but the same teal on light-grey card surfaces drops to 3.1:1 — fails AA on those instances." - Cliché conventions the brand could move past while staying recognisably itself. E.g. "All headings render uppercase via CSS — the brand voice survives mixed-case headlines, and mixed-case reads as more current without changing identity."
- Missed opportunities the existing site doesn't capitalise on. E.g. "The captured photography of named program participants is excellent but the home page renders all 6 portraits as 280×180 thumbnails in a slick-slider; the photographs support full-bleed editorial treatment that would carry the trust signal far more effectively."
Specificity bar
A weakness is specific enough when it cites:
- a measurable observation (size, ratio, contrast value, count, or named tension ID) drawn from the per-page JSON, the brand-review, or the brand-extraction;
- the design pattern at fault (named, e.g. "centered hero + dual CTA");
- one concrete fix the variant A brief will apply.
"The hero needs work" fails all three. "Hero photo is cropped to 280×180 in a 1440-wide viewport when the captured source supports 16:9 full-bleed at 1440×810; variant A fix: render at full-bleed and move the headline to a left-anchored two-column overlay" passes all three.
Format
Markdown, with a _provenance frontmatter block per the artifact-map
convention. Each item is a numbered list entry with a category tag, a
weakness statement, and a one-line fix. Example:
<!--
_provenance:
writtenBy: stardust:direct
writtenAt: 2026-04-29T11:00:00Z
readArtifacts:
- stardust/current/_brand-extraction.json
- stardust/current/brand-review.html
- stardust/current/pages/<slug>.json
stardustVersion: 0.10.x
-->
# Improvements — <slug>
1. **[dated-pattern]** Centered hero with double CTA pair (DONATE +
LEARN MORE) is the 2019 nonprofit-template silhouette.
*Fix:* Replace with a left-anchored editorial composition; one
primary CTA, one secondary text-link.
2. **[ia-clutter]** 4 distinct donor verbs across the home page
(DONATE, GIVE, SUPPORT, CONTRIBUTE) fragment the funnel.
*Fix:* Pick one canonical verb (DONATE, per the CTA frequency
table); other instances become secondary "see all ways to give"
links.
3. **[contrast]** Brand teal on light-grey card surfaces resolves to
3.1:1 — fails WCAG AA. (See `T-color-imbalance` in brand-review.)
*Fix:* Reserve teal for white-ground only; use deepened teal
(#005a68) on grey surfaces.
4. **[cliché]** All headings render uppercase via CSS, including
long-form section openers ("OFFICIAL FOUR STAR CHARITY"). The
shout reads as urgency at first heading and as fatigue by the
third.
*Fix:* Mixed-case for headings ≥3 words; preserve uppercase only
for short imperative CTAs and eyebrow labels.
5. **[missed-opportunity]** Six named-participant portraits render
as 280×180 thumbnails in a slick-slider; the captured source
supports editorial-scale treatment.
*Fix:* Replace carousel with a 3-column grid; portraits at 4:5
aspect, 1:1 minimum 480px wide.
Stopping condition
If after reading the brand-review, the per-page JSON, and the brand-extraction the agent cannot name 3 specific weaknesses that meet the specificity bar, stop. Variant A has no brief; the "better" claim fails. See § Failure modes (d).
The agent should not rationalise — "the hero is dated" is not an item, "the typography could be more modern" is not an item. Genuine empty-list cases occur when the captured site is already at a high execution level on observable dimensions. In that case the honest answer is to surface the empty list and propose reduced scope (density-and-contrast adjustments only, or pivot to a single exploratory variant rather than three).
Phase 2.6 — Multi-variant fork (when N > 1)
When the user requests N variants (phrase contains "3 variants", "4 directions", or equivalent), variant slots are role-differentiated, not seed-differentiated. Each slot serves a distinct decision the customer is making — variants exist to de-risk a brand decision, not to fan out into N rebrand explorations.
The previous default behavior (each variant rolls a fresh divergence seed with anchor references picked per slot) produced what the internal review called "three rebrands" output: each variant was defensible standalone but none felt like the same brand. The variant role contract below addresses this directly.
Branch on ia-fidelity first
The variant role contract is ia-fidelity-aware. Read the tier
stamped in Phase 1 (per reference/intent-dimensions.md § 9 and the
IA-fidelity tuning step above), and branch:
Under ia-fidelity: verbatim — surface-tuning forks (A1/A2/A3).
Variant slots are A1 / A2 / A3 (or A1…An for N > 3), all surface-tuning forks of A's role. Each must differ from the others by ≥ 2 surface changes drawn from:
- type-weight choice (e.g. 400 vs 600 vs 800 display)
- type-scale ratio (e.g. 1.2 vs 1.333 vs 1.5)
- density tier (within the multi-audience floor in § 4)
- motion energy (still vs gentle vs animated)
- color-temperature move within the captured palette (warm-leaning vs cool-leaning vs neutral-balanced)
- spacing rhythm (compact vs even vs generous within the floor)
Forbidden differentiation axes under verbatim:
- section sequence
- section presence / absence
- IA priority
- layout strategy of a major section
A1 / A2 / A3 names indicate "different tunings of the same role,"
not different roles. When the user asks for "3 variants" while
ia-fidelity is verbatim, the fork produces A1 / A2 / A3
automatically; for N=1, just A.
The improvements list (Phase 2.5) still anchors variant A's role —
A1/A2/A3 all apply every item from <slug>-improvements.md. They
differ only in surface treatment of the same applied fixes.
The convergence detector in prototype/SKILL.md Discipline 10
becomes its inverse under verbatim: structural deltas
(section-sequence / presence / IA priority / layout strategy) are
forbidden, surface-only deltas are required.
Under ia-fidelity: reimagined — A + B + C role-differentiated.
Variant slots are A + B + C (or A + B + C + D…) per the variant role contract below. The contract is unchanged from the prior behavior: faithful + improvements / one captured trait amplified / different captured trait amplified.
The remainder of this Phase 2.6 (variant role contract, variant
differentiation contract, C-cliff failure mode) applies as written
under reimagined. Under verbatim, only the surface-fork rules
above apply; the variant role contract below does not.
Variant role contract
| Slot | Role | Brief |
|---|---|---|
| A | Faithful + improvements — "this is what your site should be tomorrow." | Same IA. Same section sequence. Same composition strategy. Apply every item from <slug>-improvements.md exactly — no extras, no embellishment, no creative reach. The brand team should react "yes, that's us, with the obvious fixes." This is the variant a risk-averse stakeholder green-lights. |
| B | One captured trait amplified — "what if we leaned into X?" | Pick one specific trait already in the captured brand surface — a motif underused in current execution, a photographic treatment the site doesn't fully exploit, an IA priority the current site underplays, a tonal register that survives in copy but not in layout. Justify in one sentence in the variant's shape brief: "This variant amplifies in service of ." |
| C+ | Different captured trait amplified — "what if we leaned into Y?" | Different from B by definition. Different captured trait. Different brand-personality move. Forbidden definitions: "B but more", "bolder fonts", "more empty space", "more brutalist", "more editorial". Each subsequent variant must be a defensible standalone proposition. |
Variants beyond C (D, E, …) follow the C+ contract — each amplifies a distinct captured trait, declared in the shape brief.
Surface forks of role-differentiated variants (B1/B2/B3, C1/C2/C3…)
Under ia-fidelity: reimagined, a variant's role (A, B, C, …) may
spawn surface forks — tunings of the same role across the
same surface axes that A1/A2/A3 use under verbatim. The pattern:
Bis "scroll cinema amplified" (the role).B1,B2,B3are surface tunings of B that all amplify scroll cinema, but vary along type-weight, type-scale, density, motion-energy, color-temperature, or spacing-rhythm.
This composes the verbatim-mode surface-fork machinery with the reimagined-mode role differentiation: the role contract binds the captured trait being amplified; the surface-fork delta governs how that trait reads in chrome.
Surface forks of role-differentiated variants are opt-in, not default. The default fork under reimagined is still A + B + C. Surface forks appear in two ways:
- Explicit user request: "design 5 variant directions for B" — the user asks for surface tunings of an existing role- differentiated variant. Render B1 / B2 / B3 / B4 / B5, each amplifying B's captured trait but with distinct surface tunings.
- Via
--add-variant <name>with a parent declared: e.g.,--add-variant B3after B exists. The parent inferred from the slot name's letter prefix (B3→ parentB). See § Add-variant mode → Per-field inheritance rules for the inheritance chain.
Surface forks of role-differentiated variants follow the same ≥ 2 surface-changes contract as A1/A2/A3 — the per-pair differentiation is surface-only (type-weight / type-scale / density / motion-energy / color-temperature / spacing-rhythm), with the captured trait being amplified held constant across the fork. Structural differentiation (section sequence / presence / IA priority / layout strategy) is forbidden between B and its surface forks B1/B2/B3 — the role IS the captured trait, and changing structure changes the role.
The variant-convergence detector in prototype/SKILL.md
Discipline 10 reads the variant's parent slot: when comparing
B vs B3 (parent–child surface fork), it applies the verbatim-style
inverse rule (surface deltas required, structural deltas
forbidden); when comparing B vs C (sibling role-differentiated
variants), it applies the reimagined-style rule (structural deltas
required).
The cap on motion-energy and other amplified surface axes is the parent role's cap — a B3 that amplifies motion-energy beyond B's ceiling must declare a cap override in its DESIGN.json extensions with a one-sentence rationale (e.g. "B3 raises B's motion choreography count from ≤ 3 to ≤ 5 to accommodate the loud- register tuning of scroll cinema"). The override must cite a captured-source basis or it refuses; cap overrides without a captured-source rationale produce surface drift instead of trait amplification.
Variant differentiation contract
Each pair of variants must differ by ≥ 2 substantive changes drawn from this set:
- section sequence (which sections appear in which order),
- section presence / absence (a section in one variant, not in another),
- layout strategy of a major section (e.g. hero is split-half vs. full-bleed-photo vs. type-led),
- IA priority (which audience leads the home — donor vs. recipient vs. volunteer for nonprofits; product vs. story for commerce).
Variants that fail the ≥ 2 changes test are rendered as the same variant under different chrome — "variants are barely different" is the published failure mode and is grounds for refusing render. See § Failure modes (b) — when only 1–2 captured traits are distinct enough to amplify, the agent surfaces this and proposes 1 or 2 variants rather than producing 3 weak ones.
The C-cliff failure mode
When defin
…(truncated)