Skip to content

Commit acaf3e7

Browse files
committed
feat: add evaluation scenarios and SVG validation script (Phase 2)
Follows Anthropic's Leonxlnx#1 skill development recommendation: evaluation-driven development. - reference/EVALUATIONS.md: 8 test scenarios spanning all archetypes (Abstract Mark, Wordmark, Geometric Monogram, Pictorial Reduction, Combination Mark, Negative Space, Emblem, Revision Round) with expected archetype selection, quality signals, and common failure modes - scripts/validate-svg.sh: automated validation checking banned elements, accessibility attributes, viewBox, coordinate precision, path closure, file size, shape count, unused defs, editor metadata - SKILL.md step 9 now references the validation script https://claude.ai/code/session_01TybV7LMWVrnzVqtUqwoUvM
1 parent 006fad3 commit acaf3e7

File tree

3 files changed

+312
-1
lines changed

3 files changed

+312
-1
lines changed

svg-logo-skill/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ Always infer (never ask): archetype, color palette, typography style, shape lang
118118

119119
**8. [SCALE VERIFICATION]** Mentally verify at 16px, 32px, 64px, 512px. Test on white, black, and mid-gray backgrounds. Squint test for distinctive mass distribution.
120120

121-
**9. [CODE CLEANUP]** Verify: integer coordinates, paths close with Z, no redundant attributes, viewBox set, title/desc/ARIA present, file size within budget.
121+
**9. [CODE CLEANUP]** Verify: integer coordinates, paths close with Z, no redundant attributes, viewBox set, title/desc/ARIA present, file size within budget. Run `scripts/validate-svg.sh` on the output to catch banned elements, missing accessibility, coordinate precision, and size budget violations.
122122

