# Schwung Merkscan v3 · complete review en kennis-dump

> Brede technische en conceptuele review van de live v3-merkscan: codestructuur, denkwijze, doctrine, output-keten, opbrengst, en bekende zwakke plekken. Stand 11 juni 2026. Bron: directe code- en doctrine-lezing. Compagnon-document van de A4 (`2026-06-11-v3-scan-werking-A4.md`).

## 0. Leeswijzer

Dit document is de "motorkap-open" versie. Het beschrijft niet alleen wat de scan doet, maar hoe hij is gebouwd, waarom hij zo is gebouwd, en waar de naden zitten. Vier delen:

- **Deel A · Architectuur** — waar alles staat, de keten end-to-end, de databasestaat.
- **Deel B · De gespreksmotor** — de reactieve diagnose-engine, de zetten, de vijf guardrails, verificatie, citaat-check.
- **Deel C · De output-keten** — wegers, regie, schrijf, en hoe een gesprek een rapport wordt.
- **Deel D · Doctrine en denkwijze** — de scherpte-filosofie, de routes, de schrijfregels; en het eerlijke zwakteregister.

---

## DEEL A · ARCHITECTUUR

### A1. Waar de v3 woont

Sinds eind mei is v3 de hoofdscan: `merkscan.schwung.ai/` rewrite't (status 200) naar `/v3/start.html` (`netlify.toml`). v1 (`/v1`) en v2 (`/v2`) blijven bereikbaar als bevroren etalagestukken; alleen v3 leeft verder.

Vier lagen:

| Laag | Locatie | Inhoud |
|---|---|---|
| Frontend | `v3/` | `start.html` · `intake.html` (1474 r, de chat-motor) · `merkbeeld.html` + `-detail.html` + `merkbeeld-data.js` · `result.html` |
| Backend | `netlify/functions/v3-*.js` | ~35 functies (zie A3) |
| Gedeelde logica | `_lib/v3/` | `intake-state.js` · `vragenset.js` · `pre-background.js` · `weger-background.js` · `weger-starter.js` · `doctrine-loader.js` · `agent-helpers.js` · `discipline-info.js` · `mail-templates.js` · `run-agent-direct.js` |
| Doctrine | `doctrine/` | ~33 markdown-bestanden, ingeladen per agent via LOADLIST |

De motor-kern zit in twee bestanden: `_lib/v3/intake-state.js` (gespreksregie + guardrails) en `netlify/functions/v3-agent-regie-background.js` (bevindingen-weging → kernspanning → route).

### A2. De keten end-to-end

```
start.html (formulier: naam, url, 2 concurrenten, type solo/team)
   │  POST → v3-intake (honeypot + plausibiliteitscheck → sessie + token)
   ▼
v3-scan-async(-background)            [crawl ~3-12 min, async]
   ├─ Jina-crawl van de site (+ sitemap, PDF-extractie, uploads)
   ├─ Anthropic DESTEP-marktanalyse
   ├─ 2 concurrenten geanalyseerd
   └─ 5 pre-jobs aangemaakt + parallel getriggerd
        ▼
   5× v3-agent-{disc}-pre-background  [abductieve hypothese per discipline]
        ▼
   MAIL 1 ("je scan is klaar — open de chat")
   ▼
intake.html?token=…                  [het reactieve diagnose-gesprek]
   ├─ v3-agent-intake (starter) → v3-agent-intake-background (per beurt)
   ├─ opening (JTBD Q1/Q2) → differentiaal → afdaling → verificatie → klaar
   ├─ tussendoor: merkbeeld.html (woord + beeld → Quinn + archetype)
   └─ klaar-turn: klant_samenvatting + 8-12 kandidaat_bevindingen + beslissingen
        ▼
v3-agent-orchestrator(-background)    [server-side, ~1.5-2 min]
   ├─ 5× weger (parallel)  → score 0-3 per bevinding op "draagt het gat" + 1 hefboom
   ├─ regie               → categoriseer, top 6-8, kernspanning, route, dekkings-check
   └─ schrijf             → 4 koppen reflectie + wat-helpt
        ▼
   MAIL 2 ("je rapport is klaar")
   ▼
result.html?token=…                  [hero kernspanning → reflectie → Schwung Match → Merk in Beeld]
```

