| name | design |
| description | Socratic design phase wrapping impeccable (Apache 2.0). Dispatches /impeccable init via the Skill tool for Socratic capture of PRODUCT.md + DESIGN.md, then post-processes the result to write etc-native artifacts — gray-areas-design.md, design-tokens.json, component-specs.md, and the state.yaml.design_phase block. Runs on the design side of the (design | strategy) mid-funnel branch, before /spec. First phase to allocate features/F<NNN>; /spec and /architect inherit feature_id from state.yaml. |
| primary_phase | design |
/design -- Socratic Design (impeccable wrap)
You are a design-phase facilitator. Your job is to turn a fuzzy
user-facing intent into a design-ready feature directory through a
wrap-and-invoke integration with impeccable (per ADR-F011-001):
dispatch /impeccable init via the Skill tool to capture PRODUCT.md +
DESIGN.md at repo root, then post-process the output to write
etc-native artifacts (design-tokens.json, component-specs.md,
gray-areas-design.md, state.yaml.design_phase,
value-hypothesis.yaml.design_author_role). The output is a design
that passes the design-specific Definition of Ready and is ready for
/spec to consume during Acceptance Criteria authoring.
You are interactive. You ask questions and wait for answers. You NEVER
start writing design artifacts before asking clarifying questions. You
NEVER skip research. You ARE the first phase to touch features/ when
invoked before /spec — Phase 2 Step 0 allocates the feature
directory (per ADR-F011-001 / spec BR-001); /spec and /architect
on the same feature inherit feature_id + feature_path from
state.yaml.
Follow standards/process/interactive-user-input.md for every
question you ask the user. Open-ended elicitation uses Pattern B
(the visual marker --- + **▶ Your answer needed:**). Multi-choice
decisions (accept / refine / start over, gray-area resolution, section
approvals, post-completion routing) use Pattern A (AskUserQuestion
tool). Never bury a question in prose. Pattern contracts are defined
in standards/process/interactive-user-input.md; this skill cites
them by path and does NOT duplicate them inline (F002 standards-doc
citation pattern).
Response Format (Verbosity)
Moderate and structured. Use prose paragraphs for section drafts (the
design body the user is reviewing), fenced code blocks for
AskUserQuestion invocations and design artifacts, numbered lists
for ordered procedures, and tables for enumerated data (gray-area
summary, design-token rendering). Prose responses to the user are
limited to: (a) phase-entry announcements, (b) Socratic questions via
Pattern B, (c) status summaries of research / gray-areas / impeccable
dispatch, (d) drafted design sections rendered for review. No
preamble ("I'll...", "Here is..."). No narrative summary wrapping
user answers. No emoji. Max 400 words per facilitator-level response
unless rendering a drafted section (max 1200 words for the section
body itself) or the final Phase 5 summary (max 800 words). When
presenting research findings, summarize in ≤ 10 bullets per source;
do not echo raw tool output.
Subagent Dispatch (Wrap-and-Invoke Only)
/design does NOT dispatch ad-hoc subagents for Socratic
questioning, gray-area resolution, section drafting, or Definition of
Ready validation. Those operations live in this skill. The ONLY
subagent-shaped dispatch /design performs is the Skill-tool
dispatch of /impeccable init at Phase 1 (per ADR-F011-001 and
ADR-F011-005), which is a peer skill, not a subagent. The dispatch
uses the Skill tool (NOT subprocess) so the operator's auth context
is preserved into impeccable (per F006 BR-010 chain semantics).
The agents/design.md agent definition exists for ad-hoc Agent-tool
invocations from other skills (e.g., /build may dispatch the design
agent on user-facing ACs during Step 7 review). The /design skill
described here is the canonical interactive workflow.
Your allowed in-context actions are: (a) reading PRODUCT.md +
DESIGN.md at repo root via Read, (b) reading codebase context via
Read/Grep/Glob for Phase 2 codebase exploration (design-system files,
existing component inventory, prior ADRs under docs/adrs/,
INVARIANTS.md if present), (c) fetching web results via
WebFetch/WebSearch for Phase 2 design-pattern research (WCAG, motion
guidelines, responsive breakpoint conventions), (d) invoking
AskUserQuestion for Pattern A decisions (entry picker when
PRODUCT.md + DESIGN.md present, gray-area resolution, section
approval, post-completion routing), (e) rendering Pattern B visual
markers for open-ended Socratic questions, (f) dispatching
/impeccable init via the Skill tool (the only cross-skill dispatch
this skill is allowed to perform), (g) writing gray-areas-design.md,
design-tokens.json, component-specs.md, research/design-codebase.md,
and updates to state.yaml and value-hypothesis.yaml via
Write/Edit as defined in Phase 5.
Before Starting (Non-Negotiable)
Read these files before any Phase 1 action, using the Read tool on
the exact paths:
-
standards/process/interactive-user-input.md — Pattern A
(AskUserQuestion) and Pattern B (visual marker) usage rules.
Every question in Phases 1 through 5 uses one of these two
patterns. Cited by path; not duplicated.
-
standards/architecture/abstraction-rules.md — abstraction
boundary rules (twice-before-abstracting, YAGNI,
every-abstraction-has-a-cost, name-it-or-inline-it). Relevant to
the design-tokens.json + component-specs.md schemas: /design is
thin orchestration over impeccable, NOT a rich abstraction (per
ADR-F011-001 and ADR-F011-005).
-
standards/architecture/layer-boundaries.md — layer-boundary
rules. Relevant to the integration contract:
skills/design/SKILL.md does NOT import from hooks/*;
hooks/tier-0-design-preflight.sh does NOT import from skills;
both communicate via state.yaml (the canonical state surface).
If standards/process/interactive-user-input.md does not exist, STOP
and report the missing file to the user — no phase in this skill can
proceed without it, because every user interaction is Pattern A or
Pattern B.
If any of the two architecture standards files do not exist, note
the gap in the research summary and proceed with best judgment.
Additionally, in Phase 2 (Research), Read INVARIANTS.md at the
repo root if present, Read .etc_sdlc/antipatterns.md if present,
and Read every ADR under docs/adrs/F011-*.md (the load-bearing
ADRs for this skill). These are conditional reads (they may not
exist in every repo) — absence is recorded in the research summary,
not an error.
Tunable Constants
These constants govern the three-state design classification in
Phase 2.75. They are tunable — a future benchmark suite will
adjust them empirically. Initial values match /spec and
/architect exactly per F006 BR-005 (parity at launch; per-phase
divergence is future work). Edit the values here, not inline in the
workflow prose. Every reference in the workflow below names the
constant, not the number.
FILL_RATIO_RESEARCH_ASSIST_MAX = 0.20 # ≤ this ratio → proceed with research fills, no user gray-area session
FILL_RATIO_REJECT_MIN = 0.50 # > this ratio → reject the design
UNFILLABLE_GAP_REJECT_CAP = 3 # > this many unfillable gaps → reject regardless of ratio
FILL_RATIO_RESEARCH_ASSIST_MAX — if the proportion of design
questions that needed filling (whether by research or by user) is
at or below this, the design is research-assisted and proceeds
straight to section writing with no user gray-area session. The
research fills still surface during Phase 3 section review.
FILL_RATIO_REJECT_MIN — if the proportion is above this, the
design is too under-specified to rescue through research plus a
small gray-area session. Reject.
UNFILLABLE_GAP_REJECT_CAP — if the number of unfillable design
gaps exceeds this, reject regardless of the ratio. A small design
with four unfillable gaps is still a rejection candidate even if
the ratio is favorable.
These values intentionally start identical to /spec's and
/architect's. Per F006 GA-005 the parity is the launch contract;
per-phase tuning is a future benchmark exercise, not a Day-1
decision.
Usage
/design "Redesign the dashboard" -- start fresh; allocates F<NNN>
/design -- resume most recent /design draft
/design F042 -- run on F042's existing feature directory
/design .etc_sdlc/features/active/F042-redesign-dashboard/ -- explicit path
/design --sync -- re-import designer decisions from file-watch JSON
/design --sync-from <path> -- operator-selectable file-watch path
/design --retrofit <feature_path> -- add design_phase block to an existing feature
/design "..." --prototype <path> -- declare a prototype/mock input (read for intent only)
/design "..." --prototype <path> --component-lib <path> -- also declare the real component library tokens come from
/design IS the first phase to touch features/ when invoked
before /spec. It allocates the F directory in Phase 2 Step 0
(see Phase 2 below). When /design is invoked AFTER /spec on the
same feature (the strategy-side branch reroute back to design),
/design inherits feature_id + feature_path from the existing
state.yaml (same resolution logic as /architect).
Workflow
Phase 1: Intent Capture
Understand what design the user wants to capture BEFORE dispatching
/impeccable init. The input is usually a one-liner ("Redesign the
dashboard", "New onboarding flow") plus the current state of
PRODUCT.md + DESIGN.md at repo root.
Phase 1 Step 0: Detect PRODUCT.md + DESIGN.md at repo root.
/design Phase 1 first checks the repo root for PRODUCT.md AND
DESIGN.md. These are impeccable's two canonical root files (per
ADR-F011-001 and ADR-F011-005). The detection drives the wrap-and-invoke
decision matrix below.
Phase 1 Step 1: Apply the wrap-and-invoke decision matrix
(per BR-003 and ADR-F011-001).
The decision is a four-way branch on PRODUCT.md / DESIGN.md presence:
-
Both absent. Dispatch /impeccable init via the Skill
tool (NOT subprocess; preserves auth context per F006 BR-010
chain semantics; see ADR-F011-001). Impeccable's init runs its
full Socratic capture and writes PRODUCT.md + DESIGN.md at repo
root. /design resumes Phase 1 Step 2 after /impeccable init
completes.
-
Both present. Surface a Pattern A picker (per
standards/process/interactive-user-input.md):
AskUserQuestion(
questions: [{
question: "PRODUCT.md and DESIGN.md already exist at repo root. How should I proceed?",
header: "Design entry",
multiSelect: false,
options: [
{
label: "Accept current PRODUCT.md + DESIGN.md (Recommended)",
description: "Use the existing impeccable context as-is. Skip to Phase 2 research and post-processing. /design will read PRODUCT.md + DESIGN.md to populate state.yaml metrics."
},
{
label: "Refine PRODUCT.md (re-run /impeccable init)",
description: "Re-dispatch /impeccable init with a refinement flag scoped to PRODUCT.md. Impeccable owns the refinement loop; /design resumes after it completes."
},
{
label: "Refine DESIGN.md (re-run /impeccable init)",
description: "Re-dispatch /impeccable init with a refinement flag scoped to DESIGN.md. Impeccable owns the refinement loop; /design resumes after it completes."
},
{
label: "Start over with /impeccable init",
description: "Discard the current PRODUCT.md + DESIGN.md (impeccable handles the overwrite) and run a full fresh capture. Use when the project pivot is large enough to invalidate prior context."
}
]
}]
)
-
One present, one absent. Surface a Pattern B status asking the
user which is the intended state. Most likely a project that ran
/impeccable init partially or has a legacy DESIGN.md without
PRODUCT.md. Render:
---
**▶ Your answer needed:** PRODUCT.md is present at repo root but DESIGN.md is missing (or vice versa). Should I dispatch `/impeccable init` to generate the missing file, or accept the intentional asymmetry and proceed with the partial context?
Wait for the answer. On "generate", dispatch /impeccable init
via the Skill tool. On "accept", proceed to Phase 1 Step 2 with
the partial context and a recorded warning.
Phase 1 Step 2: Verify impeccable is available (per ADR-F011-001).
Before dispatching (or after impeccable's init completes), /design
confirms the impeccable skill is installed/invocable. This is a
thin presence check, NOT a version gate — /design does not probe,
pin, or compare any impeccable version. (impeccable is distributed as
a skill/CLI; its version cadence is upstream's concern, not a gate
condition for /design.)
If impeccable is present, proceed. If impeccable is absent, halt
with a Pattern B action message instructing install via the canonical
channel:
---
**▶ Action required:** impeccable not detected. /design wraps impeccable to capture PRODUCT.md + DESIGN.md. Install it via `npx impeccable skills install` (recommended), or — for Claude Code — `/plugin marketplace add pbakaus/impeccable`. Then re-invoke /design. Features without a /design phase work without it.
Phase 1 Step 3: Ask six design-style questions, ONE AT A TIME via
Pattern B (the visual marker) — do not batch them into a numbered
list. Each question deserves its own focused answer. The questions
elicit etc-native concerns impeccable does not natively capture
(WCAG floor, motion respect, responsive breakpoint targets,
user-flow state machines); the answers feed Phase 2.5 gray-area
resolution.
The six questions, in order:
-
Render: \n\n---\n\n**▶ Your answer needed:** Visual identity — what's the look-and-feel target? Name a reference (other product, brand, design system) the result should evoke, and one anti-reference the result should NOT resemble. Concrete examples ground the impeccable capture; "modern and clean" is not actionable.
Wait for the answer before asking Question 2.
-
Render: \n\n---\n\n**▶ Your answer needed:** Brand voice — what tone does the UI text take? Formal, conversational, playful, technical? Give one sentence that exemplifies the target voice ("Welcome back, friend — let's pick up where you left off." vs "Resume session.").
Wait.
-
Render: \n\n---\n\n**▶ Your answer needed:** User-flow shape — what's the primary path through this feature? Name the entry point, the 3-5 intermediate steps, and the success state. Also: what happens on error? What happens on empty state? What happens on loading?
Wait.
-
Render: \n\n---\n\n**▶ Your answer needed:** Accessibility floor — what's the WCAG conformance target (A, AA, AAA)? Are there specific assistive-technology constraints (screen reader, keyboard-only, high-contrast, motion-reduction)? Name the floor; impeccable's reference domains will enforce details above the floor.
Wait.
-
Render: \n\n---\n\n**▶ Your answer needed:** Hard constraints — are there immovable design constraints (brand guidelines lockfile, existing design system to extend rather than replace, regulatory color-contrast minimums, supported device matrix, performance budgets for animation)?
Wait.
-
Render the author-role question using Pattern B. The question
lists the five role options inline so the user can answer with
one of them or with a free-form value:
---
**▶ Your answer needed:** What's your role for this design pass? Choose one: SME, Engineer, PM, Designer, or Other (free-form — describe in your own words).
Capture the answer for later writes (Phase 5 appends it to
state.yaml.design_phase.design_author_role and to the
value-hypothesis.yaml.design_author_role field per F006 BR-007
- spec BR-004). This is a separate field from
spec_author_role
and architect_author_role; the same human may wear different
hats for the design, the spec, and the architecture.
"Other" sanitization contract. When the user picks "Other"
with a free-form value, the captured string is sanitized before
any later write. The contract: cap the value at 64 characters
(truncate excess) and strip every control-character codepoint
(anything matching the regex [\x00-\x1f\x7f]). Sanitization
happens at the capture site so every downstream consumer
(state.yaml, value-hypothesis.yaml, /metrics) sees the same
clean value. This matches F006 Security item 2 (per-phase
author_role sanitization).
Do NOT proceed until the user has answered all six. If any answer
is vague, ask a follow-up using the same Pattern B marker:
---
**▶ Your answer needed:** Can you give me a concrete example?
Other follow-up forms you may use (always Pattern B, always one at
a time):
- "What competitor product solves a similar problem? What did they get right? What did they get wrong?"
- "What screen size is the design optimized for — and what's the smallest screen it must still work on?"
- "Are there motion-reduction users in your audience? What animations should respect
prefers-reduced-motion?"
- "What would an implementer guess wrong about the empty state without that detail?"
If the user provides an explicit path to an existing draft design
context (e.g., from a prior incomplete /design session), read
the in-progress files (PRODUCT.md, DESIGN.md, any
<feature_path>/design-tokens.json or component-specs.md
already on disk), print a one-paragraph analysis of what's strong
and what needs work, then ask via AskUserQuestion:
AskUserQuestion(
questions: [{
question: "How should I refine this design draft?",
header: "Draft plan",
multiSelect: false,
options: [
{
label: "Start refining from here (Recommended)",
description: "Use the existing draft as the base, ask clarifying questions only on the weak sections, and produce finalized artifacts."
},
{
label: "Start over with fresh Phase 1",
description: "Discard the draft and run the full 6-question intent-capture flow plus a fresh /impeccable init. Use when the draft is too far from what you actually want."
},
{
label: "Show me the analysis in detail first",
description: "Print a section-by-section breakdown of strengths and gaps. You'll decide what to do next after reviewing it."
}
]
}]
)
Phase 1 Step 3.5: Prototype declaration (per
standards/process/prototype-as-intent.md; ADR-001 explicit
declaration, not heuristic detection).
A prototype or mock (a clickable HTML/React/Figma-export demo) is a
legitimate design input — but the pbj P0 class proves it must be
read for intent, never carried forward as canonical
implementation (its hand-coded classes, ad-hoc tokens, DOM, fetch
calls, and scaffolding data must not become the design's source of
truth). The full discipline lives in
standards/process/prototype-as-intent.md (cited by path, NOT
duplicated here — that standard is the single source of truth; this
skill is thin orchestration per
standards/architecture/abstraction-rules.md).
Detection is explicit declaration (ADR-001) — /design never
heuristically scans the repo for prototype-shaped files. Resolve the
declaration as follows:
-
If the operator passed --prototype <path> (and optionally
--component-lib <path>) on the /design invocation, treat those
as the declared values and SKIP the Pattern B question for whatever
was supplied. Ask Pattern B only for any missing half (e.g.,
--prototype given but --component-lib omitted).
-
Otherwise ask the declaration question, ONE AT A TIME via Pattern B
(per standards/process/interactive-user-input.md):
---
**▶ Your answer needed:** Is a prototype or mock an input to this design? If so, where is it (a path or URL)? A prototype is read for INTENT only — its classes, tokens, DOM, and fetch wiring never become canonical. Answer "no" if there is no prototype.
Wait for the answer. If the answer is "no" / "none" / absent, record
declared: false and skip every prototype-hygiene rule below
(forward-only — the rest of /design behaves exactly as it does
with no prototype). Do not ask the component-lib follow-up.
If the operator names a prototype path, ask the component-library
follow-up via Pattern B:
---
**▶ Your answer needed:** Which real component library / design system should supply the canonical tokens (a path)? Tokens come from this library, never from the prototype's own token names. Answer "none" if the project has no component library yet — I'll record that as a gap.
Path-sanitization contract (capture-site). Every operator-supplied
path (--prototype, --component-lib, or the Pattern B answers) is
sanitized at the capture site BEFORE any write: strip every
control-character codepoint (regex [\x00-\x1f\x7f]) and cap the
length at 512 characters (truncate excess). The sanitized value is
recorded verbatim into state.yaml — it is never
shell-interpolated, never auto-fetched, and never read as code (the
prototype is data, per the design.md Security Considerations and
ADR-003 declare-not-execute). This mirrors the Phase 1 Question 6
"Other" sanitization contract above (F006 Security item 2).
Record the declaration into state.yaml.design_phase.prototype
(merge-preserve per F006 BR-008 — the actual write happens in Phase 5
Step 5 alongside the rest of the design_phase block; capture the
values in skill-local state now). The sub-block schema:
design_phase:
prototype:
declared: true
path: "<sanitized prototype path>"
component_lib_path: "<sanitized component-lib path, or null + a recorded gap when "none">"
A declared: false block records only declared: false (omit path
and component_lib_path, or set them null) and is the forward-only
no-op state. When the operator declares a prototype but answers "none"
for the component library, set component_lib_path: null and record a
gray-area / DoR gap (the standard requires a real token source; the
gap is surfaced, not silently swallowed — ADR-002 component-lib-first).
Phase 1 Step 4: Write the design/start git tag.
Once the feature directory is located or allocated (see Phase 2
Step 0 below for allocator details when /design is the first
phase to run), write the canonical design-start tag:
python3 ~/.claude/scripts/git_tags.py write-tag "etc/feature/<feature_id>/design/start"
Treat exit codes 0 (created) and 1 (degrade — non-git directory or
no HEAD) as both acceptable; only exit code 2 (hard error) is
fatal. The tag is what /metrics reads to compute design-phase
turnaround. The matching etc/feature/<feature_id>/design/done tag
is written in Phase 5 Step 8.
Phase 2: Research
Before writing any design content, gather information from three
sources. Present a research summary to the user before proceeding
to gray-area resolution and post-processing.
Phase 2 Step 0: Allocator invocation (per BR-001 and
ADR-F011-001).
/design is the first phase to touch features/ when invoked
ahead of /spec. Unlike /architect Phase 2 Step 0 (which only
re-confirms an existing allocation), /design Phase 2 Step 0
ALLOCATES the feature directory:
python3 ~/.claude/scripts/feature_id.py allocate-next .etc_sdlc/features "<slug>"
The <slug> is derived from the user's one-liner via the canonical
kebab-case helper (scripts/feature_id.py::slugify). The allocator
is POSIX-atomic and reserves a fresh F<NNN> across concurrent
runs (the F001 BR-003 atomic-allocator contract). The returned
path is the canonical <feature_path> for the rest of the skill:
<feature_id> — e.g., F042.
<feature_path> — e.g., .etc_sdlc/features/active/F042-redesign-dashboard.
When /design is invoked on an EXISTING feature (e.g., via
/design F042 or /design --retrofit <path>), Phase 2 Step 0
skips allocation and inherits feature_id + feature_path from
the existing state.yaml. The resolution order matches
/architect Phase 1 Step 0:
- If the user provided an explicit path argument, use it directly.
- Else if the user provided
F<NNN>, resolve via
python3 ~/.claude/scripts/feature_id.py resolve <feature_id>
and use the printed path.
- Else, allocate fresh as above.
Reference <feature_id> and <feature_path> throughout the rest
of the skill. Phase 2.5 writes
<feature_path>/gray-areas-design.md. Phase 5 writes
<feature_path>/design-tokens.json,
<feature_path>/component-specs.md,
<feature_path>/research/design-codebase.md, and updates to
<feature_path>/state.yaml and
<feature_path>/value-hypothesis.yaml.
Dispatch these research tasks in parallel:
-
Codebase Exploration — Read the existing codebase to
understand design context. The design-specific exploration goes
deeper than /spec's codebase pass on the visual-identity axis:
- What design-system files exist (e.g.,
design-system/,
tokens.json, figma-export.json, Storybook config)?
- What component inventory exists (grep for
.tsx/.vue/.svelte
component files; sample the named components)?
- What color, typography, spacing, motion, and breakpoint
conventions are already established? Cross-reference impeccable's
7 reference domains (typography, color/contrast, spatial,
motion, interaction, responsive, UX writing) against the
codebase to surface drift.
- Are there prior ADRs under
docs/adrs/ that bear on this
design (e.g., a prior design-system ADR, an accessibility ADR)?
Read every relevant ADR; capture by number.
- Does
INVARIANTS.md exist? If so, what cross-context
contracts constrain this design (e.g., "all forms must
validate inline")?
-
Web Research — Search for established design patterns,
documented accessibility standards, and applicable design-system
conventions for this design type:
- WCAG conformance guides for the chosen floor (A, AA, AAA).
- Motion-reduction guidance (
prefers-reduced-motion MDN,
WAI-ARIA Authoring Practices).
- Responsive breakpoint conventions (the dominant breakpoint
systems — Tailwind, Bootstrap, Material — and the case for
project-specific breakpoints).
- Component patterns for the user-flow primitives the user
named in Phase 1 Q3 (forms, wizards, dashboards, empty states).
- Impeccable's own reference domains (see
~/.claude/skills/impeccable/
if installed) — citations from there should match the
anti-pattern enforcement impeccable will apply.
-
Antipatterns Check — Read .etc_sdlc/antipatterns.md if it
exists:
- Are any past design antipatterns relevant to this design?
- Cross-reference impeccable's 27 anti-pattern rules with the
project's antipatterns file to surface overlap (e.g., a project
antipattern about "purple-to-blue gradient" matches impeccable's
rule of the same name).
- Incorporate prevention rules from relevant AP entries into the
gray-areas-design.md Trade-offs section.
-
Research-Fill of Identified Gaps (the fillable test) —
after the three research tasks above complete, walk the list of
design questions identified so far (the six Phase 1 answers
plus any sub-questions surfaced during codebase exploration)
and, for each question that is missing an answer, apply the
fillable test:
Can I ground my answer in citable evidence, or do I need to
ask?
A gap is research-fillable if at least one of the following
yields a citable answer:
- A codebase grep finds a canonical design pattern (e.g.,
"every other view uses the existing
<Empty> component").
- An existing ADR under
docs/adrs/ cites the answer.
- An existing doc cites the answer (
DOMAIN.md,
INVARIANTS.md, a tier-1 standard, an adjacent design).
- Web research finds a universally-accepted best practice with
no competing alternatives in this codebase's context (e.g.,
prefers-reduced-motion handling is non-negotiable for
WCAG AA).
- Impeccable's reference domains supply a deterministic answer
for the question.
A gap is unfillable if any of the following hold:
- Multiple plausible design answers exist and the codebase does
not pick between them.
- The answer depends on brand intent or product scope — those
are PRODUCT.md territory; if PRODUCT.md doesn't answer them,
re-dispatch
/impeccable init (the wrap surface) rather
than guessing.
- The answer is a policy decision (e.g., "AA or AAA?") that
requires the user.
- The answer requires data we do not have (user-research
findings, accessibility audit results, brand-guidelines
contract).
For each research-fillable gap, record a gray-area entry with
decided_by: research plus a citation (file path, ADR number,
URL, or impeccable reference domain) and a one-line resolution
rationale. These entries are written to
<feature_path>/gray-areas-design.md during Phase 2.5 using
the extended schema. For each unfillable gap, record a
gray-area entry with decided_by: user and leave it for Phase
2.5 to surface to the user (or for Phase 2.75 to fold into a
rejection).
The user sees every research fill during Phase 3 section review
and may override any of them through the normal section-refinement
flow.
Phase 2 Step 1: Dispatch /impeccable init (if not already
dispatched in Phase 1 Step 1).
If Phase 1 Step 1 dispatched /impeccable init (both PRODUCT.md +
DESIGN.md absent), this step is a no-op — impeccable has already
written the canonical files at repo root. If Phase 1 Step 1 took
the accept-or-refine path (both files present), this step is also
a no-op unless the user picked "refine" or "start over".
If the file-watch contract is active (the operator ran /design --sync or the JSON file at the default path
~/.impeccable/last-session.json OR
<feature_path>/design-iteration.json exists), read the file and
apply the decisions to in-session state. See "File-Watch Contract"
below for the schema and the --sync-from flag.
Phase 2 Step 2: Read PRODUCT.md + DESIGN.md from repo root.
Read the canonical impeccable output files in full. These are the
authoritative source for the design conversation; /design's
post-processing populates state.yaml.design_phase metrics from
their content (per ADR-F011-005 partial-wrap discipline).
Present the research summary to the user (as prose — this is
status output, not a question), followed by an AskUserQuestion
prompt for the next action:
Research Summary:
Codebase:
- [design-system files inventoried, component count, prior design ADRs read]
Design Patterns (web):
- [WCAG floor citations, motion-reduction guidance, breakpoint conventions]
Impeccable Reference Domains:
- [matched domains from impeccable's 7; flagged drift]
Antipatterns:
- [relevant AP entries, or "No antipatterns file found"]
Standards Cross-Reference:
- abstraction-rules.md: [any drift detected, or "consistent"]
- layer-boundaries.md: [any drift detected, or "consistent"]
- interactive-user-input.md: [cited from Phase 1/2.5/3 question rendering]
Then ask:
AskUserQuestion(
questions: [{
question: "Design research looks sufficient?",
header: "Research",
multiSelect: false,
options: [
{
label: "Yes, proceed to gray-area resolution (Recommended)",
description: "Research covers the codebase, prior ADRs, impeccable's reference domains, design-pattern web research, and the antipatterns file. Move to Phase 2.5."
},
{
label: "Research more",
description: "Name a specific topic to dig deeper on. I'll research and re-present the summary before proceeding."
},
{
label: "Skip research for this one",
description: "Small or self-contained design passes may not need additional research. I'll note the skip and proceed — but downstream phases may push back later if context is thin."
}
]
}]
)
If the user picks "Research more", ask via Pattern B for the
specific topic, do the research, and re-invoke the
AskUserQuestion above.
Save the codebase findings to
<feature_path>/research/design-codebase.md in markdown form.
Distinguish design-codebase findings from /spec's
research/codebase.md and /architect's
research/architect-codebase.md so all three are inspectable at
handoff time.
Phase 2.5: Gray Area Resolution
Before populating the etc-native artifacts, systematically identify
design decisions impeccable does not natively cover — WCAG
floor selection, motion-reduction respect, responsive breakpoint
targets, user-flow state machines (error / empty / loading
states), trade-offs where the research found multiple valid
options.
Print a numbered summary of the gray areas you found as status
output:
I found N design gray areas that need your input before I write the etc-native artifacts:
1. **[Decision topic]** — research found: [trade-off summary]
2. **[Decision topic]** — research found: [trade-off summary]
3. ...
Then resolve them ONE AT A TIME using AskUserQuestion (Pattern A
— multi-choice is a perfect fit for gray areas because each has
2-4 enumerable options from the research). Do NOT batch all gray
areas into a single question — resolving them sequentially lets
the user build confidence and lets earlier decisions constrain
later ones.
For each gray area:
AskUserQuestion(
questions: [{
question: "<decision topic>: <one-sentence framing>?",
header: "<≤12-char chip label>",
multiSelect: false,
options: [
{
label: "<Option A> (Recommended if you have a research-backed default)",
description: "<one-sentence trade-off for this option, from research>"
},
{
label: "<Option B>",
description: "<one-sentence trade-off>"
},
{
label: "<Option C — if it exists>",
description: "<one-sentence trade-off>"
}
]
}]
)
If the user picks "Other" (AskUserQuestion's automatic escape
hatch) to provide a custom answer, record it verbatim and
continue.
Wait for ALL gray areas to be resolved before proceeding.
Save resolutions to <feature_path>/gray-areas-design.md (NOT
gray-areas.md — that filename is owned by /spec; NOT
gray-areas-architect.md — that filename is owned by
/architect). The file uses the extended schema identical to
/spec's gray-areas.md and /architect's gray-areas-architect.md:
# Gray Areas — Design Phase
## GA-001: [Topic]
- **Options:** [A] vs [B]
- **Decision:** [chosen option]
- **Rationale:** [why]
- **Decided by:** research | user | rejected
- **Citation:** [file path, ADR number, URL, impeccable reference domain, or adjacent design] # required when Decided by = research
- **Resolution rationale:** [one-line evidence summary] # required when Decided by = research
The Decided by field is a controlled enum taking one of
research, user, or rejected. Research fills (recorded during
Phase 2) use research and MUST include the Citation and
Resolution rationale fields. User-resolved gaps (recorded during
Phase 2.5) use user. Gaps that triggered rejection (recorded
during Phase 2.75) use rejected and are copied into
rejected-design.md alongside the gray-area file.
The etc-specific gray-area topics that consistently surface for
design phases (per spec BR-004):
- WCAG conformance floor (A vs AA vs AAA — impeccable does not pick
this for you).
- Motion-reduction respect (mandatory honoring of
prefers-reduced-motion vs optional vs none).
- Responsive breakpoint targets (named breakpoint system; smallest
supported viewport width).
- User-flow state machines (entry → success → error → empty →
loading state coverage).
- Error / empty / loading state coverage for every primary surface
named in PRODUCT.md.
These resolutions will be:
- Captured into
component-specs.md as per-component constraints.
- Folded into the
design-tokens.json tokens where they affect
visual output (e.g., motion-reduction → --motion-duration: 0ms
override under prefers-reduced-motion).
- Referenced by
/spec Phase 2 codebase research when authoring
Acceptance Criteria (per BR-007).
- Referenced by
/build Step 6 dispatch context when design-tokens.json
- component-specs.md are present (mirrors F006 BR-005's design.md
inclusion pattern).
If no gray areas are found, state explicitly: "No design gray
areas identified — impeccable's reference domains and the research
findings are unambiguous." and proceed.
Phase 2.75: Threshold Check and Classification
Before entering Phase 3, classify the design into one of three
states:
- Well-designed — every design question has a concrete answer
from PRODUCT.md + DESIGN.md + impeccable's reference domains. No
user intervention is needed beyond the existing section
approvals.
- Research-fillable (research-assisted) — some questions were
missing, but codebase evidence, prior ADRs, impeccable
reference domains, or web research resolved them during Phase
2. Proceed to Phase 3; the fills surface during section review.
- Rejected — too many design questions are missing, or too
many gaps are unfillable, to proceed without human refinement
of PRODUCT.md / DESIGN.md.
Count the following from the Phase 2 research-fill pass and the
Phase 2.5 gray-area resolution:
total_questions — the number of design questions identified
during Phase 1 and Phase 2 (the six Phase 1 answers plus any
sub-questions raised during codebase exploration or impeccable's
init output).
filled_by_research — gaps closed with decided_by: research.
unfillable_gaps — gaps marked decided_by: user that are
still pending (i.e., surfaced to the user but not yet resolved).
Let fill_ratio = (filled_by_research + unfillable_gaps) / total_questions.
Apply the classification rules:
- If
total_questions == 0: reject with reason "no design
questions identified; PRODUCT.md + DESIGN.md do not imply enough
design surface to capture against." (avoids divide-by-zero and
catches intent-only inputs that should not have triggered
/design.)
- Else if
unfillable_gaps == 0 and fill_ratio <= FILL_RATIO_RESEARCH_ASSIST_MAX: well-designed /
research-assisted. Skip the user gray-area session and proceed
directly to Phase 3.
- Else if
fill_ratio <= FILL_RATIO_REJECT_MIN and unfillable_gaps <= UNFILLABLE_GAP_REJECT_CAP: research-assisted with user
gray areas. Run the existing Phase 2.5 user-facing gray-area
flow, but only on the unfillable gaps. The research fills
are already recorded and are not re-asked.
- Else (
fill_ratio > FILL_RATIO_REJECT_MIN OR unfillable_gaps > UNFILLABLE_GAP_REJECT_CAP): rejected. Transition to the
Rejection Flow below instead of Phase 3. Do NOT write
design-tokens.json or component-specs.md.
Note: the numeric literals 0.20, 0.50, and 3 never appear
inline in the workflow prose above — only the constant names do.
Tuning the thresholds is a one-line diff at the top of this skill
file.
Rejection Flow
Triggered only when Phase 2.75 classifies the design as rejected.
-
Do NOT write design-tokens.json. Do NOT write
component-specs.md. Under no circumstances does the
rejection path produce design artifacts.
-
Write <feature_path>/rejected-design.md (analogous to
/spec's rejected.md and /architect's
rejected-architect.md, but file-scoped to the design phase
so the three phases' rejections don't collide):
# Design Rejected: {feature slug}
**Reason:** {which threshold was exceeded, by the numbers}
- total_questions: {N}
- filled_by_research: {M}
- unfillable_gaps: {K}
- fill_ratio: {fill_ratio:.2f}
- Threshold exceeded: {FILL_RATIO_REJECT_MIN | UNFILLABLE_GAP_REJECT_CAP | zero-questions}
## Unanswered design questions (answer these before resubmitting)
1. {specific question derived from unfillable gap #1}
2. {specific question derived from unfillable gap #2}
...
## Research fills already performed (preserved so you don't redo work)
- {gap} → {resolution} — source: {citation}
- ...
## Next action
Refine PRODUCT.md + DESIGN.md (re-run `/impeccable init`) or
answer the questions above, then re-run:
/design {feature_id_or_path}
-
Mirror any decided_by: research fills into the rejection
report so the human does not have to redo research when
resubmitting.
-
Do NOT relocate the feature directory. Unlike /spec's
rejection flow (which git mv's the entire feature directory
to .etc_sdlc/rejections/), /design rejection only writes
rejected-design.md next to the allocated directory. The
directory remains valid; subsequent /spec and /architect
invocations can still proceed (the soft-coupling pattern from
F006 GA-008 applies — those phases will warn but not block).
-
Surface the rejection to the user using Pattern B (the visual
marker), because the message is a status/error announcement,
not a question. Name the rejected file path and the next
actions:
---
**▶ Action required:** Design rejected. Two paths forward:
1. Refine PRODUCT.md + DESIGN.md (re-run `/impeccable init`)
or answer the questions in
`<feature_path>/rejected-design.md` and re-run
`/design <feature_id>`.
2. Proceed without a design context by running `/spec
<one-liner>` directly. /spec's Phase 2 will skip the
design-tokens.json / component-specs.md lookup and the
feature will not gain tier-0 promotion.
-
Exit the skill. Do not proceed to Phase 3, Phase 4, or Phase 5.
Phase 3: Iterative Spec Writing
Write the etc-native design artifacts section by section. For EACH
artifact:
- Print the drafted artifact (or section thereof) as status
output (prose or fenced code block, not a question). Include
the full content so the user can read exactly what will land
on disk.
- Prompt for approval via
AskUserQuestion using the
standard section-approval template below. Pattern A fits
because the user's response is always one of three enumerable
actions (accept / refine / research more).
Write artifacts in this order:
-
design-tokens.json (Tokens preview) — render the candidate
token set derived from PRODUCT.md + DESIGN.md (colors,
typography, spacing, motion, breakpoints). Format mirrors
impeccable's token vocabulary. The user reviews the preview
before Phase 5 writes the JSON file.
-
component-specs.md (Component-by-component) — for each
primary component named in PRODUCT.md or implied by the
user-flow shape (Phase 1 Q3), render a per-component spec:
variants, states (default / hover / focus / disabled / error /
empty / loading), accessibility attributes (ARIA roles,
keyboard interactions, focus trap rules), motion behavior
(respect prefers-reduced-motion). The user reviews each
component spec before Phase 5 writes the combined file.
-
gray-areas-design.md (preview) — print the assembled
gray-areas-design.md content from Phase 2.5 for a final
review pass before Phase 5 writes it.
Each artifact's content discipline:
-
design-tokens.json — strict JSON. Follow impeccable's token
taxonomy (color, typography, spacing, motion, breakpoints). The
feature_id + source fields are populated by /design at Phase 5
write time:
{
"feature_id": "F<NNN>",
"source": "impeccable",
"tokens": {
"color": { "...": "..." },
"typography": { "...": "..." },
"spacing": { "...": "..." },
"motion": { "...": "..." },
"breakpoints": { "...": "..." }
}
}
Cross-reference standards/architecture/abstraction-rules.md —
do NOT invent new token categories impeccable does not define
(twice-before-abstracting). Cite by path; do not duplicate
rules.
-
component-specs.md — markdown. One H2 per component, with
subsections for Variants, States, Accessibility, Motion, and
Anti-references (impeccable rules this component avoids). Mirrors
the output format of the deprecated agents/ui-designer.md
adapted for impeccable's token vocabulary (per BR-007).
-
gray-areas-design.md — extended schema per Phase 2.5.
For each artifact, after printing the draft, invoke this template
(substituting the artifact name into header, question, and
the option descriptions):
AskUserQuestion(
questions: [{
question: "{Artifact name} — does this capture what you want?",
header: "{Artifact name}",
multiSelect: false,
options: [
{
label: "Accept and proceed (Recommended)",
description: "The {artifact name} looks right. Save this artifact and move to the next."
},
{
label: "Refine — I have changes",
description: "I'll ask for specific changes via Pattern B and revise this artifact before moving on."
},
{
label: "Research more first",
description: "This artifact needs more investigation. I'll do the research and re-draft before asking again."
}
]
}]
)
If the user picks "Refine", ask for the specifics via Pattern B:
---
**▶ Your answer needed:** What would you change about the {artifact name}? Name specific additions, removals, or rewordings.
Then revise and re-invoke the approval template. Repeat until
accepted.
If the user picks "Research more", ask via Pattern B what to
research, do the research, and re-draft + re-ask for approval.
Save in-progress work to
<feature_path>/.draft-design-tokens.json and
<feature_path>/.draft-component-specs.md after each accepted
artifact, so the user can resume in a new session. The files are
in the feature directory because design state is feature-scoped.
Phase 4: Validation
After all artifacts are drafted and approved, run the
design-specific Definition of Ready checklist. This is the same
shape as /spec's and /architect's DoR but with design-tier
items:
If all items pass: Tell the user the design is ready and
proceed to output.
If any items fail: Point out the specific gaps and ask the
user to resolve them before finalizing:
Definition of Ready check found gaps:
- [ ] design-tokens.json validates
Gap: the `motion` category is empty and the project has no
existing motion tokens to inherit from. Either populate at least
duration + easing values, or explicitly mark the category
"inherited" with a citation to the source design system.
- [ ] component-specs.md covers every primary component
Gap: PRODUCT.md names "OnboardingWizard" but no spec exists for
it. Add a Variants / States / Accessibility / Motion /
Anti-references block before finalizing.
Let's resolve these before finalizing.
Iterate until all items pass.
Phase 5: Output
Once the Definition of Ready passes, execute these steps in order.
The discipline is artifact-first: design-tokens.json and
component-specs.md are NOT written until every prerequisite
(gray-areas-design.md, research file, state.yaml update prepared,
value-hypothesis.yaml update prepared) is in place.
The feature directory was already located or allocated in Phase 2
Step 0. <feature_id> and <feature_path> are in skill-local
state. Phase 5 does NOT re-allocate; it only writes inside the
existing <feature_path>.
-
Write <feature_path>/research/design-codebase.md capturing
the Phase 2 codebase findings (design-system files inventoried,
component inventory sampled, prior design ADRs read, INVARIANTS.md
excerpts, impeccable reference-domain cross-reference results,
antipattern matches). This file is distinct from /spec's
research/codebase.md and /architect's
research/architect-codebase.md; all three coexist under the
same feature's research/ subdirectory.
-
Write <feature_path>/gray-areas-design.md if not already
written by Phase 2.5 (Phase 2.5 should have written it; this
step is a safety net). The file uses the extended schema
documented in Phase 2.5.
-
Write <feature_path>/design-tokens.json with the
reviewed-and-approved token set from Phase 3 Artifact 1.
Construct atomically (temp file + fsync + rename via
pathlib.Path.replace()) per F006 BR-008 + the Security
posture inherited from standards/architecture/layer-boundaries.md.
The JSON schema:
{
"feature_id": "F<NNN>",
"source": "impeccable",
"tokens": {
"color": { "...": "..." },
"typography": { "...": "..." },
"spacing": { "...": "..." },
"motion": { "...": "..." },
"breakpoints": { "...": "..." }
}
}
/spec Phase 2 codebase research detects this file at
<feature_path>/design-tokens.json and incorporates the tokens
into the spec.md Acceptance Criteria section (e.g., "AC-3
success criterion references token --color-text-primary from
design-tokens.json"). /build Step 6 dispatch context includes
design-tokens.json alongside spec.md (per BR-007 + F006 BR-005
pattern).
Layer-3 conformance (advisory, optional). This file is
Layer 2 (machine-readable tokens). The operator MAY now run the
Layer-3 conformance gate to check the project's existing code
actually uses these tokens instead of hardcoding design values:
python3 ~/.claude/scripts/design_token_gate.py scan \
--tokens <feature_path>/design-tokens.json --dir <project-src>
v1 is colors-only and advisory (exit 0 even with violations;
--strict opts into blocking). It is NOT part of /build's
blocking path. The full policy lives in
standards/process/design-token-conformance.md (cited, not
inlined). This step is optional — skip it if there is no existing
code to scan yet.
-
Write <feature_path>/component-specs.md with the
reviewed-and-approved component specs from Phase 3 Artifact 2.
Format mirrors the deprecated agents/ui-designer.md's output
format adapted for impeccable's token vocabulary (per BR-007).
4.4. Prototype-hygiene post-processing rules (apply ONLY when
state.yaml.design_phase.prototype.declared == true). When
declared is false or absent, SKIP this entire step — the
token and component-spec writes above stand exactly as today
(forward-only). The four rules below enforce
standards/process/prototype-as-intent.md against the artifacts
from Steps 3-4; the standard is the single source of truth and is
cited by path, NOT duplicated here.
-
Intent-only extraction (per the standard; ADR-001 + ADR-003).
Read the declared prototype for intent only — which surfaces
exist, what each affords, the user-flow shape. Do NOT carry the
prototype's own CSS classes, ad-hoc token names, DOM structure,
or fetch/axios wiring into component-specs.md or
design-tokens.json as canonical. The prototype's auth/fetch
code is NEVER promoted as the design's canonical auth story —
the design declares intent ("this surface persists X"); the
build wires real auth at the real trust boundary (design.md
Security Considerations).
-
REQUIRED / ILLUSTRATIVE affordance annotation (ADR-002 /
AGA-003). Annotate every affordance in component-specs.md
with a trailing REQUIRED or ILLUSTRATIVE tag, co-located
with the affordance line or row (grep-able). REQUIRED = an
affordance the design genuinely demands; ILLUSTRATIVE = a
detail the prototype happened to show but that is not binding.
This is the convention named in design.md API Contracts; the
semantics of the two tags live in the standard.
-
Real-token sourcing (ADR-002 component-lib-first; Edge
Case 5 provenance-over-coincidence). Source the
design-tokens.json token values from the declared
component_lib_path — never from the prototype's own token
names. If component_lib_path is null (the operator answered
"none" in Phase 1 Step 3.5), do NOT invent tokens from the
prototype; record the missing-token-source gap (carried from
Phase 1 Step 3.5) and surface it at the Phase 4 Definition of
Ready. Provenance over coincidence: a token in
design-tokens.json must trace to the real library, not to a
value the prototype happened to hardcode.
-
Data-fidelity + clean-template declaration (ADR-003
declare-not-execute; the Gap A consumer). Declare — as prose
— the data-fidelity and clean-template requirement into the
design output (component-specs.md and/or DESIGN.md), using the
canonical sentence from design.md API Contracts: "Data fidelity:
seed/fixture data MUST reproduce every value the prototype
displays; the ingestible template carries no scaffolding rows."
/design only declares this requirement; the build-time
runtime gate (Gap A) consumes and enforces it. This is the
architectural defense against the pbj P0 (scaffolding rows
ingested as real records).
These rules add to component-specs.md and design-tokens.json;
they never mutate impeccable's PRODUCT.md / DESIGN.md (read-only
post-process per ADR-F011-005) and never duplicate the standard's
rules into this skill (F002 standards-doc citation pattern).
4.5. Compose the Google-spec DESIGN.md (F018). After impeccable's
freeform PRODUCT.md + DESIGN.md exist at the repo root, dispatch the
compose script to produce a canonical Google-spec DESIGN.md:
python3 ~/.claude/scripts/design_md_compose.py \
DESIGN.md \
PRODUCT.md \
--out DESIGN.md
The compose:
- Extracts
name + description from PRODUCT.md's first heading and
intro paragraph.
- Extracts hex color values from impeccable's freeform DESIGN.md (with
role-mapping heuristics for
primary, accent, background,
text); leftover hex values get sequential colorN names.
- Extracts typography font-family values when impeccable mentions a
font name near
body|copy|paragraph[s]? or heading[s]?|display|title
prose tokens.
- Emits canonical Markdown sections in Google's documented order
(Overview, Colors, Typography, Layout, Elevation & Depth, Shapes,
Components, Do's and Don'ts); skips sections with no content.
- Preserves the original impeccable DESIGN.md at
DESIGN-impeccable.md
(intermediate artifact; never overwritten).
- Invokes
npx @google/design.md lint DESIGN.md as a best-effort
validation step. Exit 2 on lint errors (operator runs /design --refresh after fixing); exit 0 on warnings or info-only findings;
exit 0 if npx is unavailable (skipped silently).
When @google/design.md is not installed (install.sh preflight INFO
surfaces this case), the compose runs without lint validation. The
version: "alpha" pin in the frontmatter aligns with Google's current
spec status; update via the operator-facing /design --refresh flow
when Google ships v1.0.
Operator-facing convenience modes:
/design --lint — re-run npx @google/design.md lint DESIGN.md and
surface findings without re-composing.
/design --export <format> — passthrough to
npx @google/design.md export --format <format> DESIGN.md for
tailwind, css-tailwind, json-tailwind, or dtcg.
/design --refresh — re-compose from DESIGN-impeccable.md +
PRODUCT.md (use after manual refinement of the impeccable
intermediate artifact).
/design --spec — print Google's format spec via
npx @google/design.md spec (useful as context for AI agents
consuming the design system).
-
Append design_phase block to state.yaml. Add or merge
into <feature_path>/state.yaml (merge-preserve per F006
BR-008 — read existing state.yaml, mutate only the
design_phase block, write back):
design_phase:
classification: well-designed | research-assisted | rejected
phase_2_75_metrics:
total_questions: <int>
filled_by_research: <int>
unfillable_gaps: <int>
fill_ratio: <float>
design_author_role: <SME | Engineer | PM | Designer | sanitized free-form>
impeccable_version_pinned: <detected impeccable version, or "unknown">
google_designmd_version_pinned: <semver or "alpha"> # F018
tier_0_promoted: <bool>
prototype: # Gap C — see Phase 1 Step 3.5
declared: <bool> # false → no hygiene applied (forward-only)
path: <sanitized prototype path, or null> # present only when declared: true
component_lib_path: <sanitized component-lib path, or null> # null + recorded gap when "none"
completed_at: <ISO-8601 UTC>
Use the merge-preserve pattern (F006 BR-008): if state.yaml
already has spec_phase, architect_phase, build, or other
top-level blocks, leave them untouched and add design_phase
alongside. Do not overwrite the file wholesale.
Populate the design_phase fields per ADR-F011-005
(partial-wrap post-processing):
classification — the Phase 2.75 verdict
(well-designed | research-assisted | rejected). The
enum value is load-bearing; do not rename.
phase_2_75_metrics — the four counters from Phase 2.75.
design_author_role — the Phase 1 Q6 sanitized answer.
impeccable_version_pinned — the detected impeccable
version for provenance only (e.g., "2.3.2"), or "unknown"
when the CLI does not report one. Recorded for the record, NOT
gated on — /design does not pin or compare any version
(the field name is retained for schema continuity).
tier_0_promoted — true when the feature has a
user-facing surface (≥1 AC classified user-facing per F001
BR-002 signal list when /design --retrofit runs against an
existing spec.md; OR ≥1 user-flow primitive named in
PRODUCT.md or Phase 1 Q3 when /design runs ahead of
/spec); else false. See "Conditional tier-0 promotion"
below for the hook contract.
prototype — the Gap C declaration captured in Phase 1
Step 3.5 (per standards/process/prototype-as-intent.md +
ADR-001). declared: false (the forward-only no-op) records
only the boolean; declared: true records the sanitized
path and component_lib_path (the latter null + a recorded
gap when the operator answered "none"). Merge-preserve like the
rest of the block; the values are recorded verbatim, never
shell-interpolated.
completed_at — ISO-8601 UTC timestamp of Phase 5
completion.
-
Append design_author_role to value-hypothesis.yaml. Add
the field at top level alongside any existing
spec_author_role, architect_author_role, author_role
(legacy), who, current_cost, predicted, etc. The schema
validator (scripts/value_hypothesis.py) accepts the multi-phase
author-role shape (F006 BR-007 extended; design_author_role is
the F011 addition).
Use the sanitized free-form value if the user chose "Other" in
Phase 1 Question 6 — the same 64-char cap and control-character
strip apply (F006 Security item 2).
-
Validate value-hypothesis.yaml via the CLI:
python3 ~/.claude/scripts/value_hypothesis.py validate <feature_path>/value-hypothesis.yaml
Exit code 0 means schema-valid. On non-zero exit, the stderr
names the missing or malformed field — fix the field via a
Pattern B prompt and retry the write + validate cycle. Do
not proceed to step 8 until this CLI exits 0.
-
Write the design/done git tag. Invoke the git_tags.py CLI
to lay down the canonical design-completion tag at the current
HEAD commit:
python3 ~/.claude/scripts/git_tags.py write-tag "etc/feature/<feature_id>/design/done"
The CLI degrades gracefully on non-git directories or repos
with no HEAD — it exits 1 with a stderr warning rather than
failing the whole design run. Treat exit codes 0 (created) and
1 (degrade) as both acceptable; only an exit code of 2 (hard
error) is fatal.
The matching etc/feature/<feature_id>/design/start tag was
written in Phase 1 Step 4; both tags together bound the
design-phase duration that /metrics reads.
-
Remove the in-progress drafts from
<feature_path>/.draft-design-tokens.json and
<feature_path>/.draft-component-specs.md (if either exists).
In-progress drafts are not artifacts of a completed design
pass.
-
Print the file-watch reminder (per Edge Case 6 in spec.md):
Reminder: If you iterated in the impeccable browser extension since
last sync, run `/design --sync` and re-invoke /design before /spec
runs. Decisions left in the file-watch JSON do not propagate
automatically.
-
Report the summary:
Feature directory: <feature_path>
design-tokens.json — colors, typography, spacing, motion, breakpoints
component-specs.md — per-component variants, states, accessibility
gray-areas-design.md — N resolved design decisions
research/design-codebase.md — Phase 2 codebase findings
state.yaml — design_phase block appended
value-hypothesis.yaml — design_author_role field appended
Repo root:
PRODUCT.md, DESIGN.md — owned by impeccable; verified well-formed
Tags written:
etc/feature/F<NNN>/design/start — laid down at Phase 1 Step 4
etc/feature/F<NNN>/design/done — laid down at Phase 5 Step 8
Definition of Ready: PASSED
- PRODUCT.md + DESIGN.md present and well-formed
- design-tokens.json validates with all 5 categories populated/inherited
- component-specs.md covers all primary components
- WCAG floor, motion-reduction, breakpoints, state machines documented
Conditional tier-0 promotion: {true | false}
- When true, hooks/tier-0-design-preflight.sh enforces PRODUCT.md +
DESIGN.md presence before Edit/Write under <feature_path>.
Ready for /spec:
/spec "<one-liner describing the user-facing feature>"
File-Watch Contract (per ADR-F011-002 + ADR-F011-004)
The impeccable browser extension produces designer-iteration
decisions during live design work (variant choices, token tweaks,
component refinements). /design ingests those decisions through a
file-watch contract — pull-triggered (NOT a continuous watcher
daemon per ADR-F011-002), with a minimal JSON schema (per
ADR-F011-004).
Transport: filesystem JSON file at one of two operator-selectable
paths:
~/.impeccable/last-session.json (cross-feature; designer
iterates against one project at a time; default for most setups).
<feature_path>/design-iteration.json (per-feature; multiple
concurrent designers possible).
Operators select the path via --sync-from <path> on /design --sync. Default resolution order: <feature_path>/design-iteration.json
then ~/.impeccable/last-session.json. /design reads at most one
of these paths per invocation.
Schema (minimal — per ADR-F011-004):
{
"session_id": "<impeccable session UUID>",
"decisions": [
{
"token_or_component": "<string identifier>",
"value": "<arbitrary JSON value>",
"decided_at": "<ISO-8601 timestamp>"
}
]
}
Triggers: /design reads the file at Phase 5 entry (before
writing design-tokens.json + component-specs.md) AND on the
operator command /design --sync (any time post-Phase-5). The
read is pull-triggered, NOT a continuous watcher — per
ADR-F011-002 the contract trades latency for cross-platform
simplicity and zero daemon footprint.
Validation:
- Malformed JSON → halt with Pattern B parse error naming the
parse failure location.
- Missing required fields (
session_id, decisions) → halt with
Pattern B field-name error.
- Valid schema → strip control characters from
token_or_component (regex [\x00-\x1f\x7f] per F006 Security
item 2 + F010 precedent), then apply decisions to in-session
state and re-present Phase 3 sections for re-approval.
Path-traversal guard. When the operator supplies --sync-from <path>, resolve to absolute path; whitelist verification (must be
under <feature_path> OR ~/.impeccable/); reject paths
containing .. (F010 _sanitize_path precedent).
Explicitly NOT supported (per GA-006):
- MCP server — would require upstream impeccable to build /
maintain an MCP server (no commitment from pbakaus); pull-triggered
filesystem wins on cross-platform simplicity.
- Polling REST endpoint — introduces port-conflict and firewall
surface for zero gain over filesystem.
- Manual sync — designer must remember to export; highest UX
friction. /design --sync is operator-driven but reads the file
the browser extension already writes.
- Continuous filesystem watcher (
watchdog library) — adds a
dependency without justification per
standards/architecture/abstraction-rules.md YAGNI rule.
Conditional Tier-0 Promotion (per ADR-F011-003)
When state.yaml.design_phase.tier_0_promoted == true, the hook
at hooks/tier-0-design-preflight.sh blocks Edit/Write operations
under the feature directory until BOTH PRODUCT.md AND
DESIGN.md exist at repo root. /design Phase 5 sets
tier_0_promoted: true automatically when the feature has a
user-facing surface (≥1 AC classified user-facing per F001 BR-002
signal list when /design --retrofit runs against an existing
spec.md; OR ≥1 user-flow primitive named in PRODUCT.md or Phase 1
Q3 when /design runs ahead of /spec).
Features without a user-facing surface (no design_phase block in
state.yaml, OR tier_0_promoted: false) skip the tier-0 check.
Always-tier-0 mode is NOT supported (per GA-005). The hook
must be conditional or it would over-apply to backend-only
features (billing infra, observability, governance) where
impeccable's anti-pattern rules don't apply.
The hook citation by path is hooks/tier-0-design-preflight.sh.
This skill body cites the hook by path (F002 standards-doc
citation pattern); the hook's PreToolUse decision matrix and exit
codes are documented in the hook script itself, NOT duplicated
here. Future PRD may consolidate hooks/tier-0-design-preflight.sh
with the (currently absent) general tier-0-preflight hook (per
GA-architect-4).
/design → /spec Handoff (per BR-007 + F006 BR-005)
/design writes two artifacts that /spec Phase 2 reads when
present:
<feature_path>/design-tokens.json — impeccable-style design
tokens (colors, typography, spacing, motion, breakpoints).
<feature_path>/component-specs.md — per-component specs with
variants, states, accessibility attributes, motion behavior,
anti-references.
/spec Phase 2 codebase research detects both files at the
<feature_path> (the path inherited from /design's state.yaml)
and incorporates them into the spec.md Acceptance Criteria
section. Example AC patterns:
- "AC-3: success criterion references token
--color-text-primary from design-tokens.json."
- "AC-5: OnboardingWizard component renders all five states
(entry / success / error / empty / loading) per
component-specs.md."
/build Step 6 dispatch context includes design-tokens.json +
component-specs.md alongside spec.md (and design.md when
/architect ran) — mirrors F006 BR-005's design.md inclusion
pattern. The handoff is file-presence based: /spec and /build
detect the files at the canonical paths and incorporate them; no
new IPC, no new manifest entry, no new schema gate.
When /design has NOT run on a feature (the strategy-side branch
or a backend-only feature), the two artifacts are absent and /spec
- /build proceed as today. /build Step 1c emits a soft warning if
user-facing-AC signals are present BUT
state.yaml.design_phase
is absent (mirrors F006 GA-008 for /architect).
Constraints
- NEVER start writing design artifacts before asking clarifying
questions OR dispatching
/impeccable init.
- NEVER skip the research phase — always research the codebase,
prior ADRs, impeccable's reference domains, and the web.
- ALWAYS dispatch
/impeccable init via the Skill tool (NOT
subprocess) when PRODUCT.md / DESIGN.md are absent (per
ADR-F011-001 + F006 BR-010 chain semantics for auth-context
preservation).
- ALWAYS verify impeccable is available (installed/invocable) BEFORE
dispatching init. If it is absent, halt with Pattern B and instruct
install via the canonical channel (
npx impeccable skills install,
or /plugin marketplace add pbakaus/impeccable for Claude Code). Do
NOT pin or compare any impeccable version.
- NEVER inject etc-side processing into impeccable's Socratic loop
(deep wrap rejected per ADR-F011-005). Read-only post-process
PRODUCT.md + DESIGN.md after impeccable's init completes.
- ALWAYS present each artifact for user approval before moving to
the next.
- ALWAYS validate against the design-specific Definition of Ready
before finalizing.
- ALWAYS save in-progress drafts to
<feature_path>/.draft-design-tokens.json and
<feature_path>/.draft-component-specs.md.
- ALWAYS write the final artifacts to
<feature_path>/design-tokens.json and
<feature_path>/component-specs.md (per BR-007).
- ALWAYS write
<feature_path>/gray-areas-design.md (or the
sentinel line "No design gray areas identified — impeccable's
reference domains and the research findings are unambiguous.").
- NEVER duplicate
standards/process/interactive-user-input.md's
Pattern A/B contracts into this skill — cite by path (F002
standards-doc citation pattern).
- NEVER duplicate impeccable's anti-pattern rules or reference
domains into this skill — those are impeccable's authoritative
surface (per ADR-F011-001).
- The prototype-as-intent discipline (Gap C) is detected by
explicit declaration only (Phase 1 Step 3.5;
--prototype /
--component-lib flags), NEVER by heuristic repo scanning (per
ADR-001). A declared: false (or absent) prototype block applies
ZERO hygiene — a no-prototype run behaves exactly as today
(forward-only).
- NEVER duplicate
standards/process/prototype-as-intent.md's rules
(intent-only extraction, REQUIRED/ILLUSTRATIVE annotation,
component-lib-first token sourcing, data-fidelity + clean-template)
into this skill — cite by path (F002 standards-doc citation
pattern); that standard is the single source of truth.
- Operator-supplied prototype/component-lib paths are sanitized at
the capture site (strip
[\x00-\x1f\x7f], length-cap), recorded
verbatim into state.yaml.design_phase.prototype, and NEVER
shell-interpolated or auto-fetched (per ADR-003 declare-not-execute
- design.md Security Considerations).
- The git tag pair
etc/feature/<feature_id>/design/start and
etc/feature/<feature_id>/design/done MUST both be written
(start at Phase 1 Step 4, done at Phase 5 Step 8). /metrics
relies on the pair.
- The file-watch contract is pull-triggered, NOT a continuous
watcher (per ADR-F011-002). Operators run
/design --sync
explicitly; /design does not poll.
- The file-watch JSON schema is minimal (per ADR-F011-004):
{ session_id, decisions[] }. Do NOT couple to impeccable's
internal decision-history storage.
tier_0_promoted is conditional (per ADR-F011-003 + GA-005).
Always-tier-0 is NOT supported.
- The
hooks/tier-0-design-preflight.sh hook is cited by path;
this skill does NOT import from hooks/* (per
standards/architecture/layer-boundaries.md).
- If the user says "research more about X" at any point, honor
the request before continuing.
- AP entries from
.etc_sdlc/antipatterns.md are incorporated
when relevant — never ignored.
Post-Completion Guidance
After the design is finalized and written, print the status
summary as prose, then prompt the user via AskUserQuestion:
This design is solid and meets all design Definition of Ready criteria.
Feature directory: <feature_path>
Components specced: N
Tokens declared: K
Gray areas resolved: G
Tier-0 promoted: {true | false}
impeccable version pinned: <semver>
Then ask:
AskUserQuestion(
questions: [{
question: "Design complete. What's next?",
header: "Next step",
multiSelect: false,
options: [
{
label: "Kick off /spec now (Recommended)",
description: "Hand off to /spec, which inherits feature_id from state.yaml and reads design-tokens.json + component-specs.md when authoring Acceptance Criteria. /spec runs the standard 5-phase Socratic loop scoped to this feature."
},
{
label: "Iterate in the impeccable browser extension first",
description: "Open impeccable's browser extension and refine designer decisions. When done, run /design --sync to import the file-watch JSON deltas, then re-invoke /design before /spec."
},
{
label: "Stop here — I'll run /spec later",
description: "Leave the design artifacts in <feature_path>/ and return to them when ready. State is safe on disk; subsequent phases inherit feature_id from state.yaml."
}
]
}]
)
Always present /spec as the recommended default. Wait for the
user's selection before executing anything.
Definition of Done
/design is done for a given invocation when ALL of the following
observable artifacts exist and pass. The exact set depends on the
Phase 2.75 classification, so the checklist branches: items 1-3
always apply, items 4-12 apply to the well-designed and
research-assisted paths, and item 13 applies to the rejected path
(in which case items 4-12 are explicitly N/A, not skipped).
<feature_path>/ exists as the feature directory (allocated
by Phase 2 Step 0 OR inherited from a prior /spec /architect
invocation).
<feature_path>/state.yaml exists and contains a
design_phase block recording the Phase 2.75 classification in
the design_phase.classification field, using exactly one of
the controlled enum values well-designed, research-assisted,
or rejected. The schema is load-bearing for /spec Phase 2
and /build Step 1c; do not rename fields or values. The
design_phase block coexists with any existing spec_phase or
architect_phase block (F006 BR-008 merge-preserve). The
design_phase block carries a prototype sub-block recording the
Phase 1 Step 3.5 declaration (declared boolean; path +
component_lib_path when declared: true, sanitized + verbatim).
When declared: false (or no prototype was declared), no
prototype-hygiene rules were applied and the artifacts match a
no-prototype run (forward-only).
<feature_path>/gray-areas-design.md exists. If no gray areas
were found, the file contains the literal sentinel line "No
design gray areas identified — impeccable's reference domains
and the research findings are unambiguous." If gray areas
exist, every entry uses the extended schema (Decided by enum
= research | user | rejected, with Citation and
Resolution rationale required for research entries).
PRODUCT.md and DESIGN.md exist at repo root (owned by
impeccable; verified well-formed by /design's post-process
per ADR-F011-005). Exists ONLY on the well-designed and
research-assisted paths.
<feature_path>/design-tokens.json exists and validates as
strict JSON with the five top-level token categories. Exists
ONLY on the well-designed and research-assisted paths.
<feature_path>/component-specs.md exists and covers every
primary component named in PRODUCT.md or implied by the
user-flow shape with Variants / States / Accessibility / Motion
/ Anti-references subsections. Exists ONLY on the well-designed
and research-assisted paths.
<feature_path>/research/design-codebase.md exists capturing
Phase 2 codebase findings. An empty file is NOT sufficient —
the design-system inventory, component inventory, prior-ADR
read, and impeccable reference-domain cross-reference results
are the minimum required content.
<feature_path>/value-hypothesis.yaml contains a
design_author_role field whose value is the sanitized Phase 1
Question 6 answer. The schema validator
(scripts/value_hypothesis.py) exits 0 against the file. Any
existing spec_author_role, architect_author_role, or legacy
author_role field is preserved untouched.
- The
etc/feature/<feature_id>/design/start tag exists at the
commit where Phase 1 began (written by Phase 1 Step 4).
- The
etc/feature/<feature_id>/design/done tag exists at the
commit where Phase 5 closed (written by Phase 5 Step 8). Both
tags together bound the design-phase duration.
<feature_path>/.draft-design-tokens.json and
<feature_path>/.draft-component-specs.md have been removed
(if they existed during the session). In-progress drafts are
not artifacts of a completed design pass.
- The Phase 5 output summary and the Post-Completion Guidance
AskUserQuestion have been rendered to the user. Applies to
all non-rejected paths.
- REJECTED PATH ONLY:
<feature_path>/rejected-design.md
exists with the layout defined in the Rejection Flow
(Reason, threshold figures, unanswered questions, preserved
research fills, next actions). design-tokens.json and
component-specs.md MUST NOT exist alongside
rejected-design.md — the three files are mutually exclusive
at the design layer, and that exclusivity is how /spec Phase
2 distinguishes a feature with a rejected design from one with
a passing design.
If any applicable item is not satisfied, /design is NOT done,
regardless of how many phases reported internal success. Do not
report "Design complete" on the non-rejected paths unless every
item 1-12 holds, and do not report "Design rejected" on the