Design Variant Picker
Generate 3 HTML design previews before site build.
Skill metadata
| Source | Bundled (installed by default) |
| Path | skills/creative/design-variant-picker |
| Version | 1.0.0 |
| Author | VibeOS |
| License | MIT |
| Platforms | linux, macos, windows |
| Tags | design, variants, preview, landing, creative, html, tokens, gallery |
| Related skills | claude-design, popular-web-designs, design-to-code-loop, internet-starter, design-md, desktop-local-preview, cinematic-web |
Reference: full SKILL.md
The following is the complete skill definition that VibeOS loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
Design Variant Picker Skill
When a user loudly and clearly asks for a site (“landing for a coffee shop”,
“SaaS like Linear”, “calm yoga studio, lots of air”), do not scaffold a full
Next app first. Normalize the brief, generate three visually different HTML
preview stubs + tokens, let the user pick A/B/C, then lock DESIGN.md and
design/tokens.css before internet-starter / design-to-code-loop. Every
direction also fixes its graphic language and one motion density (quiet,
expressive, or cinematic) before implementation.
This skill owns procedure + scripts + templates. Brief Architect owns
references/briefs.yaml + references/tone-brand-map.md (8 loud scenarios +
tone→brand families). Fixture & QA owns fixtures/ and
tests/skills/test_design_variant_picker.py. Do not edit those paths from here.
Load canonical scenarios when normalizing a brief or writing offline tests:
skill_view(name="design-variant-picker", file_path="references/briefs.yaml")
and the mapping table in references/tone-brand-map.md.
When to Use
- User asks for a new landing / marketing site / portfolio with taste expectations
- Request names a brand mood (“like Stripe”, “not dark”, “no purple”)
- You need side-by-side design directions before committing to scaffold
- Desktop Design rail will read
manifest.json(phase 2); skill path works without UI
Prerequisites
claude-designfor taste and HTML artifact rulespopular-web-designswhen brief maps to a known brand familydesign-to-code-loopafter selection (not during variant generation)internet-starterafter selection if no app exists yetdesktop-local-previewor/previewto openpreview.html- Write access under project or profile home for
.vibeos/design-variants/
How to Run
End-to-end (operator):
- Normalize user text →
normalize_brief.py→ runbrief.md(+ optional JSON) - Generate variants A, B, C (default N=3; fourth only if brief is wide or user asks)
- Write
manifest.json; run validation + diversity gate - User picks variant →
select_variant.pylocks choice into project - Then apply tokens → scaffold first page — never before step 4
Scripts (from repo root):
python3 skills/creative/design-variant-picker/scripts/normalize_brief.py \
--text "Сделай лендинг для уютной кофейни, без неона" \
--out .vibeos/design-variants/run-<id>/brief.md \
--json-out .vibeos/design-variants/run-<id>/brief.json
python3 skills/creative/design-variant-picker/scripts/normalize_brief.py \
--seed-id local_coffee_salon \
--out .vibeos/design-variants/run-<id>/brief.md
python3 skills/creative/design-variant-picker/scripts/validate_manifest.py \
--manifest .vibeos/design-variants/run-<id>/manifest.json
python3 skills/creative/design-variant-picker/scripts/diversity_gate.py \
--run-dir .vibeos/design-variants/run-<id>/
python3 skills/creative/design-variant-picker/scripts/select_variant.py \
--run-dir .vibeos/design-variants/run-<id>/ \
--variant B \
--project-dir ./my-site
python3 skills/creative/design-variant-picker/scripts/ensure_variant_tokens.py \
--run-dir .vibeos/design-variants/run-<id>/
python3 skills/creative/design-variant-picker/scripts/latest_run.py \
--project-dir ./my-site
python3 skills/creative/design-variant-picker/scripts/mix_variant.py \
--run-dir .vibeos/design-variants/run-<id>/ \
--colors A --fonts C [--out-id H]
python3 skills/creative/design-variant-picker/scripts/archive_run.py \
--run-dir .vibeos/design-variants/run-<id>/
python3 skills/creative/design-variant-picker/scripts/reject_variant.py \
--run-dir .vibeos/design-variants/run-<id>/
python3 skills/creative/design-variant-picker/scripts/apply_design.py \
--project-dir ./my-site
# Day 14 MVP page (preferred)
python3 skills/creative/design-variant-picker/scripts/scaffold_landing_page.py \
--project-dir ./my-site
# Alternate template path (same pipeline stage)
python3 skills/creative/design-variant-picker/scripts/scaffold_page.py \
--project-dir ./my-site
Quick Reference
| Artifact | Purpose |
|---|---|
brief.md | Normalized brief for this run |
manifest.json | Variant list + metadata for UI / scripts |
A/preview.html | Self-contained hero + 1–2 sections |
A/tokens.css | :root CSS variables |
A/direction.md | Art direction, graphic language, motion contract, anti-patterns |
A/thumb.png | Optional gallery thumbnail |
selected.json | { "variant": "B", "locked_at": "…" } after pick |
design/tokens.css | Copied into project on select |
DESIGN.md | Copied from chosen direction.md on select |
| Script | Exit | Role |
|---|---|---|
normalize_brief.py | 0/1 | Loud text or --seed-id → brief.md / JSON |
validate_manifest.py | 0/1 | Schema + files exist |
diversity_gate.py | 0/1 | Variants differ enough |
ensure_variant_tokens.py | 0/1 | tokens.css + colors[] fallback (no screenshot) |
capture_variant_thumbs.py | 0/1/2 | Optional thumb.png (colors strip offline; Playwright optional) |
latest_run.py | 0/1 | Newest run-* with manifest under project |
select_variant.py | 0/1 | Lock + copy to project |
mix_variant.py | 0/1 | Hybrid variant: colors from one id, fonts from another |
archive_run.py | 0/1 | Move run dir to archived/ before regenerate |
reject_variant.py | 0/1 | Clear lock without archive / project copy |
apply_design.py | 0/1/2 | After lock: @import tokens into app CSS (2 = no app) |
scaffold_landing_page.py | 0/1/2 | After apply — preferred MVP page.tsx Hero→Footer (2 = missing lock) |
scaffold_page.py | 0/1/2 | After apply — alternate template path (page.tsx.tmpl; 2 = no app dir) |
| Default | Value |
|---|---|
| Variant count N | 3 (A, B, C) |
| Run folder | .vibeos/design-variants/run-<timestamp>/ |
| Post-select tokens | <project>/design/tokens.css |
| Post-select direction | <project>/DESIGN.md |
Procedure
1. Create run directory
.vibeos/design-variants/
run-<timestamp>/
brief.md
manifest.json
A/ preview.html tokens.css direction.md [thumb.png]
B/ …
C/ …
selected.json # after user picks
Use ISO-ish run id: run-20260721T120000Z. Paths in manifest.json are
relative to the run folder.
2. Normalize brief
Run normalize_brief.py on the user's loud request (or --seed-id for offline
seeds in references/briefs.yaml). Writes brief.md from templates/brief.md
and optional JSON with structured fields. Required fields:
| Field | Notes |
|---|---|
| industry | e.g. coffee shop, B2B SaaS, portfolio |
| audience | who lands on the page |
| tone | calm / bold / luxury / playful / technical |
| primary_cta | one main action |
| must_sections | hero + blocks user expects |
| forbid | hard negatives — colors, dark mode, card soup |
| reference_brands | Stripe, Linear, etc. if named |
| locale | ru / en |
Good: “Calm yoga studio, light only, no purple, hero = one headline + book class.”
Bad: Dropping forbid list; vague “modern and clean” with no industry.
If user named a brand: one variant should brand-match; others are mood
neighbors, not clones (see Agent A references/tone-brand-map.md when present).
3. Generate variants (default N=3)
For each id in A, B, C:
- Copy
templates/direction.md→<id>/direction.md(fill title, why, layout_keyword, fonts, palette, graphic language, and motion contract) - Write
<id>/tokens.csswith--color-*,--font-*, spacing tokens - Write
<id>/preview.html— self-contained HTML+CSS; hero + one follow section max - Optional thumbs:
python3 scripts/capture_variant_thumbs.py --run-dir <run>(--mode colors= offline palette strip;--mode playwright= preview screenshot). Always keepcolors[](≥3 hex) for swatches when thumbs are skipped. Runensure_variant_tokens.pyto backfill missingtokens.css/colors[]without network.
Do not run internet-starter, create app/page.tsx, or full Next scaffold
for each variant. Previews are lightweight HTML stubs only.
Load popular-web-designs templates when brand_ref is set. Load
claude-design for process and anti-slop. Use read_file / patch for files;
use browser_navigate or desktop /preview to verify previews open.
4. Hero budget (first screen)
One job on the hero — no clutter:
| Allow (pick one each) | Forbid in hero |
|---|---|
| Brand mark or wordmark | Fake metrics / “10k+ users” stats |
| One headline (H1) | Pill badge clusters |
| One primary CTA | Feature card grid |
| One visual anchor (photo, product, abstract shape) | Stock-photo clichés with overlay stickers |
| Optional one line of supporting copy | Purple/pink AI gradient blobs |
| Dashboard mockups with invented numbers | |
| More than two type sizes above the fold |
Sections after hero may add proof/features; keep preview.html short (hero + 1 block).
5. Anti-slop rules (all variants)
Across A/B/C you must vary direction, not just hue:
- No four “AI purple gradient” clones
- No glassmorphism-by-default, rainbow palettes, emoji decor unless brand uses them
- No left-border accent callout cards as the only layout idea
- No generic labels (“Insights”, “Scale”, “Optimize”) without real copy
- Respect
forbid[]from brief literally (if “no dark theme”, no variant is dark) - Layout keywords must differ across A/B/C (hard gate):
editorial,split,full-bleed,centered,asymmetric,grid,stacked,craft,soft-wellness,hybrid(mix) —diversity_gate.pyfails when all variants share one keyword - Motion density should differ when the brief permits it. Show
quiet,expressive, andcinematicbehavior instead of giving three static color variations the same choreography.
Forbidden clichés (Day 16 — never ship these in preview.html):
| Cliché | Why it fails taste |
|---|---|
| Purple / indigo / violet glow, neon mesh, pink→indigo blobs | Default AI “premium”; almost never brand-true |
| Fake metrics hero (“10k+ users”, “99.9%”, invented stars) | Lies in first screen; proof belongs below or omit |
| Card soup in hero (3–6 equal feature cards above fold) | Kills hero budget; features sit after |
| Pill badge clusters / floating stickers on photos | Noise; one visual anchor max |
| Glassmorphism frosted panels by default | Trend residue unless brand is glass/OS UI |
| Dark UI shell when brief says light / “no dark” | Violates forbid[]; Linear brand-match stays light |
| Rainbow accents + emoji decoration | Unless the brand literally uses them |
| Fake scarcity / countdown badges without real data | Fake urgency |
| Identical layout + font family + near-same palette | Caught by diversity gate — regenerate |
Good reference HTML (offline, no CDN): references/good-variants/editorial.html,
split.html, full-bleed.html.
6. Write manifest.json
Minimal shape (full schema: templates/manifest.schema.json):
{
"run_id": "run-20260721T120000Z",
"brief_path": "brief.md",
"created_at": "2026-07-21T12:00:00Z",
"variants": [
{
"id": "A",
"title": "Quiet Editorial",
"why": "Calm tone and airy type fit a wellness brief.",
"brand_ref": "original",
"preview_path": "A/preview.html",
"tokens_path": "A/tokens.css",
"direction_path": "A/direction.md",
"colors": ["#f7f5f2", "#2a2520", "#8b7355"],
"fonts": { "heading": "Fraunces", "body": "Source Sans 3" },
"layout_keyword": "editorial"
}
]
}
Each variant needs colors[] (≥3 hex for gallery swatches) or thumb_path.
Offline runs use colors[] only — no screenshot required. Validate:
python3 skills/creative/design-variant-picker/scripts/validate_manifest.py \
--manifest .vibeos/design-variants/run-<id>/manifest.json
7. Ensure tokens + colors (offline fallback)
Before validation or when thumbs are skipped:
python3 skills/creative/design-variant-picker/scripts/ensure_variant_tokens.py \
--run-dir .vibeos/design-variants/run-<id>/
Repairs missing/empty tokens.css from manifest colors[] + fonts, adds
--color-* when absent, and restores colors[] (≥3 hex) from existing CSS.
No network; thumb.png is optional when colors[] is present.
8. Diversity gate
Before showing the gallery to the user:
python3 skills/creative/design-variant-picker/scripts/diversity_gate.py \
--run-dir .vibeos/design-variants/run-<id>/
If exit 1 — fix in this order (Day 16 procedure):
- Same
layout_keywordon all variants → assign distinct skeletons first (editorial/split/full-bleed/centered). Do not only recolor. - Pair too similar (≥2 of layout / font / palette) → change the closest variant’s layout_keyword and heading font and ≥2 palette hexes.
- Re-run the gate. Optional:
--strict-layoutsfor CI-style “all distinct + canonical keywords”. Thresholds:diversity_gate.py --help.
8b. Desktop bridge (after variants exist)
After writing run artifacts and diversity_gate.py exits 0, tell the user
how to open the gallery — do not scaffold Next or call internet-starter
yet.
- Resolve the run directory (absolute path):
python3 skills/creative/design-variant-picker/scripts/latest_run.py \
--project-dir /path/to/project
- Print in chat (one short block):
- Absolute path to the run directory
- Suggest opening the Design tab in Desktop, or slash:
/designor/design load <absolute-run-dir> - One machine-parseable marker line (Desktop may parse later):
VIBEOS_DESIGN_VARIANTS_RUN=/absolute/path/to/run-20260721T120000Z
Example assistant message:
Three design directions are ready (A/B/C). Open the Design tab in the right
rail (or use the Open variants control in chat), or run
`/design load /Users/you/my-site/.vibeos/design-variants/run-20260721T120000Z`.
VIBEOS_DESIGN_VARIANTS_RUN=/Users/you/my-site/.vibeos/design-variants/run-20260721T120000Z
Hard rule (no scaffold before select): do not run internet-starter,
create app/page.tsx, or start a full Next scaffold until the user selects a
variant (select_variant.py or Desktop Select). Variants + Design gallery
only — scaffold is step 10, never step 8.
9. User selection → lock
After explicit user choice (chat, Desktop Design tab, or slash):
python3 skills/creative/design-variant-picker/scripts/select_variant.py \
--run-dir .vibeos/design-variants/run-<id>/ \
--variant B \
--project-dir /path/to/project
Writes selected.json, updates manifest.selected, copies:
<variant>/tokens.css→<project>/design/tokens.css<variant>/direction.md→<project>/DESIGN.md
Re-running select is idempotent (overwrites lock and project files).
10. After lock only (Day 13 — apply into a real app)
Run this only after select_variant.py (or Desktop Select) has written
selected.json, <project>/design/tokens.css, and <project>/DESIGN.md.
Do not start apply while the gallery is still open for pick / mix / reject.
10.1 Detect whether an app exists
Look for a CSS entry under --project-dir (first match wins):
| Candidate path | Typical stack |
|---|---|
app/globals.css | Next.js App Router |
src/app/globals.css | Next.js App Router (src/) |
styles/globals.css | Next / CRA-style |
src/styles/globals.css | Vite / CRA with src/ |
app/global.css | Alternate Next naming |
Offline stub for scripts/tests:
fixtures/next-app-stub/app/globals.css (minimal :root shell).
App present = at least one of the paths above exists as a file.
No app = none found (empty project, tokens-only lock, or not scaffolded yet).
10.2 If no app — ask before scaffold
- Tell the user there is no app CSS entry yet.
- Propose running
internet-starterto scaffold (Next/SPA) into the same--project-dir(or a path they choose). - Do not auto-run
internet-starterwithout explicit user consent. - After they confirm and scaffold finishes, re-check §10.1, then continue to
§10.3. Re-run
select_variant.pyonly ifdesign/tokens.css/DESIGN.mdwere wiped by scaffold (normally keep them).
10.3 Apply locked tokens (apply_design.py)
When an app CSS entry exists:
python3 skills/creative/design-variant-picker/scripts/apply_design.py \
--project-dir /path/to/project
Contract (script under scripts/apply_design.py):
- Requires locked
<project>/design/tokens.css(from select). Missing → exit 1. - Detects CSS entry via the paths in §10.1. None → exit 2 and print an
internet-starter/ scaffold hint — never scaffolds Next itself. - On success (exit 0): injects an idempotent block into
globals.css:
/* vibeos-design-tokens:start */
@import url("../design/tokens.css");
/* vibeos-design-tokens:end */
Re-runs replace that span only (no duplicate imports).
- When fonts can be derived from
--font-*or a<link>comment in tokens, writes<project>/design/fonts.htmlfor the operator to paste intolayout.tsx/ HTML head (does not auto-edit React layout). - Optional
--jsonfor machine-readable result.
Fallback if the script is unavailable: design-to-code-loop (read_file +
patch) — same order, still only after select.
10.4 Verify select artifacts (already done at lock)
Confirm these exist before treating apply as complete:
| Artifact | Source |
|---|---|
<project>/design/tokens.css | Copied by select_variant.py |
<project>/DESIGN.md | Copied from chosen direction.md |
Optional formal polish of DESIGN.md via design-md is fine but not
required for Day 13 — select already wrote the direction file.
10.5 Stop here — Day 14 builds the page
Do not invent a full cinematic site in this step. After apply exits 0,
continue to §12 (scaffold_landing_page.py preferred) for the MVP landing
page, then preview. Optional polish via cinematic-web /
cinematic_landing_scaffold is not required for MVP.
Day 13 success = tokens live in app CSS. Day 14 success = first page.tsx
under locked direction.
11. Day 11 — More variants, mix, reject (Desktop /design)
When the user wants another batch of directions, a hybrid, or to back out of a choice without locking:
| User intent | Desktop slash | Script / action |
|---|---|---|
| Regenerate A/B/C | /design more | Archive old run, then new run (below) |
| Mix palette + type | /design mix A C | mix_variant.py --colors A --fonts C |
| Clear selection / don't lock | /design reject | reject_variant.py (clear lock only; ≠ archive) |
Regenerate flow (operator):
- Archive the current run so
latest_run.pyand Desktop load a clean tree:
python3 skills/creative/design-variant-picker/scripts/archive_run.py \
--run-dir .vibeos/design-variants/run-<id>/
Moves to .vibeos/design-variants/archived/run-<id>-<timestamp>/.
-
Create a new
run-<timestamp>/, normalize brief, generate fresh A/B/C, validate + diversity gate (sections 2–8). -
Emit the Desktop bridge marker again:
VIBEOS_DESIGN_VARIANTS_RUN=/absolute/path/to/run-20260721T140000Z
Suggest /design load <path> or open the Design tab. Do not scaffold
Next until the user selects again.
Mix flow:
When the user likes colors from A but typography from C (or chat says “mix A and C”):
python3 skills/creative/design-variant-picker/scripts/mix_variant.py \
--run-dir .vibeos/design-variants/run-<id>/ \
--colors A --fonts C
Writes hybrid folder H/ (override with --out-id) with:
tokens.css—--color-*from--colors,--font-*from--fontsdirection.md— explains hybrid;layout_keyword = hybridpreview.html— self-contained hero stub using hybrid tokens- Updated
manifest.jsonentry (replaces existing sameout-id)
Re-run diversity_gate.py — hybrid should still pass vs A/B/C when sources differ.
Desktop: /design mix A C should invoke the same script on the loaded run.
Reject flow:
Reject means: clear a tentative selection — do not lock, do not copy
into project design/tokens.css / DESIGN.md. Reject ≠ archive the whole run.
python3 skills/creative/design-variant-picker/scripts/reject_variant.py \
--run-dir .vibeos/design-variants/run-<id>/
Deletes selected.json if present and removes manifest.selected (same fields
select_variant.py writes). Leaves A/B/C (and hybrid) folders intact.
- Run
reject_variant.pyon the loaded run. - Tell the user the gallery is unlocked; they can pick another variant or
/design mix. - Optionally archive the whole run if they asked to “start over” (
archive_run.py).
Do not call select_variant.py on reject. Do not run internet-starter after reject.
12. Day 14 — Scaffold MVP landing page
After select → apply succeeds, generate a first real page that follows
the locked direction (not a random other site). Prefer
scaffold_landing_page.py. Do not require cinematic-web for MVP.
| Who | Script | Notes |
|---|---|---|
| Preferred MVP | scaffold_landing_page.py | CLI + Desktop /design scaffold (intended) |
| Alternate | scaffold_page.py | templates/page.tsx.tmpl markers path |
12.1 Prerequisites
Confirm:
| Artifact | From |
|---|---|
<project>/design/tokens.css | select_variant.py |
<project>/DESIGN.md | select_variant.py (chosen direction) |
App CSS has token @import | apply_design.py (exit 0) |
Optional: latest run brief.md under .vibeos/design-variants/ (or pass
--brief / --run-dir) for brand, CTA, and must-have section mapping.
12.2 Run scaffold
python3 skills/creative/design-variant-picker/scripts/scaffold_landing_page.py \
--project-dir /path/to/project
# Alternate template path
python3 skills/creative/design-variant-picker/scripts/scaffold_page.py \
--project-dir /path/to/project
Contract (scaffold_landing_page.py):
- Missing
DESIGN.mdordesign/tokens.css→ exit 2 (select+apply first). - Existing
page.tsxwithout--force→ exit 1 (no silent clobber). - Writes
app/page.tsxorsrc/app/page.tsx(createsapp/if needed). - Styles only via
var(--color-*)/var(--font-*)— no hardcoded purple slop. - Prints the written path on stdout (exit 0).
Alternate (scaffold_page.py + templates/page.tsx.tmpl):
- Missing tokens/DESIGN → exit 1; no
app//src/app/→ exit 2. - Markers
vibeos-scaffold-page:start/end; refuses non-trivial overwrite without--force.
12.3 Section mapping (Hero → Footer)
Map brief must_sections (and DESIGN.md title/why) to canonical blocks.
Defaults when brief is sparse: Hero, Features, Proof, CTA,
Footer. Full keyword table: references/section-map.md.
| Section | Role |
|---|---|
| Hero | Brand, one headline, one CTA, one visual job |
| Features | 2–3 value props (not hero clutter) |
| Proof | Trust / quote / social proof |
| CTA | Repeat primary action |
| Footer | Hours / contact / locale envelope |
12.4 Motion + prefers-reduced-motion
Scaffold uses CSS-only fade/stagger (2–3 intentional reveals). Must include:
@media (prefers-reduced-motion: reduce) {
/* disable / simplify animations — no Framer Motion required for MVP */
}
12.5 Preview
After scaffold exits 0:
- Start / open the app via
desktop-local-previewor Desktop/preview - Optional smoke:
site-page-analyzevs brief expectations - Operator may edit copy freely after first generation
Live Desktop /preview smoke is operator / Agent B — do not claim done offline.
12.6 Optional polish — cinematic-web (not MVP)
Golden task cinematic_landing_scaffold (cinematic-web /
scaffold_cinematic.py) remains ready as optional polish after
design_variant_picker_scaffold_offline. Not required for Day 14 MVP.
Pipeline: select → apply → scaffold_landing_page → preview (→ optional cinematic-web).
Pitfalls
Forbidden clichés / anti-slop
Regenerate any variant that hits these — they read as generic AI output, not brief-specific design:
| Cliché | Why it fails | Fix |
|---|---|---|
| Purple glow / purple–indigo gradient default | Instant “AI slop” signal; ignores brief forbid[] | Warm neutrals, brand-true accent, or brief reference palette |
| Fake metrics in hero (“10k+ users”, invented stars) | Erodes trust; local/wellness briefs never asked for stats | One real headline + one CTA; proof lives below fold |
| Card soup / pill clusters in hero | Hero does four jobs at once; nothing reads | One visual anchor + one headline + one primary CTA (see §4 hero budget) |
| Identical layout across A/B/C | Gallery compares hue swaps, not directions | Distinct layout_keyword per variant (editorial, split, centered, full-bleed) |
| Dark UI when brief forbids dark | Violates explicit forbid[] (e.g. yoga, coffee shop) | Light surfaces, soft contrast; re-read brief before writing CSS |
Taste references (not a run): references/good-variants/ — open locally before generating.
- Scaffolding Next×3 before pick — expensive, slow, violates product contract
- Auto-running
internet-starterafter lock — ask first; no silent scaffold - Applying tokens before select —
apply_design.pyneeds lockeddesign/tokens.css - Scaffolding page before apply — run
/design scaffoldor either scaffold script only after apply - Requiring cinematic-web for MVP — optional follow-on polish; Day 14 =
locked-direction
page.tsx - Ignoring forbid[] — user said “no dark”; all variants must comply
- Same layout + font + palette — diversity gate exists; fix before user sees gallery
- Full page in preview.html — hero + one section is enough for comparison
- Skipping manifest validation — Desktop rail and tests expect stable schema
- Editing Agent A/C paths — briefs.yaml, fixtures, tests are out of scope here
- Mid-conversation cache break — defer
/design variantsskill load to turn boundary when possible; do not swap toolsets mid-turn for variant generation
Verification
- Run folder matches layout in section 1;
brief.mdfilled - Exactly 3 variants by default (A/B/C) unless user asked for more
- Each
preview.htmlopens locally (file or static server) and shows distinct direction -
validate_manifest.pyexits 0 -
diversity_gate.pyexits 0 - After generation: chat shows run path +
/designhint +VIBEOS_DESIGN_VARIANTS_RUN=… -
latest_run.py --project-dir …exits 0 when a run exists -
select_variant.pywritesselected.json+ projectdesign/tokens.css+DESIGN.md - No full Next scaffold created before select
- After lock: detect
globals.css(or ask forinternet-starterwith consent) -
apply_design.py --project-dir …exits 0 when app CSS exists (or manualdesign-to-code-loopmerge); app CSS contains locked--color-*/--font-* - Day 14:
scaffold_landing_page.py --project-dir …writesapp/page.tsx(orsrc/app/page.tsx) with Hero/Features/Proof/CTA/Footer, token CSS vars, andprefers-reduced-motion(seereferences/section-map.md) - Alternate OK:
scaffold_page.py+page.tsx.tmpl(same pipeline stage) - Preview via
desktop-local-preview//preview(operator) or offlinesite-page-analyzeon fixture — shows locked direction - Brief
forbidconstraints visible in all previews -
mix_variant.pyadds hybridH/anddiversity_gate.pystill exits 0 -
archive_run.pymoves run toarchived/; regenerate uses a newrun-* - Agent C tests pass:
scripts/run_tests.sh tests/skills/test_design_variant_picker.py -q