Two issues fixed across personal skills:
1. Five skills had frontmatter > 1024 chars (spec limit per agentskills.io):
- client-handover: 1920 → 924
- doc: 1390 → 734
- seo: 1378 → 885
- geo: 1189 → 734
- validate: 1050 → 742
All now compliant.
2. Three orchestrators had workflow-summary descriptions that create
"shortcut" risk per writing-skills CSO (Claude may follow the
description instead of reading the full skill body, skipping steps):
- ship-feature: "design → plan → implement (TDD) → review → finish"
→ "Use when shipping a feature end-to-end — needs… (9-step pipeline)"
- init-project: "interview → design → scaffold → implement (TDD)"
→ "Use when initializing a brand-new project from scratch — needs…"
- onboard: "detect archetype, install claude-config, run full audit…"
→ "Use when bringing an existing repo into the framework — needs…"
Descriptions now follow "Use when [triggers]…" pattern. Workflow detail
preserved in skill body where it belongs. Triggers consolidated and
trimmed of duplicates.
Co-Authored-By: Claude <noreply@anthropic.com>
13 KiB
/validate — web standards audit (W3C + WCAG)
This skill orchestrates a narrow-scope standards audit :
- W3C HTML validity — validator.nu API (FULL) or
html-validate/vnu.jar(LOCAL) or static fallback. - W3C CSS validity — jigsaw.w3.org/css-validator API (FULL) or
stylelint/css-tree(LOCAL) or static fallback. - WCAG 2.1 accessibility —
pa11y/@axe-core/cli/ WAVE API (FULL) or axe against built HTML (LOCAL) or static checklist.
Scope boundary :
- In : HTML syntactic validity (DOCTYPE, required attrs, tag nesting, ID uniqueness, heading hierarchy), CSS syntactic validity (parsing errors, unknown properties, at-rule misuse), WCAG 2.1 A / AA / AAA violations (ARIA, landmarks, contrast, keyboard, SR affordances, alt text).
- Out : meta tags (title/description/OG), JSON-LD / Schema.org, sitemap.xml, robots.txt, llms.txt, security headers (HSTS/CSP), cookie flags, Core Web Vitals, image compression, hreflang, i18n routing, generic code linting (ESLint, Prettier), TypeScript type errors.
If a finding appears in an out-of-scope area (e.g. missing meta
description), the agent drops it silently — /validate stays focused.
Relation to other skills
/onboardruns an initial a11y audit at project setup (axe or static checklist →.onboard-audit/a11y.md)./validateis the on-demand equivalent, re-runnable anytime against the current codebase, and also covers HTML/CSS validity (which/onboarddoes not)./hardenaudits security posture (headers, TLS, redirects)./validateaudits conformance. They share no findings./seoand/geoaudit indexability. They may flag the same HTML features (alt attrs, heading structure) but from a ranking perspective./validateflags from a standards perspective (WCAG SC number, W3C rule id). Findings may overlap — both reports are still valid.
STEP 0 — Collect context
Parse arguments
- If
$ARGUMENTScontainshttps?://<url>→TARGET_URL. - Extract
DOMAINfromTARGET_URL:DOMAIN=${TARGET_URL#http*://}; DOMAIN=${DOMAIN%%/*}. - If
$ARGUMENTScontains--fix→MODE=fix. ElseMODE=audit. - If
--local→DEPTH=LOCAL. If--full→DEPTH=FULL. - If URL present and no depth flag → default
DEPTH=FULL. - If no URL and no depth flag → default
DEPTH=LOCAL. - If
--no-external→EXTERNAL=off. Elseon. EXTERNALauto-off in LOCAL mode (no URL to scan remotely).
Detect HTML / CSS files
HTML_COUNT=$(find . -name "*.html" \
-not -path "*/node_modules/*" \
-not -path "*/dist/*" \
-not -path "*/.next/*" \
-not -path "*/.validate-cache/*" 2>/dev/null | wc -l)
CSS_COUNT=$(find . -name "*.css" \
-not -path "*/node_modules/*" \
-not -path "*/dist/*" \
-not -path "*/.next/*" 2>/dev/null | wc -l)
If both counts are 0 and no URL provided → abort with :
⚠️ No HTML or CSS files found and no URL provided. /validate needs
either local files or a live URL. Re-run with --full <url>.
Detect framework
FRAMEWORK="static"
[ -f astro.config.mjs ] || [ -f astro.config.ts ] && FRAMEWORK="astro"
[ -f next.config.js ] || [ -f next.config.mjs ] || [ -f next.config.ts ] && FRAMEWORK="next"
[ -f vite.config.js ] || [ -f vite.config.ts ] && FRAMEWORK="vite"
[ -f svelte.config.js ] && FRAMEWORK="svelte"
[ -f nuxt.config.js ] || [ -f nuxt.config.ts ] && FRAMEWORK="nuxt"
[ -f vue.config.js ] && FRAMEWORK="vue"
For JS frameworks, HTML validity must target built output. Check for build dir :
BUILD_DIR=""
for d in dist _site build out public; do
[ -d "$d" ] && BUILD_DIR="$d" && break
done
If framework is JS-based and BUILD_DIR is empty, warn :
⚠️ Framework detected : <name>. No build output found.
HTML validity on JSX/TSX source is not meaningful.
Options :
1. Run `npm run build` then re-run /validate
2. Use --full <url> to audit production
3. Continue with partial LOCAL audit (CSS + static WCAG only)
Detect LOCAL tooling
HAS_HTML_VALIDATE=$(npx --no-install html-validate --version >/dev/null 2>&1 && echo yes || echo no)
HAS_STYLELINT=$(npx --no-install stylelint --version >/dev/null 2>&1 && echo yes || echo no)
HAS_AXE=$(npx --no-install @axe-core/cli --version >/dev/null 2>&1 && echo yes || echo no)
HAS_PA11Y=$(npx --no-install pa11y --version >/dev/null 2>&1 && echo yes || echo no)
HAS_VNU=$([ -f /usr/share/vnu/vnu.jar ] || [ -f /opt/vnu/vnu.jar ] && echo yes || echo no)
Missing tools are NOT blockers — agent falls back to remote APIs (FULL) or static checks.
Display collected context
VALIDATE — context
URL : <url or — (local mode)>
Domain : <domain or —>
Depth : LOCAL | FULL
Mode : audit | fix
External : on | off (auto-off in LOCAL)
HTML files : <N>
CSS files : <N>
Framework : <astro | next | vite | svelte | nuxt | vue | static>
Build dir : <dist/ | _site/ | ... | — none found>
Local tools : html-validate=<y/n>, stylelint=<y/n>, axe=<y/n>, pa11y=<y/n>, vnu=<y/n>
If MODE=fix, warn :
⚠️ Fixes proposés comme diffs. Appliqués seulement après confirmation.
STEP 1 — Dispatch validator-analyzer
Spawn a single validator-analyzer subagent with explicit scope and
collected context :
Agent(
subagent_type="validator-analyzer",
description="validate — W3C HTML + CSS + WCAG audit",
prompt="""
Dispatched from /validate. STRICT SCOPE — W3C HTML validity + W3C
CSS validity + WCAG 2.1 accessibility ONLY.
CONTEXT:
TARGET_URL : <url or "none — LOCAL mode">
DOMAIN : <domain or —>
DEPTH : <LOCAL | FULL>
MODE : <audit | fix>
EXTERNAL : <on | off>
HTML_FILES : <count>
CSS_FILES : <count>
FRAMEWORK : <name>
BUILD_DIR : <path or "none">
LOCAL_TOOLS : html-validate=<y/n>, stylelint=<y/n>, axe=<y/n>, pa11y=<y/n>, vnu=<y/n>
Execute your spec at $HOME/.claude/agents/validator-analyzer.md
starting at STEP 1 (skip STEP 0 — context is above).
OUT OF SCOPE — DROP silently if encountered :
- meta tags (title/description/OG/Twitter/canonical)
- JSON-LD / Schema.org / microdata
- sitemap.xml, robots.txt, llms.txt
- AI crawler directives
- security headers (HSTS/CSP/X-Frame-Options/cookie flags)
- Core Web Vitals, perf budgets
- hreflang, i18n routing
- image compression, video formats
- generic code linting (ESLint, Prettier, TS errors)
Mode behavior :
- MODE=audit : NO file modifications. Report-only. Propose fixes
as diffs in the report (```diff blocks), do NOT apply.
- MODE=fix : Report issues, then produce Fix bundle (§5) with
concrete diffs for auto-fixable items. STOP and emit
"READY TO APPLY — awaiting dispatcher confirmation" at the end
of §5. Do NOT apply any Edit/Write — the dispatcher handles STEP 3.
Output: write <PROJECT_ROOT>/.claude/audits/VALIDATE.md (run `mkdir -p .claude/audits` first) per the structure in your
spec (sections 0-8, score XX/100).
"""
)
STEP 2 — Verify output
test -s .claude/audits/VALIDATE.md && wc -l .claude/audits/VALIDATE.md || echo "MISSING .claude/audits/VALIDATE.md"
If missing or empty :
⚠️ validator-analyzer did not produce .claude/audits/VALIDATE.md. Options :
A) Retry with same scope
B) Downgrade to LOCAL and retry (if FULL failed on network)
C) Abort
Extract the score and critical-alert count from .claude/audits/VALIDATE.md for the
console summary :
grep -oE '\*\*Score\*\*\s+:\s+[0-9]+ / 100' .claude/audits/VALIDATE.md | head -1
grep -c '^### \[Critique\]' .claude/audits/VALIDATE.md
STEP 3 — Apply fixes (MODE=fix only)
Skip this step if MODE=audit.
If .claude/audits/VALIDATE.md ends with READY TO APPLY — awaiting dispatcher confirmation :
- Parse the
## 5. Fix bundlesection. - Group by file. For each group, show the combined diff to the user.
- Ask :
VALIDATE — fix bundle ready
Files to modify (N) :
- src/Layout.astro (3 fixes : lang attr, alt="", heading renumber)
- src/styles/main.css (1 fix : invalid property removed)
- src/pages/contact.html (2 fixes : unclosed tag, duplicate id)
Critical : X | Haute : Y | Moyenne : Z | Basse : W
Options :
A) Apply all
B) Review each diff before applying
C) Apply only Critique + Haute
D) Abort — keep .claude/audits/VALIDATE.md as audit report
- On
A: apply each bundle viaEdit(targetedold_string/new_string). Never useWriteon shared templates (risk of overwriting /seo or /geo content — meta tags, JSON-LD). - On
B: for each diff, show and ask yes/no/skip. - On
C: filter to Critique + Haute, then behave asA. - On
D: stop, leave.claude/audits/VALIDATE.mduntouched.
After applying, append a ## 8. Changes applied section with
commit-ready summary lines :
## 8. Changes applied
Date : <ISO-8601>
Files modified : <N>
Fixes applied : <N>
### src/Layout.astro
- [Haute][HTML] Added `lang="en"` to `<html>` (WCAG 3.1.1, W3C required attr)
- [Haute][WCAG AA] Added `alt=""` to decorative icon at line 42
- [Moyenne][HTML] Renumbered h3 → h2 (heading hierarchy, line 67)
### src/styles/main.css
- [Moyenne][CSS] Removed invalid property `bakground` → `background` at line 23
Verification :
- Re-run /validate → expected score bump <before> → <after>
- Tests to run : a11y regression (pa11y-ci), visual snapshot
Never apply fixes without explicit confirmation.
Never use --no-verify on git hooks.
STEP 4 — Console summary
VALIDATE AUDIT COMPLETE
URL : <url or static>
Depth : LOCAL | FULL
Mode : audit | fix
Score : XX / 100 (<before> → <after> if fix applied)
Report : .claude/audits/VALIDATE.md
BREAKDOWN :
W3C HTML : <N errors / M warnings>
W3C CSS : <N errors / M warnings>
WCAG 2.1 : <N A> / <M AA> / <K AAA> violations, <L incomplete>
TOP 3 ACTIONS (by severity × user impact) :
1. [Critique] <title> — <file:line>
2. [Haute] <title>
3. [Haute] <title>
NEXT STEPS :
• /validate <url> --fix → apply recommended fixes
• /validate <url> --full → re-run with live URL + remote APIs
• /validate --no-external → skip third-party APIs (faster, LOCAL-like)
• /harden / /seo / /geo → complementary audits (other scopes)
Install for better LOCAL coverage :
npm i -D html-validate stylelint @axe-core/cli pa11y
Rules
- Scope is non-negotiable. If you find yourself reporting meta
tags, sitemap, CSP, or JSON-LD, you drifted. Drop it.
/harden,/seo,/geoown those respectively. - Single agent dispatch. Only
validator-analyzer. No parallel fan-out. - Never apply fixes without user confirmation, even in
--fix. The fix mode prepares the bundle; the dispatcher confirms (A/B/C/D). - LOCAL vs FULL is about data sources, not scope. Both cover the same 3 axes. LOCAL may be degraded if local tools missing (agent falls back to static checks — flagged "STATIC MODE" in report).
- Framework awareness. For SPA/JS frameworks, validate built
output (
dist/,_site/,build/,out/), not JSX/TSX source. Warn if no build dir present. - Respect CLAUDE.md architecture rules. Public websites must ship WCAG 2.1 AA per France RGAA 4.1 when in scope. Flag AA violations as Haute, A violations as Critique.
- External validators are authoritative on live URLs. validator.nu and jigsaw are the W3C backends. If a local tool disagrees with them, trust the W3C backend; flag the divergence as a finding.
- One report file.
.claude/audits/VALIDATE.md. On re-run, move previous content to a## Historiquesection, do not overwrite silently. - Cache dir.
.validate-cache/(gitignored) stores raw tool outputs for debugging. Do not commit. - Conservative auto-fix. Only structural/syntactic fixes with no ambiguity. Content decisions (alt text, labels, contrast choices) always go to §6 User actions — never auto-applied.