De orchestrator heeft een heartbeat (patcht `updated_at` elke ~30s) en is idempotent; `cron-pipeline-revive` (elke 5 min) herstart vastgelopen orchestrator-jobs én — sinds v0.2.0 (11 juni) — geërrorde pre-jobs binnen een venster van 90s-3h (vangt een Anthropic-credit-dip op).

### A3. Backend-functies (v3-prefix), gegroepeerd

- **Entree/crawl**: `v3-intake` (sync, bot-check + sessie) · `v3-scan-async` + `-background` (crawl + DESTEP + concurrenten) · `v3-scan-meta` (read voor result.html).
- **Pre-jobs (5)**: `v3-agent-{branding,arbeidsmarkt,creatie,web-ai,marketing}-pre-background` — abductieve hypothese per discipline.
- **Gesprek**: `v3-agent-intake` (starter) + `v3-agent-intake-background` (de motor) · `v3-agent-merkbeeld-save`.
- **Wegers (5)**: `v3-agent-{disc}` (starter) + `-background` (scoring).
- **Synthese**: `v3-agent-regie` + `-background` (de kern) · `v3-agent-schrijf` + `-background`.
- **Orkestratie/status**: `v3-agent-orchestrator` + `-background` · `v3-agent-status` (polling) · `v3-pipeline-status` (volledige staat per token).
- **Comms**: `v3-feedback-submit` · `v3-stuur-mail` · `v3-stuur-rapport-mail` · `v3-sla-antwoorden-op`.

Patroon: elke zware agent is een **sync starter** (maakt `agent_jobs`-rij, triggert background, retourneert job_id) plus een **async background** (doet het werk, patcht de rij naar done/error). De UI polt `v3-agent-status`.

### A4. Databasestaat

Supabase prod `etfxariiivdemimrrcfk` (Frankfurt). Kerntabellen: `sessies` · `invullers` (met `token`, `is_aanvrager`) · `scan_resultaten` (website_data, markt_data, conc1/2_data; let op kolom `aangemaakt_op`, niet `created_at`) · `agent_jobs` (de werkpaard-tabel: `agent_name`, `status` pending/running/done/error, `result` jsonb, `error_message`, `created_at`/`updated_at`). De volledige gespreks- en bevindingen-staat wordt elke beurt herbouwd uit `agent_jobs`-rijen (zie B2), dus de DB is de single source of truth voor de gespreksstaat.

---

## DEEL B · DE GESPREKSMOTOR

### B1. De centrale denkwijze: LLM stelt voor, code bewaakt

De architectuur-keuze die alles stuurt (`v3-agent-intake-background.js:3-6`): *"de LLM stélt per turn de volgende zet voor — op basis van wat de invuller net zei; de code BEWAAKT dat voorstel tegen de bug-grenzen."* De macro-flow is code-driven (het bug-net tegen terugspringen, dubbele overgang, vragen-loop); de micro-diepte (doorgraven of stoppen) is LLM-side, begrensd door de stop-regel en de caps.

Dit is het directe antwoord op de v1/v2-kritiek: een vragenlijst voelt als een vragenlijst omdat de volgorde vaststaat. Hier reageert elke beurt op wat de invuller net zei, maar zonder dat de LLM de bewezen bug-klassen (loops, terugsprongen) opnieuw introduceert.

### B2. De macro-staat (één boog)

Fasen: `opening → differentiaal → afdaling → waarde (visuele scan) → verificatie → klaar`. De staat wordt **elke beurt vers herbouwd** door alle turn-rijen te replayen (`buildStateUitTurns`). Per beurt bijgehouden:

- **`hypotheses[]`** — de 5 pre-hypotheses, elk met `status` (open → levend → bevestigd/verworpen), `turns` (verdiepingsbeurten op deze draad), `geen_voortgang` (lege beurten).
- **`trace_nodes[]`** — per diagnose-beurt: `hypothese_id`, `zet_type`, `quote`, `classificatie`.
- **opening_done** (Q1/Q2), **job** (symptoom + frame klant/werkgevers/beide), **verificatie_stap/afwijzingen/correctie**.

