# Direct

> Analyzes a website's current design and user intent to produce a structured redesign specification, including product and design documents, a design system JSON, and a reasoning trace.

- Skill: `adobe/direct` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add adobe/direct`
- Raw SKILL.md: https://api.skillmd.com/api/skills/adobe/direct/raw
- Safety review: CAUTION (external: skill-scanner PASS, skillspector CAUTION)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Design & Media, Coding & Dev Tools, Product & Planning, Design Systems, UI Design
- Tags: Brand Extraction, Design Direction, Design Specification, Design System, Product Spec, Redesign
- License: Apache-2.0
- Author: Adobe (https://skillmd.com/u/adobe), verified publisher
- Updated: 2026-07-06
- Page: https://skillmd.com/skills/adobe/direct

---


# 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 per `skills/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.json` is `signal-strong` (see § Setup
  step 5 and Phase 2 § Mode-detection precedence); pass `--rebrand`
  to 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 the `prepare-migration` orchestrator.
- `--add-variant <name>` — optional. Add a new variant against
  the existing direction without re-running intent reasoning or
  mode detection. Writes `DESIGN-<name>.{md,json}` at the
  project root and appends a per-variant section to
  `stardust/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

1. Run the master skill's setup
   (`skills/stardust/SKILL.md` § Setup) — hard impeccable dep check,
   context loader, state read.
2. Verify `stardust/state.json` exists and contains at least one
   `extracted` page. If not, stop and recommend
   `$stardust extract <url>` first.
3. 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 at
     `stardust/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 <donor-url>."*
   - `_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.
4. Read `stardust/direction.md` if present. If a prior direction
   exists and `--re-direct` was not passed, ask whether the user wants
   to refine the existing direction or replace it.
5. **Validate provenance on every in-scope page** (prep mode only).
   When `--prep` is active, call
   `validateProvenance(page)` per
   `skills/stardust/reference/state-machine.md` § Provenance
   validation on every `extracted` page in `state.json` before
   typing or module detection. Abort with the helper's error
   when any page lacks live-render evidence. Surface
   `Provenance OK on N pages` in the prep summary. Discovery-
   mode `direct` does not validate (it operates on a 5-page
   sample for which extract's own write-time refusal is
   sufficient).
6. **Classify the captured brand signal.** Read
   `_brand-extraction.json` and 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 in `type.headingFamily.name` or `type.bodyFamily.name`.
     This is the common case for any extracted commercial site.
   - `signal-thin` — palette has 2 colors OR no captured type family
     OR `type.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.notes` flags 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` (default `packed` per § 4).
- The register is `ambiguous` and 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.md` is 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.

1. **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 — per `skills/stardust/reference/
   intent-dimensions.md` § 8b, and exempt from the `surprise` budget.
   Surface in the plan:
   *"Brand-faithful mode active — palette and type pinned to the
   captured brand surface. Pass `--rebrand` to override."*

2. **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 `--rebrand` flag 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 <reason>."*

3. **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.

4. **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:

1. Record `font_deck.name = "brand-inherited"` and
   `font_deck.picked_by = "user-constraint"`. Do not invoke
   `reference/palette-picker.md`.
2. Record `palette.source = "inherited from _brand-extraction.json"`
   and `palette.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).
3. **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.
4. Auto-emit the `brand_faithful_inversions[]` block in
   `extensions.divergence` per
   `reference/direction-format.md` § Brand-faithful inversions.
   The list is mostly mechanical (see § Brand-faithful inversions
   in direction-format.md for the canonical patterns).
5. 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 set
   ```

6. **Image-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 with `localPath: null` and a
     `downloadError`).
   - The brand-review surfaced the image as a tension (e.g.
     `T-stock-photography` when 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.

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-imbalance` tension), 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:

1. 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).
2. Mark each implied dimension as
   `picked_by = "anchor-reference: <ref-name>"`.
3. Roll the seed only for **un-implied** dimensions.
4. 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.md` to 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_by` per 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 in
  `extensions.divergence.palette_source`. Otherwise inherit
  the existing palette from
  `stardust/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.

1. **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."*
2. **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."*
3. **Contrast failures, accessibility gaps, density issues.** Pull
   from `brand-review.html` Tensions when present (`T-color-imbalance`,
   `T-img-alt-empty`, etc.). E.g. *"Primary CTA `#008192` on 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."*
4. **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."*
5. **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:

```markdown
<!--
_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 <captured trait> in service of <brand personality move from PRODUCT.md>."* |
| **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:

- `B` is "scroll cinema amplified" (the role).
- `B1`, `B2`, `B3` are 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:

1. **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.
2. **Via `--add-variant <name>` with a parent declared**: e.g.,
   `--add-variant B3` after B exists. The parent inferred from the
   slot name's letter prefix (`B3` → parent `B`). 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)
