Pièce justificative du Livre

Le relevé des chiffres

Quatorze affirmations chiffrées, mesurées contre le code plutôt que recopiées de la documentation. Ce qui tient, ce qui dérive, et comment le dire sans mentir.

Ce relevé existe parce que le canon du dépôt avertit lui-même que le manifeste doctrinal dérive du code réel. La lettre n'a pas été réécrite : le Livre porte simplement la mesure à côté de l'annonce, et voici les preuves.
← Retour au Livre de Référence
Relevé des chiffres

Relevé des chiffres — Le Livre de Référence

Date de la mesure : 2026-07-19 · Autorité : C (audit) · Portée : les affirmations
chiffrées de frontend/content/lettre-aux-humains.md, mesurées contre le dépôt.

Ce relevé existe parce que CLAUDE.md avertit lui-même que le manifeste doctrinal
dérive du code réel. Un livre de référence qui répète des chiffres gonflés ne vaut rien.
La lettre n'a pas été réécrite : le livre porte la mesure à côté de l'annonce.

Sommaire

AffirmationVerdictAnnoncéMesuré
agents 400 plus 350 essaimGONFLÉ« 400+ agents » (admin.html, civilization.html…Trois chiffres pour trois choses différentes, aucune n'étant «…
spheres 9 10 16GONFLÉ« LES 9 SPHÈRES DE L'ARCHE » (l.1193) ; « 350 …Le dépôt livre UNE seule taxonomie de sphères, à deux cadrages…
routeur llm 18 fournisseursGONFLÉ« ROUTEUR LLM — 18+ Fournisseurs IA » / « Le s…Le chiffre 18 vient de l'énumération LLMProvider, qui compte…
verticales entrepriseAMBIGU« LES 21 VERTICALES D'ENTREPRISE » — « un écos…Deux mesures divergentes selon le sens du mot. (A) Dossiers de…
76 profils professionnelsAMBIGU« AT·OM ne fournit pas une IA générique — il o…Le dépôt contient 84 dossiers-profils porteurs de code réel : …
18 experts origin validation histoAMBIGU« 18 EXPERTS ORIGIN — Validation Historique » …Deux registres ORIGIN coexistent dans le dépôt, avec deux comp…
pouls heartbeat 4.44sAMBIGU« Le Pouls — heartbeat 4.44 secondes » / « It …4.44 s EXISTE dans le code — mais ce n'est PAS le heartbeat. T…
lois immuables 6 vs 12AMBIGU« 6 lois immuables — Six lois gravées dans le …Le mot « loi » recouvre AU MOINS 5 familles distinctes et non …
18 oracles essaim sagesseEXACT« 18 Oracles — essaim de sagesse » / « 18 pers…18 oracles réellement définis, confirmés par trois sources ind…
12 moteurs civilisationnels nexusEXACT« 12 moteurs civilisationnels (Nexus de transd…12 exactement, et la bijection est parfaite. `backend/app/engi…
3 hubs interface synaptiqueEXACT« LES 3 HUBS — L'Interface Synaptique » : « To…Le chiffre 3 est EXACT et n'est nulle part contredit : l'énumé…
15 besoins fondamentauxEXACT« Le système de modules est organisé autour de…15 besoins, exactement. Trois sources indépendantes dans le co…

agents 400 plus 350 essaim — GONFLÉ

Ce que la lettre annonce

« 400+ agents » (admin.html, civilization.html, lumiere.html, ATOM-Reference-Book*.html, inscription.html, griffe.html, formation.html) ; « L'ESSAIM — 350 Agents Vivants » / « 350 intelligences spécialisées, organisées en 16 sphères » (presentation-obtenez.html:665) ; « TOTAL: 400+ Agents » (docs/VERITE-AGENTS-CORE-L0.md)

Ce que le dépôt contient

Trois chiffres pour trois choses différentes, aucune n'étant « 400 agents vivants ».

  1. CATALOGUE FRONTEND — frontend/js/agents-database.js = 405 entrées exactement (9 domaines × 45 : Personnel/Entreprise/Institutions/Creation/Communaute/Communication/Formation/MonEquipe/Durabilite). Mais ce sont des objets JS statiques produits par une factory agent(domain, name, desc, level, category, capabilities) — aucune exécution, aucun appel LLM, aucun runtime. Le fichier lui-même les nomme « capability notes » : son ORCHESTRATOR_GUIDE dit « surface the right capability note » (l.718-719) et ses payloads bus émettent capability_note_count (l.623, 631, 662). C'est le type #2 de CLAUDE.md, explicitement « NOT agents ».
  1. REGISTRE BACKEND — backend/app/services/agent_registry.py = 238 définitions d'agents (commentaire l.492 « 226 + 12 = 238 », vérifié par comptage : 238 occurrences de "name":). Répartition mesurée : personal 28, business 43, government 18, creative_studio 42, community 12, social_media 15, entertainment 8, my_team 35, scholar 25 = 226 sphère + 12 système. Celles-là sont de vraies définitions (capabilities, requires_human_gate, sphere_type, tier) semables en base via seed_agents().
  1. RUNTIME QUI EXÉCUTE VRAIMENT — 4 orchestrateurs cardinaux : agents/core/{nova,aria,orion,keli}.js, + 4 modules spécialistes (agents/specialists/{hedera,supabase,pinata,frequency}.js), + 6 sous-classes BaseAgent côté Python (PMAgent, FinanceAgent, OpsAgent, RiskAgent dans world_engine/agents/agent_runtime.py, DynamicAgent dans agent_factory.py, + 1 exemple en docstring). Ordre de grandeur : une dizaine de classes agent exécutables, pas 400.

LE « 350 » DÉCODÉ — sa ventilation dans presentation-obtenez.html somme à exactement 350, et 9 de ses 15 sphères reproduisent au chiffre près agent_registry.py (28/43/18/42/12/15/8/35/25 = 226). Les 124 restants (Transport 50, Environnement 25, Sociétal 20, Jeunesse 15, Vie Privée 8, Dashboard 6) viennent des verticales V68 absentes du dépôt : backend/verticals/ sur disque ne contient que README.md + _archived/. Et agents/capability-notes/transport-50-agents.md tranche lui-même : « 50 capability-notes », « archive déclarative, non-runtime », « le registry V68 portait une capacité de design riche, mais pas un runtime monté ». Donc 350 = 226 réels + 124 fiches archivées.

Deux défauts annexes du « 350 » : il annonce « 16 sphères » mais n'en liste que 15, et le canon du dépôt en compte 10 (backend/app/models/sphere.py::SphereType, S0→S9). Et « L'Essaim » décrit comme « visualisation interactive » n'existe pas : aucun fichier essaim n'est présent, le mot n'apparaît que dans de la prose de présentation.

Comment le dire sans mentir

Formulation courte recommandée pour le livre de référence :

« 238 agents au registre (226 par sphère + 12 agents système), 405 fiches de capacités au catalogue, 4 orchestrateurs cardinaux qui exécutent — Nova, Aria, Orion, Keli. »

Version longue si la page a la place :

« AT·OM distingue trois choses que le mot agent confond. Le catalogue compte 405 fiches de capacités réparties en 9 domaines : ce sont des descriptions consultables, pas des intelligences actives. Le registre backend porte 238 définitions d'agents réellement semables en base — 226 réparties par sphère plus 12 agents système. Et 4 orchestrateurs cardinaux — Nova, Aria, Orion, Keli — exécutent effectivement, épaulés d'une poignée de spécialistes. »

Remplacements précis à faire :

La nuance qui compte

Le mot « agent » porte trois sens incompatibles dans le dépôt, et c'est là toute la réponse.

(a) Fiche de capacité — une entrée descriptive dans un catalogue consultable. 405 dans agents-database.js. Ne s'exécute pas. CLAUDE.md le dit déjà (« type #2 : Capability Notes … NOT agents ») et le fichier lui-même s'auto-corrige dans son ORCHESTRATOR_GUIDE. La page publique, elle, les vend comme « 400+ agents IA », ce qui laisse croire à 400 intelligences actives.

(b) Définition d'agent semable — une spec avec capabilities, sphère, human-gate, prête à être insérée en base et instanciée. 238 dans agent_registry.py. Réel, livré, mais c'est un registre : un agent défini n'est pas un agent en train de tourner.

(c) Agent qui exécute — une classe avec une boucle, un prompt, des outils. 4 cardinaux JS + 4 spécialistes + ~6 classes Python.

LIVRÉ vs PRÉVU : 226 des 350 sont livrés (registre backend). Les 124 autres relèvent des verticales V68 retirées du dépôt et explicitement rétrogradées en « archive déclarative, non-runtime » — donc PRÉVU/ARCHIVÉ, pas livré. Le « 350 » n'est pas inventé : c'est un total historique 226+124 dont la moitié basse a été démontée depuis, sans que la présentation soit remise à jour.

RÉEL vs DOCTRINAL : la hiérarchie « L0 3 / L1 12 / L2 72 / L3 200+ = 400+ » de docs/VERITE-AGENTS-CORE-L0.md est purement doctrinale — aucun de ces paliers (12, 72, 200+) ne correspond à un comptage de code. Le « 405 » du catalogue frontend et le « 238 » du registre backend sont deux listes entièrement disjointes (noms, taxonomies et niveaux différents) : les additionner serait un double comptage, et aucune des deux ne vaut 400 agents vivants.

Trou de livraison à signaler : « L'Essaim », décrit comme une visualisation interactive zoomable, n'existe dans aucun fichier — c'est une maquette ASCII dans un texte de présentation.

Preuve

Comptages (depuis C:/Users/manon/Documents/GitHub/ATOM-CLEAN, dépôt principal, worktrees .claude/ exclus) :

- `grep -c "agent('" frontend/js/agents-database.js` → **405** ; par domaine `for d in Personnel Entreprise ... ; do grep -c "agent('$d'" ...` → 45 × 9. Fichier : C:/Users/manon/Documents/GitHub/ATOM-CLEAN/frontend/js/agents-database.js (742 lignes ; en-tête l.3 « 405 Agents x 9 Domaines » ; auto-qualification « capability note » l.718-719, `capability_note_count` l.623/631/662).
- `grep -c '"name":' backend/app/services/agent_registry.py` → **238** ; ventilation par fonction `_get_*_agents()` via regex Python → personal 28, business 43, government 18, creative_studio 42, community 12, social_media 15, entertainment 8, my_team 35, scholar 25, system 12. Fichier : C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/services/agent_registry.py (916 lignes ; l.492-493 `# Total including system agents: 226 + 12 = 238` / `SYSTEM_AGENTS_COUNT = 12`).
- `grep -rn "class \w\+(BaseAgent)" backend/app/ | wc -l` → **6**.
- `ls agents/core/` → aria.js, keli.js, nova.js, orion.js (**4**) ; `ls agents/specialists/` → frequency.js, hedera.js, pinata.js, supabase.js (**4**).
- `ls backend/verticals/` → **README.md, _archived/** seulement ; `git ls-files backend/verticals/` → uniquement `README.md` + fichiers sous `_archived/PROJECT_MGMT_V68/`. Aucune verticale Transport/Environment/Youth/Privacy/Dashboard versionnée.
- C:/Users/manon/Documents/GitHub/ATOM-CLEAN/agents/capability-notes/transport-50-agents.md l.1-6 : « Transport — 50 capability-notes archived » · « Statut : archive déclarative, non-runtime » · « pas un runtime monté ».
- C:/Users/manon/Documents/GitHub/ATOM-CLEAN/frontend/presentation-obtenez.html:665 (titre ESSAIM) et l.669-684 (bloc ASCII des 15 sphères, somme = 350).
- C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/models/sphere.py:27-42 → `SphereType` = 10 membres (S0 COMMUNICATION_TRANSIT → S9 SUSTAINABILITY), pas 16.
- C:/Users/manon/Documents/GitHub/ATOM-CLEAN/docs/VERITE-AGENTS-CORE-L0.md l.10-25 : hiérarchie doctrinale L0 3 / L1 12 / L2 72 / L3 « 200+ » → « TOTAL: 400+ Agents » — L1/L2/L3 ne correspondent à aucun comptage de code trouvé.
- Câblage : `frontend/js/governance-init.js:115` et `frontend/meshmap.html:16` chargent bien agents-database.js (le catalogue est livré et affiché — c'est le mot « agent » qui est trompeur, pas l'existence du fichier).

spheres 9 10 16 — GONFLÉ

Ce que la lettre annonce

« LES 9 SPHÈRES DE L'ARCHE » (l.1193) ; « 350 intelligences spécialisées, organisées en 16 sphères » (l.710) ; « 9 sphères originales + 7 expansions spécialisées = 16 domaines de vie » (l.1729) ; « 10 sphères de vie, un seul univers souverain » (l.146) ; « Votre vie numérique est organisée en 10 espaces isolés (Personnel, Affaires, Créatif, Études, Social, Communauté, XR, Équipe, Labo IA, Divertissement) » (l.3286)

Ce que le dépôt contient

Le dépôt livre UNE seule taxonomie de sphères, à deux cadrages complémentaires : 10 sphères techniques (S0..S9) et 9 sphères de contenu (S1..S9, S0 exclu). (1) backend/app/models/sphere.py:27-92 : SphereType = 10 membres exactement (COMMUNICATION_TRANSIT S0 + PERSONAL, BUSINESS, INSTITUTIONS, CREATIVE_STUDIO, COMMUNITY, ENTERTAINMENT, EDUCATION, MY_TEAM, SUSTAINABILITY) + SphereId = "0".."9" + bijection SPHERE_NAME_TO_ID. (2) backend/app/routers/spheres.py : CANONICAL_SPHERES = 9 entrées exactement (comptage : 9 occurrences de "sphere_type"), marqué « THE 9 SPHERES - IMMUTABLE / FROZEN Rule #7 », monté en prod (main.py:1228) ; main.py:97 : rule_7 enforcement = "9 spheres, 6 sections". (3) Frontend atom-relational-graph.js:36 : SPHERES = ['S0'..'S9'] = 10 ; organism-harmony-responder.js:27 = 9 ; _FRUIT_BRANCH_CODES (spheres.py) = 8 branches (S1-S5+S7-S9). LE 16 N'EXISTE PAS EN CODE VIVANT : unique occurrence dans backend/schemas/agent_schemas.py:456, fichier MORT — (a) son AGENT_DISTRIBUTION contient 15 entrées, pas 16 (comptage awk = 15), le commentaire « 16 spheres » se contredit lui-même ; (b) 6 de ces entrées appellent SphereType.GOVERNMENT, .SOCIAL_MEDIA, .SCHOLAR, .TRANSPORT, .JEUNESSE, .DASHBOARD qui ne sont PAS définies dans son propre enum SphereType (10 membres : les 9 canoniques + SYSTEM) → AttributeError à l'import, le module ne peut pas s'exécuter ; (c) zéro import : tous les imports live pointent vers app.schemas.agent_schemas (backend/app/), jamais vers backend/schemas/. Le fichier VIVANT backend/app/schemas/agent_schemas.py:434-456 déclare 9 sphères et TOTAL_AGENTS = sum(...) = 226, avec commentaire explicite « COMMUNITY absorbs the legacy social_media sphere (12 community + 15 social = 27) » et « SUSTAINABILITY has no dedicated generator » (0 agent). Les « 7 expansions V68 » de la Lettre (l.1731-1741) comptent Communauté qui est DÉJÀ l'une des 9 originales = double comptage ; le code mort n'en liste que 6 (9+6=15). backend/verticals/ sur disque ne contient que README.md + _archived/PROJECT_MGMT_V68. Enfin : memory/project_taxonomy_spheres.md et memory/project_taxonomy_canaux.md, cités par CLAUDE.md comme mémoires canoniques, N'EXISTENT PAS (déjà signalé par l'audit B-62 §1.4, jamais corrigé).

Comment le dire sans mentir

Formulation recommandée (remplace l.710, l.1729-1741 et l.3286) : « AT·OM organise votre vie numérique en 9 sphères de contenu — Personnel, Entreprise, Gouvernance, Création, Communauté, Divertissement, Formation, Mon Équipe, Durabilité — plus une dixième sphère technique, S0 Communication Transitoire, qui achemine ce qui n'appartient encore à aucune des neuf. D'où les deux chiffres qu'on rencontre dans la documentation : 9 sphères de vie, 10 avec la sphère de transit. L'architecture est gelée (Règle #7) : les neuf sont immuables, chacune avec ses 6 sections de bureau. » — Pour le 16, deux options selon l'intention. Si on veut garder la trace du plan : « Un plan d'expansion V68 prévoyait 7 verticales supplémentaires (transport, sociétal, environnement, vie privée, jeunesse, tableau de bord, communauté). Il a été abandonné au profit d'une consolidation : ces domaines sont devenus des modules à l'intérieur des 9 sphères plutôt que des sphères de plus. 9 sphères livrées et gelées ; l'expansion à 16 n'a pas eu lieu. » Si on veut simplement du vrai sans l'historique : supprimer la section « 16 SPHÈRES — L'Expansion V68 » et le passage l.710. — Pour les agents, corriger de la même main : « 226 agents répartis sur les 9 sphères » (chiffre calculé par le code vivant), et non 350. — ACTIONS PRÉALABLES à toute réécriture, sans quoi le livre restera faux : (a) remplacer la liste « 9 Sphères de l'Arche » l.1193-1215 (IDENTITÉ/SANTÉ/SAVOIR/ÉCONOMIE/…) par les 9 noms réellement livrés, ou assumer explicitement qu'il s'agit d'une lecture doctrinale distincte de la nomenclature produit — mais alors le dire, et donner la table de correspondance ; (b) supprimer la liste FAQ l.3286 qui invente XR et Labo IA ; (c) créer memory/project_taxonomy_spheres.md que CLAUDE.md cite déjà, en y scellant les 9 noms + S0, pour qu'une seule source arbitre à l'avenir.

La nuance qui compte

TROIS distinctions, dont une bien plus grave que le chiffre. (1) 9 vs 10 n'est PAS une contradiction : c'est 9+1. S0 « Communication Transitoire » est le fallback infra (contenu inclassable, transit), les 9 autres sont les sphères de CONTENU. Le code assume les deux cadrages simultanément et volontairement — enum 10 pour le routage/adressage, router REST 9 pour la surface utilisateur. Les deux chiffres sont vrais, dans deux sens différents du mot. (2) 16 = plan V68 abandonné, jamais livré, et même le plan ne tenait pas : le fichier qui l'annonce compte 15 entrées sous un commentaire disant 16, en appelant 6 membres d'enum inexistants — il planterait à l'import. La Lettre aggrave en listant 7 expansions dont « Communauté », déjà l'une des 9 originales (double comptage). L'histoire réelle est une CONSOLIDATION assumée, pas une expansion : le code vivant documente que COMMUNITY a absorbé social_media (12+15=27). Le corollaire concerne aussi le chiffre d'agents : 350 est le nombre du fichier mort ; le vivant calcule 226. (3) LE VRAI PROBLÈME — les « 9 Sphères de l'Arche » de la Lettre ne sont pas les 9 sphères du code. Elles ne coïncident QUE par le nombre. Lettre (l.1193) : IDENTITÉ, SANTÉ, SAVOIR, ÉCONOMIE, GOUVERNANCE, ÉDUCATION, INTELLIGENCE, INFRASTRUCTURE, ÉQUILIBRE. Code : Personnel, Entreprise, Gouvernance et Politique, Création, Communauté, Divertissement, Formation, Mon Équipe, Durabilité. Trois correspondent vaguement (GOUVERNANCE↔Gouvernance, ÉDUCATION↔Formation, ÉQUILIBRE↔Durabilité) ; six n'ont aucun équivalent (IDENTITÉ, SANTÉ, SAVOIR, ÉCONOMIE, INTELLIGENCE, INFRASTRUCTURE) et six sphères livrées sont absentes de la Lettre. Et la FAQ (l.3286) énonce une TROISIÈME liste de 10 (Personnel, Affaires, Créatif, Études, Social, Communauté, XR, Équipe, Labo IA, Divertissement) qui ne correspond ni aux S0-S9 ni aux 9 de l'Arche — XR et Labo IA n'existent nulle part comme sphères. Un même mot, quatre taxonomies incompatibles : un lecteur qui compare la Lettre au produit ne reconnaît rien. Corriger « 16 → 9 » sans réconcilier les NOMS laisserait le livre faux. (4) Dette documentaire : CLAUDE.md renvoie à memory/project_taxonomy_spheres.md comme mémoire canonique — le fichier n'existe pas. L'audit B-62 l'avait relevé le 2026-05-25 ; rien n'a bougé. Il n'existe donc aucune source unique de vérité écrite pour arbitrer ces quatre listes : seul le code tranche.

Preuve

FICHIERS — Enum canonique : C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/models/sphere.py:27-92 · Router FROZEN : C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/routers/spheres.py (CANONICAL_SPHERES) · Montage : C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/main.py:97,1228 · Schéma agents VIVANT : C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/schemas/agent_schemas.py:434-456 · Schéma agents MORT (source du « 16 ») : C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/schemas/agent_schemas.py:27-48,456-476 · Lettre : C:/Users/manon/Documents/GitHub/ATOM-CLEAN/frontend/content/lettre-aux-humains.md:146,710,907,1193-1215,1729-1741,3286,3376 · Frontend : frontend/js/atom-relational-graph.js:36, frontend/js/organism-harmony-responder.js:27 · Audit préexistant : memory/2026-05-25-spheres-canon-S0-S9-empirical-audit.md (B-62, §0 + §1.4). COMMANDES — `awk '/^CANONICAL_SPHERES = \[/,/^\]/' backend/app/routers/spheres.py | grep -c '\"sphere_type\"'` → **9** · `awk '/^AGENT_DISTRIBUTION = \{/,/^\}/' backend/schemas/agent_schemas.py | grep -c 'SphereType\.'` → **15** (et non 16) · `awk '/^class SphereType/,/^class AgentStatus/' backend/schemas/agent_schemas.py | grep -cE '^\s+[A-Z_]+ = \"'` → **10** membres · `grep -nE '^\s+(GOVERNMENT|SOCIAL_MEDIA|SCHOLAR|TRANSPORT|SOCIETAL|ENVIRONMENT|PRIVACY|JEUNESSE|DASHBOARD) = ' backend/schemas/agent_schemas.py` → **AUCUN RÉSULTAT** (membres appelés mais jamais définis → AttributeError à l'import) · `grep -rn 'agent_schemas' --include='*.py' backend/` → tous les imports live = `app.schemas.agent_schemas` ; `backend.schemas.agent_schemas` n'est importé que par `backend/services/agent_{execution,registry}.py`, eux-mêmes doublons morts hors de `backend/app/` · `ls memory/project_taxonomy_spheres.md` → No such file or directory · `grep -rn '16 sphères' --include='*.md' .` → uniquement LETTRE_AUX_HUMAINS.md + copies worktrees/archives, jamais un fichier de définition. NOTE MÉTHODE : tous les comptages excluent `.claude/worktrees/` (copies du même dépôt qui gonflent artificiellement les grep).

routeur llm 18 fournisseurs — GONFLÉ

Ce que la lettre annonce

« ROUTEUR LLM — 18+ Fournisseurs IA » / « Le système choisit automatiquement le meilleur modèle parmi 18+ fournisseurs: Anthropic (Claude), OpenAI (GPT), Google (Gemini), Mistral, Cohere, Groq, DeepSeek, Perplexity, Together, Replicate, Ollama, et plus » (LETTRE_AUX_HUMAINS.md §1446-1451, repris L1661 et L3316)

Ce que le dépôt contient

Le chiffre 18 vient de l'énumération LLMProvider, qui compte aujourd'hui 19 membres (18 à l'écriture du docstring, +ZHIPU ajouté depuis). Mais l'énumération n'est qu'un vocabulaire. En descendant vers l'exécution réelle, quatre couches distinctes : (1) 19 fournisseurs NOMMÉS dans l'enum ; (2) 10 fournisseurs ayant au moins un modèle catalogué dans MODEL_REGISTRY (25 ModelSpec au total) — ANTHROPIC 2, OPENAI 3, GOOGLE 3, MISTRAL 2, GROQ 1, DEEPSEEK 1, ZHIPU 3, PERPLEXITY 1, OLLAMA 8, VLLM 1 ; (3) 7 fournisseurs enregistrés au démarrage par get_llm_router() — 5 inconditionnels (ANTHROPIC, OPENAI, GOOGLE, GROQ, OLLAMA) + 2 opt-in par variable d'env (VLLM si VLLM_BASE_URL, ZHIPU si ZHIPU_API_KEY) ; (4) 4 fournisseurs seulement possèdent un adaptateur HTTP réel : OPENAI, OLLAMA, VLLM, ZHIPU — et encore, VLLMAdapter et ZhipuAdapter héritent tous deux d'OpenAIAdapter (API OpenAI-compatible), donc 2 implémentations HTTP distinctes seulement. Tout le reste tombe dans _execute_completion_legacy() qui retourne littéralement la chaîne "[Mock response from {model_id}] This is a simulated response." (llm_router.py:760). Point le plus lourd : Anthropic (Claude) et Google (Gemini), les deux noms mis en vedette dans la Lettre, n'ont PAS d'adaptateur — ils sont enregistrés, routables, budgétés, facturés en coût estimé… et répondent une réponse simulée. Enfin, 9 membres de l'enum sont purement décoratifs (zéro modèle, zéro adaptateur, jamais enregistrés) : COHERE, REPLICATE, TOGETHER, ANYSCALE, FIREWORKS, LMSTUDIO, ELEVENLABS, STABILITY, RUNWAY — dont les 3 derniers ne sont même pas des fournisseurs LLM (voix, image, vidéo). Or la Lettre cite nommément Cohere, Together et Replicate dans sa liste : trois noms qui n'existent que comme constantes de chaîne.

Comment le dire sans mentir

Formulation courte (pour le tableau récapitulatif, en remplacement de « 18+ fournisseurs (Claude, GPT, Gemini...) ») : « Routeur multi-fournisseurs — 4 fournisseurs branchés en direct, 19 au plan ». Formulation longue (pour la section dédiée) : « ROUTEUR LLM — Multi-fournisseurs, 4 branchés en direct sur 19 au plan. AT·OM n'est verrouillé sur aucune IA : le routeur choisit le modèle selon le type de tâche, avec bascule automatique si un fournisseur tombe, budget par identité et traçabilité de chaque appel. Aujourd'hui, quatre fournisseurs parlent pour de vrai : OpenAI (GPT), Ollama (Gemma 3 et 4 en local, coût zéro), vLLM (local) et Zhipu GLM. Le catalogue en compte 25 modèles répartis sur 10 fournisseurs, et l'architecture en prévoit 19. Les autres — dont Anthropic et Google — sont déjà câblés dans le routeur mais retournent une réponse simulée en attendant leur adaptateur : le chemin est tracé, la conduite n'est pas encore raccordée. » Deux gestes de rigueur à poser en même temps : (1) retirer Cohere, Together et Replicate de la liste de noms cités, puisqu'ils n'existent que comme constantes — citer ceux qui répondent vraiment (OpenAI, Ollama/Gemma, vLLM, Zhipu GLM) et nommer Anthropic et Google comme prévus ; (2) faire dire au code ce que dit le livre — corriger le docstring llm_router.py:6 (« Supports 18+ LLM providers ») en « Declares 19 providers, 4 wired to real HTTP adapters (OpenAI, Ollama, vLLM, Zhipu) — others fall through to a simulated response ». Le mensonge est né là, dans un commentaire, et il a remonté jusqu'à la Lettre. Point de vigilance distinct du chiffre, à traiter comme un défaut et non comme une formulation : le mock renvoie un succès (finish_reason="stop", coût, jetons) et non une erreur. Tant qu'Anthropic et Google n'ont pas d'adaptateur, mieux vaudrait qu'ils échouent proprement pour laisser la bascule automatique faire son travail, plutôt que de rendre une réponse simulée indiscernable d'une vraie.

La nuance qui compte

Le mot « fournisseur » a deux sens ici, et c'est toute l'affaire. Sens 1 — fournisseur DÉCLARÉ : une constante dans l'énumération LLMProvider, qui donne au routeur un nom pour le désigner. Sens 2 — fournisseur EXÉCUTABLE : un fournisseur pour lequel il existe un adaptateur HTTP capable d'aller chercher une vraie réponse. La Lettre annonce 18+ au sens 1 et laisse lire 18+ au sens 2 (« le système choisit automatiquement le meilleur modèle parmi »). Au sens 2, le compte réel est 4. Deuxième nuance, plus importante que l'écart de chiffre : le mock n'échoue pas. _execute_completion_legacy() retourne finish_reason="stop", un coût estimé, un compte de jetons — un succès parfaitement formé. Un appel routé vers Anthropic ou Google produit donc une réponse simulée qui traverse silencieusement toute la chaîne de traçabilité et de budget comme si elle était réelle. Ce n'est pas un manque de fonctionnalité, c'est un trou silencieux — même famille que le trou CHE·NU déjà documenté dans CLAUDE.md. Troisième nuance : l'architecture, elle, est authentiquement multi-fournisseurs et tient debout — routage par type de tâche, 5 stratégies (coût/qualité/vitesse/équilibré/spécifique), bascule automatique, budgets par identité, limitation de débit. Le squelette est bâti ; ce sont les adaptateurs qui manquent. Rétrograder le chiffre ne rétrograde pas le travail. Quatrième nuance : ELEVENLABS, STABILITY et RUNWAY gonflent le compte de l'enum sans être des LLM du tout (voix, image, vidéo) — les retirer du décompte « fournisseurs IA du routeur LLM » est une correction de justesse, pas une perte.

Preuve

Fichiers : `C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/services/llm_router.py` (1196 L — enum L55-81, `_build_adapter` L334-366, `_execute_completion` L658-682, mock `_execute_completion_legacy` L740-771, enregistrement boot L1046-1160) ; `C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/services/llm_model_registry.py` (484 L, MODEL_REGISTRY L49-468) ; `C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/services/llm_adapters/` (5 fichiers : base.py, openai_adapter.py, ollama_adapter.py, vllm_adapter.py, zhipu_adapter.py). Source de l'annonce : `C:/Users/manon/Documents/GitHub/ATOM-CLEAN/frontend/content/lettre-aux-humains.md:1446` + `C:/Users/manon/Documents/GitHub/ATOM-CLEAN/docs/vision/LETTRE_AUX_HUMAINS.md:1446`. Comptages : `python -c "import re; src=open('backend/app/services/llm_router.py',encoding='utf-8').read(); blk=src.split('class LLMProvider')[1].split('class TaskType')[0]; print(len(re.findall(r'^\s{4}([A-Z_]+)\s*=\s*\"',blk,re.M)))"` → 19 ; même script sur llm_model_registry.py avec `provider=LLMProvider\.([A-Z_]+)` → 10 fournisseurs distincts / 25 ModelSpec ; `grep -c "if config.provider == LLMProvider" backend/app/services/llm_router.py` → 4 branches dans `_build_adapter`, `return None` par défaut L366 ; `grep -n "Mock response from" backend/app/services/llm_router.py` → L760. Note : un doublon non synchronisé existe à `backend/services/llm_router.py` (1191 L, en-tête divergent) — à ne pas confondre avec le fichier canonique `backend/app/services/`.

verticales entreprise — AMBIGU

Ce que la lettre annonce

« LES 21 VERTICALES D'ENTREPRISE » — « un écosystème de 21 modules spécialisés — chacun avec ses propres agents IA, pages, API et bases de données » (frontend/content/lettre-aux-humains.md:184-186)

Ce que le dépôt contient

Deux mesures divergentes selon le sens du mot. (A) Dossiers de verticales sur disque et dans git : 0 actif — backend/verticals/ ne contient que _archived/PROJECT_MGMT_V68 + README.md. 20 dossiers ont existé dans toute l'histoire git, retirés progressivement par migration vers le backend canonique. (B) Domaines d'entreprise avec surface API montée : 21/21 vérifiés — les 21 domaines nommés dans le diagramme de la Lettre ont chacun un fichier routeur existant ET monté dans main.py. Profondeur très inégale : crm_router 694L/39 endpoints, marketing_router 41 endpoints, personal_productivity_router 33, mais real_estate_hub_router seulement 41L/3 endpoints.

Comment le dire sans mentir

« 21 domaines d'entreprise, tous montés en API dans le backend canonique. Les verticales existent désormais comme routeurs intégrés, non comme modules séparés : backend/verticals/ a été vidé au profit de backend/app/routers/ (20 modules V68 historiques, canonicalisés ; 1 archivé). La profondeur varie fortement d'un domaine à l'autre — de 39 endpoints pour le CRM à 3 pour l'Immobilier. » Variante courte pour la Lettre : « 21 domaines d'entreprise câblés — du CRM à la Santé — chacun avec sa surface API vivante, à des stades de maturité inégaux. » Retirer impérativement la promesse uniforme « chacun avec ses propres agents IA, pages, API complète et bases de données », fausse pour les domaines encore embryonnaires. Aligner les 5 fichiers frontend/ATOM-Reference-Book*.html:366 qui disent encore « 20 Verticals », et corriger CLAUDE.md qui annonce « 12 dirs V68 actifs » alors qu'il n'en reste aucun.

La nuance qui compte

Le mot « verticale » a deux sens, et c'est le cœur de la réponse. Sens A (module packagé dans backend/verticals/) : 0 aujourd'hui, 20 au maximum historique, 1 archivé. Sens B (domaine d'entreprise avec surface API vivante) : 21/21 montés. Le 21e — Santé — n'est pas une invention : il n'a jamais eu de dossier de verticale mais dispose bien de health_center_router.py monté ; c'est une sous-sphère de SOCIETAL promue au rang de domaine. La disparition des dossiers n'est PAS une perte de fonctionnalité mais une canonicalisation délibérée vers backend/app/routers/. En revanche la promesse qualitative uniforme de la Lettre (« chacun avec ses propres agents IA, pages, API complète et bases de données ») est fausse pour au moins un domaine : Immobilier ne pèse que 41 lignes et 3 endpoints. Le chiffre tient ; l'uniformité promise derrière ne tient pas. Enfin le corpus se contredit lui-même (20 dans les 5 livres de référence, 21 dans la Lettre et la présentation) — il faut trancher sur un seul sens du mot dans tous les documents.

Preuve

Disque : Get-ChildItem C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/verticals -Force => _archived, README.md (2 entrées). Git tracké : git ls-files backend/verticals => _archived, README.md. Historique complet : git log --all --pretty=format: --name-only --diff-filter=A -- "backend/verticals/*" | extraction du 1er segment | Sort-Object -Unique => 20 noms (BUSINESS_CRM_V68, COMMUNITY_V68, COMPLIANCE_V68, CONSTRUCTION_V68, CREATIVE_STUDIO_V68, DASHBOARD_V68, EDUCATION_V68, ENTERTAINMENT_V68, ENVIRONMENT_V68, HR_V68, JEUNESSE_V68, MARKETING_V68, PERSONAL_PRODUCTIVITY_V68, PRIVACY_V68, PROJECT_MGMT_V68, REAL_ESTATE_V68, SOCIAL_V68, SOCIETAL_V68, TEAM_COLLAB_V68, TRANSPORT_V68). Aucun dossier HEALTH/SANTE n'a jamais existé : git log --all -- "backend/verticals/*HEALTH*" => vide ; la santé vivait en sous-sphère backend/verticals/SOCIETAL_V68/backend/spheres/health/agents/health_frequency_agent.py. Migration attestée par les messages de commit : 8cd583b79 « Retire societal V68 live backing », 3f3eeabda « Canonicalize societal seam and retire community V68 », 79fe7f489 « Retire personal productivity V68 residue ». Bloc verticales dans backend/app/main.py:1832 (commentaire « 15 domain-specific modules », 14 register_router réels après retrait d'ENTERTAINMENT) — les 14 fichiers routeurs vérifiés présents 14/14. Les 7 verticales retirées survivent comme routeurs canoniques montés (vérifié par Select-String sur main.py) : crm_router.py, marketing_router.py, project_management_router.py, real_estate_hub_router.py, construction_center_router.py, transport_center_router.py, entertainment.py, health_center_router.py — tous montés=True. Comptage endpoints via @router.(get|post|put|patch|delete) : crm_router 39/694L, marketing_router 41/394L, personal_productivity_router 33/582L, dashboard_router 11/183L, health_center_router 5/413L, real_estate_hub_router 3/41L. Contradiction interne du corpus : frontend/ATOM-Reference-Book*.html:366 (5 fichiers) disent « A) 20 Verticals » tandis que frontend/presentation-obtenez.html:136 et la Lettre disent 21. Correctif déjà réclamé dans docs/cartography/wiring-audit/w5_verticals_agents.md:130. CLAUDE.md lui-même est périmé ici : il annonce « 12 dirs V68 actifs + 1 archived sur disk », or 0 actif sur cette branche.

76 profils professionnels — AMBIGU

Ce que la lettre annonce

« AT·OM ne fournit pas une IA générique — il offre 76 profils professionnels pré-configurés, chacun avec son propre dashboard, outils et workflows » + « Profils Exécutifs (P001-P010) : CEO • CTO • CFO • COO • CMO • CHRO… » (frontend/content/lettre-aux-humains.md:1757-1766)

Ce que le dépôt contient

Le dépôt contient 84 dossiers-profils porteurs de code réel : 10 personas nommés (= P001-P010 d'après data/profiles/COMPLETE_SUMMARY.md) + 74 dossiers numérotés p011_ … p076_. Le nombre 76 correspond au plafond de numérotation (10 personas + 66 numéros uniques 011→076 = 76 emplacements), PAS au nombre de dossiers : 8 numéros sont attribués deux fois (023 garage/plumber, 024 tattoo/yoga, 025 foodtruck/music, 026 taxi/yoga, 027 bookstore/photo, 028 florist/pets, 029 massage/music, 030 cleaning/community), d'où 74 dossiers pour 66 numéros. Volume : 83 fichiers .py / 14 443 lignes dans les dossiers numérotés, +22 .py dans les 10 personas. Tout est tracké git (126 fichiers). MAIS : zéro import de ces modules dans backend/ ou frontend/ (grep sur backend/app : aucun résultat) — la bibliothèque n'est câblée à aucun runtime. Et 5 dossiers sur 74 seulement mentionnent « dashboard » ou « workflow » : il n'existe pas de dashboard par profil. Enfin, la description des P001-P010 comme « Profils Exécutifs CEO/CTO/CFO » est fausse : dans le dépôt P001-P010 sont Louis (musicien), Marie (architecte), David (cardiologue), Sophie (promoteur immo), Alex (influenceur fitness), Emma (avocate immigration), Marcus (restaurateur), Léa (prof-consultante), James (agent immo), Fatima (médecin de famille). La liste CEO/CTO/CFO vit ailleurs, dans data/organization/departments.json — autre structure, non reliée.

Comment le dire sans mentir

« 84 profils métiers écrits en code — 10 personas fondateurs (P001-P010 : musicien, architecte, cardiologue, promoteur immobilier, influenceur, avocate, restaurateur, professeure-consultante, agent immobilier, médecin de famille) et 74 métiers numérotés de P011 à P076, du boulanger au vétérinaire, de la plomberie au photovoltaïque. Environ 14 400 lignes de Python, une bibliothèque de logique métier sectorielle. À ce stade c'est une bibliothèque, pas encore une expérience : ces modules ne sont branchés à aucune interface, et le dashboard par profil reste à bâtir. »

Si l'on tient à garder le chiffre 76 (qui est le plafond de numérotation, P076) : « 76 emplacements de profils métiers, 84 modules effectivement écrits (8 numéros portent deux métiers) — code livré, câblage à l'interface à venir. »

À corriger aussi, hors chiffre : supprimer ou réécrire « Profils Exécutifs (P001-P010) : CEO • CTO • CFO • COO… ». Le dépôt ne contient pas ces profils exécutifs sous ces numéros ; la nomenclature CEO/CTO/CFO appartient à une autre structure (data/organization/departments.json, les 14 départements) et ne doit pas être présentée comme les dix premiers profils.

La nuance qui compte

Deux sens du mot « profil », et c'est là toute la réponse. Sens 1 — module de logique métier : livré, et même au-delà du chiffre (84 dossiers de code Python, ~14 400 lignes, un métier chacun : boulangerie, plomberie, tatouage, vétérinaire, drone, brasserie…). Sens 2 — profil pré-configuré pour l'utilisateur, « avec son propre dashboard, outils et workflows » : NON livré. Aucun de ces modules n'est importé nulle part, aucun dashboard par profil n'existe. Le chiffre 76 n'est donc ni inventé ni gonflé — il vient de la numérotation P001→P076 — mais il désigne des emplacements de numérotation, pas un décompte de dossiers (74 numérotés à cause de 8 numéros dédoublés) ni une expérience utilisateur disponible. Second écart, distinct : le libellé « Profils Exécutifs (P001-P010) : CEO • CTO • CFO… » ne correspond à rien dans le dépôt — les P001-P010 réels sont dix personas de métiers non-exécutifs (musicien, cardiologue, avocate, médecin…). Cette ligne est à corriger indépendamment du chiffre.

Preuve

Source de l'affirmation : C:/Users/manon/Documents/GitHub/ATOM-CLEAN/frontend/content/lettre-aux-humains.md:1757,1761,3388 (dupliqué dans archives/docs-historiques/LETTRE_AUX_HUMAINS.md). Mesures : `ls -d data/profiles/p[0-9]* | wc -l` → 74 ; `ls -d data/profiles/p[0-9]* | sed 's/^p\([0-9]*\)_.*/\1/' | sort -u | wc -l` → 66 (plage 011→076) ; `... | uniq -d` → 023 024 025 026 027 028 029 030 (8 collisions) ; `find data/profiles -name "*.py" -path "*/p0*" | wc -l` → 83 ; même find + `-exec cat {} + | wc -l` → 14 443 lignes ; `git ls-files data/profiles/ | wc -l` → 126 (tout tracké, pas de squatter). Personas P001-P010 : dossiers data/profiles/{louis,marie,david,sophie,alex,emma,marcus,lea,james,fatima}, mappés nominativement dans data/profiles/COMPLETE_SUMMARY.md lignes 26-56. Non-câblage : `grep -rnE "p0[0-9][0-9]_[a-z]+|data/profiles" backend/app --include=*.py` → vide ; aucun fichier de backend/ ou frontend/js/ n'importe ces modules. Dashboard : `grep -rilE 'dashboard|workflow' data/profiles/p0*` → 5 fichiers seulement. Exécutifs CEO/CTO/CFO : data/organization/departments.json + frontend/js/atom-mapping-data.js (structure distincte des profils pNNN).

18 experts origin validation historique — AMBIGU

Ce que la lettre annonce

« 18 EXPERTS ORIGIN — Validation Historique » / « Un système parallèle de 18 agents experts pour la validation historique et scientifique » (frontend/content/lettre-aux-humains.md:2208-2212)

Ce que le dépôt contient

Deux registres ORIGIN coexistent dans le dépôt, avec deux comptes différents. (1) LE VIVANT — backend/app/agents/templates/origin_experts.py : AGENT_REGISTRY = 21 agents (6 Noyau + 6 Transmédia + 4 Piliers + 2 Co-évolution + 3 Add-ons). C'est le seul monté en API (register_router("app.api.routes.origin_routes", ...) main.py:1758) ; GET /agents renvoie total: 21, l'endpoint stats code en dur "expert_agents": 21, et le test assert len(AGENT_REGISTRY) == 21. Ironiquement son propre en-tête dit « The 18 Universal Expert Agents ». (2) LE DORMANT — backend/app/agents/templates/origin/expert_agents.py : 24 templates définis, EXPERT_AGENT_REGISTRY = exactement 18 (noyau strict, sans add-ons) et FULL_AGENT_REGISTRY = 24 (18 + 6 add-ons). Ce module n'est importé par AUCUN fichier hors de son propre package — variante non câblée. Donc « 18 » est un vrai chiffre du code, mais c'est le sous-ensemble noyau d'un module mort. Sur le « validation historique » : parmi les 21 vivants, 5 ne valident rien — SCENE_DIRECTOR, PHILOSOPHER_SCRIBE, GHOST_WRITER, GAME_MECHANIC, NARRATIVE_DESIGNER portent can_validate_facts=False, can_generate_content=True. Il reste 16 validateurs de faits sur 21. Enfin, le tableau de la lettre elle-même somme à 6+6+4+2+3 = 21, contredisant son propre titre « 18 ».

Comment le dire sans mentir

Remplacer par : « 21 agents experts ORIGIN livrés et exposés en API — 18 au noyau (6 historiens/scientifiques, 6 transmédia, 4 piliers civilisationnels, 2 co-évolution) plus 3 add-ons (ethnographie, spiritualité, climat). 16 d'entre eux valident les faits ; les 5 agents transmédia restants génèrent du contenu sous contrainte factuelle — la validation et la génération sont réparties entre agents distincts, pas cumulées dans un même agent. » Si l'on tient à garder le chiffre 18 pour sa cadence rhétorique : « 18 experts ORIGIN au noyau, 21 avec les add-ons » — et corriger le tableau, qui somme aujourd'hui à 21 sous un titre annonçant 18. Remplacer aussi le sous-titre « Validation Historique » par « Validation historique et production transmédia », qui couvre les deux moitiés réelles du dispositif. Enfin, ajouter une désambiguïsation si le livre mentionne ailleurs les 18 agents de la Sphère 3 Institutions : ce sont deux familles sans recouvrement. Note d'honnêteté à porter au livre : une seconde variante plus riche existe dans le dépôt (24 templates, backend/app/agents/templates/origin/expert_agents.py) mais elle n'est câblée nulle part — ne pas la compter comme livrée.

La nuance qui compte

Trois distinctions se superposent. (1) NOYAU vs TOTAL : « 18 » = le noyau (6+6+4+2) sans les add-ons ; avec add-ons on obtient 21 (registre vivant, 3 add-ons) ou 24 (registre dormant, 6 add-ons). Ni 18 ni 21 n'est faux — ils comptent des périmètres différents, et la lettre mélange les deux en titrant 18 au-dessus d'un tableau qui somme à 21. (2) VALIDER vs GÉNÉRER : « validation historique » ne décrit qu'une partie du dispositif. Les 6 agents TRANSMÉDIA sont des producteurs de contenu (scénario de film, mécanique de jeu, biographie romancée) et 5 des 6 ont explicitement can_validate_facts=False. La lettre le reconnaît d'ailleurs dans son propre tableau (« Créateurs de contenu avec contraintes factuelles ») tout en titrant « Validation Historique ». 16/21 valident réellement des faits. (3) HOMONYMIE « 18 agents » : le chiffre 18 désigne AUSSI, ailleurs dans le corpus, un ensemble sans aucun rapport — les 18 agents de la Sphère 3 GOVERNMENT/Institutions (frontend/ATOM-Reference-Book*.html:~3470-3518, frontend/docs/architecture-agents.js:118). Citer « 18 agents » sans qualifier laisse le lecteur confondre deux familles disjointes. (4) Enfin, la lettre dit « Ces agents peuvent générer du contenu tout en validant les faits simultanément » — le code dit le contraire : les deux capacités sont mutuellement exclusives agent par agent (can_validate_facts=Falsecan_generate_content=True). C'est le système, pas l'agent, qui fait les deux.

Preuve

Fichiers : C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/agents/templates/origin_experts.py (424L, registre vivant l.376-403) · C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/agents/templates/origin/expert_agents.py (916L, l.796-819 = 18, l.822-831 = +6 → 24) · C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/api/routes/origin_routes.py (l.590-606 endpoint, l.656 `"expert_agents": 21`) · C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/tests/test_origin_module.py:86 `assert len(AGENT_REGISTRY) == 21` · C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/main.py:1758 (montage) · C:/Users/manon/Documents/GitHub/ATOM-CLEAN/frontend/content/lettre-aux-humains.md:2208-2218 (l'affirmation + son tableau à 21). Commandes : `sed -n '797,818p' .../origin/expert_agents.py | grep -c '": '` → 18 ; `sed -n '824,830p' ... | grep -c '": '` → 6 ; `grep -c "= ExpertAgentTemplate(" .../origin/expert_agents.py` → 24 ; `sed -n '376,403p' .../origin_experts.py | grep -c '": '` → 21 ; `grep -c "can_validate_facts=False" .../origin_experts.py` → 5 ; `grep -rn "templates.origin\b" backend/ --include=*.py | grep -v origin_experts` → aucun importeur (variante dormante).

pouls heartbeat 4.44s — AMBIGU

Ce que la lettre annonce

« Le Pouls — heartbeat 4.44 secondes » / « It operates on a 4.44-second heartbeat anchored at 444 Hz, synchronizing all modules » ; « Every module synchronizes to this pulse. »

Ce que le dépôt contient

4.44 s EXISTE dans le code — mais ce n'est PAS le heartbeat. Trois mesures : (1) Le battement système réel = VIBE_BASE 432 ms, avec les cadences dérivées VIBE_SHORT/VIBE_MEDIUM = 4320 ms (4,32 s) et VIBE_LONG = 43200 ms. Rapport de fréquence dans le code runtime : 172 occurrences de 4320 contre 33 de 4440. (2) 4440 ms est un constant nommé distinct — GUARDIAN_PULSE (444 Hz × 10), le pouls immunitaire/gardien, PAS le pouls global. Un seul module s'y enregistre : immune. (3) Et GUARDIAN_PULSE ne bat même pas à 4,44 s : les deux ordonnanceurs arrondissent en ticks entiers de VIBE_BASE — round(4440/432) = 10 → 10 × 432 = 4320 ms. Les fichiers l'avouent eux-mêmes en en-tête : « GUARDIAN_PULSE (4440 ms) tous les ~10 (arrondi) ». Côté backend, le heartbeat 4.44 s est DORMANT : dimensional_bus.start_heartbeat(interval_seconds=4.44) a ZÉRO appelant, et core/heartbeat.py (SIGNAL_INTERVAL=4.44) n'est pas monté. Le seul heartbeat réellement démarré au startup est HeartbeatEngine (app/main.py:386), qui dort à HEARTBEAT_INTERVAL = 5.0 secondes.

Comment le dire sans mentir

Deux formulations possibles, selon la place qu'on veut donner au 444 Hz. — VERSION COURTE (la plus sûre) : « Le Pouls — battement de base 432 ms, cadence de synchronisation 4,32 secondes. » — VERSION COMPLÈTE (qui garde l'intention 444 Hz sans mentir) : « Le Pouls — AT·OM bat sur un tick unique de 432 ms (VIBE_BASE). Les modules s'y accordent par multiples : 4,32 s pour les organes bio, 43,2 s pour les cycles longs. Le système immunitaire porte un pouls propre, le Pouls du Gardien, déclaré à 4,44 s (444 Hz × 10) et arrondi à 4,32 s à l'exécution, l'ordonnanceur ne comptant qu'en ticks entiers de 432 ms. » — Corrections précises à porter dans ATOM-Reference-Book*.html : remplacer « 4.44-second heartbeat ... synchronizing all modules » par « 432 ms base tick, 4.32 s module cadence » ; retirer « Every module synchronizes to this pulse » (un seul module, immune, s'enregistre sur GUARDIAN_PULSE) ; et ne PAS écrire que le backend bat à 4,44 s — le heartbeat WebSocket réellement démarré tourne à 5,0 s, le code 4.44 s n'ayant aucun appelant.

La nuance qui compte

Le mot « pouls » a DEUX SENS dans AT·OM, et c'est là toute la réponse. (1) Le POULS SYSTÈME (le vrai heartbeat, celui qui « synchronise tous les modules ») = VIBE_BASE 432 ms, avec sa cadence moyenne à 4,32 s. C'est un seul setInterval qui pilote tout le corps bio. (2) Le POULS DU GARDIEN = GUARDIAN_PULSE 4440 ms, dérivé de 444 Hz × 10, réservé au système immunitaire — un organe parmi d'autres, un seul abonné. Le livre de référence a pris le pouls d'un organe pour le pouls du cœur. Second niveau de nuance : même le pouls du gardien est NOMINAL, pas EFFECTIF. Comme tout passe par un ordonnanceur unique cadencé à 432 ms, 4440 est arrondi à 10 ticks et bat en réalité à 4320 ms. 4,44 s est donc une valeur déclarée qui n'existe à l'exécution que dans deux chemins de repli (immune-system.js:470 et atom-websocket.js:436, actifs seulement si BioTickMaster est absent). Troisième niveau : côté backend, l'écart est encore plus net — le 4.44 s doctrinal (SIGNAL_INTERVAL, start_heartbeat) est du code mort non appelé, tandis que le heartbeat WebSocket qui tourne vraiment en production bat à 5,0 s, une valeur qui n'est ni canon ni harmonique.

Preuve

Cadence canon : C:/Users/manon/Documents/GitHub/ATOM-CLEAN/frontend/js/sacred-constants.js:51-54 (VIBE_BASE: 432, VIBE_SHORT: 4320, VIBE_MEDIUM: 4320, VIBE_LONG: 43200) et :163 (GUARDIAN_PULSE: 4440, « 444 Hz × 10 — immune system heartbeat »). — Arrondi frontend : C:/Users/manon/Documents/GitHub/ATOM-CLEAN/frontend/js/bio-tick-master.js:351 `var ticksPerCadence = Math.max(1, Math.round(resolvedCadenceMs / VIBE_BASE));` + aveu en-tête ligne 19 « GUARDIAN_PULSE(4440ms) ~ tous les 10 -- immune (arrondi) ». — Arrondi backend identique : C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/core/bio_tick_backend.py:79 `tpc = max(1, round(cadence_ms / VIBE_BASE))`, :38 `GUARDIAN_PULSE: int = 4440`, :112 `await asyncio.sleep(VIBE_BASE / 1000.0)`. Calcul vérifié : `node -e "Math.round(4440/432)"` → 10 → 10×432 = 4320 ms. — Un seul abonné : `grep -rn "GUARDIAN_PULSE" --include=*.js frontend/js | grep register` → 1 résultat, immune-system.js:466. — Backend 4.44 dormant : `grep -rn "start_heartbeat" --include=*.py backend/` → seulement les 2 définitions (app/engines/dimensional_bus.py:492, core/heartbeat.py:161), AUCUN appelant. — Heartbeat réellement démarré : backend/app/main.py:386 `await heartbeat_engine.start()` → :232 `await asyncio.sleep(config.HEARTBEAT_INTERVAL)` → :68 `HEARTBEAT_INTERVAL: float = 5.0`. — Comptage runtime : `grep -rn "4320" --include=*.js --include=*.py frontend/js backend agents core | wc -l` → 172 ; même commande avec `4440` → 33. — L'affirmation auditée vit dans C:/Users/manon/Documents/GitHub/ATOM-CLEAN/frontend/ATOM-Reference-Book.html:454, :469, :559, :566-567 (et les 4 variantes Public/Investor/ESO du même livre).

lois immuables 6 vs 12 — AMBIGU

Ce que la lettre annonce

« 6 lois immuables — Six lois gravées dans le code, même le système ne peut pas les enfreindre » (landing.html) / « 6 Lois Immuables — gelées, ne peuvent jamais être modifiées » (Lettre aux humains) — vs « 12 lois canon eta » (CLAUDE.md).

Ce que le dépôt contient

Le mot « loi » recouvre AU MOINS 5 familles distinctes et non interchangeables dans le dépôt. (1) 6 Lois Fondamentales CHE·NU — 6 exactement, mais UNIQUEMENT en documentation (archives/ + docs/agents-specs/), ZÉRO occurrence en code actif : aucun fichier .py/.js ne définit cet ensemble de 6. (2) Ce qui est réellement gravé dans le code et exécuté = 3 Tree Laws (backend/app/core/tree_laws.py, enum TreeLaw : HUMAN_AGENCY, NO_MANIPULATION, FULL_TRANSPARENCY, enforcement HTTP 423) + 8 CORE_PRINCIPLES (backend/app/core/foundation.py, tuple frozen) — les deux appelés live depuis nova_pipeline.py Lane D (l.914-932) et master_mind.py (l.469-482). Donc 3+8, pas 6. (3) 12 lois canon η — 12 confirmées dans la source doctrinale (12 titres « ### Loi N » dans atlas-decodage.md) et 12 membres d'enum AncestralLaw, mais seulement 7 primitives Python livrées (lois 1,2,4,5,7,10,12) ; les lois 3,6,8,9,11 n'ont AUCUN fichier. (4) 46 Lois du Covenant — 46 entrées comptées dans COVENANT_LAWS (frontend/js/covenant-transducer.js). (5) 5 lois mathématiques sealed (enum SealedMathematicalLaw). Bonus dérive : docs/research/PRESENTATION-ATOM-FIRE-HORSE.md annonce « 7 lois immuables » avec une liste entièrement différente (Souveraineté Humaine, Transparence Totale, Frontière d'Identité, IA-à-IA Contrôlé, Ordre Chronologique, Traçabilité, Architecture Gelée) — troisième compte incompatible pour le même intitulé « lois immuables ».

Comment le dire sans mentir

Pour la garantie publique (landing / Lettre), remplacer « 6 lois immuables — six lois gravées dans le code » par : « 3 lois de l'Arbre gravées dans le code — Agentivité humaine, Non-manipulation, Transparence totale. Le système les vérifie à chaque action et bloque (HTTP 423) s'il les enfreint. Elles s'appuient sur 8 principes fondateurs gelés, hérités des 6 Lois Fondamentales CHE·NU. » — c'est vérifiable ligne par ligne et ça garde l'intention (« même le système ne peut pas les enfreindre » devient vrai, car c'est exactement ce que fait check_tree_laws). Pour le corpus canon (CLAUDE.md), écrire : « 12 lois canon η énoncées (atlas-decodage.md), 12 référencées en enum, 7 outillées en primitives Python — les lois 3, 6, 8, 9 et 11 restent documentaires. » Et surtout, poser le lexique une fois pour toutes dans le livre de référence : « loi » désigne cinq choses distinctes dans AT·OM — 3 lois de l'Arbre (exécutées), 8 principes Foundation (exécutés), 6 lois CHE·NU (héritage doctrinal), 12 lois η (méthode de décodage), 46 lois du Covenant (signature vibratoire) — plus 5 lois mathématiques scellées. Nommer la famille à chaque mention supprime la contradiction. Enfin, corriger ou dater PRESENTATION-ATOM-FIRE-HORSE.md, dont les « 7 lois immuables » sont une troisième liste sans correspondant en code.

La nuance qui compte

La contradiction apparente 6 vs 12 n'en est PAS une : ce sont deux familles sans rapport. Les 12 lois η sont épistémiques (méthode de décodage du canon, autorité doctrinale, hf-atom-tools/) ; les 6 lois CHE·NU sont éthiques/constitutionnelles (droits de l'usager, héritage CHE·NU gelé). Les mélanger est l'erreur à éviter. La vraie divergence est ailleurs, et elle est double. (a) LIVRÉ vs DOCTRINAL sur les 12 : 12 lois énoncées, 12 référencées, 7 outillées en Python — 5 n'existent que comme entrée d'enum pointant vers un .md. (b) DOCUMENTÉ vs GRAVÉ sur les 6 : le chiffre 6 est exact comme énoncé documentaire, mais la phrase « gravées dans le code » est fausse au sens strict — le code n'applique pas 6 lois, il applique 3 Tree Laws + 8 principes Foundation. Les 6 CHE·NU sont couvertes en substance (souveraineté, non-manipulation, réversibilité, consentement se retrouvent dans FORBIDDEN_CAPABILITIES / AUTHORITY_MODEL / SILENCE_GUARANTEES) mais jamais sous forme d'une liste de 6 énumérable et testable. Enfin, trois listes différentes (6, 7, 3) circulent sous l'étiquette « lois immuables » : c'est le vrai défaut de cohérence, pas le 6 lui-même.

Preuve

Les 6 CHE·NU (doc seule) : C:/Users/manon/Documents/GitHub/ATOM-CLEAN/archives/backend-reference/onedrive-chenu-lock-core/FOUNDATION_LAWS.md l.17-22 (tableau 6 lignes) + CORE_REFERENCE.md l.47-58 ; copies docs/agents/ et docs/agents-specs/CHENU_AGENTS_CORE_6_Foundational_NovaArchitect_v1_0.md l.9. Annonces publiques : frontend/landing.html l.5229-5230 ; frontend/content/lettre-aux-humains.md l.3198 ; frontend/livre-reference.html l.3155. Code réellement exécuté : backend/app/core/tree_laws.py l.32-35 (enum 3 membres) + l.48-80 (3 TreeLawDefinition) ; backend/app/core/foundation.py l.29-37 (CORE_PRINCIPLES = 8 chaînes) ; wiring : backend/app/services/nova_pipeline.py l.914-932 et backend/app/services/master_mind.py l.469-482. Absence prouvée du groupe de 6 en code : `grep -rn "FOUNDATION_LAWS|foundationLaws|IMMUTABLE_LAWS|LOIS_FONDAMENTALES|sixLaws" backend/ frontend/js/` → 0 résultat. Les 12 η : `grep -c "^### Loi [0-9]" memory/ancestral/architecture/atlas-decodage.md` → 12 (l.539 à 642) ; hf-atom-tools/atom_canon/laws/__init__.py l.85-98 (enum LAW_01..LAW_12) ; `ls hf-atom-tools/atom_canon/laws/*.py | wc -l` → 8 = __init__.py + 7 primitives seulement (law1, law2, law4, law5, law7, law10, law12 — pas de law3/6/8/9/11) ; le fichier l'écrit lui-même l.11 : « 7 primitives Python directes ». Les 46 : comptage des `id:` dans le bloc COVENANT_LAWS de frontend/js/covenant-transducer.js (l.99 à `];`) → 46. Les 7 concurrentes : docs/research/PRESENTATION-ATOM-FIRE-HORSE.md l.219-231 et l.412.

18 oracles essaim sagesse — EXACT

Ce que la lettre annonce

« 18 Oracles — essaim de sagesse » / « 18 perspectives uniques sur chaque sujet »

Ce que le dépôt contient

18 oracles réellement définis, confirmés par trois sources indépendantes et concordantes : 18 clés dans le dict ORACLES de backend/app/data/oracles_data.py (répartition 3/4/4/4/3 sur 5 cercles), 18 oracles numérotés 1-18 dans MAP_CIRCLES de backend/app/data/master_map_data.py (avec "total_oracles": 18), et 18 entrées dans FALLBACK_ORACLES de frontend/js/oracle-unified.js (num: 1 → num: 18). Le routeur est monté pour de vrai (main.py:1707, préfixe /api/v2/oracles), expose 8 endpoints, et /query effectue un routage réel par pattern regex vers cercle primaire + secondaires. En revanche, AUCUN oracle ne produit d'analyse : _invoke_oracle (oracle_swarm.py:411) retombe sur _generate_default_response, qui renvoie des gabarits de chaîne ; register_oracle_handler n'a zéro appelant dans tout le dépôt ; et illuminate() n'est exposé par aucune route HTTP (seuls les tests l'importent).

Comment le dire sans mentir

Garder le chiffre, préciser l'état : « 18 Oracles — 18 perspectives définies (identité, cercle, spécialité, prompt), réparties en 5 cercles concentriques. L'API de consultation et le routage par thème sont livrés ; le raisonnement propre à chaque Oracle reste à brancher. » Si l'on tient à la formule d'essaim : « Un essaim de 18 Oracles : l'orchestration (5 phases, exécution parallèle, routage) est bâtie et testée ; les 18 voix sont écrites mais pas encore raccordées à un modèle — elles répondent aujourd'hui par gabarit. » À éviter tel quel : « 18 perspectives uniques sur chaque sujet » au présent, qui laisse croire que 18 analyses distinctes sont produites à chaque requête. Et harmoniser la lettre, qui annonce les 18 Oracles comme acquis à un endroit et les note à 0% quelques milliers de lignes plus loin.

La nuance qui compte

Le chiffre 18 est juste, mais le mot « Oracle » a deux sens et l'écart entre les deux est tout le sujet. (1) Oracle = fiche de persona : identité, cercle, spécialité, mission et system_prompt rédigé — 18/18 livrés, complets, servis par l'API. (2) Oracle = organe qui produit une analyse : 0/18. L'essaim s'exécute vraiment (asyncio.gather, protocole en 5 phases, calcul d'Arithmos et de fréquence Hz effectifs) mais chaque oracle rend un gabarit du type « [Nom] Analyse de 'mot' depuis le Cercle N. », pas une pensée. Le point de branchement existe (register_oracle_handler) mais n'est jamais appelé : c'est un socle prêt à recevoir des cerveaux, pas un essaim qui pense. La lettre le documente d'ailleurs elle-même ailleurs (frontend/content/lettre-aux-humains.md:2823 affiche « 18 Oracles 0% 🔴 » et :2860 liste la route /api/v2/oracles/illuminate en TODO) — donc la promesse et l'aveu cohabitent dans le même document, ce qui est incohérent pour le lecteur. Détail secondaire : les deux registres comptent bien 18 chacun mais portent des titres différents pour un même id (ORIGIN_HISTORIAN = « Historian of Civilizations » dans oracles_data.py, « L'Archeologue du Verbe » dans master_map_data.py et le frontend) — le compte tient, mais un lecteur qui croise les deux voit deux panthéons.

Preuve

Comptages : `grep -oP '^\s{4}"[A-Z_]+"(?=: \{)' backend/app/data/oracles_data.py | wc -l` → 18 ; `grep -oP '"circle": \d' backend/app/data/oracles_data.py | sort | uniq -c` → 3/4/4/4/3 ; `grep -n total_oracles backend/app/data/master_map_data.py` → ligne 87 `"total_oracles": 18` ; `sed -n '257,340p' frontend/js/oracle-unified.js | grep -c "{ id:"` → 18. Montage : `grep -n oracles backend/app/main.py` → ligne 1707 `register_router("app.routers.oracles", "/api/v2/oracles", ["Oracles"], "oracles")` ; `grep -n "@router\." backend/app/routers/oracles.py` → 8 endpoints. Absence de câblage LLM : `grep -rn "register_oracle_handler" --include="*.py" . | grep -v "def register"` → 0 résultat ; `grep -rn "oracles/illuminate" --include="*.py" --include="*.js" .` → 0 résultat ; `grep -rn "get_swarm\b|oracle_swarm" --include="*.py" backend/` → seul backend/tests/unit/test_oracle_swarm_merge_adapter.py. Gabarits : backend/app/services/oracle_swarm.py:453-470 (_generate_default_response). Appels frontend réels : frontend/js/oracle-unified.js:326 et :389.

12 moteurs civilisationnels nexus transduction — EXACT

Ce que la lettre annonce

« 12 moteurs civilisationnels (Nexus de transduction) »

Ce que le dépôt contient

12 exactement, et la bijection est parfaite. backend/app/engines/nexus_transduction.js (613L) porte en clair « IMPORTS DES 12 MOTEURS CIVILISATIONNELS » (l.55) suivi de 12 import : tzolkin, yiking, kabbalah, chakra, cymatics, egypt, greek, aztec, electromagnetic, rapanui, sumerian, atlantis. Les 12 fichiers cibles existent tous (403L à 678L chacun, 6 447L cumulés). NEXUS_CONFIG.civilizations liste les 12 mêmes entrées avec role/layer/priority, réparties en 6 niveaux. Le schéma ASCII de l'en-tête reprend les 12. Aucun écart : ni moteur annoncé-manquant, ni moteur présent-non-déclaré.

Comment le dire sans mentir

Deux options selon la précision voulue. Courte : « 12 moteurs civilisationnels déclarés et présents dans le Nexus de transduction (source JS, 6 447 lignes) — non exécutés par le runtime FastAPI, qui expose de son côté un catalogue plat de 27 moteurs. » Longue, si le livre veut porter la distinction : « Le Nexus de transduction (backend/app/engines/nexus_transduction.js) fédère 12 moteurs — 10 civilisationnels (Maya, Yi-King, Kabbale, Chakras, Égypte, Grèce, Aztèque, Rapa Nui, Sumer, Atlantide) et 2 moteurs de signal (électromagnétisme, cymatique). Les 12 fichiers existent, la déclaration et le code concordent exactement. Ce sont des modules ES6 : ils constituent la source du Nexus, pas encore un service en fonction — le backend Python ne les charge pas. L'API REST livrée expose, elle, un catalogue plat de 27 moteurs où le Nexus figure comme simple pont. » À corriger au passage, hors périmètre de cette affirmation : la docstring « all 29 » de routers/engines.py (réel 27) et le « 14 moteurs civilisationnels (Horus, Maat, Pythagore) » de nova.py:250, qui ne correspond à rien dans le dépôt.

La nuance qui compte

Trois distinctions, par ordre d'importance. (1) ÉCRIT vs EXÉCUTÉ — ce sont des modules ES6 (import/export) posés dans un backend Python. backend/ n'a ni package.json ni bundler, et engines/__init__.py n'expose que la couche dimensionnelle Sephiroth : le runtime FastAPI ne charge jamais ces 12 fichiers. Le code est présent, substantiel et cohérent, mais dormant côté serveur. (2) « MOTEUR » A DEUX SENS — dans le Nexus JS, moteur = l'un des 12 modules de civilisation orchestrés ; dans l'API REST livrée (routers/engines.py), moteur = une entrée d'un catalogue plat de 27, où nexus_transduction n'est qu'UNE ligne de type « bridge », pas un chef d'orchestre. Même mot, deux granularités : le Nexus est un moteur dans un registre, et le contenant de 12 dans l'autre. C'est pourquoi le dépôt affiche 12, 27, 18 et 14 sans se contredire vraiment. (3) « CIVILISATIONNEL » EST GÉNÉREUX — sur les 12, dix sont des civilisations (Maya, Chine, Hébreu, Inde, Égypte, Grèce, Aztèque, Rapa Nui, Sumer, Atlantide) ; electromagnetic et cymatics sont classés origine « Science » dans le catalogue Python et rangés « Niveau 5 : Signal » dans le Nexus. Ce sont des couches physiques, pas des civilisations. Enfin, nova.py:250 injecte « 14 moteurs civilisationnels (Horus, Maat, Pythagore…) » dans la directive LLM — chiffre ET noms sans correspondance dans aucun catalogue réel : c'est la seule vraie fausseté du lot, et elle est servie à l'agent Nova.

Preuve

`backend/app/engines/nexus_transduction.js` l.55-69 (imports) et l.83-110 (NEXUS_CONFIG.civilizations). Comptages : `grep -c "^import .*Engine from './" backend/app/engines/nexus_transduction.js` → 12 ; `sed -n '/civilizations: {/,/^  },/p' … | grep -c "role:"` → 12 ; boucle `test -f` sur les 12 cibles → 12/12 OK ; `cat <les 12>.js | wc -l` → 6447. Chiffres concurrents : `backend/app/routers/engines.py` ENGINE_CATALOG → 27 entrées comptées (docstring l.108 annonce « all 29 » = drift 2) ; `backend/app/routers/nova.py:250` → « 14 moteurs de calcul » ; `frontend/js/engine-registry.js:3` → « 18 engines classified into 8 castes ». Liveness : aucun `package.json` ni bundler sous `backend/` ; `backend/app/engines/__init__.py` n'exporte que la couche dimensionnelle (router/providers/bus/torus), jamais les 12 ; `grep -rn "app/engines" backend/app/main.py backend/app/routers/engines.py` → 0 résultat.

3 hubs interface synaptique — EXACT

Ce que la lettre annonce

« LES 3 HUBS — L'Interface Synaptique » : « Toute interaction dans l'Arche passe par 3 Hubs synchronisés » (Communication/Dire, Navigation/Voir, Exécution/Faire) ; « Les 3 hubs ne divergent JAMAIS… Si un hub échoue → Retour en arrière total. »

Ce que le dépôt contient

Le chiffre 3 est EXACT et n'est nulle part contredit : l'énumération HubType compte exactement 3 membres (COMMUNICATION, NAVIGATION, EXECUTION), le switcher expose exactement 3 adaptateurs, et la ceinture d'outils du frontend compte exactement 3 en-têtes (NavHub, CommHub, ExecHub). Réalité de livraison à deux vitesses : (a) LIVRÉ et rendu — frontend/js/desktop-shell.js HUB_SECTIONS (l.122) regroupe 12 entrées d'outils sous 3 séparateurs, effectivement bouclé et rendu (l.811 this.HUB_SECTIONS.forEach) ; (b) CODÉ MAIS DORMANT — le Synaptic Switcher atomique (backend/core/synaptic/, 1660 L sur 4 fichiers, tous trackés git) implémente bien la commutation atomique 3/3 avec rollback (f"Only {len(activated_hubs)}/3 hubs activated", switcher l.476), mais il a ZÉRO importateur hors de son propre paquet : aucun main.py, aucun router, aucun service ne l'importe. La garantie « jamais de divergence / rollback total » n'est donc exécutée par rien au runtime. Aucun endpoint REST n'expose les 3 hubs : le seul router synaptique monté (synaptic_graph_router, main.py l.1409) ne contient aucune occurrence de « hub ».

Comment le dire sans mentir

Garder le 3 — il est juste — mais séparer ce qui est rendu de ce qui est écrit. Proposition : « 3 hubs transversaux — Communication (Dire), Navigation (Voir), Exécution (Faire). Les 3 structurent la ceinture d'outils du bureau et sont visibles dans l'interface (12 outils répartis sous NavHub, CommHub, ExecHub). Le Synaptic Switcher qui doit les commuter atomiquement — activation 3/3 ou rollback total — est écrit (1660 lignes, backend/core/synaptic/) mais pas encore branché au runtime : la garantie de non-divergence est un contrat de conception, pas encore une propriété exécutée. » Si une seule phrase est possible : « 3 hubs livrés dans l'interface ; leur commutation atomique est codée mais pas encore câblée. » Éviter absolument « toute interaction passe par les 3 hubs » au présent de l'indicatif : aucun chemin de code ne le fait aujourd'hui. Et ne jamais laisser un lecteur additionner ce 3 avec les ~30 fichiers nommés « hub » du dépôt — ce sont des hubs de domaine, un autre mot sous la même orthographe.

La nuance qui compte

Le mot « hub » a TROIS sens distincts dans le dépôt, et seul le premier correspond à l'affirmation. (1) Les 3 hubs synaptiques transversaux CommHub/NavHub/ExecHub — Dire/Voir/Faire, l'objet de la lettre. (2) Les hubs de domaine, sans aucun rapport avec le 3 : 7 modules JS (comms-hub-module.js, community-hub.js, connector-hub.js, creation-hub-module.js, creation-studio-hub.js, geo-hub-module.js, realtime-sync-hub.js), 7 routers backend (communications_hub_router.py, creation_hub_router.py, environment_hub_router.py, hr_hub_router.py, personal_hub_router.py, real_estate_hub_router.py, transport_hub_router.py), 13 services hub.py et 4 contrats alembic *_hub_contract.py. Compter les fichiers nommés « hub » donnerait ~30, jamais 3 — ce n'est pas la même chose. (3) Le « 3 HUBS layout » : une convention CSS de grille à 3 colonnes (panneau gauche / visualisation centre / détails droite) présente dans 9 pages HTML (civilization, dashboard, frequencies, funder, griffe, live, livre-reference, nexus, spheres) — purement visuel, sans lien avec Dire/Voir/Faire. Seconde nuance, celle qui compte pour l'honnêteté : la lettre affirme un comportement runtime (« ne divergent JAMAIS », « retour en arrière total »). Ce comportement est écrit, pas branché. Les 3 hubs sont livrés comme organisation de l'interface ; la commutation atomique qui les garantit est du code dormant.

Preuve

Source de l'affirmation : `C:/Users/manon/Documents/GitHub/ATOM-CLEAN/frontend/content/lettre-aux-humains.md` l.1218-1268 (dupliqué dans `archives/docs-historiques/LETTRE_AUX_HUMAINS.md`). — Comptage du 3 : `backend/core/synaptic/synaptic_context.py` l.28-32 (`class HubType(str, Enum)` = 3 membres) ; `backend/core/synaptic/synaptic_switcher.py` l.368-372 (`hub_adapters` = dict de 3) et l.476 (`Only {n}/3 hubs activated`). — Non-câblage : `grep -rn "core.synaptic|synaptic_switcher|SynapticSwitcher" --include=*.py backend/ | grep -v __pycache__ | grep -v "^backend/core/synaptic"` → 0 résultat ; `grep -rn "HubType" --include=*.py backend/` → toutes les occurrences sont internes à `backend/core/synaptic/` ; `grep -n "hub" backend/app/routers/synaptic_graph_router.py` → 0 résultat. — Livraison frontend : `frontend/js/desktop-shell.js` l.121-141 (`HUB_SECTIONS`, 3 séparateurs) et l.811-812 (rendu). — Tailles : `wc -l backend/core/synaptic/*.py` → 106 + 376 + 566 + 612 = 1660. — Autres attestations doctrinales cohérentes : `backend/app/routers/spheres.py` l.24, `backend/schemas/agent_schemas.py` l.37, `frontend/docs/architecture-data.js` l.40, `rosetta-core/src/components/layout/CommHub.tsx`.

15 besoins fondamentaux — EXACT

Ce que la lettre annonce

« Le système de modules est organisé autour de 15 besoins fondamentaux » (LETTRE_AUX_HUMAINS.md §« 15 BESOINS FONDAMENTAUX », suivi d'un tableau numéroté 1→15)

Ce que le dépôt contient

15 besoins, exactement. Trois sources indépendantes dans le code LIVE concordent parfaitement sur le nombre, les noms ET l'ordre : (1) backend/app/services/canon_needs.py — 15 appels _register() peuplant le registry CANONICAL_NEEDS ; (2) backend/app/modules/canon/need_canon.py — 15 objets Need(...) dans la classe NeedCanon ; (3) backend/app/modules/canon/catalog/need_canon.v1.yaml — 15 entrées - id: need. Les 15 dans l'ordre : clarity, execution, memory, governance, safety, trust, learning, coordination, communication, discovery, organization, identity, presence, resilience, performance. Le tableau français de la Lettre (Clarté, Exécution, Mémoire, Gouvernance, Sécurité, Confiance, Apprentissage, Coordination, Communication, Découverte, Organisation, Identité, Présence, Résilience, Performance) est la traduction fidèle 1:1 de cette liste. C'est LIVRÉ et CÂBLÉ, pas doctrinal : backend/app/routers/canon.py expose 7 endpoints qui consomment get_canon_needs() (dashboard, get_all_needs, get_need, get_needs_for_sphere, assess_needs, find_coverage_gaps, get_need_mapping), et le router est monté dans main.py:1880 via register_router("app.routers.canon", ...). backend/app/routers/modules.py:45-57 expose en parallèle NeedCanon (import optionnel HAS_).

Comment le dire sans mentir

Le chiffre est bon — le garder tel quel. Formulation recommandée : « 15 besoins fondamentaux — Clarté, Exécution, Mémoire, Gouvernance, Sécurité, Confiance, Apprentissage, Coordination, Communication, Découverte, Organisation, Identité, Présence, Résilience, Performance. Cette taxonomie est livrée et câblée : elle existe en trois exemplaires concordants dans le code (canon_needs.py, need_canon.py, need_canon.v1.yaml) et est interrogeable par API via le router Canon monté au démarrage. » Si l'on veut être précis sur ce que la grille EST, ajouter la glose : « Ce ne sont pas les besoins matériels d'une personne, mais la grille canonique de ce que tout module, agent ou flux de travail doit servir — un module qui ne déclare aucun besoin n'est pas activable. » (formulation tirée du principe inscrit dans le YAML lui-même : « A module must declare which needs it serves; otherwise it is not activable in simulation »). Éviter d'écrire « besoins humains fondamentaux » sans glose : la citation de la Lettre « Chaque module répond à des besoins humains fondamentaux » pousse vers une lecture Maslow que le code ne porte pas — la grille réelle est architecturale (Performance, Résilience, Gouvernance ne sont pas des besoins humains).

La nuance qui compte

Trois nuances, aucune ne change le compte de 15. (1) DÉRIVE D'IDENTIFIANTS dans le YAML : les 11 premiers besoins utilisent le séparateur point (need.clarityneed.organization), mais les 4 derniers utilisent l'underscore (need_identity, need_presence, need_resilience, need_performance), alors que les deux sources Python emploient uniformément le point (need.identity, etc.). C'est une incohérence réelle du catalogue YAML — un croisement YAML↔Python sur ces 4 ids échouerait. À signaler comme dette technique, pas comme erreur de comptage. Le YAML donne aussi au 12e le label « Identity Boundary » là où le Python dit « Identity ». (2) DEUX SENS DU MOT « BESOIN » dans le dépôt. Sens A (celui de l'affirmation) = la taxonomie canonique des 15 besoins que tout module/agent/workflow doit servir — c'est une grille d'évaluation d'architecture, pas une liste de besoins humains matériels type Maslow. Sens B = les « BESOINS LOCAUX », un moteur de place-de-marché des besoins d'une communauté (LNIS / Moteur de Civilisation) : concept entièrement distinct, et VÉRIFIÉ MORT dans le code live — grep -rln "besoins_locaux|local_needs|BesoinLocal" sur backend/app/ et frontend/js/ ne retourne rien ; il ne survit que dans archives/backend-reference/.../BesoinsPage.js, transit/v46-economy/ et docs/research/ATOM-GOVERNANCE-MASTER.md. Un lecteur de la Lettre pourrait confondre les deux. (3) DUPLICATION DE L'ARBRE : backend/modules/canon/ duplique backend/app/modules/canon/ (même YAML, même need_canon.py) — deux copies du catalogue, une seule est importée par les routers (app.modules.canon).

Preuve

Fichiers : C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/services/canon_needs.py (344 L) ; C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/modules/canon/need_canon.py ; C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/modules/canon/catalog/need_canon.v1.yaml ; C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/routers/canon.py (lignes 88-151) ; C:/Users/manon/Documents/GitHub/ATOM-CLEAN/backend/app/main.py:1880 ; texte source C:/Users/manon/Documents/GitHub/ATOM-CLEAN/docs/vision/LETTRE_AUX_HUMAINS.md:1958-1980 (copies identiques dans frontend/content/lettre-aux-humains.md et archives/docs-historiques/). Commandes : `grep -c "^_register(" backend/app/services/canon_needs.py` → 15 ; `grep -c "Need(" backend/app/modules/canon/need_canon.py` → 15 ; `grep -c "^- id: need" backend/app/modules/canon/catalog/need_canon.v1.yaml` → 15 ; `grep -o 'id="need[a-z._]*"' backend/app/modules/canon/need_canon.py` → les 15 ids en clair ; `grep -rn "get_canon_needs" backend/app/routers/` → 7 sites d'appel dans canon.py ; `grep -n "app.routers.canon\"" backend/app/main.py` → ligne 1880 (montage confirmé).

Synthèse

RELEVÉ

RELEVÉ — 12 affirmations chiffrées vérifiées contre le dépôt

1. CE QUI TIENT — à garder tel quel

AnnoncéMesuréÉtat
15 besoins fondamentaux15, dans 3 sources concordantes (canon_needs.py, need_canon.py, need_canon.v1.yaml), router Canon montéLivré et câblé
12 moteurs civilisationnels12 imports = 12 fichiers, 6 447 L, bijection parfaiteÉcrit, non exécuté (modules ES6 dans un backend Python)
18 Oracles18 dans 3 registres (backend data, master map, frontend)Personas + API livrés ; le raisonnement n'est pas branché
3 Hubs3, jamais contredit (HubType, switcher, ceinture d'outils)Rendus dans l'interface ; la commutation atomique est dormante

Quatre chiffres justes. Trois d'entre eux exigent quand même une mention d'état : le compte est bon, l'exécution ne suit pas. « 18 perspectives uniques sur chaque sujet » au présent est la seule formule à retirer — les 18 Oracles répondent aujourd'hui par gabarit.

2. CE QUI DÉRIVE — du plus gros écart au plus petit

1. Routeur LLM — 18+ annoncés → 4 branchés (écart 4,5×)
Le plus grave du lot, et pas seulement pour le chiffre : Anthropic et Google, les deux noms mis en vedette, n'ont pas d'adaptateur et retournent une réponse simulée avec finish_reason="stop", un coût et un compte de jetons. Le mock réussit au lieu d'échouer. Cohere, Together et Replicate n'existent que comme constantes de chaîne.
« Routeur multi-fournisseurs — 4 branchés en direct (OpenAI, Ollama/Gemma, vLLM, Zhipu GLM), 19 au plan. »
→ À traiter comme défaut, pas comme formulation : faire échouer proprement les fournisseurs non branchés.

2. Sphères — 16 annoncées → 9 (+1 technique) (écart 1,8×)
Le « 16 » vient d'un fichier mort (backend/schemas/agent_schemas.py) qui compte 15 entrées sous un commentaire disant 16, en appelant 6 membres d'enum inexistants — il planterait à l'import. Le code vivant gèle 9 (Règle #7) + S0.
« 9 sphères de contenu, 10 avec la sphère de transit. »
Plus grave que le chiffre : les « 9 Sphères de l'Arche » de la Lettre (IDENTITÉ, SANTÉ, SAVOIR, ÉCONOMIE…) ne coïncident avec les 9 du code que par le nombre. Six n'ont aucun équivalent. Et la FAQ énonce une troisième liste de 10 qui invente XR et Labo IA. Corriger « 16 → 9 » sans réconcilier les noms laisserait le livre faux.

3. Agents — 400+ / 350 annoncés → 238 au registre, 405 fiches, 4 qui exécutent (écart 1,5× à 100×)
Trois chiffres pour trois choses. Le « 350 » n'est pas inventé : 226 réels + 124 fiches archivées des verticales V68 retirées, dont le dépôt dit lui-même « archive déclarative, non-runtime ».
« 238 agents au registre, 405 fiches de capacités, 4 orchestrateurs cardinaux qui exécutent. »
→ « L'Essaim » décrit comme visualisation interactive n'existe dans aucun fichier.

4. Pouls — 4,44 s annoncé → 432 ms / 4,32 s (écart : mauvais organe)
4,44 s existe, mais c'est GUARDIAN_PULSE, le pouls immunitaire, un seul abonné. Et même lui bat à 4,32 s : l'ordonnanceur arrondit round(4440/432) = 10 ticks. Côté backend, le 4,44 s est du code mort ; le heartbeat réellement démarré tourne à 5,0 s.
« Battement de base 432 ms, cadence de synchronisation 4,32 s. »
→ Retirer « Every module synchronizes to this pulse ».

5. Profils — 76 annoncés → 84 dossiers / 66 numéros (écart de sens, pas de volume)
76 = plafond de numérotation P001-P076, pas un décompte. 8 numéros portent deux métiers. ~14 400 lignes de Python importées nulle part, et 5 dossiers sur 74 mentionnent un dashboard.
« 84 profils métiers écrits en code. Bibliothèque livrée, câblage à l'interface à venir. »
→ Ligne fausse à retirer indépendamment : « Profils Exécutifs (P001-P010) : CEO • CTO • CFO ». Les P001-P010 réels sont dix personas de métier (musicien, cardiologue, avocate…).

6. Experts ORIGIN — 18 annoncés → 21 vivants (le tableau de la Lettre somme déjà à 21)
18 = le noyau d'un module dormant ; 21 = le registre monté en API. Et 5 des 21 ne valident rien (can_validate_facts=False) : 16 validateurs réels.
« 21 agents experts ORIGIN — 18 au noyau, 3 add-ons. 16 valident les faits, 5 produisent du transmédia sous contrainte. »

7. Verticales — 21 annoncées → 21 domaines montés, 0 dossier
Le chiffre tient au sens « domaine avec API vivante » (21/21 vérifiés). Il ne tient pas au sens « module packagé » : backend/verticals/ est vide. Ce n'est pas une perte, c'est une canonicalisation assumée.
→ Ce qui est faux, c'est la promesse uniforme : « chacun avec ses propres agents IA, pages, API complète et bases de données ». CRM = 39 endpoints ; Immobilier = 41 lignes, 3 endpoints.

8. Lois — 6 annoncées « gravées dans le code » → 3 + 8
Les 6 lois CHE·NU existent en documentation seulement : zéro occurrence en code actif. Ce qui est réellement exécuté et bloque (HTTP 423) = 3 Tree Laws + 8 principes Foundation.
« 3 lois de l'Arbre gravées dans le code — Agentivité humaine, Non-manipulation, Transparence totale — appuyées sur 8 principes fondateurs gelés, hérités des 6 Lois CHE·NU. »
→ Ainsi formulé, « même le système ne peut pas les enfreindre » devient vrai.

3. LES MOTS À DOUBLE SENS

Sept mots portent plusieurs sens incompatibles. C'est de là que vient l'essentiel des désaccords — pas de l'arithmétique.

Recommandation : poser ce lexique une fois, en tête du livre de référence. Nommer la famille à chaque mention supprime la majorité des contradictions apparentes sans changer un seul chiffre.

4. CE QU'IL FAUT DATER — trop mouvant pour être gravé

Ne pas graver de nombre absolu, ou l'accompagner d'une date de mesure :

Dette documentaire à régler avant toute réécriture — sans quoi rien n'arbitrera les listes contradictoires :

  1. memory/project_taxonomy_spheres.md et memory/project_taxonomy_canaux.md, cités par CLAUDE.md comme mémoires canoniques, n'existent pas. Signalé par l'audit B-62 le 2026-05-25, jamais corrigé. Seul le code tranche aujourd'hui.
  2. Les 5 fichiers ATOM-Reference-Book*.html:366 disent encore « 20 Verticals » quand la Lettre dit 21.
  3. docs/research/PRESENTATION-ATOM-FIRE-HORSE.md porte une troisième liste de « 7 lois immuables » sans correspondant en code.
  4. nova.py:250 injecte « 14 moteurs civilisationnels (Horus, Maat, Pythagore) » dans la directive LLM — chiffre et noms sans correspondance nulle part. Servi à l'agent en production.
  5. llm_router.py:6 — « Supports 18+ LLM providers ». Le mensonge est né dans ce commentaire et a remonté jusqu'à la Lettre.

Deux observations transversales, sans jugement.

La première : dans plusieurs cas, la Lettre se contredit elle-même dans le même document — elle annonce les 18 Oracles comme acquis, puis les note « 0% 🔴 » quelques milliers de lignes plus loin ; elle titre « 18 experts » au-dessus d'un tableau qui somme à 21. La promesse et l'aveu cohabitent déjà.

La seconde : aucun des écarts relevés ne vient d'un travail absent. Le routeur LLM a ses 5 stratégies, ses budgets, sa bascule ; le Synaptic Switcher a ses 1 660 lignes et son rollback ; les 84 profils ont leurs 14 400 lignes. Ce qui manque presque partout, c'est le dernier raccordement — l'adaptateur, l'import, le montage. Rétrograder les chiffres ne rétrograde pas l'ouvrage.