Eén LLM-call per beurt doet dubbel werk (`klassificeerEnKiesZet`): classificeert het vorige antwoord (→ trace_node) én kiest de volgende zet.

### B3. De zetten (let op: twee vocabulaires)

Doctrinaal (uit `t-formulier-differentiaal.md`, in `vragenset.js`) zijn er vijf zet-types: **ontkoppel** (haal de zelfbedachte oplossing eraf), **zak** (één draad naar beneden: symptoom → oorzaak → gedrag/overtuiging), **toets** (leg een klant-woord of pre-hypothese terug, dwing scherpte), **check_zijwaarts** (open een naburige differentiaal-tak), **kaats_terug** (benoem het gat + hefbomen als duiding; eindpunt, niet oplossen — de CTA is Schwung).

Maar de **LLM kiest runtime uit een ánder vijftal**: `zak · toets · wissel · volg · verifieer`. De code mapt die op de zet_types en wijst `ontkoppel`/`check_zijwaarts`/`kaats_terug` zelf toe op basis van fase. Voor begripsvorming: het doctrinaire vijftal is de denktaal, het runtime-vijftal is de stuurtaal. (Dit is een begripsvalkuil, geen bug — wel iets om consistent te benoemen.)

De zet-keuze-prompt instrueert expliciet om de diepte te borgen: *"een hypothese die net geopend is (0 afdaling-turns) verdient éérst minstens één 'zak' of 'toets' — veeg niet langs alle hypotheses zonder er één echt uit te diepen."* En reageert op sturing van de invuller ("ga verder / rond af" → verifieer).

### B4. De vijf guardrails (in code afgedwongen)

| # | Naam | Constante | Voorkomt | Afdwingplek |
|---|---|---|---|---|
| 1 | turn-cap | `MAX_DIAGNOSE_TURNS=15` | eindeloos doorgraven | `valideerZet` forceert afronding bij ≥15 |
| 2 | anti-loop | `MAX_GEEN_VOORTGANG=2` | draad blijft hangen op vage/ontwijkende antwoorden | 2 lege beurten → status forced `bevestigd` |
| 3 | dekkings-vloer | `MIN_HYPOTHESES_GERAAKT=3` | te vroeg afronden na te weinig hypotheses | premature `verifieer` wordt overruled naar nieuwe hypothese openen |
| 4 | geen-terugsprong | `MAX_AFDALING_PER_HYPOTHESE=4` | heropenen van afgeronde/verworpen draad | draad met ≥4 turns of niet-levend → andere draad |
| 5 | laddering-vloer | `MIN_AFDALING_VOOR_BODEM=1` | uiteenvallen tot vragenlijst (de 18-mei testfout) | bodem-classificatie op openingsbeurt sluit de hypothese NIET; verse draad wordt eerst gelladderd |

Plus `MAX_HYPOTHESES_GETOETST=5` (budget) en `MAX_VERIFICATIE_HEROPEN=1` (zie B6). Guardrail 5 is het hart van waarom v3 geen vragenlijst wordt: zonder die vloer kortsluit de stop-regel de hele afdaling en veeg je langs alle hypotheses zonder er één uit te diepen.

### B5. De bodem (stop-regel)

Een draad sluit (`status → bevestigd`) zodra één van: een **bodem-classificatie** (`gedrag_overtuiging` of `duiding_aangeboden`) na ≥1 verdiepingsbeurt; de LLM markeert de hypothese als bevestigd/verworpen; de anti-loop vuurt; of de 4-turns-cap is geraakt. De doctrinaire afdaling is "zak tot gedrag of overtuiging": je hebt bodem als het antwoord concreet gedrag of een overtuiging raakt, óf als de invuller je de duiding zelf overhandigt.

### B6. De verificatie-poort (member-checking)

