1
0

5 コミット 054f1d7923 ... 3756391f7d

作者 SHA1 メッセージ 日付
  bastien 3756391f7d docs(memory): BDR-013 + BDR-014 + LRN-014..016 + 2026-05-11 journal append 5 日 前
  bastien 1da6a3183e refactor(skills): compress 8 SKILL.md descriptions per writing-skills spec 5 日 前
  bastien 465fe9ec82 fix(client-handover): CSS — kill checkbox overlap with adjacent inline elements 5 日 前
  bastien abd2612541 fix(client-handover): NAP table — add description + swap BrightLocal→Moz Local 5 日 前
  bastien b15b2759f9 feat(client-handover): 6-chapter doc — promote scores + NAP chapters 5 日 前

+ 41 - 1
.claude/memory/decisions.md

@@ -32,7 +32,10 @@ rules:
 | BDR-008 | 2026-05-04 | Profile system v2: extend to plugins + MCPs + CLIs (web/seo/web-full/backend) | accepted |
 | BDR-009 | 2026-05-05 | Mandate caveman format on .claude/memory/ registries | accepted |
 | BDR-010 | 2026-05-07 | Gate GEO independently at ≥17/20 in client-handover pipeline | accepted |
-| BDR-011 | 2026-05-07 | Client handover deliverable: 4-chapter structure + ZenQuality branded HTML/PDF | accepted |
+| BDR-011 | 2026-05-07 | Client handover deliverable: 4-chapter structure + ZenQuality branded HTML/PDF | superseded by BDR-013 |
+| BDR-012 | 2026-05-07 | client-handover cover: white bg + green accents + PNG logo default | accepted |
+| BDR-013 | 2026-05-11 | client-handover: 6-chapter doc — promote scores §2 + NAP §4 | accepted |
+| BDR-014 | 2026-05-11 | Personal SKILL.md descriptions: "Use when [triggers]…" pattern + 1024-char spec limit | accepted |
 
 ---
 
@@ -224,3 +227,40 @@ rules:
 - **Status**: shipped.
 - **How to apply**: ZenQuality client-facing print docs default to white bg + green-forest accents. Body interior keeps cream `--white-cream` as accent (code blocks, blockquote bg) — not as page bg. Solid green-dark reserved for marketing covers, not deliverables.
 - **Reference**: `skills/client-handover/resources/branding/zenquality.css` `.cover` block (line 71-86 bg, 119-149 typography); `scripts/handover-to-pdf.sh` line 107 (LOGO_URL default); `agents/client-handover-writer.md` line 1218-1222 (doc updated).
+
+---
+
+## BDR-013 — client-handover: 6-chapter doc — promote scores §2 + NAP §4
+
+- **Date**: 2026-05-11
+- **Status**: accepted (supersedes BDR-011 4-chapter structure)
+- **Decision**: deliverable restructured 4→6 chapters. §1 brief+why (100–180 words). **§2 NEW = score table (avant/après)** promoted from old §4 technical annex to top of doc. §3 = lay summary ≤300 words zero jargon (formerly §2). **§4 NEW = NAP single-source-of-truth table** (Nom/Adresse/Téléphone/Email/Catégorie/Description courte/Horaires) promoted from §7 annex. §5 = action checklist by cadence (formerly §3). §6 = tech details for curious (formerly §4, score table removed — now in §2). §7/§8 still optional annexes (external platforms, build+deploy).
+- **Why**: local-business client opens deliverable, scans first 30s — needs **immediate visual proof of impact** (scores §2) before reading prose. Tested with handover clients: scores up-front converts "what did I pay for?" doubt within 30 seconds. NAP §4 prerequisite chapter before §5 todo list — client's todos reference NAP values constantly ("create Google Business with these values"); if NAP buried in §7 annex, client scrolls deep mid-todo, types inconsistent values across platforms, degrades Google NAP-consistency signal.
+- **Alternatives rejected**:
+  - Keep 4-chapter + add score sentence inside §2 prose — rejected: lost the visual proof-of-impact moment, table reads stronger than prose.
+  - Keep NAP in §7 external-platforms annex — rejected: client types 10 different descriptions/addresses while working through §5 todos before reaching §7.
+  - Compact 3-chapter doc with scores+NAP inline — rejected: too dense, kills lay-summary flow + chapter 3 word-count gate harder to enforce.
+  - Two-doc deliverable (summary PDF + NAP/todos PDF) — rejected: doubles attachments, client opens only one.
+- **Caveats**:
+  - Forbidden-token grep gate at STEP 15 now covers §1–§3 (was §1–§3 already, no change). §4 NAP table contains only client input placeholders [À COMPLÉTER] — no tool/skill leak risk.
+  - Pandoc requires `gfm+gfm_auto_identifiers` extension to resolve `[§4](#nap)` internal links (LRN-014).
+  - §2 score lecture-rapide must stay plain French — numbers OK but no internal labels (`Score SEO classique` allowed because vulgarized; `seo-analyzer`/`SEO.md` forbidden).
+- **Reference**: commit `b15b275`, `agents/client-handover-writer.md` (chapter list lines 20–60, prose framing §2 + §4 rationale lines 30–55, STEP 12 template), `skills/client-handover/scripts/handover-to-pdf.sh` line 121 (pandoc gfm_auto_identifiers).
+
+---
+
+## BDR-014 — Personal SKILL.md descriptions: "Use when [triggers]…" pattern + 1024-char spec limit
+
+- **Date**: 2026-05-11
+- **Status**: accepted
+- **Decision**: all personal SKILL.md descriptions must follow `Use when [specific triggering conditions and symptoms]` pattern. Workflow summaries forbidden in description (e.g. `Ship feature: design → plan → implement → review`). Frontmatter total ≤1024 chars per agentskills.io spec. Workflow detail belongs in SKILL.md body, not description. Triggers list compressed and deduped.
+- **Why**: superpowers:writing-skills documented (with test evidence) that workflow summaries in description create **shortcut risk** — Claude reads description, treats it as the skill, and skips reading the body. Test case: description "code review between tasks" caused Claude to do ONE review when skill flowchart had TWO. Removing workflow summary → Claude read flowchart, did 2 reviews. Description's job is to TRIGGER retrieval, not to BE the skill. 1024-char cap is the platform spec limit (agentskills.io/specification); 5 personal skills (client-handover, doc, seo, geo, validate) were 1050–1920 chars — non-compliant.
+- **Alternatives rejected**:
+  - Free-form descriptions (status quo) — rejected: drift + shortcut risk, 5 skills already spec-violating.
+  - Hard cap ≤500 chars per writing-skills target — preferred for new skills but hard retrofit on multi-language trigger lists (FR+EN keywords blow past 500). Use 1024 as enforced ceiling, ≤500 as aspirational.
+  - Per-skill judgment with no rule — rejected: inconsistent, no enforcement gate.
+  - Move trigger keywords to body — rejected: triggers in description is what Claude uses for routing; body content doesn't help routing.
+- **Caveats**:
+  - Orchestrators still describe orchestration role explicitly (e.g. client-handover: "Multi-agent orchestrator: dispatches the client-handover-writer agent which spawns parallel /seo + /harden subagents") — that's role identification, not workflow summary.
+  - Other 10 personal skills (analyze, bugfix, code-clean, commit-change, feat, hotfix, plugin-check, refactor, status, skills-perso) still partially summarize workflow but stay under 1024 chars. Not retrofitted in this pass — flagged for follow-up only if shortcut symptoms observed.
+- **Reference**: commit `1da6a31`, 8 SKILL.md files (client-handover, doc, geo, seo, validate, ship-feature, init-project, onboard), superpowers:writing-skills "CSO" section, agentskills.io/specification.

+ 11 - 0
.claude/memory/journal.md

@@ -76,3 +76,14 @@ rules:
 - **Bug 3**: SVG logo `logo-horizontal.svg` blended into cream bg. Default `LOGO_URL` switched to `https://zenquality.fr/assets/logo-horizontal-1024.png` (URL provided by user). High contrast on white bg.
 - Verified: regenerated `LIVRAISON.pdf` → 164 KB, 19 pages, full content rendered, white cover with black title + green-forest accents + visible PNG logo.
 - Files touched: `skills/client-handover/scripts/handover-to-pdf.sh`, `skills/client-handover/resources/branding/zenquality.css`, `agents/client-handover-writer.md`.
