mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-18 00:56:30 +03:00
skill v4.0.0-alpha.9: daily-driver core + mandatory new-work playbook
Architecture per Paul: impeccable is primarily a daily driver on existing codebases; the always-loaded core should serve that 90% path, not carry the full generative arsenal on every invocation. SKILL.md now holds brief-wins, existing-worlds (the headline path), the four visitor modes, the full craft floor, and a hard gate: new identity work (greenfield, or a redesign discarding the current look) MUST read reference/new-work.md before any design decision. That file carries the generative playbook (seed, subject grounding, plan/self-check/signature, hero-thesis, everything-bold, prove-don't-claim, color commitment, calibration, persuade type/imagery). context.mjs enforces the gate mechanically: NEW_WORK directive when no PRODUCT.md/DESIGN.md exists, and the old mandatory register-file read is replaced by a REGISTER family hint. No surfaces: map anywhere; mode is derived per task. Gate compliance is measurable via skillEvidence.directSkillFileReads. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
bf2dd7ec13
commit
0fde0850cf
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: impeccable
|
||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||
version: 4.0.0-alpha.8
|
||||
version: 4.0.0-alpha.9
|
||||
---
|
||||
|
||||
Designs and iterates production-grade frontend interfaces. Real working code, committed design choices, exceptional craft.
|
||||
@@ -13,27 +13,13 @@ Approach every design task as the design lead at a small studio known for giving
|
||||
1. Run `node .agents/skills/impeccable/scripts/context.mjs` once per session (if the runtime shows this skill's loaded base directory, run `node <skill-base-dir>/scripts/context.mjs`; keep cwd at the user's project). It prints the project's PRODUCT.md and DESIGN.md when they exist; follow what it prints, including any `UPDATE_AVAILABLE` directive (ask once, never block). If it reports `NO_PRODUCT_MD`: for `init`, `teach`, `craft`, `shape`, or wording that clearly maps to a from-scratch build flow, divert into `reference/init.md` first, **unless no user can respond** (a one-shot or automated run, or the user said not to ask): then write your own one-paragraph understanding of the product, audience, and the page's job from the brief and continue. For scoped evaluate/refine/fix requests against existing code, never divert into init; the existing code is the context.
|
||||
2. If the user invoked a sub-command (`audit`, `polish`, `live`, ...), read **`reference/<command>.md`** (the `.native` variant from the Commands table when the platform is `ios`/`android`/`adaptive`) and follow it. On unattended runs, `craft` and `shape` collapse into this file's process: decide, record each decision in one line, build, self-review.
|
||||
3. Read at least one project file (CSS / tokens / theme / a representative component) to learn what world you're in. If PRODUCT.md's `## Platform` is `ios` or `android`, also read `reference/<platform>.md` (`adaptive` reads both).
|
||||
4. If the project is brand-new (no committed tokens, fonts, or brand colors found in step 3), run `node .agents/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed breaks your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this step entirely when step 3 found committed brand colors: identity-preservation wins.
|
||||
|
||||
## How to design
|
||||
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this file warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this skill warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
|
||||
**Existing worlds are sacred.** When the surface already has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside it: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Treat the task as new identity work only when nothing committed exists, or when the user asks for a redesign that discards the current look. A redesign is new work: derive the concept from the subject and the brief, not from the incumbent page's structure or styling.
|
||||
**Existing worlds are sacred.** Most of impeccable's work happens inside a site or app that already exists. When the surface has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside that world: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Inventing parallel colors, fonts, or styles on an existing surface is a defect, not creativity.
|
||||
|
||||
**Ground it in the subject.** Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
**Plan, self-check, build.** Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
**Commit.** Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
**Calibration.** AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
**New identity work reads the playbook first.** When nothing committed exists (greenfield, or a codebase with no real tokens or chosen faces), or the user asks for a redesign that discards the current look, you MUST read [reference/new-work.md](reference/new-work.md) before making any design decision. Not optional, not skippable under time pressure: producing new identity without it yields the generic default this skill exists to prevent. A redesign is new work; derive the concept from the subject and the brief, not from the incumbent page's structure or styling. `context.mjs` prints this directive when it detects the situation. Scoped fixes inside an existing world don't need the playbook; the craft floor below governs them.
|
||||
|
||||
## Craft floor
|
||||
|
||||
@@ -57,7 +43,7 @@ Calibration for this provider:
|
||||
|
||||
Name the visitor's mode before designing; the page's grammar follows from it, and most ruined pages are one mode wearing another mode's grammar. The brief and the surface decide the mode. PRODUCT.md's `register` field names the family (`brand` covers Persuade and Experience; `product` covers Operate and Read), and `reference/brand.md` / `reference/product.md` carry extended depth for the two families.
|
||||
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans.
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Briefs that imply imagery must ship real, verified imagery; a colored rectangle where a photo belongs reads as incomplete. New Persuade surfaces take their typeface procedure and reject list from [reference/new-work.md](reference/new-work.md).
|
||||
|
||||
**Operate** (app UI, dashboards, admin, tools; design SERVES the task). A person getting something done: density, scanability, and consistency outrank expressiveness. These surfaces earn trust by feeling native to their platform: system font stacks and workhorse UI faces are legitimate and often correct here (the Persuade reject list does not apply). The brand lives in the details: focus states, empty states, microcopy, one owned accent.
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# New identity work
|
||||
|
||||
You are reading this because nothing committed exists yet (greenfield), or the user asked for a redesign that discards the current look. Either way the task is the same: invent a visual identity that could not be mistaken for anyone else's, and build it to the craft floor. SKILL.md's rules all still apply; this file is the process that produces the identity.
|
||||
|
||||
## Seed
|
||||
|
||||
If the project is brand-new (no committed tokens, fonts, or brand colors found in the code), run `node .agents/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed exists to break your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this entirely when the code already has committed brand colors: identity-preservation wins.
|
||||
|
||||
## Ground it in the subject
|
||||
|
||||
Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
## Plan, self-check, build
|
||||
|
||||
Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
## Commit
|
||||
|
||||
Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
## Type and imagery for new Persuade and Experience surfaces
|
||||
|
||||
Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans. (For Operate and Read surfaces the opposite holds: system stacks and workhorse UI faces are legitimate and often correct.)
|
||||
|
||||
Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Verify stock URLs resolve before shipping them.
|
||||
|
||||
## Calibration
|
||||
|
||||
AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
|
||||
Before finishing, verify against SKILL.md's craft floor and run the detector; a bold page that ships mechanical defects is not done.
|
||||
@@ -904,6 +904,10 @@ async function cli() {
|
||||
'reference/init.md and write PRODUCT.md first; for any other (scoped) ' +
|
||||
'command against existing code, proceed using the code as context and ' +
|
||||
`offer \`${IMPECCABLE_COMMAND} init\` as a suggestion (do not block).`,
|
||||
'NEW_WORK: No committed design context was found. If this task produces ' +
|
||||
'new design (a build from scratch, or a redesign that discards the ' +
|
||||
'current look), you MUST read reference/new-work.md before making any ' +
|
||||
'design decision. Scoped fixes to existing code do not need it.',
|
||||
];
|
||||
parts.push(buildResolvedContextDirective(ctx, cliOptions, { targetExists }));
|
||||
if (shouldWarnMissingTarget(ctx, targetProvided, targetExists)) {
|
||||
@@ -922,10 +926,22 @@ async function cli() {
|
||||
parts.push(buildMissingTargetDirective());
|
||||
}
|
||||
const register = extractRegister(ctx.product);
|
||||
const next = register
|
||||
? `NEXT STEP: This project's register is \`${register}\`. You MUST now read \`reference/${register}.md\` before producing any design output.`
|
||||
: `NEXT STEP: You MUST now read the matching register reference (\`reference/brand.md\` or \`reference/product.md\`) before producing any design output. Pick based on PRODUCT.md above.`;
|
||||
parts.push(next);
|
||||
// The register field survives as a family hint (brand = Persuade/Experience,
|
||||
// product = Operate/Read); SKILL.md's mode section carries the essentials
|
||||
// inline, so no register-file read is mandated here. What IS mandated:
|
||||
// the new-work playbook when no committed design system exists yet.
|
||||
if (!ctx.hasDesign) {
|
||||
parts.push(
|
||||
'NEW_WORK: PRODUCT.md exists but no DESIGN.md was found. If the code ' +
|
||||
'has no committed design system either (check the project files), and ' +
|
||||
'this task produces new design or a redesign that discards the current ' +
|
||||
'look, you MUST read reference/new-work.md before making any design ' +
|
||||
'decision. Scoped fixes inside an existing design system do not need it.',
|
||||
);
|
||||
}
|
||||
if (register) {
|
||||
parts.push(`REGISTER: \`${register}\` (family hint: brand = Persuade/Experience surfaces, product = Operate/Read). Derive the visitor's mode per SKILL.md; \`reference/${register}.md\` has extended depth for substantial work.`);
|
||||
}
|
||||
const platform = extractPlatform(ctx.product);
|
||||
const nativeRefs =
|
||||
platform === 'adaptive' ? ['ios', 'android'] : platform === 'ios' || platform === 'android' ? [platform] : [];
|
||||
@@ -933,7 +949,7 @@ async function cli() {
|
||||
const refList = nativeRefs.map(p => `\`reference/${p}.md\``).join(' and ');
|
||||
const label = platform === 'adaptive' ? '`adaptive` (both iOS and Android)' : `\`${platform}\``;
|
||||
parts.push(
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to the register reference.`,
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to SKILL.md's mode guidance.`,
|
||||
);
|
||||
} else if (!platform) {
|
||||
// A `## Platform` section that names something we don't recognize (a
|
||||
|
||||
@@ -7105,6 +7105,14 @@
|
||||
}
|
||||
|
||||
async function captureAndEmit(el, basePayload, snapshot, rect) {
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
|
||||
// Plain requests do not send a screenshot to the agent, so capture is
|
||||
// presentation-only. Wait only for the helper to accept the event before
|
||||
// starting CPU-heavy capture; this yields the browser task and prevents
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) await sendEvent(basePayload);
|
||||
|
||||
let screenshotPath;
|
||||
let blob;
|
||||
let paper;
|
||||
@@ -7122,7 +7130,6 @@
|
||||
// are present. Without annotations the image is pure visual anchoring -
|
||||
// it biases the model toward the current rendering and works against the
|
||||
// three-distinct-directions brief.
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
if (blob && hasAnnotations) {
|
||||
try {
|
||||
const uploadRes = await fetch(
|
||||
@@ -7140,7 +7147,11 @@
|
||||
console.warn('[impeccable] annotation upload failed:', err);
|
||||
}
|
||||
}
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Annotated requests must wait for capture + upload because the screenshot
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
{
|
||||
"name": "impeccable",
|
||||
"description": "Design fluency for frontend development. 1 skill with 23 commands (/impeccable polish, /impeccable audit, /impeccable critique, etc.) and curated anti-pattern detection.",
|
||||
"version": "4.0.0-alpha.8",
|
||||
"version": "4.0.0-alpha.9",
|
||||
"author": {
|
||||
"name": "Paul Bakaus",
|
||||
"email": "paul@paulbakaus.com"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "impeccable",
|
||||
"description": "Design fluency for frontend development. 1 skill with 23 commands (/impeccable polish, /impeccable audit, /impeccable critique, etc.) and curated anti-pattern detection.",
|
||||
"version": "4.0.0-alpha.8",
|
||||
"version": "4.0.0-alpha.9",
|
||||
"author": {
|
||||
"name": "Paul Bakaus",
|
||||
"email": "paul@paulbakaus.com"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: impeccable
|
||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||
version: 4.0.0-alpha.8
|
||||
version: 4.0.0-alpha.9
|
||||
user-invocable: true
|
||||
argument-hint: "[craft|shape · audit|critique · animate|bolder|colorize|delight|layout|overdrive|quieter|typeset · adapt|clarify|distill · harden|onboard|optimize|polish · init|document|extract|live] [target]"
|
||||
license: Apache 2.0
|
||||
@@ -19,27 +19,13 @@ Approach every design task as the design lead at a small studio known for giving
|
||||
1. Run `node .claude/skills/impeccable/scripts/context.mjs` once per session (if the runtime shows this skill's loaded base directory, run `node <skill-base-dir>/scripts/context.mjs`; keep cwd at the user's project). It prints the project's PRODUCT.md and DESIGN.md when they exist; follow what it prints, including any `UPDATE_AVAILABLE` directive (ask once, never block). If it reports `NO_PRODUCT_MD`: for `init`, `teach`, `craft`, `shape`, or wording that clearly maps to a from-scratch build flow, divert into `reference/init.md` first, **unless no user can respond** (a one-shot or automated run, or the user said not to ask): then write your own one-paragraph understanding of the product, audience, and the page's job from the brief and continue. For scoped evaluate/refine/fix requests against existing code, never divert into init; the existing code is the context.
|
||||
2. If the user invoked a sub-command (`audit`, `polish`, `live`, ...), read **`reference/<command>.md`** (the `.native` variant from the Commands table when the platform is `ios`/`android`/`adaptive`) and follow it. On unattended runs, `craft` and `shape` collapse into this file's process: decide, record each decision in one line, build, self-review.
|
||||
3. Read at least one project file (CSS / tokens / theme / a representative component) to learn what world you're in. If PRODUCT.md's `## Platform` is `ios` or `android`, also read `reference/<platform>.md` (`adaptive` reads both).
|
||||
4. If the project is brand-new (no committed tokens, fonts, or brand colors found in step 3), run `node .claude/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed breaks your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this step entirely when step 3 found committed brand colors: identity-preservation wins.
|
||||
|
||||
## How to design
|
||||
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this file warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this skill warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
|
||||
**Existing worlds are sacred.** When the surface already has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside it: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Treat the task as new identity work only when nothing committed exists, or when the user asks for a redesign that discards the current look. A redesign is new work: derive the concept from the subject and the brief, not from the incumbent page's structure or styling.
|
||||
**Existing worlds are sacred.** Most of impeccable's work happens inside a site or app that already exists. When the surface has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside that world: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Inventing parallel colors, fonts, or styles on an existing surface is a defect, not creativity.
|
||||
|
||||
**Ground it in the subject.** Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
**Plan, self-check, build.** Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
**Commit.** Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
**Calibration.** AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
**New identity work reads the playbook first.** When nothing committed exists (greenfield, or a codebase with no real tokens or chosen faces), or the user asks for a redesign that discards the current look, you MUST read [reference/new-work.md](reference/new-work.md) before making any design decision. Not optional, not skippable under time pressure: producing new identity without it yields the generic default this skill exists to prevent. A redesign is new work; derive the concept from the subject and the brief, not from the incumbent page's structure or styling. `context.mjs` prints this directive when it detects the situation. Scoped fixes inside an existing world don't need the playbook; the craft floor below governs them.
|
||||
|
||||
## Craft floor
|
||||
|
||||
@@ -57,7 +43,7 @@ Build to this floor without announcing it. The design detector (the project hook
|
||||
|
||||
Name the visitor's mode before designing; the page's grammar follows from it, and most ruined pages are one mode wearing another mode's grammar. The brief and the surface decide the mode. PRODUCT.md's `register` field names the family (`brand` covers Persuade and Experience; `product` covers Operate and Read), and `reference/brand.md` / `reference/product.md` carry extended depth for the two families.
|
||||
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans.
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Briefs that imply imagery must ship real, verified imagery; a colored rectangle where a photo belongs reads as incomplete. New Persuade surfaces take their typeface procedure and reject list from [reference/new-work.md](reference/new-work.md).
|
||||
|
||||
**Operate** (app UI, dashboards, admin, tools; design SERVES the task). A person getting something done: density, scanability, and consistency outrank expressiveness. These surfaces earn trust by feeling native to their platform: system font stacks and workhorse UI faces are legitimate and often correct here (the Persuade reject list does not apply). The brand lives in the details: focus states, empty states, microcopy, one owned accent.
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# New identity work
|
||||
|
||||
You are reading this because nothing committed exists yet (greenfield), or the user asked for a redesign that discards the current look. Either way the task is the same: invent a visual identity that could not be mistaken for anyone else's, and build it to the craft floor. SKILL.md's rules all still apply; this file is the process that produces the identity.
|
||||
|
||||
## Seed
|
||||
|
||||
If the project is brand-new (no committed tokens, fonts, or brand colors found in the code), run `node .claude/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed exists to break your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this entirely when the code already has committed brand colors: identity-preservation wins.
|
||||
|
||||
## Ground it in the subject
|
||||
|
||||
Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
## Plan, self-check, build
|
||||
|
||||
Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
## Commit
|
||||
|
||||
Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
## Type and imagery for new Persuade and Experience surfaces
|
||||
|
||||
Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans. (For Operate and Read surfaces the opposite holds: system stacks and workhorse UI faces are legitimate and often correct.)
|
||||
|
||||
Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Verify stock URLs resolve before shipping them.
|
||||
|
||||
## Calibration
|
||||
|
||||
AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
|
||||
Before finishing, verify against SKILL.md's craft floor and run the detector; a bold page that ships mechanical defects is not done.
|
||||
@@ -904,6 +904,10 @@ async function cli() {
|
||||
'reference/init.md and write PRODUCT.md first; for any other (scoped) ' +
|
||||
'command against existing code, proceed using the code as context and ' +
|
||||
`offer \`${IMPECCABLE_COMMAND} init\` as a suggestion (do not block).`,
|
||||
'NEW_WORK: No committed design context was found. If this task produces ' +
|
||||
'new design (a build from scratch, or a redesign that discards the ' +
|
||||
'current look), you MUST read reference/new-work.md before making any ' +
|
||||
'design decision. Scoped fixes to existing code do not need it.',
|
||||
];
|
||||
parts.push(buildResolvedContextDirective(ctx, cliOptions, { targetExists }));
|
||||
if (shouldWarnMissingTarget(ctx, targetProvided, targetExists)) {
|
||||
@@ -922,10 +926,22 @@ async function cli() {
|
||||
parts.push(buildMissingTargetDirective());
|
||||
}
|
||||
const register = extractRegister(ctx.product);
|
||||
const next = register
|
||||
? `NEXT STEP: This project's register is \`${register}\`. You MUST now read \`reference/${register}.md\` before producing any design output.`
|
||||
: `NEXT STEP: You MUST now read the matching register reference (\`reference/brand.md\` or \`reference/product.md\`) before producing any design output. Pick based on PRODUCT.md above.`;
|
||||
parts.push(next);
|
||||
// The register field survives as a family hint (brand = Persuade/Experience,
|
||||
// product = Operate/Read); SKILL.md's mode section carries the essentials
|
||||
// inline, so no register-file read is mandated here. What IS mandated:
|
||||
// the new-work playbook when no committed design system exists yet.
|
||||
if (!ctx.hasDesign) {
|
||||
parts.push(
|
||||
'NEW_WORK: PRODUCT.md exists but no DESIGN.md was found. If the code ' +
|
||||
'has no committed design system either (check the project files), and ' +
|
||||
'this task produces new design or a redesign that discards the current ' +
|
||||
'look, you MUST read reference/new-work.md before making any design ' +
|
||||
'decision. Scoped fixes inside an existing design system do not need it.',
|
||||
);
|
||||
}
|
||||
if (register) {
|
||||
parts.push(`REGISTER: \`${register}\` (family hint: brand = Persuade/Experience surfaces, product = Operate/Read). Derive the visitor's mode per SKILL.md; \`reference/${register}.md\` has extended depth for substantial work.`);
|
||||
}
|
||||
const platform = extractPlatform(ctx.product);
|
||||
const nativeRefs =
|
||||
platform === 'adaptive' ? ['ios', 'android'] : platform === 'ios' || platform === 'android' ? [platform] : [];
|
||||
@@ -933,7 +949,7 @@ async function cli() {
|
||||
const refList = nativeRefs.map(p => `\`reference/${p}.md\``).join(' and ');
|
||||
const label = platform === 'adaptive' ? '`adaptive` (both iOS and Android)' : `\`${platform}\``;
|
||||
parts.push(
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to the register reference.`,
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to SKILL.md's mode guidance.`,
|
||||
);
|
||||
} else if (!platform) {
|
||||
// A `## Platform` section that names something we don't recognize (a
|
||||
|
||||
@@ -7105,6 +7105,14 @@
|
||||
}
|
||||
|
||||
async function captureAndEmit(el, basePayload, snapshot, rect) {
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
|
||||
// Plain requests do not send a screenshot to the agent, so capture is
|
||||
// presentation-only. Wait only for the helper to accept the event before
|
||||
// starting CPU-heavy capture; this yields the browser task and prevents
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) await sendEvent(basePayload);
|
||||
|
||||
let screenshotPath;
|
||||
let blob;
|
||||
let paper;
|
||||
@@ -7122,7 +7130,6 @@
|
||||
// are present. Without annotations the image is pure visual anchoring -
|
||||
// it biases the model toward the current rendering and works against the
|
||||
// three-distinct-directions brief.
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
if (blob && hasAnnotations) {
|
||||
try {
|
||||
const uploadRes = await fetch(
|
||||
@@ -7140,7 +7147,11 @@
|
||||
console.warn('[impeccable] annotation upload failed:', err);
|
||||
}
|
||||
}
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Annotated requests must wait for capture + upload because the screenshot
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: impeccable
|
||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||
version: 4.0.0-alpha.8
|
||||
version: 4.0.0-alpha.9
|
||||
license: Apache 2.0
|
||||
---
|
||||
|
||||
@@ -14,27 +14,13 @@ Approach every design task as the design lead at a small studio known for giving
|
||||
1. Run `node .cursor/skills/impeccable/scripts/context.mjs` once per session (if the runtime shows this skill's loaded base directory, run `node <skill-base-dir>/scripts/context.mjs`; keep cwd at the user's project). It prints the project's PRODUCT.md and DESIGN.md when they exist; follow what it prints, including any `UPDATE_AVAILABLE` directive (ask once, never block). If it reports `NO_PRODUCT_MD`: for `init`, `teach`, `craft`, `shape`, or wording that clearly maps to a from-scratch build flow, divert into `reference/init.md` first, **unless no user can respond** (a one-shot or automated run, or the user said not to ask): then write your own one-paragraph understanding of the product, audience, and the page's job from the brief and continue. For scoped evaluate/refine/fix requests against existing code, never divert into init; the existing code is the context.
|
||||
2. If the user invoked a sub-command (`audit`, `polish`, `live`, ...), read **`reference/<command>.md`** (the `.native` variant from the Commands table when the platform is `ios`/`android`/`adaptive`) and follow it. On unattended runs, `craft` and `shape` collapse into this file's process: decide, record each decision in one line, build, self-review.
|
||||
3. Read at least one project file (CSS / tokens / theme / a representative component) to learn what world you're in. If PRODUCT.md's `## Platform` is `ios` or `android`, also read `reference/<platform>.md` (`adaptive` reads both).
|
||||
4. If the project is brand-new (no committed tokens, fonts, or brand colors found in step 3), run `node .cursor/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed breaks your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this step entirely when step 3 found committed brand colors: identity-preservation wins.
|
||||
|
||||
## How to design
|
||||
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this file warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this skill warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
|
||||
**Existing worlds are sacred.** When the surface already has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside it: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Treat the task as new identity work only when nothing committed exists, or when the user asks for a redesign that discards the current look. A redesign is new work: derive the concept from the subject and the brief, not from the incumbent page's structure or styling.
|
||||
**Existing worlds are sacred.** Most of impeccable's work happens inside a site or app that already exists. When the surface has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside that world: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Inventing parallel colors, fonts, or styles on an existing surface is a defect, not creativity.
|
||||
|
||||
**Ground it in the subject.** Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
**Plan, self-check, build.** Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
**Commit.** Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
**Calibration.** AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
**New identity work reads the playbook first.** When nothing committed exists (greenfield, or a codebase with no real tokens or chosen faces), or the user asks for a redesign that discards the current look, you MUST read [reference/new-work.md](reference/new-work.md) before making any design decision. Not optional, not skippable under time pressure: producing new identity without it yields the generic default this skill exists to prevent. A redesign is new work; derive the concept from the subject and the brief, not from the incumbent page's structure or styling. `context.mjs` prints this directive when it detects the situation. Scoped fixes inside an existing world don't need the playbook; the craft floor below governs them.
|
||||
|
||||
## Craft floor
|
||||
|
||||
@@ -52,7 +38,7 @@ Build to this floor without announcing it. The design detector (the project hook
|
||||
|
||||
Name the visitor's mode before designing; the page's grammar follows from it, and most ruined pages are one mode wearing another mode's grammar. The brief and the surface decide the mode. PRODUCT.md's `register` field names the family (`brand` covers Persuade and Experience; `product` covers Operate and Read), and `reference/brand.md` / `reference/product.md` carry extended depth for the two families.
|
||||
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans.
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Briefs that imply imagery must ship real, verified imagery; a colored rectangle where a photo belongs reads as incomplete. New Persuade surfaces take their typeface procedure and reject list from [reference/new-work.md](reference/new-work.md).
|
||||
|
||||
**Operate** (app UI, dashboards, admin, tools; design SERVES the task). A person getting something done: density, scanability, and consistency outrank expressiveness. These surfaces earn trust by feeling native to their platform: system font stacks and workhorse UI faces are legitimate and often correct here (the Persuade reject list does not apply). The brand lives in the details: focus states, empty states, microcopy, one owned accent.
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# New identity work
|
||||
|
||||
You are reading this because nothing committed exists yet (greenfield), or the user asked for a redesign that discards the current look. Either way the task is the same: invent a visual identity that could not be mistaken for anyone else's, and build it to the craft floor. SKILL.md's rules all still apply; this file is the process that produces the identity.
|
||||
|
||||
## Seed
|
||||
|
||||
If the project is brand-new (no committed tokens, fonts, or brand colors found in the code), run `node .cursor/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed exists to break your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this entirely when the code already has committed brand colors: identity-preservation wins.
|
||||
|
||||
## Ground it in the subject
|
||||
|
||||
Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
## Plan, self-check, build
|
||||
|
||||
Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
## Commit
|
||||
|
||||
Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
## Type and imagery for new Persuade and Experience surfaces
|
||||
|
||||
Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans. (For Operate and Read surfaces the opposite holds: system stacks and workhorse UI faces are legitimate and often correct.)
|
||||
|
||||
Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Verify stock URLs resolve before shipping them.
|
||||
|
||||
## Calibration
|
||||
|
||||
AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
|
||||
Before finishing, verify against SKILL.md's craft floor and run the detector; a bold page that ships mechanical defects is not done.
|
||||
@@ -904,6 +904,10 @@ async function cli() {
|
||||
'reference/init.md and write PRODUCT.md first; for any other (scoped) ' +
|
||||
'command against existing code, proceed using the code as context and ' +
|
||||
`offer \`${IMPECCABLE_COMMAND} init\` as a suggestion (do not block).`,
|
||||
'NEW_WORK: No committed design context was found. If this task produces ' +
|
||||
'new design (a build from scratch, or a redesign that discards the ' +
|
||||
'current look), you MUST read reference/new-work.md before making any ' +
|
||||
'design decision. Scoped fixes to existing code do not need it.',
|
||||
];
|
||||
parts.push(buildResolvedContextDirective(ctx, cliOptions, { targetExists }));
|
||||
if (shouldWarnMissingTarget(ctx, targetProvided, targetExists)) {
|
||||
@@ -922,10 +926,22 @@ async function cli() {
|
||||
parts.push(buildMissingTargetDirective());
|
||||
}
|
||||
const register = extractRegister(ctx.product);
|
||||
const next = register
|
||||
? `NEXT STEP: This project's register is \`${register}\`. You MUST now read \`reference/${register}.md\` before producing any design output.`
|
||||
: `NEXT STEP: You MUST now read the matching register reference (\`reference/brand.md\` or \`reference/product.md\`) before producing any design output. Pick based on PRODUCT.md above.`;
|
||||
parts.push(next);
|
||||
// The register field survives as a family hint (brand = Persuade/Experience,
|
||||
// product = Operate/Read); SKILL.md's mode section carries the essentials
|
||||
// inline, so no register-file read is mandated here. What IS mandated:
|
||||
// the new-work playbook when no committed design system exists yet.
|
||||
if (!ctx.hasDesign) {
|
||||
parts.push(
|
||||
'NEW_WORK: PRODUCT.md exists but no DESIGN.md was found. If the code ' +
|
||||
'has no committed design system either (check the project files), and ' +
|
||||
'this task produces new design or a redesign that discards the current ' +
|
||||
'look, you MUST read reference/new-work.md before making any design ' +
|
||||
'decision. Scoped fixes inside an existing design system do not need it.',
|
||||
);
|
||||
}
|
||||
if (register) {
|
||||
parts.push(`REGISTER: \`${register}\` (family hint: brand = Persuade/Experience surfaces, product = Operate/Read). Derive the visitor's mode per SKILL.md; \`reference/${register}.md\` has extended depth for substantial work.`);
|
||||
}
|
||||
const platform = extractPlatform(ctx.product);
|
||||
const nativeRefs =
|
||||
platform === 'adaptive' ? ['ios', 'android'] : platform === 'ios' || platform === 'android' ? [platform] : [];
|
||||
@@ -933,7 +949,7 @@ async function cli() {
|
||||
const refList = nativeRefs.map(p => `\`reference/${p}.md\``).join(' and ');
|
||||
const label = platform === 'adaptive' ? '`adaptive` (both iOS and Android)' : `\`${platform}\``;
|
||||
parts.push(
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to the register reference.`,
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to SKILL.md's mode guidance.`,
|
||||
);
|
||||
} else if (!platform) {
|
||||
// A `## Platform` section that names something we don't recognize (a
|
||||
|
||||
@@ -7105,6 +7105,14 @@
|
||||
}
|
||||
|
||||
async function captureAndEmit(el, basePayload, snapshot, rect) {
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
|
||||
// Plain requests do not send a screenshot to the agent, so capture is
|
||||
// presentation-only. Wait only for the helper to accept the event before
|
||||
// starting CPU-heavy capture; this yields the browser task and prevents
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) await sendEvent(basePayload);
|
||||
|
||||
let screenshotPath;
|
||||
let blob;
|
||||
let paper;
|
||||
@@ -7122,7 +7130,6 @@
|
||||
// are present. Without annotations the image is pure visual anchoring -
|
||||
// it biases the model toward the current rendering and works against the
|
||||
// three-distinct-directions brief.
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
if (blob && hasAnnotations) {
|
||||
try {
|
||||
const uploadRes = await fetch(
|
||||
@@ -7140,7 +7147,11 @@
|
||||
console.warn('[impeccable] annotation upload failed:', err);
|
||||
}
|
||||
}
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Annotated requests must wait for capture + upload because the screenshot
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: impeccable
|
||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||
version: 4.0.0-alpha.8
|
||||
version: 4.0.0-alpha.9
|
||||
---
|
||||
|
||||
Designs and iterates production-grade frontend interfaces. Real working code, committed design choices, exceptional craft.
|
||||
@@ -13,27 +13,13 @@ Approach every design task as the design lead at a small studio known for giving
|
||||
1. Run `node .gemini/skills/impeccable/scripts/context.mjs` once per session (if the runtime shows this skill's loaded base directory, run `node <skill-base-dir>/scripts/context.mjs`; keep cwd at the user's project). It prints the project's PRODUCT.md and DESIGN.md when they exist; follow what it prints, including any `UPDATE_AVAILABLE` directive (ask once, never block). If it reports `NO_PRODUCT_MD`: for `init`, `teach`, `craft`, `shape`, or wording that clearly maps to a from-scratch build flow, divert into `reference/init.md` first, **unless no user can respond** (a one-shot or automated run, or the user said not to ask): then write your own one-paragraph understanding of the product, audience, and the page's job from the brief and continue. For scoped evaluate/refine/fix requests against existing code, never divert into init; the existing code is the context.
|
||||
2. If the user invoked a sub-command (`audit`, `polish`, `live`, ...), read **`reference/<command>.md`** (the `.native` variant from the Commands table when the platform is `ios`/`android`/`adaptive`) and follow it. On unattended runs, `craft` and `shape` collapse into this file's process: decide, record each decision in one line, build, self-review.
|
||||
3. Read at least one project file (CSS / tokens / theme / a representative component) to learn what world you're in. If PRODUCT.md's `## Platform` is `ios` or `android`, also read `reference/<platform>.md` (`adaptive` reads both).
|
||||
4. If the project is brand-new (no committed tokens, fonts, or brand colors found in step 3), run `node .gemini/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed breaks your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this step entirely when step 3 found committed brand colors: identity-preservation wins.
|
||||
|
||||
## How to design
|
||||
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this file warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this skill warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
|
||||
**Existing worlds are sacred.** When the surface already has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside it: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Treat the task as new identity work only when nothing committed exists, or when the user asks for a redesign that discards the current look. A redesign is new work: derive the concept from the subject and the brief, not from the incumbent page's structure or styling.
|
||||
**Existing worlds are sacred.** Most of impeccable's work happens inside a site or app that already exists. When the surface has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside that world: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Inventing parallel colors, fonts, or styles on an existing surface is a defect, not creativity.
|
||||
|
||||
**Ground it in the subject.** Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
**Plan, self-check, build.** Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
**Commit.** Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
**Calibration.** AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
**New identity work reads the playbook first.** When nothing committed exists (greenfield, or a codebase with no real tokens or chosen faces), or the user asks for a redesign that discards the current look, you MUST read [reference/new-work.md](reference/new-work.md) before making any design decision. Not optional, not skippable under time pressure: producing new identity without it yields the generic default this skill exists to prevent. A redesign is new work; derive the concept from the subject and the brief, not from the incumbent page's structure or styling. `context.mjs` prints this directive when it detects the situation. Scoped fixes inside an existing world don't need the playbook; the craft floor below governs them.
|
||||
|
||||
## Craft floor
|
||||
|
||||
@@ -53,7 +39,7 @@ Build to this floor without announcing it. The design detector (the project hook
|
||||
|
||||
Name the visitor's mode before designing; the page's grammar follows from it, and most ruined pages are one mode wearing another mode's grammar. The brief and the surface decide the mode. PRODUCT.md's `register` field names the family (`brand` covers Persuade and Experience; `product` covers Operate and Read), and `reference/brand.md` / `reference/product.md` carry extended depth for the two families.
|
||||
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans.
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Briefs that imply imagery must ship real, verified imagery; a colored rectangle where a photo belongs reads as incomplete. New Persuade surfaces take their typeface procedure and reject list from [reference/new-work.md](reference/new-work.md).
|
||||
|
||||
**Operate** (app UI, dashboards, admin, tools; design SERVES the task). A person getting something done: density, scanability, and consistency outrank expressiveness. These surfaces earn trust by feeling native to their platform: system font stacks and workhorse UI faces are legitimate and often correct here (the Persuade reject list does not apply). The brand lives in the details: focus states, empty states, microcopy, one owned accent.
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# New identity work
|
||||
|
||||
You are reading this because nothing committed exists yet (greenfield), or the user asked for a redesign that discards the current look. Either way the task is the same: invent a visual identity that could not be mistaken for anyone else's, and build it to the craft floor. SKILL.md's rules all still apply; this file is the process that produces the identity.
|
||||
|
||||
## Seed
|
||||
|
||||
If the project is brand-new (no committed tokens, fonts, or brand colors found in the code), run `node .gemini/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed exists to break your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this entirely when the code already has committed brand colors: identity-preservation wins.
|
||||
|
||||
## Ground it in the subject
|
||||
|
||||
Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
## Plan, self-check, build
|
||||
|
||||
Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
## Commit
|
||||
|
||||
Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
## Type and imagery for new Persuade and Experience surfaces
|
||||
|
||||
Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans. (For Operate and Read surfaces the opposite holds: system stacks and workhorse UI faces are legitimate and often correct.)
|
||||
|
||||
Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Verify stock URLs resolve before shipping them.
|
||||
|
||||
## Calibration
|
||||
|
||||
AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
|
||||
Before finishing, verify against SKILL.md's craft floor and run the detector; a bold page that ships mechanical defects is not done.
|
||||
@@ -904,6 +904,10 @@ async function cli() {
|
||||
'reference/init.md and write PRODUCT.md first; for any other (scoped) ' +
|
||||
'command against existing code, proceed using the code as context and ' +
|
||||
`offer \`${IMPECCABLE_COMMAND} init\` as a suggestion (do not block).`,
|
||||
'NEW_WORK: No committed design context was found. If this task produces ' +
|
||||
'new design (a build from scratch, or a redesign that discards the ' +
|
||||
'current look), you MUST read reference/new-work.md before making any ' +
|
||||
'design decision. Scoped fixes to existing code do not need it.',
|
||||
];
|
||||
parts.push(buildResolvedContextDirective(ctx, cliOptions, { targetExists }));
|
||||
if (shouldWarnMissingTarget(ctx, targetProvided, targetExists)) {
|
||||
@@ -922,10 +926,22 @@ async function cli() {
|
||||
parts.push(buildMissingTargetDirective());
|
||||
}
|
||||
const register = extractRegister(ctx.product);
|
||||
const next = register
|
||||
? `NEXT STEP: This project's register is \`${register}\`. You MUST now read \`reference/${register}.md\` before producing any design output.`
|
||||
: `NEXT STEP: You MUST now read the matching register reference (\`reference/brand.md\` or \`reference/product.md\`) before producing any design output. Pick based on PRODUCT.md above.`;
|
||||
parts.push(next);
|
||||
// The register field survives as a family hint (brand = Persuade/Experience,
|
||||
// product = Operate/Read); SKILL.md's mode section carries the essentials
|
||||
// inline, so no register-file read is mandated here. What IS mandated:
|
||||
// the new-work playbook when no committed design system exists yet.
|
||||
if (!ctx.hasDesign) {
|
||||
parts.push(
|
||||
'NEW_WORK: PRODUCT.md exists but no DESIGN.md was found. If the code ' +
|
||||
'has no committed design system either (check the project files), and ' +
|
||||
'this task produces new design or a redesign that discards the current ' +
|
||||
'look, you MUST read reference/new-work.md before making any design ' +
|
||||
'decision. Scoped fixes inside an existing design system do not need it.',
|
||||
);
|
||||
}
|
||||
if (register) {
|
||||
parts.push(`REGISTER: \`${register}\` (family hint: brand = Persuade/Experience surfaces, product = Operate/Read). Derive the visitor's mode per SKILL.md; \`reference/${register}.md\` has extended depth for substantial work.`);
|
||||
}
|
||||
const platform = extractPlatform(ctx.product);
|
||||
const nativeRefs =
|
||||
platform === 'adaptive' ? ['ios', 'android'] : platform === 'ios' || platform === 'android' ? [platform] : [];
|
||||
@@ -933,7 +949,7 @@ async function cli() {
|
||||
const refList = nativeRefs.map(p => `\`reference/${p}.md\``).join(' and ');
|
||||
const label = platform === 'adaptive' ? '`adaptive` (both iOS and Android)' : `\`${platform}\``;
|
||||
parts.push(
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to the register reference.`,
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to SKILL.md's mode guidance.`,
|
||||
);
|
||||
} else if (!platform) {
|
||||
// A `## Platform` section that names something we don't recognize (a
|
||||
|
||||
@@ -7105,6 +7105,14 @@
|
||||
}
|
||||
|
||||
async function captureAndEmit(el, basePayload, snapshot, rect) {
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
|
||||
// Plain requests do not send a screenshot to the agent, so capture is
|
||||
// presentation-only. Wait only for the helper to accept the event before
|
||||
// starting CPU-heavy capture; this yields the browser task and prevents
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) await sendEvent(basePayload);
|
||||
|
||||
let screenshotPath;
|
||||
let blob;
|
||||
let paper;
|
||||
@@ -7122,7 +7130,6 @@
|
||||
// are present. Without annotations the image is pure visual anchoring -
|
||||
// it biases the model toward the current rendering and works against the
|
||||
// three-distinct-directions brief.
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
if (blob && hasAnnotations) {
|
||||
try {
|
||||
const uploadRes = await fetch(
|
||||
@@ -7140,7 +7147,11 @@
|
||||
console.warn('[impeccable] annotation upload failed:', err);
|
||||
}
|
||||
}
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Annotated requests must wait for capture + upload because the screenshot
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: impeccable
|
||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||
version: 4.0.0-alpha.8
|
||||
version: 4.0.0-alpha.9
|
||||
user-invocable: true
|
||||
argument-hint: "[craft|shape · audit|critique · animate|bolder|colorize|delight|layout|overdrive|quieter|typeset · adapt|clarify|distill · harden|onboard|optimize|polish · init|document|extract|live] [target]"
|
||||
license: Apache 2.0
|
||||
@@ -16,27 +16,13 @@ Approach every design task as the design lead at a small studio known for giving
|
||||
1. Run `node .github/skills/impeccable/scripts/context.mjs` once per session (if the runtime shows this skill's loaded base directory, run `node <skill-base-dir>/scripts/context.mjs`; keep cwd at the user's project). It prints the project's PRODUCT.md and DESIGN.md when they exist; follow what it prints, including any `UPDATE_AVAILABLE` directive (ask once, never block). If it reports `NO_PRODUCT_MD`: for `init`, `teach`, `craft`, `shape`, or wording that clearly maps to a from-scratch build flow, divert into `reference/init.md` first, **unless no user can respond** (a one-shot or automated run, or the user said not to ask): then write your own one-paragraph understanding of the product, audience, and the page's job from the brief and continue. For scoped evaluate/refine/fix requests against existing code, never divert into init; the existing code is the context.
|
||||
2. If the user invoked a sub-command (`audit`, `polish`, `live`, ...), read **`reference/<command>.md`** (the `.native` variant from the Commands table when the platform is `ios`/`android`/`adaptive`) and follow it. On unattended runs, `craft` and `shape` collapse into this file's process: decide, record each decision in one line, build, self-review.
|
||||
3. Read at least one project file (CSS / tokens / theme / a representative component) to learn what world you're in. If PRODUCT.md's `## Platform` is `ios` or `android`, also read `reference/<platform>.md` (`adaptive` reads both).
|
||||
4. If the project is brand-new (no committed tokens, fonts, or brand colors found in step 3), run `node .github/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed breaks your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this step entirely when step 3 found committed brand colors: identity-preservation wins.
|
||||
|
||||
## How to design
|
||||
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this file warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this skill warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
|
||||
**Existing worlds are sacred.** When the surface already has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside it: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Treat the task as new identity work only when nothing committed exists, or when the user asks for a redesign that discards the current look. A redesign is new work: derive the concept from the subject and the brief, not from the incumbent page's structure or styling.
|
||||
**Existing worlds are sacred.** Most of impeccable's work happens inside a site or app that already exists. When the surface has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside that world: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Inventing parallel colors, fonts, or styles on an existing surface is a defect, not creativity.
|
||||
|
||||
**Ground it in the subject.** Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
**Plan, self-check, build.** Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
**Commit.** Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
**Calibration.** AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
**New identity work reads the playbook first.** When nothing committed exists (greenfield, or a codebase with no real tokens or chosen faces), or the user asks for a redesign that discards the current look, you MUST read [reference/new-work.md](reference/new-work.md) before making any design decision. Not optional, not skippable under time pressure: producing new identity without it yields the generic default this skill exists to prevent. A redesign is new work; derive the concept from the subject and the brief, not from the incumbent page's structure or styling. `context.mjs` prints this directive when it detects the situation. Scoped fixes inside an existing world don't need the playbook; the craft floor below governs them.
|
||||
|
||||
## Craft floor
|
||||
|
||||
@@ -54,7 +40,7 @@ Build to this floor without announcing it. The design detector (the project hook
|
||||
|
||||
Name the visitor's mode before designing; the page's grammar follows from it, and most ruined pages are one mode wearing another mode's grammar. The brief and the surface decide the mode. PRODUCT.md's `register` field names the family (`brand` covers Persuade and Experience; `product` covers Operate and Read), and `reference/brand.md` / `reference/product.md` carry extended depth for the two families.
|
||||
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans.
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Briefs that imply imagery must ship real, verified imagery; a colored rectangle where a photo belongs reads as incomplete. New Persuade surfaces take their typeface procedure and reject list from [reference/new-work.md](reference/new-work.md).
|
||||
|
||||
**Operate** (app UI, dashboards, admin, tools; design SERVES the task). A person getting something done: density, scanability, and consistency outrank expressiveness. These surfaces earn trust by feeling native to their platform: system font stacks and workhorse UI faces are legitimate and often correct here (the Persuade reject list does not apply). The brand lives in the details: focus states, empty states, microcopy, one owned accent.
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# New identity work
|
||||
|
||||
You are reading this because nothing committed exists yet (greenfield), or the user asked for a redesign that discards the current look. Either way the task is the same: invent a visual identity that could not be mistaken for anyone else's, and build it to the craft floor. SKILL.md's rules all still apply; this file is the process that produces the identity.
|
||||
|
||||
## Seed
|
||||
|
||||
If the project is brand-new (no committed tokens, fonts, or brand colors found in the code), run `node .github/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed exists to break your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this entirely when the code already has committed brand colors: identity-preservation wins.
|
||||
|
||||
## Ground it in the subject
|
||||
|
||||
Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
## Plan, self-check, build
|
||||
|
||||
Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
## Commit
|
||||
|
||||
Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
## Type and imagery for new Persuade and Experience surfaces
|
||||
|
||||
Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans. (For Operate and Read surfaces the opposite holds: system stacks and workhorse UI faces are legitimate and often correct.)
|
||||
|
||||
Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Verify stock URLs resolve before shipping them.
|
||||
|
||||
## Calibration
|
||||
|
||||
AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
|
||||
Before finishing, verify against SKILL.md's craft floor and run the detector; a bold page that ships mechanical defects is not done.
|
||||
@@ -904,6 +904,10 @@ async function cli() {
|
||||
'reference/init.md and write PRODUCT.md first; for any other (scoped) ' +
|
||||
'command against existing code, proceed using the code as context and ' +
|
||||
`offer \`${IMPECCABLE_COMMAND} init\` as a suggestion (do not block).`,
|
||||
'NEW_WORK: No committed design context was found. If this task produces ' +
|
||||
'new design (a build from scratch, or a redesign that discards the ' +
|
||||
'current look), you MUST read reference/new-work.md before making any ' +
|
||||
'design decision. Scoped fixes to existing code do not need it.',
|
||||
];
|
||||
parts.push(buildResolvedContextDirective(ctx, cliOptions, { targetExists }));
|
||||
if (shouldWarnMissingTarget(ctx, targetProvided, targetExists)) {
|
||||
@@ -922,10 +926,22 @@ async function cli() {
|
||||
parts.push(buildMissingTargetDirective());
|
||||
}
|
||||
const register = extractRegister(ctx.product);
|
||||
const next = register
|
||||
? `NEXT STEP: This project's register is \`${register}\`. You MUST now read \`reference/${register}.md\` before producing any design output.`
|
||||
: `NEXT STEP: You MUST now read the matching register reference (\`reference/brand.md\` or \`reference/product.md\`) before producing any design output. Pick based on PRODUCT.md above.`;
|
||||
parts.push(next);
|
||||
// The register field survives as a family hint (brand = Persuade/Experience,
|
||||
// product = Operate/Read); SKILL.md's mode section carries the essentials
|
||||
// inline, so no register-file read is mandated here. What IS mandated:
|
||||
// the new-work playbook when no committed design system exists yet.
|
||||
if (!ctx.hasDesign) {
|
||||
parts.push(
|
||||
'NEW_WORK: PRODUCT.md exists but no DESIGN.md was found. If the code ' +
|
||||
'has no committed design system either (check the project files), and ' +
|
||||
'this task produces new design or a redesign that discards the current ' +
|
||||
'look, you MUST read reference/new-work.md before making any design ' +
|
||||
'decision. Scoped fixes inside an existing design system do not need it.',
|
||||
);
|
||||
}
|
||||
if (register) {
|
||||
parts.push(`REGISTER: \`${register}\` (family hint: brand = Persuade/Experience surfaces, product = Operate/Read). Derive the visitor's mode per SKILL.md; \`reference/${register}.md\` has extended depth for substantial work.`);
|
||||
}
|
||||
const platform = extractPlatform(ctx.product);
|
||||
const nativeRefs =
|
||||
platform === 'adaptive' ? ['ios', 'android'] : platform === 'ios' || platform === 'android' ? [platform] : [];
|
||||
@@ -933,7 +949,7 @@ async function cli() {
|
||||
const refList = nativeRefs.map(p => `\`reference/${p}.md\``).join(' and ');
|
||||
const label = platform === 'adaptive' ? '`adaptive` (both iOS and Android)' : `\`${platform}\``;
|
||||
parts.push(
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to the register reference.`,
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to SKILL.md's mode guidance.`,
|
||||
);
|
||||
} else if (!platform) {
|
||||
// A `## Platform` section that names something we don't recognize (a
|
||||
|
||||
@@ -7105,6 +7105,14 @@
|
||||
}
|
||||
|
||||
async function captureAndEmit(el, basePayload, snapshot, rect) {
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
|
||||
// Plain requests do not send a screenshot to the agent, so capture is
|
||||
// presentation-only. Wait only for the helper to accept the event before
|
||||
// starting CPU-heavy capture; this yields the browser task and prevents
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) await sendEvent(basePayload);
|
||||
|
||||
let screenshotPath;
|
||||
let blob;
|
||||
let paper;
|
||||
@@ -7122,7 +7130,6 @@
|
||||
// are present. Without annotations the image is pure visual anchoring -
|
||||
// it biases the model toward the current rendering and works against the
|
||||
// three-distinct-directions brief.
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
if (blob && hasAnnotations) {
|
||||
try {
|
||||
const uploadRes = await fetch(
|
||||
@@ -7140,7 +7147,11 @@
|
||||
console.warn('[impeccable] annotation upload failed:', err);
|
||||
}
|
||||
}
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Annotated requests must wait for capture + upload because the screenshot
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: impeccable
|
||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||
version: 4.0.0-alpha.8
|
||||
version: 4.0.0-alpha.9
|
||||
license: Apache 2.0
|
||||
---
|
||||
|
||||
@@ -14,27 +14,13 @@ Approach every design task as the design lead at a small studio known for giving
|
||||
1. Run `node .kiro/skills/impeccable/scripts/context.mjs` once per session (if the runtime shows this skill's loaded base directory, run `node <skill-base-dir>/scripts/context.mjs`; keep cwd at the user's project). It prints the project's PRODUCT.md and DESIGN.md when they exist; follow what it prints, including any `UPDATE_AVAILABLE` directive (ask once, never block). If it reports `NO_PRODUCT_MD`: for `init`, `teach`, `craft`, `shape`, or wording that clearly maps to a from-scratch build flow, divert into `reference/init.md` first, **unless no user can respond** (a one-shot or automated run, or the user said not to ask): then write your own one-paragraph understanding of the product, audience, and the page's job from the brief and continue. For scoped evaluate/refine/fix requests against existing code, never divert into init; the existing code is the context.
|
||||
2. If the user invoked a sub-command (`audit`, `polish`, `live`, ...), read **`reference/<command>.md`** (the `.native` variant from the Commands table when the platform is `ios`/`android`/`adaptive`) and follow it. On unattended runs, `craft` and `shape` collapse into this file's process: decide, record each decision in one line, build, self-review.
|
||||
3. Read at least one project file (CSS / tokens / theme / a representative component) to learn what world you're in. If PRODUCT.md's `## Platform` is `ios` or `android`, also read `reference/<platform>.md` (`adaptive` reads both).
|
||||
4. If the project is brand-new (no committed tokens, fonts, or brand colors found in step 3), run `node .kiro/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed breaks your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this step entirely when step 3 found committed brand colors: identity-preservation wins.
|
||||
|
||||
## How to design
|
||||
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this file warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this skill warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
|
||||
**Existing worlds are sacred.** When the surface already has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside it: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Treat the task as new identity work only when nothing committed exists, or when the user asks for a redesign that discards the current look. A redesign is new work: derive the concept from the subject and the brief, not from the incumbent page's structure or styling.
|
||||
**Existing worlds are sacred.** Most of impeccable's work happens inside a site or app that already exists. When the surface has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside that world: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Inventing parallel colors, fonts, or styles on an existing surface is a defect, not creativity.
|
||||
|
||||
**Ground it in the subject.** Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
**Plan, self-check, build.** Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
**Commit.** Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
**Calibration.** AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
**New identity work reads the playbook first.** When nothing committed exists (greenfield, or a codebase with no real tokens or chosen faces), or the user asks for a redesign that discards the current look, you MUST read [reference/new-work.md](reference/new-work.md) before making any design decision. Not optional, not skippable under time pressure: producing new identity without it yields the generic default this skill exists to prevent. A redesign is new work; derive the concept from the subject and the brief, not from the incumbent page's structure or styling. `context.mjs` prints this directive when it detects the situation. Scoped fixes inside an existing world don't need the playbook; the craft floor below governs them.
|
||||
|
||||
## Craft floor
|
||||
|
||||
@@ -52,7 +38,7 @@ Build to this floor without announcing it. The design detector (the project hook
|
||||
|
||||
Name the visitor's mode before designing; the page's grammar follows from it, and most ruined pages are one mode wearing another mode's grammar. The brief and the surface decide the mode. PRODUCT.md's `register` field names the family (`brand` covers Persuade and Experience; `product` covers Operate and Read), and `reference/brand.md` / `reference/product.md` carry extended depth for the two families.
|
||||
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans.
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Briefs that imply imagery must ship real, verified imagery; a colored rectangle where a photo belongs reads as incomplete. New Persuade surfaces take their typeface procedure and reject list from [reference/new-work.md](reference/new-work.md).
|
||||
|
||||
**Operate** (app UI, dashboards, admin, tools; design SERVES the task). A person getting something done: density, scanability, and consistency outrank expressiveness. These surfaces earn trust by feeling native to their platform: system font stacks and workhorse UI faces are legitimate and often correct here (the Persuade reject list does not apply). The brand lives in the details: focus states, empty states, microcopy, one owned accent.
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# New identity work
|
||||
|
||||
You are reading this because nothing committed exists yet (greenfield), or the user asked for a redesign that discards the current look. Either way the task is the same: invent a visual identity that could not be mistaken for anyone else's, and build it to the craft floor. SKILL.md's rules all still apply; this file is the process that produces the identity.
|
||||
|
||||
## Seed
|
||||
|
||||
If the project is brand-new (no committed tokens, fonts, or brand colors found in the code), run `node .kiro/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed exists to break your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this entirely when the code already has committed brand colors: identity-preservation wins.
|
||||
|
||||
## Ground it in the subject
|
||||
|
||||
Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
## Plan, self-check, build
|
||||
|
||||
Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
## Commit
|
||||
|
||||
Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
## Type and imagery for new Persuade and Experience surfaces
|
||||
|
||||
Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans. (For Operate and Read surfaces the opposite holds: system stacks and workhorse UI faces are legitimate and often correct.)
|
||||
|
||||
Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Verify stock URLs resolve before shipping them.
|
||||
|
||||
## Calibration
|
||||
|
||||
AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
|
||||
Before finishing, verify against SKILL.md's craft floor and run the detector; a bold page that ships mechanical defects is not done.
|
||||
@@ -904,6 +904,10 @@ async function cli() {
|
||||
'reference/init.md and write PRODUCT.md first; for any other (scoped) ' +
|
||||
'command against existing code, proceed using the code as context and ' +
|
||||
`offer \`${IMPECCABLE_COMMAND} init\` as a suggestion (do not block).`,
|
||||
'NEW_WORK: No committed design context was found. If this task produces ' +
|
||||
'new design (a build from scratch, or a redesign that discards the ' +
|
||||
'current look), you MUST read reference/new-work.md before making any ' +
|
||||
'design decision. Scoped fixes to existing code do not need it.',
|
||||
];
|
||||
parts.push(buildResolvedContextDirective(ctx, cliOptions, { targetExists }));
|
||||
if (shouldWarnMissingTarget(ctx, targetProvided, targetExists)) {
|
||||
@@ -922,10 +926,22 @@ async function cli() {
|
||||
parts.push(buildMissingTargetDirective());
|
||||
}
|
||||
const register = extractRegister(ctx.product);
|
||||
const next = register
|
||||
? `NEXT STEP: This project's register is \`${register}\`. You MUST now read \`reference/${register}.md\` before producing any design output.`
|
||||
: `NEXT STEP: You MUST now read the matching register reference (\`reference/brand.md\` or \`reference/product.md\`) before producing any design output. Pick based on PRODUCT.md above.`;
|
||||
parts.push(next);
|
||||
// The register field survives as a family hint (brand = Persuade/Experience,
|
||||
// product = Operate/Read); SKILL.md's mode section carries the essentials
|
||||
// inline, so no register-file read is mandated here. What IS mandated:
|
||||
// the new-work playbook when no committed design system exists yet.
|
||||
if (!ctx.hasDesign) {
|
||||
parts.push(
|
||||
'NEW_WORK: PRODUCT.md exists but no DESIGN.md was found. If the code ' +
|
||||
'has no committed design system either (check the project files), and ' +
|
||||
'this task produces new design or a redesign that discards the current ' +
|
||||
'look, you MUST read reference/new-work.md before making any design ' +
|
||||
'decision. Scoped fixes inside an existing design system do not need it.',
|
||||
);
|
||||
}
|
||||
if (register) {
|
||||
parts.push(`REGISTER: \`${register}\` (family hint: brand = Persuade/Experience surfaces, product = Operate/Read). Derive the visitor's mode per SKILL.md; \`reference/${register}.md\` has extended depth for substantial work.`);
|
||||
}
|
||||
const platform = extractPlatform(ctx.product);
|
||||
const nativeRefs =
|
||||
platform === 'adaptive' ? ['ios', 'android'] : platform === 'ios' || platform === 'android' ? [platform] : [];
|
||||
@@ -933,7 +949,7 @@ async function cli() {
|
||||
const refList = nativeRefs.map(p => `\`reference/${p}.md\``).join(' and ');
|
||||
const label = platform === 'adaptive' ? '`adaptive` (both iOS and Android)' : `\`${platform}\``;
|
||||
parts.push(
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to the register reference.`,
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to SKILL.md's mode guidance.`,
|
||||
);
|
||||
} else if (!platform) {
|
||||
// A `## Platform` section that names something we don't recognize (a
|
||||
|
||||
@@ -7105,6 +7105,14 @@
|
||||
}
|
||||
|
||||
async function captureAndEmit(el, basePayload, snapshot, rect) {
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
|
||||
// Plain requests do not send a screenshot to the agent, so capture is
|
||||
// presentation-only. Wait only for the helper to accept the event before
|
||||
// starting CPU-heavy capture; this yields the browser task and prevents
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) await sendEvent(basePayload);
|
||||
|
||||
let screenshotPath;
|
||||
let blob;
|
||||
let paper;
|
||||
@@ -7122,7 +7130,6 @@
|
||||
// are present. Without annotations the image is pure visual anchoring -
|
||||
// it biases the model toward the current rendering and works against the
|
||||
// three-distinct-directions brief.
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
if (blob && hasAnnotations) {
|
||||
try {
|
||||
const uploadRes = await fetch(
|
||||
@@ -7140,7 +7147,11 @@
|
||||
console.warn('[impeccable] annotation upload failed:', err);
|
||||
}
|
||||
}
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Annotated requests must wait for capture + upload because the screenshot
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: impeccable
|
||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||
version: 4.0.0-alpha.8
|
||||
version: 4.0.0-alpha.9
|
||||
user-invocable: true
|
||||
argument-hint: "[craft|shape · audit|critique · animate|bolder|colorize|delight|layout|overdrive|quieter|typeset · adapt|clarify|distill · harden|onboard|optimize|polish · init|document|extract|live] [target]"
|
||||
license: Apache 2.0
|
||||
@@ -19,27 +19,13 @@ Approach every design task as the design lead at a small studio known for giving
|
||||
1. Run `node .opencode/skills/impeccable/scripts/context.mjs` once per session (if the runtime shows this skill's loaded base directory, run `node <skill-base-dir>/scripts/context.mjs`; keep cwd at the user's project). It prints the project's PRODUCT.md and DESIGN.md when they exist; follow what it prints, including any `UPDATE_AVAILABLE` directive (ask once, never block). If it reports `NO_PRODUCT_MD`: for `init`, `teach`, `craft`, `shape`, or wording that clearly maps to a from-scratch build flow, divert into `reference/init.md` first, **unless no user can respond** (a one-shot or automated run, or the user said not to ask): then write your own one-paragraph understanding of the product, audience, and the page's job from the brief and continue. For scoped evaluate/refine/fix requests against existing code, never divert into init; the existing code is the context.
|
||||
2. If the user invoked a sub-command (`audit`, `polish`, `live`, ...), read **`reference/<command>.md`** (the `.native` variant from the Commands table when the platform is `ios`/`android`/`adaptive`) and follow it. On unattended runs, `craft` and `shape` collapse into this file's process: decide, record each decision in one line, build, self-review.
|
||||
3. Read at least one project file (CSS / tokens / theme / a representative component) to learn what world you're in. If PRODUCT.md's `## Platform` is `ios` or `android`, also read `reference/<platform>.md` (`adaptive` reads both).
|
||||
4. If the project is brand-new (no committed tokens, fonts, or brand colors found in step 3), run `node .opencode/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed breaks your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this step entirely when step 3 found committed brand colors: identity-preservation wins.
|
||||
|
||||
## How to design
|
||||
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this file warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this skill warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
|
||||
**Existing worlds are sacred.** When the surface already has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside it: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Treat the task as new identity work only when nothing committed exists, or when the user asks for a redesign that discards the current look. A redesign is new work: derive the concept from the subject and the brief, not from the incumbent page's structure or styling.
|
||||
**Existing worlds are sacred.** Most of impeccable's work happens inside a site or app that already exists. When the surface has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside that world: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Inventing parallel colors, fonts, or styles on an existing surface is a defect, not creativity.
|
||||
|
||||
**Ground it in the subject.** Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
**Plan, self-check, build.** Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
**Commit.** Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
**Calibration.** AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
**New identity work reads the playbook first.** When nothing committed exists (greenfield, or a codebase with no real tokens or chosen faces), or the user asks for a redesign that discards the current look, you MUST read [reference/new-work.md](reference/new-work.md) before making any design decision. Not optional, not skippable under time pressure: producing new identity without it yields the generic default this skill exists to prevent. A redesign is new work; derive the concept from the subject and the brief, not from the incumbent page's structure or styling. `context.mjs` prints this directive when it detects the situation. Scoped fixes inside an existing world don't need the playbook; the craft floor below governs them.
|
||||
|
||||
## Craft floor
|
||||
|
||||
@@ -57,7 +43,7 @@ Build to this floor without announcing it. The design detector (the project hook
|
||||
|
||||
Name the visitor's mode before designing; the page's grammar follows from it, and most ruined pages are one mode wearing another mode's grammar. The brief and the surface decide the mode. PRODUCT.md's `register` field names the family (`brand` covers Persuade and Experience; `product` covers Operate and Read), and `reference/brand.md` / `reference/product.md` carry extended depth for the two families.
|
||||
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans.
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Briefs that imply imagery must ship real, verified imagery; a colored rectangle where a photo belongs reads as incomplete. New Persuade surfaces take their typeface procedure and reject list from [reference/new-work.md](reference/new-work.md).
|
||||
|
||||
**Operate** (app UI, dashboards, admin, tools; design SERVES the task). A person getting something done: density, scanability, and consistency outrank expressiveness. These surfaces earn trust by feeling native to their platform: system font stacks and workhorse UI faces are legitimate and often correct here (the Persuade reject list does not apply). The brand lives in the details: focus states, empty states, microcopy, one owned accent.
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# New identity work
|
||||
|
||||
You are reading this because nothing committed exists yet (greenfield), or the user asked for a redesign that discards the current look. Either way the task is the same: invent a visual identity that could not be mistaken for anyone else's, and build it to the craft floor. SKILL.md's rules all still apply; this file is the process that produces the identity.
|
||||
|
||||
## Seed
|
||||
|
||||
If the project is brand-new (no committed tokens, fonts, or brand colors found in the code), run `node .opencode/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed exists to break your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this entirely when the code already has committed brand colors: identity-preservation wins.
|
||||
|
||||
## Ground it in the subject
|
||||
|
||||
Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
## Plan, self-check, build
|
||||
|
||||
Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
## Commit
|
||||
|
||||
Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
## Type and imagery for new Persuade and Experience surfaces
|
||||
|
||||
Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans. (For Operate and Read surfaces the opposite holds: system stacks and workhorse UI faces are legitimate and often correct.)
|
||||
|
||||
Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Verify stock URLs resolve before shipping them.
|
||||
|
||||
## Calibration
|
||||
|
||||
AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
|
||||
Before finishing, verify against SKILL.md's craft floor and run the detector; a bold page that ships mechanical defects is not done.
|
||||
@@ -904,6 +904,10 @@ async function cli() {
|
||||
'reference/init.md and write PRODUCT.md first; for any other (scoped) ' +
|
||||
'command against existing code, proceed using the code as context and ' +
|
||||
`offer \`${IMPECCABLE_COMMAND} init\` as a suggestion (do not block).`,
|
||||
'NEW_WORK: No committed design context was found. If this task produces ' +
|
||||
'new design (a build from scratch, or a redesign that discards the ' +
|
||||
'current look), you MUST read reference/new-work.md before making any ' +
|
||||
'design decision. Scoped fixes to existing code do not need it.',
|
||||
];
|
||||
parts.push(buildResolvedContextDirective(ctx, cliOptions, { targetExists }));
|
||||
if (shouldWarnMissingTarget(ctx, targetProvided, targetExists)) {
|
||||
@@ -922,10 +926,22 @@ async function cli() {
|
||||
parts.push(buildMissingTargetDirective());
|
||||
}
|
||||
const register = extractRegister(ctx.product);
|
||||
const next = register
|
||||
? `NEXT STEP: This project's register is \`${register}\`. You MUST now read \`reference/${register}.md\` before producing any design output.`
|
||||
: `NEXT STEP: You MUST now read the matching register reference (\`reference/brand.md\` or \`reference/product.md\`) before producing any design output. Pick based on PRODUCT.md above.`;
|
||||
parts.push(next);
|
||||
// The register field survives as a family hint (brand = Persuade/Experience,
|
||||
// product = Operate/Read); SKILL.md's mode section carries the essentials
|
||||
// inline, so no register-file read is mandated here. What IS mandated:
|
||||
// the new-work playbook when no committed design system exists yet.
|
||||
if (!ctx.hasDesign) {
|
||||
parts.push(
|
||||
'NEW_WORK: PRODUCT.md exists but no DESIGN.md was found. If the code ' +
|
||||
'has no committed design system either (check the project files), and ' +
|
||||
'this task produces new design or a redesign that discards the current ' +
|
||||
'look, you MUST read reference/new-work.md before making any design ' +
|
||||
'decision. Scoped fixes inside an existing design system do not need it.',
|
||||
);
|
||||
}
|
||||
if (register) {
|
||||
parts.push(`REGISTER: \`${register}\` (family hint: brand = Persuade/Experience surfaces, product = Operate/Read). Derive the visitor's mode per SKILL.md; \`reference/${register}.md\` has extended depth for substantial work.`);
|
||||
}
|
||||
const platform = extractPlatform(ctx.product);
|
||||
const nativeRefs =
|
||||
platform === 'adaptive' ? ['ios', 'android'] : platform === 'ios' || platform === 'android' ? [platform] : [];
|
||||
@@ -933,7 +949,7 @@ async function cli() {
|
||||
const refList = nativeRefs.map(p => `\`reference/${p}.md\``).join(' and ');
|
||||
const label = platform === 'adaptive' ? '`adaptive` (both iOS and Android)' : `\`${platform}\``;
|
||||
parts.push(
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to the register reference.`,
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to SKILL.md's mode guidance.`,
|
||||
);
|
||||
} else if (!platform) {
|
||||
// A `## Platform` section that names something we don't recognize (a
|
||||
|
||||
@@ -7105,6 +7105,14 @@
|
||||
}
|
||||
|
||||
async function captureAndEmit(el, basePayload, snapshot, rect) {
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
|
||||
// Plain requests do not send a screenshot to the agent, so capture is
|
||||
// presentation-only. Wait only for the helper to accept the event before
|
||||
// starting CPU-heavy capture; this yields the browser task and prevents
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) await sendEvent(basePayload);
|
||||
|
||||
let screenshotPath;
|
||||
let blob;
|
||||
let paper;
|
||||
@@ -7122,7 +7130,6 @@
|
||||
// are present. Without annotations the image is pure visual anchoring -
|
||||
// it biases the model toward the current rendering and works against the
|
||||
// three-distinct-directions brief.
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
if (blob && hasAnnotations) {
|
||||
try {
|
||||
const uploadRes = await fetch(
|
||||
@@ -7140,7 +7147,11 @@
|
||||
console.warn('[impeccable] annotation upload failed:', err);
|
||||
}
|
||||
}
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Annotated requests must wait for capture + upload because the screenshot
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: impeccable
|
||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||
version: 4.0.0-alpha.8
|
||||
version: 4.0.0-alpha.9
|
||||
license: Apache 2.0
|
||||
allowed-tools:
|
||||
- Bash(npx impeccable *)
|
||||
@@ -17,27 +17,13 @@ Approach every design task as the design lead at a small studio known for giving
|
||||
1. Run `node .pi/skills/impeccable/scripts/context.mjs` once per session (if the runtime shows this skill's loaded base directory, run `node <skill-base-dir>/scripts/context.mjs`; keep cwd at the user's project). It prints the project's PRODUCT.md and DESIGN.md when they exist; follow what it prints, including any `UPDATE_AVAILABLE` directive (ask once, never block). If it reports `NO_PRODUCT_MD`: for `init`, `teach`, `craft`, `shape`, or wording that clearly maps to a from-scratch build flow, divert into `reference/init.md` first, **unless no user can respond** (a one-shot or automated run, or the user said not to ask): then write your own one-paragraph understanding of the product, audience, and the page's job from the brief and continue. For scoped evaluate/refine/fix requests against existing code, never divert into init; the existing code is the context.
|
||||
2. If the user invoked a sub-command (`audit`, `polish`, `live`, ...), read **`reference/<command>.md`** (the `.native` variant from the Commands table when the platform is `ios`/`android`/`adaptive`) and follow it. On unattended runs, `craft` and `shape` collapse into this file's process: decide, record each decision in one line, build, self-review.
|
||||
3. Read at least one project file (CSS / tokens / theme / a representative component) to learn what world you're in. If PRODUCT.md's `## Platform` is `ios` or `android`, also read `reference/<platform>.md` (`adaptive` reads both).
|
||||
4. If the project is brand-new (no committed tokens, fonts, or brand colors found in step 3), run `node .pi/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed breaks your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this step entirely when step 3 found committed brand colors: identity-preservation wins.
|
||||
|
||||
## How to design
|
||||
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this file warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this skill warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
|
||||
**Existing worlds are sacred.** When the surface already has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside it: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Treat the task as new identity work only when nothing committed exists, or when the user asks for a redesign that discards the current look. A redesign is new work: derive the concept from the subject and the brief, not from the incumbent page's structure or styling.
|
||||
**Existing worlds are sacred.** Most of impeccable's work happens inside a site or app that already exists. When the surface has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside that world: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Inventing parallel colors, fonts, or styles on an existing surface is a defect, not creativity.
|
||||
|
||||
**Ground it in the subject.** Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
**Plan, self-check, build.** Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
**Commit.** Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
**Calibration.** AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
**New identity work reads the playbook first.** When nothing committed exists (greenfield, or a codebase with no real tokens or chosen faces), or the user asks for a redesign that discards the current look, you MUST read [reference/new-work.md](reference/new-work.md) before making any design decision. Not optional, not skippable under time pressure: producing new identity without it yields the generic default this skill exists to prevent. A redesign is new work; derive the concept from the subject and the brief, not from the incumbent page's structure or styling. `context.mjs` prints this directive when it detects the situation. Scoped fixes inside an existing world don't need the playbook; the craft floor below governs them.
|
||||
|
||||
## Craft floor
|
||||
|
||||
@@ -55,7 +41,7 @@ Build to this floor without announcing it. The design detector (the project hook
|
||||
|
||||
Name the visitor's mode before designing; the page's grammar follows from it, and most ruined pages are one mode wearing another mode's grammar. The brief and the surface decide the mode. PRODUCT.md's `register` field names the family (`brand` covers Persuade and Experience; `product` covers Operate and Read), and `reference/brand.md` / `reference/product.md` carry extended depth for the two families.
|
||||
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans.
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Briefs that imply imagery must ship real, verified imagery; a colored rectangle where a photo belongs reads as incomplete. New Persuade surfaces take their typeface procedure and reject list from [reference/new-work.md](reference/new-work.md).
|
||||
|
||||
**Operate** (app UI, dashboards, admin, tools; design SERVES the task). A person getting something done: density, scanability, and consistency outrank expressiveness. These surfaces earn trust by feeling native to their platform: system font stacks and workhorse UI faces are legitimate and often correct here (the Persuade reject list does not apply). The brand lives in the details: focus states, empty states, microcopy, one owned accent.
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# New identity work
|
||||
|
||||
You are reading this because nothing committed exists yet (greenfield), or the user asked for a redesign that discards the current look. Either way the task is the same: invent a visual identity that could not be mistaken for anyone else's, and build it to the craft floor. SKILL.md's rules all still apply; this file is the process that produces the identity.
|
||||
|
||||
## Seed
|
||||
|
||||
If the project is brand-new (no committed tokens, fonts, or brand colors found in the code), run `node .pi/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed exists to break your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this entirely when the code already has committed brand colors: identity-preservation wins.
|
||||
|
||||
## Ground it in the subject
|
||||
|
||||
Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
## Plan, self-check, build
|
||||
|
||||
Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
## Commit
|
||||
|
||||
Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
## Type and imagery for new Persuade and Experience surfaces
|
||||
|
||||
Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans. (For Operate and Read surfaces the opposite holds: system stacks and workhorse UI faces are legitimate and often correct.)
|
||||
|
||||
Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Verify stock URLs resolve before shipping them.
|
||||
|
||||
## Calibration
|
||||
|
||||
AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
|
||||
Before finishing, verify against SKILL.md's craft floor and run the detector; a bold page that ships mechanical defects is not done.
|
||||
@@ -904,6 +904,10 @@ async function cli() {
|
||||
'reference/init.md and write PRODUCT.md first; for any other (scoped) ' +
|
||||
'command against existing code, proceed using the code as context and ' +
|
||||
`offer \`${IMPECCABLE_COMMAND} init\` as a suggestion (do not block).`,
|
||||
'NEW_WORK: No committed design context was found. If this task produces ' +
|
||||
'new design (a build from scratch, or a redesign that discards the ' +
|
||||
'current look), you MUST read reference/new-work.md before making any ' +
|
||||
'design decision. Scoped fixes to existing code do not need it.',
|
||||
];
|
||||
parts.push(buildResolvedContextDirective(ctx, cliOptions, { targetExists }));
|
||||
if (shouldWarnMissingTarget(ctx, targetProvided, targetExists)) {
|
||||
@@ -922,10 +926,22 @@ async function cli() {
|
||||
parts.push(buildMissingTargetDirective());
|
||||
}
|
||||
const register = extractRegister(ctx.product);
|
||||
const next = register
|
||||
? `NEXT STEP: This project's register is \`${register}\`. You MUST now read \`reference/${register}.md\` before producing any design output.`
|
||||
: `NEXT STEP: You MUST now read the matching register reference (\`reference/brand.md\` or \`reference/product.md\`) before producing any design output. Pick based on PRODUCT.md above.`;
|
||||
parts.push(next);
|
||||
// The register field survives as a family hint (brand = Persuade/Experience,
|
||||
// product = Operate/Read); SKILL.md's mode section carries the essentials
|
||||
// inline, so no register-file read is mandated here. What IS mandated:
|
||||
// the new-work playbook when no committed design system exists yet.
|
||||
if (!ctx.hasDesign) {
|
||||
parts.push(
|
||||
'NEW_WORK: PRODUCT.md exists but no DESIGN.md was found. If the code ' +
|
||||
'has no committed design system either (check the project files), and ' +
|
||||
'this task produces new design or a redesign that discards the current ' +
|
||||
'look, you MUST read reference/new-work.md before making any design ' +
|
||||
'decision. Scoped fixes inside an existing design system do not need it.',
|
||||
);
|
||||
}
|
||||
if (register) {
|
||||
parts.push(`REGISTER: \`${register}\` (family hint: brand = Persuade/Experience surfaces, product = Operate/Read). Derive the visitor's mode per SKILL.md; \`reference/${register}.md\` has extended depth for substantial work.`);
|
||||
}
|
||||
const platform = extractPlatform(ctx.product);
|
||||
const nativeRefs =
|
||||
platform === 'adaptive' ? ['ios', 'android'] : platform === 'ios' || platform === 'android' ? [platform] : [];
|
||||
@@ -933,7 +949,7 @@ async function cli() {
|
||||
const refList = nativeRefs.map(p => `\`reference/${p}.md\``).join(' and ');
|
||||
const label = platform === 'adaptive' ? '`adaptive` (both iOS and Android)' : `\`${platform}\``;
|
||||
parts.push(
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to the register reference.`,
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to SKILL.md's mode guidance.`,
|
||||
);
|
||||
} else if (!platform) {
|
||||
// A `## Platform` section that names something we don't recognize (a
|
||||
|
||||
@@ -7105,6 +7105,14 @@
|
||||
}
|
||||
|
||||
async function captureAndEmit(el, basePayload, snapshot, rect) {
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
|
||||
// Plain requests do not send a screenshot to the agent, so capture is
|
||||
// presentation-only. Wait only for the helper to accept the event before
|
||||
// starting CPU-heavy capture; this yields the browser task and prevents
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) await sendEvent(basePayload);
|
||||
|
||||
let screenshotPath;
|
||||
let blob;
|
||||
let paper;
|
||||
@@ -7122,7 +7130,6 @@
|
||||
// are present. Without annotations the image is pure visual anchoring -
|
||||
// it biases the model toward the current rendering and works against the
|
||||
// three-distinct-directions brief.
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
if (blob && hasAnnotations) {
|
||||
try {
|
||||
const uploadRes = await fetch(
|
||||
@@ -7140,7 +7147,11 @@
|
||||
console.warn('[impeccable] annotation upload failed:', err);
|
||||
}
|
||||
}
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Annotated requests must wait for capture + upload because the screenshot
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: impeccable
|
||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||
version: 4.0.0-alpha.8
|
||||
version: 4.0.0-alpha.9
|
||||
user-invocable: true
|
||||
argument-hint: "[craft|shape · audit|critique · animate|bolder|colorize|delight|layout|overdrive|quieter|typeset · adapt|clarify|distill · harden|onboard|optimize|polish · init|document|extract|live] [target]"
|
||||
license: Apache 2.0
|
||||
@@ -19,27 +19,13 @@ Approach every design task as the design lead at a small studio known for giving
|
||||
1. Run `node .qoder/skills/impeccable/scripts/context.mjs` once per session (if the runtime shows this skill's loaded base directory, run `node <skill-base-dir>/scripts/context.mjs`; keep cwd at the user's project). It prints the project's PRODUCT.md and DESIGN.md when they exist; follow what it prints, including any `UPDATE_AVAILABLE` directive (ask once, never block). If it reports `NO_PRODUCT_MD`: for `init`, `teach`, `craft`, `shape`, or wording that clearly maps to a from-scratch build flow, divert into `reference/init.md` first, **unless no user can respond** (a one-shot or automated run, or the user said not to ask): then write your own one-paragraph understanding of the product, audience, and the page's job from the brief and continue. For scoped evaluate/refine/fix requests against existing code, never divert into init; the existing code is the context.
|
||||
2. If the user invoked a sub-command (`audit`, `polish`, `live`, ...), read **`reference/<command>.md`** (the `.native` variant from the Commands table when the platform is `ios`/`android`/`adaptive`) and follow it. On unattended runs, `craft` and `shape` collapse into this file's process: decide, record each decision in one line, build, self-review.
|
||||
3. Read at least one project file (CSS / tokens / theme / a representative component) to learn what world you're in. If PRODUCT.md's `## Platform` is `ios` or `android`, also read `reference/<platform>.md` (`adaptive` reads both).
|
||||
4. If the project is brand-new (no committed tokens, fonts, or brand colors found in step 3), run `node .qoder/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed breaks your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this step entirely when step 3 found committed brand colors: identity-preservation wins.
|
||||
|
||||
## How to design
|
||||
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this file warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this skill warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
|
||||
**Existing worlds are sacred.** When the surface already has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside it: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Treat the task as new identity work only when nothing committed exists, or when the user asks for a redesign that discards the current look. A redesign is new work: derive the concept from the subject and the brief, not from the incumbent page's structure or styling.
|
||||
**Existing worlds are sacred.** Most of impeccable's work happens inside a site or app that already exists. When the surface has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside that world: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Inventing parallel colors, fonts, or styles on an existing surface is a defect, not creativity.
|
||||
|
||||
**Ground it in the subject.** Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
**Plan, self-check, build.** Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
**Commit.** Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
**Calibration.** AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
**New identity work reads the playbook first.** When nothing committed exists (greenfield, or a codebase with no real tokens or chosen faces), or the user asks for a redesign that discards the current look, you MUST read [reference/new-work.md](reference/new-work.md) before making any design decision. Not optional, not skippable under time pressure: producing new identity without it yields the generic default this skill exists to prevent. A redesign is new work; derive the concept from the subject and the brief, not from the incumbent page's structure or styling. `context.mjs` prints this directive when it detects the situation. Scoped fixes inside an existing world don't need the playbook; the craft floor below governs them.
|
||||
|
||||
## Craft floor
|
||||
|
||||
@@ -57,7 +43,7 @@ Build to this floor without announcing it. The design detector (the project hook
|
||||
|
||||
Name the visitor's mode before designing; the page's grammar follows from it, and most ruined pages are one mode wearing another mode's grammar. The brief and the surface decide the mode. PRODUCT.md's `register` field names the family (`brand` covers Persuade and Experience; `product` covers Operate and Read), and `reference/brand.md` / `reference/product.md` carry extended depth for the two families.
|
||||
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans.
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Briefs that imply imagery must ship real, verified imagery; a colored rectangle where a photo belongs reads as incomplete. New Persuade surfaces take their typeface procedure and reject list from [reference/new-work.md](reference/new-work.md).
|
||||
|
||||
**Operate** (app UI, dashboards, admin, tools; design SERVES the task). A person getting something done: density, scanability, and consistency outrank expressiveness. These surfaces earn trust by feeling native to their platform: system font stacks and workhorse UI faces are legitimate and often correct here (the Persuade reject list does not apply). The brand lives in the details: focus states, empty states, microcopy, one owned accent.
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# New identity work
|
||||
|
||||
You are reading this because nothing committed exists yet (greenfield), or the user asked for a redesign that discards the current look. Either way the task is the same: invent a visual identity that could not be mistaken for anyone else's, and build it to the craft floor. SKILL.md's rules all still apply; this file is the process that produces the identity.
|
||||
|
||||
## Seed
|
||||
|
||||
If the project is brand-new (no committed tokens, fonts, or brand colors found in the code), run `node .qoder/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed exists to break your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this entirely when the code already has committed brand colors: identity-preservation wins.
|
||||
|
||||
## Ground it in the subject
|
||||
|
||||
Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
## Plan, self-check, build
|
||||
|
||||
Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
## Commit
|
||||
|
||||
Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
## Type and imagery for new Persuade and Experience surfaces
|
||||
|
||||
Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans. (For Operate and Read surfaces the opposite holds: system stacks and workhorse UI faces are legitimate and often correct.)
|
||||
|
||||
Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Verify stock URLs resolve before shipping them.
|
||||
|
||||
## Calibration
|
||||
|
||||
AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
|
||||
Before finishing, verify against SKILL.md's craft floor and run the detector; a bold page that ships mechanical defects is not done.
|
||||
@@ -904,6 +904,10 @@ async function cli() {
|
||||
'reference/init.md and write PRODUCT.md first; for any other (scoped) ' +
|
||||
'command against existing code, proceed using the code as context and ' +
|
||||
`offer \`${IMPECCABLE_COMMAND} init\` as a suggestion (do not block).`,
|
||||
'NEW_WORK: No committed design context was found. If this task produces ' +
|
||||
'new design (a build from scratch, or a redesign that discards the ' +
|
||||
'current look), you MUST read reference/new-work.md before making any ' +
|
||||
'design decision. Scoped fixes to existing code do not need it.',
|
||||
];
|
||||
parts.push(buildResolvedContextDirective(ctx, cliOptions, { targetExists }));
|
||||
if (shouldWarnMissingTarget(ctx, targetProvided, targetExists)) {
|
||||
@@ -922,10 +926,22 @@ async function cli() {
|
||||
parts.push(buildMissingTargetDirective());
|
||||
}
|
||||
const register = extractRegister(ctx.product);
|
||||
const next = register
|
||||
? `NEXT STEP: This project's register is \`${register}\`. You MUST now read \`reference/${register}.md\` before producing any design output.`
|
||||
: `NEXT STEP: You MUST now read the matching register reference (\`reference/brand.md\` or \`reference/product.md\`) before producing any design output. Pick based on PRODUCT.md above.`;
|
||||
parts.push(next);
|
||||
// The register field survives as a family hint (brand = Persuade/Experience,
|
||||
// product = Operate/Read); SKILL.md's mode section carries the essentials
|
||||
// inline, so no register-file read is mandated here. What IS mandated:
|
||||
// the new-work playbook when no committed design system exists yet.
|
||||
if (!ctx.hasDesign) {
|
||||
parts.push(
|
||||
'NEW_WORK: PRODUCT.md exists but no DESIGN.md was found. If the code ' +
|
||||
'has no committed design system either (check the project files), and ' +
|
||||
'this task produces new design or a redesign that discards the current ' +
|
||||
'look, you MUST read reference/new-work.md before making any design ' +
|
||||
'decision. Scoped fixes inside an existing design system do not need it.',
|
||||
);
|
||||
}
|
||||
if (register) {
|
||||
parts.push(`REGISTER: \`${register}\` (family hint: brand = Persuade/Experience surfaces, product = Operate/Read). Derive the visitor's mode per SKILL.md; \`reference/${register}.md\` has extended depth for substantial work.`);
|
||||
}
|
||||
const platform = extractPlatform(ctx.product);
|
||||
const nativeRefs =
|
||||
platform === 'adaptive' ? ['ios', 'android'] : platform === 'ios' || platform === 'android' ? [platform] : [];
|
||||
@@ -933,7 +949,7 @@ async function cli() {
|
||||
const refList = nativeRefs.map(p => `\`reference/${p}.md\``).join(' and ');
|
||||
const label = platform === 'adaptive' ? '`adaptive` (both iOS and Android)' : `\`${platform}\``;
|
||||
parts.push(
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to the register reference.`,
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to SKILL.md's mode guidance.`,
|
||||
);
|
||||
} else if (!platform) {
|
||||
// A `## Platform` section that names something we don't recognize (a
|
||||
|
||||
@@ -7105,6 +7105,14 @@
|
||||
}
|
||||
|
||||
async function captureAndEmit(el, basePayload, snapshot, rect) {
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
|
||||
// Plain requests do not send a screenshot to the agent, so capture is
|
||||
// presentation-only. Wait only for the helper to accept the event before
|
||||
// starting CPU-heavy capture; this yields the browser task and prevents
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) await sendEvent(basePayload);
|
||||
|
||||
let screenshotPath;
|
||||
let blob;
|
||||
let paper;
|
||||
@@ -7122,7 +7130,6 @@
|
||||
// are present. Without annotations the image is pure visual anchoring -
|
||||
// it biases the model toward the current rendering and works against the
|
||||
// three-distinct-directions brief.
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
if (blob && hasAnnotations) {
|
||||
try {
|
||||
const uploadRes = await fetch(
|
||||
@@ -7140,7 +7147,11 @@
|
||||
console.warn('[impeccable] annotation upload failed:', err);
|
||||
}
|
||||
}
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Annotated requests must wait for capture + upload because the screenshot
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: impeccable
|
||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||
version: 4.0.0-alpha.8
|
||||
version: 4.0.0-alpha.9
|
||||
user-invocable: true
|
||||
argument-hint: "[craft|shape · audit|critique · animate|bolder|colorize|delight|layout|overdrive|quieter|typeset · adapt|clarify|distill · harden|onboard|optimize|polish · init|document|extract|live] [target]"
|
||||
license: Apache 2.0
|
||||
@@ -19,27 +19,13 @@ Approach every design task as the design lead at a small studio known for giving
|
||||
1. Run `node .rovodev/skills/impeccable/scripts/context.mjs` once per session (if the runtime shows this skill's loaded base directory, run `node <skill-base-dir>/scripts/context.mjs`; keep cwd at the user's project). It prints the project's PRODUCT.md and DESIGN.md when they exist; follow what it prints, including any `UPDATE_AVAILABLE` directive (ask once, never block). If it reports `NO_PRODUCT_MD`: for `init`, `teach`, `craft`, `shape`, or wording that clearly maps to a from-scratch build flow, divert into `reference/init.md` first, **unless no user can respond** (a one-shot or automated run, or the user said not to ask): then write your own one-paragraph understanding of the product, audience, and the page's job from the brief and continue. For scoped evaluate/refine/fix requests against existing code, never divert into init; the existing code is the context.
|
||||
2. If the user invoked a sub-command (`audit`, `polish`, `live`, ...), read **`reference/<command>.md`** (the `.native` variant from the Commands table when the platform is `ios`/`android`/`adaptive`) and follow it. On unattended runs, `craft` and `shape` collapse into this file's process: decide, record each decision in one line, build, self-review.
|
||||
3. Read at least one project file (CSS / tokens / theme / a representative component) to learn what world you're in. If PRODUCT.md's `## Platform` is `ios` or `android`, also read `reference/<platform>.md` (`adaptive` reads both).
|
||||
4. If the project is brand-new (no committed tokens, fonts, or brand colors found in step 3), run `node .rovodev/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed breaks your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this step entirely when step 3 found committed brand colors: identity-preservation wins.
|
||||
|
||||
## How to design
|
||||
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this file warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this skill warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
|
||||
**Existing worlds are sacred.** When the surface already has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside it: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Treat the task as new identity work only when nothing committed exists, or when the user asks for a redesign that discards the current look. A redesign is new work: derive the concept from the subject and the brief, not from the incumbent page's structure or styling.
|
||||
**Existing worlds are sacred.** Most of impeccable's work happens inside a site or app that already exists. When the surface has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside that world: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Inventing parallel colors, fonts, or styles on an existing surface is a defect, not creativity.
|
||||
|
||||
**Ground it in the subject.** Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
**Plan, self-check, build.** Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
**Commit.** Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
**Calibration.** AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
**New identity work reads the playbook first.** When nothing committed exists (greenfield, or a codebase with no real tokens or chosen faces), or the user asks for a redesign that discards the current look, you MUST read [reference/new-work.md](reference/new-work.md) before making any design decision. Not optional, not skippable under time pressure: producing new identity without it yields the generic default this skill exists to prevent. A redesign is new work; derive the concept from the subject and the brief, not from the incumbent page's structure or styling. `context.mjs` prints this directive when it detects the situation. Scoped fixes inside an existing world don't need the playbook; the craft floor below governs them.
|
||||
|
||||
## Craft floor
|
||||
|
||||
@@ -57,7 +43,7 @@ Build to this floor without announcing it. The design detector (the project hook
|
||||
|
||||
Name the visitor's mode before designing; the page's grammar follows from it, and most ruined pages are one mode wearing another mode's grammar. The brief and the surface decide the mode. PRODUCT.md's `register` field names the family (`brand` covers Persuade and Experience; `product` covers Operate and Read), and `reference/brand.md` / `reference/product.md` carry extended depth for the two families.
|
||||
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans.
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Briefs that imply imagery must ship real, verified imagery; a colored rectangle where a photo belongs reads as incomplete. New Persuade surfaces take their typeface procedure and reject list from [reference/new-work.md](reference/new-work.md).
|
||||
|
||||
**Operate** (app UI, dashboards, admin, tools; design SERVES the task). A person getting something done: density, scanability, and consistency outrank expressiveness. These surfaces earn trust by feeling native to their platform: system font stacks and workhorse UI faces are legitimate and often correct here (the Persuade reject list does not apply). The brand lives in the details: focus states, empty states, microcopy, one owned accent.
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# New identity work
|
||||
|
||||
You are reading this because nothing committed exists yet (greenfield), or the user asked for a redesign that discards the current look. Either way the task is the same: invent a visual identity that could not be mistaken for anyone else's, and build it to the craft floor. SKILL.md's rules all still apply; this file is the process that produces the identity.
|
||||
|
||||
## Seed
|
||||
|
||||
If the project is brand-new (no committed tokens, fonts, or brand colors found in the code), run `node .rovodev/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed exists to break your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this entirely when the code already has committed brand colors: identity-preservation wins.
|
||||
|
||||
## Ground it in the subject
|
||||
|
||||
Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
## Plan, self-check, build
|
||||
|
||||
Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
## Commit
|
||||
|
||||
Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
## Type and imagery for new Persuade and Experience surfaces
|
||||
|
||||
Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans. (For Operate and Read surfaces the opposite holds: system stacks and workhorse UI faces are legitimate and often correct.)
|
||||
|
||||
Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Verify stock URLs resolve before shipping them.
|
||||
|
||||
## Calibration
|
||||
|
||||
AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
|
||||
Before finishing, verify against SKILL.md's craft floor and run the detector; a bold page that ships mechanical defects is not done.
|
||||
@@ -904,6 +904,10 @@ async function cli() {
|
||||
'reference/init.md and write PRODUCT.md first; for any other (scoped) ' +
|
||||
'command against existing code, proceed using the code as context and ' +
|
||||
`offer \`${IMPECCABLE_COMMAND} init\` as a suggestion (do not block).`,
|
||||
'NEW_WORK: No committed design context was found. If this task produces ' +
|
||||
'new design (a build from scratch, or a redesign that discards the ' +
|
||||
'current look), you MUST read reference/new-work.md before making any ' +
|
||||
'design decision. Scoped fixes to existing code do not need it.',
|
||||
];
|
||||
parts.push(buildResolvedContextDirective(ctx, cliOptions, { targetExists }));
|
||||
if (shouldWarnMissingTarget(ctx, targetProvided, targetExists)) {
|
||||
@@ -922,10 +926,22 @@ async function cli() {
|
||||
parts.push(buildMissingTargetDirective());
|
||||
}
|
||||
const register = extractRegister(ctx.product);
|
||||
const next = register
|
||||
? `NEXT STEP: This project's register is \`${register}\`. You MUST now read \`reference/${register}.md\` before producing any design output.`
|
||||
: `NEXT STEP: You MUST now read the matching register reference (\`reference/brand.md\` or \`reference/product.md\`) before producing any design output. Pick based on PRODUCT.md above.`;
|
||||
parts.push(next);
|
||||
// The register field survives as a family hint (brand = Persuade/Experience,
|
||||
// product = Operate/Read); SKILL.md's mode section carries the essentials
|
||||
// inline, so no register-file read is mandated here. What IS mandated:
|
||||
// the new-work playbook when no committed design system exists yet.
|
||||
if (!ctx.hasDesign) {
|
||||
parts.push(
|
||||
'NEW_WORK: PRODUCT.md exists but no DESIGN.md was found. If the code ' +
|
||||
'has no committed design system either (check the project files), and ' +
|
||||
'this task produces new design or a redesign that discards the current ' +
|
||||
'look, you MUST read reference/new-work.md before making any design ' +
|
||||
'decision. Scoped fixes inside an existing design system do not need it.',
|
||||
);
|
||||
}
|
||||
if (register) {
|
||||
parts.push(`REGISTER: \`${register}\` (family hint: brand = Persuade/Experience surfaces, product = Operate/Read). Derive the visitor's mode per SKILL.md; \`reference/${register}.md\` has extended depth for substantial work.`);
|
||||
}
|
||||
const platform = extractPlatform(ctx.product);
|
||||
const nativeRefs =
|
||||
platform === 'adaptive' ? ['ios', 'android'] : platform === 'ios' || platform === 'android' ? [platform] : [];
|
||||
@@ -933,7 +949,7 @@ async function cli() {
|
||||
const refList = nativeRefs.map(p => `\`reference/${p}.md\``).join(' and ');
|
||||
const label = platform === 'adaptive' ? '`adaptive` (both iOS and Android)' : `\`${platform}\``;
|
||||
parts.push(
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to the register reference.`,
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to SKILL.md's mode guidance.`,
|
||||
);
|
||||
} else if (!platform) {
|
||||
// A `## Platform` section that names something we don't recognize (a
|
||||
|
||||
@@ -7105,6 +7105,14 @@
|
||||
}
|
||||
|
||||
async function captureAndEmit(el, basePayload, snapshot, rect) {
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
|
||||
// Plain requests do not send a screenshot to the agent, so capture is
|
||||
// presentation-only. Wait only for the helper to accept the event before
|
||||
// starting CPU-heavy capture; this yields the browser task and prevents
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) await sendEvent(basePayload);
|
||||
|
||||
let screenshotPath;
|
||||
let blob;
|
||||
let paper;
|
||||
@@ -7122,7 +7130,6 @@
|
||||
// are present. Without annotations the image is pure visual anchoring -
|
||||
// it biases the model toward the current rendering and works against the
|
||||
// three-distinct-directions brief.
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
if (blob && hasAnnotations) {
|
||||
try {
|
||||
const uploadRes = await fetch(
|
||||
@@ -7140,7 +7147,11 @@
|
||||
console.warn('[impeccable] annotation upload failed:', err);
|
||||
}
|
||||
}
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Annotated requests must wait for capture + upload because the screenshot
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: impeccable
|
||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||
version: 4.0.0-alpha.8
|
||||
version: 4.0.0-alpha.9
|
||||
user-invocable: true
|
||||
argument-hint: "[craft|shape · audit|critique · animate|bolder|colorize|delight|layout|overdrive|quieter|typeset · adapt|clarify|distill · harden|onboard|optimize|polish · init|document|extract|live] [target]"
|
||||
license: Apache 2.0
|
||||
@@ -16,27 +16,13 @@ Approach every design task as the design lead at a small studio known for giving
|
||||
1. Run `node .trae-cn/skills/impeccable/scripts/context.mjs` once per session (if the runtime shows this skill's loaded base directory, run `node <skill-base-dir>/scripts/context.mjs`; keep cwd at the user's project). It prints the project's PRODUCT.md and DESIGN.md when they exist; follow what it prints, including any `UPDATE_AVAILABLE` directive (ask once, never block). If it reports `NO_PRODUCT_MD`: for `init`, `teach`, `craft`, `shape`, or wording that clearly maps to a from-scratch build flow, divert into `reference/init.md` first, **unless no user can respond** (a one-shot or automated run, or the user said not to ask): then write your own one-paragraph understanding of the product, audience, and the page's job from the brief and continue. For scoped evaluate/refine/fix requests against existing code, never divert into init; the existing code is the context.
|
||||
2. If the user invoked a sub-command (`audit`, `polish`, `live`, ...), read **`reference/<command>.md`** (the `.native` variant from the Commands table when the platform is `ios`/`android`/`adaptive`) and follow it. On unattended runs, `craft` and `shape` collapse into this file's process: decide, record each decision in one line, build, self-review.
|
||||
3. Read at least one project file (CSS / tokens / theme / a representative component) to learn what world you're in. If PRODUCT.md's `## Platform` is `ios` or `android`, also read `reference/<platform>.md` (`adaptive` reads both).
|
||||
4. If the project is brand-new (no committed tokens, fonts, or brand colors found in step 3), run `node .trae-cn/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed breaks your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this step entirely when step 3 found committed brand colors: identity-preservation wins.
|
||||
|
||||
## How to design
|
||||
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this file warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this skill warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
|
||||
**Existing worlds are sacred.** When the surface already has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside it: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Treat the task as new identity work only when nothing committed exists, or when the user asks for a redesign that discards the current look. A redesign is new work: derive the concept from the subject and the brief, not from the incumbent page's structure or styling.
|
||||
**Existing worlds are sacred.** Most of impeccable's work happens inside a site or app that already exists. When the surface has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside that world: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Inventing parallel colors, fonts, or styles on an existing surface is a defect, not creativity.
|
||||
|
||||
**Ground it in the subject.** Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
**Plan, self-check, build.** Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
**Commit.** Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
**Calibration.** AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
**New identity work reads the playbook first.** When nothing committed exists (greenfield, or a codebase with no real tokens or chosen faces), or the user asks for a redesign that discards the current look, you MUST read [reference/new-work.md](reference/new-work.md) before making any design decision. Not optional, not skippable under time pressure: producing new identity without it yields the generic default this skill exists to prevent. A redesign is new work; derive the concept from the subject and the brief, not from the incumbent page's structure or styling. `context.mjs` prints this directive when it detects the situation. Scoped fixes inside an existing world don't need the playbook; the craft floor below governs them.
|
||||
|
||||
## Craft floor
|
||||
|
||||
@@ -54,7 +40,7 @@ Build to this floor without announcing it. The design detector (the project hook
|
||||
|
||||
Name the visitor's mode before designing; the page's grammar follows from it, and most ruined pages are one mode wearing another mode's grammar. The brief and the surface decide the mode. PRODUCT.md's `register` field names the family (`brand` covers Persuade and Experience; `product` covers Operate and Read), and `reference/brand.md` / `reference/product.md` carry extended depth for the two families.
|
||||
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans.
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Briefs that imply imagery must ship real, verified imagery; a colored rectangle where a photo belongs reads as incomplete. New Persuade surfaces take their typeface procedure and reject list from [reference/new-work.md](reference/new-work.md).
|
||||
|
||||
**Operate** (app UI, dashboards, admin, tools; design SERVES the task). A person getting something done: density, scanability, and consistency outrank expressiveness. These surfaces earn trust by feeling native to their platform: system font stacks and workhorse UI faces are legitimate and often correct here (the Persuade reject list does not apply). The brand lives in the details: focus states, empty states, microcopy, one owned accent.
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# New identity work
|
||||
|
||||
You are reading this because nothing committed exists yet (greenfield), or the user asked for a redesign that discards the current look. Either way the task is the same: invent a visual identity that could not be mistaken for anyone else's, and build it to the craft floor. SKILL.md's rules all still apply; this file is the process that produces the identity.
|
||||
|
||||
## Seed
|
||||
|
||||
If the project is brand-new (no committed tokens, fonts, or brand colors found in the code), run `node .trae-cn/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed exists to break your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this entirely when the code already has committed brand colors: identity-preservation wins.
|
||||
|
||||
## Ground it in the subject
|
||||
|
||||
Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
## Plan, self-check, build
|
||||
|
||||
Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
## Commit
|
||||
|
||||
Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
## Type and imagery for new Persuade and Experience surfaces
|
||||
|
||||
Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans. (For Operate and Read surfaces the opposite holds: system stacks and workhorse UI faces are legitimate and often correct.)
|
||||
|
||||
Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Verify stock URLs resolve before shipping them.
|
||||
|
||||
## Calibration
|
||||
|
||||
AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
|
||||
Before finishing, verify against SKILL.md's craft floor and run the detector; a bold page that ships mechanical defects is not done.
|
||||
@@ -904,6 +904,10 @@ async function cli() {
|
||||
'reference/init.md and write PRODUCT.md first; for any other (scoped) ' +
|
||||
'command against existing code, proceed using the code as context and ' +
|
||||
`offer \`${IMPECCABLE_COMMAND} init\` as a suggestion (do not block).`,
|
||||
'NEW_WORK: No committed design context was found. If this task produces ' +
|
||||
'new design (a build from scratch, or a redesign that discards the ' +
|
||||
'current look), you MUST read reference/new-work.md before making any ' +
|
||||
'design decision. Scoped fixes to existing code do not need it.',
|
||||
];
|
||||
parts.push(buildResolvedContextDirective(ctx, cliOptions, { targetExists }));
|
||||
if (shouldWarnMissingTarget(ctx, targetProvided, targetExists)) {
|
||||
@@ -922,10 +926,22 @@ async function cli() {
|
||||
parts.push(buildMissingTargetDirective());
|
||||
}
|
||||
const register = extractRegister(ctx.product);
|
||||
const next = register
|
||||
? `NEXT STEP: This project's register is \`${register}\`. You MUST now read \`reference/${register}.md\` before producing any design output.`
|
||||
: `NEXT STEP: You MUST now read the matching register reference (\`reference/brand.md\` or \`reference/product.md\`) before producing any design output. Pick based on PRODUCT.md above.`;
|
||||
parts.push(next);
|
||||
// The register field survives as a family hint (brand = Persuade/Experience,
|
||||
// product = Operate/Read); SKILL.md's mode section carries the essentials
|
||||
// inline, so no register-file read is mandated here. What IS mandated:
|
||||
// the new-work playbook when no committed design system exists yet.
|
||||
if (!ctx.hasDesign) {
|
||||
parts.push(
|
||||
'NEW_WORK: PRODUCT.md exists but no DESIGN.md was found. If the code ' +
|
||||
'has no committed design system either (check the project files), and ' +
|
||||
'this task produces new design or a redesign that discards the current ' +
|
||||
'look, you MUST read reference/new-work.md before making any design ' +
|
||||
'decision. Scoped fixes inside an existing design system do not need it.',
|
||||
);
|
||||
}
|
||||
if (register) {
|
||||
parts.push(`REGISTER: \`${register}\` (family hint: brand = Persuade/Experience surfaces, product = Operate/Read). Derive the visitor's mode per SKILL.md; \`reference/${register}.md\` has extended depth for substantial work.`);
|
||||
}
|
||||
const platform = extractPlatform(ctx.product);
|
||||
const nativeRefs =
|
||||
platform === 'adaptive' ? ['ios', 'android'] : platform === 'ios' || platform === 'android' ? [platform] : [];
|
||||
@@ -933,7 +949,7 @@ async function cli() {
|
||||
const refList = nativeRefs.map(p => `\`reference/${p}.md\``).join(' and ');
|
||||
const label = platform === 'adaptive' ? '`adaptive` (both iOS and Android)' : `\`${platform}\``;
|
||||
parts.push(
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to the register reference.`,
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to SKILL.md's mode guidance.`,
|
||||
);
|
||||
} else if (!platform) {
|
||||
// A `## Platform` section that names something we don't recognize (a
|
||||
|
||||
@@ -7105,6 +7105,14 @@
|
||||
}
|
||||
|
||||
async function captureAndEmit(el, basePayload, snapshot, rect) {
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
|
||||
// Plain requests do not send a screenshot to the agent, so capture is
|
||||
// presentation-only. Wait only for the helper to accept the event before
|
||||
// starting CPU-heavy capture; this yields the browser task and prevents
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) await sendEvent(basePayload);
|
||||
|
||||
let screenshotPath;
|
||||
let blob;
|
||||
let paper;
|
||||
@@ -7122,7 +7130,6 @@
|
||||
// are present. Without annotations the image is pure visual anchoring -
|
||||
// it biases the model toward the current rendering and works against the
|
||||
// three-distinct-directions brief.
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
if (blob && hasAnnotations) {
|
||||
try {
|
||||
const uploadRes = await fetch(
|
||||
@@ -7140,7 +7147,11 @@
|
||||
console.warn('[impeccable] annotation upload failed:', err);
|
||||
}
|
||||
}
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Annotated requests must wait for capture + upload because the screenshot
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: impeccable
|
||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||
version: 4.0.0-alpha.8
|
||||
version: 4.0.0-alpha.9
|
||||
user-invocable: true
|
||||
argument-hint: "[craft|shape · audit|critique · animate|bolder|colorize|delight|layout|overdrive|quieter|typeset · adapt|clarify|distill · harden|onboard|optimize|polish · init|document|extract|live] [target]"
|
||||
license: Apache 2.0
|
||||
@@ -16,27 +16,13 @@ Approach every design task as the design lead at a small studio known for giving
|
||||
1. Run `node .trae/skills/impeccable/scripts/context.mjs` once per session (if the runtime shows this skill's loaded base directory, run `node <skill-base-dir>/scripts/context.mjs`; keep cwd at the user's project). It prints the project's PRODUCT.md and DESIGN.md when they exist; follow what it prints, including any `UPDATE_AVAILABLE` directive (ask once, never block). If it reports `NO_PRODUCT_MD`: for `init`, `teach`, `craft`, `shape`, or wording that clearly maps to a from-scratch build flow, divert into `reference/init.md` first, **unless no user can respond** (a one-shot or automated run, or the user said not to ask): then write your own one-paragraph understanding of the product, audience, and the page's job from the brief and continue. For scoped evaluate/refine/fix requests against existing code, never divert into init; the existing code is the context.
|
||||
2. If the user invoked a sub-command (`audit`, `polish`, `live`, ...), read **`reference/<command>.md`** (the `.native` variant from the Commands table when the platform is `ios`/`android`/`adaptive`) and follow it. On unattended runs, `craft` and `shape` collapse into this file's process: decide, record each decision in one line, build, self-review.
|
||||
3. Read at least one project file (CSS / tokens / theme / a representative component) to learn what world you're in. If PRODUCT.md's `## Platform` is `ios` or `android`, also read `reference/<platform>.md` (`adaptive` reads both).
|
||||
4. If the project is brand-new (no committed tokens, fonts, or brand colors found in step 3), run `node .trae/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed breaks your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this step entirely when step 3 found committed brand colors: identity-preservation wins.
|
||||
|
||||
## How to design
|
||||
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this file warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this skill warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
|
||||
**Existing worlds are sacred.** When the surface already has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside it: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Treat the task as new identity work only when nothing committed exists, or when the user asks for a redesign that discards the current look. A redesign is new work: derive the concept from the subject and the brief, not from the incumbent page's structure or styling.
|
||||
**Existing worlds are sacred.** Most of impeccable's work happens inside a site or app that already exists. When the surface has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside that world: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Inventing parallel colors, fonts, or styles on an existing surface is a defect, not creativity.
|
||||
|
||||
**Ground it in the subject.** Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
**Plan, self-check, build.** Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
**Commit.** Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
**Calibration.** AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
**New identity work reads the playbook first.** When nothing committed exists (greenfield, or a codebase with no real tokens or chosen faces), or the user asks for a redesign that discards the current look, you MUST read [reference/new-work.md](reference/new-work.md) before making any design decision. Not optional, not skippable under time pressure: producing new identity without it yields the generic default this skill exists to prevent. A redesign is new work; derive the concept from the subject and the brief, not from the incumbent page's structure or styling. `context.mjs` prints this directive when it detects the situation. Scoped fixes inside an existing world don't need the playbook; the craft floor below governs them.
|
||||
|
||||
## Craft floor
|
||||
|
||||
@@ -54,7 +40,7 @@ Build to this floor without announcing it. The design detector (the project hook
|
||||
|
||||
Name the visitor's mode before designing; the page's grammar follows from it, and most ruined pages are one mode wearing another mode's grammar. The brief and the surface decide the mode. PRODUCT.md's `register` field names the family (`brand` covers Persuade and Experience; `product` covers Operate and Read), and `reference/brand.md` / `reference/product.md` carry extended depth for the two families.
|
||||
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans.
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Briefs that imply imagery must ship real, verified imagery; a colored rectangle where a photo belongs reads as incomplete. New Persuade surfaces take their typeface procedure and reject list from [reference/new-work.md](reference/new-work.md).
|
||||
|
||||
**Operate** (app UI, dashboards, admin, tools; design SERVES the task). A person getting something done: density, scanability, and consistency outrank expressiveness. These surfaces earn trust by feeling native to their platform: system font stacks and workhorse UI faces are legitimate and often correct here (the Persuade reject list does not apply). The brand lives in the details: focus states, empty states, microcopy, one owned accent.
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# New identity work
|
||||
|
||||
You are reading this because nothing committed exists yet (greenfield), or the user asked for a redesign that discards the current look. Either way the task is the same: invent a visual identity that could not be mistaken for anyone else's, and build it to the craft floor. SKILL.md's rules all still apply; this file is the process that produces the identity.
|
||||
|
||||
## Seed
|
||||
|
||||
If the project is brand-new (no committed tokens, fonts, or brand colors found in the code), run `node .trae/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed exists to break your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this entirely when the code already has committed brand colors: identity-preservation wins.
|
||||
|
||||
## Ground it in the subject
|
||||
|
||||
Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
## Plan, self-check, build
|
||||
|
||||
Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
## Commit
|
||||
|
||||
Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
## Type and imagery for new Persuade and Experience surfaces
|
||||
|
||||
Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans. (For Operate and Read surfaces the opposite holds: system stacks and workhorse UI faces are legitimate and often correct.)
|
||||
|
||||
Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Verify stock URLs resolve before shipping them.
|
||||
|
||||
## Calibration
|
||||
|
||||
AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
|
||||
Before finishing, verify against SKILL.md's craft floor and run the detector; a bold page that ships mechanical defects is not done.
|
||||
@@ -904,6 +904,10 @@ async function cli() {
|
||||
'reference/init.md and write PRODUCT.md first; for any other (scoped) ' +
|
||||
'command against existing code, proceed using the code as context and ' +
|
||||
`offer \`${IMPECCABLE_COMMAND} init\` as a suggestion (do not block).`,
|
||||
'NEW_WORK: No committed design context was found. If this task produces ' +
|
||||
'new design (a build from scratch, or a redesign that discards the ' +
|
||||
'current look), you MUST read reference/new-work.md before making any ' +
|
||||
'design decision. Scoped fixes to existing code do not need it.',
|
||||
];
|
||||
parts.push(buildResolvedContextDirective(ctx, cliOptions, { targetExists }));
|
||||
if (shouldWarnMissingTarget(ctx, targetProvided, targetExists)) {
|
||||
@@ -922,10 +926,22 @@ async function cli() {
|
||||
parts.push(buildMissingTargetDirective());
|
||||
}
|
||||
const register = extractRegister(ctx.product);
|
||||
const next = register
|
||||
? `NEXT STEP: This project's register is \`${register}\`. You MUST now read \`reference/${register}.md\` before producing any design output.`
|
||||
: `NEXT STEP: You MUST now read the matching register reference (\`reference/brand.md\` or \`reference/product.md\`) before producing any design output. Pick based on PRODUCT.md above.`;
|
||||
parts.push(next);
|
||||
// The register field survives as a family hint (brand = Persuade/Experience,
|
||||
// product = Operate/Read); SKILL.md's mode section carries the essentials
|
||||
// inline, so no register-file read is mandated here. What IS mandated:
|
||||
// the new-work playbook when no committed design system exists yet.
|
||||
if (!ctx.hasDesign) {
|
||||
parts.push(
|
||||
'NEW_WORK: PRODUCT.md exists but no DESIGN.md was found. If the code ' +
|
||||
'has no committed design system either (check the project files), and ' +
|
||||
'this task produces new design or a redesign that discards the current ' +
|
||||
'look, you MUST read reference/new-work.md before making any design ' +
|
||||
'decision. Scoped fixes inside an existing design system do not need it.',
|
||||
);
|
||||
}
|
||||
if (register) {
|
||||
parts.push(`REGISTER: \`${register}\` (family hint: brand = Persuade/Experience surfaces, product = Operate/Read). Derive the visitor's mode per SKILL.md; \`reference/${register}.md\` has extended depth for substantial work.`);
|
||||
}
|
||||
const platform = extractPlatform(ctx.product);
|
||||
const nativeRefs =
|
||||
platform === 'adaptive' ? ['ios', 'android'] : platform === 'ios' || platform === 'android' ? [platform] : [];
|
||||
@@ -933,7 +949,7 @@ async function cli() {
|
||||
const refList = nativeRefs.map(p => `\`reference/${p}.md\``).join(' and ');
|
||||
const label = platform === 'adaptive' ? '`adaptive` (both iOS and Android)' : `\`${platform}\``;
|
||||
parts.push(
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to the register reference.`,
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to SKILL.md's mode guidance.`,
|
||||
);
|
||||
} else if (!platform) {
|
||||
// A `## Platform` section that names something we don't recognize (a
|
||||
|
||||
@@ -7105,6 +7105,14 @@
|
||||
}
|
||||
|
||||
async function captureAndEmit(el, basePayload, snapshot, rect) {
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
|
||||
// Plain requests do not send a screenshot to the agent, so capture is
|
||||
// presentation-only. Wait only for the helper to accept the event before
|
||||
// starting CPU-heavy capture; this yields the browser task and prevents
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) await sendEvent(basePayload);
|
||||
|
||||
let screenshotPath;
|
||||
let blob;
|
||||
let paper;
|
||||
@@ -7122,7 +7130,6 @@
|
||||
// are present. Without annotations the image is pure visual anchoring -
|
||||
// it biases the model toward the current rendering and works against the
|
||||
// three-distinct-directions brief.
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
if (blob && hasAnnotations) {
|
||||
try {
|
||||
const uploadRes = await fetch(
|
||||
@@ -7140,7 +7147,11 @@
|
||||
console.warn('[impeccable] annotation upload failed:', err);
|
||||
}
|
||||
}
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Annotated requests must wait for capture + upload because the screenshot
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
+28
-20
@@ -1,4 +1,4 @@
|
||||
# Impeccable Live performance baseline
|
||||
# Impeccable Live performance baseline and first optimization
|
||||
|
||||
## Goal
|
||||
|
||||
@@ -8,30 +8,36 @@ Measure the latency Impeccable controls in the Pick → Go → first usable vari
|
||||
|
||||
`bun run bench:live` reuses the Live runtime E2E fixture system. It stages a real framework project, starts the helper and framework dev servers, opens Chromium, drives the picker, and records monotonic boundaries for:
|
||||
|
||||
1. Go → generate POST begins (`browserPreparationMs`)
|
||||
2. generate POST → agent poll receives the event (`serverPickupMs`)
|
||||
3. deterministic source scaffold (`scaffoldMs`)
|
||||
4. agent generation (`generationMs`)
|
||||
5. source write (`writeMs`)
|
||||
6. write → first variant in the DOM (`writeToFirstVariantMs`)
|
||||
7. first variant → all variants/cycling (`deliveryGapMs`)
|
||||
1. Playwright starts Go → generate POST begins (`browserPreparationMs`, includes automation actionability)
|
||||
2. browser Go handler → generate fetch begins (`browserDispatchMs`)
|
||||
3. Playwright actionability before the Go handler (`automationClickMs`)
|
||||
4. generate POST → agent poll receives the event (`serverPickupMs`)
|
||||
5. deterministic source scaffold (`scaffoldMs`)
|
||||
6. agent generation (`generationMs`)
|
||||
7. source write (`writeMs`)
|
||||
8. write → first variant in the DOM (`writeToFirstVariantMs`)
|
||||
9. first variant → all variants/cycling (`deliveryGapMs`)
|
||||
|
||||
The deterministic agent measures Impeccable’s fixed floor. An LLM-backed run uses the same orchestration seam, but remains opt-in because it sends staged fixture source to an external provider.
|
||||
|
||||
## Baseline, July 11 2026
|
||||
## Baseline and result, July 11 2026
|
||||
|
||||
Fixture: `vite8-react-plain`. Browser: local headless Chromium. Three variants. Warm interaction loop.
|
||||
|
||||
| Metric | Plain, median | Annotated, median |
|
||||
|---|---:|---:|
|
||||
| Go → first variant | 916 ms | 431 ms |
|
||||
| Browser preparation | 828 ms | 335 ms |
|
||||
| Server pickup | 0.8 ms | 0.4 ms |
|
||||
| Scaffold | 41 ms | 41 ms |
|
||||
| Write → first variant | 47 ms | 54 ms |
|
||||
| First → all variants | 1.3 ms | 1.3 ms |
|
||||
| Metric | Before, plain | After, plain | Annotated control |
|
||||
|---|---:|---:|---:|
|
||||
| Go → first variant | 916 ms | 414 ms | 423 ms |
|
||||
| Browser preparation, including Playwright | 828 ms | 312 ms | 350 ms |
|
||||
| Browser handler → generate fetch | — | 2.2 ms | 46.7 ms |
|
||||
| Playwright actionability | — | 309 ms | 303 ms |
|
||||
| Server pickup | 0.8 ms | 2.2 ms | 0.8 ms |
|
||||
| Scaffold | 41 ms | 54 ms | 43 ms |
|
||||
| Write → first variant | 47 ms | 44 ms | 28 ms |
|
||||
| First → all variants | 1.3 ms | 1.3 ms | 1.2 ms |
|
||||
|
||||
The plain path spends 90.4% of its model-free latency before the generate request leaves the browser. `handleGo()` always calls `captureAndEmit()`, which captures the element for the generating shader even when there are no annotations to upload. The annotation-path difference needs a capture microbenchmark before changing branch logic.
|
||||
Dispatch-before-capture reduces the median model-free Pick → first-variant loop by **54.8%**, from 916 ms to 414 ms on the same fixture and deterministic agent. The refined in-browser probe shows that Live begins the plain generate fetch in **2.2 ms median**; most of the remaining 414 ms total is Playwright actionability, not product work. The product-side estimate after subtracting that automation delay is about **105 ms**.
|
||||
|
||||
The annotated control still blocks on screenshot capture and upload by design. Its browser handler → fetch time is 46.7 ms median, and the E2E event retains comments, strokes, and `screenshotPath`.
|
||||
|
||||
## Harness evidence
|
||||
|
||||
@@ -44,7 +50,7 @@ The plain path spends 90.4% of its model-free latency before the generate reques
|
||||
|
||||
### 1. Dispatch first, capture second
|
||||
|
||||
For unannotated picks, send `generate` immediately, then capture the shader texture concurrently. Preserve annotated capture as blocking until the protocol supports attaching screenshot evidence after event pickup. This targets the measured 828 ms plain-path bottleneck and does not touch generation quality.
|
||||
**Shipped.** Unannotated picks send `generate` and wait only for the helper to accept it, then continue shader capture off the critical path. Annotated capture remains blocking because the screenshot is semantic model input. This produced the 54.8% median reduction above without changing the agent payload or provider path.
|
||||
|
||||
### 2. Progressive variant delivery
|
||||
|
||||
@@ -95,6 +101,8 @@ Run a fast producer first and validate identity, copy preservation, param wiring
|
||||
|
||||
Replace generic generating dots with truthful stage states from the journal: preparing capture, locating source, generating, previewing variant 1, and finishing alternatives. Never display fake percentage progress.
|
||||
|
||||
## Follow-up goal
|
||||
## Completed goal
|
||||
|
||||
Reduce the median plain Pick → first usable variant latency by at least 25% on the measured Vite/Chromium protocol baseline and materially reduce model-backed time-to-first-variant, while holding source validity, copy preservation, visual-quality acceptance, and Claude/Codex harness compatibility at or above baseline. Implement the unannotated dispatch-before-capture path first, then progressive delivery or a warm provider-specific producer only when their own benchmarks show a net win.
|
||||
|
||||
Result: **54.8% median reduction** on the deterministic protocol benchmark. The next goal should target model-dominated sessions: progressively reveal the first valid variant, then benchmark a warm provider-specific producer only if it beats main-thread generation without reducing visual acceptance.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "impeccable",
|
||||
"description": "Design fluency for frontend development. 1 skill with 23 commands (/impeccable polish, /impeccable audit, /impeccable critique, etc.) and curated anti-pattern detection.",
|
||||
"version": "4.0.0-alpha.8",
|
||||
"version": "4.0.0-alpha.9",
|
||||
"author": {
|
||||
"name": "Paul Bakaus",
|
||||
"email": "paul@paulbakaus.com"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: impeccable
|
||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||
version: 4.0.0-alpha.8
|
||||
version: 4.0.0-alpha.9
|
||||
user-invocable: true
|
||||
argument-hint: "[craft|shape · audit|critique · animate|bolder|colorize|delight|layout|overdrive|quieter|typeset · adapt|clarify|distill · harden|onboard|optimize|polish · init|document|extract|live] [target]"
|
||||
license: Apache 2.0
|
||||
@@ -19,27 +19,13 @@ Approach every design task as the design lead at a small studio known for giving
|
||||
1. Run `node .claude/skills/impeccable/scripts/context.mjs` once per session (if the runtime shows this skill's loaded base directory, run `node <skill-base-dir>/scripts/context.mjs`; keep cwd at the user's project). It prints the project's PRODUCT.md and DESIGN.md when they exist; follow what it prints, including any `UPDATE_AVAILABLE` directive (ask once, never block). If it reports `NO_PRODUCT_MD`: for `init`, `teach`, `craft`, `shape`, or wording that clearly maps to a from-scratch build flow, divert into `reference/init.md` first, **unless no user can respond** (a one-shot or automated run, or the user said not to ask): then write your own one-paragraph understanding of the product, audience, and the page's job from the brief and continue. For scoped evaluate/refine/fix requests against existing code, never divert into init; the existing code is the context.
|
||||
2. If the user invoked a sub-command (`audit`, `polish`, `live`, ...), read **`reference/<command>.md`** (the `.native` variant from the Commands table when the platform is `ios`/`android`/`adaptive`) and follow it. On unattended runs, `craft` and `shape` collapse into this file's process: decide, record each decision in one line, build, self-review.
|
||||
3. Read at least one project file (CSS / tokens / theme / a representative component) to learn what world you're in. If PRODUCT.md's `## Platform` is `ios` or `android`, also read `reference/<platform>.md` (`adaptive` reads both).
|
||||
4. If the project is brand-new (no committed tokens, fonts, or brand colors found in step 3), run `node .claude/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed breaks your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this step entirely when step 3 found committed brand colors: identity-preservation wins.
|
||||
|
||||
## How to design
|
||||
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this file warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this skill warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save.
|
||||
|
||||
**Existing worlds are sacred.** When the surface already has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside it: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Treat the task as new identity work only when nothing committed exists, or when the user asks for a redesign that discards the current look. A redesign is new work: derive the concept from the subject and the brief, not from the incumbent page's structure or styling.
|
||||
**Existing worlds are sacred.** Most of impeccable's work happens inside a site or app that already exists. When the surface has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside that world: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Inventing parallel colors, fonts, or styles on an existing surface is a defect, not creativity.
|
||||
|
||||
**Ground it in the subject.** Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
**Plan, self-check, build.** Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
**Commit.** Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
**Calibration.** AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
**New identity work reads the playbook first.** When nothing committed exists (greenfield, or a codebase with no real tokens or chosen faces), or the user asks for a redesign that discards the current look, you MUST read [reference/new-work.md](reference/new-work.md) before making any design decision. Not optional, not skippable under time pressure: producing new identity without it yields the generic default this skill exists to prevent. A redesign is new work; derive the concept from the subject and the brief, not from the incumbent page's structure or styling. `context.mjs` prints this directive when it detects the situation. Scoped fixes inside an existing world don't need the playbook; the craft floor below governs them.
|
||||
|
||||
## Craft floor
|
||||
|
||||
@@ -57,7 +43,7 @@ Build to this floor without announcing it. The design detector (the project hook
|
||||
|
||||
Name the visitor's mode before designing; the page's grammar follows from it, and most ruined pages are one mode wearing another mode's grammar. The brief and the surface decide the mode. PRODUCT.md's `register` field names the family (`brand` covers Persuade and Experience; `product` covers Operate and Read), and `reference/brand.md` / `reference/product.md` carry extended depth for the two families.
|
||||
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans.
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Briefs that imply imagery must ship real, verified imagery; a colored rectangle where a photo belongs reads as incomplete. New Persuade surfaces take their typeface procedure and reject list from [reference/new-work.md](reference/new-work.md).
|
||||
|
||||
**Operate** (app UI, dashboards, admin, tools; design SERVES the task). A person getting something done: density, scanability, and consistency outrank expressiveness. These surfaces earn trust by feeling native to their platform: system font stacks and workhorse UI faces are legitimate and often correct here (the Persuade reject list does not apply). The brand lives in the details: focus states, empty states, microcopy, one owned accent.
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# New identity work
|
||||
|
||||
You are reading this because nothing committed exists yet (greenfield), or the user asked for a redesign that discards the current look. Either way the task is the same: invent a visual identity that could not be mistaken for anyone else's, and build it to the craft floor. SKILL.md's rules all still apply; this file is the process that produces the identity.
|
||||
|
||||
## Seed
|
||||
|
||||
If the project is brand-new (no committed tokens, fonts, or brand colors found in the code), run `node .claude/skills/impeccable/scripts/palette.mjs` for a brand seed color. The seed exists to break your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this entirely when the code already has committed brand colors: identity-preservation wins.
|
||||
|
||||
## Ground it in the subject
|
||||
|
||||
Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
## Plan, self-check, build
|
||||
|
||||
Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
## Commit
|
||||
|
||||
Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
## Type and imagery for new Persuade and Experience surfaces
|
||||
|
||||
Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans. (For Operate and Read surfaces the opposite holds: system stacks and workhorse UI faces are legitimate and often correct.)
|
||||
|
||||
Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Verify stock URLs resolve before shipping them.
|
||||
|
||||
## Calibration
|
||||
|
||||
AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
|
||||
Before finishing, verify against SKILL.md's craft floor and run the detector; a bold page that ships mechanical defects is not done.
|
||||
@@ -904,6 +904,10 @@ async function cli() {
|
||||
'reference/init.md and write PRODUCT.md first; for any other (scoped) ' +
|
||||
'command against existing code, proceed using the code as context and ' +
|
||||
`offer \`${IMPECCABLE_COMMAND} init\` as a suggestion (do not block).`,
|
||||
'NEW_WORK: No committed design context was found. If this task produces ' +
|
||||
'new design (a build from scratch, or a redesign that discards the ' +
|
||||
'current look), you MUST read reference/new-work.md before making any ' +
|
||||
'design decision. Scoped fixes to existing code do not need it.',
|
||||
];
|
||||
parts.push(buildResolvedContextDirective(ctx, cliOptions, { targetExists }));
|
||||
if (shouldWarnMissingTarget(ctx, targetProvided, targetExists)) {
|
||||
@@ -922,10 +926,22 @@ async function cli() {
|
||||
parts.push(buildMissingTargetDirective());
|
||||
}
|
||||
const register = extractRegister(ctx.product);
|
||||
const next = register
|
||||
? `NEXT STEP: This project's register is \`${register}\`. You MUST now read \`reference/${register}.md\` before producing any design output.`
|
||||
: `NEXT STEP: You MUST now read the matching register reference (\`reference/brand.md\` or \`reference/product.md\`) before producing any design output. Pick based on PRODUCT.md above.`;
|
||||
parts.push(next);
|
||||
// The register field survives as a family hint (brand = Persuade/Experience,
|
||||
// product = Operate/Read); SKILL.md's mode section carries the essentials
|
||||
// inline, so no register-file read is mandated here. What IS mandated:
|
||||
// the new-work playbook when no committed design system exists yet.
|
||||
if (!ctx.hasDesign) {
|
||||
parts.push(
|
||||
'NEW_WORK: PRODUCT.md exists but no DESIGN.md was found. If the code ' +
|
||||
'has no committed design system either (check the project files), and ' +
|
||||
'this task produces new design or a redesign that discards the current ' +
|
||||
'look, you MUST read reference/new-work.md before making any design ' +
|
||||
'decision. Scoped fixes inside an existing design system do not need it.',
|
||||
);
|
||||
}
|
||||
if (register) {
|
||||
parts.push(`REGISTER: \`${register}\` (family hint: brand = Persuade/Experience surfaces, product = Operate/Read). Derive the visitor's mode per SKILL.md; \`reference/${register}.md\` has extended depth for substantial work.`);
|
||||
}
|
||||
const platform = extractPlatform(ctx.product);
|
||||
const nativeRefs =
|
||||
platform === 'adaptive' ? ['ios', 'android'] : platform === 'ios' || platform === 'android' ? [platform] : [];
|
||||
@@ -933,7 +949,7 @@ async function cli() {
|
||||
const refList = nativeRefs.map(p => `\`reference/${p}.md\``).join(' and ');
|
||||
const label = platform === 'adaptive' ? '`adaptive` (both iOS and Android)' : `\`${platform}\``;
|
||||
parts.push(
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to the register reference.`,
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to SKILL.md's mode guidance.`,
|
||||
);
|
||||
} else if (!platform) {
|
||||
// A `## Platform` section that names something we don't recognize (a
|
||||
|
||||
@@ -7105,6 +7105,14 @@
|
||||
}
|
||||
|
||||
async function captureAndEmit(el, basePayload, snapshot, rect) {
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
|
||||
// Plain requests do not send a screenshot to the agent, so capture is
|
||||
// presentation-only. Wait only for the helper to accept the event before
|
||||
// starting CPU-heavy capture; this yields the browser task and prevents
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) await sendEvent(basePayload);
|
||||
|
||||
let screenshotPath;
|
||||
let blob;
|
||||
let paper;
|
||||
@@ -7122,7 +7130,6 @@
|
||||
// are present. Without annotations the image is pure visual anchoring -
|
||||
// it biases the model toward the current rendering and works against the
|
||||
// three-distinct-directions brief.
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
if (blob && hasAnnotations) {
|
||||
try {
|
||||
const uploadRes = await fetch(
|
||||
@@ -7140,7 +7147,11 @@
|
||||
console.warn('[impeccable] annotation upload failed:', err);
|
||||
}
|
||||
}
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Annotated requests must wait for capture + upload because the screenshot
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -39,11 +39,11 @@ export const harnessPaths = [
|
||||
export const liveExperiments = [
|
||||
{
|
||||
rank: 1,
|
||||
title: 'Dispatch first, capture second',
|
||||
evidence: 'The plain path spends 828 ms before the generate POST leaves the browser.',
|
||||
move: 'For unannotated picks, post the event immediately and run shader capture in parallel. Keep annotated capture on the blocking path until the protocol can attach evidence later.',
|
||||
expected: 'Removes up to 90% of the measured model-free floor on the common path.',
|
||||
confidence: 'Measured',
|
||||
title: 'Dispatch first, capture second — shipped',
|
||||
evidence: 'Plain click-handler → generate fetch is now 2.2 ms median; end-to-end model-free latency fell from 916 ms to 414 ms.',
|
||||
move: 'Unannotated picks wait for the helper to accept the event, then capture the shader off-path. Annotated picks still capture and upload before dispatch.',
|
||||
expected: 'Delivered a 54.8% median reduction on the same fixture and deterministic agent.',
|
||||
confidence: 'Measured + shipped',
|
||||
},
|
||||
{
|
||||
rank: 2,
|
||||
@@ -111,4 +111,3 @@ export const currentHarnessProbe = {
|
||||
surfacedAutomatically: false,
|
||||
result: 'The sentinel appeared only after an explicit session read; no app terminal was attached.',
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"generatedAt": "2026-07-11T23:46:48.581Z",
|
||||
"generatedAt": "2026-07-12T00:14:29.714Z",
|
||||
"reports": [
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
@@ -373,6 +373,422 @@
|
||||
}
|
||||
],
|
||||
"harnessProbe": null
|
||||
},
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"generatedAt": "2026-07-12T00:14:09.714Z",
|
||||
"benchmark": {
|
||||
"fixture": "vite8-react-plain",
|
||||
"agent": "fake",
|
||||
"provider": "deterministic",
|
||||
"model": null,
|
||||
"scenario": "plain",
|
||||
"variants": 3,
|
||||
"delivery": "atomic"
|
||||
},
|
||||
"setup": {
|
||||
"dependencies": 689.2,
|
||||
"liveServer": 236.71,
|
||||
"injection": 29.09,
|
||||
"devServer": 541.5,
|
||||
"pageLoad": 94.45,
|
||||
"handshake": 263.64
|
||||
},
|
||||
"summary": {
|
||||
"count": 7,
|
||||
"metrics": {
|
||||
"browserPreparationMs": {
|
||||
"median": 311.53,
|
||||
"p95": 825.97,
|
||||
"min": 307.22,
|
||||
"max": 827.73
|
||||
},
|
||||
"browserDispatchMs": {
|
||||
"median": 2.2,
|
||||
"p95": 5.26,
|
||||
"min": 2,
|
||||
"max": 6.4
|
||||
},
|
||||
"automationClickMs": {
|
||||
"median": 309.33,
|
||||
"p95": 820.89,
|
||||
"min": 305.22,
|
||||
"max": 821.33
|
||||
},
|
||||
"serverPickupMs": {
|
||||
"median": 2.23,
|
||||
"p95": 6.44,
|
||||
"min": 0.96,
|
||||
"max": 7.69
|
||||
},
|
||||
"goToAgentMs": {
|
||||
"median": 313.51,
|
||||
"p95": 832.1,
|
||||
"min": 309.45,
|
||||
"max": 835.42
|
||||
},
|
||||
"scaffoldMs": {
|
||||
"median": 54.19,
|
||||
"p95": 54.74,
|
||||
"min": 51.07,
|
||||
"max": 54.85
|
||||
},
|
||||
"generationMs": {
|
||||
"median": 0.03,
|
||||
"p95": 0.16,
|
||||
"min": 0.03,
|
||||
"max": 0.19
|
||||
},
|
||||
"writeMs": {
|
||||
"median": 0.42,
|
||||
"p95": 0.69,
|
||||
"min": 0.38,
|
||||
"max": 0.77
|
||||
},
|
||||
"writeToFirstVariantMs": {
|
||||
"median": 44.39,
|
||||
"p95": 76.33,
|
||||
"min": 41.73,
|
||||
"max": 86.24
|
||||
},
|
||||
"replyMs": {
|
||||
"median": 2.01,
|
||||
"p95": 2.97,
|
||||
"min": 1.95,
|
||||
"max": 3.26
|
||||
},
|
||||
"goToFirstVariantMs": {
|
||||
"median": 414.2,
|
||||
"p95": 960.68,
|
||||
"min": 409.19,
|
||||
"max": 973.99
|
||||
},
|
||||
"goToAllVariantsMs": {
|
||||
"median": 416.61,
|
||||
"p95": 962.65,
|
||||
"min": 410.41,
|
||||
"max": 976.22
|
||||
},
|
||||
"deliveryGapMs": {
|
||||
"median": 1.26,
|
||||
"p95": 2.36,
|
||||
"min": 1.2,
|
||||
"max": 2.41
|
||||
},
|
||||
"impeccableOverheadMs": {
|
||||
"median": 414.17,
|
||||
"p95": 960.53,
|
||||
"min": 409.15,
|
||||
"max": 973.8
|
||||
}
|
||||
}
|
||||
},
|
||||
"runs": [
|
||||
{
|
||||
"iteration": 1,
|
||||
"scenario": "plain",
|
||||
"eventId": "9bbde352",
|
||||
"browserPreparationMs": 827.73,
|
||||
"browserDispatchMs": 6.4,
|
||||
"automationClickMs": 821.33,
|
||||
"serverPickupMs": 7.69,
|
||||
"goToAgentMs": 835.42,
|
||||
"scaffoldMs": 51.07,
|
||||
"generationMs": 0.19,
|
||||
"writeMs": 0.77,
|
||||
"writeToFirstVariantMs": 86.24,
|
||||
"replyMs": 3.26,
|
||||
"goToFirstVariantMs": 973.99,
|
||||
"goToAllVariantsMs": 976.22,
|
||||
"deliveryGapMs": 2.24,
|
||||
"impeccableOverheadMs": 973.8
|
||||
},
|
||||
{
|
||||
"iteration": 2,
|
||||
"scenario": "plain",
|
||||
"eventId": "f21d7bba",
|
||||
"browserPreparationMs": 821.86,
|
||||
"browserDispatchMs": 2,
|
||||
"automationClickMs": 819.86,
|
||||
"serverPickupMs": 0.96,
|
||||
"goToAgentMs": 822.82,
|
||||
"scaffoldMs": 53.02,
|
||||
"generationMs": 0.08,
|
||||
"writeMs": 0.39,
|
||||
"writeToFirstVariantMs": 53.22,
|
||||
"replyMs": 2.15,
|
||||
"goToFirstVariantMs": 929.64,
|
||||
"goToAllVariantsMs": 930.99,
|
||||
"deliveryGapMs": 1.35,
|
||||
"impeccableOverheadMs": 929.56
|
||||
},
|
||||
{
|
||||
"iteration": 3,
|
||||
"scenario": "plain",
|
||||
"eventId": "8641ce90",
|
||||
"browserPreparationMs": 310.72,
|
||||
"browserDispatchMs": 2.6,
|
||||
"automationClickMs": 308.12,
|
||||
"serverPickupMs": 2.37,
|
||||
"goToAgentMs": 313.09,
|
||||
"scaffoldMs": 53.46,
|
||||
"generationMs": 0.03,
|
||||
"writeMs": 0.42,
|
||||
"writeToFirstVariantMs": 43.16,
|
||||
"replyMs": 2.3,
|
||||
"goToFirstVariantMs": 410.21,
|
||||
"goToAllVariantsMs": 411.41,
|
||||
"deliveryGapMs": 1.2,
|
||||
"impeccableOverheadMs": 410.18
|
||||
},
|
||||
{
|
||||
"iteration": 4,
|
||||
"scenario": "plain",
|
||||
"eventId": "bde64b84",
|
||||
"browserPreparationMs": 311.14,
|
||||
"browserDispatchMs": 2.3,
|
||||
"automationClickMs": 308.84,
|
||||
"serverPickupMs": 1.75,
|
||||
"goToAgentMs": 312.88,
|
||||
"scaffoldMs": 54.47,
|
||||
"generationMs": 0.03,
|
||||
"writeMs": 0.49,
|
||||
"writeToFirstVariantMs": 43.77,
|
||||
"replyMs": 2.01,
|
||||
"goToFirstVariantMs": 411.69,
|
||||
"goToAllVariantsMs": 412.95,
|
||||
"deliveryGapMs": 1.26,
|
||||
"impeccableOverheadMs": 411.66
|
||||
},
|
||||
{
|
||||
"iteration": 5,
|
||||
"scenario": "plain",
|
||||
"eventId": "9198fca0",
|
||||
"browserPreparationMs": 307.22,
|
||||
"browserDispatchMs": 2,
|
||||
"automationClickMs": 305.22,
|
||||
"serverPickupMs": 2.23,
|
||||
"goToAgentMs": 309.45,
|
||||
"scaffoldMs": 54.85,
|
||||
"generationMs": 0.04,
|
||||
"writeMs": 0.42,
|
||||
"writeToFirstVariantMs": 44.39,
|
||||
"replyMs": 2.01,
|
||||
"goToFirstVariantMs": 409.19,
|
||||
"goToAllVariantsMs": 410.41,
|
||||
"deliveryGapMs": 1.22,
|
||||
"impeccableOverheadMs": 409.15
|
||||
},
|
||||
{
|
||||
"iteration": 6,
|
||||
"scenario": "plain",
|
||||
"eventId": "c4273708",
|
||||
"browserPreparationMs": 820.82,
|
||||
"browserDispatchMs": 2.1,
|
||||
"automationClickMs": 818.72,
|
||||
"serverPickupMs": 3.53,
|
||||
"goToAgentMs": 824.35,
|
||||
"scaffoldMs": 54.43,
|
||||
"generationMs": 0.03,
|
||||
"writeMs": 0.41,
|
||||
"writeToFirstVariantMs": 41.73,
|
||||
"replyMs": 1.95,
|
||||
"goToFirstVariantMs": 920.98,
|
||||
"goToAllVariantsMs": 922.2,
|
||||
"deliveryGapMs": 1.22,
|
||||
"impeccableOverheadMs": 920.95
|
||||
},
|
||||
{
|
||||
"iteration": 7,
|
||||
"scenario": "plain",
|
||||
"eventId": "ffed990a",
|
||||
"browserPreparationMs": 311.53,
|
||||
"browserDispatchMs": 2.2,
|
||||
"automationClickMs": 309.33,
|
||||
"serverPickupMs": 1.98,
|
||||
"goToAgentMs": 313.51,
|
||||
"scaffoldMs": 54.19,
|
||||
"generationMs": 0.03,
|
||||
"writeMs": 0.38,
|
||||
"writeToFirstVariantMs": 46.06,
|
||||
"replyMs": 2.01,
|
||||
"goToFirstVariantMs": 414.2,
|
||||
"goToAllVariantsMs": 416.61,
|
||||
"deliveryGapMs": 2.41,
|
||||
"impeccableOverheadMs": 414.17
|
||||
}
|
||||
],
|
||||
"harnessProbe": null
|
||||
},
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"generatedAt": "2026-07-12T00:14:29.712Z",
|
||||
"benchmark": {
|
||||
"fixture": "vite8-react-plain",
|
||||
"agent": "fake",
|
||||
"provider": "deterministic",
|
||||
"model": null,
|
||||
"scenario": "annotated",
|
||||
"variants": 3,
|
||||
"delivery": "atomic"
|
||||
},
|
||||
"setup": {
|
||||
"dependencies": 679.81,
|
||||
"liveServer": 236.59,
|
||||
"injection": 28.58,
|
||||
"devServer": 518.43,
|
||||
"pageLoad": 148.21,
|
||||
"handshake": 263.27
|
||||
},
|
||||
"summary": {
|
||||
"count": 3,
|
||||
"metrics": {
|
||||
"browserPreparationMs": {
|
||||
"median": 349.77,
|
||||
"p95": 402.2,
|
||||
"min": 347.72,
|
||||
"max": 408.03
|
||||
},
|
||||
"browserDispatchMs": {
|
||||
"median": 46.7,
|
||||
"p95": 99.35,
|
||||
"min": 44.9,
|
||||
"max": 105.2
|
||||
},
|
||||
"automationClickMs": {
|
||||
"median": 302.83,
|
||||
"p95": 303.05,
|
||||
"min": 302.82,
|
||||
"max": 303.07
|
||||
},
|
||||
"serverPickupMs": {
|
||||
"median": 0.84,
|
||||
"p95": 2.84,
|
||||
"min": 0.81,
|
||||
"max": 3.06
|
||||
},
|
||||
"goToAgentMs": {
|
||||
"median": 350.61,
|
||||
"p95": 405.04,
|
||||
"min": 348.53,
|
||||
"max": 411.09
|
||||
},
|
||||
"scaffoldMs": {
|
||||
"median": 42.51,
|
||||
"p95": 43.57,
|
||||
"min": 37.9,
|
||||
"max": 43.69
|
||||
},
|
||||
"generationMs": {
|
||||
"median": 0.08,
|
||||
"p95": 0.17,
|
||||
"min": 0.03,
|
||||
"max": 0.18
|
||||
},
|
||||
"writeMs": {
|
||||
"median": 0.55,
|
||||
"p95": 0.68,
|
||||
"min": 0.38,
|
||||
"max": 0.7
|
||||
},
|
||||
"writeToFirstVariantMs": {
|
||||
"median": 31.94,
|
||||
"p95": 91.06,
|
||||
"min": 28.16,
|
||||
"max": 97.63
|
||||
},
|
||||
"replyMs": {
|
||||
"median": 2.15,
|
||||
"p95": 2.99,
|
||||
"min": 1.64,
|
||||
"max": 3.08
|
||||
},
|
||||
"goToFirstVariantMs": {
|
||||
"median": 423.69,
|
||||
"p95": 535.33,
|
||||
"min": 422.9,
|
||||
"max": 547.73
|
||||
},
|
||||
"goToAllVariantsMs": {
|
||||
"median": 424.9,
|
||||
"p95": 537.87,
|
||||
"min": 424.06,
|
||||
"max": 550.42
|
||||
},
|
||||
"deliveryGapMs": {
|
||||
"median": 1.21,
|
||||
"p95": 2.54,
|
||||
"min": 1.16,
|
||||
"max": 2.69
|
||||
},
|
||||
"impeccableOverheadMs": {
|
||||
"median": 423.61,
|
||||
"p95": 535.16,
|
||||
"min": 422.87,
|
||||
"max": 547.55
|
||||
}
|
||||
}
|
||||
},
|
||||
"runs": [
|
||||
{
|
||||
"iteration": 1,
|
||||
"scenario": "annotated",
|
||||
"eventId": "700d0eea",
|
||||
"browserPreparationMs": 408.03,
|
||||
"browserDispatchMs": 105.2,
|
||||
"automationClickMs": 302.83,
|
||||
"serverPickupMs": 3.06,
|
||||
"goToAgentMs": 411.09,
|
||||
"scaffoldMs": 37.9,
|
||||
"generationMs": 0.18,
|
||||
"writeMs": 0.7,
|
||||
"writeToFirstVariantMs": 97.63,
|
||||
"replyMs": 3.08,
|
||||
"goToFirstVariantMs": 547.73,
|
||||
"goToAllVariantsMs": 550.42,
|
||||
"deliveryGapMs": 2.69,
|
||||
"impeccableOverheadMs": 547.55
|
||||
},
|
||||
{
|
||||
"iteration": 2,
|
||||
"scenario": "annotated",
|
||||
"eventId": "fc262897",
|
||||
"browserPreparationMs": 347.72,
|
||||
"browserDispatchMs": 44.9,
|
||||
"automationClickMs": 302.82,
|
||||
"serverPickupMs": 0.81,
|
||||
"goToAgentMs": 348.53,
|
||||
"scaffoldMs": 42.51,
|
||||
"generationMs": 0.08,
|
||||
"writeMs": 0.55,
|
||||
"writeToFirstVariantMs": 31.94,
|
||||
"replyMs": 1.64,
|
||||
"goToFirstVariantMs": 423.69,
|
||||
"goToAllVariantsMs": 424.9,
|
||||
"deliveryGapMs": 1.21,
|
||||
"impeccableOverheadMs": 423.61
|
||||
},
|
||||
{
|
||||
"iteration": 3,
|
||||
"scenario": "annotated",
|
||||
"eventId": "6dda2190",
|
||||
"browserPreparationMs": 349.77,
|
||||
"browserDispatchMs": 46.7,
|
||||
"automationClickMs": 303.07,
|
||||
"serverPickupMs": 0.84,
|
||||
"goToAgentMs": 350.61,
|
||||
"scaffoldMs": 43.69,
|
||||
"generationMs": 0.03,
|
||||
"writeMs": 0.38,
|
||||
"writeToFirstVariantMs": 28.16,
|
||||
"replyMs": 2.15,
|
||||
"goToFirstVariantMs": 422.9,
|
||||
"goToAllVariantsMs": 424.06,
|
||||
"deliveryGapMs": 1.16,
|
||||
"impeccableOverheadMs": 422.87
|
||||
}
|
||||
],
|
||||
"harnessProbe": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -6,18 +6,24 @@ import '../../styles/sub-pages.css';
|
||||
import '../../styles/live-performance.css';
|
||||
|
||||
const reports = 'reports' in benchmarkData ? benchmarkData.reports : [benchmarkData];
|
||||
const plain = reports.find(report => report.benchmark.scenario === 'plain' && report.benchmark.agent === 'fake') || reports[0];
|
||||
const annotated = reports.find(report => report.benchmark.scenario === 'annotated' && report.benchmark.agent === 'fake');
|
||||
const plainReports = reports.filter(report => report.benchmark.scenario === 'plain' && report.benchmark.agent === 'fake');
|
||||
const annotatedReports = reports.filter(report => report.benchmark.scenario === 'annotated' && report.benchmark.agent === 'fake');
|
||||
const baseline = plainReports[0] || reports[0];
|
||||
const plain = plainReports.at(-1) || baseline;
|
||||
const annotated = annotatedReports.at(-1);
|
||||
const metric = (name: string) => plain.summary.metrics[name]?.median || 0;
|
||||
const protocolFloor = metric('goToFirstVariantMs');
|
||||
const browserPreparation = metric('browserPreparationMs');
|
||||
const baselineFloor = baseline.summary.metrics.goToFirstVariantMs?.median || protocolFloor;
|
||||
const browserDispatch = metric('browserDispatchMs');
|
||||
const automationClick = metric('automationClickMs');
|
||||
const serverPickup = metric('serverPickupMs');
|
||||
const scaffold = metric('scaffoldMs');
|
||||
const writeAndRender = metric('writeMs') + metric('writeToFirstVariantMs');
|
||||
const overlapFloor = Math.max(0, protocolFloor - browserPreparation);
|
||||
const preparationShare = protocolFloor ? (browserPreparation / protocolFloor) * 100 : 0;
|
||||
const productFloor = Math.max(0, protocolFloor - automationClick);
|
||||
const improvement = baselineFloor ? Math.max(0, 1 - (protocolFloor / baselineFloor)) : 0;
|
||||
const annotatedFloor = annotated?.summary.metrics.goToFirstVariantMs?.median || 0;
|
||||
const maxScenarioFloor = Math.max(protocolFloor, annotatedFloor, 1);
|
||||
const maxScenarioFloor = Math.max(baselineFloor, protocolFloor, annotatedFloor, 1);
|
||||
const optimizedTapeWidth = Math.max(12, (protocolFloor / baselineFloor) * 952);
|
||||
const generatedDate = new Date(plain.generatedAt).toLocaleDateString('en-US', {
|
||||
month: 'short', day: 'numeric', year: 'numeric',
|
||||
});
|
||||
@@ -29,8 +35,8 @@ const displayMs = (value: number) => {
|
||||
};
|
||||
|
||||
const stageData = [
|
||||
{ name: 'Browser preparation', value: browserPreparation, tone: 'capture' },
|
||||
{ name: 'Server pickup', value: serverPickup, tone: 'pickup' },
|
||||
{ name: 'Playwright actionability', value: automationClick, tone: 'capture' },
|
||||
{ name: 'Live dispatch + pickup', value: browserDispatch + serverPickup, tone: 'pickup' },
|
||||
{ name: 'Source scaffold', value: scaffold, tone: 'scaffold' },
|
||||
{ name: 'Write + browser settle', value: writeAndRender, tone: 'render' },
|
||||
];
|
||||
@@ -63,15 +69,15 @@ const stageData = [
|
||||
<article
|
||||
class="live-performance"
|
||||
data-live-performance
|
||||
data-protocol-floor={protocolFloor}
|
||||
data-overlap-floor={overlapFloor}
|
||||
data-protocol-floor={baselineFloor}
|
||||
data-overlap-floor={productFloor}
|
||||
>
|
||||
<header class="live-performance-hero ks-section">
|
||||
<p class="live-performance-kicker">Live latency lab · protocol baseline</p>
|
||||
<h1>The wait starts<br /><span>before the model.</span></h1>
|
||||
<p class="live-performance-kicker">Live latency lab · optimization result</p>
|
||||
<h1>Capture left<br /><span>the critical path.</span></h1>
|
||||
<p class="live-performance-lede">
|
||||
With generation removed, Go still takes {displayMs(protocolFloor)} to show the first variant.
|
||||
{' '}{preparationShare.toFixed(1)}% of that time passes before the generate event leaves the browser.
|
||||
The same model-free run fell from {displayMs(baselineFloor)} to {displayMs(protocolFloor)}, a{' '}
|
||||
{(improvement * 100).toFixed(1)}% reduction. Live now starts the generate fetch in {displayMs(browserDispatch)} median.
|
||||
</p>
|
||||
<div class="live-performance-meta" aria-label="Benchmark context">
|
||||
<span>{plain.summary.count} warm runs</span>
|
||||
@@ -85,7 +91,7 @@ const stageData = [
|
||||
<div class="live-performance-section-head">
|
||||
<div>
|
||||
<p class="live-performance-label">Click → first usable variant</p>
|
||||
<h2 id="critical-path-title">The measured critical path</h2>
|
||||
<h2 id="critical-path-title">The critical path moved</h2>
|
||||
</div>
|
||||
<p>Median values. Deterministic generation isolates Impeccable’s own floor.</p>
|
||||
</div>
|
||||
@@ -93,25 +99,15 @@ const stageData = [
|
||||
<div class="latency-tape">
|
||||
<svg viewBox="0 0 1000 214" role="img" aria-labelledby="latency-title latency-desc">
|
||||
<title id="latency-title">Impeccable Live model-free latency timeline</title>
|
||||
<desc id="latency-desc">A 916 millisecond timeline dominated by 828 milliseconds of browser preparation before the generate request.</desc>
|
||||
<line class="latency-axis" x1="24" y1="112" x2="976" y2="112"></line>
|
||||
<g class="latency-ticks" aria-hidden="true">
|
||||
<line x1="24" y1="102" x2="24" y2="124"></line>
|
||||
<line x1="284" y1="106" x2="284" y2="120"></line>
|
||||
<line x1="544" y1="106" x2="544" y2="120"></line>
|
||||
<line x1="804" y1="106" x2="804" y2="120"></line>
|
||||
<line x1="976" y1="102" x2="976" y2="124"></line>
|
||||
</g>
|
||||
<rect class="latency-segment is-capture" x="24" y="88" width="860" height="48"></rect>
|
||||
<rect class="latency-segment is-pickup" x="884" y="88" width="2" height="48"></rect>
|
||||
<rect class="latency-segment is-scaffold" x="886" y="88" width="43" height="48"></rect>
|
||||
<rect class="latency-segment is-render" x="929" y="88" width="47" height="48"></rect>
|
||||
<text class="latency-major-label" x="44" y="75">Browser prepares capture</text>
|
||||
<text class="latency-major-value" x="44" y="118">{displayMs(browserPreparation)}</text>
|
||||
<text class="latency-remainder-label" x="974" y="166" text-anchor="end">everything after dispatch · {displayMs(overlapFloor)}</text>
|
||||
<path class="latency-bracket" d="M884 148 V158 H976 V148"></path>
|
||||
<text class="latency-axis-label" x="24" y="194">Go</text>
|
||||
<text class="latency-axis-label" x="976" y="194" text-anchor="end">First variant</text>
|
||||
<desc id="latency-desc">The same model-free benchmark improved from {displayMs(baselineFloor)} to {displayMs(protocolFloor)} median.</desc>
|
||||
<text class="latency-major-label" x="24" y="42">Before · capture blocks dispatch</text>
|
||||
<rect class="latency-segment is-capture" x="24" y="54" width="952" height="42"></rect>
|
||||
<text class="latency-major-value" x="44" y="82">{displayMs(baselineFloor)}</text>
|
||||
<text class="latency-major-label" x="24" y="128">After · dispatch precedes capture</text>
|
||||
<rect class="latency-segment is-scaffold" x="24" y="140" width={optimizedTapeWidth} height="42"></rect>
|
||||
<text class="latency-major-value" x="44" y="168">{displayMs(protocolFloor)}</text>
|
||||
<path class="latency-bracket" d={`M${24 + optimizedTapeWidth} 184 V194 H976 V184`}></path>
|
||||
<text class="latency-remainder-label" x="976" y="210" text-anchor="end">−{(improvement * 100).toFixed(1)}% · same fixture and deterministic agent</text>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
@@ -126,55 +122,60 @@ const stageData = [
|
||||
</ol>
|
||||
|
||||
<div class="live-performance-finding" role="note">
|
||||
<strong>Finding 01</strong>
|
||||
<p>The browser captures the selected element for the generating shader even when no annotations need to reach the model. That capture blocks event dispatch.</p>
|
||||
<strong>Result 01</strong>
|
||||
<p>Unannotated requests wait only for the helper to accept the event. Shader capture continues off-path; annotated requests still capture and upload first because the screenshot is semantic input.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="live-performance-section ks-section" aria-labelledby="paths-title">
|
||||
<div class="live-performance-section-head">
|
||||
<div>
|
||||
<p class="live-performance-label">Capture paths</p>
|
||||
<h2 id="paths-title">Annotation state changes the floor</h2>
|
||||
<p class="live-performance-label">Before / after / control</p>
|
||||
<h2 id="paths-title">The common path is decisively faster</h2>
|
||||
</div>
|
||||
<p>The difference is repeatable enough to investigate, not yet explained enough to optimize against.</p>
|
||||
<p>The annotated path remains a control: its screenshot must reach the agent before generation starts.</p>
|
||||
</div>
|
||||
<div class="scenario-comparison" role="img" aria-label={`Plain path ${displayMs(protocolFloor)}; annotated path ${displayMs(annotatedFloor)}`}>
|
||||
<div class="scenario-comparison" role="img" aria-label={`Baseline ${displayMs(baselineFloor)}; optimized plain path ${displayMs(protocolFloor)}; annotated control ${displayMs(annotatedFloor)}`}>
|
||||
<div class="scenario-row">
|
||||
<div class="scenario-label"><strong>Plain pick</strong><span>No comments or strokes</span></div>
|
||||
<div class="scenario-track"><span class="is-plain" style={`--scenario-width:${(protocolFloor / maxScenarioFloor) * 100}%`}></span></div>
|
||||
<div class="scenario-label"><strong>Before</strong><span>Plain pick, capture first</span></div>
|
||||
<div class="scenario-track"><span class="is-plain" style={`--scenario-width:${(baselineFloor / maxScenarioFloor) * 100}%`}></span></div>
|
||||
<output>{displayMs(baselineFloor)}</output>
|
||||
</div>
|
||||
<div class="scenario-row">
|
||||
<div class="scenario-label"><strong>After</strong><span>Plain pick, dispatch first</span></div>
|
||||
<div class="scenario-track"><span class="is-annotated" style={`--scenario-width:${(protocolFloor / maxScenarioFloor) * 100}%`}></span></div>
|
||||
<output>{displayMs(protocolFloor)}</output>
|
||||
</div>
|
||||
<div class="scenario-row">
|
||||
<div class="scenario-label"><strong>Annotated pick</strong><span>Pin + stroke + upload</span></div>
|
||||
<div class="scenario-track"><span class="is-annotated" style={`--scenario-width:${(annotatedFloor / maxScenarioFloor) * 100}%`}></span></div>
|
||||
<div class="scenario-label"><strong>Annotated control</strong><span>Pin + stroke + upload</span></div>
|
||||
<div class="scenario-track"><span class="is-control" style={`--scenario-width:${(annotatedFloor / maxScenarioFloor) * 100}%`}></span></div>
|
||||
<output>{displayMs(annotatedFloor)}</output>
|
||||
</div>
|
||||
</div>
|
||||
<p class="live-performance-caption">Protocol-only measurements: {plain.summary.count} plain runs, {annotated?.summary.count || 0} annotated runs. Browser and filesystem caches were warm.</p>
|
||||
<p class="live-performance-caption">Median protocol measurements: {baseline.summary.count} before runs, {plain.summary.count} optimized runs, {annotated?.summary.count || 0} annotated controls. Browser and filesystem caches were warm.</p>
|
||||
</section>
|
||||
|
||||
<section class="live-performance-section live-simulator-section ks-section" aria-labelledby="simulator-title">
|
||||
<div class="live-performance-section-head">
|
||||
<div>
|
||||
<p class="live-performance-label">Latency simulator</p>
|
||||
<h2 id="simulator-title">Model speed does not erase fixed overhead</h2>
|
||||
<h2 id="simulator-title">The gain survives slower models</h2>
|
||||
</div>
|
||||
<p>Move the model time. The protocol floor stays put.</p>
|
||||
<p>Move model time to compare the old floor with the optimized product-side estimate.</p>
|
||||
</div>
|
||||
<div class="live-simulator">
|
||||
<label for="model-latency">Model generates all variants <output data-model-value>15 s</output></label>
|
||||
<input id="model-latency" data-model-latency type="range" min="0" max="60000" step="500" value="15000" />
|
||||
<div class="simulator-results" aria-live="polite">
|
||||
<div>
|
||||
<span>Current atomic path</span>
|
||||
<span>Before optimization</span>
|
||||
<strong data-current-total>15.9 s</strong>
|
||||
<small>model + measured protocol floor</small>
|
||||
<small>model + measured baseline</small>
|
||||
</div>
|
||||
<div>
|
||||
<span>Capture fully overlapped</span>
|
||||
<span>Current optimized path</span>
|
||||
<strong data-overlap-total>15.1 s</strong>
|
||||
<small>best-case projection, not a measured target</small>
|
||||
<small>model + measured floor, excluding Playwright actionability</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
|
||||
.scenario-track .is-plain { background: var(--ks-kinpaku); }
|
||||
.scenario-track .is-annotated { background: var(--ks-patina); }
|
||||
.scenario-track .is-control { background: var(--ks-graphite-2); }
|
||||
|
||||
.scenario-row output {
|
||||
color: var(--ks-champagne);
|
||||
|
||||
+4
-18
@@ -18,27 +18,13 @@ Approach every design task as the design lead at a small studio known for giving
|
||||
1. Run `node {{scripts_path}}/context.mjs` once per session (if the runtime shows this skill's loaded base directory, run `node <skill-base-dir>/scripts/context.mjs`; keep cwd at the user's project). It prints the project's PRODUCT.md and DESIGN.md when they exist; follow what it prints, including any `UPDATE_AVAILABLE` directive (ask once, never block). If it reports `NO_PRODUCT_MD`: for `init`, `teach`, `craft`, `shape`, or wording that clearly maps to a from-scratch build flow, divert into `reference/init.md` first, **unless no user can respond** (a one-shot or automated run, or the user said not to ask): then write your own one-paragraph understanding of the product, audience, and the page's job from the brief and continue. For scoped evaluate/refine/fix requests against existing code, never divert into init; the existing code is the context. <!-- rule:skill-setup-context -->
|
||||
2. If the user invoked a sub-command (`audit`, `polish`, `live`, ...), read **`reference/<command>.md`** (the `.native` variant from the Commands table when the platform is `ios`/`android`/`adaptive`) and follow it. On unattended runs, `craft` and `shape` collapse into this file's process: decide, record each decision in one line, build, self-review. <!-- rule:skill-setup-command-ref -->
|
||||
3. Read at least one project file (CSS / tokens / theme / a representative component) to learn what world you're in. If PRODUCT.md's `## Platform` is `ios` or `android`, also read `reference/<platform>.md` (`adaptive` reads both). <!-- rule:skill-setup-read-project -->
|
||||
4. If the project is brand-new (no committed tokens, fonts, or brand colors found in step 3), run `node {{scripts_path}}/palette.mjs` for a brand seed color. The seed breaks your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this step entirely when step 3 found committed brand colors: identity-preservation wins. <!-- rule:skill-setup-palette-seed -->
|
||||
|
||||
## How to design
|
||||
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this file warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save. <!-- rule:skill-brief-wins -->
|
||||
**The brief wins.** Where the brief pins down a direction (a named aesthetic, an era, a place, a material, a specific font or palette), follow it exactly, including when it asks for a look this skill warns is saturated. Redirecting a pinned direction toward your own taste is a failure, not a save. <!-- rule:skill-brief-wins -->
|
||||
|
||||
**Existing worlds are sacred.** When the surface already has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside it: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Treat the task as new identity work only when nothing committed exists, or when the user asks for a redesign that discards the current look. A redesign is new work: derive the concept from the subject and the brief, not from the incumbent page's structure or styling. <!-- rule:skill-existing-world-preservation -->
|
||||
**Existing worlds are sacred.** Most of impeccable's work happens inside a site or app that already exists. When the surface has a committed design system (real tokens, deliberately chosen faces, a palette the brand owns), work inside that world: extend it, sharpen it, leave it unmistakably the same brand, and never degrade a working page's performance. Inventing parallel colors, fonts, or styles on an existing surface is a defect, not creativity. <!-- rule:skill-existing-world-preservation -->
|
||||
|
||||
**Ground it in the subject.** Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume. <!-- rule:skill-ground-in-subject -->
|
||||
|
||||
**Plan, self-check, build.** Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan. <!-- rule:skill-plan-self-check -->
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet. <!-- rule:skill-hero-thesis -->
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit. <!-- rule:skill-everything-bold -->
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance. <!-- rule:skill-prove-dont-claim -->
|
||||
|
||||
**Commit.** Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice. <!-- rule:skill-color-strategy-commitment -->
|
||||
|
||||
**Calibration.** AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious. <!-- rule:skill-slop-calibration -->
|
||||
**New identity work reads the playbook first.** When nothing committed exists (greenfield, or a codebase with no real tokens or chosen faces), or the user asks for a redesign that discards the current look, you MUST read [reference/new-work.md](reference/new-work.md) before making any design decision. Not optional, not skippable under time pressure: producing new identity without it yields the generic default this skill exists to prevent. A redesign is new work; derive the concept from the subject and the brief, not from the incumbent page's structure or styling. `context.mjs` prints this directive when it detects the situation. Scoped fixes inside an existing world don't need the playbook; the craft floor below governs them. <!-- rule:skill-new-work-gate -->
|
||||
|
||||
## Craft floor
|
||||
|
||||
@@ -68,7 +54,7 @@ Calibration for this provider:
|
||||
|
||||
Name the visitor's mode before designing; the page's grammar follows from it, and most ruined pages are one mode wearing another mode's grammar. The brief and the surface decide the mode. PRODUCT.md's `register` field names the family (`brand` covers Persuade and Experience; `product` covers Operate and Read), and `reference/brand.md` / `reference/product.md` carry extended depth for the two families. <!-- rule:skill-visitor-mode -->
|
||||
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans. <!-- rule:brand-register-core -->
|
||||
**Persuade** (landing pages, marketing, campaigns; design IS the product). The deliverable is an impression that stops the scroll, earns the click, converts. Spans every genre (tech, luxury, consumer); don't collapse them into one look. Briefs that imply imagery must ship real, verified imagery; a colored rectangle where a photo belongs reads as incomplete. New Persuade surfaces take their typeface procedure and reject list from [reference/new-work.md](reference/new-work.md). <!-- rule:brand-register-core -->
|
||||
|
||||
**Operate** (app UI, dashboards, admin, tools; design SERVES the task). A person getting something done: density, scanability, and consistency outrank expressiveness. These surfaces earn trust by feeling native to their platform: system font stacks and workhorse UI faces are legitimate and often correct here (the Persuade reject list does not apply). The brand lives in the details: focus states, empty states, microcopy, one owned accent. <!-- rule:product-register-core -->
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# New identity work
|
||||
|
||||
You are reading this because nothing committed exists yet (greenfield), or the user asked for a redesign that discards the current look. Either way the task is the same: invent a visual identity that could not be mistaken for anyone else's, and build it to the craft floor. SKILL.md's rules all still apply; this file is the process that produces the identity.
|
||||
|
||||
## Seed
|
||||
|
||||
If the project is brand-new (no committed tokens, fonts, or brand colors found in the code), run `node {{scripts_path}}/palette.mjs` for a brand seed color. The seed exists to break your reflex palette; it does not override the subject. When the subject's world clearly dictates color (an era, a place, a material, a medium), derive the palette from that world and use the seed only to check yourself. Otherwise anchor on it. Use OKLCH throughout. Skip this entirely when the code already has committed brand colors: identity-preservation wins.
|
||||
|
||||
## Ground it in the subject
|
||||
|
||||
Name one concrete subject, its audience, and the page's single job. The subject's own world (its materials, instruments, artifacts, places, history, vernacular) is where distinctive choices come from. What would this thing look like as a physical object? What did its world look like before the web? A design whose subject appears only in the copy is a template wearing a costume.
|
||||
|
||||
## Plan, self-check, build
|
||||
|
||||
Plan a compact token system in your reasoning: palette, type, layout concept in one sentence, and a **signature**: the one element this page will be remembered by, drawn from the subject's world. A signature carries weight: sized and placed so the page organizes itself around it. The standard page skeleton is a default, not a given; derive structure from what the subject needs. Then audit the plan: work through what you'd produce for a similar brief from another client, and wherever the two plans converge (same palette family, same face, same skeleton), that part is your generic default, not a choice. Revise it, then build, deriving every color and type decision from the revised plan.
|
||||
|
||||
**The opening viewport is a thesis, not a header.** Open with the most characteristic thing in the subject's world, in whatever form it takes: the product visibly working, an artifact from that world, the signature itself at full scale. A headline over two buttons is the template answer; earn it or replace it. The memory test: if a stranger scrolled past this page once, what would they describe an hour later? If the honest answer is a mood ("clean", "tasteful"), the concept hasn't committed yet.
|
||||
|
||||
**Everything bold, nothing bland.** Bold is not decoration and not clutter; it is commitment to the concept, carried through every section. Commitment takes whatever form the concept demands: maximal or severely clean, drenched in color or nearly monochrome, copy so precise it stings, the product demonstrating itself instead of being described. A spare page built on one uncompromising idea is bold; a busy page of tasteful defaults is bland. The signature is where the concept peaks, not the only place it lives; cut anything that neither advances the concept nor serves the brief. Polish is the floor, not the point: when torn between refined and committed, commit.
|
||||
|
||||
**Prove, don't claim.** A page earns belief by showing the product doing its job: the interface at work, the mechanism dramatized, numbers and specifics a competitor couldn't copy-paste. A reader should understand what it does by looking, before reading a word. Sections that restate the hero's claim in different words add length, not substance.
|
||||
|
||||
## Commit
|
||||
|
||||
Pick a color strategy before picking colors: Restrained (neutrals + one accent; the default when the visitor came to operate or read) / Committed (one saturated color carries 30-60% of the surface) / Full palette (3-4 named roles) / Drenched (the surface IS the color). Persuade and Experience surfaces have permission for the bolder strategies; take them when the brief allows. Dark vs. light is never a default: write one sentence of physical scene (who uses this, where, under what light, in what mood) and let it force the answer. The warm cream near-white body background is the saturated AI default; where the axis is free, pick a background that is a choice.
|
||||
|
||||
## Type and imagery for new Persuade and Experience surfaces
|
||||
|
||||
Choose faces like objects from the brand's world; these training-data defaults mean you stopped looking: Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, Space Grotesk, Space Mono, IBM Plex, Inter-as-display, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans. (For Operate and Read surfaces the opposite holds: system stacks and workhorse UI faces are legitimate and often correct.)
|
||||
|
||||
Imagery-implying briefs (food, travel, place, product, fashion) must ship real, verified imagery, searched for the brand's physical object rather than the category; a colored rectangle where a photo belongs reads as incomplete, and one decisive photo beats five mediocre ones. Verify stock URLs resolve before shipping them.
|
||||
|
||||
## Calibration
|
||||
|
||||
AI-generated interfaces cluster around a few looks regardless of subject: warm cream + high-contrast serif + terracotta accent; near-black + one neon accent (acid green, cyan) + glowing edges; broadsheet-editorial hairlines + italic display serif + small tracked mono labels. All are legitimate when the brief calls for them; the brief always wins. Where the brief leaves the aesthetic free, landing in one of them means your self-check failed. Same one tier deeper: if someone could guess your aesthetic from the category alone, or from category-plus-avoidance, rework until neither answer is obvious.
|
||||
|
||||
Before finishing, verify against SKILL.md's craft floor and run the detector; a bold page that ships mechanical defects is not done.
|
||||
@@ -904,6 +904,10 @@ async function cli() {
|
||||
'reference/init.md and write PRODUCT.md first; for any other (scoped) ' +
|
||||
'command against existing code, proceed using the code as context and ' +
|
||||
`offer \`${IMPECCABLE_COMMAND} init\` as a suggestion (do not block).`,
|
||||
'NEW_WORK: No committed design context was found. If this task produces ' +
|
||||
'new design (a build from scratch, or a redesign that discards the ' +
|
||||
'current look), you MUST read reference/new-work.md before making any ' +
|
||||
'design decision. Scoped fixes to existing code do not need it.',
|
||||
];
|
||||
parts.push(buildResolvedContextDirective(ctx, cliOptions, { targetExists }));
|
||||
if (shouldWarnMissingTarget(ctx, targetProvided, targetExists)) {
|
||||
@@ -922,10 +926,22 @@ async function cli() {
|
||||
parts.push(buildMissingTargetDirective());
|
||||
}
|
||||
const register = extractRegister(ctx.product);
|
||||
const next = register
|
||||
? `NEXT STEP: This project's register is \`${register}\`. You MUST now read \`reference/${register}.md\` before producing any design output.`
|
||||
: `NEXT STEP: You MUST now read the matching register reference (\`reference/brand.md\` or \`reference/product.md\`) before producing any design output. Pick based on PRODUCT.md above.`;
|
||||
parts.push(next);
|
||||
// The register field survives as a family hint (brand = Persuade/Experience,
|
||||
// product = Operate/Read); SKILL.md's mode section carries the essentials
|
||||
// inline, so no register-file read is mandated here. What IS mandated:
|
||||
// the new-work playbook when no committed design system exists yet.
|
||||
if (!ctx.hasDesign) {
|
||||
parts.push(
|
||||
'NEW_WORK: PRODUCT.md exists but no DESIGN.md was found. If the code ' +
|
||||
'has no committed design system either (check the project files), and ' +
|
||||
'this task produces new design or a redesign that discards the current ' +
|
||||
'look, you MUST read reference/new-work.md before making any design ' +
|
||||
'decision. Scoped fixes inside an existing design system do not need it.',
|
||||
);
|
||||
}
|
||||
if (register) {
|
||||
parts.push(`REGISTER: \`${register}\` (family hint: brand = Persuade/Experience surfaces, product = Operate/Read). Derive the visitor's mode per SKILL.md; \`reference/${register}.md\` has extended depth for substantial work.`);
|
||||
}
|
||||
const platform = extractPlatform(ctx.product);
|
||||
const nativeRefs =
|
||||
platform === 'adaptive' ? ['ios', 'android'] : platform === 'ios' || platform === 'android' ? [platform] : [];
|
||||
@@ -933,7 +949,7 @@ async function cli() {
|
||||
const refList = nativeRefs.map(p => `\`reference/${p}.md\``).join(' and ');
|
||||
const label = platform === 'adaptive' ? '`adaptive` (both iOS and Android)' : `\`${platform}\``;
|
||||
parts.push(
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to the register reference.`,
|
||||
`NEXT STEP: This project targets ${label}. Also read ${refList} for native conventions, in addition to SKILL.md's mode guidance.`,
|
||||
);
|
||||
} else if (!platform) {
|
||||
// A `## Platform` section that names something we don't recognize (a
|
||||
|
||||
@@ -7105,6 +7105,14 @@
|
||||
}
|
||||
|
||||
async function captureAndEmit(el, basePayload, snapshot, rect) {
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
|
||||
// Plain requests do not send a screenshot to the agent, so capture is
|
||||
// presentation-only. Wait only for the helper to accept the event before
|
||||
// starting CPU-heavy capture; this yields the browser task and prevents
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) await sendEvent(basePayload);
|
||||
|
||||
let screenshotPath;
|
||||
let blob;
|
||||
let paper;
|
||||
@@ -7122,7 +7130,6 @@
|
||||
// are present. Without annotations the image is pure visual anchoring -
|
||||
// it biases the model toward the current rendering and works against the
|
||||
// three-distinct-directions brief.
|
||||
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
|
||||
if (blob && hasAnnotations) {
|
||||
try {
|
||||
const uploadRes = await fetch(
|
||||
@@ -7140,7 +7147,11 @@
|
||||
console.warn('[impeccable] annotation upload failed:', err);
|
||||
}
|
||||
}
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Annotated requests must wait for capture + upload because the screenshot
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
+10
-8
@@ -461,7 +461,7 @@ describe('loadContext (monorepo project context)', () => {
|
||||
assert.match(res.stdout, /"targetPath": "apps\/dashboard\/src\/App\.jsx"/);
|
||||
assert.match(res.stdout, /"productPath": "apps\/dashboard\/PRODUCT\.md"/);
|
||||
assert.match(res.stdout, /"designPath": "DESIGN\.md"/);
|
||||
assert.match(res.stdout, /NEXT STEP: This project's register is `product`\./);
|
||||
assert.match(res.stdout, /REGISTER: `product`/);
|
||||
});
|
||||
|
||||
it('asks for an app when the CLI runs from a monorepo root without selection', () => {
|
||||
@@ -806,8 +806,10 @@ describe('context.mjs CLI', () => {
|
||||
assert.match(res.stdout, /^# PRODUCT\.md/);
|
||||
assert.match(res.stdout, /# Acme/);
|
||||
assert.equal(res.stdout.includes('# DESIGN.md'), false);
|
||||
// The NEXT STEP directive is always appended after `---`.
|
||||
assert.match(res.stdout, /\n---\n\nNEXT STEP:/);
|
||||
// Directives are appended after `---`; with no DESIGN.md the
|
||||
// new-work gate directive fires.
|
||||
assert.match(res.stdout, /\n---\n\n/);
|
||||
assert.match(res.stdout, /NEW_WORK: PRODUCT\.md exists but no DESIGN\.md/);
|
||||
});
|
||||
|
||||
it('concatenates PRODUCT.md and DESIGN.md with a --- separator', async () => {
|
||||
@@ -819,7 +821,7 @@ describe('context.mjs CLI', () => {
|
||||
assert.match(res.stdout, /^# PRODUCT\.md/);
|
||||
assert.match(res.stdout, /\n---\n/);
|
||||
assert.match(res.stdout, /# DESIGN\.md\n\n# Acme design/);
|
||||
assert.match(res.stdout, /NEXT STEP:/);
|
||||
assert.equal(res.stdout.includes('NEW_WORK:'), false);
|
||||
});
|
||||
|
||||
it('reads from a fallback dir when cwd is clean', async () => {
|
||||
@@ -836,8 +838,8 @@ describe('context.mjs CLI', () => {
|
||||
const { spawnSync } = await import('node:child_process');
|
||||
const res = spawnSync(process.execPath, [SCRIPT_PATH], { cwd: scratch, encoding: 'utf8', env: { ...process.env, IMPECCABLE_NO_UPDATE_CHECK: '1' } });
|
||||
assert.equal(res.status, 0);
|
||||
assert.match(res.stdout, /NEXT STEP: This project's register is `brand`\./);
|
||||
assert.match(res.stdout, /read `reference\/brand\.md`/);
|
||||
assert.match(res.stdout, /REGISTER: `brand`/);
|
||||
assert.match(res.stdout, /reference\/brand\.md/);
|
||||
});
|
||||
|
||||
it('falls back to a generic register directive when no register field is present', async () => {
|
||||
@@ -845,8 +847,8 @@ describe('context.mjs CLI', () => {
|
||||
const { spawnSync } = await import('node:child_process');
|
||||
const res = spawnSync(process.execPath, [SCRIPT_PATH], { cwd: scratch, encoding: 'utf8', env: { ...process.env, IMPECCABLE_NO_UPDATE_CHECK: '1' } });
|
||||
assert.equal(res.status, 0);
|
||||
assert.match(res.stdout, /NEXT STEP: You MUST now read the matching register reference/);
|
||||
assert.match(res.stdout, /reference\/brand\.md.*reference\/product\.md/);
|
||||
assert.match(res.stdout, /NEW_WORK: PRODUCT\.md exists but no DESIGN\.md/);
|
||||
assert.equal(res.stdout.includes('REGISTER:'), false);
|
||||
});
|
||||
|
||||
it('appends a native platform directive for an ios project', async () => {
|
||||
|
||||
@@ -5,8 +5,26 @@ import { join } from 'node:path';
|
||||
|
||||
const SOURCE = readFileSync(join(process.cwd(), 'skill/scripts/live-browser.js'), 'utf-8');
|
||||
const PENDING_DOCK_POSITION_SOURCE = SOURCE.match(/function positionPendingDock\(\) \{[\s\S]*?\n \}/)?.[0] || '';
|
||||
const CAPTURE_AND_EMIT_SOURCE = SOURCE.match(/async function captureAndEmit\([\s\S]*?\n \}/)?.[0] || '';
|
||||
|
||||
describe('live-browser source contracts', () => {
|
||||
it('dispatches plain generation before screenshot capture without bypassing annotated evidence', () => {
|
||||
const dispatchIndex = CAPTURE_AND_EMIT_SOURCE.indexOf('if (!hasAnnotations) await sendEvent(basePayload);');
|
||||
const captureIndex = CAPTURE_AND_EMIT_SOURCE.indexOf('await captureElementToBlob');
|
||||
assert.ok(dispatchIndex >= 0, 'plain generation should dispatch immediately');
|
||||
assert.ok(captureIndex > dispatchIndex, 'plain generation dispatch must happen before capture begins');
|
||||
assert.match(
|
||||
CAPTURE_AND_EMIT_SOURCE,
|
||||
/if \(blob && hasAnnotations\)[\s\S]*?\/annotation\?token=/,
|
||||
'annotation screenshots should still upload before annotated generation dispatch',
|
||||
);
|
||||
assert.match(
|
||||
CAPTURE_AND_EMIT_SOURCE,
|
||||
/if \(hasAnnotations\) \{\s*sendEvent\(screenshotPath \? \{ \.\.\.basePayload, screenshotPath \} : basePayload\);\s*\}/,
|
||||
'annotated generation should dispatch exactly after capture and upload resolve',
|
||||
);
|
||||
});
|
||||
|
||||
it('saves copy edits to the staged buffer with rich AI context', () => {
|
||||
assert.doesNotMatch(
|
||||
SOURCE,
|
||||
|
||||
Reference in New Issue
Block a user