Aan het eind legt de motor zijn lezing van het gat voor. Het oordeel of de invuller bevestigt is **geen knop maar een LLM-oordeel** (`llmVerificatieOordeel`): `bevestigd` / `gecorrigeerd` / `onvolledig`. Een licht "ja, maar" telt als bevestigd; alleen een echte correctie of "dit mist nog" telt als afwijzing. Dit is wat de holle ja-knik voorkomt — het oordeel hangt aan de inhoud van de reactie.

Een afwijzing **heropent de diagnose** op de aangewezen hypothese-draad (`status → levend`, turns teruggeklemd zodat er ruimte is om te ladderen), maximaal 1× (`MAX_VERIFICATIE_HEROPEN`). Bij een tweede afwijzing wordt afgerond, maar de onverwerkte correctie wordt verplicht in het rapport meegenomen (`verificatie_correctie` → injectie in de klaar-prompt: *"Verwerk deze in de klant_samenvatting ÉN maak er minstens één kandidaat_bevinding van. Negeer 'm niet — dit is het laatste wat de invuller zei."*). Fail-safe: als de oordeel-call faalt, default `bevestigd` (niet vastlopen).

### B7. De fuzzy citaat-check (waarheidspoort, laag 3)

`checkCitaten` extraheert elk citaat ≥18 tekens uit de agent-output en vergelijkt het met het invuller-corpus (alles wat de invuller zei). Twee trappen: (1) exacte genormaliseerde match (lowercase, leestekens weg); (2) fuzzy vangnet op inhoudswoord-overlap. **Drempel: <60% woord-overlap → geflagd als mogelijk verzonnen.** Rationale: een tikfout-correctie deelt bijna alle woorden, een echt verzonnen citaat deelt er weinig. Een treffer blokkeert de beurt niet — het is een zachte waarschuwing in `intern_log` + `citaat_waarschuwing`. Dit draait alleen op verificatie/klaar-output (waar de dure citaten landen).

### B8. De pre-hypothese-seeding

Reden van bestaan (`pre-background.js:9-12`): *"een chat die één draad afdaalt vertakt daar niet vanzelf in. De vooraf gevormde hypothese richt de chat op een draad die 'ie zelf niet zou openen."* Elk van de 5 disciplines levert één abductieve hypothese: `gat` (verankerd in website-citaat of markt-feit, geen cliché) · `hefboom` · `toets_vraag` (open, weerlegbaar, laat ook "nee" toe) · `pilaar` · `positie_op_as` (profit/hybride/impact). Zonder geldige pre-hypotheses start de scan niet (holle-scan-guard).

---

## DEEL C · DE OUTPUT-KETEN

### C1. De wegers: scoren op "draagt het gat" (de v3-omdraaiing)

De grootste v3-correctie (17 mei) zit hier. **Was**: score 0-3 op "raakt dit mijn discipline-kern" — dat strafte cross-cutting duiding structureel af (de kinderstad-bevinding: duiding scoorde ~1,4 en viel weg). **Nu**: de weger leest de differentiaal-trace (het gat) en scoort *hoe sterk een bevinding het gat draagt*:

- **3** — deze bevinding ís het gat, of een directe drager (cross-cutting mag).
- **2** — raakt het gat duidelijk.
- **1** — losse, echte observatie.
- **0** — niet relevant of klopt niet.

*"Een bevinding die meerdere disciplines raakt is dáárom juist sterk, niet zwak."* Elke weger benoemt verplicht één **hefboom** (strategisch of praktisch) op het centrale gat. Prominente wegers wegen rijk (~25 w/bevinding) + mogen 0-2 eigen bevindingen toevoegen; marge-wegers wegen kort (~10 w) zonder toevoegen — maar met volle stem.

### C2. Regie: van scorematrix naar kernspanning + route

De rekenkunde gebeurt in code (`bouwBevindingenMatrix`: `avg = som/aantal`, `spread = max − min`). De LLM categoriseert en kiest:

