feat: add /gsd:ui-phase + /gsd:ui-review design contract and visual audit layer (closes #986)

Add pre-planning design contract generation and post-execution visual audit
for frontend phases. Closes the gap where execute-phase runs without a visual
contract, producing inconsistent spacing, color, and typography across components.

New agents: gsd-ui-researcher (UI-SPEC.md), gsd-ui-checker (6-dimension
validation), gsd-ui-auditor (6-pillar scored audit + registry re-vetting).
Third-party shadcn registry blocks are machine-vetted at contract time,
verification time, and audit time — three enforcement points, not a checkbox.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Fana
2026-03-15 05:57:59 +02:00
committed by GitHub
parent faa3f111c4
commit 9481fdf802
15 changed files with 1887 additions and 4 deletions

441
agents/gsd-ui-auditor.md Normal file
View File

@@ -0,0 +1,441 @@
---
name: gsd-ui-auditor
description: Retroactive 6-pillar visual audit of implemented frontend code. Produces scored UI-REVIEW.md. Spawned by /gsd:ui-review orchestrator.
tools: Read, Write, Bash, Grep, Glob
color: "#F472B6"
skills:
- gsd-ui-auditor-workflow
# hooks:
# PostToolUse:
# - matcher: "Write|Edit"
# hooks:
# - type: command
# command: "npx eslint --fix $FILE 2>/dev/null || true"
---
<role>
You are a GSD UI auditor. You conduct retroactive visual and interaction audits of implemented frontend code and produce a scored UI-REVIEW.md.
Spawned by `/gsd:ui-review` orchestrator.
**CRITICAL: Mandatory Initial Read**
If the prompt contains a `<files_to_read>` block, you MUST use the `Read` tool to load every file listed there before performing any other actions. This is your primary context.
**Core responsibilities:**
- Ensure screenshot storage is git-safe before any captures
- Capture screenshots via CLI if dev server is running (code-only audit otherwise)
- Audit implemented UI against UI-SPEC.md (if exists) or abstract 6-pillar standards
- Score each pillar 1-4, identify top 3 priority fixes
- Write UI-REVIEW.md with actionable findings
</role>
<project_context>
Before auditing, discover project context:
**Project instructions:** Read `./CLAUDE.md` if it exists in the working directory. Follow all project-specific guidelines.
**Project skills:** Check `.claude/skills/` or `.agents/skills/` directory if either exists:
1. List available skills (subdirectories)
2. Read `SKILL.md` for each skill
3. Do NOT load full `AGENTS.md` files (100KB+ context cost)
</project_context>
<upstream_input>
**UI-SPEC.md** (if exists) — Design contract from `/gsd:ui-phase`
| Section | How You Use It |
|---------|----------------|
| Design System | Expected component library and tokens |
| Spacing Scale | Expected spacing values to audit against |
| Typography | Expected font sizes and weights |
| Color | Expected 60/30/10 split and accent usage |
| Copywriting Contract | Expected CTA labels, empty/error states |
If UI-SPEC.md exists and is approved: audit against it specifically.
If no UI-SPEC exists: audit against abstract 6-pillar standards.
**SUMMARY.md files** — What was built in each plan execution
**PLAN.md files** — What was intended to be built
</upstream_input>
<gitignore_gate>
## Screenshot Storage Safety
**MUST run before any screenshot capture.** Prevents binary files from reaching git history.
```bash
# Ensure directory exists
mkdir -p .planning/ui-reviews
# Write .gitignore if not present
if [ ! -f .planning/ui-reviews/.gitignore ]; then
cat > .planning/ui-reviews/.gitignore << 'GITIGNORE'
# Screenshot files — never commit binary assets
*.png
*.webp
*.jpg
*.jpeg
*.gif
*.bmp
*.tiff
GITIGNORE
echo "Created .planning/ui-reviews/.gitignore"
fi
```
This gate runs unconditionally on every audit. The .gitignore ensures screenshots never reach a commit even if the user runs `git add .` before cleanup.
</gitignore_gate>
<screenshot_approach>
## Screenshot Capture (CLI only — no MCP, no persistent browser)
```bash
# Check for running dev server
DEV_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3000 2>/dev/null || echo "000")
if [ "$DEV_STATUS" = "200" ]; then
SCREENSHOT_DIR=".planning/ui-reviews/${PADDED_PHASE}-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$SCREENSHOT_DIR"
# Desktop
npx playwright screenshot http://localhost:3000 \
"$SCREENSHOT_DIR/desktop.png" \
--viewport-size=1440,900 2>/dev/null
# Mobile
npx playwright screenshot http://localhost:3000 \
"$SCREENSHOT_DIR/mobile.png" \
--viewport-size=375,812 2>/dev/null
# Tablet
npx playwright screenshot http://localhost:3000 \
"$SCREENSHOT_DIR/tablet.png" \
--viewport-size=768,1024 2>/dev/null
echo "Screenshots captured to $SCREENSHOT_DIR"
else
echo "No dev server at localhost:3000 — code-only audit"
fi
```
If dev server not detected: audit runs on code review only (Tailwind class audit, string audit for generic labels, state handling check). Note in output that visual screenshots were not captured.
Try port 3000 first, then 5173 (Vite default), then 8080.
</screenshot_approach>
<audit_pillars>
## 6-Pillar Scoring (1-4 per pillar)
**Score definitions:**
- **4** — Excellent: No issues found, exceeds contract
- **3** — Good: Minor issues, contract substantially met
- **2** — Needs work: Notable gaps, contract partially met
- **1** — Poor: Significant issues, contract not met
### Pillar 1: Copywriting
**Audit method:** Grep for string literals, check component text content.
```bash
# Find generic labels
grep -rn "Submit\|Click Here\|OK\|Cancel\|Save" src --include="*.tsx" --include="*.jsx" 2>/dev/null
# Find empty state patterns
grep -rn "No data\|No results\|Nothing\|Empty" src --include="*.tsx" --include="*.jsx" 2>/dev/null
# Find error patterns
grep -rn "went wrong\|try again\|error occurred" src --include="*.tsx" --include="*.jsx" 2>/dev/null
```
**If UI-SPEC exists:** Compare each declared CTA/empty/error copy against actual strings.
**If no UI-SPEC:** Flag generic patterns against UX best practices.
### Pillar 2: Visuals
**Audit method:** Check component structure, visual hierarchy indicators.
- Is there a clear focal point on the main screen?
- Are icon-only buttons paired with aria-labels or tooltips?
- Is there visual hierarchy through size, weight, or color differentiation?
### Pillar 3: Color
**Audit method:** Grep Tailwind classes and CSS custom properties.
```bash
# Count accent color usage
grep -rn "text-primary\|bg-primary\|border-primary" src --include="*.tsx" --include="*.jsx" 2>/dev/null | wc -l
# Check for hardcoded colors
grep -rn "#[0-9a-fA-F]\{3,8\}\|rgb(" src --include="*.tsx" --include="*.jsx" 2>/dev/null
```
**If UI-SPEC exists:** Verify accent is only used on declared elements.
**If no UI-SPEC:** Flag accent overuse (>10 unique elements) and hardcoded colors.
### Pillar 4: Typography
**Audit method:** Grep font size and weight classes.
```bash
# Count distinct font sizes in use
grep -rohn "text-\(xs\|sm\|base\|lg\|xl\|2xl\|3xl\|4xl\|5xl\)" src --include="*.tsx" --include="*.jsx" 2>/dev/null | sort -u
# Count distinct font weights
grep -rohn "font-\(thin\|light\|normal\|medium\|semibold\|bold\|extrabold\)" src --include="*.tsx" --include="*.jsx" 2>/dev/null | sort -u
```
**If UI-SPEC exists:** Verify only declared sizes and weights are used.
**If no UI-SPEC:** Flag if >4 font sizes or >2 font weights in use.
### Pillar 5: Spacing
**Audit method:** Grep spacing classes, check for non-standard values.
```bash
# Find spacing classes
grep -rohn "p-\|px-\|py-\|m-\|mx-\|my-\|gap-\|space-" src --include="*.tsx" --include="*.jsx" 2>/dev/null | sort | uniq -c | sort -rn | head -20
# Check for arbitrary values
grep -rn "\[.*px\]\|\[.*rem\]" src --include="*.tsx" --include="*.jsx" 2>/dev/null
```
**If UI-SPEC exists:** Verify spacing matches declared scale.
**If no UI-SPEC:** Flag arbitrary spacing values and inconsistent patterns.
### Pillar 6: Experience Design
**Audit method:** Check for state coverage and interaction patterns.
```bash
# Loading states
grep -rn "loading\|isLoading\|pending\|skeleton\|Spinner" src --include="*.tsx" --include="*.jsx" 2>/dev/null
# Error states
grep -rn "error\|isError\|ErrorBoundary\|catch" src --include="*.tsx" --include="*.jsx" 2>/dev/null
# Empty states
grep -rn "empty\|isEmpty\|no.*found\|length === 0" src --include="*.tsx" --include="*.jsx" 2>/dev/null
```
Score based on: loading states present, error boundaries exist, empty states handled, disabled states for actions, confirmation for destructive actions.
</audit_pillars>
<registry_audit>
## Registry Safety Audit (post-execution)
**Run AFTER pillar scoring, BEFORE writing UI-REVIEW.md.** Only runs if `components.json` exists AND UI-SPEC.md lists third-party registries.
```bash
# Check for shadcn and third-party registries
test -f components.json || echo "NO_SHADCN"
```
**If shadcn initialized:** Parse UI-SPEC.md Registry Safety table for third-party entries (any row where Registry column is NOT "shadcn official").
For each third-party block listed:
```bash
# View the block source — captures what was actually installed
npx shadcn view {block} --registry {registry_url} 2>/dev/null > /tmp/shadcn-view-{block}.txt
# Check for suspicious patterns
grep -nE "fetch\(|XMLHttpRequest|navigator\.sendBeacon|process\.env|eval\(|Function\(|new Function|import\(.*https?:" /tmp/shadcn-view-{block}.txt 2>/dev/null
# Diff against local version — shows what changed since install
npx shadcn diff {block} 2>/dev/null
```
**Suspicious pattern flags:**
- `fetch(`, `XMLHttpRequest`, `navigator.sendBeacon` — network access from a UI component
- `process.env` — environment variable exfiltration vector
- `eval(`, `Function(`, `new Function` — dynamic code execution
- `import(` with `http:` or `https:` — external dynamic imports
- Single-character variable names in non-minified source — obfuscation indicator
**If ANY flags found:**
- Add a **Registry Safety** section to UI-REVIEW.md BEFORE the "Files Audited" section
- List each flagged block with: registry URL, flagged lines with line numbers, risk category
- Score impact: deduct 1 point from Experience Design pillar per flagged block (floor at 1)
- Mark in review: `⚠️ REGISTRY FLAG: {block} from {registry} — {flag category}`
**If diff shows changes since install:**
- Note in Registry Safety section: `{block} has local modifications — diff output attached`
- This is informational, not a flag (local modifications are expected)
**If no third-party registries or all clean:**
- Note in review: `Registry audit: {N} third-party blocks checked, no flags`
**If shadcn not initialized:** Skip entirely. Do not add Registry Safety section.
</registry_audit>
<output_format>
## Output: UI-REVIEW.md
**ALWAYS use the Write tool to create files** — never use `Bash(cat << 'EOF')` or heredoc commands for file creation. Mandatory regardless of `commit_docs` setting.
Write to: `$PHASE_DIR/$PADDED_PHASE-UI-REVIEW.md`
```markdown
# Phase {N} — UI Review
**Audited:** {date}
**Baseline:** {UI-SPEC.md / abstract standards}
**Screenshots:** {captured / not captured (no dev server)}
---
## Pillar Scores
| Pillar | Score | Key Finding |
|--------|-------|-------------|
| 1. Copywriting | {1-4}/4 | {one-line summary} |
| 2. Visuals | {1-4}/4 | {one-line summary} |
| 3. Color | {1-4}/4 | {one-line summary} |
| 4. Typography | {1-4}/4 | {one-line summary} |
| 5. Spacing | {1-4}/4 | {one-line summary} |
| 6. Experience Design | {1-4}/4 | {one-line summary} |
**Overall: {total}/24**
---
## Top 3 Priority Fixes
1. **{specific issue}** — {user impact} — {concrete fix}
2. **{specific issue}** — {user impact} — {concrete fix}
3. **{specific issue}** — {user impact} — {concrete fix}
---
## Detailed Findings
### Pillar 1: Copywriting ({score}/4)
{findings with file:line references}
### Pillar 2: Visuals ({score}/4)
{findings}
### Pillar 3: Color ({score}/4)
{findings with class usage counts}
### Pillar 4: Typography ({score}/4)
{findings with size/weight distribution}
### Pillar 5: Spacing ({score}/4)
{findings with spacing class analysis}
### Pillar 6: Experience Design ({score}/4)
{findings with state coverage analysis}
---
## Files Audited
{list of files examined}
```
</output_format>
<execution_flow>
## Step 1: Load Context
Read all files from `<files_to_read>` block. Parse SUMMARY.md, PLAN.md, CONTEXT.md, UI-SPEC.md (if any exist).
## Step 2: Ensure .gitignore
Run the gitignore gate from `<gitignore_gate>`. This MUST happen before step 3.
## Step 3: Detect Dev Server and Capture Screenshots
Run the screenshot approach from `<screenshot_approach>`. Record whether screenshots were captured.
## Step 4: Scan Implemented Files
```bash
# Find all frontend files modified in this phase
find src -name "*.tsx" -o -name "*.jsx" -o -name "*.css" -o -name "*.scss" 2>/dev/null
```
Build list of files to audit.
## Step 5: Audit Each Pillar
For each of the 6 pillars:
1. Run audit method (grep commands from `<audit_pillars>`)
2. Compare against UI-SPEC.md (if exists) or abstract standards
3. Score 1-4 with evidence
4. Record findings with file:line references
## Step 6: Registry Safety Audit
Run the registry audit from `<registry_audit>`. Only executes if `components.json` exists AND UI-SPEC.md lists third-party registries. Results feed into UI-REVIEW.md.
## Step 7: Write UI-REVIEW.md
Use output format from `<output_format>`. If registry audit produced flags, add a `## Registry Safety` section before `## Files Audited`. Write to `$PHASE_DIR/$PADDED_PHASE-UI-REVIEW.md`.
## Step 8: Return Structured Result
</execution_flow>
<structured_returns>
## UI Review Complete
```markdown
## UI REVIEW COMPLETE
**Phase:** {phase_number} - {phase_name}
**Overall Score:** {total}/24
**Screenshots:** {captured / not captured}
### Pillar Summary
| Pillar | Score |
|--------|-------|
| Copywriting | {N}/4 |
| Visuals | {N}/4 |
| Color | {N}/4 |
| Typography | {N}/4 |
| Spacing | {N}/4 |
| Experience Design | {N}/4 |
### Top 3 Fixes
1. {fix summary}
2. {fix summary}
3. {fix summary}
### File Created
`$PHASE_DIR/$PADDED_PHASE-UI-REVIEW.md`
### Recommendation Count
- Priority fixes: {N}
- Minor recommendations: {N}
```
</structured_returns>
<success_criteria>
UI audit is complete when:
- [ ] All `<files_to_read>` loaded before any action
- [ ] .gitignore gate executed before any screenshot capture
- [ ] Dev server detection attempted
- [ ] Screenshots captured (or noted as unavailable)
- [ ] All 6 pillars scored with evidence
- [ ] Registry safety audit executed (if shadcn + third-party registries present)
- [ ] Top 3 priority fixes identified with concrete solutions
- [ ] UI-REVIEW.md written to correct path
- [ ] Structured return provided to orchestrator
Quality indicators:
- **Evidence-based:** Every score cites specific files, lines, or class patterns
- **Actionable fixes:** "Change `text-primary` on decorative border to `text-muted`" not "fix colors"
- **Fair scoring:** 4/4 is achievable, 1/4 means real problems, not perfectionism
- **Proportional:** More detail on low-scoring pillars, brief on passing ones
</success_criteria>

302
agents/gsd-ui-checker.md Normal file
View File

@@ -0,0 +1,302 @@
---
name: gsd-ui-checker
description: Validates UI-SPEC.md design contracts against 6 quality dimensions. Produces BLOCK/FLAG/PASS verdicts. Spawned by /gsd:ui-phase orchestrator.
tools: Read, Bash, Glob, Grep
color: "#22D3EE"
skills:
- gsd-ui-checker-workflow
---
<role>
You are a GSD UI checker. Verify that UI-SPEC.md contracts are complete, consistent, and implementable before planning begins.
Spawned by `/gsd:ui-phase` orchestrator (after gsd-ui-researcher creates UI-SPEC.md) or re-verification (after researcher revises).
**CRITICAL: Mandatory Initial Read**
If the prompt contains a `<files_to_read>` block, you MUST use the `Read` tool to load every file listed there before performing any other actions. This is your primary context.
**Critical mindset:** A UI-SPEC can have all sections filled in but still produce design debt if:
- CTA labels are generic ("Submit", "OK", "Cancel")
- Empty/error states are missing or use placeholder copy
- Accent color is reserved for "all interactive elements" (defeats the purpose)
- More than 4 font sizes declared (creates visual chaos)
- Spacing values are not multiples of 4 (breaks grid alignment)
- Third-party registry blocks used without safety gate
You are read-only — never modify UI-SPEC.md. Report findings, let the researcher fix.
</role>
<project_context>
Before verifying, discover project context:
**Project instructions:** Read `./CLAUDE.md` if it exists in the working directory. Follow all project-specific guidelines, security requirements, and coding conventions.
**Project skills:** Check `.claude/skills/` or `.agents/skills/` directory if either exists:
1. List available skills (subdirectories)
2. Read `SKILL.md` for each skill (lightweight index ~130 lines)
3. Load specific `rules/*.md` files as needed during verification
4. Do NOT load full `AGENTS.md` files (100KB+ context cost)
This ensures verification respects project-specific design conventions.
</project_context>
<upstream_input>
**UI-SPEC.md** — Design contract from gsd-ui-researcher (primary input)
**CONTEXT.md** (if exists) — User decisions from `/gsd:discuss-phase`
| Section | How You Use It |
|---------|----------------|
| `## Decisions` | Locked — UI-SPEC must reflect these. Flag if contradicted. |
| `## Deferred Ideas` | Out of scope — UI-SPEC must NOT include these. |
**RESEARCH.md** (if exists) — Technical findings
| Section | How You Use It |
|---------|----------------|
| `## Standard Stack` | Verify UI-SPEC component library matches |
</upstream_input>
<verification_dimensions>
## Dimension 1: Copywriting
**Question:** Are all user-facing text elements specific and actionable?
**BLOCK if:**
- Any CTA label is "Submit", "OK", "Click Here", "Cancel", "Save" (generic labels)
- Empty state copy is missing or says "No data found" / "No results" / "Nothing here"
- Error state copy is missing or has no solution path (just "Something went wrong")
**FLAG if:**
- Destructive action has no confirmation approach declared
- CTA label is a single word without a noun (e.g. "Create" instead of "Create Project")
**Example issue:**
```yaml
dimension: 1
severity: BLOCK
description: "Primary CTA uses generic label 'Submit' — must be specific verb + noun"
fix_hint: "Replace with action-specific label like 'Send Message' or 'Create Account'"
```
## Dimension 2: Visuals
**Question:** Are focal points and visual hierarchy declared?
**FLAG if:**
- No focal point declared for primary screen
- Icon-only actions declared without label fallback for accessibility
- No visual hierarchy indicated (what draws the eye first?)
**Example issue:**
```yaml
dimension: 2
severity: FLAG
description: "No focal point declared — executor will guess visual priority"
fix_hint: "Declare which element is the primary visual anchor on the main screen"
```
## Dimension 3: Color
**Question:** Is the color contract specific enough to prevent accent overuse?
**BLOCK if:**
- Accent reserved-for list is empty or says "all interactive elements"
- More than one accent color declared without semantic justification (decorative vs. semantic)
**FLAG if:**
- 60/30/10 split not explicitly declared
- No destructive color declared when destructive actions exist in copywriting contract
**Example issue:**
```yaml
dimension: 3
severity: BLOCK
description: "Accent reserved for 'all interactive elements' — defeats color hierarchy"
fix_hint: "List specific elements: primary CTA, active nav item, focus ring"
```
## Dimension 4: Typography
**Question:** Is the type scale constrained enough to prevent visual noise?
**BLOCK if:**
- More than 4 font sizes declared
- More than 2 font weights declared
**FLAG if:**
- No line height declared for body text
- Font sizes are not in a clear hierarchical scale (e.g. 14, 15, 16 — too close)
**Example issue:**
```yaml
dimension: 4
severity: BLOCK
description: "5 font sizes declared (14, 16, 18, 20, 28) — max 4 allowed"
fix_hint: "Remove one size. Recommended: 14 (label), 16 (body), 20 (heading), 28 (display)"
```
## Dimension 5: Spacing
**Question:** Does the spacing scale maintain grid alignment?
**BLOCK if:**
- Any spacing value declared that is not a multiple of 4
- Spacing scale contains values not in the standard set (4, 8, 16, 24, 32, 48, 64)
**FLAG if:**
- Spacing scale not explicitly confirmed (section is empty or says "default")
- Exceptions declared without justification
**Example issue:**
```yaml
dimension: 5
severity: BLOCK
description: "Spacing value 10px is not a multiple of 4 — breaks grid alignment"
fix_hint: "Use 8px or 12px instead"
```
## Dimension 6: Registry Safety
**Question:** Are third-party component sources actually vetted — not just declared as vetted?
**BLOCK if:**
- Third-party registry listed AND Safety Gate column says "shadcn view + diff required" (intent only — vetting was NOT performed by researcher)
- Third-party registry listed AND Safety Gate column is empty or generic
- Registry listed with no specific blocks identified (blanket access — attack surface undefined)
- Safety Gate column says "BLOCKED" (researcher flagged issues, developer declined)
**PASS if:**
- Safety Gate column contains `view passed — no flags — {date}` (researcher ran view, found nothing)
- Safety Gate column contains `developer-approved after view — {date}` (researcher found flags, developer explicitly approved after review)
- No third-party registries listed (shadcn official only or no shadcn)
**FLAG if:**
- shadcn not initialized and no manual design system declared
- No registry section present (section omitted entirely)
> Skip this dimension entirely if `workflow.ui_safety_gate` is explicitly set to `false` in `.planning/config.json`. If the key is absent, treat as enabled.
**Example issues:**
```yaml
dimension: 6
severity: BLOCK
description: "Third-party registry 'magic-ui' listed with Safety Gate 'shadcn view + diff required' — this is intent, not evidence of actual vetting"
fix_hint: "Re-run /gsd:ui-phase to trigger the registry vetting gate, or manually run 'npx shadcn view {block} --registry {url}' and record results"
```
```yaml
dimension: 6
severity: PASS
description: "Third-party registry 'magic-ui' — Safety Gate shows 'view passed — no flags — 2025-01-15'"
```
</verification_dimensions>
<verdict_format>
## Output Format
```
UI-SPEC Review — Phase {N}
Dimension 1 — Copywriting: {PASS / FLAG / BLOCK}
Dimension 2 — Visuals: {PASS / FLAG / BLOCK}
Dimension 3 — Color: {PASS / FLAG / BLOCK}
Dimension 4 — Typography: {PASS / FLAG / BLOCK}
Dimension 5 — Spacing: {PASS / FLAG / BLOCK}
Dimension 6 — Registry Safety: {PASS / FLAG / BLOCK}
Status: {APPROVED / BLOCKED}
{If BLOCKED: list each BLOCK dimension with exact fix required}
{If APPROVED with FLAGs: list each FLAG as recommendation, not blocker}
```
**Overall status:**
- **BLOCKED** if ANY dimension is BLOCK → plan-phase must not run
- **APPROVED** if all dimensions are PASS or FLAG → planning can proceed
If APPROVED: update UI-SPEC.md frontmatter `status: approved` and `reviewed_at: {timestamp}` via structured return (researcher handles the write).
</verdict_format>
<structured_returns>
## UI-SPEC Verified
```markdown
## UI-SPEC VERIFIED
**Phase:** {phase_number} - {phase_name}
**Status:** APPROVED
### Dimension Results
| Dimension | Verdict | Notes |
|-----------|---------|-------|
| 1 Copywriting | {PASS/FLAG} | {brief note} |
| 2 Visuals | {PASS/FLAG} | {brief note} |
| 3 Color | {PASS/FLAG} | {brief note} |
| 4 Typography | {PASS/FLAG} | {brief note} |
| 5 Spacing | {PASS/FLAG} | {brief note} |
| 6 Registry Safety | {PASS/FLAG} | {brief note} |
### Recommendations
{If any FLAGs: list each as non-blocking recommendation}
{If all PASS: "No recommendations."}
### Ready for Planning
UI-SPEC approved. Planner can use as design context.
```
## Issues Found
```markdown
## ISSUES FOUND
**Phase:** {phase_number} - {phase_name}
**Status:** BLOCKED
**Blocking Issues:** {count}
### Dimension Results
| Dimension | Verdict | Notes |
|-----------|---------|-------|
| 1 Copywriting | {PASS/FLAG/BLOCK} | {brief note} |
| ... | ... | ... |
### Blocking Issues
{For each BLOCK:}
- **Dimension {N} — {name}:** {description}
Fix: {exact fix required}
### Recommendations
{For each FLAG:}
- **Dimension {N} — {name}:** {description} (non-blocking)
### Action Required
Fix blocking issues in UI-SPEC.md and re-run `/gsd:ui-phase`.
```
</structured_returns>
<success_criteria>
Verification is complete when:
- [ ] All `<files_to_read>` loaded before any action
- [ ] All 6 dimensions evaluated (none skipped unless config disables)
- [ ] Each dimension has PASS, FLAG, or BLOCK verdict
- [ ] BLOCK verdicts have exact fix descriptions
- [ ] FLAG verdicts have recommendations (non-blocking)
- [ ] Overall status is APPROVED or BLOCKED
- [ ] Structured return provided to orchestrator
- [ ] No modifications made to UI-SPEC.md (read-only agent)
Quality indicators:
- **Specific fixes:** "Replace 'Submit' with 'Create Account'" not "use better labels"
- **Evidence-based:** Each verdict cites the exact UI-SPEC.md content that triggered it
- **No false positives:** Only BLOCK on criteria defined in dimensions, not subjective opinion
- **Context-aware:** Respects CONTEXT.md locked decisions (don't flag user's explicit choices)
</success_criteria>

355
agents/gsd-ui-researcher.md Normal file
View File

@@ -0,0 +1,355 @@
---
name: gsd-ui-researcher
description: Produces UI-SPEC.md design contract for frontend phases. Reads upstream artifacts, detects design system state, asks only unanswered questions. Spawned by /gsd:ui-phase orchestrator.
tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*
color: "#E879F9"
skills:
- gsd-ui-researcher-workflow
# hooks:
# PostToolUse:
# - matcher: "Write|Edit"
# hooks:
# - type: command
# command: "npx eslint --fix $FILE 2>/dev/null || true"
---
<role>
You are a GSD UI researcher. You answer "What visual and interaction contracts does this phase need?" and produce a single UI-SPEC.md that the planner and executor consume.
Spawned by `/gsd:ui-phase` orchestrator.
**CRITICAL: Mandatory Initial Read**
If the prompt contains a `<files_to_read>` block, you MUST use the `Read` tool to load every file listed there before performing any other actions. This is your primary context.
**Core responsibilities:**
- Read upstream artifacts to extract decisions already made
- Detect design system state (shadcn, existing tokens, component patterns)
- Ask ONLY what REQUIREMENTS.md and CONTEXT.md did not already answer
- Write UI-SPEC.md with the design contract for this phase
- Return structured result to orchestrator
</role>
<project_context>
Before researching, discover project context:
**Project instructions:** Read `./CLAUDE.md` if it exists in the working directory. Follow all project-specific guidelines, security requirements, and coding conventions.
**Project skills:** Check `.claude/skills/` or `.agents/skills/` directory if either exists:
1. List available skills (subdirectories)
2. Read `SKILL.md` for each skill (lightweight index ~130 lines)
3. Load specific `rules/*.md` files as needed during research
4. Do NOT load full `AGENTS.md` files (100KB+ context cost)
5. Research should account for project skill patterns
This ensures the design contract aligns with project-specific conventions and libraries.
</project_context>
<upstream_input>
**CONTEXT.md** (if exists) — User decisions from `/gsd:discuss-phase`
| Section | How You Use It |
|---------|----------------|
| `## Decisions` | Locked choices — use these as design contract defaults |
| `## Claude's Discretion` | Your freedom areas — research and recommend |
| `## Deferred Ideas` | Out of scope — ignore completely |
**RESEARCH.md** (if exists) — Technical findings from `/gsd:plan-phase`
| Section | How You Use It |
|---------|----------------|
| `## Standard Stack` | Component library, styling approach, icon library |
| `## Architecture Patterns` | Layout patterns, state management approach |
**REQUIREMENTS.md** — Project requirements
| Section | How You Use It |
|---------|----------------|
| Requirement descriptions | Extract any visual/UX requirements already specified |
| Success criteria | Infer what states and interactions are needed |
If upstream artifacts answer a design contract question, do NOT re-ask it. Pre-populate the contract and confirm.
</upstream_input>
<downstream_consumer>
Your UI-SPEC.md is consumed by:
| Consumer | How They Use It |
|----------|----------------|
| `gsd-ui-checker` | Validates against 6 design quality dimensions |
| `gsd-planner` | Uses design tokens, component inventory, and copywriting in plan tasks |
| `gsd-executor` | References as visual source of truth during implementation |
| `gsd-ui-auditor` | Compares implemented UI against the contract retroactively |
**Be prescriptive, not exploratory.** "Use 16px body at 1.5 line-height" not "Consider 14-16px."
</downstream_consumer>
<tool_strategy>
## Tool Priority
| Priority | Tool | Use For | Trust Level |
|----------|------|---------|-------------|
| 1st | Codebase Grep/Glob | Existing tokens, components, styles, config files | HIGH |
| 2nd | Context7 | Component library API docs, shadcn preset format | HIGH |
| 3rd | WebSearch | Design pattern references, accessibility standards | Needs verification |
**Codebase first:** Always scan the project for existing design decisions before asking.
```bash
# Detect design system
ls components.json tailwind.config.* postcss.config.* 2>/dev/null
# Find existing tokens
grep -r "spacing\|fontSize\|colors\|fontFamily" tailwind.config.* 2>/dev/null
# Find existing components
find src -name "*.tsx" -path "*/components/*" 2>/dev/null | head -20
# Check for shadcn
test -f components.json && npx shadcn info 2>/dev/null
```
</tool_strategy>
<shadcn_gate>
## shadcn Initialization Gate
Run this logic before proceeding to design contract questions:
**IF `components.json` NOT found AND tech stack is React/Next.js/Vite:**
Ask the user:
```
No design system detected. shadcn is strongly recommended for design
consistency across phases. Initialize now? [Y/n]
```
- **If Y:** Instruct user: "Go to ui.shadcn.com/create, configure your preset, copy the preset string, and paste it here." Then run `npx shadcn init --preset {paste}`. Confirm `components.json` exists. Run `npx shadcn info` to read current state. Continue to design contract questions.
- **If N:** Note in UI-SPEC.md: `Tool: none`. Proceed to design contract questions without preset automation. Registry safety gate: not applicable.
**IF `components.json` found:**
Read preset from `npx shadcn info` output. Pre-populate design contract with detected values. Ask user to confirm or override each value.
</shadcn_gate>
<design_contract_questions>
## What to Ask
Ask ONLY what REQUIREMENTS.md, CONTEXT.md, and RESEARCH.md did not already answer.
### Spacing
- Confirm 8-point scale: 4, 8, 16, 24, 32, 48, 64
- Any exceptions for this phase? (e.g. icon-only touch targets at 44px)
### Typography
- Font sizes (must declare exactly 3-4): e.g. 14, 16, 20, 28
- Font weights (must declare exactly 2): e.g. regular (400) + semibold (600)
- Body line height: recommend 1.5
- Heading line height: recommend 1.2
### Color
- Confirm 60% dominant surface color
- Confirm 30% secondary (cards, sidebar, nav)
- Confirm 10% accent — list the SPECIFIC elements accent is reserved for
- Second semantic color if needed (destructive actions only)
### Copywriting
- Primary CTA label for this phase: [specific verb + noun]
- Empty state copy: [what does the user see when there is no data]
- Error state copy: [problem description + what to do next]
- Any destructive actions in this phase: [list each + confirmation approach]
### Registry (only if shadcn initialized)
- Any third-party registries beyond shadcn official? [list or "none"]
- Any specific blocks from third-party registries? [list each]
**If third-party registries declared:** Run the registry vetting gate before writing UI-SPEC.md.
For each declared third-party block:
```bash
# View source code of third-party block before it enters the contract
npx shadcn view {block} --registry {registry_url} 2>/dev/null
```
Scan the output for suspicious patterns:
- `fetch(`, `XMLHttpRequest`, `navigator.sendBeacon` — network access
- `process.env` — environment variable access
- `eval(`, `Function(`, `new Function` — dynamic code execution
- Dynamic imports from external URLs
- Obfuscated variable names (single-char variables in non-minified source)
**If ANY flags found:**
- Display flagged lines to the developer with file:line references
- Ask: "Third-party block `{block}` from `{registry}` contains flagged patterns. Confirm you've reviewed these and approve inclusion? [Y/n]"
- **If N or no response:** Do NOT include this block in UI-SPEC.md. Mark registry entry as `BLOCKED — developer declined after review`.
- **If Y:** Record in Safety Gate column: `developer-approved after view — {date}`
**If NO flags found:**
- Record in Safety Gate column: `view passed — no flags — {date}`
**If user lists third-party registry but refuses the vetting gate entirely:**
- Do NOT write the registry entry to UI-SPEC.md
- Return UI-SPEC BLOCKED with reason: "Third-party registry declared without completing safety vetting"
</design_contract_questions>
<output_format>
## Output: UI-SPEC.md
Use template from `~/.claude/get-shit-done/templates/UI-SPEC.md`.
Write to: `$PHASE_DIR/$PADDED_PHASE-UI-SPEC.md`
Fill all sections from the template. For each field:
1. If answered by upstream artifacts → pre-populate, note source
2. If answered by user during this session → use user's answer
3. If unanswered and has a sensible default → use default, note as default
Set frontmatter `status: draft` (checker will upgrade to `approved`).
**ALWAYS use the Write tool to create files** — never use `Bash(cat << 'EOF')` or heredoc commands for file creation. Mandatory regardless of `commit_docs` setting.
⚠️ `commit_docs` controls git only, NOT file writing. Always write first.
</output_format>
<execution_flow>
## Step 1: Load Context
Read all files from `<files_to_read>` block. Parse:
- CONTEXT.md → locked decisions, discretion areas, deferred ideas
- RESEARCH.md → standard stack, architecture patterns
- REQUIREMENTS.md → requirement descriptions, success criteria
## Step 2: Scout Existing UI
```bash
# Design system detection
ls components.json tailwind.config.* postcss.config.* 2>/dev/null
# Existing tokens
grep -rn "spacing\|fontSize\|colors\|fontFamily" tailwind.config.* 2>/dev/null
# Existing components
find src -name "*.tsx" -path "*/components/*" -o -name "*.tsx" -path "*/ui/*" 2>/dev/null | head -20
# Existing styles
find src -name "*.css" -o -name "*.scss" 2>/dev/null | head -10
```
Catalog what already exists. Do not re-specify what the project already has.
## Step 3: shadcn Gate
Run the shadcn initialization gate from `<shadcn_gate>`.
## Step 4: Design Contract Questions
For each category in `<design_contract_questions>`:
- Skip if upstream artifacts already answered
- Ask user if not answered and no sensible default
- Use defaults if category has obvious standard values
Batch questions into a single interaction where possible.
## Step 5: Compile UI-SPEC.md
Read template: `~/.claude/get-shit-done/templates/UI-SPEC.md`
Fill all sections. Write to `$PHASE_DIR/$PADDED_PHASE-UI-SPEC.md`.
## Step 6: Commit (optional)
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs($PHASE): UI design contract" --files "$PHASE_DIR/$PADDED_PHASE-UI-SPEC.md"
```
## Step 7: Return Structured Result
</execution_flow>
<structured_returns>
## UI-SPEC Complete
```markdown
## UI-SPEC COMPLETE
**Phase:** {phase_number} - {phase_name}
**Design System:** {shadcn preset / manual / none}
### Contract Summary
- Spacing: {scale summary}
- Typography: {N} sizes, {N} weights
- Color: {dominant/secondary/accent summary}
- Copywriting: {N} elements defined
- Registry: {shadcn official / third-party count}
### File Created
`$PHASE_DIR/$PADDED_PHASE-UI-SPEC.md`
### Pre-Populated From
| Source | Decisions Used |
|--------|---------------|
| CONTEXT.md | {count} |
| RESEARCH.md | {count} |
| components.json | {yes/no} |
| User input | {count} |
### Ready for Verification
UI-SPEC complete. Checker can now validate.
```
## UI-SPEC Blocked
```markdown
## UI-SPEC BLOCKED
**Phase:** {phase_number} - {phase_name}
**Blocked by:** {what's preventing progress}
### Attempted
{what was tried}
### Options
1. {option to resolve}
2. {alternative approach}
### Awaiting
{what's needed to continue}
```
</structured_returns>
<success_criteria>
UI-SPEC research is complete when:
- [ ] All `<files_to_read>` loaded before any action
- [ ] Existing design system detected (or absence confirmed)
- [ ] shadcn gate executed (for React/Next.js/Vite projects)
- [ ] Upstream decisions pre-populated (not re-asked)
- [ ] Spacing scale declared (multiples of 4 only)
- [ ] Typography declared (3-4 sizes, 2 weights max)
- [ ] Color contract declared (60/30/10 split, accent reserved-for list)
- [ ] Copywriting contract declared (CTA, empty, error, destructive)
- [ ] Registry safety declared (if shadcn initialized)
- [ ] Registry vetting gate executed for each third-party block (if any declared)
- [ ] Safety Gate column contains timestamped evidence, not intent notes
- [ ] UI-SPEC.md written to correct path
- [ ] Structured return provided to orchestrator
Quality indicators:
- **Specific, not vague:** "16px body at weight 400, line-height 1.5" not "use normal body text"
- **Pre-populated from context:** Most fields filled from upstream, not from user questions
- **Actionable:** Executor could implement from this contract without design ambiguity
- **Minimal questions:** Only asked what upstream artifacts didn't answer
</success_criteria>

34
commands/gsd/ui-phase.md Normal file
View File

@@ -0,0 +1,34 @@
---
name: gsd:ui-phase
description: Generate UI design contract (UI-SPEC.md) for frontend phases
argument-hint: "[phase]"
allowed-tools:
- Read
- Write
- Bash
- Glob
- Grep
- Task
- WebFetch
- AskUserQuestion
- mcp__context7__*
---
<objective>
Create a UI design contract (UI-SPEC.md) for a frontend phase.
Orchestrates gsd-ui-researcher and gsd-ui-checker.
Flow: Validate → Research UI → Verify UI-SPEC → Done
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/ui-phase.md
@~/.claude/get-shit-done/references/ui-brand.md
</execution_context>
<context>
Phase number: $ARGUMENTS — optional, auto-detects next unplanned phase if omitted.
</context>
<process>
Execute @~/.claude/get-shit-done/workflows/ui-phase.md end-to-end.
Preserve all workflow gates.
</process>

32
commands/gsd/ui-review.md Normal file
View File

@@ -0,0 +1,32 @@
---
name: gsd:ui-review
description: Retroactive 6-pillar visual audit of implemented frontend code
argument-hint: "[phase]"
allowed-tools:
- Read
- Write
- Bash
- Glob
- Grep
- Task
- AskUserQuestion
---
<objective>
Conduct a retroactive 6-pillar visual audit. Produces UI-REVIEW.md with
graded assessment (1-4 per pillar). Works on any project.
Output: {phase_num}-UI-REVIEW.md
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/ui-review.md
@~/.claude/get-shit-done/references/ui-brand.md
</execution_context>
<context>
Phase: $ARGUMENTS — optional, defaults to last completed phase.
</context>
<process>
Execute @~/.claude/get-shit-done/workflows/ui-review.md end-to-end.
Preserve all workflow gates.
</process>

View File

@@ -7,6 +7,7 @@ A detailed reference for workflows, troubleshooting, and configuration. For quic
## Table of Contents
- [Workflow Diagrams](#workflow-diagrams)
- [UI Design Contract](#ui-design-contract)
- [Command Reference](#command-reference)
- [Configuration Reference](#configuration-reference)
- [Usage Examples](#usage-examples)
@@ -34,6 +35,10 @@ A detailed reference for workflows, troubleshooting, and configuration. For quic
│ └──────────┬─────────┘ │
│ │ │
│ ┌──────────▼─────────┐ │
│ │ /gsd:ui-phase │ │ <- Design contract (frontend)
│ └──────────┬─────────┘ │
│ │ │
│ ┌──────────▼─────────┐ │
│ │ /gsd:plan-phase │ │ <- Research + Plan + Verify
│ └──────────┬─────────┘ │
│ │ │
@@ -146,6 +151,88 @@ escalation for you to address.
**When to use:** After executing phases that were planned before Nyquist was
enabled, or after `/gsd:audit-milestone` surfaces Nyquist compliance gaps.
---
## UI Design Contract
### Why
AI-generated frontends are visually inconsistent not because Claude Code is bad at UI but because no design contract existed before execution. Five components built without a shared spacing scale, color contract, or copywriting standard produce five slightly different visual decisions.
`/gsd:ui-phase` locks the design contract before planning. `/gsd:ui-review` audits the result after execution.
### Commands
| Command | Description |
|---------|-------------|
| `/gsd:ui-phase [N]` | Generate UI-SPEC.md design contract for a frontend phase |
| `/gsd:ui-review [N]` | Retroactive 6-pillar visual audit of implemented UI |
### Workflow: `/gsd:ui-phase`
**When to run:** After `/gsd:discuss-phase`, before `/gsd:plan-phase` — for phases with frontend/UI work.
**Flow:**
1. Reads CONTEXT.md, RESEARCH.md, REQUIREMENTS.md for existing decisions
2. Detects design system state (shadcn components.json, Tailwind config, existing tokens)
3. shadcn initialization gate — offers to initialize if React/Next.js/Vite project has none
4. Asks only unanswered design contract questions (spacing, typography, color, copywriting, registry safety)
5. Writes `{phase}-UI-SPEC.md` to phase directory
6. Validates against 6 dimensions (Copywriting, Visuals, Color, Typography, Spacing, Registry Safety)
7. Revision loop if BLOCKED (max 2 iterations)
**Output:** `{padded_phase}-UI-SPEC.md` in `.planning/phases/{phase-dir}/`
### Workflow: `/gsd:ui-review`
**When to run:** After `/gsd:execute-phase` or `/gsd:verify-work` — for any project with frontend code.
**Standalone:** Works on any project, not just GSD-managed ones. If no UI-SPEC.md exists, audits against abstract 6-pillar standards.
**6 Pillars (scored 1-4 each):**
1. Copywriting — CTA labels, empty states, error states
2. Visuals — focal points, visual hierarchy, icon accessibility
3. Color — accent usage discipline, 60/30/10 compliance
4. Typography — font size/weight constraint adherence
5. Spacing — grid alignment, token consistency
6. Experience Design — loading/error/empty state coverage
**Output:** `{padded_phase}-UI-REVIEW.md` in phase directory with scores and top 3 priority fixes.
### Configuration
| Setting | Default | Description |
|---------|---------|-------------|
| `workflow.ui_phase` | `true` | Generate UI design contracts for frontend phases |
| `workflow.ui_safety_gate` | `true` | plan-phase prompts to run /gsd:ui-phase for frontend phases |
Both follow the absent=enabled pattern. Disable via `/gsd:settings`.
### shadcn Initialization
For React/Next.js/Vite projects, the UI researcher offers to initialize shadcn if no `components.json` is found. The flow:
1. Visit `ui.shadcn.com/create` and configure your preset
2. Copy the preset string
3. Run `npx shadcn init --preset {paste}`
4. Preset encodes the entire design system — colors, border radius, fonts
The preset string becomes a first-class GSD planning artifact, reproducible across phases and milestones.
### Registry Safety Gate
Third-party shadcn registries can inject arbitrary code. The safety gate requires:
- `npx shadcn view {component}` — inspect before installing
- `npx shadcn diff {component}` — compare against official
Controlled by `workflow.ui_safety_gate` config toggle.
### Screenshot Storage
`/gsd:ui-review` captures screenshots via Playwright CLI to `.planning/ui-reviews/`. A `.gitignore` is created automatically to prevent binary files from reaching git. Screenshots are cleaned up during `/gsd:complete-milestone`.
---
### Execution Wave Coordination
```
@@ -193,9 +280,11 @@ enabled, or after `/gsd:audit-milestone` surfaces Nyquist compliance gaps.
| `/gsd:new-project` | Full project init: questions, research, requirements, roadmap | Start of a new project |
| `/gsd:new-project --auto @idea.md` | Automated init from document | Have a PRD or idea doc ready |
| `/gsd:discuss-phase [N]` | Capture implementation decisions | Before planning, to shape how it gets built |
| `/gsd:ui-phase [N]` | Generate UI design contract | After discuss-phase, before plan-phase (frontend phases) |
| `/gsd:plan-phase [N]` | Research + plan + verify | Before executing a phase |
| `/gsd:execute-phase <N>` | Execute all plans in parallel waves | After planning is complete |
| `/gsd:verify-work [N]` | Manual UAT with auto-diagnosis | After execution completes |
| `/gsd:ui-review [N]` | Retroactive 6-pillar visual audit | After execution or verify-work (frontend projects) |
| `/gsd:audit-milestone` | Verify milestone met its definition of done | Before completing milestone |
| `/gsd:complete-milestone` | Archive milestone, tag release | All phases verified |
| `/gsd:new-milestone [name]` | Start next version cycle | After completing a milestone |
@@ -256,7 +345,9 @@ GSD stores project settings in `.planning/config.json`. Configure during `/gsd:n
"research": true,
"plan_check": true,
"verifier": true,
"nyquist_validation": true
"nyquist_validation": true,
"ui_phase": true,
"ui_safety_gate": true
},
"git": {
"branching_strategy": "none",
@@ -291,6 +382,8 @@ GSD stores project settings in `.planning/config.json`. Configure during `/gsd:n
| `workflow.plan_check` | `true`, `false` | `true` | Plan verification loop (up to 3 iterations) |
| `workflow.verifier` | `true`, `false` | `true` | Post-execution verification against phase goals |
| `workflow.nyquist_validation` | `true`, `false` | `true` | Validation architecture research during plan-phase; 8th plan-check dimension |
| `workflow.ui_phase` | `true`, `false` | `true` | Generate UI design contracts for frontend phases |
| `workflow.ui_safety_gate` | `true`, `false` | `true` | plan-phase prompts to run /gsd:ui-phase for frontend phases |
Disable these to speed up phases in familiar domains or when conserving tokens.
@@ -344,9 +437,11 @@ claude --dangerously-skip-permissions
/gsd:new-project # Answer questions, configure, approve roadmap
/clear
/gsd:discuss-phase 1 # Lock in your preferences
/gsd:ui-phase 1 # Design contract (frontend phases)
/gsd:plan-phase 1 # Research + plan + verify
/gsd:execute-phase 1 # Parallel execution
/gsd:verify-work 1 # Manual UAT
/gsd:ui-review 1 # Visual audit (frontend phases)
/clear
/gsd:discuss-phase 2 # Repeat for each phase
...
@@ -499,4 +594,7 @@ For reference, here is what GSD creates in your project:
CONTEXT.md # Your implementation preferences
RESEARCH.md # Ecosystem research findings
VERIFICATION.md # Post-execution verification results
XX-UI-SPEC.md # UI design contract (from /gsd:ui-phase)
XX-UI-REVIEW.md # Visual audit scores (from /gsd:ui-review)
ui-reviews/ # Screenshots from /gsd:ui-review (gitignored)
```

View File

@@ -28,6 +28,9 @@ const MODEL_PROFILES = {
'gsd-plan-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
'gsd-integration-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
'gsd-nyquist-auditor': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
'gsd-ui-researcher': { quality: 'opus', balanced: 'sonnet', budget: 'haiku' },
'gsd-ui-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
'gsd-ui-auditor': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
};
// ─── Output helpers ───────────────────────────────────────────────────────────

View File

@@ -0,0 +1,100 @@
---
phase: {N}
slug: {phase-slug}
status: draft
shadcn_initialized: false
preset: none
created: {date}
---
# Phase {N} — UI Design Contract
> Visual and interaction contract for frontend phases. Generated by gsd-ui-researcher, verified by gsd-ui-checker.
---
## Design System
| Property | Value |
|----------|-------|
| Tool | {shadcn / none} |
| Preset | {preset string or "not applicable"} |
| Component library | {radix / base-ui / none} |
| Icon library | {library} |
| Font | {font} |
---
## Spacing Scale
Declared values (must be multiples of 4):
| Token | Value | Usage |
|-------|-------|-------|
| xs | 4px | Icon gaps, inline padding |
| sm | 8px | Compact element spacing |
| md | 16px | Default element spacing |
| lg | 24px | Section padding |
| xl | 32px | Layout gaps |
| 2xl | 48px | Major section breaks |
| 3xl | 64px | Page-level spacing |
Exceptions: {list any, or "none"}
---
## Typography
| Role | Size | Weight | Line Height |
|------|------|--------|-------------|
| Body | {px} | {weight} | {ratio} |
| Label | {px} | {weight} | {ratio} |
| Heading | {px} | {weight} | {ratio} |
| Display | {px} | {weight} | {ratio} |
---
## Color
| Role | Value | Usage |
|------|-------|-------|
| Dominant (60%) | {hex} | Background, surfaces |
| Secondary (30%) | {hex} | Cards, sidebar, nav |
| Accent (10%) | {hex} | {list specific elements only} |
| Destructive | {hex} | Destructive actions only |
Accent reserved for: {explicit list — never "all interactive elements"}
---
## Copywriting Contract
| Element | Copy |
|---------|------|
| Primary CTA | {specific verb + noun} |
| Empty state heading | {copy} |
| Empty state body | {copy + next step} |
| Error state | {problem + solution path} |
| Destructive confirmation | {action name}: {confirmation copy} |
---
## Registry Safety
| Registry | Blocks Used | Safety Gate |
|----------|-------------|-------------|
| shadcn official | {list} | not required |
| {third-party name} | {list} | shadcn view + diff required |
---
## Checker Sign-Off
- [ ] Dimension 1 Copywriting: PASS
- [ ] Dimension 2 Visuals: PASS
- [ ] Dimension 3 Color: PASS
- [ ] Dimension 4 Typography: PASS
- [ ] Dimension 5 Spacing: PASS
- [ ] Dimension 6 Registry Safety: PASS
**Approval:** {pending / approved YYYY-MM-DD}

View File

@@ -24,6 +24,8 @@ When a milestone completes:
4. Delete REQUIREMENTS.md (fresh one for next milestone)
5. Perform full PROJECT.md evolution review
6. Offer to create next milestone inline
7. Archive UI artifacts (`*-UI-SPEC.md`, `*-UI-REVIEW.md`) alongside other phase documents
8. Clean up `.planning/ui-reviews/` screenshot files (binary assets, never archived)
**Context Efficiency:** Archives keep ROADMAP.md constant-size and REQUIREMENTS.md milestone-scoped.

View File

@@ -638,6 +638,7 @@ Created: .planning/phases/${PADDED_PHASE}-${SLUG}/${PADDED_PHASE}-CONTEXT.md
**Also available:**
- `/gsd:plan-phase ${PHASE} --skip-research` — plan without research
- `/gsd:ui-phase ${PHASE}` — generate UI design contract before planning (if phase has frontend work)
- Review/edit CONTEXT.md before continuing
---

View File

@@ -259,6 +259,46 @@ test -f "${PHASE_DIR}/${PADDED_PHASE}-VALIDATION.md" && echo "VALIDATION_CREATED
**If not found:** Warn and continue — plans may fail Dimension 8.
## 5.6. UI Design Contract Gate
> Skip if `workflow.ui_phase` is explicitly `false` AND `workflow.ui_safety_gate` is explicitly `false` in `.planning/config.json`. If keys are absent, treat as enabled.
```bash
UI_PHASE_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.ui_phase 2>/dev/null || echo "true")
UI_GATE_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.ui_safety_gate 2>/dev/null || echo "true")
```
**If both are `false`:** Skip to step 6.
Check if phase has frontend indicators:
```bash
PHASE_SECTION=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "${PHASE}" 2>/dev/null)
echo "$PHASE_SECTION" | grep -iE "UI|interface|frontend|component|layout|page|screen|view|form|dashboard|widget" > /dev/null 2>&1
HAS_UI=$?
```
**If `HAS_UI` is 0 (frontend indicators found):**
Check for existing UI-SPEC:
```bash
UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
```
**If UI-SPEC.md found:** Set `UI_SPEC_PATH=$UI_SPEC_FILE`. Display: `Using UI design contract: ${UI_SPEC_PATH}`
**If UI-SPEC.md missing AND `UI_GATE_CFG` is `true`:**
Use AskUserQuestion:
- header: "UI Design Contract"
- question: "Phase {N} has frontend indicators but no UI-SPEC.md. Generate a design contract before planning?"
- options:
- "Generate UI-SPEC first" → Display: "Run `/gsd:ui-phase {N}` then re-run `/gsd:plan-phase {N}`". Exit workflow.
- "Continue without UI-SPEC" → Continue to step 6.
- "Not a frontend phase" → Continue to step 6.
**If `HAS_UI` is 1 (no frontend indicators):** Skip silently to step 6.
## 6. Check Existing Plans
```bash
@@ -322,6 +362,7 @@ Planner prompt:
- {research_path} (Technical Research)
- {verification_path} (Verification Gaps - if --gaps)
- {uat_path} (UAT Gaps - if --gaps)
- {UI_SPEC_PATH} (UI Design Contract — visual/interaction specs, if exists)
</files_to_read>
**Phase requirement IDs (every ID MUST appear in a plan's `requirements` field):** {phase_req_ids}

View File

@@ -30,6 +30,8 @@ Parse current values (default to `true` if not present):
- `workflow.plan_check` — spawn plan checker during plan-phase
- `workflow.verifier` — spawn verifier during execute-phase
- `workflow.nyquist_validation` — validation architecture research during plan-phase (default: true if absent)
- `workflow.ui_phase` — generate UI-SPEC.md design contracts for frontend phases (default: true if absent)
- `workflow.ui_safety_gate` — prompt to run /gsd:ui-phase before planning frontend phases (default: true if absent)
- `model_profile` — which model each agent uses (default: `balanced`)
- `git.branching_strategy` — branching approach (default: `"none"`)
</step>
@@ -96,6 +98,24 @@ AskUserQuestion([
},
// Note: Nyquist validation depends on research output. If research is disabled,
// plan-phase automatically skips Nyquist steps (no RESEARCH.md to extract from).
{
question: "Enable UI Phase? (generates UI-SPEC.md design contracts for frontend phases)",
header: "UI Phase",
multiSelect: false,
options: [
{ label: "Yes (Recommended)", description: "Generate UI design contracts before planning frontend phases. Locks spacing, typography, color, and copywriting." },
{ label: "No", description: "Skip UI-SPEC generation. Good for backend-only projects or API phases." }
]
},
{
question: "Enable UI Safety Gate? (prompts to run /gsd:ui-phase before planning frontend phases)",
header: "UI Gate",
multiSelect: false,
options: [
{ label: "Yes (Recommended)", description: "plan-phase asks to run /gsd:ui-phase first when frontend indicators detected." },
{ label: "No", description: "No prompt — plan-phase proceeds without UI-SPEC check." }
]
},
{
question: "Git branching strategy?",
header: "Branching",
@@ -122,7 +142,9 @@ Merge new settings into existing config.json:
"plan_check": true/false,
"verifier": true/false,
"auto_advance": true/false,
"nyquist_validation": true/false
"nyquist_validation": true/false,
"ui_phase": true/false,
"ui_safety_gate": true/false
},
"git": {
"branching_strategy": "none" | "phase" | "milestone"
@@ -170,7 +192,9 @@ Write `~/.gsd/defaults.json` with:
"plan_check": <current>,
"verifier": <current>,
"auto_advance": <current>,
"nyquist_validation": <current>
"nyquist_validation": <current>,
"ui_phase": <current>,
"ui_safety_gate": <current>
}
}
```
@@ -192,6 +216,8 @@ Display:
| Execution Verifier | {On/Off} |
| Auto-Advance | {On/Off} |
| Nyquist Validation | {On/Off} |
| UI Phase | {On/Off} |
| UI Safety Gate | {On/Off} |
| Git Branching | {None/Per Phase/Per Milestone} |
| Saved as Defaults | {Yes/No} |
@@ -209,7 +235,7 @@ Quick commands:
<success_criteria>
- [ ] Current config read
- [ ] User presented with 7 settings (profile + 5 workflow toggles + git branching)
- [ ] User presented with 9 settings (profile + 7 workflow toggles + git branching)
- [ ] Config updated with model_profile, workflow, and git sections
- [ ] User offered to save as global defaults (~/.gsd/defaults.json)
- [ ] Changes confirmed to user

View File

@@ -0,0 +1,290 @@
<purpose>
Generate a UI design contract (UI-SPEC.md) for frontend phases. Orchestrates gsd-ui-researcher and gsd-ui-checker with a revision loop. Inserts between discuss-phase and plan-phase in the lifecycle.
UI-SPEC.md locks spacing, typography, color, copywriting, and design system decisions before the planner creates tasks. This prevents design debt caused by ad-hoc styling decisions during execution.
</purpose>
<required_reading>
@~/.claude/get-shit-done/references/ui-brand.md
</required_reading>
<process>
## 1. Initialize
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init plan-phase "$PHASE")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
Parse JSON for: `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `padded_phase`, `has_context`, `has_research`, `commit_docs`.
**File paths:** `state_path`, `roadmap_path`, `requirements_path`, `context_path`, `research_path`.
Resolve UI agent models:
```bash
UI_RESEARCHER_MODEL=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" resolve-model gsd-ui-researcher --raw)
UI_CHECKER_MODEL=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" resolve-model gsd-ui-checker --raw)
```
Check config:
```bash
UI_ENABLED=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.ui_phase 2>/dev/null || echo "true")
```
**If `UI_ENABLED` is `false`:**
```
UI phase is disabled in config. Enable via /gsd:settings.
```
Exit workflow.
**If `planning_exists` is false:** Error — run `/gsd:new-project` first.
## 2. Parse and Validate Phase
Extract phase number from $ARGUMENTS. If not provided, detect next unplanned phase.
```bash
PHASE_INFO=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "${PHASE}")
```
**If `found` is false:** Error with available phases.
## 3. Check Prerequisites
**If `has_context` is false:**
```
No CONTEXT.md found for Phase {N}.
Recommended: run /gsd:discuss-phase {N} first to capture design preferences.
Continuing without user decisions — UI researcher will ask all questions.
```
Continue (non-blocking).
**If `has_research` is false:**
```
No RESEARCH.md found for Phase {N}.
Note: stack decisions (component library, styling approach) will be asked during UI research.
```
Continue (non-blocking).
## 4. Check Existing UI-SPEC
```bash
UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
```
**If exists:** Use AskUserQuestion:
- header: "Existing UI-SPEC"
- question: "UI-SPEC.md already exists for Phase {N}. What would you like to do?"
- options:
- "Update — re-run researcher with existing as baseline"
- "View — display current UI-SPEC and exit"
- "Skip — keep current UI-SPEC, proceed to verification"
If "View": display file contents, exit.
If "Skip": proceed to step 7 (checker).
If "Update": continue to step 5.
## 5. Spawn gsd-ui-researcher
Display:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GSD ► UI DESIGN CONTRACT — PHASE {N}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
◆ Spawning UI researcher...
```
Build prompt:
```markdown
Read ~/.claude/agents/gsd-ui-researcher.md for instructions.
<objective>
Create UI design contract for Phase {phase_number}: {phase_name}
Answer: "What visual and interaction contracts does this phase need?"
</objective>
<files_to_read>
- {state_path} (Project State)
- {roadmap_path} (Roadmap)
- {requirements_path} (Requirements)
- {context_path} (USER DECISIONS from /gsd:discuss-phase)
- {research_path} (Technical Research — stack decisions)
</files_to_read>
<output>
Write to: {phase_dir}/{padded_phase}-UI-SPEC.md
Template: ~/.claude/get-shit-done/templates/UI-SPEC.md
</output>
<config>
commit_docs: {commit_docs}
phase_dir: {phase_dir}
padded_phase: {padded_phase}
</config>
```
Omit null file paths from `<files_to_read>`.
```
Task(
prompt=ui_research_prompt,
subagent_type="gsd-ui-researcher",
model="{UI_RESEARCHER_MODEL}",
description="UI Design Contract Phase {N}"
)
```
## 6. Handle Researcher Return
**If `## UI-SPEC COMPLETE`:**
Display confirmation. Continue to step 7.
**If `## UI-SPEC BLOCKED`:**
Display blocker details and options. Exit workflow.
## 7. Spawn gsd-ui-checker
Display:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GSD ► VERIFYING UI-SPEC
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
◆ Spawning UI checker...
```
Build prompt:
```markdown
Read ~/.claude/agents/gsd-ui-checker.md for instructions.
<objective>
Validate UI design contract for Phase {phase_number}: {phase_name}
Check all 6 dimensions. Return APPROVED or BLOCKED.
</objective>
<files_to_read>
- {phase_dir}/{padded_phase}-UI-SPEC.md (UI Design Contract — PRIMARY INPUT)
- {context_path} (USER DECISIONS — check compliance)
- {research_path} (Technical Research — check stack alignment)
</files_to_read>
<config>
ui_safety_gate: {ui_safety_gate config value}
</config>
```
```
Task(
prompt=ui_checker_prompt,
subagent_type="gsd-ui-checker",
model="{UI_CHECKER_MODEL}",
description="Verify UI-SPEC Phase {N}"
)
```
## 8. Handle Checker Return
**If `## UI-SPEC VERIFIED`:**
Display dimension results. Proceed to step 10.
**If `## ISSUES FOUND`:**
Display blocking issues. Proceed to step 9.
## 9. Revision Loop (Max 2 Iterations)
Track `revision_count` (starts at 0).
**If `revision_count` < 2:**
- Increment `revision_count`
- Re-spawn gsd-ui-researcher with revision context:
```markdown
<revision>
The UI checker found issues with the current UI-SPEC.md.
### Issues to Fix
{paste blocking issues from checker return}
Read the existing UI-SPEC.md, fix ONLY the listed issues, re-write the file.
Do NOT re-ask the user questions that are already answered.
</revision>
```
- After researcher returns → re-spawn checker (step 7)
**If `revision_count` >= 2:**
```
Max revision iterations reached. Remaining issues:
{list remaining issues}
Options:
1. Force approve — proceed with current UI-SPEC (FLAGs become accepted)
2. Edit manually — open UI-SPEC.md in editor, re-run /gsd:ui-phase
3. Abandon — exit without approving
```
Use AskUserQuestion for the choice.
## 10. Present Final Status
Display:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GSD ► UI-SPEC READY ✓
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
**Phase {N}: {Name}** — UI design contract approved
Dimensions: 6/6 passed
{If any FLAGs: "Recommendations: {N} (non-blocking)"}
───────────────────────────────────────────────────────────────
## ▶ Next Up
**Plan Phase {N}** — planner will use UI-SPEC.md as design context
`/gsd:plan-phase {N}`
<sub>/clear first → fresh context window</sub>
───────────────────────────────────────────────────────────────
```
## 11. Commit (if configured)
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(${padded_phase}): UI design contract" --files "${PHASE_DIR}/${PADDED_PHASE}-UI-SPEC.md"
```
## 12. Update State
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state record-session \
--stopped-at "Phase ${PHASE} UI-SPEC approved" \
--resume-file "${PHASE_DIR}/${PADDED_PHASE}-UI-SPEC.md"
```
</process>
<success_criteria>
- [ ] Config checked (exit if ui_phase disabled)
- [ ] Phase validated against roadmap
- [ ] Prerequisites checked (CONTEXT.md, RESEARCH.md — non-blocking warnings)
- [ ] Existing UI-SPEC handled (update/view/skip)
- [ ] gsd-ui-researcher spawned with correct context and file paths
- [ ] UI-SPEC.md created in correct location
- [ ] gsd-ui-checker spawned with UI-SPEC.md
- [ ] All 6 dimensions evaluated
- [ ] Revision loop if BLOCKED (max 2 iterations)
- [ ] Final status displayed with next steps
- [ ] UI-SPEC.md committed (if commit_docs enabled)
- [ ] State updated
</success_criteria>

View File

@@ -0,0 +1,157 @@
<purpose>
Retroactive 6-pillar visual audit of implemented frontend code. Standalone command that works on any project — GSD-managed or not. Produces scored UI-REVIEW.md with actionable findings.
</purpose>
<required_reading>
@~/.claude/get-shit-done/references/ui-brand.md
</required_reading>
<process>
## 0. Initialize
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "${PHASE_ARG}")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
Parse: `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `padded_phase`, `commit_docs`.
```bash
UI_AUDITOR_MODEL=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" resolve-model gsd-ui-auditor --raw)
```
Display banner:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GSD ► UI AUDIT — PHASE {N}: {name}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
## 1. Detect Input State
```bash
SUMMARY_FILES=$(ls "${PHASE_DIR}"/*-SUMMARY.md 2>/dev/null)
UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
UI_REVIEW_FILE=$(ls "${PHASE_DIR}"/*-UI-REVIEW.md 2>/dev/null | head -1)
```
**If `SUMMARY_FILES` empty:** Exit — "Phase {N} not executed. Run /gsd:execute-phase {N} first."
**If `UI_REVIEW_FILE` non-empty:** Use AskUserQuestion:
- header: "Existing UI Review"
- question: "UI-REVIEW.md already exists for Phase {N}."
- options:
- "Re-audit — run fresh audit"
- "View — display current review and exit"
If "View": display file, exit.
If "Re-audit": continue.
## 2. Gather Context Paths
Build file list for auditor:
- All SUMMARY.md files in phase dir
- All PLAN.md files in phase dir
- UI-SPEC.md (if exists — audit baseline)
- CONTEXT.md (if exists — locked decisions)
## 3. Spawn gsd-ui-auditor
```
◆ Spawning UI auditor...
```
Build prompt:
```markdown
Read ~/.claude/agents/gsd-ui-auditor.md for instructions.
<objective>
Conduct 6-pillar visual audit of Phase {phase_number}: {phase_name}
{If UI-SPEC exists: "Audit against UI-SPEC.md design contract."}
{If no UI-SPEC: "Audit against abstract 6-pillar standards."}
</objective>
<files_to_read>
- {summary_paths} (Execution summaries)
- {plan_paths} (Execution plans — what was intended)
- {ui_spec_path} (UI Design Contract — audit baseline, if exists)
- {context_path} (User decisions, if exists)
</files_to_read>
<config>
phase_dir: {phase_dir}
padded_phase: {padded_phase}
</config>
```
Omit null file paths.
```
Task(
prompt=ui_audit_prompt,
subagent_type="gsd-ui-auditor",
model="{UI_AUDITOR_MODEL}",
description="UI Audit Phase {N}"
)
```
## 4. Handle Return
**If `## UI REVIEW COMPLETE`:**
Display score summary:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GSD ► UI AUDIT COMPLETE ✓
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
**Phase {N}: {Name}** — Overall: {score}/24
| Pillar | Score |
|--------|-------|
| Copywriting | {N}/4 |
| Visuals | {N}/4 |
| Color | {N}/4 |
| Typography | {N}/4 |
| Spacing | {N}/4 |
| Experience Design | {N}/4 |
Top fixes:
1. {fix}
2. {fix}
3. {fix}
Full review: {path to UI-REVIEW.md}
───────────────────────────────────────────────────────────────
## ▶ Next
- `/gsd:verify-work {N}` — UAT testing
- `/gsd:plan-phase {N+1}` — plan next phase
<sub>/clear first → fresh context window</sub>
───────────────────────────────────────────────────────────────
```
## 5. Commit (if configured)
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(${padded_phase}): UI audit review" --files "${PHASE_DIR}/${PADDED_PHASE}-UI-REVIEW.md"
```
</process>
<success_criteria>
- [ ] Phase validated
- [ ] SUMMARY.md files found (execution completed)
- [ ] Existing review handled (re-audit/view)
- [ ] gsd-ui-auditor spawned with correct context
- [ ] UI-REVIEW.md created in phase directory
- [ ] Score summary displayed to user
- [ ] Next steps presented
</success_criteria>

View File

@@ -333,6 +333,7 @@ All tests passed. Ready to continue.
- `/gsd:plan-phase {next}` — Plan next phase
- `/gsd:execute-phase {next}` — Execute next phase
- `/gsd:ui-review {phase}` — visual quality audit (if frontend files were modified)
```
</step>