` — refactor needed)
+- Heading hierarchy with ambiguous correction (multiple valid fixes)
+
+### Output
+
+At end of §5, emit verbatim :
+```
+READY TO APPLY — awaiting dispatcher confirmation
+```
+
+**Do NOT apply any Edit/Write.** Dispatcher handles STEP 3 of `/validate`.
+
+---
+
+## Rules
+
+- **Single agent, narrow scope.** W3C HTML + W3C CSS + WCAG 2.1 only.
+ Drop anything else (meta tags, JSON-LD, perf, security, generic linting).
+- **Degrade gracefully.** Missing tools → fall back to static checks.
+ Never fail hard. Always produce VALIDATE.md, even in degraded mode.
+- **Framework awareness.** For SPA/JS frameworks (Next/Astro/Vite/
+ SvelteKit/Nuxt), validate built output (`dist/`, `_site/`, `build/`,
+ `out/`), not JSX/TSX source. Note "Validated against built HTML at
+ `
`" in §0. If no build output found, warn user.
+- **Respect MODE.** `audit` = no modifications. `fix` = prepare bundle,
+ STOP, return control via `READY TO APPLY`.
+- **Cite evidence.** Every finding : `file:line` + tool output quote.
+ Empty findings or hand-waving = bug.
+- **One report.** `VALIDATE.md` at project root (or `docs/VALIDATE.md`
+ if convention exists). On re-run, move previous content to a
+ `## Historique` section — do not overwrite silently.
+- **External validators are authoritative.** If validator.nu disagrees
+ with `html-validate`, trust validator.nu. If jigsaw disagrees with
+ stylelint, trust jigsaw. Flag divergences as a separate finding
+ (config drift or tool version mismatch).
+- **WCAG level hierarchy.** Level A violations are Critique (blocks
+ users). Never downgrade. RGAA 4.1 (France) maps roughly to WCAG 2.1
+ AA — report both references when applicable.
+- **No auto-fix on content.** Never auto-generate alt text, labels, or
+ color choices. These go to §6 User actions.
diff --git a/skills/harden/SKILL.md b/skills/harden/SKILL.md
index d731e71..83c0e8b 100644
--- a/skills/harden/SKILL.md
+++ b/skills/harden/SKILL.md
@@ -352,7 +352,8 @@ Agent(
- Legal pages (mentions légales, CGV, privacy) — unless the issue is
a security-header gap on those pages, not their content
- Content quality, keyword density, readability
- - a11y / WCAG (owned by /onboard a11y dispatch)
+ - a11y / WCAG (owned by /validate — W3C + WCAG audit)
+ - W3C HTML / CSS syntactic validity (owned by /validate)
If you detect an out-of-scope issue, DROP IT silently. Do NOT mention
it even as a "note". Stay focused.
diff --git a/skills/seo/SKILL.md b/skills/seo/SKILL.md
index e74f303..6eea5e4 100644
--- a/skills/seo/SKILL.md
+++ b/skills/seo/SKILL.md
@@ -17,6 +17,8 @@ description: |
"AI search", "GEO", "llms.txt", "ChatGPT visibility", "Perplexity",
"Google AI Overview".
For GEO-only audit → use /geo.
+ For W3C HTML/CSS validity + WCAG a11y → use /validate (syntactic conformance,
+ not ranking signals).
For code-only bugs → use /bugfix. For feature work → use /feat.
argument-hint: optional keywords/scope, e.g. "local SEO plombier 91 94 77" or "SaaS B2B content strategy"
allowed-tools:
diff --git a/skills/validate/SKILL.md b/skills/validate/SKILL.md
new file mode 100644
index 0000000..834aca4
--- /dev/null
+++ b/skills/validate/SKILL.md
@@ -0,0 +1,378 @@
+---
+name: validate
+description: |
+ Web standards audit — W3C HTML validity (validator.nu), W3C CSS
+ validity (jigsaw.w3.org/css-validator), WCAG 2.1 accessibility
+ (axe-core, pa11y, WAVE API). Dedicated to syntactic and
+ accessibility conformance. Produces VALIDATE.md at project root.
+ Dispatches the validator-analyzer agent with a STRICT scope
+ filter — no meta/OG/JSON-LD/CWV/security-header noise.
+ Trigger: "validate", "validation", "w3c", "html validity",
+ "css validity", "wcag", "accessibility", "a11y audit", "axe",
+ "pa11y", "wave", "validator.w3.org", "nu validator",
+ "validation html", "accessibilité", "audit a11y", "audit wcag",
+ "normes w3c", "conformité web", "validité html css".
+ For security hardening (CSP, HSTS, 404) → use /harden.
+ For SEO/indexability (meta, sitemap, JSON-LD) → use /seo.
+ For AI engines (llms.txt, QAPage, entity SEO) → use /geo.
+argument-hint: [URL] [--fix] [--local|--full] [--no-external]
+allowed-tools:
+ - Read
+ - Edit
+ - Write
+ - Bash
+ - Grep
+ - Glob
+ - Agent
+ - WebFetch
+---
+
+# /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
+
+- `/onboard` runs an initial a11y audit at project setup (axe or
+ static checklist → `.onboard-audit/a11y.md`). `/validate` is the
+ **on-demand** equivalent, re-runnable anytime against the current
+ codebase, and also covers HTML/CSS validity (which `/onboard` does
+ not).
+- `/harden` audits security posture (headers, TLS, redirects).
+ `/validate` audits conformance. They share no findings.
+- `/seo` and `/geo` audit indexability. They may flag the same HTML
+ features (alt attrs, heading structure) but from a ranking
+ perspective. `/validate` flags 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 `$ARGUMENTS` contains `https?://` → `TARGET_URL`.
+- Extract `DOMAIN` from `TARGET_URL` : `DOMAIN=${TARGET_URL#http*://}; DOMAIN=${DOMAIN%%/*}`.
+- If `$ARGUMENTS` contains `--fix` → `MODE=fix`. Else `MODE=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`. Else `on`.
+- `EXTERNAL` auto-off in LOCAL mode (no URL to scan remotely).
+
+### Detect HTML / CSS files
+
+```bash
+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 .
+```
+
+### Detect framework
+
+```bash
+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 :
+
+```bash
+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 : . 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 to audit production
+ 3. Continue with partial LOCAL audit (CSS + static WCAG only)
+```
+
+### Detect LOCAL tooling
+
+```bash
+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 :
+Domain :
+Depth : LOCAL | FULL
+Mode : audit | fix
+External : on | off (auto-off in LOCAL)
+HTML files :
+CSS files :
+Framework :
+Build dir :
+Local tools : html-validate=, stylelint=, axe=, pa11y=, vnu=
+```
+
+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 :
+ DOMAIN :
+ DEPTH :
+ MODE :
+ EXTERNAL :
+ HTML_FILES :
+ CSS_FILES :
+ FRAMEWORK :
+ BUILD_DIR :
+ LOCAL_TOOLS : html-validate=, stylelint=, axe=, pa11y=, vnu=
+
+ 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 /VALIDATE.md per the structure in your
+ spec (sections 0-8, score XX/100).
+ """
+)
+```
+
+---
+
+## STEP 2 — Verify output
+
+```bash
+test -s VALIDATE.md && wc -l VALIDATE.md || echo "MISSING VALIDATE.md"
+```
+
+If missing or empty :
+```
+⚠️ validator-analyzer did not produce 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 VALIDATE.md for the
+console summary :
+
+```bash
+grep -oE '\*\*Score\*\*\s+:\s+[0-9]+ / 100' VALIDATE.md | head -1
+grep -c '^### \[Critique\]' VALIDATE.md
+```
+
+---
+
+## STEP 3 — Apply fixes (MODE=fix only)
+
+Skip this step if `MODE=audit`.
+
+If VALIDATE.md ends with `READY TO APPLY — awaiting dispatcher confirmation` :
+
+1. Parse the `## 5. Fix bundle` section.
+2. Group by file. For each group, show the combined diff to the user.
+3. 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 VALIDATE.md as audit report
+```
+
+4. On `A` : apply each bundle via `Edit` (targeted `old_string` /
+ `new_string`). Never use `Write` on shared templates (risk of
+ overwriting /seo or /geo content — meta tags, JSON-LD).
+5. On `B` : for each diff, show and ask yes/no/skip.
+6. On `C` : filter to Critique + Haute, then behave as `A`.
+7. On `D` : stop, leave VALIDATE.md untouched.
+
+After applying, append a `## 8. Changes applied` section with
+commit-ready summary lines :
+
+```markdown
+## 8. Changes applied
+
+Date :
+Files modified :
+Fixes applied :
+
+### src/Layout.astro
+- [Haute][HTML] Added `lang="en"` to `` (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 →
+- 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 :
+Depth : LOCAL | FULL
+Mode : audit | fix
+Score : XX / 100 ( → if fix applied)
+Report : VALIDATE.md
+
+BREAKDOWN :
+ W3C HTML :
+ W3C CSS :
+ WCAG 2.1 : / / violations,
+
+TOP 3 ACTIONS (by severity × user impact) :
+ 1. [Critique] —
+ 2. [Haute]
+ 3. [Haute]
+
+NEXT STEPS :
+ • /validate --fix → apply recommended fixes
+ • /validate --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`, `/geo` own 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.** `VALIDATE.md` at project root (or
+ `docs/VALIDATE.md` if that convention exists). On re-run, move
+ previous content to a `## Historique` section, 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.
diff --git a/tasks/TODO.md b/tasks/TODO.md
index 1a6e0b4..ec20258 100644
--- a/tasks/TODO.md
+++ b/tasks/TODO.md
@@ -48,3 +48,22 @@ Objectif : charger `## Typical pain points` + `Surface sécurité` de l'archéty
- [x] STEP 6 dispatch cso fallback → re-écrire prompt : universal checks + sections conditionnelles par category (web / embedded / library / cli / infra / data / desktop)
- [x] STEP 6 dispatch cso gstack ON → passer `--archetype --context-file .onboard-audit/archetype-context.md` dans args
- [ ] OUT-OF-SCOPE ce fix : étendre le pattern à analyze/code-clean/doc (déjà reçoivent `ARCHETYPE: `, juste pas le context-file). À faire dans un 2e passage si besoin.
+
+## /validate — nouveau skill W3C + WCAG (option A)
+Scope : W3C HTML validity (validator.nu API) + W3C CSS validity (jigsaw API) + WCAG a11y (axe-core CLI / pa11y / WAVE API / fallback statique). Même pattern que /harden (audit par défaut, --fix avec confirmation A/B/C/D). Rapport = VALIDATE.md racine. Complémentaire à /onboard (qui audite a11y au setup initial — /validate est l'outil on-demand réutilisable).
+
+Design décisions :
+- **Agent dédié** : `agents/validator-analyzer.md` (nouveau). Pas de réutilisation de seo-analyzer — scope différent (validité syntaxique vs indexabilité).
+- **Depth** : LOCAL (fichiers HTML/CSS statiques, tools npm locaux si dispo) | FULL (URL live + APIs distantes W3C/WAVE).
+- **External validators** : validator.nu/?out=json (HTML), jigsaw.w3.org/css-validator (CSS), WAVE API optionnelle (quota gratuit ~100/mois), axe-cli local, pa11y-cli local.
+- **Tools fallback order** : npm tools locaux → APIs distantes → agent général statique (cas onboard). Aucun install forcé.
+- **--fix conservateur** : `alt=""` sur images décoratives évidentes, `lang` sur ``, fermetures de tags manquantes, sauts de niveau heading renumérotés. PAS : labels forms, contraste couleurs, landmarks (demandent décision humaine).
+- **Out of scope** : meta tags/SEO → /seo ; JSON-LD → /geo ; security headers → /harden ; code linting générique (ESLint/Prettier) → hors scope web standards.
+
+Subtasks :
+- [x] Créer `agents/validator-analyzer.md` — spec 6 étapes (478 lignes)
+- [x] Créer `skills/validate/SKILL.md` — dispatcher (378 lignes)
+- [x] Ajouter routage `/validate` dans `~/.claude/CLAUDE.md` section "Skill routing"
+- [x] Mettre à jour `skills/harden/SKILL.md` — W3C/a11y redirigé vers /validate
+- [x] Mettre à jour `skills/seo/SKILL.md` — cross-ref /validate pour W3C/WCAG
+- [x] Grep cohérence : refs /validate correctes, skill détecté par la harness