123123
**10. [VARIANT OUTPUT]** Provide:
124124
* Full color + monochrome dark (`currentColor`) + monochrome light
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Evaluation Scenarios
2+
3+
Test the skill against these 8 scenarios. Each covers a different archetype, industry, and difficulty level. After generating, run `scripts/validate-svg.sh` on the output, then check the quality signals manually.
4+
5+
---
6+
7+
## Scenario 1: Abstract Mark — Tech SaaS
8+
**Prompt:** "Create a logo for Nexus, a cloud infrastructure platform for developers."
9+
**Expected archetype:** Abstract Mark or Geometric Monogram
10+
**Quality signals:**
11+
- No literal cloud shape (banned pattern)
12+
- No code brackets `</>` (banned pattern)
13+
- Color differentiation from blue (competitive landscape is blue-heavy)
14+
- ≤ 5 shapes, works at 16px
15+
**Common failures:** Generic cloud icon, circuit board traces, purple-blue gradient
16+
17+
## Scenario 2: Wordmark — Consumer Brand
18+
**Prompt:** "Design a logo for Oat, a plant-based milk company. The brand should feel warm, natural, and approachable."
19+
**Expected archetype:** Wordmark (3-letter name, consumer brand)
20+
**Quality signals:**
21+
- All text as `<path>`, no `<text>` elements
22+
- Humanist or rounded sans-serif voice (warm adjectives)
23+
- At least one distinctive letterform modification
24+
- Warm color palette, not cool/corporate
25+
**Common failures:** Generic leaf/sprout icon, `<text>` element instead of paths, all-green cliché
26+
27+
## Scenario 3: Geometric Monogram — Developer Tool
28+
**Prompt:** "Logo for KV, a key-value database for real-time applications."
29+
**Expected archetype:** Geometric Monogram (2-letter name, dev tool)
30+
**Quality signals:**
31+
- K and V constructed from geometric primitives
32+
- Letters integrated into geometry (not just placed inside a shape)
33+
- Monospace or geometric sans voice
34+
- Works as a 16px favicon
35+
**Common failures:** Garbled letterforms, code brackets, generic database cylinder
36+
37+
## Scenario 4: Pictorial Reduction — Animal Brand
38+
**Prompt:** "Create a logo for Finch, a personal finance app. It should feel trustworthy but not corporate."
39+
**Expected archetype:** Pictorial Reduction (brand name IS a bird)
40+
**Quality signals:**
41+
- Bird reduced to ≤ 5 shapes, recognizable from silhouette
42+
- NOT a literal detailed bird illustration
43+
- Warmth balanced with trust (rounded forms + enclosed shapes)
44+
- Differentiated from fintech blue
45+
**Common failures:** Over-detailed bird (clip-art), generic shield, too many shapes
46+
47+
## Scenario 5: Combination Mark — New Brand
48+
**Prompt:** "Design a logo for Bloom Health, a telehealth platform for mental wellness. We want it to feel calming and modern."
49+
**Expected archetype:** Combination Mark (unfamiliar brand, needs name recognition)
50+
**Quality signals:**
51+
- Icon and wordmark work independently
52+
- Separate `<g id="mark">` and `<g id="wordmark">` groups
53+
- No literal medical symbols (cross, caduceus, heart — all banned)
54+
- Calming palette (teal, muted green, warm neutrals — not clinical blue)
55+
- Mark-to-wordmark ratio follows 1:1 to 1.618:1 rule
56+
**Common failures:** Generic leaf/flower, literal heart shape, purple-blue gradient
57+
58+
## Scenario 6: Negative Space — Clever Mark
59+
**Prompt:** "Create a logo for Arrow Logistics. We want something clever and memorable."
60+
**Expected archetype:** Negative Space Mark (user asked for "clever")
61+
**Quality signals:**
62+
- An arrow or directional element formed by negative space (NOT drawn as a positive shape)
63+
- The positive shapes serve dual purpose (foreground form + background meaning)
64+
- Works when colors are inverted
65+
- Primary reading dominates at small sizes
66+
**Common failures:** Drawing the arrow explicitly (defeats the purpose), misaligned vertices destroying the illusion, too-subtle negative space
67+
68+
## Scenario 7: Emblem — Heritage Brand
69+
**Prompt:** "Design a logo for Ironwood Brewing Co., established 2008. We want a badge-style mark that feels authentic and handcrafted."
70+
**Expected archetype:** Emblem (user explicitly requests badge style)
71+
**Quality signals:**
72+
- Container shape (circle, rounded rectangle) with interior elements
73+
- ≤ 7 shapes total
74+
- Simplified interior (no ornamental flourishes)
75+
- Icon-only variant provided for favicon (text inside emblem vanishes at small sizes)
76+
- No generic shield (banned)
77+
**Common failures:** Too much interior detail, curved text failing, no favicon variant, generic wheat/hops illustration
78+
79+
## Scenario 8: Revision Round — Feedback Translation
80+
**Prompt (initial):** "Create a logo for Vertex, an AI research lab."
81+
**Follow-up feedback:** "This feels too corporate. Can you make it more approachable but keep it smart?"
82+
**Quality signals for revision:**
83+
- Shapes soften (more rounded corners, organic curves)
84+
- Colors warm up (shift from navy/charcoal toward warmer tones)
85+
- Typography shifts toward lowercase or humanist sans
86+
- The core concept is preserved (not a complete pivot)
87+
- Constraint accumulation: any previously approved elements stay locked
88+
**Common failures:** Complete concept pivot instead of parameter refinement, making it too playful (overcorrecting), losing the "smart" feel
89+
90+
---
91+
92+
## Automated Validation Checklist
93+
After each scenario, run `scripts/validate-svg.sh <output.svg>` to verify:
94+
- [ ] No banned SVG elements
95+
- [ ] Accessibility attributes present
96+
- [ ] `viewBox` set, no hardcoded dimensions
97+
- [ ] Integer-first coordinates
98+
- [ ] All paths closed with `Z`
99+
- [ ] File size within budget
100+
- [ ] Shape count within budget
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
#!/usr/bin/env bash
2+
# SVG Logo Validation Script
3+
# Checks generated SVG against the skill's technical requirements.
4+
# Usage: ./validate-svg.sh <path-to-svg>
5+
6+
set -euo pipefail
7+
8+
if [[ $# -lt 1 ]]; then
9+
echo "Usage: $0 <svg-file>"
10+
exit 1
11+
fi
12+
13+
SVG_FILE="$1"
14+
if [[ ! -f "$SVG_FILE" ]]; then
15+
echo "Error: File not found: $SVG_FILE"
16+
exit 1
17+
fi
18+
19+
PASS=0
20+
FAIL=0
21+
WARN=0
22+
23+
pass() { echo " ✓ PASS: $1"; ((PASS++)); }
24+
fail() { echo " ✗ FAIL: $1"; ((FAIL++)); }
25+
warn() { echo " ⚠ WARN: $1"; ((WARN++)); }
26+
27+
echo "=== SVG Logo Validation: $SVG_FILE ==="
28+
echo ""
29+
30+
# --- Banned Elements ---
31+
echo "Banned Elements:"
32+
for elem in "<text" "<tspan" "<filter" "<feGaussianBlur" "<feDropShadow" "<image" "<style" "<script" "<animate" "<foreignObject"; do
33+
if grep -q "$elem" "$SVG_FILE"; then
34+
fail "Contains banned element: $elem"
35+
fi
36+
done
37+
# Check for base64 embedded data
38+
if grep -q "base64," "$SVG_FILE"; then
39+
fail "Contains embedded base64 data"
40+
fi
41+
# Check for external use references
42+
if grep -qE 'href="https?://' "$SVG_FILE"; then
43+
fail "Contains external URL reference"
44+
fi
45+
if [[ $FAIL -eq 0 ]]; then
46+
pass "No banned elements found"
47+
fi
48+
49+
echo ""
50+
51+
# --- Accessibility ---
52+
echo "Accessibility:"
53+
if grep -q "<title" "$SVG_FILE"; then
54+
pass "<title> element present"
55+
else
56+
fail "Missing <title> element"
57+
fi
58+
59+
if grep -q "<desc" "$SVG_FILE"; then
60+
pass "<desc> element present"
61+
else
62+
fail "Missing <desc> element"
63+
fi
64+
65+
if grep -q 'role="img"' "$SVG_FILE"; then
66+
pass 'role="img" present'
67+
else
68+
fail 'Missing role="img" on root <svg>'
69+
fi
70+
71+
if grep -q "aria-labelledby" "$SVG_FILE"; then
72+
pass "aria-labelledby present"
73+
else
74+
fail "Missing aria-labelledby on root <svg>"
75+
fi
76+
77+
echo ""
78+
79+
# --- ViewBox & Dimensions ---
80+
echo "ViewBox & Dimensions:"
81+
if grep -q "viewBox" "$SVG_FILE"; then
82+
pass "viewBox attribute present"
83+
else
84+
fail "Missing viewBox attribute"
85+
fi
86+
87+
# Check for hardcoded pixel dimensions (width="123px" or height="123px")
88+
if grep -qE '(width|height)="[0-9]+(px)?"' "$SVG_FILE" | head -1 && grep -qE '<svg[^>]*(width|height)="[0-9]+(px)?"' "$SVG_FILE"; then
89+
warn "Root <svg> has hardcoded width/height — prefer viewBox-only for scalability"
90+
fi
91+
92+
if grep -q 'xmlns="http://www.w3.org/2000/svg"' "$SVG_FILE"; then
93+
pass "xmlns namespace present"
94+
else
95+
fail "Missing xmlns namespace"
96+
fi
97+
98+
echo ""
99+
100+
# --- Coordinate Precision ---
101+
echo "Coordinate Precision:"
102+
# Find coordinates with more than 2 decimal places in path data
103+
EXCESS_DECIMALS=$(grep -oE '[0-9]+\.[0-9]{3,}' "$SVG_FILE" | wc -l)
104+
if [[ $EXCESS_DECIMALS -gt 0 ]]; then
105+
fail "Found $EXCESS_DECIMALS coordinates with >2 decimal places"
106+
else
107+
pass "All coordinates within 2 decimal places"
108+
fi
109+
110+
echo ""
111+
112+
# --- Path Closure ---
113+
echo "Path Closure:"
114+
# Extract all d="..." attributes and check each subpath ends with Z/z
115+
# This is a heuristic: count M/m commands vs Z/z commands in path data
116+
M_COUNT=$(grep -oE '[Mm]' "$SVG_FILE" | wc -l)
117+
Z_COUNT=$(grep -oE '[Zz]' "$SVG_FILE" | wc -l)
118+
if [[ $M_COUNT -gt 0 && $Z_COUNT -lt $M_COUNT ]]; then
119+
warn "Found $M_COUNT path subpaths but only $Z_COUNT closures (Z) — some paths may be unclosed"
120+
else
121+
pass "Path closure count looks correct ($M_COUNT subpaths, $Z_COUNT closures)"
122+
fi
123+
124+
echo ""
125+
126+
# --- File Size ---
127+
echo "File Size:"
128+
FILE_SIZE=$(wc -c < "$SVG_FILE")
129+
if [[ $FILE_SIZE -gt 5120 ]]; then
130+
fail "File size ${FILE_SIZE} bytes exceeds 5KB wordmark budget"
131+
elif [[ $FILE_SIZE -gt 3072 ]]; then
132+
warn "File size ${FILE_SIZE} bytes — OK for wordmarks, over budget for simple marks (<1.5KB) and moderate marks (<3KB)"
133+
elif [[ $FILE_SIZE -gt 1536 ]]; then
134+
warn "File size ${FILE_SIZE} bytes — OK for moderate marks, over budget for simple marks (<1.5KB)"
135+
else
136+
pass "File size ${FILE_SIZE} bytes — within simple mark budget"
137+
fi
138+
139+
echo ""
140+
141+
# --- Shape Count ---
142+
echo "Shape Count:"
143+
# Count visible shape elements (rect, circle, ellipse, polygon, polyline, line, path)
144+
SHAPE_COUNT=$(grep -coE '<(rect|circle|ellipse|polygon|polyline|line|path)[\s/>]' "$SVG_FILE" || echo 0)
145+
# Subtract shapes inside <defs> (they're templates, not visible)
146+
DEFS_SHAPES=$(sed -n '/<defs>/,/<\/defs>/p' "$SVG_FILE" | grep -coE '<(rect|circle|ellipse|polygon|polyline|line|path)[\s/>]' || echo 0)
147+
VISIBLE_SHAPES=$((SHAPE_COUNT - DEFS_SHAPES))
148+
# Add <use> elements (they instantiate shapes)
149+
USE_COUNT=$(grep -coE '<use[\s/>]' "$SVG_FILE" || echo 0)
150+
TOTAL=$((VISIBLE_SHAPES + USE_COUNT))
151+
152+
if [[ $TOTAL -gt 7 ]]; then
153+
warn "Shape count: $TOTAL visible elements (budget: ≤7 for marks, wordmark letters exempt)"
154+
else
155+
pass "Shape count: $TOTAL visible elements (within budget)"
156+
fi
157+
158+
echo ""
159+
160+
# --- Unused Defs ---
161+
echo "Unused Defs:"
162+
if grep -q "<defs>" "$SVG_FILE"; then
163+
# Extract IDs defined in defs
164+
DEFS_IDS=$(sed -n '/<defs>/,/<\/defs>/p' "$SVG_FILE" | grep -oE 'id="[^"]*"' | sed 's/id="//;s/"//' || true)
165+
UNUSED=0
166+
for id in $DEFS_IDS; do
167+
# Check if this ID is referenced elsewhere (href, url(), aria-labelledby, etc.)
168+
REF_COUNT=$(grep -c "$id" "$SVG_FILE" || echo 0)
169+
if [[ $REF_COUNT -le 1 ]]; then
170+
warn "Potentially unused def: id=\"$id\""
171+
((UNUSED++))
172+
fi
173+
done
174+
if [[ $UNUSED -eq 0 ]]; then
175+
pass "All defs appear to be referenced"
176+
fi
177+
else
178+
pass "No <defs> block (nothing to check)"
179+
fi
180+
181+
echo ""
182+
183+
# --- Editor Metadata ---
184+
echo "Editor Metadata:"
185+
METADATA_FOUND=0
186+
for pattern in "data-name" "xml:space" "inkscape:" "sodipodi:" "illustrator" "sketch:"; do
187+
if grep -qi "$pattern" "$SVG_FILE"; then
188+
fail "Contains editor metadata: $pattern"
189+
((METADATA_FOUND++))
190+
fi
191+
done
192+
if [[ $METADATA_FOUND -eq 0 ]]; then
193+
pass "No editor metadata found"
194+
fi
195+
196+
echo ""
197+
198+
# --- Summary ---
199+
echo "=== Summary ==="
200+
echo " Passed: $PASS"
201+
echo " Failed: $FAIL"
202+
echo " Warnings: $WARN"
203+
echo ""
204+
205+
if [[ $FAIL -gt 0 ]]; then
206+
echo "RESULT: FAIL ($FAIL issues must be fixed)"
207+
exit 1
208+
else
209+
echo "RESULT: PASS (with $WARN warnings)"
210+
exit 0
211+
fi

0 commit comments

Comments
 (0)