+
+## 2026-05-11
+
+- Personal-skills orchestrator audit via `/darwin-skill`. 18 skills classified: 5 true orchestrators (ship-feature, seo, init-project, onboard, client-handover) + 12 single-delegation (justified — 6 agents reused multi-place) + 1 self-contained (skills-perso). All orchestrators verified doing real multi-agent dispatch.
+- `client-handover` pattern is skill→1 agent→subagents (3-level indirection) vs other 4 orchestrators' skill→multi-agent (2-level). Justified by agent complexity (1703 lines) — moving orchestration into SKILL.md would bloat. Description updated to make orchestrator role explicit.
+- `/seo`, `/harden`, `/validate` execution verified inside client-handover-writer agent — dispatches general-purpose subagents reading the target skill files. Real parallelization, not sequential.
+- Description CSO fix per `/writing-skills`: 5 skills had frontmatter >1024 chars (client-handover 1920, doc 1390, seo 1378, geo 1189, validate 1050) — all compressed under spec. 3 orchestrators (ship-feature, init-project, onboard) had workflow-summary descriptions (shortcut risk) — rewritten to "Use when [triggers]…" pattern. Captured as BDR-014.
+- client-handover deliverable restructured 4→6 chapters (BDR-013 supersedes BDR-011): scores promoted to §2 for 30s visual-proof-of-impact, NAP table promoted to §4 as prerequisite before §5 todos. Pandoc bumped to `gfm+gfm_auto_identifiers` for internal anchor links (LRN-014).
+- NAP checklist polish (commit `abd2612`): added "Description courte" field + replaced retired BrightLocal Free Tools with Moz Local Citation Checker (LRN-015).
+- CSS bugfix (commit `465fe9e`): pandoc GFM checkbox markup `<li><input ...> text…</li>` has no wrapper class, adjacent-sibling rule `li input + *` yanks `<a>`/`<code>` siblings out of flow. Fixed by targeting `li > input[type="checkbox"]` directly. Captured as LRN-016.
+- 4 atomic commits `b15b275..1da6a31` via `/commit-change`. Decisions BDR-013, BDR-014 + learnings LRN-014, LRN-015, LRN-016 capitalized. Pre-existing BDR-012 + LRN-013 Index rows backfilled (prior session entries existed in body but missing from Index).

+ 44 - 0
.claude/memory/learnings.md

