Design-dna — the prospect's colors, our rigor
This skill is the shared design interface of signal-forge. It produces one palette per
prospect as a versioned token contract (sf-tokens/1.0); pitch-deck, demo-forge, dashboards,
docs, workshop-kit, and account-copy consume design/tokens.css and define no colors of
their own. Get this wrong and every downstream artifact is wrong. Read
../forge/references/design-rigor.md (the hybrid rule + QA ladder) and
../forge/references/evidence-rules.md (no invented values) — they govern this output.
Full craft lives in three references (read the one you're in):
references/token-schema.md— THE contract: every--sf-*variable, its semantics, constraints, the header format, dark-mode names, and the backward-compatibility rule.references/extraction-protocol.md— fetch surfaces, frequency×prominence tally, identity-core rules, provenance format, the failure ladder, per-client caching.references/harmonization-tree.md— the decision tree, ramp generation, WCAG matrix procedure, identity-preservation check, and the CETI house-fallback palette.
Typed input slots (fill at intake; UNKNOWN is legal, never invent)
PROSPECT_URLS: list[url] | UNKNOWN # brand surfaces to extract from
BRAND_ASSETS: list[path] | none # supplied logos / brand PDF / guideline deck (outrank the live site)
CLIENT_SLUG: str # per-client isolation + cache key
PRIOR_TOKENS: path | none # existing tokens.css → re-extraction (rebrand) path
REGISTER: {rigor|soft} | rigor # soft ⇒ prefer owala-colors engine; else dict-color/Wada
PROSPECT_URLS = UNKNOWN and no BRAND_ASSETS ⇒ run the failure ladder; if it dead-ends,
ship the house-fallback and log it (never guess a hex).
Typed outputs
design/tokens.css # sf-tokens/1.0 header + :root (light) + [data-theme="dark"]; every --sf-* name present
design/palette.md # provenance table · light WCAG matrix · dark WCAG matrix · identity-preservation statement
UNKNOWNS.md (append) # any failed fetch / house-fallback, routed "design-dna"
FACTORY/atoms.md (append) # ≥1 atom: palette outcome and/or new extraction route
Artifact specs + acceptance checklists
design/tokens.css — measurable spec:
- Opens with the exact header block from
token-schema.md §1(schema:,client:,source:,palette:,provenance:,generated:,dark:lines filled). - Defines every name in
token-schema.md §8— no omissions, no extras. -
--sf-leadaliases--sf-lead-500; ramp 50→900 is monotonically darkening. -
[data-theme="dark"]rebinds the same names (no-darkvariables). - No hardcoded hex outside
:root/[data-theme="dark"]; shadows tint to anchor, not black.
design/palette.md — measurable spec:
- Provenance table:
| hex | role observed | source URL | surface | accessed |— one row per shipped color; derived colors cite their curated palette + combination name. - Light contrast matrix table: every required pair (
harmonization-tree.md §D) with ratio + AA verdict; zero failures. - Dark contrast matrix table: same pairs against the dark twin; zero failures.
- Identity-preservation statement (side-by-side): extracted lead → shipped
--sf-lead, with ΔH (≤8°), chroma, and lightness deltas, ending "same color, better".
Pipeline (stages with blocking predicates)
Frame
Read the three references. Fill the input slots. Decide the path: extract (URLs/assets
present) or house-fallback (ladder dead-ends). If PRIOR_TOKENS exists and the brand is
unchanged within the re-extraction cadence (90 days), reuse the cache; a rebrand signal
forces full re-extraction.
Predicate F: input slots filled; path chosen; cache decision logged.
Do
- Extract (
extraction-protocol.md): fetch site CSS incl. linked stylesheets, inline styles, SVG logo fills,theme-color, favicon/manifest, hero. Tally colors by frequency×prominence (logo/CTA/header outweigh body). Determine the 1–3 identity-core colors. Write a provenance row for every kept color.Predicate D1: every candidate color has a source URL + accessed date, or it is dropped.
- Harmonize (
harmonization-tree.md): assess core quality (muddy / clashing / too many / mono); snap onto the nearest Wada combination (dict-color) or Owala cast (owala-colors) perREGISTER; assign lead/support/anchor/surfaces/text/semantic; generate the OKLCH ramp; pair the dark twin (dark-mode-pairingmethod).Predicate D2: every color is sourced (cited) or from a named curated palette (cited); no extracted core color moved > 8° in hue.
- Audit (
harmonization-tree.md §D): build the WCAG 2.2 AA matrix over the pairs artifacts actually use; remediate failures lightness-only until zero; repeat for dark. Useowala-design:wcag-contrastwhen installed, else compute ratios directly.Predicate D3: zero failing pairs in light AND dark.
Review
Run the identity-preservation check (§E) and the acceptance checklists above. Confirm one
palette per prospect (no artifact defines colors). Confirm the header + provenance are
complete. This maps to the Contrast pass of the QA ladder in design-rigor.md.
Predicate R: both checklists pass; identity statement honestly reads "same color, better".
Capture
Emit tokens.css + palette.md. Append any fetch failure / fallback to UNKNOWNS.md.
Mint ≥1 atom to FACTORY/atoms.md via the mint-atoms skill (a run that mints none did not
complete): type: template (a palette outcome / harmonization that landed), and/or
type: triage-route (a new source that resolved a hard extraction). Trace any human color
correction to the line that allowed it (see Feedback below).
Predicate C: outputs written; ≥1 atom minted; fallbacks logged.
Scale-native operation (N clients)
- Per-client isolation — extraction/harmonization for client A never reads client B's
cache or tokens. The only cross-client shared assets are the schema (
token-schema.md) and the house-fallback palette (a constant). Runs live underprospects/<slug>/design/. - Token caching — raw candidate tallies cache under
design/.extract-cache/<slug>.json, keyed by slug + domain + fetch-date. - House-token reuse — neutrals (surfaces/text/anchor) may reuse the house default only
when the brand supplies nothing better, cited as
CETI house default. - Re-extraction cadence — 90 days by default; a changed
theme-color, new logo hash, or "they rebranded" invalidates the cache → re-fetch → newtokens.css(values change, names and schema do not) → regenerate dependent artifacts, never hand-patch. - Schema stability — because artifact skills bind only to
--sf-*names, a per-client value change ripples through automatically; only a rename breaks them (major version bump + migration note).
Core invariants (H8)
- Every shipped color is sourced from the prospect's materials (cited) or from a named curated palette (cited) — Wada / JIS / Owala / CETI house default. No invented values.
UNKNOWNinputs and failed extractions are logged (UNKNOWNS.md + tokens headerclient: house-fallback), never silently defaulted.- One palette per prospect. Artifacts consume
--sf-*; none define colors. - Extracted identity core survives with ΔH ≤ 8° — recognizably their color.
- Contrast fixes are lightness-only; hue is never moved to pass an audit.
DONE predicate
A design-dna run is DONE when: tokens.css defines every token-schema.md §8 name with a
complete header · palette.md carries a full provenance table + light and dark WCAG
matrices with zero failures · the identity-preservation statement holds (ΔH ≤ 8°) · every
color is sourced or curated-and-cited · any fallback is logged in UNKNOWNS.md · ≥1 atom is
minted.
Refusal conditions (H9)
Refuse to emit / ship, and surface the blocker, when:
- A required contrast pair fails AA in light or dark and cannot be fixed lightness-only without breaking recognizability — do not ship failing contrast pairs.
- A color would be invented ("brandish" guess) to fill a gap — run the ladder or ship the logged house-fallback instead. Never invent brand colors.
- Harmonization would move an extracted core hue > 8° — that is a different brand.
- An artifact requests a
var(--sf-…)not in the schema — fix the schema (versioned) or the artifact; do not let an undefined token ship.
Feedback tracing (H10)
When a human corrects the palette ("wrong blue", "too muted", "that's not our green"), route
through mint-atoms: log the correction dated with the run slug, then trace it to the line
that allowed it — a mis-weighted prominence rule (extraction-protocol.md §2), a
harmonization bound (harmonization-tree.md §A), or an identity mis-read (§3). Fix at the
line, bump the reference if the fix generalizes, and regenerate tokens.css +
dependent artifacts from the corrected palette — never hand-patch a hex in one artifact.
Skill composition
Prefer when installed; degrade to hand-computation to the same standard: dict-color
(Wada/JIS harmony engine), owala-design:owala-colors (soft register), …:design-tokens
(OKLCH token emit), …:dark-mode-pairing (dark twin), …:wcag-contrast (matrix audit),
…:layout-rhythm / …:motion-curves (spacing + motion token values).