- **Categoriseer** (drempels): *structureel* (avg ≥2.0, spread ≤1) · *polariserend* (avg ≥2.0, spread ≥2) · *gewoon* (1.5-2.0, spread ≤1) · *niche* (1.5-2.0, spread ≥2) · *single-agent* (max 1-2 in top-N) · *zwak* (<1.5, eruit).
- **Top 6-8 met spreiding-eis**: ≥3 van 4 pilaren · ≥3 van 4 perspectieven · ≥1 bevestiging tussen de spanningen · spiegel-balans (klant + kandidaat als beide in scope).
- **Gat-bescherming (Stap 2b, v3)**: een bevinding die HET GAT draagt hoort in de top-N óók bij grote spreiding — cross-cutting duiding krijgt per definitie ongelijke discipline-scores. *"Het gat is de ruggengraat van het rapport, geen losse node."*
- **Kernspanning** = het gat in één zin (12-22 w), geen jargon, een spanning of paradox erin, observatie geen advies. Niet iets nieuws uit de matrix verzinnen.
- **Route** = 1 van 8 (zie D2), gestuurd door levensfase (fase) + FOCUS (spiegel).
- **Dekkings-check** (hard): alle 4 pilaren ≥1 bevinding · ≥3 van 4 perspectieven · ≥1 bevestiging · spiegel-balans. Onvulbare pilaar → `witte_vlekken` (schrijf benoemt het als observatie).
- **Hefbomenkaart**: de 5 weger-hefbomen gebundeld en aangescherpt op het gat, elk strategisch/praktisch.

Regie levert ook `merkwaardering` (titel + uitleg, geen cijfer) en `signalen_duiding` (de 8 donuts in klant-taal). maxTokens staat op 12000 (5000 brak af op rijke intakes).

### C3. Schrijf: van regie-bundel naar leestekst

Twee blokken. **Reflectie** = 4 koppen, in vaste volgorde: *Wat hier speelt* (de duiding; opent verplicht met invuller-citaat, **nooit** een website-observatie) · *Waar het wringt* · *Wat dit zegt over het merk* · *De opgave* (geen advies). Per kop 1 alinea, 3-5 zinnen, 90-130 woorden, totaal ~480. De HERO-kernspanning is van regie, niet van schrijf — de reflectie onderbouwt 'm, herhaalt 'm niet. **Wat zou helpen** = de hefbomen als lopende tekst (geen bullets), suggestief, met de praktische hefboom als eerste zet. Stuurt daarna Mail 2.

### C4. result.html · de dramaturgie

Verticaal, top-naar-onder: **HERO kernspanning** (full-bleed) → **reflectie** (4 koppen) → **wat-helpt** → **Schwung Match** (route-naam + fase + motivatie + "Plan een gesprek"-CTA) → **diensten-strook** → **Merk in Beeld-doorklik** → contact-CTA. Bewust: het rapport leidt met diagnose en conversie; de onderbouwing (merkwaardering, signalen, Quinn/archetype, concurrentie, witte ruimte) staat één klik dieper op `merkbeeld-detail.html`.

---

## DEEL D · DOCTRINE EN DENKWIJZE

### D1. De scherpte-doctrine (de ziel van de waarde)

`doctrine/schrijven/scherpte.md` is geschreven na de 14-mei-bevinding dat de keten "niks deed dat de website al niet zei". **Duiding** = een uitspraak die (a) niet op de site staat, (b) de invuller niet letterlijk zei maar herkent zodra hij het hoort, (c) twee bronnen verbindt die los niets betekenen, (d) een lever impliceert zonder advies. *"Duiding is interpretatie die werk doet."*

Vijf scherpte-testen (0-2 elk, intern bedoeld als zelf-check): **T1 verrast het de klant?** · **T2 klopt het specifiek?** (verweven met letterlijke fragmenten) · **T3 wijst het een lever aan?** (maandag oppakbaar) · **T4 is het uitwisselbaar?** (zou dit rapport met andere namen voor 5 anderen gelden? dan 0) · **T5 voelt de klant zich gezien?** (bronnen inhoudelijk geweven, niet als "(bron: X)"-label). Bandscores: 8-10 landt · 5-7 vergeten binnen een dag · 0-4 boilerplate met een naam erin.

Antipatronen (verboden): de aankondigings-opener ("Wat opvalt…"), de voorzichtigheids-mitigator ("mogelijk/wellicht"), de abstracte categorisering ("positionerings-uitdaging"), de brondoublet, de parallelle structuur ("X is onduidelijk. Y is onduidelijk."), de afsluit-cliché ("De volgende stap is met Schwung bespreken…"), de ge-genericeerde drijfveer.