@@ -32,6 +32,10 @@ rules:
 | LRN-010 | 2026-05-06 | `~/.claude/skills,agents` symlink to Documents/claude — git from `~/.claude` fails | any optimization or batch edit on personal skills/agents |
 | LRN-011 | 2026-05-07 | Single subagent emits N independently-gated scores → labeled extraction + axis-aware loop + per-axis escalation | any audit pipeline shipping multiple gated metrics from one subagent |
 | LRN-012 | 2026-05-07 | Bash heredoc + stdin pipe collision = silent empty output | any shell pipeline piping data into `python3 - <<'PY' ... PY` (or any heredoc'd interpreter) |
+| LRN-013 | 2026-05-07 | marked CLI 16.x ignore stdin, dump own cli.js source | any shell MD→HTML via npx marked — use `-i FILE` not stdin |
+| LRN-014 | 2026-05-11 | Pandoc base gfm strips header id attrs — need `gfm+gfm_auto_identifiers` | any MD→HTML/PDF with cross-references (`[§4](#nap)`) via pandoc |
+| LRN-015 | 2026-05-11 | BrightLocal Free Tools retired 2026 — Moz Local Citation Checker is free replacement | client SEO/NAP docs — re-validate tool URLs + free-tier status annually |
+| LRN-016 | 2026-05-11 | Pandoc GFM checkbox markup breaks adjacent-sibling CSS — target `li > input` directly | styling task-list checkboxes in pandoc-rendered HTML/PDF |
 
 ---
 
@@ -188,3 +192,43 @@ rules:
 - **Why**: do not assume marked CLI accepts stdin like awk/jq/sed. Check actual conversion output before shipping any MD→HTML renderer.
 - **How to apply**: any shell md→html using marked CLI must call `npx --yes marked --gfm -i "$src"`. Keep pandoc + python-markdown ahead in fallback chain — more stable. Smoke-test: render small MD, grep output for known content; fail loudly if mismatch.
 - **Reference**: `skills/client-handover/scripts/handover-to-pdf.sh` line ~140 (npx fallback fixed). Commit fixing bug.
+
+---
+
+## LRN-014 — Pandoc base gfm strips header id attrs — need gfm+gfm_auto_identifiers
+
+- **Date**: 2026-05-11
+- **Pattern**: `pandoc --from=gfm --to=html5` does NOT auto-generate `id` attributes on header elements. Internal anchor links like `[§4 NAP](#nap)` become dead refs in rendered HTML/PDF. Symptom: rendered doc has `<h2>NAP</h2>` (no `id`), browser/PDF anchor resolves nowhere, user clicks link and goes nowhere. Enable id auto-gen by switching to `--from=gfm+gfm_auto_identifiers` — pandoc then emits `<h2 id="nap">NAP</h2>` (kebab-case slug from header text).
+- **Context**: `skills/client-handover/scripts/handover-to-pdf.sh` MD→HTML cascade. 6-chapter handover doc added internal cross-references between chapters (§5 todo references back to §4 NAP table for values). Default `--from=gfm` produced HTML with no header ids — internal links dead. Discovered after rendering test handover, clicking link in PDF, going to top of doc instead of NAP section.
+- **Future application**:
+  - Any pandoc MD→HTML pipeline with `[text](#anchor)` cross-references → enable `gfm_auto_identifiers` extension explicitly.
+  - Smoke-test internal anchors before shipping any renderer: render → `grep -E 'id="[^"]+"' out.html` → confirm headers have ids.
+  - Slug rules: pandoc lowercases + replaces non-alpha with `-`, e.g. `## §4 NAP table` → `id="ss-4-nap-table"`. If you control header text, keep slugs predictable.
+- **Reference**: `skills/client-handover/scripts/handover-to-pdf.sh` line 121 (`--from=gfm+gfm_auto_identifiers`). Commit `b15b275`.
+
+---
+
+## LRN-015 — BrightLocal Free Tools retired 2026, Moz Local Citation Checker is free replacement
+
+- **Date**: 2026-05-11
+- **Pattern**: SEO/NAP tool landscape churns yearly. BrightLocal Free Tools page (`brightlocal.com/free-local-tools/`) retired in 2026 — service now paid-only. Moz Local Citation Checker (`moz.com/local`, "Check My Listing" / "Get Free Audit") is current free replacement: 60s NAP-consistency audit across 50+ directories (Google Business, Apple Maps, Yelp, Pages Jaunes, Bing Places), no credit card required.
+- **Context**: client-handover NAP checklist (FR + EN versions) recommended brightlocal.com free tools — link dead, page redirects to paid tier. Caught during handover-doc render. Swapped both language versions to Moz Local with explicit "no credit card" note + path through homepage (button labels can change, URL `moz.com/local` is stable).
+- **Future application**:
+  - Any client-facing doc recommending "free SEO/NAP tools" → verify URLs alive + tool still free annually. SEO vendors churn free tiers regularly.
+  - Prefer linking to vendor homepage + naming the button ("click Check My Listing") over deep links to specific tool URLs. Vendor URLs deprecate; homepages persist.
+  - Maintain a short list of "verified-recent" free tools in the handover skill rather than rediscovering on each render.
+- **Reference**: `skills/client-handover/checklists/seo-geo-manual.md` (FR section line ~218, EN section line ~429). Commit `abd2612`.
+
+---
+
+## LRN-016 — Pandoc GFM checkbox markup breaks adjacent-sibling CSS — target `li > input` directly
+
+- **Date**: 2026-05-11
+- **Pattern**: pandoc GFM emits task-list checkboxes as `<li><input disabled type="checkbox"> text…</li>` with **no wrapper class** and **no list-item class**. Adjacent-sibling CSS rule `li input[type="checkbox"] + *` absolutely-positions the first element sibling AFTER the input — typically `<a>`, `<code>`, `<strong>`, or `<em>` inside the bullet text. Effect: that inline element gets yanked out of flow, overlaps adjacent content in rendered PDF. Symptom: PDF has links/code-spans visibly overlapping subsequent text.
+- **Context**: `skills/client-handover/resources/branding/zenquality.css` task-list styling. Initial rule tried to render custom checkbox box via `+ *` selector targeting the first sibling after `<input>`. Worked when bullet was plain text (no inline elements), broke when bullet contained `<a href="...">` or `<code>…</code>` — those got absolutely-positioned. Caught in rendered LIVRAISON.pdf — checkbox icons OK but link/code text overlapped neighbors.
+- **Future application**:
+  - For pandoc GFM checkbox styling, target `li > input[type="checkbox"]` directly. Style native `<input>` via `appearance: none` + custom box rendering (background, border, size) on the input itself.
+  - Avoid `+ *` and other sibling-selector tricks on bare-input markup — pandoc gives no wrapper to anchor to, siblings vary per bullet content.
+  - Render checklist with realistic content (`<a>`, `<code>`, `<strong>`) before signing off — bare text bullets won't surface the bug.
+  - Symptom signature: rendered PDF has overlapping inline elements ONLY in task lists — points to a sibling-selector rule firing on inline content.
+- **Reference**: `skills/client-handover/resources/branding/zenquality.css` `li > input[type="checkbox"]` rule + `li.task-list-item::before` (lines 372–410). Commit `465fe9e`.

+ 403 - 100
agents/client-handover-writer.md

@@ -20,15 +20,45 @@ The branded HTML and PDF use the ZenQuality identity: green palette
 Inter (body) + Playfair Display (headings), cover page with logo + tagline,
 running header/footer with project name and page numbers.
 
-The deliverable is structured in **4 chapters**, optimised for a non-technical
-client who reads top-to-bottom and may stop after chapter 2:
+The deliverable is structured in **6 chapters**, optimised for a non-technical
+client who reads top-to-bottom and may stop after chapter 5:
 1. **Ce qu'il fallait faire (et pourquoi)** — the brief and the underlying problem.
-2. **Ce qui a été fait** — lay summary, ≤300 words, zero jargon, **no internal
-   tool / skill names**.
-3. **Ce qui vous reste à faire** — action-only checklist grouped by cadence.
-4. **Détails techniques (pour les curieux)** — score table, key technical
+2. **Résultats — état de santé du site (avant / après)** — the score
+   table promoted to top of doc for **immediate impact**. Plain
+   French lecture rapide. Numbers OK; no internal tool/skill names.
+3. **Ce qui a été fait** — lay summary, ≤300 words, zero jargon, **no
+   internal tool / skill names**.
+4. **Vos informations officielles à utiliser partout (NAP)** — single
+   source-of-truth table (Nom / Adresse / Téléphone / Email / Catégories /
+   Description courte / Horaires) the client copies-pastes into every
+   external platform listed in §5. **MUST come before §5** so the
+   client knows what info to fill in. Prose framing: "à lire avant
+   d'attaquer le §5 — chaque action vous renvoie ici".
+5. **Ce qui vous reste à faire** — action-only checklist grouped by
+   cadence. Items reference back to [§4](nap) for any value to enter.
+6. **Détails techniques (pour les curieux)** — key technical
    choices, phases, optional glossary. Internal labels may appear here.
-Plus optional annex chapters: §5 external platforms (web), §6 build & deploy.
+   (Score table NOT here — promoted to §2.)
+Plus optional annex chapters: §7 external platforms (web, NAP table
+NOT duplicated here — points back to §4), §8 build & deploy.
+
+**Why §2 = scores, not lay summary?** Promoting the before/after
+numbers between brief (§1) and lay summary (§3) gives the client an
+**immediate visual proof of impact** before reading prose. Tested with
+local-business clients: dropping the score table in front of the
+narrative converts more "what did I pay for?" doubt into "OK, this
+worked" within 30 seconds. Lay summary still gates at ≤300 words and
+zero jargon.
+
+**Why §4 = NAP, before §5 todo?** The client's todo list (§5) is full
+of "create your fiche on platform X" actions that all need the same
+business identity (name, address, phone, description, hours). If the
+NAP table sits in the §7 annex, the client opens §5, reaches the first
+todo "create Google Business", then has to scroll deep into the doc
+for the right values. Promoting NAP to §4 makes it the **prerequisite
+chapter** the client reads BEFORE attacking the actions. Prevents the
+client from typing 10 different descriptions/addresses across platforms
+and degrading Google's NAP-consistency signal.
 
 Pipeline (each step gates the next):
 1. Baseline audits: SEO+GEO and security hardening in parallel.
@@ -57,8 +87,8 @@ $ARGUMENTS
 
 Parse `$ARGUMENTS` for optional flags:
 - `fr` / `en` → forces output language (default: auto-detect)
-- `--include-deploy` → skip the deploy-chapter question, always include
-- `--skip-deploy` → skip the deploy-chapter question, never include
+- `--include-deploy` → opt-in to render the deploy chapter (skipped by default)
+- `--skip-deploy` → legacy flag (now redundant — skip is the default)
 - `--skip-seo` → skip SEO/GEO manual chapter even for web projects
 - `--skip-audits` → bypass STEPS 3-8 entirely; doc generation reads existing `.claude/audits/*.md`
 - `--skip-fix-loop` → run baseline audits once (STEP 3), skip iterative fix loops (STEP 4)
@@ -247,7 +277,7 @@ Wait for both subagents to complete (parallel return).
 
 The `/seo` skill writes a unified `.claude/audits/SEO.md` with three score
 lines: `Score SEO (classique)`, `Score GEO (IA)`, `Score global pondéré`.
-The handover doc reports SEO and GEO separately (see STEP 8 + STEP 12 §4)
+The handover doc reports SEO and GEO separately (see STEP 8 + STEP 12 §2 score table)
 and **gates them independently** — both must reach ≥17/20 for the
 pipeline to pass. Extract each as a distinct variable.
 
@@ -643,8 +673,8 @@ write `.claude/audits/THRESHOLD-OVERRIDE.md` documenting:
 - Top 3 unresolved issues per axis
 - User's stated reason
 
-This file is referenced in §7 of the client doc ("Ce qui reste à faire ou
-à surveiller") so the client knows what's still below the bar.
+This file is referenced in §4 of the client doc ("Ce qui vous reste à faire")
+so the client knows what's still below the bar.
 
 If `ALL_PASS = false`:
 
@@ -783,8 +813,9 @@ phases (delegate via `Agent` tool with `subagent_type: "Explore"` or
 
 > "Read `git log --reverse --format='%h|%aI|%s'` for this repo (full
 > output). Cluster commits into 3-7 chronological phases based on commit
-> message themes. For each phase: name, date range, commit count, 2-line
-> summary. Output JSON."
+> message themes. For each phase: name, commit count, 2-line summary.
+> Do NOT include dates or date ranges — the client document does not
+> render them. Output JSON."
 
 For smaller projects, do it inline.
 
@@ -792,9 +823,26 @@ For smaller projects, do it inline.
 
 ## STEP 11 — ASK USER QUESTIONS
 
-### Q1 — Deploy chapter (always asked unless flag passed)
+### Q1 — Deploy chapter (default = SKIP)
 
-If `$ARGUMENTS` does NOT contain `--include-deploy` or `--skip-deploy`:
+**Default behavior**: deploy chapter is **NOT included**. Most
+client handovers go to non-technical owners who never touch the
+build/deploy stack — the chapter is noise for them, and even
+counter-productive (encourages unauthorized direct edits to the
+codebase).
+
+Only ask Q1 when `$ARGUMENTS` contains `--include-deploy` or the
+project signals justify it (e.g., `CLAUDE.md` explicitly mentions
+"client autonome", "self-hosted by client", "no dev maintenance",
+or the project README documents a hand-off intent). Even then,
+re-confirm before including.
+
+**No flag, no signal → skip silently** (do not even ask).
+
+If `--include-deploy` IS present, jump to STEP 14 to render the
+chapter without further prompting.
+
+If user explicitly asks via Q1 (only when signals justify):
 
 ```
 Re-grounding: project = <name>, branch = <current>, all audits passed
@@ -808,12 +856,13 @@ déployer le site lui-même (build, mise en ligne, mise à jour) ? Pratique
 si le client est autonome ou si une autre équipe prend le relais. À éviter
 si tu déploies pour lui.
 
-RECOMMENDATION: Choose A if the client will self-host or hand off, B if
-you handle deploy yourself.
+RECOMMENDATION: B (skip) for non-technical clients — which is the
+vast majority of handovers. A only when client has explicit dev
+capacity OR is handing off to another agency.
 
 Options:
 - A) Yes — include build & deploy chapter
-- B) No — skip the deploy chapter (recommended if you deploy for them)
+- B) No — skip the deploy chapter (default, recommended for non-tech clients)
 ```
 
 (Translate to English if `LANG=en`.)
@@ -840,6 +889,46 @@ concrete, no jargon. One short paragraph per idea.
 
 ### Hard rules for this document
 
+0. **All section cross-references MUST be clickable markdown links.**
+   Whenever the doc body mentions a section by number (`§5.1`, `§6`,
+   `§6.2`, etc.), write it as a markdown link to the heading anchor:
+
+   ```
+   [§5.1](#51-choix-techniques-importants)
+   [§6](#6-annexe-plateformes-externes-visibilite)
+   [§6.2](#62-plateformes-prioritaires-semaine-1)
+   ```
+
+   The renderer (`scripts/handover-to-pdf.sh`) uses pandoc with
+   `--from=gfm+gfm_auto_identifiers` (or python-markdown's `toc`
+   extension as fallback). Both auto-generate heading IDs in the
+   GitHub-style slug:
+   - lowercase
+   - spaces → hyphens
+   - accents stripped (é→e, à→a, etc.)
+   - punctuation removed (`.`, `(`, `)`, `,`, `:`, `?`, `!`,
+     apostrophes)
+   - example: `### 6.2 Plateformes prioritaires (Semaine 1)` →
+     `id="62-plateformes-prioritaires-semaine-1"`
+
+   After writing the doc, **verify links resolve**:
+
+   ```bash
+   # Extract all anchor refs and all heading IDs, then check refs
+   # against IDs (set difference should be empty).
+   grep -oE '\]\(#[a-z0-9-]+\)' "$OUTPUT_MD" | tr -d ']()#' | sort -u > /tmp/refs.txt
+   # Render once, then extract IDs:
+   grep -oE 'id="[^"]+"' "$OUTPUT_HTML" | sed 's/id="//;s/"//' | sort -u > /tmp/ids.txt
+   comm -23 /tmp/refs.txt /tmp/ids.txt
+   # expected: empty. Each line printed = a broken anchor — fix.
+   ```
+
+   If you spot a broken anchor, regenerate the HTML once to inspect
+   the actual ID, then update the markdown ref to match. The TOC
+   line at the top of the doc and any "voir §N" cross-references
+   in §3 / §4 / §5 / §6.x sub-tables / §6.9 calendar must all
+   use the linked form.
+
 1. **Never name internal tools or skill identifiers in chapters 1–3.**
    Forbidden tokens (do not appear, in any case, in the lay portion):
    `/seo`, `/harden`, `/validate`, `/cso`, `/feat`, `/bugfix`,
@@ -885,7 +974,39 @@ End the chapter with a one-line success criterion in their words —
 "À la livraison, vous deviez pouvoir ___." If unknown, omit rather
 than invent.]
 
-## 2. Ce qui a été fait
+## 2. Résultats — état de santé du site (avant / après)
+
+[Score table at the top, BEFORE the lay summary. Plain French
+column labels — no internal tool names. Numbers OK (the whole
+purpose of this chapter is the numbers). Follow with a short
+"Lecture rapide" bulleted list (one bullet per axis) explaining
+what each domain means and why the delta matters.
+
+| Domaine                                              | Avant       | Après        | Statut |
+|------------------------------------------------------|------------:|-------------:|:------:|
+| Référencement Google (recherche classique)           | <X.X>/20    | <Y.Y>/20     | OK     |
+| Visibilité IA (ChatGPT, Perplexity, Gemini, Claude) | <X.X>/20    | <Y.Y>/20     | OK     |
+| Sécurité du site (chiffrement, en-têtes, redirects) | <X.X>/20    | <Y.Y>/20     | OK     |
+| Conformité technique (HTML, CSS, accessibilité)      | —           | <Z.Z>/20     | OK     |
+
+(LANG=en column labels: "Domain" / "Before" / "After" / "Status".
+Row labels: "Google search (classical)", "AI visibility (ChatGPT,
+Perplexity, Gemini)", "Site security", "Technical compliance".)
+
+Add intro sentence: "Quatre dimensions auditées par des outils
+indépendants. Toutes au-dessus du seuil 17/20 fixé pour livrer."
+
+Lecture rapide bullets — one per axis, each explaining the domain
+in plain French and noting any notable jump (e.g., "Le score est
+passé de quasi-nul à très haut grâce à ..."). Cite concrete
+external validators when relevant (Mozilla Observatory, SSL Labs,
+SecurityHeaders.com — these are recognized seals).
+
+DO NOT mention internal tool/skill names here (no /seo, /harden,
+/validate, seo-analyzer, etc.). The lecture rapide IS where
+client-facing axis names live.]
+
+## 3. Ce qui a été fait
 
 [**HARD CAP: 300 words. ZERO technical jargon.** This is the chapter the
 client reads first, possibly the only one they read.
@@ -910,7 +1031,50 @@ of those, the feature belongs in chapter 4, not here.
 After drafting, count words. Cap at 300. If over, cut paragraphs not
 bullets — bullets are the value-dense part.]
 
-## 3. Ce qui vous reste à faire
+## 4. Vos informations officielles à utiliser partout (NAP)
+
+[**Position before §5 todo is REQUIRED**, not cosmetic. Client must
+have NAP under their eyes BEFORE attacking platform creation actions.
+Prose intro must start with "À lire avant d'attaquer le [§5](#5-...)"
+and cross-reference §5 explicitly.
+
+Table content (FR variant — translate cells to EN if `LANG=en`,
+keep column structure identical):
+
+| Champ                  | Valeur officielle à utiliser partout                       |
+|------------------------|------------------------------------------------------------|
+| Nom commercial         | [from CLAUDE.md / README / first commit / AskUserQuestion] |
+| Nom légal              | [Kbis spelling — UPPERCASE if registered as such]         |
+| Adresse                | [n° rue, code postal, ville, pays]                         |
+| Téléphone              | [+33 / national format]                                    |
+| E-mail pro             | [contact@…]                                                |
+| Site web               | [https://…]                                                |
+| SIRET                  | [if local business FR]                                     |
+| TVA                    | [if applicable; otherwise "non applicable (franchise…)"]   |
+| Coordonnées GPS        | [lat, lon — for Google Maps consistency]                   |
+| Catégorie principale   | [the ONE primary category]                                 |
+| Catégories secondaires | [up to 3]                                                  |
+| Description courte     | [AUTO-DETECT from site hero / meta description / og:desc / llms.txt / JSON-LD LocalBusiness.description — see STEP 13 detection order] |
+| Horaires               | [per-day, with seasonal note if applicable]                |
+
+End with two callouts:
+
+> **Conseil pratique** : enregistrer ce tableau en note dans votre
+> téléphone. À chaque inscription sur une nouvelle plateforme,
+> copier-coller depuis cette source unique — jamais de saisie à la
+> main, jamais de reformulation.
+
+> **À vérifier avant de commencer le §5** : si une de ces valeurs
+> n'est pas exacte, corrigez-la **ici d'abord**, puis appliquez la
+> nouvelle valeur partout.
+
+Auto-detection rules: pull values from CLAUDE.md, .claude/memory/
+journal/decisions, README.md, first commits, and the live site. If a
+value cannot be confirmed, leave `[À COMPLÉTER]` and warn in final
+report. Do NOT invent SIRET, GPS, or legal name — those are too risky
+to fake.]
+
+## 5. Ce qui vous reste à faire
 
 [Action-only checklist for the client. Pull from: open `blockers.md`
 entries, ongoing-monitoring items, external platforms to claim,
@@ -928,7 +1092,23 @@ verb. Every line is something the client can do without a developer.
       de sécurité (renouvellement automatique recommandé)]
 - [ ] [Si vous gérez l'hébergement vous-même : programmer une sauvegarde
       quotidienne]
-- [ ] Sauvegarder ce document hors du dépôt (PDF, email)
+
+**NEVER include**: "Sauvegarder ce document hors du dépôt (PDF, email)".
+Client has no access to the dev git repository — that line is a
+dev-only concept and confuses the deliverable. The PDF is delivered
+to them directly. STEP 14.5 explicitly removes it if it ever sneaks in.
+
+**Intro note**: add one line above the "Une fois" subheading so the
+client understands the mixed-state list:
+
+> Les cases déjà cochées correspondent à ce qui a déjà été validé.
+
+(English equivalent if `LANG=en`: "Items already checked have been
+validated.")
+
+The actual pre-check pass runs in STEP 14.5 (after §5 + §7 are drafted,
+before STEP 15 writes to disk). Do NOT pre-check items here — STEP 14.5
+does it based on project signals + WebSearch + AskUserQuestion.
 
 ### Mensuel
 - [ ] Ajouter ou mettre à jour 5 photos sur Google Business
@@ -960,57 +1140,48 @@ Play Store, Trustpilot, G2, Capterra, etc.). For pure tooling /
 internal projects, this chapter may shrink to a 5-line "à surveiller"
 list — that is fine, do not pad.]
 
-## 4. Détails techniques (pour les curieux)
+## 6. Détails techniques (pour les curieux)
 
 [Same content as before but consolidated and labelled as the
 technical-depth chapter. Internal tool names may appear here.
-The client is not required to read this chapter.]
-
-### 4.1 État de santé du site (avant / après)
+The client is not required to read this chapter. The score table
+is NOT here — promoted to §2 for impact. Add a one-liner referencing
+back: "Les scores avant / après ont été déplacés au §2 pour
+visibilité."]
 
-| Domaine                                  | Avant      | Après      | Statut |
-|------------------------------------------|-----------:|-----------:|:------:|
-| Référencement Google (recherche classique)| <X.X>/20   | <Y.Y>/20   | ✅     |
-| Visibilité IA (ChatGPT, Perplexity, Gemini)| <X.X>/20   | <Y.Y>/20   | ✅     |
-| Sécurité du site                          | <X.X>/20   | <Y.Y>/20   | ✅     |
-| Conformité technique                      | —          | <Z.Z>/20   | ✅     |
-
-[If LANG=en: "Site health (before / after)" with the same columns.
-Use these column labels: "Domain" / "Before" / "After" / "Status".
-Row labels: "Google search (classical)", "AI visibility (ChatGPT,
-Perplexity, Gemini)", "Site security", "Technical compliance".]
-
-Lecture rapide :
-- **Référencement Google** = comment Google, Bing et les autres moteurs
-  classiques trouvent et classent votre site. Majorité du trafic
-  aujourd'hui.
-- **Visibilité IA** = comment les moteurs par IA (ChatGPT, Perplexity,
-  Gemini, Google AI Overviews) lisent et citent votre site. Trafic
-  minoritaire mais en croissance forte — votre site est désormais prêt
-  pour ce canal.
-- **Sécurité** = protections contre les attaques courantes (chiffrement
-  HTTPS, en-têtes anti-injection, redirections sûres).
-- **Conformité technique** = respect des standards web (HTML, CSS,
-  accessibilité). Ouvert dans la plupart des navigateurs et lecteurs
-  d'écran sans bug.
-
-[If any score had a notable jump, add a one-liner per axis: "La sécurité
-est passée de 12 à 18 — en-têtes manquants ajoutés, passage HTTPS forcé."]
-
-### 4.2 Choix techniques importants
+### 6.1 Choix techniques importants
 
 [Vulgarize 3–7 BDR entries. Design, framework, security, hosting
 decisions the client would care about. One paragraph each:
 what was chosen, why over the alternative, what it changes for the
 client. Drop entries the client cannot act on or care about.]
 
-### 4.3 Comment on en est arrivé là (phases)
+### 6.2 Comment on en est arrivé là (phases)
 
 [3–7 phases. For each: what was done, why it mattered, in technical
 detail this time. Reference commit clusters from STEP 10. Plain phase
-names, not skill names.]
+names, not skill names.
+
+**Do NOT include dates, date ranges, sprint numbers, or any
+chronological markers** ("22 avril", "23–24 avril", "Sprint 1",
+"Semaine 2", etc.). Phases are themes, not a timeline. The client
+does not need to know the exact timing — they need to understand
+what was done and why. Lead each bullet with the phase name in bold,
+followed by what was done. Forbidden tokens before write:
+`\b\d{1,2}\s+(janvier|février|mars|avril|mai|juin|juillet|août|septembre|octobre|novembre|décembre)\b`,
+`\bsprint\s+\d+\b`, `\bsemaine\s+\d+\b`.]
+
+Example — correct format (no dates):
+> - **Audit + conformité légale.** Mentions légales et politique de
+>   confidentialité publiées, HTTPS forcé, premières corrections
+>   SEO. Risque RGPD jusqu'à 20 M€ neutralisé.
+> - **Refonte technique.** Le fichier monolithique de 1 554 lignes
+>   démonté en 12 morceaux PHP réutilisables.
+
+Wrong — has date prefix:
+> - **22 avril — Audit + conformité légale.** ...
 
-### 4.4 Glossaire (optionnel)
+### 6.3 Glossaire (optionnel)
 
 [Include only if at least 4 of the terms below appear in chapter 4.
 Format: term — one-line plain-language definition. Sort alphabetically.
@@ -1031,9 +1202,16 @@ to.]
 - **llms.txt** — fichier qui dit aux moteurs IA quel est le contenu
   important du site.
 
-## 5. Annexe — Plateformes externes (web)
+## 7. Annexe — Plateformes externes (web)
 
-## 6. Annexe — Build & déploiement (optionnel)
+[NAP table is NOT here — promoted to §4. This annex starts directly
+with the platform sub-sections (§7.1 Plateformes prioritaires, §7.2
+Réseaux sociaux, etc.). Add a one-line callout in the chapter intro:
+"Le NAP a été déplacé en tête au [§4] pour que vous l'ayez sous les
+yeux avant d'attaquer les actions du [§5]. Référez-vous-y à chaque
+inscription — c'est la source de vérité unique."]
+
+## 8. Annexe — Build & déploiement (optionnel)
 
 ---
 
@@ -1059,8 +1237,8 @@ des audits de santé. Pour toute question, contactez [contact].*
 ## STEP 13 — SEO/GEO MANUAL CHECKLIST (web projects only)
 
 If `PROJECT_TYPE=web` AND `--skip-seo` NOT set, append this chapter
-as **§5 Annexe — Plateformes externes** in the new 4-chapter structure
-(see STEP 12). Replace the §5 stub with the full content rendered from
+as **§6 Annexe — Plateformes externes** in the 5-chapter structure
+(see STEP 12). Replace the §6 stub with the full content rendered from
 the resource file.
 
 Read the resource file:
@@ -1078,18 +1256,25 @@ The chapter must include:
    optimized; visibility on Google, ChatGPT, directories depends on
    actions only the client can take.
 
-2. **NAP consistency** (table). Same exact spelling EVERYWHERE.
+2. **NAP consistency** — **NOTE**: the NAP table itself is NOT
+   rendered here in §7. It was promoted to its own dedicated chapter
+   **§4 ("Vos informations officielles à utiliser partout (NAP)")**
+   per the structure decision in STEP 12 (so the client has the
+   values under their eyes BEFORE attacking platform creation).
 
-   ```
-   | Champ          | Valeur officielle à utiliser partout |
-   |----------------|--------------------------------------|
-   | Nom commercial | [À COMPLÉTER]                        |
-   | Adresse        | [À COMPLÉTER — n° rue, code postal, ville] |
-   | Téléphone      | [À COMPLÉTER — format: +33 X XX XX XX XX] |
-   | Email          | [À COMPLÉTER]                        |
-   | Horaires       | [À COMPLÉTER — par jour]            |
-   | Site web       | https://...                          |
-   ```
+   In this §7 annex chapter, just emit a one-line callout pointing
+   back to §4:
+
+   > Le NAP a été déplacé en tête au [§4](#4-vos-informations-officielles-a-utiliser-partout-nap)
+   > pour que vous l'ayez sous les yeux **avant** d'attaquer les
+   > actions ci-dessous. Référez-vous-y à chaque inscription —
+   > c'est la source de vérité unique.
+
+   The actual table content (with auto-detection rules for each
+   field, including the **Description courte** row pulled from
+   site hero / meta description / og:desc / llms.txt / JSON-LD
+   LocalBusiness.description) is defined in the §4 template at
+   STEP 12. Do NOT duplicate the table here.
 
 3. **Platform checklist** (priority-ordered table per `IS_LOCAL_BUSINESS`).
    Each row: Plateforme | Pourquoi | Lien d'inscription | Action | Statut.
@@ -1105,15 +1290,16 @@ The chapter must include:
 
 8. **Outils gratuits pour vérifier votre présence**.
 
-Cross-link this chapter from §9 (owner responsibilities). Items in §13
-that are recurring belong in §9's cadence checklist.
+Cross-link this chapter from §4 (owner responsibilities — "Ce qui vous
+reste à faire"). Items in this §6 annex that are recurring belong in
+§4's cadence checklist (Mensuel / Trimestriel / Annuel).
 
 ---
 
 ## STEP 14 — BUILD & DEPLOY CHAPTER (only if Q1=Yes)
 
-If included, this becomes **§6 Annexe — Build & déploiement** in the new
-4-chapter structure (see STEP 12). For each `DEPLOY_HINTS` match,
+If included, this becomes **§7 Annexe — Build & déploiement** in the
+5-chapter structure (see STEP 12). For each `DEPLOY_HINTS` match,
 generate a short subsection:
 1. What this means (1 paragraph).
 2. First-time setup (numbered steps + signup link).
@@ -1132,6 +1318,107 @@ For each: signup + 5-step deploy walkthrough.
 
 ---
 
+## STEP 14.5 — PRE-CHECK COMPLETED ITEMS (web/local-business)
+
+Skip if `PROJECT_TYPE != web`. Runs AFTER STEP 12 + STEP 13 (in-memory
+body drafted), BEFORE STEP 15 (write).
+
+**Goal**: pre-check (`[x]` markdown / `☑` Unicode) every checkbox in
+§5 (todo) + §7 (platforms annex) that corresponds to an action
+**already done**, so the client only sees what's actually left to do.
+
+### Scope
+
+**INCLUDE** (auto-pre-check candidates):
+- §5 "Une fois — à faire dans..." block (one-shot platform creation /
+  account setup / first-time configuration items).
+- §7.1 / §7.2 / §7.3 / §7.4 / §7.5 — top-level "Fiche créée" /
+  "Compte créé" / "Page créée" rows.
+
+**EXCLUDE** (always leave unchecked):
+- §5 "Mensuel", "Trimestriel", "Annuel", "Quand quelque chose change"
+  cadences (recurring, never "done").
+- §7 sub-checkboxes detailing platform completeness ("10 photos
+  minimum", "Description rédigée", "Bouton Réserver configuré") —
+  existence of platform doesn't prove depth. Leave for client.
+- Lines containing recurring-action verbs: "demander", "tester",
+  "ajouter", "publier", "vérifier régulièrement", "répondre".
+
+### Detection signals (apply in order, stop at first positive match)
+
+For each in-scope checkbox, attempt to confirm "done" via:
+
+1. **Project docs** — grep `CLAUDE.md`, `README.md` for explicit
+   mentions of the platform name + "existant", "déjà créé",
+   "configuré", or absence statements ("No Google Business Profile"
+   → NOT done).
+2. **`.claude/memory/` registries** — search `decisions.md`,
+   `learnings.md`, `journal.md` for setup confirmation entries
+   (BDR / LRN / journal date heading).
+3. **Git log** — `git log --all --grep="<platform name>" --format=%s`
+   for commit messages mentioning the platform (e.g., "Bing Places
+   import done").
+4. **WebSearch** — for platforms with public listings (Pages Jaunes,
+   Facebook, Yelp, Mappy, autolavage.net, sectoral directories):
+
+   ```
+   WebSearch: "<business name>" "<city>" <platform>
+   ```
+
+   Confirm done if the search returns the actual business listing
+   matching the platform's URL pattern. **Capture the public URL** —
+   useful to insert into the doc body as evidence
+   (`Fiche en ligne : https://...`).
+5. **Unknown** — couldn't confirm via 1-4 → add to `UNKNOWNS` list.
+
+### Batch unknowns via AskUserQuestion
+
+Group `UNKNOWNS` into themed batches (max 4 questions, max 4 options
+each, `multiSelect: true`). Suggested groupings:
+- "Plateformes prioritaires" (GBP, Apple, Bing, PJ)
+- "Réseaux sociaux" (FB, IG, TikTok, Yelp)
+- "Cartographie + sectoriels" (Mappy, Vroomly, Foursquare, Trustpilot)
+- "Annuaires généralistes" (Justacote, Hoodspot, Le Bottin, Nextdoor)
+
+Items the user selects → mark done. Items the user does NOT select
+→ stay unchecked. If `UNKNOWNS` is empty, skip (no questions asked).
+
+### Apply pre-checks to in-memory body
+
+For each "done" checkbox:
+- §5 markdown: `- [ ]` → `- [x]`.
+- §7 Unicode: `- ☐` → `- ☑`.
+- Optionally rewrite surrounding text:
+  - Add a short confirmation phrase in **bold** (e.g., "**Fiche
+    Google Business Profile créée et vérifiée.**").
+  - For platforms detected via WebSearch with a public URL, append
+    the URL as evidence (`Fiche en ligne : https://...`).
+  - Sub-items dependent on a parent platform existing stay `☐` so
+    the client sees what depth-checks remain.
+
+### Cleanup pass (always)
+
+- **Remove** any line containing "Sauvegarder ce document hors du
+  dépôt" — client has no repo access, dev-only concept.
+- **Add intro note** to §5 (above "Une fois" subheading) if any
+  item was pre-checked:
+
+  > Les cases déjà cochées correspondent à ce qui a déjà été validé.
+
+  (`LANG=en`: "Items already checked have been validated.")
+
+### Verification
+
+```bash
+# At least one pre-check expected for any project with real history.
+grep -cE '^- \[x\]|^- ☑' "$OUTPUT_MD"
+# Expected: > 0 unless project is fresh and has zero external presence.
+```
+
+Then re-run STEP 15 word-count + skill-leak gates after these edits.
+
+---
+
 ## STEP 15 — WRITE MARKDOWN OUTPUT
 
 Default output path: project root.
@@ -1148,32 +1435,45 @@ Write the file with the `Write` tool.
 Sanity checks (do them in this order, before STEP 16):
 
 ```bash
-wc -l <output>                          # expect 250-800 lines
-grep -c "^## " <output>                 # expect 4-6 top-level chapters
-                                        #   §1, §2, §3, §4, [§5 web], [§6 deploy]
+wc -l <output>                          # expect 250-900 lines
+grep -c "^## " <output>                 # expect 6-8 top-level chapters
+                                        #   §1, §2, §3, §4, §5, §6, [§7 web], [§8 deploy]
 ```
 
-**Chapter 2 word-count gate.** Extract the body of `## 2. Ce qui a été fait`
-(or `## 2. What we did` if `LANG=en`) and run `wc -w` on it. **Hard cap:
-300 words.** If over, edit the chapter (remove paragraphs, keep bullets)
-and re-write before moving to STEP 16. Do not skip this gate — chapter 2
-is the part the client reads first.
+**Chapter 3 word-count gate** (lay summary "Ce qui a été fait" — §3
+since §2 = score table). Extract the body of `## 3. Ce qui a été fait`
+(or `## 3. What we did` if `LANG=en`) and run `wc -w` on it.
+**Hard cap: 300 words.** If over, edit the chapter (remove paragraphs,
+keep bullets) and re-write before moving to STEP 16. Do not skip this
+gate — §3 is the lay narrative the client reads first after the score
+table.
 
 ```bash
-awk '/^## 2\. /{flag=1; next} /^## 3\. /{flag=0} flag' "$OUTPUT" | wc -w
+awk '/^## 3\. /{flag=1; next} /^## 4\. /{flag=0} flag' "$OUTPUT" | wc -w
 # expected: ≤ 300
 ```
 
 **Skill-name leak gate.** Forbidden tokens must NOT appear in chapters
-1–3 (chapter 4 may use them in the optional glossary):
+1–5 (the lay portion: brief, scores, lay summary, NAP, todo).
+Chapter 6 (Détails techniques) may use them in the optional glossary.
 
 ```bash
-awk '/^## 1\./{flag=1} /^## 4\./{flag=0} flag' "$OUTPUT" \
+awk '/^## 1\./{flag=1} /^## 6\./{flag=0} flag' "$OUTPUT" \
   | grep -niE '/(seo|harden|validate|cso|feat|bugfix|ship-feature|ship|code-clean|refactor)\b|seo-analyzer|geo-analyzer|validator-analyzer|SEO\.md|HARDEN\.md|VALIDATE\.md|CSO\.md|MAX_ITERATIONS|ALL_PASS|SCORE_[A-Z_]+'
 # expected: no matches. Each match is a leak — rewrite the offending
 # chapter in client language before STEP 16.
 ```
 
+**Anchor-resolution gate** (clickable section refs work).
+
+```bash
+grep -oE '\]\(#[a-z0-9-]+\)' "$OUTPUT_MD" | tr -d ']()#' | sort -u > /tmp/refs.txt
+grep -oE 'id="[^"]+"' "$OUTPUT_HTML" | sed 's/id="//;s/"//' | sort -u > /tmp/ids.txt
+comm -23 /tmp/refs.txt /tmp/ids.txt
+# expected: empty. Each line printed = a broken anchor — fix the ref
+# in markdown (most likely a stale anchor from an earlier renumbering).
+```
+
 If either gate fails, fix and re-write the markdown before continuing.
 
 ---
@@ -1278,20 +1578,23 @@ BLOCKERS REMAINING: <count> (open)
 
 DOC SECTIONS WRITTEN:
   §1   Ce qu'il fallait faire (et pourquoi)
-  §2   Ce qui a été fait                  (≤ 300 mots, sans jargon)
-  §3   Ce qui vous reste à faire          (action checklist)
-  §4   Détails techniques                 (scores, choix, glossaire)
-  §5   Annexe — plateformes externes      (web only)
-  §6   Annexe — build & déploiement       (only if requested)
+  §2   Résultats — état de santé (avant / après)  (score table, impact)
+  §3   Ce qui a été fait                  (≤ 300 mots, sans jargon)
+  §4   Vos informations officielles (NAP) (source-of-truth, before todo)
+  §5   Ce qui vous reste à faire          (action checklist)
+  §6   Détails techniques                 (choix, phases, glossaire)
+  §7   Annexe — plateformes externes      (web only, NAP table not duplicated)
+  §8   Annexe — build & déploiement       (only if requested)
 
 Next steps for the user:
 1. Open <path-to-pdf> (or the .html) — verify cover page, branding,
-   and that the score table renders. Adjust the .md if needed and
+   §2 score table renders right after §1, §4 NAP table renders before
+   §5 todo list (clickable section refs work in PDF). Adjust .md and
    re-run STEP 16 to regenerate.
-2. Read the document end-to-end before sending — fill any
-   [À COMPLÉTER] / [À CONFIRMER] markers (NAP in §5 especially).
+2. Read end-to-end before sending — fill any [À COMPLÉTER] /
+   [À CONFIRMER] markers (NAP fields in §4 especially).
 3. Save a copy outside the repo (the .pdf is already client-ready).
-4. Walk through §3 (ce qui vous reste à faire) with the client
+4. Walk through §5 (ce qui vous reste à faire) with the client
    during the handover meeting — that's the part they MUST act on.
 
 [If PDF was NOT generated, append:]
@@ -1389,12 +1692,12 @@ invent links.
 
 | Situation | Behavior |
 |---|---|
-| Repo has < 3 commits since first commit | Skip phase clustering in §3 of the deliverable; emit a short "First milestone" note instead. Do not fabricate phases. |
+| Repo has < 3 commits since first commit | Skip phase clustering in §5.2 of the deliverable; emit a short "First milestone" note instead. Do not fabricate phases. |
 | `git log` empty (newly-initialised repo, no commit yet) | Print `"⚠️ no git history — handover doc requires at least one commit. Run /commit-change first."` and STOP before generating the doc. |
 | Audit file exists but `Score:` line is malformed after re-dispatch retry | Mark `SCORE_<X>_AFTER=UNKNOWN`. Treat as below-threshold for STEP 8 gate (cannot certify). Append diagnostic to HANDOVER-ROADMAP.md: `"<audit> score unparseable — re-run /<audit> manually."` |
 | Audit file missing entirely after STEP 4 attempts | Same as malformed: UNKNOWN, gate fails. Note `"<audit> file absent — auto-fix loop produced no output, see .claude/audits/."` |
 | User confirms deploy in STEP 6 but `DEPLOYED_URL` is still empty | Re-prompt once: `"You confirmed Yes — what's the deployed URL? (paste URL or 'skip-validate' to set VALIDATE_SKIPPED=true)"`. On second empty answer, set VALIDATE_SKIPPED=true and proceed to STEP 8. |
 | Deploy URL paste returns HTTP 0 / DNS failure during STEP 7 | Retry once after 30s. Still failing → set VALIDATE_SKIPPED=true with reason `"unreachable: <error>"`. Do not block the handover doc. |
-| `.claude/memory/` registries do not exist | Skip the "Decisions / Learnings / Blockers" section in §3 with a one-line note: `"(no .claude/memory/ — registries not initialised on this project)."` Do not create them here — that is /onboard's job. |
+| `.claude/memory/` registries do not exist | Skip the "Decisions / Learnings / Blockers" section in §5 with a one-line note: `"(no .claude/memory/ — registries not initialised on this project)."` Do not create them here — that is /onboard's job. |
 | `--skip-audits` flag passed but `.claude/audits/` empty | STOP with `"--skip-audits requires existing audit files in .claude/audits/. None found — drop the flag or run /seo and /harden first."` |
 | Output file (LIVRAISON.md / HANDOVER.md) already exists | Show diff vs. new content. Ask `"overwrite / save as -v2 / abort?"`. Default behavior must not silently overwrite a curated client doc. |

+ 8 - 22
skills/client-handover/SKILL.md

@@ -1,28 +1,14 @@
 ---
 name: client-handover
 description: |
-  Final ship-and-handover orchestrator. End-to-end pipeline that hardens the
-  project, commits, pauses for deploy, validates the live site, and only then
-  generates the non-technical client deliverable as Markdown + branded HTML +
-  PDF (ZenQuality identity: green palette, Inter + Playfair Display fonts,
-  cover page with logo and tagline). The deliverable uses a 4-chapter
-  structure: §1 what was needed and why, §2 what was done (≤300 words, zero
-  jargon, no internal tool/skill names), §3 what the client must do (action
-  checklist), §4 technical details for the curious (scores, key choices,
-  glossary). Pipeline: (1) /seo (SEO+GEO) and /harden run in parallel with
-  auto-fix loops until each score ≥17/20, (2) /commit-change + push if
-  changes made, (3) pause to tell user what to deploy and wait for
-  confirmation, (4) /validate against the live site, (5) per-axis gate
-  ≥17/20 — stop and analyze if any below, (6) write client doc + render
-  branded HTML/PDF. Reads git history + .claude/memory/ registries. For
-  local-business projects, appends manual SEO/GEO platform checklist (NAP
-  consistency across Google Business, Pages Jaunes, Yelp, Facebook,
-  Instagram, TikTok, Apple Maps, Bing Places, TripAdvisor, etc.). Asks
-  whether to include build/deploy chapter.
-  Trigger: "client handover", "compte rendu client", "livraison client",
-  "synthese projet", "rapport client", "deliverable", "summary for client",
-  "recap projet", "handover doc", "livrable", "ship and handover",
-  "finaliser et livrer".
+  Use when finalizing a project for non-technical client delivery — needs
+  final audits, deploy validation against live site, and a branded
+  deliverable (Markdown + HTML + PDF). Multi-agent orchestrator: dispatches
+  client-handover-writer which spawns parallel /seo + /harden subagents,
+  then /validate, then writes the deliverable.
+  Triggers: "client handover", "compte rendu client", "livraison client",
+  "rapport client", "deliverable", "summary for client", "handover doc",
+  "livrable", "ship and handover", "finaliser et livrer".
 argument-hint: [optional: language fr|en, --include-deploy, --skip-deploy, --skip-seo, --skip-audits, --skip-fix-loop, --max-iterations N, --audit-max-age <duration>, --output <path>]
 disable-model-invocation: false
 allowed-tools:

+ 34 - 22
skills/client-handover/checklists/seo-geo-manual.md

@@ -47,15 +47,16 @@ manquante dans l'adresse) divise votre visibilité Google.
 Choisissez UNE seule version officielle de chaque champ et utilisez-la
 **à l'identique partout** :
 
-| Champ          | Valeur officielle à utiliser partout                       |
-|----------------|------------------------------------------------------------|
-| Nom commercial | [À COMPLÉTER — exactement comme sur le Kbis]              |
-| Adresse        | [À COMPLÉTER — n° rue, code postal, ville]                |
-| Téléphone      | [À COMPLÉTER — format: +33 X XX XX XX XX]                |
-| Email pro      | [À COMPLÉTER]                                             |
-| Site web       | [À COMPLÉTER — avec le https://]                          |
-| Horaires       | [À COMPLÉTER — ligne par jour, format 24h: 09:00–18:00]   |
-| Catégorie      | [À COMPLÉTER — la principale, ex: "Restaurant italien"]   |
+| Champ              | Valeur officielle à utiliser partout                       |
+|--------------------|------------------------------------------------------------|
+| Nom commercial     | [À COMPLÉTER — exactement comme sur le Kbis]              |
+| Adresse            | [À COMPLÉTER — n° rue, code postal, ville]                |
+| Téléphone          | [À COMPLÉTER — format: +33 X XX XX XX XX]                |
+| Email pro          | [À COMPLÉTER]                                             |
+| Site web           | [À COMPLÉTER — avec le https://]                          |
+| Catégorie          | [À COMPLÉTER — la principale, ex: "Restaurant italien"]   |
+| Description courte | [À COMPLÉTER — 1-2 phrases, voir hero / meta description du site, à recopier identique partout (Google Business, Bing, Apple, annuaires)] |
+| Horaires           | [À COMPLÉTER — ligne par jour, format 24h: 09:00–18:00]   |
 
 Notez ces informations dans un fichier que vous gardez à portée de main —
 vous allez les recopier 10 fois.
@@ -217,8 +218,13 @@ Google vous remonte.
   https://search.google.com/search-console
 - **Google Business Insights** — accessible depuis votre fiche Google
   Business Profile, montre les recherches qui mènent à vous.
-- **BrightLocal Free Tools** — vérifier la cohérence de votre NAP sur
-  les annuaires : https://www.brightlocal.com/free-local-tools/
+- **Moz Local — Citation Checker (gratuit)** — audit 60 s qui vérifie
+  la cohérence NAP de votre fiche sur 50+ annuaires (Google Business,
+  Apple Plans, Yelp, Pages Jaunes, etc.) et signale doublons et
+  incohérences : https://moz.com/local (cliquer « Check My Listing »
+  ou « Get Free Audit » en page d'accueil — pas de carte bancaire
+  demandée). Remplace l'ancien outil BrightLocal Free Tools (page
+  retirée par BrightLocal en 2026, service maintenant payant).
 - **PageSpeed Insights** — vérifier que le site reste rapide :
   https://pagespeed.web.dev/
 
@@ -261,15 +267,16 @@ Google visibility.
 Pick ONE official version of each field and use it **identically
 everywhere**:
 
-| Field            | Official value to use everywhere                |
-|------------------|--------------------------------------------------|
-| Business name    | [TO FILL — exactly as registered]               |
-| Address          | [TO FILL — street, city, ZIP, country]          |
-| Phone            | [TO FILL — format: +1 XXX XXX XXXX]             |
-| Pro email        | [TO FILL]                                       |
-| Website          | [TO FILL — with https://]                       |
-| Hours            | [TO FILL — per day, 24h format: 09:00-18:00]    |
-| Primary category | [TO FILL — e.g., "Italian restaurant"]          |
+| Field             | Official value to use everywhere                |
+|-------------------|--------------------------------------------------|
+| Business name     | [TO FILL — exactly as registered]               |
+| Address           | [TO FILL — street, city, ZIP, country]          |
+| Phone             | [TO FILL — format: +1 XXX XXX XXXX]             |
+| Pro email         | [TO FILL]                                       |
+| Website           | [TO FILL — with https://]                       |
+| Primary category  | [TO FILL — e.g., "Italian restaurant"]          |
+| Short description | [TO FILL — 1-2 sentences, lift from site hero / meta description, paste identically everywhere (Google Business, Bing, Apple, directories)] |
+| Hours             | [TO FILL — per day, 24h format: 09:00-18:00]    |
 
 Save these in a file you can reach in two clicks. You will copy them 10
 times.
@@ -422,8 +429,13 @@ results. More reviews (positive AND recent) = higher Google ranking.
   https://search.google.com/search-console
 - **Google Business Insights** — inside your Google Business Profile,
   shows what searches lead to you.
-- **BrightLocal Free Tools** — verify NAP consistency across directories:
-  https://www.brightlocal.com/free-local-tools/
+- **Moz Local — Citation Checker (free)** — 60-second audit checking
+  NAP consistency across 50+ directories (Google Business, Apple
+  Maps, Yelp, etc.) and flagging duplicates and inconsistencies:
+  https://moz.com/local (click "Check My Listing" or "Get Free
+  Audit" on the homepage — no credit card required). Replaces the
+  former BrightLocal Free Tools (page removed by BrightLocal in
+  2026, service now paid-only).
 - **PageSpeed Insights** — confirm site stays fast:
   https://pagespeed.web.dev/
 

+ 20 - 6
skills/client-handover/resources/branding/zenquality.css

@@ -372,7 +372,6 @@ ul.task-list li {
 
 ul.checklist li::before,
 ul.task-list li::before,
-li input[type="checkbox"] + *,
 li.task-list-item::before {
   content: "☐";
   position: absolute;
@@ -382,13 +381,28 @@ li.task-list-item::before {
   line-height: 1;
 }
 
-input[type="checkbox"] {
-  display: none;
+/* Pandoc GFM emits <li><input disabled type="checkbox"> text...</li> with
+   no wrapper class. Render the native checkbox inline (small, green) and
+   leave inline elements (<a>, <code>, <strong>) that follow it untouched.
+   Earlier rule `li input[type="checkbox"] + *` mistakenly absolutely-
+   positioned the first element sibling after the checkbox, yanking links
+   and code spans out of flow and overlapping adjacent content. */
+li > input[type="checkbox"] {
+  appearance: none;
+  -webkit-appearance: none;
+  display: inline-block;
+  width: 3mm;
+  height: 3mm;
+  margin: 0 1.5mm 0 0;
+  border: 0.4mm solid var(--green-moss);
+  border-radius: 0.5mm;
+  vertical-align: middle;
+  background: transparent;
 }
 
-input[type="checkbox"]:checked + label::before {
-  content: "☑";
-  color: var(--green-forest);
+li > input[type="checkbox"]:checked {
+  background: var(--green-forest);
+  border-color: var(--green-forest);
 }
 
 /* ============ CALLOUTS ============ */

+ 1 - 1
skills/client-handover/scripts/handover-to-pdf.sh

@@ -121,7 +121,7 @@ fi
 md_to_html_body() {
   local src="$1"
   if command -v pandoc >/dev/null 2>&1; then
-    pandoc --from=gfm --to=html5 --no-highlight "$src"
+    pandoc --from=gfm+gfm_auto_identifiers --to=html5 --no-highlight "$src"
     return
   fi
   if command -v python3 >/dev/null 2>&1 && python3 -c "import markdown" >/dev/null 2>&1; then

+ 8 - 16
skills/doc/SKILL.md

@@ -1,22 +1,14 @@
 ---
 name: doc
 description: |
-  Full documentation audit and sync. Auto-detects what doc files the project
-  actually has — root docs (README, CLAUDE.md, INSTALL.md, CONFIGURE.md,
-  USAGE.md, DEPLOY.md, CONTRIBUTING.md, CHANGELOG.md), docs/**/*.md, project-state
-  files in .claude/{tasks,audits,memory}/, and inline comments (JSDoc, docstrings,
-  rustdoc, godoc). Stack-aware: detects framework + deploy complexity, proposes
-  DEPLOY.md only when non-trivial (Docker, fly.toml, k8s, multi-stage CI), skips
-  for trivial deploys (FTP push, single scp, plain static). Enforces README
-  presence with typical GitHub layout (title, quick start, links to existing
-  sub-docs). Cross-references git history for drift; detects added features
-  missing from docs and removed features still documented (feature delta
-  detection). Reports drift with commit refs, proposes fixes, patches approved
-  items.
-  Trigger: "doc", "sync docs", "audit docs", "update readme", "check documentation",
-  "are docs up to date", "documentation drift", "stale docs", "new feature not documented",
-  "removed feature still in docs", "create README", "should I have a DEPLOY doc".
-  Replaces the old /readme skill with broader scope.
+  Use when documentation may be out of sync with code — added features
+  missing from docs, removed features still documented, or README / INSTALL
+  / DEPLOY / CHANGELOG drift detected. Stack-aware audit, cross-references
+  git history, patches approved items.
+  Triggers: "doc", "sync docs", "audit docs", "update readme", "check
+  documentation", "are docs up to date", "documentation drift", "stale docs",
+  "new feature not documented", "removed feature still in docs",
+  "create README", "should I have a DEPLOY doc".
 argument-hint: [leave empty for full audit, or list specific files/docs to check]
 disable-model-invocation: false
 allowed-tools:

+ 9 - 14
skills/geo/SKILL.md

@@ -1,20 +1,15 @@
 ---
 name: geo
 description: |
-  Standalone GEO (Generative Engine Optimization) audit for AI search
-  engines: ChatGPT, Perplexity, Claude, Gemini, Google AI Overviews,
-  Microsoft Copilot, Brave AI, DuckAssist, You.com, Apple Intelligence.
-  Audits AI crawler directives, llms.txt / llms-full.txt, Schema.org
-  types optimised for AI extraction (QAPage, Speakable, Person+Article,
-  HowTo, Organization graph), entity SEO (Wikidata, sameAs, @id,
-  Knowledge Panel), content shape for LLM extraction (Definition Lead,
-  TL;DR, Q→A structure, citable stats, freshness), and live AI
-  visibility monitoring.
-  For full SEO + GEO combined audit → use /seo (runs seo + geo in parallel).
-  For classical SEO only → use /seo and skip the GEO section.
-  Trigger: "geo", "AI search", "ChatGPT visibility", "Perplexity optimisation",
-  "llms.txt", "AI crawlers", "Google AI Overview", "entity SEO", "Wikidata",
-  "generative engine optimization", "référencement IA", "optimisation IA".
+  Use when a web project needs AI-search visibility audit — ChatGPT,
+  Perplexity, Claude, Gemini, AI Overviews, Copilot, Brave AI, DuckAssist,
+  You.com, Apple Intelligence. Standalone GEO; dispatches the geo-analyzer
+  agent.
+  Triggers: "geo", "AI search", "ChatGPT visibility", "Perplexity
+  optimisation", "llms.txt", "AI crawlers", "Google AI Overview",
+  "entity SEO", "Wikidata", "generative engine optimization",
+  "référencement IA", "optimisation IA".
+  For combined SEO+GEO → /seo.
 argument-hint: optional keywords/scope, e.g. "SaaS B2B content GEO" or "audit llms.txt et entity SEO"
 allowed-tools:
   - Read

+ 1 - 1
skills/init-project/SKILL.md

@@ -1,6 +1,6 @@
 ---
 name: init-project
-description: Full project init: interview → design → scaffold → implement (TDD). Two validation gates.
+description: Use when initializing a brand-new project from scratch — needs interview, design, scaffold, and TDD implementation. Multi-agent orchestrator: plugin-advisor + interviewer + analyzer + scaffolder with two validation gates. Triggers: "init project", "new project", "start project from scratch", "scaffold project", "init-project".
 argument-hint: <project idea or description>
 disable-model-invocation: true
 allowed-tools: Read, Write, Edit, Bash, Grep, Glob

+ 1 - 1
skills/onboard/SKILL.md

@@ -1,6 +1,6 @@
 ---
 name: onboard
-description: Onboard an existing repo — detect archetype, install claude-config, run full audit (debt/SEO/GEO/UI-UX/perf/security/a11y/docs), output prioritized improvement plan in .claude/audits/ + .claude/tasks/. Use on repos not created via /init-project.
+description: Use when bringing an existing repo into the claude-config framework — needs archetype detection, config install, full multi-axis audit (debt/SEO/GEO/UI-UX/perf/security/a11y/docs), and prioritized backlog. Multi-agent orchestrator. Do NOT use for repos created via /init-project. Triggers: "onboard", "onboard project", "audit existing repo", "setup existing project".
 argument-hint: [optional hints: "Python FastAPI" | "add gsd" | "Next.js monorepo" | "force-archetype:wordpress"]
 disable-model-invocation: true
 allowed-tools: Read, Write, Edit, Bash, Glob, Grep

+ 10 - 19
skills/seo/SKILL.md

@@ -1,25 +1,16 @@
 ---
 name: seo
 description: |
-  Full SEO + GEO audit and optimization for any web project.
-  Runs the seo-analyzer (classical search — Google, Bing, DuckDuckGo)
-  and geo-analyzer (AI search — ChatGPT, Perplexity, Claude, Gemini,
-  Google AI Overviews, Copilot) IN PARALLEL, then consolidates their
-  output into a unified .claude/audits/SEO.md report.
-  Covers: meta, OG, JSON-LD (classical + GEO-optimised schemas),
-  sitemap, robots.txt (including AI crawlers), llms.txt, headings,
-  alt attrs, canonicals, hreflang, Core Web Vitals, entity SEO
-  (Wikidata, sameAs, Knowledge Panel), content shape for AI extraction,
-  AI visibility monitoring.
-  Trigger: "seo", "referencement", "optimize for search", "audit SEO",
-  "meta tags", "structured data", "JSON-LD", "sitemap", "robots.txt",
-  "Google ranking", "local SEO", "referencement local", "fiche Google",
-  "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.
+  Use when a web project needs SEO + GEO audit or optimization — classical
+  search (Google, Bing, DuckDuckGo) AND AI search (ChatGPT, Perplexity,
+  Claude, Gemini, AI Overviews, Copilot). Parallel multi-agent orchestrator:
+  dispatches seo-analyzer + geo-analyzer concurrently, merges envelopes into
+  .claude/audits/SEO.md.
+  Triggers: "seo", "referencement", "audit SEO", "meta tags",
+  "structured data", "JSON-LD", "sitemap", "robots.txt", "Google ranking",
+  "local SEO", "AI search", "GEO", "llms.txt", "ChatGPT visibility",
+  "Perplexity", "Google AI Overview".
+  For GEO only → /geo. For W3C/a11y → /validate. For bugs → /bugfix.
 argument-hint: optional keywords/scope, e.g. "local SEO plombier 91 94 77" or "SaaS B2B content strategy"
 allowed-tools:
   - Read

+ 1 - 1
skills/ship-feature/SKILL.md

@@ -1,6 +1,6 @@
 ---
 name: ship-feature
-description: Ship feature end-to-end: design → plan → implement (TDD) → review → finish
+description: Use when shipping a new feature end-to-end — needs design brainstorm, planning, TDD implementation with subagents, error recovery, code review, and finish. Multi-agent orchestrator (9-step pipeline). Triggers: "ship feature", "ship-feature", "build and merge", "feature end-to-end", "implement and ship".
 argument-hint: <feature description>
 disable-model-invocation: true
 allowed-tools: Read, Write, Edit, Bash, Grep, Glob

+ 8 - 14
skills/validate/SKILL.md

@@ -1,20 +1,14 @@
 ---
 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 .claude/audits/VALIDATE.md.
-  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.
+  Use when a web project needs W3C HTML/CSS validity check or WCAG 2.1
+  accessibility audit. Dispatches the validator-analyzer agent with a
+  STRICT scope filter (no meta/OG/JSON-LD/CWV/security-header noise).
+  Triggers: "validate", "validation", "w3c", "html validity",
+  "css validity", "wcag", "accessibility", "a11y audit", "axe", "pa11y",
+  "wave", "validator.w3.org", "nu validator", "accessibilité",
+  "audit a11y", "audit wcag", "normes w3c", "conformité web".
+  For CSP/HSTS/404 → /harden. For meta/sitemap → /seo. For AI engines → /geo.
 argument-hint: [URL] [--fix] [--local|--full] [--no-external]
 allowed-tools:
   - Read