De meetstreep: *"niet 'is dit rapport correct?' maar 'zou de klant ons aanhuren op basis van dit rapport alleen?'"* Gouden referentie: het Appje-eitje-rapport (*"25 jaar boosheid heeft een product opgeleverd. Nu nog een stem die die boosheid waardig is."*, lever: *"Eerste werk is stem-werk, niet design-werk."*).

### D2. De 8 routes (4 fasen × 2 spiegels)

| Fase | Klantmerk | Werkgeversmerk |
|---|---|---|
| Merkontwikkeling (binnen→binnen) | **Merkfundament** | **EVP-sprint** |
| Merkactivatie (binnen→buiten) | **Activatie-concept** | **Arbeidsmarktcampagne** |
| Merkgroei (buiten→buiten) | **Merkuitbouw** | **Talentcyclus** |
| Merkbewaking (buiten→binnen) | **Merkmantra** | **Werkgevers-mantra** |

Kort per route (haakje = klant-taal die 'm triggert): Merkfundament — vage waarden/net gefuseerd ("we weten niet meer wie we zijn"). EVP-sprint — werkgeversmerk niet gedefinieerd ("we vinden geen mensen"). Activatie-concept — fundament staat, lage bekendheid ("we willen een campagne"). Arbeidsmarktcampagne — EVP staat, niet zichtbaar ("we willen een werving-campagne"). Merkuitbouw — bestaand merk, nieuwe segmenten ("we breiden uit naar X"). Talentcyclus — werving loopt, binden hapert ("we verliezen mensen na 1 jaar"). Merkmantra — volwassen merk, brand drift ("ons verhaal verschilt per kanaal"). Werkgevers-mantra — EVP staat, inconsistent uitgedragen ("vacatures zijn anders dan cultuur"). Regie noemt **nooit de routenaam in de reflectie-tekst** (de tekst beschrijft de inhoud), maar de naam verschijnt wel apart in het Schwung Match-blok.

### D3. De 5 harde schrijfregels

1. **Geen absolute markt-uitspraken** (2 concurrenten + DESTEP, geen survey). Wel: "in de twee onderzochte concurrenten…".
2. **Geen kwetsbare website-details** (geen 404's, broken links, SEO-score, design-kritiek). Merk-niveau mag, technisch niveau niet.
3. **Diagnose altijd met handelingsperspectief** (richting in de observatie, geen advies-stem).
4. **Data alleen om spanning te vergroten** (max 1 hoofd-DESTEP-feit + 1 ondersteunend datapunt per reflectie).
5. **Cliche-anti-patroon "geen X-probleem maar Y-probleem"** max 1× per reflectie.

Overkoepelend: "B1 met ballen" (eenvoudige taal voor scherpe dingen), "wij zijn de vertaler" (vakwoorden mogen, doctrine-jargon niet), en in de chat "Schwung als journalist, niet als consultant" (de intake-agent is de vragensteller, niet de duider — duiding komt pas in het rapport).

### D4. Zwakteregister (eerlijk, voor de evaluatie)

1. **Rubriek-drift in de wegers.** De code scoort op "draagt het gat", maar de weger-prompt laat `proces/weging-protocol.md` nog inlezen, dat de oudere "raakt mijn discipline-kern"-definitie van een 3 geeft. Twee tegenstrijdige definities in één call. *Risico*: inconsistente scoring. *Fix*: weging-protocol.md herschrijven naar de gat-rubriek, of de verwijzing schrappen.
2. **Scherpte-check niet ín de keten gewired.** `scherpte.md §6` ontwerpt een `scherpte_check`-veld (de 5 testen als zelf-check, voor regressie-logging). De schrijf-prompt vraagt het niet en de output slaat het niet op. Sinds 12 juni bestaat wel een los offline meet-script (`scripts/scherpte-eval.js`, 4 lagen) dat afgeronde scans scoort en het Scherpte-dashboard in `beheer.html` voedt. Maar de zelf-check *binnen* de live keten ontbreekt nog; dat blijft de grootste hefboom voor automatische regressie-logging per scan.
3. **Batch-evaluatie nog smal / variantie.** Per-scan-patchen werd op 18 mei het anti-patroon (elke randgeval-patch jaagt LLM-variantie achterna). Het structurele antwoord is deels gebouwd: `scherpte-eval.js` meet sinds 12 juni de output-scherpte per scan (adversarieel jury-panel + harde meters + website-delta). De actuele meetstand staat in het bewijs-blok hieronder (auto-ververst). De scores variëren nog met de keten-configuratie (o.a. DESTEP-marktanalyse, in onderzoek), dus te smal en te wisselend om stabiliteit te bewijzen. De bredere **evaluatie-tool** over alle 5 assen (techniek · online · concurrent · gesprek · output) is nog niet af.
4. **Twee zet-vocabulaires** (doctrinair vs runtime) — begripsverwarrend, geen bug, wel documenteren.
5. **Dekkings-check interne inconsistentie**: Stap 2 vraagt ≥3 van 4 pilaren, Stap 5 vraagt alle 4 pilaren. Strenger op de check dan op de selectie.
6. **Operationele afhankelijkheid**: de hele scan valt stil als het Anthropic-saldo op is (holle-scan-guard). Sinds 11 juni vangt `cron-pipeline-revive` v0.2.0 dit automatisch op zodra credits terug zijn; auto-reload bij Anthropic is de echte preventie.
7. **`doctrine/merk/gespreksmotor.md` bestaat niet** (CLAUDE.md verwijst er wel naar — stale). De gesprek-filosofie leeft in `_lib/v3/`-code en `denken/`-docs.

### D5. Wat sterk is (de andere kant)

- De **differentiaal-opzet** is een echt ander mechanisme dan een enquête: abductie vooraf + afdalen naar gedrag/overtuiging + member-check is methodisch verdedigbaar en zeldzaam in tooling.
- De **gat-omdraaiing in de wegers** repareert precies de structurele fout (cross-cutting duiding werd afgestraft) die de scan eerder waardeloos maakte.
- De **bewijs-integriteit** (fuzzy citaat-check + verplichte verwerking van correcties) is een serieuze rem op LLM-fabricatie.
- De **scherpte-doctrine** geeft een expliciete, hoge norm ("zou de klant ons aanhuren op dit rapport alleen?") die de meeste content-tools missen.
- De **vijf guardrails** zijn geen theorie maar reacties op echte testfouten (18 mei) — het systeem is hardened door gebruik.

---

## Vervolg (verrijkingsslagen)

Deze review is gebaseerd op code + doctrine. De eerste verrijkingsslag is sinds 12 juni gezet:
1. **Echte scan-output uit de prod-DB** lezen (afgeronde v3-scans: kernspanning, bevindingen, traces) → toetsen of de denkwijze in de praktijk duiding oplevert. *Gedaan*: `scherpte-eval.js` leest de prod-DB read-only en evalueert afgeronde scans.
2. **Verse scans tegen de 5 scherpte-testen leggen.** *Gedaan*: een adversarieel jury-panel scoort de output op de 5 testen, met een website-delta-test als directe maat voor toegevoegde waarde boven de site. Zie het bewijs-blok hieronder voor een uitgewerkt (geanonimiseerd) geval plus de actuele meetstand (auto-ververst uit `_results.json`).

Wat nog open is: een grotere batch voor stabiliteit, en de structurele eindstap: de bredere **evaluatie-tool** over alle 5 assen, met de scherpte-check gewired ín de schrijf-output voor automatische scoring per scan.

---

## Bewijs · doet de scan iets dat de site niet al zegt? (geanonimiseerd)

> **Waarom geanonimiseerd.** Een merkscan is een vertrouwelijke diagnose van een echte, vaak nog niet-klant-organisatie. De naam plus de letterlijke kernspanning publiceren zou de relatie en het vertrouwen schaden, en valt onder de anonimiseringsregel (`doctrine/learnings.md`). Het bewijs zit niet in *wie* de klant is, maar in het *mechanisme*: het gesprek legt iets bloot dat de website niet toont. Dat blijft volledig zichtbaar zonder de identiteit. Namen, sector-details en herkenbare formuleringen zijn daarom vervangen door neutrale omschrijvingen.

### De directe toets: site-only versus scan (de website-delta-test)

Laag 3 van `scherpte-eval.js` is hiervoor gebouwd. Eén jurylid schrijft de scherpst mogelijke kernspanning uit **alleen de website + marktdata** (geen gesprek). Een blinde tweede jury legt die naast de **échte** kernspanning uit de scan en oordeelt: voegt het gesprek iets toe dat de site onmogelijk kon weten?

**Uitgewerkt geval · een bureau dat werkgeversmerk-trajecten verkoopt (B2B)**

- *Wat de website alleen al gaf* (site-only baseline): "Het bureau belooft klanten een onweerstaanbaar werkgeversmerk, terwijl het eigen digitale fundament zichtbaar brokkelt."
- *Wat de scan eruit haalde* (na het diagnose-gesprek): "Het bureau verkoopt de kracht van werkgeversmerk aan anderen, maar laat zijn eigen merk op methode draaien."
- *Wat het gesprek toevoegde:* de site-versie ziet alleen een zichtbaar technisch verval. Het gesprek legt het diepere mechanisme bloot: de organisatie stuurt zichzelf intern aan op **methode** in plaats van op merkidentiteit, methode als substituut voor merk. Dat is een operationeel inzicht dat nergens op de site staat en pas in het reactieve gesprek bovenkwam.
- *Het gesprek deed hier het werk:* de website-delta-test bevestigt dat de scan-kernspanning op een dieper niveau zit dan de site-only-versie. Eén terugkerende zwakte: de eerste maandagstap blijft soms te procedureel (T3). De actuele scores per scan staan in het meetstand-blok hieronder (automatisch ververst).

Dit is precies het soort uitspraak waar de hele scan op mikt: niet samenvatten wat er staat, maar een onuitgesproken spanning benoemen die de invuller herkent zodra hij het hoort.

### De geaggregeerde maat

<!-- scherpte-cijfers:start -->
**Stand van de meting** (automatisch gegenereerd uit `_results.json`, laatst gemeten 2026-06-12): 3 gemeten scans, gemiddelde scherpte **8,3/10**, **3 van de 3** landt in de topband (8-10), gemiddelde toegevoegde waarde boven de website **8,0/10**.

Per scan: Sovot 9/10 · Schwung.ai 8/10 · Successr 8/10.
<!-- scherpte-cijfers:end -->

Per scan convergeren drie onafhankelijke LLM-lagen (jury, website-delta, harde meters) op hetzelfde oordeel, met lage spreiding (0-2). De gesprek-motor daalt betrouwbaar af naar gedrag/overtuiging (de bodem); de website-delta laat zien dat de scan-kernspanning telkens op een dieper niveau zit dan de site-only-versie.

**Eerlijke grens:** dit is een kleine, zelf-gemeten basis, en de jury is een AI-panel (verankerd tegen een platina- en een zwak-anker, mediaan i.p.v. gemiddelde), geen klant-oordeel. De scores bewegen ook met de configuratie van de keten (o.a. de DESTEP-marktanalyse beïnvloedt de scherpte merkbaar) — dat is in onderzoek; het meetstand-blok hierboven beweegt automatisch mee. Het bewijs toont dat de machinerie structureel iets toevoegt boven de website, niet dat elke scan voor elke klant raak is. De terugkerende zwaktes zitten in de laatste vertaalslag: de kernspanning scherper omdraaien (T1) en de hefboom concreter maken (T3). Een grotere batch plus klant-feedback ná het rapport is de volgende bewijslast.

### De kwalitatieve gouden referentie

Los van de meting bestaat één uitgeschreven referentie-duiding (uit de doctrine, een echte vroege scan): "25 jaar boosheid heeft een product opgeleverd. Nu nog een stem die die boosheid waardig is.", met als lever "Eerste werk is stem-werk, niet design-werk." Dat is de lat: een zin die de klant nooit zo opschreef, niet op de site staat, en meteen een richting wijst.
