Le relevé interne du propriétaire

L’état technique
du dépôt

Ce que le système est vraiment — mesuré dans le code, jamais recopié de la documentation. Quinze domaines, 361 pièces, chacune avec son état et la preuve qui l’étaye. (Le guide d’accueil, lui, est Le Livre du Nouveau Propriétaire.)

244 livrées · 81 câblées en attente · 36 déclaratives · 15 réfutées à la contre-épreuve · relevé du 2026-07-19

Avant-propos

Comment lire ce livre

La seule question qui compte, devant n'importe quelle regle de ce systeme : quel fichier retourne false ou leve une exception quand on la viole ?

Si la reponse est « aucun », vous tenez du texte, pas une garde.

Ce livre a ete bati sur cette question. Quinze domaines ont ete releves en ouvrant le code, jamais en lisant la documentation — parce que le depot avertit lui-meme que son manifeste doctrinal derive du code reel. Chaque piece porte donc un etat et une preuve :

LIVRÉ — le code existe *et* quelque chose l'appelle : une route montee, un import reel, un test qui l'exerce.
CÂBLÉ, EN ATTENTE — le code existe, il est correct, mais rien ne l'appelle. Il attend.
DÉCLARATIF — ca n'existe qu'en documentation, en commentaire ou en maquette.

Et les pieces declarees livrees ont ensuite ete reprises par un second lecteur, avec la consigne inverse : les refuter. Quinze n'ont pas tenu. Elles ont leur chapitre, avant les domaines.

Le portrait

Ce que vous possédez

Vous héritez d'une membrane HTTP en bien meilleur état que sa réputation : 357 routers, tous montés, zéro orphelin, 4 428 portes d'entrée, 85 % authentifiées, 1 268 fichiers de test.
Le mécanisme de montage est bien pensé : dix routers vitaux font échouer le démarrage, le reste dégrade sans coucher le serveur, et un témoin nominatif dit qui est mort.
La membrane de mérite (perméable / gestationné / scellé) est bâtie, testée, sans dépendance, et trois consommateurs réels s'en servent avant d'agir.
La cryptographie est vraie là où elle prétend l'être : Ed25519 pour la signature, HMAC-SHA256 avec séparation de domaine et comparaison à temps constant pour l'armure.
L'œuvre publique est complète et se régénère depuis ses sources — aucune page recopiée à la main.
Le squelette est là : une carte fractale de 24 troncs, 2 577 feuilles, servie en API.

Mais : les agents ne travaillent pas — l'exécution retourne une chaîne en dur, Nova excepté.
Les étages ne sont pas une sécurité — un clic suffit pour se hisser au sommet.
Les règles de frontière sont du texte servi en HTTP — aucune ne refuse quoi que ce soit.
Le site public ne publie pas ce dépôt, et 43 pages ne sont reliées à rien.

En une phrase : *une charpente solide, une belle façade, une plomberie honnête — et le moteur n'est pas branché.*

Les gardes

Les sept choses à ne pas casser

1. Les dix routers core=True (main.py:1216-1228). Leur panne refuse le démarrage : c'est une protection, pas un défaut. Ne la retirez pas pour « déboguer plus vite ».
2. Object.freeze dans frontend/js/sacred-constants.js. C'est le Point 0. Tout s'y réfère, et le pouls du Sanctum diffuse une somme de contrôle faite exprès pour détecter qu'on l'a bougé.
3. Les deux gardes de gouvernance des agents (routers/agents.py:684-700 et :774) : refus du chaînage agent→agent, point de contrôle humain obligatoire en L2/L3. C'est le seul endroit du système où un interdit est réellement appliqué.
4. Le gate d'authentification MCP (mcp_server.py:751), fermé par défaut. Sans lui, la lecture du code source est ouverte à tout Internet.
5. Le silence du centre. Le Centre-Réceptacle mesure et ne renvoie jamais d'ordre ; les deux pôles voisins publient des topics nommés au lieu du pouls canonique. Le jour où l'un des trois republie vers les étages, vous avez une boucle et plus de vide central.
6. Les fichiers engendrésindex.html, livre-reference.html, releve-chiffres.html. Éditez la source (landing-unifie.html, content/lettre-aux-humains.md), jamais la copie : elle sera écrasée sans avertissement.
7. Les populations mises au frigo (agents/capability-notes/, cinq notes). Elles sont archivées volontairement et un test vérifie qu'elles y restent. Ne les « réveillez » pas par curiosité.

Par où commencer

Les sept premiers gestes

1. Mesurer avant de toucher. Appeler /internal/registration-status sur le serveur en marche. Si le nombre « ok » est nettement sous 366, des pans entiers sont muets et personne ne l'a vu.
2. Fermer la porte des étages. Faire dériver le niveau autorisé de la session serveur au lieu du clic (env-runtime.js:799, desktop-shell.js:979). Tant que ce trou est ouvert, la hiérarchie est un rangement d'écran. À faire avant toute mise en ligne publique.
3. Rebrancher la publication. Le domaine public est servi par un autre projet, depuis un autre dépôt, figé depuis mars. Soit vous rattachez le domaine au projet qui sert ce dépôt, soit vous déployez ce frontend depuis celui qui porte le domaine. Sans ce geste, aucun des six autres ne se voit.
4. Armer les alarmes. REGISTER_ROUTER_STRICT=1 en intégration continue (jamais en production) : chaque router mort devient un échec bruyant. Aucun code à écrire. Meilleur rapport effort/résultat du dépôt.
5. Brancher l'exécution des agents. Nova sait déjà parler à un modèle réel. Réutiliser ce connecteur là où il y a # TODO: Actual LLM execution. C'est le geste qui transforme un catalogue en système. Tout le reste — quotas, coûts, approbations, traçabilité — est déjà bâti et attend.
6. Réparer ce qui est visible et cassé. Les huit cartes muettes (bibliothèques externes bloquées par la politique de sécurité : les rapatrier en local plutôt qu'ouvrir la politique), puis relier au menu les pages orphelines qui marchent — à commencer par le Livre, que l'onglet portant son nom contourne aujourd'hui.
7. Trancher les orphelins. 52 services que rien n'importe, un arbre fantôme de 2 460 lignes en double, un point d'entrée agents que personne n'appelle, un noyau NEXUS de 1 287 lignes que le catalogue déclare branché à tort. Chacun : brancher ou supprimer. Le pire état est l'état actuel — vert aux tests, absent du produit.

Comment ça se tient

La carte en un coup d’œil

Lecture verticale, du porteur vers le porté. *Si l'étage du bas tombe, tout ce qui est au-dessus tombe.*

``
FAÇADE Pages (148) · Œuvre publique · Livres
↑ dépend de : config.js, governance-init.js, CSP
SURFACES Domaines métier · Décodage (Babel, temples, canon)
Économie & chaîne · Armure 15D
↑ dépend de : routers, services, base
MEMBRANE Routers (357) · Auth & RBAC · Membrane de mérite
Étages L1-L4 · Gate MCP
↑ dépend de : main.py, bus, base
PLOMBERIE Bus d'événements · Topics · Base (Supabase)
Fournisseurs LLM
↑ dépend de : constantes, main.py
CENTRE main.py · Point Zéro · Constantes gelées · Cartographie
``

Les dépendances qui font mal :
- Tout dépend de main.py. Un router non déclaré n'existe pas, quel que soit son code.
- Le peuple dépend entièrement des fournisseurs LLM. Sans eux, 529 fiches et zéro travailleur.
- Les quatre cardinaux dépendent entièrement du bus. Sans bus, ils ne font rien.
- Les étages ne dépendent de rien — c'est précisément le problème : aucune session ne les gouverne.
- Le double pouls vient de deux bus séparés (serveur et navigateur). Ce n'est pas un bogue local, c'est une conséquence d'architecture.
- Le décodage, l'économie et l'armure supposent la base présente. 55 % des routers survivent sans elle ; ces domaines-là, moins.
- La façade dépend de la politique de sécurité du déploiement — c'est elle qui protège le site et elle qui casse huit cartes.

Ce qu’on croit avoir

Les surprises

Ce qu'on croit avoir et qu'on n'a pas

- Douze modules métier « verticals » annoncés. Le dépôt versionné n'en contient aucun. Sur un clone neuf, ils n'existent pas.
- 400+ agents. Il y a 405 à 529 *fiches*, 238 *définitions*, et environ dix classes exécutables — dont quatre réellement appelées. Rapport vitrine/atelier : 40 pour 1.
- Un catalogue d'agents affiché. Il est chargé, mais aucune page ne le lit : le chargeur et le lecteur sont des ensembles disjoints, et une branche de lecture pointe vers un objet global qui n'existe nulle part.
- Une isolation en trois zones. Le fichier qui devait l'imposer se déclare lui-même « échafaudage », liste 3 modules au lieu de ~160, et n'est lancé par aucun script du dépôt.
- Une escalade automatique des alertes critiques. Elle est morte deux fois : l'étage émetteur n'a aucun droit de commande, et la comparaison de casse ne peut pas correspondre. Une alerte sentinelle critique ne remonte à personne.
- Des règles de frontière et de passation. Elles sont lues, transportées, recopiées — jamais appliquées. Zéro sur quatre.
- Une sphère Durabilité peuplée. 45 fiches en vitrine, 0 définition au registre.
- Un site public servi par ce dépôt. Non : par un autre projet, depuis un autre dépôt, dernier déploiement en mars.

Ce qu'on a sans le savoir

- Zéro router orphelin. La documentation en annonce 36 ; il n'y en a plus un seul. La famille « canon », décrite comme abandonnée, est complète et montée.
- 4 428 portes d'entrée web, dont 85 % authentifiées.
- Un témoin de vérité déjà bâti : un endpoint qui livre la liste nominative des routers morts au démarrage.
- Un mode strict déjà codé — il suffit d'une variable d'environnement pour rendre toute panne bruyante.
- Un coupe-circuit de site entier, avec dérogation locale pour vous. Si un jour tout semble mort, regardez cette ligne en premier.
- De la vraie cryptographie, correctement faite, testée, là où on s'attendait à des maquettes.
- 1 268 fichiers de test, dont 705 touchent une route : c'est le filet qui protège tout le reste.
- Un dépôt qui se dénonce lui-même : une page de relevé porte des ancres nommées « gonflé » sur ses propres chiffres. Quelqu'un a déjà commencé le travail d'honnêteté — il suffit de le continuer.

L’épreuve

Ce qui n’a pas tenu à la contre-épreuve

Chaque pièce déclarée livrée a été reprise par un second lecteur, avec une consigne inverse : essayer de la réfuter. Car « livré » exige deux choses — que le code existe, et que quelque chose l’appelle vraiment. Un fichier que personne n’importe n’est pas livré : il attend.

Quinze pièces n’ont pas tenu. Les voici, sans arrangement.

La pièceÉtat réelPourquoi
index.html — la page-mère servie à la racinecâblé, en attenteLe code tient entièrement : frontend/index.html existe, est git-tracké, et python scripts/generer-index.py --check sort 0 (aucune dérive avec landing-unifie.html). Le contenu prétendu est réel — 4 teasers Chapitre I-IV vers presentation-{exposition,fondations,ecritures,programme}.html, 10 cartes domaines, porte vers la-lettre.html et lettre-aux-humains.html — et TOUTES les cibles + les 2 CSS existent sur disque. Le mécanisme d'ombrage décrit dans l'en-tête est exact : frontend/vercel.json:118-142 déclare outputDirectory "." et un rewrite / → /landing-unifie.html, qu'un vrai index.html pré-empte correctement. CE
Les 6 ATOM-Reference-Book*.html — livres investisseur/publicà revoirRÉFUTÉ COMME "LIVRÉ", mais la preuve avancée est elle-même partiellement fausse. VÉRIFIÉ OK : les 6 fichiers existent, sont trackés git, et sont bien purement statiques (grep -c "<script" = 0 pour les six) ; HTML bien formé (DOCTYPE + </html>) ; les images référencées existent réellement sur disque (frontend/images/chenu-infographic.png, logo-atom-new.png, diagram-agent-hub.jpg, env-1.png, minimap-globe.png vérifiées présentes). Tailles réelles 7388-8272 lignes / 511-578 Ko (l'annonce "~560 Ko" masque un écart plus large). RÉFUTATION DE LA PREUVE : l'affirmation "aucun d'eux n'est lié depuis une autre page" est F
livre-reference.html + releve-chiffres.html — le Livre au propre et sa colonne des mesurescâblé, en attenteLa moitié « engendré, pas recopié » TIENT et se vérifie : python scripts/generer-livre-reference.py sort « 246 Ko · 8 parties · 108 sections » et laisse git status --porcelain frontend/livre-reference.html VIDE — reproduction à l'octet près depuis frontend/content/lettre-aux-humains.md ; idem pour generer-releve-chiffres.py → frontend/releve-chiffres.html. Le fond existe (66 blocs class="releve" dans le Livre) et les ancres avancées sont réelles (id="agents-400-plus-350-essaim-gonflé", id="spheres-9-10-16-gonflé", id="routeur-llm-18-fournisseurs-gonflé"). Mais la moitié APPELÉ échoue. Un grep dépôt-large su
Catalogue frontend — 405 fichescâblé, en attenteLa DONNÉE tient, la VITRINE non, et la preuve avancée est fausse sur 2 des 3 pages. CE QUI TIENT : 405 exact (grep -c "agent('" = 405), 9 domaines × 45 exact (clé réelle = 'MonEquipe', pas 'Mon Equipe'). La factory frontend/js/agents-database.js:63-86 émet bien name, level L0-L3, token_cost (10/25/50/100), capabilities. 742 lignes confirmées. Le fichier EST chargé au runtime et atom-universe.js:73 + _discoverSingletons() (l.137) découvre réellement window.ATOMAgentsDB sur agents.html et meshmap.html (les deux sont dans GOVERNANCE_PAGES). PREUVE FAUSSE : livre-reference.html:1464 et releve-chiffres.html:92 ne ch
Route marché (embaucher / renvoyer / exécuter) — backend/app/routers/agents.pylivréLe montage tient : main.py:1226 register_router(core=True), prefix /api/v2/agents cuit dans agents.py:50, les 5 imports résolvent tous (symboles vérifiés un par un), tests/integration/test_agents.py exerce les routes contre le vrai client, et 5 appelants frontend existent (config.js:326, agent-templates-picker.js:128, desktop-shell.js:4273/9588/9736). Fausse piste écartée : agent_execution_router.py annonce /api/v2/agents/stats dans son docstring mais son vrai prefix est /api/v2/agent-execution — pas de collision. CE QUI RÉFUTE L'ANNONCE : (1) « demander une exécution » n'exécute rien — agents.py:800 retourne en
sendCommand — le seul passage d'un étage à l'autre (frontend/js/hierarchy-sync.js:557-587)livréLIVRÉ au sens strict, mais le prétendu ne tient pas. PREUVES DE LIVRAISON : chargé au runtime (governance-init.js:337, tier 2 ; observer.html:16) ; exercé par un vrai test collecté (frontend/vitest.config.js include js/__tests__/**/*.test.js → hierarchy-template-guards.test.js:54-88 : sendCommand('luna','nexus','financial_command') attendu true + _processCommandQueues + 2 publications bus vérifiées) ; un chemin runtime vivant (hierarchy-sync.js:737 nexus→ethos change_frequency, déclenché par nft.multi.resonance réellement publié par multi-nft-orchestrator.js:687). RÉFUTATIONS DU PRÉTENDU : (1) ACCESS_MATRIX ligne
Routeur Armure — le pont JS→PythonlivréLe ROUTEUR tient, le PONT ne tient pas — le prétendu « reçoit du frontend les 15 forces calculées » est faux. CE QUI EST LIVRÉ (vérifié au-delà de la preuve avancée) : backend/app/routers/armure.py, 166 L, 2 routes (POST /api/v2/armure/dimensions, GET /api/v2/armure/snapshot), les deux sous Depends(get_current_user). Monté à backend/app/main.py:1491. J'ai résolu TOUS les imports plutôt que de faire confiance au montage — register_router (main.py:1174) est non-strict et avale les ImportError en silence, donc un import mort serait invisible : app/services/armure_store.py (64 L), armure_sentinel.py (138 L), armure_t
hedera_service.py — le grand service HederadéclaratifLe câblage tient, la capacité non. VRAI : le routeur est monté (main.py:1757 register_router "app.api.routes.hedera_routes"), ~19 endpoints exposés, et 4 fichiers de tests l'exercent réellement — donc PAS "câblé-en-attente". FAUX : la pièce ne touche jamais Hedera. (1) hedera-sdk n'existe dans AUCUN des 4 requirements ni dans backend/Dockerfile (qui n'installe que requirements.txt) ni dans aucun fichier de déploiement → HEDERA_SDK_AVAILABLE=False partout, ligne 168 _simulation_mode = not HEDERA_SDK_AVAILABLE = True en permanence ; aucun flag HEDERA_LIVE_MODE dans ce fichier. (2) La branche live n'a jamais pu
hedera_mainnet_bridge.py — frappe UR COINà revoirCÂBLÉ-EN-ATTENTE, pas LIVRÉ. Le câblage est réel : route montée sans condition (main.py:1757, non-core), 3 services live l'importent (sovereign_bridge_service.py:35 en top-level, fractal_seed_treasury_consumer.py:95 et babel_fractal_treasury_consumer.py:211 en lazy), 15 tests l'exercent dont mint_urcoin de bout en bout sur le chemin de refus. MAIS la frappe elle-même est inatteignable : hiero_sdk_python n'est déclaré dans AUCUN des 4 fichiers de dépendances (requirements.txt, -full, -test, _unified) — dépendance jamais déclarée, pas un pip install oublié. Le TokenMintTransaction (l.218) ne s'est jamais exécuté
hedera_routes.py — l'API blockchaincâblé, en attenteLe câblage tient, la capacité non. VÉRIFIÉ CÔTÉ MONTAGE : main.py:1757 fait bien register_router → app.include_router ; la chaîne d'import résout (app/api/dependencies.py et app/services/auth/sovereignty_dep.py existent) ; le frontend appelle réellement les chemins (frontend/js/hedera-flow.js:96-97,161-164 → /hedera/account/create, /hedera/token/transfer, /hedera/dashboard/economic, /hedera/token/info). Le HMAC admin sur /token/mint est authentique et fail-closed (404 si HEDERA_ADMIN_SECRET absent — variable déclarée NULLE PART dans deploy/.env.example ni .env.template). 14 décorateurs de route, pas 13. RÉFUTATIO
nft_emissioncâblé, en attenteLe câblage est réel (main.py:1955 monte le router sous /api/v2/nft ; 2 tests unitaires exercent le service), mais la PIÈCE ELLE-MÊME ne frappe rien. (1) _try_hedera_mint_nft (nft_emission_service.py:163-190) ne construit jamais de transaction : il écrit une ligne HCS puis renvoie sim_inv_mint_xxx ou, même en live, pending_xxx — alors que hedera_service.py:380 possède une vraie TokenMintTransaction() utilisée par mint_ur. Capacité présente à côté, jamais câblée. (2) Ce pending_xxx n'est réconcilié par personne : le scheduler pending_mint_retry.py (démarré main.py:390) traite des lignes à stripe_payment_id, pas nft
Supabase (PostgreSQL) — côté navigateurcâblé, en attenteLIVRÉ ne se confirme pas tel qu'énoncé. La moitié « lit » tient sur un seul chemin ; la moitié « écrit » ne tient sur aucun. (1) bio-state-persistence.js:347-353 = branche INATTEIGNABLE : gardée par if (typeof atomPost === 'function') { ...; return; } et atomPost est une function declaration top-level globale dans frontend/config.js:256 — le MÊME fichier qui définit SUPABASE_URL, sans IIFE. Il n'existe aucun état où ATOM_CONFIG.SUPABASE_URL est lisible et atomPost absent → le fetch Supabase ne s'exécute jamais. (2) realtime-sync-hub.js:40-41 = orphelin total : zéro balise <script> dans les 122 HTML, absent des
Supabase / PostgreSQL — côté serveurà revoirDÉCLARATIF pour la partie Supabase, LIVRÉ seulement pour la partie SQL générique — et l'affirmation « la même base » n'est pas prouvable. CE QUI TIENT (à ne pas sous-lire) : la connexion SQL directe tourne vraiment. backend/app/main.py:278-279 appelle init_db() au démarrage ; backend/app/core/database.py construit un vrai moteur asyncpg (create_async_engine, AsyncAdaptedQueuePool, test SELECT 1) ; get_db/get_db_optional = 1969 occurrences dans 198 fichiers de backend/app/routers/ ; tests présents. Le mécanisme SQLAlchemy async est monté, importé et exercé. CE QUI RÉFUTE — 3 trous : (1) L'ENDROIT CITÉ EST INERTE.
Stripe — paiements, côté serveurcâblé, en attenteLe câblage tient, l'annonce non. CE QUI TIENT : le router est bien monté (backend/app/main.py:1344), et ce n'est PAS un router mort silencieux — toutes ses dépendances résolvent (app/models/stripe_bridge.py, app/services/sovereign_bridge_service.py, app/services/pending_mint_retry.py, les 3 constantes STRIPE_* dans app/core/bus_topics.py:835-837, et les colonnes stripe_customer_id/stripe_subscription_id/subscription_tier/subscription_expires_at/is_admin dans app/models/user.py). Des tests l'exercent vraiment (backend/tests/routers/test_sensitive_router_auth_contracts.py:79 monte payments.router dans un TestClient
Stripe — côté navigateur (clé publiable LIVE)à revoirRÉFUTÉ — CÂBLÉ-EN-ATTENTE, pas LIVRÉ. Le chargement est réel : frontend/funder.html:27 charge /js/stripe-client.js en <head>, le module s'auto-initialise (stripe-client.js:766-772), exporte window.STRIPE_CONFIG avec la clé pk_live_ (ligne 28), et les 5 cartes de palier (funder.html:1325-1361) appellent selectTier() qui fait stripe.redirectToCheckout() (lignes 1993-2001) avec les 5 stripePriceId renseignés. MAIS la caisse ne peut pas s'ouvrir en production : frontend/vercel.json:33-34 impose sur source "/(.*)" — donc funder.html inclus — la CSP « script-src 'self' 'unsafe-inline' 'unsafe-eval' », sans https://js.s
Domaine 1 · état : solide

Les modules opérationnels — routers HTTP et couche services du backend

C'est la partie du système qui répond quand quelqu'un frappe à la porte : 357 fichiers « routers » qui exposent environ 4 428 portes d'entrée web (les endpoints), et 720 fichiers « services » qui contiennent le travail réel derrière ces portes. Tout est monté par un seul fichier chef d'orchestre, backend/app/main.py, qui décide au démarrage quels modules s'allument.

23 livrées · 1 en attente · 1 déclaratives

L’inventaire

La pièceÉtatOù elle vitCe qu’elle fait
main.py — le tableau de montageH1_spine · S0livrébackend/app/main.py (2246 lignes)Le seul fichier qui décide quels modules s'allument au démarrage ; tout passe par lui.367 lignes register_router( mesurées ; 366 cibles de module distinctes (355 sous app.routers.*, 11 sous app.api.*)
register_router() — le monteur tolérantH1_spine · S0livrébackend/app/main.py:1174-1200Monte un router ; si l'import échoue, il note l'erreur et continue au lieu de faire planter le serveur.Fonction lue intégralement : try/except ImportError, alimente les listes _registered_ok et _registered_broken ; mode strict activable par la variable REGISTER_ROUTER_STRICT=1
Les 357 routers sur disque, 357 montésH2_membrane · S0livrébackend/app/routers/ (343 à la racine + 4 sous-dossiers : babel, stone_decoder, agents_browser, _archive)La totalité des routers présents est effectivement déclarée au montage — aucun orphelin.Diff programmatique disque↔main.py : 355 montés directement, 0 fantôme, 2 restants (education.py, education_lms_router.py) montés indirectement via backend/app/routers/education_router.py:26 et :34
Les 10 routers CORE (core=True)H1_spine · S0livrébackend/app/main.py:1216-1228health, monitoring, threads, checkpoints, nova, bureau_relay, inter_village_router, agents, notifications, spheres — si l'un casse, le serveur refuse de démarrer.10 occurrences de core=True mesurées ; main.py:1184 lève RuntimeError si un core échoue
/internal/registration-status — le témoin de véritéH2_membrane · S0livrébackend/app/main.py:2080-2100Endpoint qui dit exactement quels routers ont réussi ou échoué au démarrage. C'est le seul moyen de savoir la vérité runtime.Fonction lue ; retourne total/ok/broken_count/broken ; protégée par require_internal_token (en-tête X-Internal-Token)
Bloc alphabétique de masse — ~100 routers métierH6_domain_vertical · S2livrébackend/app/main.py:1899-2025Le gros du système d'affaires : crm, compta, marketing, communication_center, creation_hub, exchange_center, economy_engine, defense_center, energy_center, etc.100 appels register_router comptés dans la plage de lignes ; l'en-tête « FRACTAL-CODE-INDEX » ne décrit pas le contenu réel du bloc
Sprints gouvernance TERRE→UNITÉ — 29 routersH6_domain_vertical · S3livrébackend/app/main.py:1261-1375geo, resources, governance, constitution, voice, replay, provenance, cooperation, justice, transit, formation, integration — la couche institutionnelle.29 appels register_router comptés dans la plage
RBAC et contrôle d'accès — 39 routersH2_membrane · S3livrébackend/app/main.py:1375-1548Rôles, permissions, accès aux zones 3D. Le plus gros bloc après le bloc alphabétique.39 appels register_router comptés dans la plage
Stone decoder et temples — 29 routersH6_domain_vertical · S9livrébackend/app/main.py:1610-1704 ; backend/app/services/stone_decoder/ (22 fichiers)Décodage des sites/temples et orchestration de sources externes.29 appels register_router comptés ; 22 fichiers .py mesurés dans services/stone_decoder/
Environnement malléable, modules L1-L4 — 23 routersH4_mapping_projection · S0livrébackend/app/main.py:1798-1832Le système de widgets et les quatre niveaux d'architecture (Ethos, Agora, Nexus, Luna).23 appels register_router comptés dans la plage
Famille Babel — 11 routers + 64 servicesH5_specialized_backstage · S7livrébackend/app/routers/babel/ ; backend/app/services/babel/ (64 fichiers .py)Le décodeur de langage : mesure de fréquence des mots, dissonance, ponts inter-villages et trésorerie.11 cibles register_router app.routers.babel* listées ; dont inter_village_router en core=True (main.py:1225) ; 64 fichiers services mesurés
Famille Canon — 13 routers, tous montésH0_origin · S9livrébackend/app/main.py (13 cibles `app.routers.canon*`)Cohérence doctrinale : compartiment, historien, accès, hiérarchie mémoire, sync, métadonnées, pont quantique, divergence, mapping.13 cibles distinctes listées et vérifiées montées — contredit CLAUDE.md qui annonce « une famille canon_*_router ×10 » orpheline
ACMI — agents canon-aware, 15 routersH5_specialized_backstage · S8livrébackend/app/main.py:1548-1610L'agent à mémoire infinie et ses capacités synaptiques.15 appels register_router comptés dans la plage
Les 3 plus gros routers du systèmeH6_domain_vertical · S8livrébackend/app/routers/qg_fractalization_router.py (185 endpoints), governed_collaboration_router.py (161), qr_sentinel_router.py (123)À eux trois : 469 endpoints, soit environ 11 % de toute la surface web.Comptage des décorateurs @router.<verbe> fichier par fichier ; les trois sont montés
Le motif « DB d'abord, sinon mémoire » — 198 routersH2_membrane · S0livré198 fichiers de backend/app/routers/ importent get_db_optionalPlus de la moitié des routers continuent de répondre même si la base de données est absente.grep -rl get_db_optional sur routers/ = 198 fichiers
Authentification — 301 routers sur 357H2_membrane · S3livrébackend/app/routers/ (301 fichiers référencent get_current_user ou require_internal_token)85 % des routers portent une dépendance d'authentification.grep -rl 'get_current_user\|require_internal_token' = 301 fichiers
Les 13 routers agrégateursH2_membrane · S0livré13 fichiers de backend/app/routers/ appellent router.include_router(...)Des routers qui en montent d'autres — c'est par là que education.py et education_lms_router.py sont vivants sans être nommés dans main.py.grep -rl 'router.include_router' sur routers/ = 13 fichiers ; cas vérifié ligne par ligne dans education_router.py:33-34
La couche services — 720 fichiersH5_specialized_backstage · S0livrébackend/app/services/ (406 fichiers à la racine + sous-paquets)Le travail réel derrière les portes. Les plus gros paquets : babel 64, qg_fractalization 24, stone_decoder 22, bioacoustic 15, royalty_team 12, embeddings 12.find services -name '*.py' hors __init__ = 720 ; 661 référencés par un import réel quelque part dans backend/
300 services appelés directement par les routersH5_specialized_backstage · S0livrébackend/app/routers/ → 300 modules distincts sous app.services.*C'est la vraie surface de travail branchée sur le web. Les 420 autres services servent d'autres services.grep des from app.services.X import sur routers/, dédoublonné = 300 modules distincts
52 services que rien n'importeH5_specialized_backstage · S0câblé, en attentebackend/app/services/ — dont sphere_service.py, vector_db.py, embedding_service.py, websocket_handler.py, gematria.py, page_rank.py, forum.py, social_feed.py, preferences.py, zama_service.py, xr_renderer_service.py, automation_engine.pyDu code qui existe et paraît correct, mais qu'aucune ligne du dépôt n'appelle.Analyse de toutes les instructions d'import de backend/ (1973 cibles distinctes), après avoir tenu compte des ré-exports via __init__.py : 52 modules sans aucun import
master_hash_registry / flame_registry — catalogue, pas moteurH0_origin · S0livrébackend/app/core/master_hash_registry.py ; backend/app/core/flame_registry.pyDeux catalogues qui nomment des modules par du texte. Ils ne les importent jamais — ils donnent seulement des étiquettes au bus d'événements.Aucun importlib/import_module/__import__ dans les deux fichiers ; consommés uniquement par bus_acl.py:102 et event_bus.py:306,340,413 via get_descriptor. Un service peut y figurer et rester mort : c'est le cas de sphere_service et vector_db.
backend/verticals/ — vide dans le dépôtH6_domain_vertical · S2déclaratifbackend/verticals/ (README.md + _archived/ seulement)Les 12 dossiers « V68 actifs » annoncés par la documentation ne sont pas dans le dépôt.ls backend/verticals/ = README.md, _archived ; git ls-files verticals/ = 5 fichiers, tous sous _archived/PROJECT_MGMT_V68. Sur un clone neuf, il n'y a aucun vertical actif.
3 routers sans endpoint sur le router principalH2_membrane · S0livrébackend/app/routers/comms_router.py, trading.py, workflow_runtime_router.pyIls utilisent d'autres variables (protected_router, hybrid_router) — ce n'est pas un défaut, mais ça trompe les comptages naïfs.@router.* = 0 dans ces 3 fichiers ; mais 137 @protected_router.*, 4 @hybrid_router.*, 8 @_private_router.*, 4 @internal_router.* mesurés dans routers/
La couverture de testsH3_vital_loop · S0livrébackend/tests/ — 1268 fichiers test_*.py705 de ces fichiers touchent un router ou un chemin d'API. C'est la meilleure preuve indirecte que les modules se chargent vraiment.find tests -name 'test_*.py' = 1268 ; grep -rl 'app.routers|/api/v2|/api/v1' = 705
La surface legacy /api/v1H7_frontstage_external · S0livrébackend/app/api/v1/routes/ — 11 cibles montées, dont auth_routes, agent_routes, nova_routes, performance_routes (main.py:1203-1206)L'ancienne génération d'API, encore montée. À traiter comme compatibilité, pas comme tronc.11 appels register_router("app.api.*") mesurés, tous en core=False (donc leur panne serait silencieuse)

Les chiffres, mesurés

Ce qu’on compteLa mesureComment
Fichiers routers présents (hors __init__ et _archive)357annoncé ailleurs : CLAUDE.md annonce « 355 router files »find backend/app/routers -name '*.py' ! -name '__init__.py', moins les 4 fichiers de _archive/
Routers réellement déclarés au montage357 sur 357 (100 %)annoncé ailleurs : CLAUDE.md annonce « 259 montés sur 295, 36 orphelins » — chiffre périmé, il n'y a plus d'orphelinDiff programmatique : 355 cibles app.routers.* dans main.py + 2 montées indirectement via education_router.py:33-34
Routers CORE (panne = serveur refuse de démarrer)10grep -c 'core=True' backend/app/main.py
Routers optionnels (panne = silencieuse au démarrage)356366 cibles register_router mesurées, moins les 10 core=True
Endpoints web exposés4 428Décorateurs @<router>.<get|post|put|patch|delete|websocket> sur backend/app/routers/ hors _archive. Répartition : 2718 GET, 1424 POST, 89 PUT, 73 DELETE, 13 PATCH, 1 WebSocket
Fichiers services présents720 (dont 406 à la racine de services/)annoncé ailleurs : CLAUDE.md annonce « 631 service files »find backend/app/services -name '*.py' ! -name '__init__.py'
Services référencés par au moins un import réel661 sur 720 (92 %)Extraction des 1973 cibles d'import distinctes de backend/, intersection avec la liste des fichiers services
Services que rien n'importe (orphelins vrais)52Les 59 non trouvés, moins 7 qui sont ré-exportés par le __init__.py de leur paquet (vérifié fichier par fichier)
Services appelés directement par un router300 modules distinctsgrep des 'from app.services.<X> import' sur backend/app/routers/, dédoublonné
Routers tolérants à l'absence de base de données198 sur 357 (55 %)grep -rl get_db_optional backend/app/routers/
Routers portant une authentification301 sur 357 (85 %)grep -rl 'get_current_user\|require_internal_token' backend/app/routers/
Verticals métier actifs dans le dépôt0annoncé ailleurs : CLAUDE.md annonce « 12 V68 dirs actifs » — ils n'existent pas dans le dépôt versionnéls backend/verticals/ = README.md + _archived ; git ls-files verticals/ = 5 fichiers, tous archivés
Fichiers de test backend1268, dont 705 touchant un router ou un chemin d'APIfind backend/tests -name 'test_*.py' ; puis grep -rl 'app.routers|/api/v2|/api/v1'
Routers agrégateurs (qui en montent d'autres)13grep -rl 'router.include_router' backend/app/routers/

Ce sur quoi vous pouvez compter

La membrane HTTP est en bien meilleur état que ce que la documentation laisse croire. Les 357 routers présents sur disque sont tous déclarés au montage — il n'y a plus un seul orphelin, alors que CLAUDE.md en annonce encore 36. La famille canon, décrite comme dix routers abandonnés, est aujourd'hui complète et montée à treize.

Le mécanisme de montage est bien pensé. register_router() (main.py:1174) sépare franchement deux régimes : dix routers CORE dont la panne fait refuser le démarrage — donc jamais de dégradation invisible sur le cœur — et le reste en optionnel, qui échoue en écrivant une erreur sans coucher le serveur. Un commentaire dans le fichier raconte pourquoi : une panne d'import était autrefois journalisée en simple avertissement, invisible en production pendant plus de vingt-quatre heures. C'est corrigé, et un mode strict (REGISTER_ROUTER_STRICT=1) permet d'échouer franchement en développement.

L'instrumentation existe et elle est honnête : /internal/registration-status (main.py:2080) livre la liste nominative des routers cassés au démarrage, protégée par un jeton interne.

Les habitudes de code sont régulières : 198 routers sur 357 continuent de répondre sans base de données, 301 sur 357 portent une authentification, et 1268 fichiers de test dont 705 touchent une route — c'est la meilleure preuve indirecte que ces modules se chargent vraiment.

Ce qui manque

Du plus bloquant au moins.

1. « Monté » veut dire « déclaré », pas « vivant ». Je n'ai pas pu le prouver : fastapi et sqlalchemy ne sont pas installés sur cette machine, donc aucun import n'a pu être testé. Comme register_router avale les erreurs d'import des 356 routers optionnels, un router peut être déclaré dans main.py et n'exposer aucune porte en production sans que rien ne le crie. Mon 357 sur 357 est un compte de déclarations. La vérité runtime n'est lisible que sur le serveur, via /internal/registration-status.

2. 52 services que rien n'appelle. Du code entier, d'apparence correcte, qu'aucune ligne du dépôt n'importe : sphere_service, vector_db, embedding_service, websocket_handler, gematria, page_rank, forum, social_feed, zama_service, xr_renderer_service, automation_engine et 41 autres. Le piège : plusieurs figurent dans master_hash_registry.py, ce qui donne l'illusion d'être branchés. Ce fichier ne contient aucun import dynamique — il ne fait que distribuer des étiquettes au bus d'événements. Y être inscrit ne réveille rien.

3. backend/verticals/ est vide. La documentation annonce douze verticals V68 actifs. Le dépôt versionné n'en contient aucun : seulement un README et un dossier _archived (5 fichiers suivis par git). Sur un clone neuf, ces douze modules métier n'existent pas. Les quatorze routers « verticals » de main.py:1832-1853 pointent, eux, vers backend/app/routers/ — ils ne dépendent pas de ce dossier.

4. Trois concentrations lourdes. qg_fractalization_router (185 endpoints), governed_collaboration_router (161) et qr_sentinel_router (123) portent à eux seuls 469 endpoints, soit 11 % de la surface. Aucun n'est CORE : si l'un casse à l'import, 185 portes disparaissent en silence.

5. Un bloc mal étiqueté. Les 100 routers de main.py:1899-2025 sont sous l'en-tête « FRACTAL-CODE-INDEX REST query API ». Le contenu réel est tout autre chose : crm, compta, marketing, creation_hub, energy_center. Un lecteur qui se fie aux commentaires se trompe de carte.

6. La surface legacy /api/v1 (11 routers) est montée en optionnel. Elle peut mourir sans bruit.

Se tient avec : Base de données et persistance — 198 routers sur 357 dépendent de get_db_optional et changent de comportement selon que la base répond ou non · Authentification et RBAC — 301 routers portent get_current_user ou require_internal_token ; le bloc RBAC de main.py:1375-1548 (39 routers) gouverne l'accès de tous les autres · Bus d'événements et catalogues de topics — event_bus.py et bus_acl.py consultent master_hash_registry pour valider la provenance des messages ; c'est ce qui donne aux services orphelins une fausse apparence de branchement · Agents et ACMI — 15 routers en main.py:1548-1610, et 12 cibles de montage portant 'agent' dans leur nom · Babel et le décodage — 11 routers plus 64 fichiers services, dont un router en CORE (inter_village_router) · Canon et cohérence doctrinale — 13 routers canon montés, plus l'outil de détection de divergence code/documentation (canon_divergence_router) · Frontend — les 4 428 endpoints sont la surface que consomment les pages de frontend/ via atomFetch et atomPost · Tests — 705 des 1268 fichiers de test touchent un router ; c'est le filet qui protège ce domaine

Domaine 2 · état : partiel

Les pages du frontend — frontend/*.html : ce que chaque page est, et ce qu'elle fait vraiment

C'est la partie visible d'AT·OM : 148 fichiers HTML qui vont de l'affiche publique (l'œuvre, les lettres, les livres) jusqu'aux tableaux de bord qui parlent au serveur. Chaque page est autonome — elle charge elle-même sa liste de scripts, il n'y a pas de framework qui assemble le tout.

21 livrées · 2 en attente · 1 déclaratives

L’inventaire

La pièceÉtatOù elle vitCe qu’elle fait
index.html — la page-mère servie à la racineH7_frontstage_external · S0livréfrontend/index.html:1-434 ; généré par scripts/generer-index.py:24La porte d'entrée : hero, 4 chapitres en teasers, 9 domaines, porte vers la Lettre.C'est une copie générée de landing-unifie.html. Le commentaire en tête du fichier explique pourquoi (frontend/index.html:1-6) : Vercel sert un fichier statique AVANT d'appliquer une réécriture, donc « / » exige un vrai index.html. Le fichier de travail reste landing-unifie.html.
landing-unifie.html — le fichier de travail de la page-mèreH7_frontstage_external · S0livréfrontend/landing-unifie.html (428L, 6 scripts)La vraie source à éditer ; elle relie 21 pages de l'œuvre (les Lettres, les Écritures, les présentations, les cosmogrammes).21 liens .html distincts mesurés dans le fichier ; c'est la cible de scripts/generer-index.py:24 (SOURCE).
Les 6 ATOM-Reference-Book*.html — les livres investisseur/publicH7_frontstage_external · S0livréfrontend/ATOM-Reference-Book*.html — 6 fichiers, 8272L pour le plus grosSix variantes du Livre de Référence (base, Investor, Investor-DE, Investor-ESO, Public, Public-ESO) — 7 400 à 8 300 lignes chacune, ~560 Ko.Zéro balise <script> dans les six : ce sont des documents purement statiques (les 19 src= par fichier sont des images/ , ex. images/chenu-infographic.png). Ils fonctionnent tels quels — mais aucun d'eux n'est lié depuis une autre page (5 des 6 sont dans la liste des 43 orphelines).
livre-reference.html + releve-chiffres.html — le Livre au propre et sa colonne des mesuresH7_frontstage_external · S0livréfrontend/livre-reference.html (3454L) ; frontend/releve-chiffres.html (380L)Le Livre engendré depuis la source markdown, et le relevé qui met la mesure réelle à côté de chaque chiffre annoncé.Engendrés, pas recopiés : scripts/generer-livre-reference.py:3 et :17 (SOURCE = frontend/content/lettre-aux-humains.md, SORTIE = frontend/livre-reference.html) ; scripts/generer-releve-chiffres.py. Le relevé porte des ancres explicites comme id="agents-400-plus-350-essaim-gonflé" et id="spheres-9-10-16-gonflé" — c'est le dépôt qui documente lui-même sa propre dérive.
la-lettre.html + lettre-aux-humains.html + lettre-tissee.htmlH7_frontstage_external · S0livréfrontend/la-lettre.html (1121L, 269 Ko) ; lettre-aux-humains.html (150L) ; lettre-tissee.html (159L)Les Lettres — le registre intime de l'œuvre.la-lettre.html charge 6 scripts et renvoie vers landing-unifie.html + onboarding.html (les 2 seuls liens sortants). Contenu statique, décor animé — rien à câbler, rien de cassé.
Les 7 presentation-*.html — les chapitres de l'expositionH7_frontstage_external · S0livréfrontend/presentation-{exposition,fondations,ecritures,programme,economie,juin,obtenez}.html — 142L à 1136LExposition, Fondations, Écritures, Programme, Économie, Juin, Obtenez.Tous liés depuis landing-unifie.html (mesuré dans la liste des 21 href). 6 scripts chacun, essentiellement du décor (veil-vivante, decor-incunable).
Les 10 pages de sphère — personal, entreprise, institutions, creation, communaute, communication, formation, logistique, durabilite, cuisineH6_domain_vertical · S1-S9livréfrontend/{personal,entreprise,institutions,...}.html ; carte des modules dans frontend/js/governance-init.js:71-119 (SPHERE_MODULE_MAP)Le cœur métier : chaque sphère a sa page et ses modules dédiés.Les 10 pages sont listées dans GOVERNANCE_PAGES (governance-init.js:53-56) donc elles reçoivent la pile complète. Les 10 modules de sphère existent tous sur disque (vérifié un par un : 311L à 1617L). Elles appellent le serveur : institutions 17 appels, communication 13, personal 9, durabilite 8, communaute 8, logistique 7, entreprise 7, formation 3. institutions.html est la plus lourde (3241L) et charge à elle seule 33 modules dont 7 orphelins S3 recâblés le 2026-07-01 (commentaire governance-init.js:88).
desktop.html — le bureauH4_mapping_projection · S8livréfrontend/desktop.html (1688L, 88 <script>)Le poste de travail : 88 balises script, 80 fichiers chargés, la page la plus câblée du dépôt.Listée dans GOVERNANCE_PAGES (governance-init.js:56) et possède ses 13 modules propres (governance-init.js:110-116 : bureau-widgets, environment-browser, env-renderer-village, nexus-commander, vps-console…). C'est le seul endroit qui relie 20 autres pages (agents, budget, les 9 sphères, dashboard, governance, meshmap, settings, transit…) — c'est votre vrai menu.
admin.html — l'administrationH5_specialized_backstage · S3livréfrontend/admin.html (2995L ; 1645 lignes de JS inline ; 14 appels serveur)197 Ko, 2995 lignes, 1645 lignes de JavaScript écrites directement dans la page.14 appels atomFetch/atomPost mesurés. Mais : seulement 3 scripts externes chargés, tout le reste est inline — donc non réutilisable et non testable. Et la page n'est liée depuis nulle part (elle figure dans les 43 orphelines) : on n'y accède qu'en tapant l'adresse.
dashboard.html + settings.html + governance.html + compliance.htmlH5_specialized_backstage · S3livréfrontend/dashboard.html (1577L, 9 scripts) ; settings.html (456L) ; governance.html (478L) ; compliance.html (872L)Le poste de pilotage courant.dashboard est dans GOVERNANCE_PAGES (governance-init.js:53) et reçoit 2 modules propres (governance-init.js:121-124 : dashboard-master-bridge, dashboard-cascade-readout). compliance reçoit compliance-module.js (governance-init.js:141). Toutes appellent le serveur (dashboard 1, settings 3, governance 2).
auth.html + auth-callback.html + inscription.html + onboarding.html + checkout.htmlH2_membrane · S1livréfrontend/auth.html (836L) ; auth-callback.html (196L, 141 lignes inline, 0 script externe) ; inscription.html (759L) ; onboarding.html (1028L) ; checkout.html (385L)La porte d'entrée des membres : connexion, retour d'authentification, inscription, accueil, paiement.config.js:474 et :565 portent les vrais appels (/api/v1/auth/logout, /api/v1/auth/refresh). onboarding est dans GOVERNANCE_PAGES (governance-init.js:56) et ne mène qu'à 3 endroits : /agents.html, /auth.html, /dashboard.html. auth-callback.html est 100% inline et orpheline de lien — normal pour un callback, mais rien ne le documente dans la page.
Les 4 centres Tier-2 minimaux — dev-center, education-center, government-center, labor-centerH6_domain_vertical · S3livréfrontend/dev-center.html:1-65 (et les 3 jumelles) ; moteur partagé frontend/js/center-summary-page.js (221L)Quatre pages de 64-65 lignes qui affichent Résumé / Départements / Spécialisations / Processus / Statistiques.Le serveur répond : register_router pour dev_center_router (backend/app/main.py:1916), education_center_router (:1923), government_center_router (:1934), labor_center_router (:1947). Les 4 pages sont dans GOVERNANCE_PAGES (governance-init.js:64). Elles marchent — mais les 4 affichent « Loading… » en dur et les 4 sont orphelines de navigation : aucun lien nulle part ne mène à elles.
mission-center.html — l'agrégateur des 8 flux d'opportunitésH6_domain_vertical · S5livréfrontend/mission-center.html:1-58 (8 scripts pour 58 lignes) ; backend/app/main.py:1698-1699Tâches / Projets / Emplois / Cours / Événements / Commissions / Experts / Investir, avec bascule de proximité LOCAL/NEARBY/GLOBAL.Le router est monté avec un commentaire explicite (main.py:1698 : « prefix="" because mission_center.py has prefix="/api/v2/mission-center" baked in »). La page est dans GOVERNANCE_PAGES (governance-init.js:62) et reçoit mission-workspace.js (governance-init.js:124-126). Ses 8 sections <section id="mc-tab-*"> sont vides dans le HTML : tout est rempli par mission-center-tabs.js + mission-center.js. Orpheline de navigation elle aussi.
Les 14 autres *-center.html — health, legal, transport, exchange, energy, defense, science, disaster, agriculture, design, communication, creation-hub, comms-hub, support-deskH6_domain_vertical · S3livréfrontend/{health,legal,transport,exchange,energy,defense,science,disaster,agriculture,design}-center.html + communication-center.html + creation-hub.htmlLes centres sectoriels étoffés (735L à 2750L chacun).Attention, deux régimes distincts mesurés. Côté serveur monté : health_center_router (main.py:1936), legal_center_router (:1948), transport_center_router (:2008), exchange_center_router (:1928). Côté serveur ABSENT : energy-center, defense-center, science-center, disaster-center, agriculture-center, design-center → 0 fichier correspondant dans backend/app/routers/ (grep -rl, résultat 0). Ces 6-là ont donc une page riche (735L à 1331L) mais aucune route dédiée derrière.
business.html + construction.html + operations.html + crm.html + compta.html + logistique.html — les outils d'entrepriseH6_domain_vertical · S2livréfrontend/business.html (1066L, 28 appels serveur) ; construction.html (1001L, 21) ; operations.html (395L, 14) ; crm.html (890L) ; compta.html (1300L)Les pages qui travaillent vraiment : ce sont elles qui parlent le plus au serveur.business.html détient le record mesuré du dépôt : 28 occurrences atomFetch/atomPost/fetch(api/. construction.html en a 21, operations.html 14. Ce sont les pages les plus « branchées » du frontend. Toutes accessibles par lien.
agents.html + nexus.html + conseil.html + threads.html — la couche agentsH3_vital_loop · S8livréfrontend/agents.html (1870L) ; nexus.html (2173L, 8 scripts, 4 appels serveur) ; conseil.html (271L) ; threads.html (580L)L'annuaire des agents, le poste de commande, le conseil, les fils de discussion.agents.html est dans GOVERNANCE_PAGES (governance-init.js:53) et reçoit 3 modules (governance-init.js:117 : agents-database.js, agent-workspace.js, agent-character-manager.js). Rappel de mesure : agents-database.js contient des fiches de référence, PAS des agents exécutables — le relevé des chiffres du dépôt le dit lui-même.
Les 8 pages à script externe — cooperation, cosmogramme-3d, donut, flows, geo-hub, mirror-earth, resources, temple-decoderH4_mapping_projection · S9câblé, en attentefrontend/mirror-earth.html (script src="https://unpkg.com/leaflet@1.9.4/…") ; cosmogramme-3d.html (cesium.com) ; donut/flows/cooperation.html (d3js.org) ; geo-hub.html (unpkg maplibre)Cartes et graphiques : d3.js, Leaflet, MapLibre, CesiumJS.Le code de page est correct, mais frontend/vercel.json impose Content-Security-Policy avec script-src 'self' 'unsafe-inline' 'unsafe-eval' — aucun hôte externe autorisé. En production le navigateur refuse de charger d3, Leaflet, MapLibre et Cesium : ces 8 cartes s'affichent vides. mirror-earth reçoit pourtant 3 modules dédiés (governance-init.js:149-153 : temple-tuning-motor-bridge, temple-flow-bridge, mirror-earth).
babel-measure.html + babel-reception.html + babel-matrix27-dashboard.html + babel-fractal-test.htmlH5_specialized_backstage · S0livréfrontend/babel-measure.html (373L) ; babel-reception.html (146L, 1 seul script : js/babel-reception.js) ; babel-matrix27-dashboard.html (329L, 0 script externe, 112 lignes inline) ; babel-fractal-test.html (482L, 14 scripts)Le Décodeur de Babel côté écran : mesurer un mot, recevoir les dissonances, tableau matrice 27, banc d'essai fractal.CLAUDE.md documente 9 endpoints REST Babel sur 3 routers et 36 topics de bus. Mais les 4 pages sont orphelines de navigation (aucun lien nulle part). babel-matrix27-dashboard n'a aucun script externe — tout tient dans 112 lignes inline.
meshmap.html + spheres.html + world.html + monde-interieur.html + le-grand-cosmogramme.html — les cartes du systèmeH4_mapping_projection · S9livréfrontend/meshmap.html (803L, 13 scripts) ; spheres.html (1311L) ; world.html (455L) ; monde-interieur.html (422L) ; le-grand-cosmogramme.html (426L)La représentation du maillage, des sphères et du monde.meshmap est dans GOVERNANCE_PAGES (governance-init.js:57) et lié depuis desktop.html. spheres.html : 1 appel serveur mesuré. Toutes accessibles.
_harness-reconnexion.html + forge-generator-pool-test.html + simulation-dashboard.html + coverage.html + observer.htmlH1_spine · S0câblé, en attentefrontend/_harness-reconnexion.html (121L, 28 <script>) ; simulation-dashboard.html (241L, 23 <script>) ; coverage.html (333L, un seul <div id="coverageDashboardRoot">) ; observer.html (31L, 7 scripts dont 3 sous js/observer/)Les bancs d'essai internes : harnais de reconnexion (28 scripts pour 121 lignes), test du pool de générateurs, tableau de simulation, couverture, observatoire.Les 5 sont orphelines de navigation. coverage.html reçoit coverage-dashboard.js (governance-init.js:127-129) et n'a qu'un seul conteneur vide — la page ne vaut que ce que le module y injecte. Le préfixe « _ » de _harness-reconnexion signale clairement l'outil de développement, pas une page de produit.
404.html + 500.html + offline.html + maintenance.html + widget-sentinel.htmlH2_membrane · S0livréfrontend/404.html (96L, 0 script) ; 500.html (96L, 0 script) ; offline.html (114L) ; maintenance.html (68L) ; widget-sentinel.html (78L)Les pages de secours.maintenance.html a un interrupteur réel : governance-init.js:33 déclare const SITE_MAINTENANCE = false avec le commentaire « SITE LIVE — activated March 2026 ». Si vous le passez à true, governance-init.js:39-45 redirige TOUTES les pages vers /maintenance.html, sauf si localStorage porte atom_maintenance_bypass=true. C'est votre coupe-circuit — sachez qu'il existe.
conditions.html + confidentialite.html + mentions-legales.html + help.htmlH7_frontstage_external · S3livréfrontend/conditions.html (152L) ; confidentialite.html (202L) ; mentions-legales.html (131L) ; help.html (229L)Le juridique et l'aide.Les trois pages juridiques n'ont aucun JavaScript (0 script, 0 inline) — c'est correct et voulu pour du texte de loi. Elles sont liées depuis les pieds de page.
editor.html + planches-atelier.html + toute-loeuvre.html + studio.html — l'atelierH5_specialized_backstage · S4livréfrontend/editor.html (1797L dont 1251 lignes de JS inline, 3 <script>) ; planches-atelier.html (174L, 13 src) ; toute-loeuvre.html (501L) ; studio.html (2849L)L'éditeur de mise en page, l'atelier des planches, la vue « toute l'œuvre d'un seul regard », le studio.editor.html est le cas extrême du problème inline : 1251 lignes de JavaScript écrites dans la page, seulement 3 balises script, et la page n'est liée de nulle part. toute-loeuvre.html ne contient aucun lien .html sortant (mesuré : liste vide) — elle affiche les pages en cadres iframe.
La racine du dépôt — pas de index.html, et une redirection qui part ailleursH2_membrane · S0déclaratifATOM-CLEAN/vercel.json:1-9 (racine) vs frontend/vercel.jsonCe qui décide où va le trafic.Le vercel.json de la RACINE se nomme "atom-legacy-redirect" et renvoie tout en 308 vers https://atom-arche.vercel.app/$1. Il n'existe aucun index.html à la racine du dépôt (ls: No such file). Donc : les 148 pages ne sont publiées que si c'est le dossier frontend/ qui est déployé (frontend/vercel.json, name "at-om-arche", outputDirectory "."). La racine, elle, ne fait que rediriger.

Les chiffres, mesurés

Ce qu’on compteLa mesureComment
Pages HTML dans frontend/148annoncé ailleurs : La consigne de départ annonçait « ~144 pages » ; CLAUDE.md annonce « 122 pages HTML ». Les deux sous-comptent : le vrai chiffre est 148.ls frontend/*.html | wc -l
Fichiers .js dans frontend/js/1658annoncé ailleurs : CLAUDE.md annonce « ~1350 fichiers JS mesurés localement » pour tout frontend/. Le seul sous-dossier js/ en contient déjà 1658.find frontend/js -name '*.js' | wc -l
Références <script src> distinctes vers un .js237grep -ho 'src="[^"]*\.js' frontend/*.html | tri unique
Références de script cassées (fichier absent)0boucle test -f sur chacune des 237 références — aucune manquante. C'est la bonne nouvelle du domaine.
Pages jamais liées depuis une autre page (orphelines de navigation)43 sur 148comm -23 (liste des .html) (liste des href="*.html" trouvés dans toutes les pages)
Pages chargeant un script hébergé à l'extérieur8annoncé ailleurs : Ces 8 sont cassées en production : frontend/vercel.json impose Content-Security-Policy script-src 'self' — d3js.org, unpkg.com et cesium.com sont donc bloqués par le navigateur.grep 'script src="https://' frontend/*.html → cooperation, cosmogramme-3d, donut, flows, geo-hub, mirror-earth, resources, temple-decoder
Pages sans aucun JavaScript (ni script externe, ni inline)12comptage <script> + lignes de JS inline par page = 0|0 : 404, 500, conditions, confidentialite, mentions-legales, le-souffle, et les 6 ATOM-Reference-Book*
Pages qui appellent réellement le serveur depuis leur code inline61grep atomFetch|atomPost|fetch(...api/ dans chaque page — de 28 occurrences (business.html) à 1
Routes montées dans le serveur369 register_routergrep -c 'register_router(' backend/app/main.py (à noter : seulement 4 include_router directs, le reste passe par le helper)
Modules de sphère déclarés dans governance-init.js et présents sur disque10 sur 10test -f sur js/{personnel,entreprise,institutions,creation,communaute,communication,formation,mon-equipe,durabilite,cuisine}-module.js — tous présents, de 311L à 1617L

Ce sur quoi vous pouvez compter

Trois choses tiennent solidement, et elles sont mesurables.

Premièrement, le câblage n'est pas cassé. J'ai extrait les 237 références de script distinctes de toutes les pages et vérifié l'existence de chaque fichier : zéro manquant. C'est rare dans un dépôt de cette taille, et ça veut dire qu'aucune page ne plante au chargement à cause d'un fichier absent.

Deuxièmement, l'œuvre publique est complète et se régénère. index.html, livre-reference.html et releve-chiffres.html ne sont pas recopiés à la main : ils sont engendrés par scripts/generer-index.py, scripts/generer-livre-reference.py et scripts/generer-releve-chiffres.py depuis leurs sources. Le chemin de lecture — page-mère, les Lettres, les 7 présentations, le Livre, le relevé des chiffres — est entièrement relié et fonctionne sans serveur.

Troisièmement, le cœur métier est réellement branché. Les 10 pages de sphère ont leurs 10 modules présents sur disque (vérifiés un par un, de 311 à 1617 lignes), elles figurent dans la liste GOVERNANCE_PAGES de governance-init.js:53-56 qui leur donne la pile complète, et elles appellent le serveur. business.html avec ses 28 appels, construction.html avec 21, institutions.html avec 17 : ces pages-là travaillent pour de vrai.

Ce qui manque

Du plus bloquant au moins.

1. Huit cartes sont muettes en production. cooperation, cosmogramme-3d, donut, flows, geo-hub, mirror-earth, resources et temple-decoder chargent d3.js, Leaflet, MapLibre ou CesiumJS depuis l'extérieur. Or frontend/vercel.json impose une Content-Security-Policy avec script-src 'self' : le navigateur refuse ces fichiers. Le code des pages est bon, la carte reste blanche. C'est le seul défaut que j'ai pu prouver comme cassant quelque chose de visible.

2. Quarante-trois pages sur 148 sont inaccessibles à la navigation. Personne ne peut les atteindre en cliquant — il faut connaître l'adresse. Parmi elles, des pages qui marchent : admin.html (14 appels serveur), mission-center.html (router monté en main.py:1699), les 4 centres Tier-2 (routers montés en main.py:1916, 1923, 1934, 1947), les 4 pages Babel, et 5 des 6 livres de référence. Ce n'est pas du code mort, c'est du travail livré et enterré.

3. Six centres sectoriels n'ont aucune route derrière. energy-center, defense-center, science-center, disaster-center, agriculture-center et design-center ont chacun une page de 735 à 1331 lignes, mais un grep -rl sur backend/app/routers/ ne trouve aucun fichier à leur nom. Les pages existent, le serveur n'a rien à leur répondre.

4. Le JavaScript écrit dans les pages. admin.html porte 1645 lignes de code inline, editor.html 1251, liberation.html 560. Ce code n'est ni réutilisable, ni testable, ni chargé par governance-init. Si une de ces pages tombe, il n'y a pas de module à ouvrir : il faut fouiller le HTML.

5. Les seize pages « Loading… » qui ne se remplissent que si le serveur répond. Les 4 centres Tier-2, mission-center, coverage.html (un seul div vide) sont des coquilles par conception : tout leur contenu vient de center-summary-page.js ou d'un module. Elles ne sont pas fausses, mais elles n'ont aucun repli — serveur absent, page vide, sans message.

Se tient avec : Le serveur (backend/app/main.py) — 369 routes montées via register_router ; c'est de là que viennent les données des 61 pages qui appellent le serveur, et son absence explique les 6 centres sectoriels sans réponse · Les modules JavaScript (frontend/js/, 1658 fichiers) — les pages ne sont que des coquilles qui les chargent ; governance-init.js est le distributeur · Le déploiement (frontend/vercel.json et le vercel.json racine) — décide de ce qui est publié, et sa Content-Security-Policy casse 8 cartes · Les générateurs (scripts/generer-index.py, generer-livre-reference.py, generer-releve-chiffres.py) — 3 pages de l'œuvre en dépendent et ne doivent pas être éditées à la main · Le bus de messages (frontend/js/message-bus.js, 1359 lignes) — chargé par presque toutes les pages câblées ; c'est la plomberie entre modules d'une même page · Supabase — seul service tiers autorisé par la CSP en connect-src (vzbrhovthpihrhdbbjud.supabase.co), avec une poignée d'API ouvertes (Wikipedia, OpenLibrary, open-meteo, GBIF, iNaturalist, OpenStreetMap)

Domaine 3 · état : partiel

La population interne — agents, fiches, registres et les 4 cardinaux

C'est le peuple du système : les fiches de personnages qu'on peut « embaucher » dans un catalogue, les définitions rangées dans un registre côté serveur, et le très petit nombre de classes qui savent réellement s'exécuter. Trois choses différentes que le vocabulaire du dépôt appelle toutes « agents », et qu'il faut absolument séparer pour ne pas se croire propriétaire de 400 travailleurs alors qu'on possède 400 cartes de visite.

15 livrées · 5 en attente · 5 déclaratives

L’inventaire

La pièceÉtatOù elle vitCe qu’elle fait
Catalogue frontend — 405 fichesH7_frontstage_external · S0→S9 (les 9 domaines)livréfrontend/js/agents-database.js (742 lignes)La vitrine : 405 fiches d'agents décrites (nom, niveau L0-L3, coût en jetons, capacités), rangées en 9 domaines de 45.405 appels agent('...') comptés (grep -c). Chargé par frontend/js/governance-init.js:115 et par 3 pages : livre-reference.html, meshmap.html, releve-chiffres.html.
Miroir backend du catalogue — 529 fichesH5_specialized_backstage · S0livrébackend/app/data/agents_fallback.py (690 lignes)La même vitrine côté serveur, en secours quand la base de données est absente. 405 fiches canoniques + 124 fiches d'extension V68.529 tuples comptés (grep -cE '^\s*\("'). Importé pour de vrai par backend/app/routers/agents.py:147 (from app.data.agents_fallback import FALLBACK_MARKETPLACE).
Divergence de nom du 8e domaineH4_mapping_projection · S8 Mon Équipedéclaratiffrontend/js/agents-database.js:484 (MON_EQUIPE) vs backend/app/data/agents_fallback.py:414 ("Logistique")Le fichier backend dit en tête qu'il « reflète » le frontend, mais son 8e domaine s'appelle Logistique là où le frontend dit MonEquipe. Les 45 fiches ne portent pas les mêmes noms.Comptage par domaine : le frontend sort MonEquipe 45 ; le backend sort Logistique 45 et zéro MonEquipe.
Registre serveur — 226 + 12 définitionsH5_specialized_backstage · S8livrébackend/app/services/agent_registry.py (916 lignes)Le vrai registre : 226 définitions d'agents publics répartis en 9 sphères + 12 agents système (6 cartographie de l'univers, 6 cartographie de profil). Sait semer la base de données.226 entrées {"name": " comptées ; SYSTEM_AGENTS_COUNT = 12 (l.494) ; assertion len(agents) == expected_total à la l.545. Importé par routers/agents.py:46, routers/nova.py:54, api/v1/routes/agent_routes.py:47, services/agent_execution.py:62.
Trou S9 Durabilité — 0 agent au registreH5_specialized_backstage · S9 Durabilitédéclaratifbackend/app/schemas/agent_schemas.py:444-455La sphère Durabilité est déclarée dans la table de répartition avec la valeur 0. Le catalogue frontend affiche pourtant 45 fiches Durabilité.SphereType.SUSTAINABILITY: 0 lu directement dans AGENT_DISTRIBUTION. Somme = 226.
Route marché (embaucher / renvoyer / exécuter)H7_frontstage_external · S2 Entrepriselivrébackend/app/routers/agents.py (979 lignes, 10 routes)Parcourir le marché, voir le détail d'une fiche, embaucher, renvoyer, demander une exécution, consulter Nova, les stats et la santé.Monté dans backend/app/main.py:1226 (register_router("app.routers.agents", ..., core=True)). 10 décorateurs @router comptés.
L'exécution d'un agent est une maquetteH3_vital_loop · S2déclaratifbackend/app/routers/agents.py:794-806 et backend/app/services/agent_execution.py:431-455Quand on demande à un agent de travailler, le système renvoie une phrase fabriquée. Aucun modèle de langage n'est appelé.routers/agents.py:794 # Execute (mock response) puis "output": f"[Mock response from {agent_dict['name']}]...". agent_execution.py:432 # TODO: Actual LLM execution + "note": "This is a placeholder. Real LLM integration pending.". Les jetons et le coût sont estimés par len(str(...)) // 4.
Service d'exécution + gouvernance humaineH2_membrane · S3 Institutionslivrébackend/app/services/agent_execution.py (763 lignes, AgentExecutionService l.125)La machinerie autour de l'exécution : point de contrôle humain obligatoire pour les niveaux L2/L3, approbation, rejet, annulation, historique, quota de jetons. Cette partie-là, elle, fonctionne.Importé par api/v1/routes/agent_routes.py:48 (route montée main.py:1204). Le refus de chaînage agent→agent est réel : routers/agents.py:684-700 renvoie HTTP 400 si call_agent ou agent_chain est fourni ; HTTP 423 si un L2/L3 n'a pas de point de contrôle approuvé (l.774).
Les 4 cardinaux — source de véritéH1_spine · S0câblé, en attenteagents/core/nova.js (302 l.), aria.js (335 l.), orion.js (134 l.), keli.js (77 l.) ; agents/index.js (182 l.)Les quatre personnages d'entrée : Nova le surveillant (999 Hz), Aria l'accueil (528 Hz), Orion l'architecte (741 Hz), Keli l'intime et la validation canon (999 Hz).agents/index.js fait require('./core/nova') etc., mais AUCUN fichier du dépôt ne fait require de agents/index.js (recherche require sur tout l'arbre hors node_modules : zéro résultat). Ce point d'entrée-là ne sert donc à personne.
Les 4 cardinaux — copies servables, vraiment réveilléesH1_spine · S0livréfrontend/js/agents-core/{aria,nova,orion,keli}.jsDes copies conformes des 4 cardinaux, celles-là chargées par le navigateur. C'est par ce chemin que les cardinaux existent réellement au runtime.Chargées deux fois dans frontend/js/governance-init.js (lignes 429-432 et 776-779), commentaire « CARDINAUX L0 (B-1162) — réveil runtime quaternité ». Chaque fichier déclare son en-tête « Copie servable de agents/core/... (source de vérité, laissée INTACTE) ».
Ce que les cardinaux font vraimentH1_spine · S0 Communicationlivréfrontend/js/agents-core/nova.js:147,301,308 · aria.js:203,209,338 · orion.js:89,95,159 · keli.js:55Ils publient et écoutent des messages sur le bus interne — rien de plus. Nova : cohérence + validation de fréquence + registre d'agents en mémoire. Aria : étapes d'accueil, vérification de profil, octroi de souveraineté. Orion : brouillons de plans d'architecture. Keli : un seul geste, voter sur une proposition de souveraineté.Sujets publiés mesurés : Nova coherence.check.requested, frequency.validation.result, coherence.score.updated, nova.agent.registered/unregistered ; Aria aria.profile.checked, sovereignty.granted, onboarding.guidance.generated ; Orion orion.plan.draft, architecture.plan.requested/proposed ; Keli sovereignty.proposal.voted (unique publication du fichier, 77 lignes au total).
Nova côté serveur — le seul vrai cerveau branchéH3_vital_loop · S0livrébackend/app/routers/nova.py (1890 lignes), connecteur l.562-582Le seul endroit de tout le domaine où un modèle de langage réel est appelé, avec repli sur des réponses toutes faites si aucune clé d'API n'est configurée. Chat, chat en flux, conversations, points de contrôle, analyse d'intention._get_llm_connector() charge app.services.llm_connector ; l.575 « no API keys configured — using fallback responses » ; l.805 « Try real LLM streaming » ; l.854 « No LLM available — fallback template ». Router monté main.py:1223 en core=True.
Agents de fil (ThreadAgent) — jamais exposésH3_vital_loop · S1 Personnelcâblé, en attentebackend/app/services/thread_agent_service.py (756 lignes, classe ThreadAgent l.173)Le 1er type d'agent du canon (agent attaché à un fil de conversation, avec mémoire et identité). Le code existe en entier.Aucun router ne l'importe : recherche thread_agent_service|ThreadAgentService dans backend/app/routers et backend/app/main.py = zéro résultat. Et de toute façon l.478 # Execute capability (mock for now), l.526 « TODO: Replace with actual LLM calls », l.553 « CAPABILITY HANDLERS (Mock implementations) ».
Hiérarchie L0-L3 — 5 classes, import gardéH1_spine · S8câblé, en attentebackend/agents/levels/hierarchy.py:39,225,291,398,512BaseAgent + L0SystemAgent + L1OrchestratorAgent + L2SpecialistAgent + L3AssistantAgent. La charpente de la hiérarchie.Importée uniquement dans un bloc try/except : backend/app/routers/agents_core.py:127, avec repli l.138 logger.warning("agents.levels unavailable"). Sinon seulement backend/agents/registry/registry.py:24 et les tests. Si le chemin d'import n'est pas dans le PYTHONPATH du serveur, la route renvoie 503 et personne ne s'en aperçoit.
Classes réellement exécutables — les 4 du moteur de mondeH6_domain_vertical · S2 Entrepriselivrébackend/app/modules/world_engine/agents/agent_runtime.py:29,89,159,235,292BaseAgent abstraite + PMAgent, FinanceAgent, OpsAgent, RiskAgent. Ce sont les seules classes-agents que du code appelle vraiment pour produire un comportement.Appelées par backend/app/modules/world_engine/domain/worker.py:152 (create_full_agent_team()) et backend/app/modules/poc_enterprise/core/orchestrator.py:232 (create_default_agents()). Réexportées par world_engine/__init__.py:57.
DynamicAgent + fabrique d'agentsH5_specialized_backstage · S4 Créationlivrébackend/app/services/agent_factory.py:139 (DynamicAgent), :363 (get_agent_factory) ; base commune backend/app/services/base_agent.py (351 lignes)Une classe qui fabrique un agent à la volée à partir d'une description. Rendue visible par une route dédiée.backend/app/routers/agent_factory_router.py:79 importe le module et :139 appelle get_agent_factory(). Router monté main.py:1433. Le router avoue lui-même l.40 que la fabrique n'est « pas encore branchée dans master_mind ».
21 experts ORIGINH6_domain_vertical · S7 Formationlivrébackend/app/agents/templates/origin_experts.py:376 (AGENT_REGISTRY)Une population à part, 21 experts spécialisés (historien, scientifique, chronos, linguiste, stratège, Gaia Sentinel…) avec gabarit de consigne et contraintes, pour valider des contenus d'origine.Comptés dans le dictionnaire : 6 noyau + 6 transmédia + 4 piliers + 2 co-évolution + 3 add-ons = 21. Exposés par backend/app/api/routes/origin_routes.py:590-613, router monté main.py:1758. À noter : origin_routes.py:656 annonce "expert_agents": 21 — pour une fois le chiffre déclaré est juste.
Introspection du cadre agents — 29 routesH4_mapping_projection · S8livrébackend/app/routers/agents_core.py (912 lignes)Un panneau de lecture seule qui montre les rouages : niveaux, statuts, types de point de contrôle, protocole de messages, inventaire des champs de chaque modèle.29 décorateurs @router.get comptés ; monté main.py:1665. Toutes les routes renvoient 503 quand le module sous-jacent n'est pas importable — c'est le comportement documenté en tête de fichier (l.19).
Les autres routes du domaineH7_frontstage_external · S0livrémain.py:1204 (agent_routes v1, 14 routes) · :1867 (agent_execution_router, 6 routes) · :1433 (agent_factory_router, 3) · :1437 (extended_agents_router, 3) · :1624-1626 (navigateurs Aria/Nova/Orion)Le reste de la surface HTTP du domaine population.Chaque ligne register_router lue dans backend/app/main.py ; nombre de routes obtenu par grep -cE '@router\.(get|post|put|delete|patch)' sur chaque fichier.
Fiches de capacité archivées (5 notes)H6_domain_vertical · S6 Divertissement / S5déclaratifagents/capability-notes/ : transport-50-agents.md (92 l.), societal-4-modules.md (209 l.), entertainment-7-families.md (53 l.), creative-studio-3-agents.md (39 l.), hr-team-V68.md (37 l.)Des populations entières (50 agents transport, 7 familles divertissement…) volontairement mises au frigo sous forme de notes. Elles ne s'exécutent pas et ne doivent pas être ressuscitées sans décision.backend/app/services/transport_hub_service.py:112 pointe le fichier comme source_file d'un registre « garé », et transversal_hub_surfaces_service.py:476 écrit noir sur blanc : « Laisser le registry 50 agents archive comme capability-notes, pas comme runtime ressuscitable par defaut. » Vérifié par backend/tests/test_f41_posttag_boot_contract.py:85.
88 profils de personnes (data/profiles/)H7_frontstage_external · S1 Personneldéclaratifdata/profiles/ — 93 entrées dont 88 dossiers (marie, alex, p011_startup … p076_bookstore) + 5 documents .mdDes personas d'usage (boulangerie, avocat, vétérinaire, café…) censés incarner des cas d'usage.Aucune référence en code : recherche de data/profiles dans backend/ et frontend/ (.py/.js) = zéro résultat ; recherche de p011_startup, profiles/marie, CHENU_30_PROFILES sur backend+frontend+scripts = zéro résultat. Le dossier data/profiles/marie/ ne contient qu'un seul fichier, sponsorship_manager.py, que rien n'importe.
Modules JS agent-* : 11 branchés sur 20H7_frontstage_external · S0câblé, en attentefrontend/js/agent-*.js (20 fichiers)La couche interface du domaine. Onze modules sont chargés au démarrage, neuf ne le sont pas.Chargés par governance-init.js : agents-database, agent-workspace, agent-character-manager, agent-env-profile, agent-field-kit, agent-guards, agent-hierarchy, agent-mirror-world, agent-output-graph-bridge, agent-output-protocol, agent-synergy-cluster. Non chargés : agent-decision-log, agent-execution-ui, agent-negotiation, agent-permissions, agent-templates-picker, knowledge-agent-wiring (n'apparaissent que dans frontend/js/__tests__/) ; agent-api-reference et governance-agents ne vivent que dans desktop.html ; agent-forum est appelé par sovereign-agora.js et meshmap.html.
Personnages créés par l'utilisateurH7_frontstage_external · S1 Personnellivréfrontend/js/agent-character-manager.js (579 lignes)Permet au propriétaire de créer ses propres personnages (avatar, consigne, rôle, jusqu'à 5 traits, 9 capacités, 3 sous-agents) et les raccorde automatiquement à des connecteurs externes selon le préfixe de capacité.Chargé par governance-init.js:115. Stockage dans le navigateur : STORAGE_KEY = 'atom_agent_characters' (l.15) — donc local à la machine, pas en base.
Arbre fantôme backend/services/H5_specialized_backstage · S0câblé, en attentebackend/services/agent_registry.py (652 l.), agent_execution.py (706 l.), thread_agent_service.py (751 l.), extended_agents.py (351 l.)Une deuxième copie, plus ancienne et plus courte, des mêmes services. Piège classique : on modifie le mauvais fichier.2460 lignes au total. Aucun import depuis l'application : recherche de from backend.services / import backend.services dans backend/app = zéro résultat. Le registre vivant fait 916 lignes, le fantôme 652.
Filet de testsH2_membrane · S8livrébackend/tests/integration/test_agents.py (328 l.), backend/agents/tests/test_agents.py, agents/core/__tests__/sentient-forest-canon.test.js (157 l.), agents/__tests__/agent-registry-core.test.js (23 l.), + 9 tests unitaires frontend/js/__tests__/unit/agent-*.test.jsCe qui garde le domaine honnête. Le test d'intégration sème le registre pour de vrai (l.314).Fichiers listés et comptés. backend/tests/unit/test_task7_migration.py:20-36 lit le source d'agent_registry.py pour vérifier qu'il n'utilise plus SphereType.SYSTEM mais AgentTier.SYSTEM.

Les chiffres, mesurés

Ce qu’on compteLa mesureComment
Fiches d'agents dans le catalogue frontend405annoncé ailleurs : L'en-tête du fichier annonce « 405 Agents x 9 Domaines » — pour une fois, exact. Mais le canon global parle de « 400+ agents » comme s'il s'agissait de travailleurs.grep -c "agent('" frontend/js/agents-database.js → 405 ; répartition par domaine : 9 × 45 exactement
Fiches dans le miroir backend529annoncé ailleurs : Cohérent avec sa propre docstring l.2. Mais 529 ≠ 405 : les deux catalogues du système ne contiennent pas le même monde.grep -cE '^\s*\("' backend/app/data/agents_fallback.py → 529 (405 canoniques + 124 extension V68)
Définitions au registre serveur226 publiques + 12 système = 238grep -c '{"name": "' backend/app/services/agent_registry.py → 226 ; SYSTEM_AGENTS_COUNT = 12 (l.494) ; assertion vérifiée à l.545
Agents de la sphère S9 Durabilité au registre0annoncé ailleurs : Le catalogue frontend affiche 45 fiches Durabilité (agents-database.js:540). Écart 45 → 0.backend/app/schemas/agent_schemas.py:452 → SphereType.SUSTAINABILITY: 0
Classes-agents réellement exécutablesenviron 10annoncé ailleurs : « 400+ agents » du manifeste. Le rapport réel entre fiches et exécutants est d'environ 40 pour 1.grep -rn 'class .*BaseAgent' backend → 5 dans backend/agents/levels/hierarchy.py (dont 1 abstraite), 5 dans world_engine/agents/agent_runtime.py (dont 1 abstraite), 1 DynamicAgent dans agent_factory.py, 1 exemple en docstring dans base_agent.py:20. Effectivement appelées par du code : les 4 de world_engine (worker.py:152, orchestrator.py:232).
Exécutions d'agent qui appellent un vrai modèle0 (hors Nova)routers/agents.py:794 `# Execute (mock response)` ; agent_execution.py:432 `# TODO: Actual LLM execution` ; thread_agent_service.py:478 `# Execute capability (mock for now)`. Seul backend/app/routers/nova.py:562-582 charge un connecteur LLM réel.
Routes HTTP du domaine population montées dans main.py68 sur 8 routersagents.py 10 (main.py:1226) + agent_routes.py 14 (:1204) + agents_core.py 29 (:1665) + agent_execution_router 6 (:1867) + agent_factory_router 3 (:1433) + extended_agents_router 3 (:1437) + les 3 routers de navigateur Aria/Nova/Orion (:1624-1626). Comptage par grep -cE '@router\.(get|post|put|delete|patch)'.
Cardinaux au runtime4ls agents/core/ → aria.js, keli.js, nova.js, orion.js. Chargés via leurs copies frontend/js/agents-core/*.js dans governance-init.js:429-432 et 776-779.
Lignes de code par cardinalAria 335 · Nova 302 · Orion 134 · Keli 77wc -l agents/core/*.js. Keli, le 4e trône anti-concentration, ne sait faire qu'une chose : voter (une seule publication sur le bus, l.55).
Profils de personnes branchés en code0 sur 88ls data/profiles → 88 dossiers ; grep -rn 'data/profiles' backend frontend --include=*.py --include=*.js → aucun résultat ; grep de 'p011_startup', 'profiles/marie', 'CHENU_30_PROFILES' → aucun résultat
Modules JS agent-* chargés au démarrage11 sur 20grep -c '/js/<module>.js' frontend/js/governance-init.js pour chacun des 20 fichiers frontend/js/agent-*.js
Lignes de code dupliquées dans l'arbre fantôme2460wc -l backend/services/{agent_registry,agent_execution,thread_agent_service,extended_agents}.py ; aucun `from backend.services` dans backend/app
Experts ORIGIN21Décompte du dictionnaire AGENT_REGISTRY, backend/app/agents/templates/origin_experts.py:376 → 6+6+4+2+3

Ce sur quoi vous pouvez compter

Quatre choses tiennent debout et méritent votre confiance.

D'abord, le catalogue. Les 405 fiches frontend et les 529 fiches backend sont réelles, complètes, bien écrites, avec des descriptions en français adressées à l'utilisateur (« Vous suit vos stocks… »). C'est un vrai travail de conception, pas du remplissage. La navigation, le filtrage par domaine et par niveau, l'embauche et le renvoi fonctionnent de bout en bout.

Ensuite, la gouvernance humaine. C'est la partie la plus sérieuse du domaine. La règle « pas d'agent qui en appelle un autre » est appliquée pour de vrai : backend/app/routers/agents.py:684-700 refuse la requête avec une erreur 400 si on tente de chaîner. Le point de contrôle humain pour les niveaux L2 et L3 est appliqué aussi : erreur 423 tant qu'un humain n'a pas approuvé (agents.py:774). Ce ne sont pas des intentions dans un document, c'est du code qui bloque.

Puis, les 4 cardinaux au navigateur. Ils sont réellement réveillés au démarrage (governance-init.js:429-432), ils écoutent et publient sur le bus interne. Ils sont petits mais honnêtes : ils font exactement ce que leur code dit, ni plus ni moins.

Enfin, Nova côté serveur (backend/app/routers/nova.py, 1890 lignes). C'est le seul endroit du domaine où un vrai modèle de langage est appelé, avec un repli propre sur des réponses toutes faites quand aucune clé n'est configurée. Si quelque chose dans ce système « parle » vraiment, c'est là.

Ce qui manque

Du plus bloquant au moins :

1. Les agents ne travaillent pas. C'est le trou central. Quand on demande à un agent d'exécuter une tâche, le système répond [Mock response from <nom>]: Processed input successfully (backend/app/routers/agents.py:794-806). Le service dédié dit la même chose autrement : # TODO: Actual LLM execution et "note": "This is a placeholder. Real LLM integration pending." (agent_execution.py:432-455). Les jetons facturés sont calculés par len(str(...)) // 4, une estimation grossière. Tout l'échafaudage — embauche, quotas, coûts, points de contrôle, traçabilité — entoure un centre vide. Nova est la seule exception.

2. Les agents de fil (ThreadAgent) sont enfermés. 756 lignes de code correct dans backend/app/services/thread_agent_service.py, et aucun router ne l'importe. Le canon présente pourtant les Thread Agents comme le type d'agent numéro 1, celui que l'utilisateur voit. Il n'est joignable par aucune adresse. Et même s'il l'était, ses capacités sont des maquettes (l.553 « CAPABILITY HANDLERS (Mock implementations) »).

3. Les deux catalogues ne décrivent pas le même monde. Le backend dit « reflète le frontend » en tête de fichier, mais il contient 529 fiches contre 405, et son 8e domaine s'appelle Logistique là où le frontend dit MonEquipe. Selon qu'on interroge la page ou le serveur, on ne voit pas la même population.

4. La sphère Durabilité est vide au registre. SphereType.SUSTAINABILITY: 0 (agent_schemas.py:452) alors que la vitrine en montre 45. Si un utilisateur clique sur un agent Durabilité, il tombe sur le catalogue de secours, jamais sur une définition en base.

5. Neuf modules d'interface sur vingt ne sont pas chargés. agent-permissions.js, agent-decision-log.js, agent-negotiation.js, agent-execution-ui.js, agent-templates-picker.js, knowledge-agent-wiring.js n'existent qu'à travers leurs propres tests. Ils passent au vert et ne servent personne. agent-permissions en particulier — les permissions d'agent — est un manque qui compte.

6. Le point d'entrée agents/index.js est mort. Personne ne fait require dessus dans tout le dépôt. Le fichier qui se présente comme « AT·OM AGENT ORCHESTRATION SYSTEM — Nova, Aria & 400 Specialists » n'orchestre rien.

7. Un arbre fantôme de 2460 lignes. backend/services/agent_registry.py (652 lignes) coexiste avec backend/app/services/agent_registry.py (916 lignes, le vivant). Trois autres fichiers du même genre. Aucun n'est importé par l'application. C'est un piège à modification.

8. Les 88 profils de personnes ne sont branchés nulle part. Zéro référence en code, dans les deux sens de recherche.

Se tient avec : Fournisseurs LLM — le domaine population dépend entièrement de app/services/llm_connector.py pour cesser d'être une maquette ; aujourd'hui seul Nova s'en sert · Bus de messages — les 4 cardinaux n'existent qu'à travers frontend/js/message-bus.js ; sans bus, ils ne font rien · Gouvernance et points de contrôle — les checkpoints L2/L3 et l'interdiction de chaînage sont la membrane du domaine (S3 Institutions) · Sphères et taxonomie — les 9 domaines du catalogue et les 9 SphereType du registre ne coïncident pas exactement (S9 vide côté registre) · Base de données Supabase — 12 migrations alembic v82_* portent des tables agents ; le registre sait semer via seed_agents(), appelé depuis 3 routers · Moteur de monde (world_engine) — seule zone où des classes agents s'exécutent vraiment, via domain/worker.py · ORIGIN-GENESIS — population parallèle de 21 experts, gouvernée séparément · Connecteurs externes — agent-character-manager.js raccorde automatiquement les personnages créés par l'utilisateur à connector-hub.js

Domaine 4 · état : partiel

Les étages de cohabitation (L1 ETHOS / L2 AGORA / L3 NEXUS / L4 LUNA), la membrane, les gates et le Point Zéro

C'est l'étage « qui a le droit de voir quoi » du système : quatre paliers d'observation empilés (sentinelles, opérations, commandement, observatoire), une membrane qui décide si une lecture passe ou « gestationne encore », et un centre vide — le Point Zéro — qui bat un pouls et n'ordonne rien. Aujourd'hui le tri de visibilité fonctionne vraiment côté écran, mais personne ne vérifie qui vous êtes avant de vous laisser choisir votre étage.

19 livrées · 3 en attente · 4 déclaratives

L’inventaire

La pièceÉtatOù elle vitCe qu’elle fait
ACCESS_MATRIX — la matrice des regardsH2_membrane · S0livréfrontend/js/hierarchy-sync.js:68-72Table qui dit qui voit qui : ethos ne voit qu'ethos, agora ne voit qu'agora, nexus voit ethos+agora+nexus, luna voit les quatre. Elle dit aussi qui peut commander : nexus commande ethos+agora, luna commande les trois autres, ethos et agora ne commandent personne.Le module est chargé au démarrage : frontend/js/governance-init.js:337 liste '/js/hierarchy-sync.js'. La matrice est consommée réellement par level-consoles.js:373 (getVisibleLevels) qui appelle ATOMHierarchySync.getAccess.
HierarchySync — le moteur des 4 étagesH2_membrane · S0livréfrontend/js/hierarchy-sync.js (999 lignes)Tient l'état de santé de chaque étage, un diapason numérique, un registre d'intentions, un journal de communication inter-étages plafonné à 200 entrées, et une file de commandes par étage.Chargé par governance-init.js:337 ; référencé par level-consoles.js:145,153,179,181-182,205 (widgets et actions rapides).
sendCommand — le seul passage d'un étage à l'autreH2_membrane · S0livréfrontend/js/hierarchy-sync.js:557-586C'est LA réponse à « comment un agent d'un étage parle-t-il à un autre » : il ne parle pas directement, il dépose une commande dans la file de l'étage visé, et seulement si canCommand l'autorise. Sinon, refus journalisé « ACCESS DENIED » et retour false.Le refus est réel : ligne 558-561 lit ACCESS_MATRIX[fromLevel] et fait canCommand.includes(toLevel) avant toute écriture. La file est vidée par _processCommandQueues (ligne ~590).
Escalade L1 → L3 sur alerte critiqueH2_membrane · S0déclaratiffrontend/js/hierarchy-sync.js:687-690Censé faire monter une alerte sentinelle critique de ETHOS vers NEXUS. Ne peut pas fonctionner : deux défauts cumulés.1) L'appel est sendCommand('ethos','nexus',...) alors que ACCESS_MATRIX.ethos.canCommand vaut [] (ligne 69) — le garde refuse systématiquement. 2) Le test est payload.severity === 'critical' en minuscules, alors que les seuls émetteurs réels publient 'HIGH'/'MEDIUM'/'LOW' en majuscules (frontend/js/event-bridge-router.js:233,257,263,308,318). Le chemin n'a jamais pu s'exécuter.
Les 4 consoles d'étageH7_frontstage_external · S0livréfrontend/js/level-consoles.js (501 lignes)Définit une console par étage — Moniteur Sentinelle (L1), Opérations Agent (L2), Centre de Commande (L3), Observatoire Luna (L4) — avec widgets par défaut, mise en page, actions rapides et métriques.Chargé par governance-init.js:341. Consommé par env-runtime.js:482-483, 597-598, 817-818, 1041-1042 et par desktop-shell.js:982-983.
Le filtre de visibilité effectif (widget-registry)H2_membrane · S0livréfrontend/js/widget-registry.js:241-252 et :629Traduit l'étiquette d'étage ('L3', 'nexus'…) en un chiffre 1-4, puis écarte tout widget dont le niveau dépasse celui demandé. C'est le seul endroit où la hiérarchie a un effet mécanique observable.Ligne 629 : « if (filters.accessLevel && d.accessLevel > filters.accessLevel) continue; ». Alimenté par level-consoles.js:395-405 qui calcule maxAccessLevel depuis getVisibleLevels et le passe à getDescriptors.
Le choix de son propre étage — sans aucun contrôleH7_frontstage_external · S0livréfrontend/js/env-runtime.js:799-814 et frontend/js/desktop-shell.js:979-986setActiveLevel(levelName) bascule l'utilisateur sur l'étage demandé. C'est appelé depuis un simple clic dans le menu du bureau.Lignes 800-806 : la seule vérification est « le nom d'étage existe-t-il dans LEVEL_MAP ». Aucune lecture de session, de rôle, de jeton. Cliquer « Observatoire Luna » donne L4.
membrane_service — la perméabilité par mériteH2_membrane · S9livrébackend/app/services/membrane_service.py (103 lignes)Le vrai gardien côté serveur. Croise 4 axes (localisation ind/com/civ, identité du propriétaire, mérite gestationné, rôle porteur) et rend un verdict : permeable, gestating (pas encore mérité) ou sealed (l'intérieur d'autrui, inviolable).Appelé pour de vrai par backend/app/services/mcp_live_organs.py:38, backend/app/services/mcp_repo_tools.py:61 et backend/app/services/bureau_service.py:143. Couvert par 10 tests dans backend/tests/unit/test_membrane_service.py.
Le gate d'authentification MCP (fail-closed)H2_membrane · S0livrébackend/app/services/mcp_server.py:751-779Ferme la porte d'entrée des outils agents : exige un jeton machine (MCP_API_TOKEN) ou un JWT utilisateur valide, sinon 401. Sans lui, tout Internet pouvait lire le code source via repo_read_file.Dépendance obligatoire sur le POST /mcp/ (ligne 783 : Depends(_require_mcp_auth)). Échappatoire dev MCP_AUTH_DISABLED=1, désactivée par défaut (ligne 761).
Le routeur Membrane des 3 MondesH2_membrane · S0livrébackend/app/routers/membrane.py (432 lignes, 6 endpoints)Gère les « passages » entre Mon Monde (privé), Notre Monde (collectif) et Le Monde (public) : création, listage, révocation, synchronisation, avec champs filtrés/bloqués et 3 niveaux de perméabilité (read_only, comments, interactive).Monté dans backend/app/main.py:1258. Protégé globalement par Depends(get_current_user_id) (ligne 44). Repli en mémoire si la base est absente.
spatial_rbac_enforcer — les gates par sphèreH2_membrane · S0livrébackend/app/services/spatial_rbac_enforcer.py (414 lignes)Quatre types de gates (role_gate, invite, token_gate, quest_gate) appliqués à l'entrée d'une sphère, au placement d'objet, à l'interaction et au passage de portail. Journalise chaque décision.Exposé par backend/app/routers/spatial_rbac_router.py:70-72 (import réel). Deux fichiers de tests : backend/tests/unit/test_spatial_rbac_enforcer.py et backend/tests/routers/test_spatial_rbac_router.py.
Point Zéro Heartbeat (Sanctum 963 Hz)H0_origin · S0livrébackend/app/services/sanctum/point_zero_heartbeat.py (144 lignes) + heartbeat_scheduler.py (124 lignes)Le battement du centre. Diffuse un instantané des constantes canon immuables (φ, φ⁻¹, Fibonacci, fréquences Solfeggio, plafond η 0.30) pour que les abonnés détectent toute dérive par somme de contrôle.Démarré dans la séquence de démarrage : backend/app/main.py:753-754 (await get_heartbeat_scheduler().start()), arrêté ligne 917-918. Écouté par backend/app/routers/fractal_clock_router.py:163 et relayé par backend/app/services/atom_node_ws_relay.py:80.
sacred-constants.js — le Point 0 lui-mêmeH0_origin · S0livréfrontend/js/sacred-constants.js (527 lignes, 29 911 octets)Le référentiel gelé : window.SACRED = Object.freeze({...}). C'est ce que l'ADR désigne comme « Point 0 » — non pas un service, mais un bloc de constantes que rien ne doit pouvoir modifier.Object.freeze à la ligne 23 et sur 18 sous-blocs (MONDES:101, MEMBRANE_PERMEABILITY:138, FIBONACCI:434…). Le heartbeat serveur en recopie une partie (point_zero_heartbeat.py:39-44, avec un TODO explicite : la version Python n'est pas importée du même fichier).
Centre-Réceptacle Observer — le centre muetH0_origin · S9livréfrontend/js/centre-receptacle-observer.js (289 lignes)Réifie le vide central : il REÇOIT la présence des 4 étages, MESURE leur accord (cohérence du centre à 852 Hz) et n'émet qu'un seul constat, 'centre.receptacle.accord'. Il ne renvoie jamais d'ordre. C'est la garde doctrinale du Point Zéro : le centre accueille, il ne commande pas.Chargé par governance-init.js. Aucune republication vers les étages dans le fichier (le seul _publish est le constat d'accueil).
Les deux pôles nommés du Point ZéroH1_spine · S9livréfrontend/js/point-zero-chicxulub.js (854 l.) et frontend/js/point-zero-temple-salomon.js (344 l.)Deux voisins géographiques du centre qui, volontairement, n'émettent PAS le pouls générique : Chicxulub publie 'pointzero.geomagnetic.heartbeat', Temple-Salomon publie 'pointzero.emanation.heartbeat'.chicxulub ligne 377 et temple-salomon lignes 19-20. La règle est écrite dans le code serveur : backend/app/services/qg_fractalization/cluster_k_frontier.py:378 — « they must never be promoted to canonical Point 0 pulse owners ».
zero-point-sync — un second pouls concurrentH1_spine · S0livréfrontend/js/zero-point-sync.js:271 (725 lignes)Calcule un Point Zéro local par zone (pyramide inversée : Point 0 Maître → 144k piliers → 20M graines) et publie, lui, le topic générique 'pointzero.heartbeat'.C'est le SEUL émetteur frontend du topic générique (grep sur publish('pointzero.heartbeat') dans frontend/js = 1 résultat). Il est bien chargé par governance-init.js. Le système se retrouve donc avec deux battements canon indépendants : celui du Sanctum côté serveur et celui-ci côté navigateur — exactement le risque nommé dans frontend/js/communication-center-governed.js:245.
Le registre des étages côté serveur (master_hash_registry)H1_spine · S0livrébackend/app/core/master_hash_registry.py (731 lignes)Étiquette chaque module serveur d'un niveau L1-ETHOS / L2-AGORA / L3-NEXUS / L4-LUNA, plus une sphère et un canal. Sert d'annuaire consultable (get_by_level, get_by_sphere, get_by_canal).Testé : backend/tests/unit/test_master_hash_registry.py:145-146 et :171 (assert que chaque niveau appartient bien aux 4 valeurs). Mais aucun code d'application n'appelle get_by_level en production — les seuls appelants sont les tests.
QG Fractalization — la cartographie servie en APIH4_mapping_projection · S9livrébackend/app/services/qg_fractalization/ (25 fichiers, 35 251 lignes) + backend/app/routers/qg_fractalization_router.py (1 357 l., 185 endpoints)Sert par HTTP la carte fractale complète : les 24 troncs, leurs étages H0-H7, leur zone frontière, leurs vagues d'exécution W0-W4 et des centaines de « surfaces » d'atlas.Monté dans backend/app/main.py:1575, préfixe /api/v2/qg-fractalization (routeur ligne 28). Le service lit des JSON de docs/cartography/ (base.py:12-22).
Le contenu de cette cartographie — du texte, pas une contrainteH4_mapping_projection · S9déclaratifbackend/app/services/qg_fractalization/cluster_k_frontier.py:124,135,306,317,357,378 (1 554 lignes)Les « frontier_rule » (par ex. « la position canonique reste en amont du maillage de projection ») sont des chaînes de caractères retournées par l'API. Rien dans le code ne les applique.Ce sont des littéraux dans des dictionnaires Python retournés tels quels par les méthodes get_*_surface. Aucune vérification, aucune levée d'exception, aucun refus.
Protocole de collaboration gouvernée — 4 rôles, 3 lanesH2_membrane · S0livrédocs/cartography/QG-GOVERNED-COLLABORATION-PROTOCOL.json + backend/app/routers/governed_collaboration_router.py (161 endpoints)Définit qui travaille où : 4 rôles (pilote souverain humain, exécution canon QG, lane communication, bureau externe), 3 lanes, 2 membranes canoniques (/api/v2/bureau/relay et /api/v2/communication-center), et 4 règles de passation.Routeur monté dans main.py:1572. Les 2 membranes existent réellement : bureau_relay monté main.py:1224 (core=True), communication_center_router monté main.py:1903.
La règle qui protège le centre (no_external_rewrite_center)H2_membrane · S0déclaratifdocs/cartography/QG-GOVERNED-COLLABORATION-PROTOCOL.json, handoff_rules[0]Interdit toute réécriture externe du centre pendant les vagues W0, W1, W2 : « The center is closed and must remain protected while the method is propagated. »La règle est lue et servie (protocol.py:91-92, router ligne 71-72) mais jamais appliquée : aucune occurrence de 'no_external_rewrite_center' dans du code de contrôle, seulement dans le JSON et dans les paquets qui le recopient (base_packets.py:120,189,300,416,527).
.importlinter — la garde des 3 zones, jamais arméeH2_membrane · S0déclaratif/.importlinter (à la racine du dépôt)Devait empêcher mécaniquement la zone EXTERIEUR (Wild, 396 Hz) d'importer directement la zone INTERIEUR (Sanctum, 963 Hz) sans traverser le TORUS (membrane, 528 Hz), et garder le Point Zéro immuable.Le fichier dit lui-même « Status: SCAFFOLDING — placeholder module lists ». Le contrat cite 3 modules source et 1 module interdit (app.services.bayon) au lieu des ~160 annoncés, et ne mentionne même pas app.services.sanctum. Aucune occurrence de 'lint-imports' dans .github/, scripts/, ou tout .yml/.sh du dépôt : jamais exécuté.
atom-fractal-canon — le miroir portableH4_mapping_projection · S9câblé, en attenteatom-fractal-canon/index.json + registry/ (7 fichiers, 63 373 octets)Copie compacte et portable du registre fractal (24 modules, 2 577 feuilles, 5 872 arêtes), avec ses propres invariants auto-vérifiés.Le fichier le déclare lui-même : "runtime_contract": {"imported_by_app": false, "runtime_dependency": false}. Vérifié : aucun .py de backend/app ni .js de frontend/js n'ouvre ce dossier ; seul un endpoint le RÉSUME (governed_collaboration_router.py:34). À noter : index.json:4 pointe encore vers un ancien chemin machine, C:\Users\pro-s\Github\V\ATOM-CLEAN.
vide_centre_relique — l'invariant du centre videH0_origin · S9câblé, en attentehf-atom-tools/atom_canon/invariants/vide_centre_relique.py (142 lignes)Formalise la doctrine du Point Zéro : l'absence d'une relique centrale (ou sa présence seulement symbolique) fonctionne comme preuve de puissance, et se distingue d'un centre plein.Correct et testé (hf-atom-tools/atom_canon/tests/test_vide_centre_relique.py, 5 cas). Mais rien dans backend/ ne l'importe : les seuls appelants sont son propre __init__.py et ses tests.
nexus-core.js — l'orphelinH3_vital_loop · S0câblé, en attentefrontend/js/nexus-core.js (1 287 lignes)Une implémentation du noyau NEXUS qui n'est chargée nulle part.governance-init.js:334 charge '/js/nexus-core-unification.js', pas '/js/nexus-core.js'. Aucune page HTML ni aucun autre module ne le référence. Pourtant frontend/js/CATALOGUE-MODULES-JS.md:88 l'annonce « nexus-core(+unification)|WIRED|L4 » — le catalogue se trompe.
La seconde échelle L0-L3 (CHE·NU V69)H5_specialized_backstage · S8livrébackend/agents/levels/hierarchy.py (647 lignes) + backend/agents/core/models.py:23-35Une hiérarchie d'agents COMPLÈTEMENT DIFFÉRENTE qui utilise les mêmes noms : L0 Système, L1 Orchestrateur, L2 Spécialiste, L3 Assistant. Quatre classes exécutables (L0SystemAgent, L1OrchestratorAgent, L2SpecialistAgent, L3AssistantAgent).Importé réellement par backend/agents/registry/registry.py:24 et backend/app/routers/agents_core.py:127 ; le routeur est monté dans main.py:1665 (/api/v2/agents-core).

Les chiffres, mesurés

Ce qu’on compteLa mesureComment
Étages de cohabitation définis4 (ethos, agora, nexus, luna)const LEVEL, frontend/js/hierarchy-sync.js:40-45 ; ACCESS_MATRIX lignes 68-72
Modules serveur étiquetés par étage96 au total : 8 L1-ETHOS, 67 L2-AGORA, 9 L3-NEXUS, 12 L4-LUNAgrep -o 'level="[^"]*"' backend/app/core/master_hash_registry.py | sort | uniq -c
Fichiers serveur portant une étiquette LEVEL: dans leur en-tête115annoncé ailleurs : À ne pas confondre avec les 96 entrées du registre : 115 fichiers se déclarent, 96 sont enregistrés.grep -rl "LEVEL: L[1-4]" backend/app --include=*.py | wc -l
Fichiers JS déclarant un niveau dans leur MALLEABILITY_CONTRACT839 fichiers sur 1 286grep -rl "level: 'L[1-4]'" frontend/js/*.js | wc -l — et 921 occurrences au total (233 L1, 450 L2, 134 L3, 104 L4)
Endroits où le niveau produit un effet mécanique1widget-registry.js:629 — le seul filtre qui écarte réellement quelque chose sur la base du niveau
Chemins de commande inter-étages autorisés5 sur 12 possiblesACCESS_MATRIX, hierarchy-sync.js:69-72 : nexus→ethos, nexus→agora, luna→ethos, luna→agora, luna→nexus. ethos et agora ne commandent rien.
Appels réels à sendCommand dans le code2, dont 1 morthierarchy-sync.js:687 (ethos→nexus, toujours refusé) et :737 (nexus→ethos, valide)
Troncs de la carte fractale et leur répartition par étage H24 troncs : H2_membrane 6, H5 5, H7 5, H0 2, H1 2, H6 2, H3 1, H4 1lecture de docs/cartography/QG-FRACTALIZATION-MANIFEST.json, clé 'trunks', comptage des structural_tier
Répartition par zone frontièrespecialized_organs 8, membrane_ring 6, frontstage_surface 5, origin_core 4, projection_bridge 1même fichier, frontier_distribution du bloc summary — cohérent avec atom-fractal-canon/index.json
Feuilles et arêtes de la carte2 577 feuilles, 5 872 arêtesQG-FRACTALIZATION-MANIFEST.json, summary.leaf_count et summary.flow_edge_count
Endpoints de la cartographie fractale185grep -c '^@router' backend/app/routers/qg_fractalization_router.py, préfixe /api/v2/qg-fractalization
Lignes de code du service de cartographie35 251 sur 25 fichierswc -l backend/app/services/qg_fractalization/*.py — dont cluster_r 4 230, cluster_y 4 217, cluster_k 3 908
Endpoints de la membrane des 3 Mondes6grep -c '^@router' backend/app/routers/membrane.py, monté main.py:1258
Lanes et rôles du protocole de collaboration gouvernée3 lanes, 4 rôles, 2 membranes canoniques, 4 règles de passationannoncé ailleurs : backend/app/main.py:1571 annonce en commentaire « hiérarchie a 4 lanes » — le fichier n'en contient que 3.lecture de docs/cartography/QG-GOVERNED-COLLABORATION-PROTOCOL.json
Règles de passation réellement appliquées par du code0 sur 4grep 'no_external_rewrite_center' dans backend/app : uniquement des recopies dans base_packets.py, aucun point de refus
Modules couverts par le contrat d'isolation des 3 zones3 sources / 1 interditannoncé ailleurs : L'ADR et le fichier lui-même parlent de ~160 modules à répartir (Sanctum ~28, Torus ~76, Wild ~55). Écart : 3 contre 160.lecture de /.importlinter, contrat zones-hierarchy
Exécutions de import-linter dans le dépôt0grep -rn 'lint-imports' sur tous les .yml, .yaml, .sh, .py, .json (hors worktrees) : aucun résultat
Cadence du pouls du Point Zéro39 s (CYCLE_9)annoncé ailleurs : À ne pas confondre avec VIBE_BASE=432 ms ni avec VIBE_LONG=43,2 s : ce sont trois cadences distinctes.backend/app/main.py:749 en commentaire, heartbeat_scheduler.py:117 (asyncio.sleep(self._cadence_seconds))
Émetteurs du topic générique pointzero.heartbeat2 (un par bus)serveur : sanctum/point_zero_heartbeat.py ; navigateur : frontend/js/zero-point-sync.js:271 (seul résultat du grep sur publish('pointzero.heartbeat'))
Fichiers frontend touchant pointzero.heartbeat23annoncé ailleurs : L'ADR du 2026-05-09 parlait de « 9 listeners orphelins, 0 publishers actifs ». Le trou est bouché côté serveur, mais l'écoute a plus que doublé.grep -rl 'pointzero.heartbeat' frontend/js | wc -l
Constantes canon recopiées à la main entre les deux langages5 blocs (PHI, PHI_INV, Fibonacci 8 premiers, 11 fréquences Solfeggio, plafond η 0,30)backend/app/services/sanctum/point_zero_heartbeat.py:39-44, avec le commentaire « TODO: when backend/app/core/sacred_constants.py is created »
Miroir portable atom-fractal-canon importé par l'application0 foisatom-fractal-canon/index.json déclare runtime_contract.imported_by_app = false ; vérifié par grep 'atom-fractal-canon' sur backend/app et frontend/js

Ce sur quoi vous pouvez compter

Trois choses tiennent vraiment.

D'abord, la chaîne de visibilité côté écran est complète et mécanique, du haut en bas : la matrice (hierarchy-sync.js:68-72) → getVisibleLevels (level-consoles.js:373) → maxAccessLevel (level-consoles.js:395-405) → le filtre effectif (widget-registry.js:629). Un utilisateur en « agora » ne verra réellement pas les widgets marqués L3 ou L4. Ce n'est pas de la décoration.

Ensuite, la membrane serveur est bâtie, propre et testée. membrane_service.py est un fichier de 103 lignes sans dépendance à la base de données ni au framework — on peut le tester à froid, et c'est fait (10 tests). Ses trois verdicts sont bien pensés : « permeable », « gestating » (pas encore mérité — un pas-encore, pas un refus) et « sealed » (l'intérieur d'autrui, inviolable). Trois consommateurs réels s'en servent avant d'agir : les organes vivants MCP, l'accès au dépôt, et le bureau.

Enfin, le Point Zéro bat pour de vrai côté serveur : le planificateur démarre à l'allumage (main.py:753-754) et s'arrête proprement (main.py:917-918), et au moins deux consommateurs l'écoutent (fractal_clock_router.py:163, atom_node_ws_relay.py:80). La discipline du centre muet est respectée : le Centre-Réceptacle mesure sans jamais renvoyer d'ordre, et les deux pôles voisins émettent des topics nommés plutôt que de squatter le pouls canonique.

Ce qui manque

Du plus bloquant au moins.

1. Les étages ne sont pas une sécurité — ils sont une préférence d'affichage. env-runtime.js:799-803 ne vérifie qu'une seule chose : que le nom d'étage existe. Aucune session, aucun rôle, aucun jeton. Le menu du bureau (desktop-shell.js:979-986) offre les quatre consoles en clic direct. N'importe qui peut se hisser à L4 LUNA. Tout ce qui est « caché » à un étage inférieur n'est caché qu'à quelqu'un qui ne clique pas.

2. La seule escalade automatique du système est morte deux fois. hierarchy-sync.js:687 tente sendCommand('ethos','nexus') alors qu'ethos n'a aucun droit de commande (ligne 69) — refus garanti. Et même sans ça, la condition teste 'critical' en minuscules quand les émetteurs réels publient 'HIGH' (event-bridge-router.js:233,308). Une alerte sentinelle critique ne remonte à personne.

3. Deux Points Zéro battent en parallèle sans se connaître. Le Sanctum publie 'pointzero.heartbeat' côté serveur ; zero-point-sync.js:271 publie le même nom de topic côté navigateur, sur un bus différent. 23 fichiers frontend touchent ce topic. Le code serveur lui-même a nommé le danger (communication-center-governed.js:245 : « multiple_runtime_neighbor_publishers_share_pointzero_heartbeat_without_canonical_ownership »). Les constantes canon sont d'ailleurs recopiées à la main en Python (point_zero_heartbeat.py:39-44) au lieu d'être lues depuis sacred-constants.js — un TODO l'admet.

4. L'isolation des 3 zones n'existe pas. .importlinter était censé l'imposer mécaniquement ; il se déclare lui-même « SCAFFOLDING », liste 3 modules d'exemple au lieu de ~160, ne cite même pas app.services.sanctum, et n'est lancé par aucun script ni aucune CI du dépôt. L'obstacle historique (le fichier decision_point_schemas.py tronqué) est pourtant réparé — j'ai vérifié qu'il compile. La voie est libre, personne ne l'a prise.

5. Les règles de frontière sont du texte servi en HTTP. Les « frontier_rule » de cluster_k_frontier.py et les 4 handoff_rules du protocole (dont « le centre est fermé ») sont lus, transportés, recopiés dans des paquets — jamais appliqués. Aucun code ne refuse quoi que ce soit sur leur base.

6. Deux échelles portent les mêmes noms. L1/L2/L3 veut dire ETHOS/AGORA/NEXUS d'un côté, et Orchestrateur/Spécialiste/Assistant de l'autre (backend/agents/core/models.py:23-35), les deux montés en production. Rien n'indique dans le code lequel est en jeu.

7. L'annuaire serveur des étages ne sert à rien en production : get_by_level (master_hash_registry.py:729) n'est appelé que par des tests.

Se tient avec : Agents et orchestrateurs — les quatre personas cardinales (Aria, Nova, Orion, Keli) sont référencées dans chaque ORCHESTRATOR_GUIDE des modules d'étage ; et le "TOI augmenté" (Keli) est explicitement prévu par la membrane pour opérer SOUS l'identité du Point Zéro (membrane_service.py, docstring) · Sphères S0-S9 — la seconde coordonnée de chaque module dans master_hash_registry.py, et la cible des gates de spatial_rbac_enforcer.py (SPHERE_GATES) · Bus de messages — c'est le seul moyen de circulation entre étages ; le domaine dépend entièrement de frontend/js/message-bus.js côté navigateur et de app/services/event_bus.py côté serveur, et le double pouls du Point Zéro vient précisément de ce que ce sont deux bus séparés · Horloge fractale et pouls bio — fractal_clock_router.py:163 est le consommateur principal du battement du centre ; les cadences (432 ms, 39 s, 43,2 s) viennent de là · MCP et le bureau — mcp_live_organs.py, mcp_repo_tools.py et bureau_service.py sont les trois seuls consommateurs vivants de la membrane ; c'est là que la perméabilité par mérite s'exerce vraiment · Souveraineté et invariants canon — l'invariant IC-N10 (souveraineté observée, non imposée) est ce que traduit le verdict "sealed" de la membrane ; le paquet hf-atom-tools/atom_canon/ en porte la version formelle, encore non branchée au serveur · Temples et positionnement fractal — cluster_k_frontier.py articule le Point Zéro avec le maillage des temples et l'adresse fractale

Domaine 5 · état : partiel

L'armure 15D et le quantique

L'armure, c'est la fiche d'identité chiffrée d'un membre : quinze « dimensions » (identité, valeur, mémoire, souveraineté…) qu'on résume en une empreinte cryptographique unique, pour pouvoir signer un engagement sans jamais montrer le contenu. Le « quantique », lui, est un nom : il y a de la vraie cryptographie moderne (Ed25519, HMAC-SHA256) qui fonctionne, mais rien dans le dépôt n'exécute de calcul quantique ni de signature post-quantique — ce sont des simulations classiques et des maquettes.

13 livrées · 4 en attente · 4 déclaratives

L’inventaire

La pièceÉtatOù elle vitCe qu’elle fait
aip_signing — la signature Ed25519H2_membrane · S3livrébackend/app/services/aip_signing.py (115 L), routeur monté à backend/app/main.py:1869Signe et vérifie vraiment des engagements avec la cryptographie Ed25519 standard.Importe cryptography.hazmat.primitives.asymmetric.ed25519 et appelle sk.sign(payload) (l.90) / pk.verify(...) (l.107). Aucun mock. register_router("app.routers.aip_router", ...) à main.py:1869. 4 tests dans backend/tests/services/test_aip_signing.py.
armure_15d — l'empreinte d'armure (HMAC-SHA256)H1_spine · S1livrébackend/app/services/armure_15d.py (325 L, 15 441 octets)Calcule l'empreinte scellée des 15 dimensions sans jamais révéler leur contenu ; c'est le cœur cryptographique du domaine.Vrai schéma d'engagement : hmac.new(kb, _V2_DOMAIN + canonical, hashlib.sha256) (l.162), séparation de domaine _V2_DOMAIN = b"ARMURE15D\x00v2\x00hmac\x00" (l.89), aveuglement (l.161), comparaison à temps constant hmac.compare_digest (l.237). Importé par armure.py, verite.py, aip_signing.py.
Routeur Armure — le pont JS→PythonH2_membrane · S1livrébackend/app/routers/armure.py (166 L), monté à main.py:1491Reçoit du frontend les 15 forces calculées et en fabrique l'empreinte du membre. 2 routes.2 décorateurs @router. comptés. register_router("app.routers.armure", "", ["Armure 15D"], "armure") à main.py:1491. Protégé par Depends(get_current_user).
dimensions_15 — le schéma canoniqueH1_spine · S1livrébackend/app/services/dimensions_15.py:25La table de référence des 15 dimensions (sovereignty, temporal… core_999) avec triades et organes, plus une garde d'intégrité.Importé réellement par armure_15d.py:209 (from app.services.dimensions_15 import DIMENSIONS_15, TRIADS). Fonction is_valid_schema() l.73.
armure_store — la mémoire des empreintesH2_membrane · S1livrébackend/app/services/armure_store.py (64 L, 2 488 octets)Garde la dernière empreinte de chaque membre pour que la signature scelle du réel plutôt qu'un bouchon._LATEST: Dict[str, Dict[str, Any]] = {} l.26 — dictionnaire EN MÉMOIRE VIVE, plafond _MAX_MEMBERS = 5000 l.27, éviction LRU l.36. Lu par aip_signing.py:75. Son propre docstring : « La persistance DB reste un câblage ultérieur ».
Routeur Antenna — le dNFT 15D des 144 000 âmesH4_mapping_projection · S1livrébackend/app/routers/antenna.py (1 118 L), monté à main.py:1655 ; DIMENSIONS_15 l.137Frappe et fragmente des jetons d'âme en 15 morceaux, un par dimension.23 décorateurs @router. comptés. Monté main.py:1655. Authentifié (Depends(get_current_user) dès l.230). 3 tests dans backend/tests/routers/test_antenna_router_security.py.
dimensional-armor.js — l'armure côté écranH7_frontstage_external · S0livréfrontend/js/dimensional-armor.js (626 L), chargé par frontend/js/governance-init.js:461Affiche l'état des 15 dimensions et fait des contrôles de santé (uptime, latence, solde…).Ligne de chargement explicite '/js/dimensional-armor.js' à governance-init.js:461. Respecte les 4 patrons : singleton l.34, MALLEABILITY_CONTRACT l.544, ORCHESTRATOR_GUIDE l.570.
quantum-armor-nft-seeder.js — les graines NFTH7_frontstage_external · S0livréfrontend/js/quantum-armor-nft-seeder.js (1 666 L), chargé à governance-init.js:462Lit l'armure affichée et en dérive des graines de jetons souverains.Ligne de chargement '/js/quantum-armor-nft-seeder.js' à governance-init.js:462, avec le commentaire « lit armure → seeder.seed.sovereign ».
Orchestrateur quantique Q1–Q5H6_domain_vertical · S3livrébackend/app/modules/quantum/ (13 fichiers .py), routeur backend/app/routers/quantum.py (676 L) monté à main.py:1807Cinq modules d'aide à la décision (équité, multi-objectif, scénarios, incertitude, contraintes). Ils tournent — mais en calcul classique.quantum.py:28 from app.modules.quantum.quantum_orchestrator import ... = import réel. 14 endpoints comptés. MAIS q1_fairness_explorer.py importe random (l.23) et math (l.24) — AUCUN qiskit, cirq ou pennylane dans tout le dossier. 7 tests dans test_quantum_orchestrator.py.
Pont CHE·NU quantiqueH5_specialized_backstage · S3livréhf-atom-tools/atom_canon/bridges/chenu_quantum_bridge.py (473 L), routeur backend/app/routers/canon_quantum_bridge_router.py (240 L) monté à main.py:189218 endpoints qui prétendent router vers l'écosystème externe CHE·NU. Ils répondent — avec des réponses fabriquées.Import réel à canon_quantum_bridge_router.py:14. 16 fonctions de routage, 18 endpoints. Mode mock par défaut : _resolve_mock_flag l.46-49. 10 tests dans test_canon_quantum_bridge_router.py.
CHENU_LIVE_MODE — l'interrupteur qui ne branche rienH5_specialized_backstage · S3déclaratifhf-atom-tools/atom_canon/bridges/chenu_quantum_bridge.py:43 (seul lecteur en production)L'interrupteur censé passer du simulé au réel. Le basculer remplace des maquettes par des trous.Lu par EXACTEMENT 1 fichier de production (l.43) ; les 8 autres occurrences sont des tests. Mode « live » renvoie "phase": "P1_TODO" (l.76, l.155) et "real_chenu_routing_TODO" (l.196). AUCUN import httpx/requests dans le fichier.
CHENU_API_URL / CHENU_API_KEYH5_specialized_backstage · S3déclaratifnulle part dans le code PythonLes réglages de connexion au service externe. Les configurer ne fait rien du tout.grep -rn "CHENU_API_URL|CHENU_API_KEY" --include="*.py" backend/ hf-atom-tools/ retourne ZÉRO ligne. Aucun fichier ne les lit.
Crypto post-quantique (Dilithium / Falcon)H5_specialized_backstage · S3câblé, en attentebackend/security/post_quantum/crypto.py (338 L) + backend/security/models.py:306Le module censé signer contre les futurs ordinateurs quantiques. Il ne signe rien de réel et personne ne l'appelle.Clés fabriquées en texte : public_key = f"pub_{algorithm.value}_{key_id[:8]}" (crypto.py:64). Signature = mock_pq_sign (models.py:306) qui LÈVE une exception si ATOM_ALLOW_MOCK_PQ_CRYPTO n'est pas mis (l.312-316). ORPHELIN : aucun fichier de backend/app/ ne l'importe. 5 tests seulement.
Dilithium dans la signature réelleH2_membrane · S3déclaratifbackend/app/services/aip_signing.py:4 (docstring)L'hybride Ed25519+Dilithium annoncé n'existe qu'en commentaire.Docstring l.4 : « Phase 1+ : Hybrid Ed25519+Dilithium2 ». Le code refuse tout autre algorithme : if sig.algorithm != "ed25519": return False # phase 0 only ed25519 (l.104-105).
confirmation-armor.jsH7_frontstage_external · S0câblé, en attentefrontend/js/confirmation-armor.js (1 404 L)Un gros module d'armure de confirmation, entièrement écrit, que rien ne charge.Absent des deux tableaux de chargement de governance-init.js (grep "armor.*\.js'" ne retourne que les lignes 461 et 462). N'apparaît ailleurs que comme chaîne de caractères dans frontend/js/spiral-router.js:862.
loteria-armor-bridge.jsH7_frontstage_external · S0câblé, en attentefrontend/js/loteria-armor-bridge.js (119 L)Petit pont entre le jeu de progression et l'armure. Jamais chargé.Absent des tableaux de chargement de governance-init.js. Cité uniquement en commentaire à frontend/js/loteria-bridge.js:12 et dans une liste emits l.114.
armor-economy-bridge.jsH7_frontstage_external · S2livréfrontend/js/armor-economy-bridge.js (659 L), governance-init.js:875Relie l'armure à l'économie. Chargé, mais en différé (liste non bloquante).Présent dans la liste de chargement paresseux à governance-init.js:875 ('armor-economy-bridge', 'sovereignty-engagement'). Référencé aussi par societal-systems-map.js:397 et vps-topology.js:134.
spiderweb.py — une DEUXIÈME table de 15 dimensionsH6_domain_vertical · S3livrébackend/app/routers/spiderweb.py:103, monté à main.py:1977Un routeur vivant qui utilise 15 dimensions portant des noms totalement différents de ceux de l'armure.l.103-107 : ["Physical", "Emotional", "Mental", "Spiritual", "Creative", "Social", "Financial", "Professional", "Educational", "Health", "Environmental", "Governance", "Cultural", "Technological", "Cosmic"] — zéro nom en commun avec antenna.py:137. Utilisé en dur l.479-480, 563-565.
zama_service.py — pas de chiffrement homomorpheH6_domain_vertical · S4câblé, en attentebackend/app/services/zama_service.py (171 L)Malgré le nom, ce n'est PAS du chiffrement Zama/FHE : ce sont des avatars et des scènes 3D.Les 8 fonctions du fichier sont get_avatar, update_avatar, create_scene, get_scene, list_scenes, update_scene, add_marker, get_markers. Aucun fhevm/TFHE. Seule référence hors du fichier : backend/app/core/master_hash_registry.py:496 (un registre, pas un appelant).
docs/zama-armorH0_origin · S4déclaratifdocs/zama-armor/ (2 fichiers)Une spécification et une maquette d'écran. Aucun code exécutable.Contenu complet du dossier : ZAMA_IGNITION_MODULE_SPEC.md + ZamaIgnitionStoryboard.jsx (du JSX, interdit par la règle vanilla du dépôt, donc non exécutable ici).
FractalExpansion.js — la source des forces D1..D15H1_spine · S1livrécore/FractalExpansion.js:137 et :166-176C'est lui qui calcule la force de chaque dimension, à partir de l'harmonie globale et du nombre d'or._deriveArmorVariables l.166 : boucle for (var d = 1; d <= DIMENSIONS; d++) produisant {strength, frequency, coherence} avec Math.pow(PHI_INV, ...) l.172. Publié sur le bus l.151-156 (fractal.agent.aspirated).

Les chiffres, mesurés

Ce qu’on compteLa mesureComment
Tables « 15 dimensions » incompatibles3 vocabulaires différents (4 emplacements)annoncé ailleurs : CLAUDE.md et la mémoire annoncent « 15 dims en antenna.py::DIMENSIONS_15 » comme s'il n'y en avait qu'unegrep -rn "DIMENSIONS_15" backend/ → antenna.py:137 et services/dimensions_15.py:25 sont IDENTIQUES (sovereignty…core_999) ; spiderweb.py:103 est tout autre (Physical, Emotional…) ; frontend/js/dimensional-armor.js:50-64 en donne un troisième (Électrique, Physique, Réseau…)
Fichiers lisant CHENU_LIVE_MODE en production1grep -rn "CHENU_LIVE_MODE" --include="*.py" → 10 occurrences dont 9 dans des tests ou CLAUDE.md ; seul hf-atom-tools/atom_canon/bridges/chenu_quantum_bridge.py:43 le lit en production
Fichiers lisant CHENU_API_URL ou CHENU_API_KEY0grep -rn "CHENU_API_URL|CHENU_API_KEY" --include="*.py" backend/ hf-atom-tools/ → aucun résultat
Bibliothèques de calcul quantique réel0annoncé ailleurs : Le nom « Quantum Entangler », « Q1-Q5 orchestrator », « quantum interference » laisse croire à du calcul quantiquegrep "qiskit|cirq|pennylane" dans backend/app/modules/quantum/ → rien. q1_fairness_explorer.py n'importe que `random` (l.23) et `math` (l.24)
Signatures post-quantiques réelles (Dilithium/Falcon)0annoncé ailleurs : CLAUDE.md annonce « post-quantum crypto sont livrés dans le repo AT·OM »backend/security/post_quantum/crypto.py:64 fabrique les clés par f-string ; models.py:306 `mock_pq_sign` lève une exception sauf si ATOM_ALLOW_MOCK_PQ_CRYPTO=true
Signatures cryptographiques VRAIES et vérifiables2 mécanismesEd25519 réel via la lib `cryptography` (aip_signing.py:90,107) + HMAC-SHA256 avec séparation de domaine et aveuglement (armure_15d.py:162)
Endpoints du domaine montés dans main.py57grep -c "@router." → antenna.py 23 + canon_quantum_bridge_router.py 18 + quantum.py 14 + armure.py 2. Les 4 routeurs sont montés (main.py:1655, 1892, 1807, 1491)
Persistance des empreintes d'armure0 (mémoire vive uniquement)backend/app/services/armure_store.py:26 `_LATEST: Dict = {}`, plafond 5000 (l.27) — tout est perdu au redémarrage du serveur
Fichiers JS d'armure écrits vs chargés5 écrits (4 574 L), 3 chargéswc -l sur les 5 fichiers *armor*.js ; governance-init.js charge dimensional-armor.js (l.461), quantum-armor-nft-seeder.js (l.462), armor-economy-bridge.js (l.875, différé). confirmation-armor.js (1 404 L) et loteria-armor-bridge.js (119 L) ne sont dans aucune liste
Tests du domaine39 fonctions `def test_`grep -c "def test_" → test_quantum_qrnd15_14_coverage 10, test_canon_quantum_bridge_router 10, test_quantum_orchestrator 7, test_post_quantum_crypto 5, test_aip_signing 4, test_antenna_router_security 3. Aucun fichier de test dédié à armure_15d.py
Fichiers .py sous backend/app/modules/ (staging CHE·NU)113annoncé ailleurs : La spec TS annonce 35 modules / 54 400+ lignes pour CHE·NU v2.7.0find backend/app/modules -name "*.py" | wc -l ; dont 13 dans modules/quantum/

Ce sur quoi vous pouvez compter

Le vrai trésor du domaine, c'est la cryptographie classique — et elle est solide. aip_signing.py signe et vérifie avec Ed25519 par la bibliothèque cryptography standard : ce sont de vraies signatures, pas des imitations. armure_15d.py est encore mieux fait : c'est un schéma d'engagement en HMAC-SHA256 avec séparation de domaine (ARMURE15D\0v2\0hmac\0), aveuglement optionnel, et comparaison à temps constant contre les attaques temporelles. Quelqu'un qui connaissait la cryptographie a écrit ce fichier.

Le pont frontend→backend fonctionne de bout en bout et il est authentifié : FractalExpansion.js calcule les 15 forces, POST /api/v2/armure/dimensions les ingère derrière Depends(get_current_user), l'empreinte est calculée puis relue par la signature. La discipline du dépôt est respectée : le routeur ne renvoie jamais le contenu des dimensions, seulement l'empreinte et des comptes.

Les quatre routeurs du domaine sont réellement montés dans main.py (lignes 1491, 1655, 1807, 1892) — 57 endpoints qui répondent. Et le fichier services/dimensions_15.py porte une garde d'intégrité (is_valid_schema()) qui refuse un schéma abîmé.

Ce qui manque

1. Il n'y a pas une armure à 15 dimensions, il y en a trois qui ne se parlent pas. antenna.py:137 et services/dimensions_15.py:25 disent sovereignty/temporal/territorial… spiderweb.py:103 (routeur vivant, monté) dit Physical/Emotional/Mental… frontend/js/dimensional-armor.js:50 dit Électrique/Physique/Réseau… Zéro nom en commun entre les trois. Le fichier canonique l'avoue d'ailleurs lui-même dans son en-tête : « Toute divergence entre les deux est un bug ». Il n'a simplement pas vu la troisième.

2. Le post-quantique n'existe pas. Zéro signature Dilithium ou Falcon réelle. backend/security/post_quantum/crypto.py fabrique ses clés avec une f-string (f"pub_{algorithm.value}_...") et sa fonction de signature *refuse de s'exécuter* sans une variable d'environnement de test. En plus, ce module est complètement orphelin : aucun fichier de backend/app/ ne l'importe. C'est 338 lignes qui ne servent à rien aujourd'hui.

3. Le « quantique » est du calcul classique. Les modules Q1–Q5 tournent vraiment, mais ils importent random et math. Aucun qiskit, cirq ou pennylane nulle part. Ce sont des heuristiques de décision honnêtes habillées d'un vocabulaire quantique.

4. L'interrupteur CHE·NU est un leurre. Basculer CHENU_LIVE_MODE=true ne connecte rien : il n'y a aucun client HTTP dans le pont, et le mode « live » renvoie littéralement "phase": "P1_TODO". Pire, CHENU_API_URL et CHENU_API_KEY ne sont lues par aucun fichier — les configurer est sans effet. Le mode simulé donne aujourd'hui de meilleures réponses que le mode « réel ».

5. Les empreintes d'armure s'évaporent au redémarrage. armure_store.py est un dictionnaire en mémoire vive plafonné à 5 000 membres avec éviction. Après un redémarrage du serveur, toute signature retombe silencieusement sur le bouchon sha256("armure-15d:"+id) — sans erreur, sans avertissement. C'est une dégradation invisible.

6. Le cœur cryptographique n'a pas de tests. armure_15d.py, le fichier le plus sensible du domaine (325 lignes de HMAC), n'a aucun fichier de test dédié. Les 39 tests du domaine couvrent les périphéries.

7. 1 523 lignes de JS écrites pour rien. confirmation-armor.js (1 404 L) et loteria-armor-bridge.js (119 L) ne sont chargés par aucune page.

Se tient avec : Économie & UR COIN — armor-economy-bridge.js relie l'armure à l'économie ; la dimension 7 « financial » et la dimension 5 « Valeur » (deux tables différentes) prétendent toutes deux gouverner la valeur · Hedera / blockchain — antenna.py frappe les dNFT d'âme, services/hedera/mint-armor.js, dimension 12 « Blockchain » ; même pattern mock-by-default via HEDERA_LIVE_MODE · Identité & authentification — tout le domaine dépend de app.core.auth.get_current_user ; l'armure EST la fiche d'identité scellée du membre · Gouvernance AIP — aip_signing.py est le consommateur principal de l'empreinte d'armure ; le routeur aip_router est monté à main.py:1869 · Souveraineté (S3) — verite.py importe armure_15d ; la dimension 11 « Souveraineté » et la dimension 1 « sovereignty » se recouvrent sans être reliées · Canon η / ACMI — hf-atom-tools/atom_canon/bridges/ héberge le pont CHE·NU ; le hub fractal_hub.py:71 lit entangle_result · Spiderweb / défense — spiderweb.py porte la deuxième table de 15 et une couche de 9 organes de protection ; c'est le voisin le plus proche et le plus divergent · Frontend / governance-init.js — l'unique porte de chargement des modules JS d'armure (lignes 461, 462, 875)

Domaine 6 · état : partiel

Les portefeuilles et la trésorerie (UR COIN, Crédits, Hedera, paiements)

C'est la partie du système qui tient l'argent : une monnaie interne appelée « Crédits », une monnaie-jeton appelée « UR COIN » censée vivre sur la chaîne Hedera, et un pont entre les deux. Aujourd'hui les Crédits vivent vraiment dans une base de données, mais UR COIN ne sort pas de la machine — la trousse logicielle Hedera n'est même pas installée.

17 livrées · 6 en attente · 2 déclaratives

L’inventaire

La pièceÉtatOù elle vitCe qu’elle fait
TreasuryService — la banque centrale des CréditsH3_vital_loop · S2livrébackend/app/services/treasury_service.py (1 965 lignes)Émet, brûle, récompense, dépense, transfère les Crédits ; tient les budgets et le pont Crédits↔UR COIN.Appelé par 18 fichiers (grep 'get_treasury()'), dont backend/app/routers/economy_engine.py:312 qui monte 8 routes REST ; register_router('app.routers.economy_engine') dans main.py:1922
Les tables de la trésorerie (où vit vraiment un solde en Crédits)H1_spine · S2livrébackend/app/models/treasury.py:46 (treasury_wallets), :181 (treasury_transactions) ; backend/app/models/treasury_state.py:44/131/185 (treasury_master, treasury_budgets, treasury_bridge_pool)Cinq tables PostgreSQL : le portefeuille double de chaque personne, le grand livre des transactions, le compte maître, les budgets et la réserve du pont.Migrations réelles : backend/alembic/versions/v80_023_treasury_wallets_transactions.py et v80_024_treasury_master_budgets_bridge.py
Chemin async DB-first (les méthodes a*)H1_spine · S2livrébackend/app/services/treasury_service.py:1022-1945 (amint_credits, aburn_credits, areward_credits, aspend_credits, atransfer_credits, abridge_*, astake_coin, aget_dashboard…)La vraie version : chaque mouvement d'argent s'écrit en base, avec verrou de ligne, double écriture et refus si la base est absente.Toutes les routes /api/v2/economy-engine/treasury/* appellent ces méthodes (economy_engine.py:312, 333, 351, 381…) et _require_treasury_db(db) échoue si pas de base
Chemin sync-RAM legacy (les méthodes sans a)H1_spine · S2câblé, en attentebackend/app/services/treasury_service.py:192-1020 (collect_revenue, disburse_credits, reward_credits, get_dashboard…)L'ancienne version qui garde l'argent en mémoire vive : elle repart à zéro à chaque redémarrage du serveur.Décision D23 inscrite en tête de fichier (treasury_service.py:35-48) : à retirer, 6 appelants live restants (checkout_system, grand_exchange, marketplace_3d, merchant_service, ristourne_policy_service, trinity_palace_service). Aucune route REST ne l'utilise plus.
Garde-fou d'émission des Crédits (gouvernance + doctrine de réserve)H2_membrane · S3livrébackend/app/services/treasury_service.py:884 (_acheck_credit_mint_governance) et :940 (_check_credit_mint_reserve_doctrine)Avant toute création de Crédits : si le montant dépasse le seuil, il faut une approbation humaine ; si le module de gouvernance ou la doctrine de réserve est injoignable, l'émission est REFUSÉE (fail-close).amint_credits l'appelle en premier (ligne 1290) avant toute écriture ; le refus renvoie requires_checkpoint=True
Routeur Economy Engine — trésorerie (8 routes)H7_frontstage_external · S2livrébackend/app/routers/economy_engine.py:308-500 ; monté dans main.py:1922Tableau de bord, consultation de son portefeuille, création (admin), transfert, pont Crédits↔UR COIN, mise en jeu et retrait.register_router('app.routers.economy_engine', …, 'economy_engine') ligne 1922 de main.py ; /treasury/mint est protégé par Depends(require_admin) ligne 344
Routeur Portefeuille (13 routes) et sous-portefeuillesH7_frontstage_external · S1livrébackend/app/routers/wallet_router.py (272 lignes, prefix /api/v2/wallet) ; monté dans main.py:2013Vue d'ensemble d'un portefeuille (soldes, NFT, redevances, parts, ristourne), historique, transferts, et des sous-portefeuilles par projet avec budget.13 décorateurs @router mesurés ; test de sécurité présent : backend/tests/routers/test_wallet_router_security.py
WalletPortfolio — l'agrégateur de patrimoineH4_mapping_projection · S1livrébackend/app/services/wallet_portfolio.py (585 lignes) + wallet_portfolio_persistence.py (382 lignes)Rassemble en une seule vue les Crédits, l'UR COIN, les NFT, les œuvres, les redevances, les parts et les commandes d'une personne.Appelé par wallet_router.py:30 et par treasury_canon_router.py:35 (portfolio_scope_view) ; test backend/tests/unit/test_wallet_portfolio_db_contract.py
HederaMainnetBridge — le seul chemin qui peut vraiment frapper de l'UR COINH2_membrane · S2câblé, en attentebackend/app/services/hedera_mainnet_bridge.py:166 (mint_urcoin), :111 (_ensure_client)Construit et signe une vraie transaction de frappe sur Hedera, avec bilan honnête (refus si montant ≤ 0) et plafond de 100 UR par transaction.Le code est correct et testé (backend/tests/test_hedera_mainnet_bridge.py, tests/unit/test_hedera_mainnet_bridge_canon.py) MAIS _ensure_client importe hiero_sdk_python, absent des 4 fichiers requirements — à l'exécution il lève RuntimeError et mint_urcoin retourne status=FAILED.
HederaService — le grand service Hedera en mode simulationH2_membrane · S2câblé, en attentebackend/app/services/hedera_service.py (1 177 lignes), simulation forcée ligne 168Jetons, comptes, journal immuable HCS, tableaux de bord économiques. 18 embranchements « si mode simulation » qui renvoient de fausses réponses.hedera_service.py:49-52 — l'import de la trousse hedera échoue → HEDERA_SDK_AVAILABLE=False → ligne 168 self._simulation_mode = True, en permanence. Les routes /hedera/* l'utilisent quand même (14 endpoints montés main.py:1757).
Routes /hedera (14 endpoints, dont frappe et destruction)H7_frontstage_external · S2livrébackend/app/api/routes/hedera_routes.py (844 lignes) ; monté dans main.py:1757Frapper, brûler, transférer de l'UR COIN, créer un compte, consulter un solde, convertir.14 @router mesurés ; /token/mint (ligne 241) est protégé par une signature HMAC (require_hedera_admin_signature, ligne 39) qui renvoie 404 si HEDERA_ADMIN_SECRET est absent — donc fermé par défaut.
SovereignBridgeService — abonnement payé → UR frappéH3_vital_loop · S2livrébackend/app/services/sovereign_bridge_service.py (912 lignes), _mint_ur_via_canon_bridge ligne 223, process_subscription ligne 285Quand quelqu'un paie un abonnement, calcule le montant d'UR à lui donner et demande la frappe.Appelé par backend/app/routers/payments.py:474 (tâche de fond du webhook Stripe) et par backend/app/services/pending_mint_retry.py:60 ; testé dans tests/unit/test_sovereign_bridge_service.py
Le commutateur HEDERA_LIVE_MODEH2_membrane · S3livrésovereign_bridge_service.py:244, babel/babel_fractal_treasury_consumer.py:252, mission_nft_service.py:405 ; valeur par défaut dans .env.example:182 = falseFaux par défaut : ces 3 chemins renvoient un faux résultat (tx_id 'mock_sov_…', status 'mock_by_default') sans jamais toucher la chaîne._env_flag('HEDERA_LIVE_MODE', default=False) puis return self._mock_bridge_result(...) — sovereign_bridge_service.py:244-246
File d'attente des frappes ratées (pending_mints)H3_vital_loop · S2livrébackend/app/services/pending_mint_retry.py (worker) + backend/app/models/stripe_bridge.py (table)Si la frappe d'UR échoue après un paiement, la demande est mise en file et réessayée automatiquement, 9 lignes par battement, avec un maximum de tentatives.Ordonnanceur démarré dans main.py:390 et :877 (get_pending_mint_scheduler) ; 3 routes admin exposées payments.py:773/800/820
Routeur Paiements Stripe (9 routes)H7_frontstage_external · S2livrébackend/app/routers/payments.py (848 lignes, prefix /api/v2/payments) ; monté main.py:1344Session de paiement, statut d'abonnement, annulation, portail client, webhook Stripe, et 3 routes admin sur la file des frappes.9 @router mesurés ; stripe>=8.0.0 est bien déclaré (requirements.txt:72) — contrairement à Hedera. Le webhook refuse de fonctionner sans STRIPE_WEBHOOK_SECRET (ligne 407).
Garde d'émission G4 (θ = ce qu'on capte borne ce qu'on émet)H2_membrane · S9câblé, en attentebackend/app/services/babel/g4_emission_guard.py (181 lignes)Interdit d'émettre plus d'UR que ce que le système a réellement capté sur 24 h ; si captation = 0, émission = 0.Un seul appelant : babel_fractal_treasury_consumer.py:478-479. Le fichier dit lui-même en tête (ligne 22) : « État inerte préservé : G4 est un GARDE, pas un armement… le battement ne produit pas d'énergie ».
governed_reward — le chemin de frappe gouverné partagéH2_membrane · S2livrébackend/app/services/babel/governed_mint.py (82 lignes)Force les trois producteurs d'énergie (temple, forge, fractal) à passer par le grand livre en base au lieu du pot en mémoire vive.Importé par les consommateurs de trésorerie Babel, eux-mêmes abonnés au bus au démarrage (main.py:605-618, 665-669, 700-712)
Doctrine de souveraineté d'UR (pas d'ancrage sur une monnaie fiat)H0_origin · S3livrébackend/app/services/ur_sovereignty_doctrine.py (185 lignes), UR_PEGGED_TO_FIAT=False ligne 41, BRIDGE_IS_PERMANENT=False ligne 42Deux règles de fer : UR n'est indexé sur aucune devise, et le pont UR↔fiat est un échafaudage transitoire conçu pour disparaître. Aucune fonction ici ne bouge d'argent.Importée par pay/core.py:25 et pay/transition_rate.py:32 ; validate_rate_stance refuse un taux non sourcé
AT·OM Pay — l'orchestrateur de paiement souverainH5_specialized_backstage · S0câblé, en attentebackend/app/services/pay/ (7 fichiers, 1 068 lignes : core, bordereau, card, reconcile, transition_rate, money_adapter_registry)Reçoit une intention de paiement, produit un devis et un bordereau comptable équilibré. Le mode réel est refusé volontairement (KYC/AML + accord du propriétaire).AUCUN routeur ne l'importe (grep money_adapter_registry|pay.core dans app/routers/ et app/api/ = 0 résultat). Seul appelant hors du dossier : liquidity_bridge.py:53 et :305. Testé par backend/tests/test_atom_pay.py.
Routeur Treasury Canon (7 routes de tarification canonique)H4_mapping_projection · S2livrébackend/app/routers/treasury_canon_router.py (131 lignes, prefix /api/v2/treasury/canon) ; monté main.py:1606Calcule un prix, un partage de redevances, une modulation de jetons selon le « scope » (individuel/communautaire/civique).7 @router mesurés (correspond à la promesse de son entête) ; l'ancrage Hedera y est en mode faux par construction (tokenomics_hedera_bridge.py = simple hachage SHA-256, hedera_tx_id = 'MOCK_TX_…')
Routeur Pont Souverain (8 routes, toutes en lecture)H7_frontstage_external · S3livrébackend/app/routers/sovereign_bridge.py (288 lignes, prefix /api/v2/sovereign-bridge) ; monté main.py:1792Consultation seulement : statut, modules, types d'événements, phases de justice, paliers de restitution, statistiques.Les 8 décorateurs sont des @router.get — aucun POST, donc aucune mutation d'argent possible par cette porte. Test tests/routers/test_sovereign_bridge_auth_contract.py
ur_engine et la table ur_balances — un SECOND registre d'URH1_spine · S2livrébackend/app/services/ur_engine.py (408 lignes), get_balance ligne 266 ; table ur_balances créée par alembic/versions/v80_018_ur_ledger.pyUn compte d'UR par personne, séparé du coin_balance du portefeuille de trésorerie.Appelé par 10 fichiers dont wallet_portfolio.py:174 et routers/economy.py. Rien ne réconcilie ur_balances avec treasury_wallets.coin_balance — deux vérités possibles pour le même UR.
Portefeuille et flux Hedera côté navigateurH7_frontstage_external · S1câblé, en attentefrontend/js/rosetta-wallet.js (1 659 lignes), frontend/js/hedera-flow.js (1 847 lignes)L'interface de portefeuille et la visualisation des flux Hedera pour l'usager.Aucun des deux n'est chargé par frontend/js/governance-init.js (seul /js/raa-treasury-loop.js y figure, ligne 601). rosetta-wallet.js n'est référencé que par une page de test et un fichier de tests unitaires.
Dossier Hedera en JavaScript (outils de frappe hors backend)H5_specialized_backstage · S2déclaratifservices/hedera/ (12 fichiers : create-token.js, mint-armor.js, mintArmorToken.js, sync-engine.js…)Scripts autonomes en Node pour créer le jeton UR et frapper des NFT d'armure.Aucun code Python du backend ne les appelle ; ils lisent leur propre .env (services/hedera/config.js:10) et ne partagent ni la gouvernance, ni le plafond quotidien, ni le grand livre.
Doublon backend/services/tokenomics_hedera_bridge.pyH5_specialized_backstage · S2déclaratifbackend/services/tokenomics_hedera_bridge.py (229 lignes) — à ne pas confondre avec backend/app/services/tokenomics_hedera_bridge.py (50 lignes)Une seconde version du pont d'ancrage, avec sa propre variable HEDERA_SIMULATION_MODE.Aucun import de production : seul backend/tests/unit/test_tokenomics_hedera_bridge_hcs.py:17 le charge par chemin de fichier. Le routeur, lui, importe la version app/ (treasury_canon_router.py:33).

Les chiffres, mesurés

Ce qu’on compteLa mesureComment
Fichiers de service du domaine argent (trésorerie, portefeuilles, Hedera, pont souverain, paie)13 fichiers, ~8 700 lignes avec leurs routeswc -l sur backend/app/services/{treasury_service,treasury_models,sovereign_bridge_service,hedera_service,hedera_mainnet_bridge,tokenomics_hedera_bridge,wallet_portfolio,wallet_portfolio_persistence,ur_sovereignty_doctrine,fractal_seed_treasury_consumer}.py + 5 routeurs
Endpoints REST « argent » réellement montés dans main.py62 endpoints sur 7 routeursgrep -c '@router' par fichier : economy_engine/treasury 8 + wallet_router 13 + treasury_canon_router 7 + api/routes/hedera_routes 14 + payments 9 + sovereign_bridge 8 + crop_circle_treasury_router 3 ; chacun confirmé par un register_router dans backend/app/main.py
Fichiers de production qui lisent HEDERA_LIVE_MODE3grep -rn HEDERA_LIVE_MODE --include=*.py backend/ → sovereign_bridge_service.py:244, babel/babel_fractal_treasury_consumer.py:252, mission_nft_service.py:405 (le reste = tests et un commentaire dans core/bus_acl.py)
Trousse logicielle Hedera déclarée comme dépendance0annoncé ailleurs : hedera_service.py:24 dit « requires: pip install hedera-sdk-py » et hedera_mainnet_bridge.py:112 importe hiero_sdk_python — deux trousses différentes, aucune installéegrep -ciE 'hedera|hiero' sur requirements.txt, requirements-full.txt, requirements-test.txt, requirements_unified.txt → 0 partout ; aucun 'hiero-sdk-python' ni 'hedera-sdk-py' dans tout le dépôt
Chemins de code capables de créer de la monnaie (mint)4 chemins distinctsamint_credits (treasury_service.py:1270), areward_credits via governed_mint.py, mint_urcoin (hedera_mainnet_bridge.py:166), et _mint_ur_via_canon_bridge (sovereign_bridge_service.py:223)
Endroits où vit un solde4 tables + 2 caches en mémoiretreasury_wallets + treasury_transactions (alembic/versions/v80_023), treasury_master + treasury_budgets + treasury_bridge_pool (v80_024), ur_balances (v80_018_ur_ledger), plus les dictionnaires RAM TreasuryService._wallets et WalletPortfolio (PersistentDict)
Plafond d'émission quotidien des Crédits1 000 Crédits/jour ; réserve de départ 1 000 000treasury_service.py:137 _mint_rate_daily = Decimal('1000') ; treasury_service.py:113 _treasury_balance = Decimal('1000000') ; g4_emission_guard.py:41 MINT_URCOIN_DAILY_CAP = Decimal('1000')
Plafond de sécurité par transaction Hedera100 URhedera_mainnet_bridge.py:45 MAX_SAFE_AMOUNT = int(os.getenv('MAX_SAFE_AMOUNT','100')) — et MAX_SAFE_AMOUNT n'est PAS dans .env.example
Adaptateurs de rails monétaires prévus (AT·OM Pay)5 déclarés : 2 « partial », 3 « mock »backend/app/services/pay/money_adapter_registry.py:67-131 — atom_liquidity_bridge et canadian_banking en partial ; external_wallet_readonly, fiat_crypto_ramp, brokerage_readonly en mock
Sujets de bus liés à l'argent dans le catalogue central11grep -cE '^(TREASURY|HEDERA|WALLET|UR_|STRIPE|ECONOMY|PAYMENT)' backend/app/core/bus_topics.py → 11 (2 treasury.*, 5 hedera.*, 3 stripe.*, +1)
Fichiers de tests couvrant le domaine22 fichiers de test .pyfind backend/tests -iname '*treasury*' -o -iname '*wallet*' -o -iname '*hedera*' -o -iname '*sovereign_bridge*' -o -iname '*pay*' (fichiers .py seulement, .pyc exclus)

Ce sur quoi vous pouvez compter

Trois choses tiennent vraiment.

Un : les Crédits sont une vraie monnaie en base de données. Les cinq tables existent, les migrations existent (v80_023 et v80_024), chaque mouvement passe par une méthode async qui verrouille la ligne, écrit une transaction dans le grand livre et refuse de fonctionner si la base est absente. Ce n'est pas de la mémoire volatile.

Deux : la porte de création de monnaie est fermée à double tour. La route /treasury/mint exige un compte administrateur (economy_engine.py:344). Avant d'écrire quoi que ce soit, amint_credits consulte la gouvernance ET la doctrine de réserve, et si l'un des deux est injoignable, l'émission est REFUSÉE plutôt qu'autorisée (treasury_service.py:930-937 et 985-990). Le plafond quotidien est de 1 000 Crédits. La route /hedera/token/mint exige une signature cryptographique et renvoie 404 si le secret n'est pas configuré, donc elle est invisible par défaut.

Trois : la chaîne paiement → frappe ne perd rien. Le webhook Stripe répond vite, la frappe part en tâche de fond, et si elle rate, la demande est mise dans une file (pending_mints) qu'un ouvrier réessaie automatiquement au démarrage du serveur (main.py:390 et 877). L'usager a payé, son UR lui est dû, et le système s'en souvient.

Ce qui manque

Du plus bloquant au moins.

1. LA TROUSSE HEDERA N'EST PAS INSTALLÉE. Aucun des quatre fichiers requirements ne mentionne hedera ni hiero. Conséquence directe : hedera_service.py bascule en mode simulation dès le démarrage (ligne 168) et y reste, et hedera_mainnet_bridge._ensure_client() lève RuntimeError. Autrement dit, même en mettant HEDERA_LIVE_MODE=true, il ne se passera rien sur la chaîne. UR COIN, aujourd'hui, n'existe que dans notre base.

2. DEUX TROUSSES DIFFÉRENTES, TROIS NOMS DE JETON. hedera_service.py importe hedera (l'ancienne, Java) ; hedera_mainnet_bridge.py importe hiero_sdk_python (la nouvelle). Pire, dans le même fichier : _ensure_client utilise hiero_sdk_python mais get_balance (ligne 258) importe from hedera import AccountBalanceQuery — cette fonction ne peut pas marcher, quelle que soit la trousse installée. Côté nom du jeton : le pont lit UR_COIN_TOKEN_ID, le service lit HEDERA_UR_TOKEN_ID, et .env.example ne déclare ni l'un ni l'autre — il déclare HEDERA_TOKEN_ID. Trois noms pour la même chose.

3. VARIABLES MANQUANTES DANS .env.example. UR_COIN_TOKEN_ID, HEDERA_ADMIN_SECRET et MAX_SAFE_AMOUNT n'y figurent pas. Quelqu'un qui installe le système en suivant le fichier d'exemple ne peut ni frapper (jeton inconnu) ni ouvrir les routes admin (404 permanent).

4. DEUX REGISTRES D'UR QUI NE SE PARLENT PAS. La table ur_balances (ur_engine.py) et le champ coin_balance de treasury_wallets tiennent tous deux « l'UR d'une personne ». Rien dans le code ne les réconcilie. Le portefeuille affiché à l'usager (wallet_portfolio.py:169-196) lit l'UR chez ur_engine et les Crédits chez treasury — et pour les Crédits il appelle get_user_balance (treasury_service.py:754) qui est la version MÉMOIRE VIVE, celle que la décision D23 déclare morte. Le solde affiché à l'usager risque donc d'être 0 alors que la base dit autre chose.

5. LE MOTEUR D'ÉMISSION EST DÉSARMÉ VOLONTAIREMENT. Le garde G4 dit lui-même en entête (g4_emission_guard.py:22) : « État inerte préservé… le battement ne produit pas d'énergie ». C'est un choix de prudence, pas un bogue — mais il faut le savoir : l'économie ne se met pas en marche toute seule.

6. AT·OM PAY N'A PAS DE PORTE. 1 068 lignes correctes et testées dans backend/app/services/pay/, avec cinq rails monétaires décrits, et zéro routeur qui les expose. C'est un beau moteur dans une caisse.

7. LE PORTEFEUILLE CÔTÉ NAVIGATEUR N'EST PAS BRANCHÉ. rosetta-wallet.js (1 659 lignes) et hedera-flow.js (1 847 lignes) ne sont pas dans la liste de chargement de governance-init.js. L'usager ne les voit jamais.

8. SIX APPELANTS ENCORE SUR LE CHEMIN MÉMOIRE VIVE. checkout_system, grand_exchange, marketplace_3d, merchant_service, ristourne_policy_service et trinity_palace_service utilisent encore les méthodes sync (liste dans treasury_service.py:38-44). Tout ce qu'ils comptabilisent disparaît au redémarrage.

Se tient avec : Gouvernance et points de contrôle humains (app/core/governance.py) — sans elle, aucune émission de Crédits n'est autorisée : c'est une dépendance dure, fail-close · Doctrine de réserve (app/services/reserve_doctrine.py) — deuxième verrou obligatoire avant toute expansion monétaire · Paiements externes Stripe (app/routers/payments.py) — la seule entrée d'argent réel dans le système aujourd'hui · Babel et l'énergie fractale (app/services/babel/) — les trois producteurs temple, forge et fractal qui alimentent la frappe gouvernée, actuellement désarmés au niveau G4 · Le bus d'événements interne (app/core/bus_topics.py) — 11 sujets argent (2 treasury, 5 hedera, 3 stripe) par lesquels le reste du système apprend qu'un mouvement a eu lieu · Souveraineté S3 (ur_sovereignty_doctrine, sovereign_bridge) — pose les règles que la trésorerie doit respecter : pas d'indexation sur une devise, pont transitoire · Paie et comptabilité (payroll_service, compta_router, pay/bordereau) — consommateurs en aval du grand livre de trésorerie · NFT et missions (mission_nft_service) — troisième lecteur de HEDERA_LIVE_MODE, même contrat mock-par-défaut

Domaine 7 · état : partiel

Les NFT et ce qui se frappe (minting, Hedera, tokens)

C'est la partie du système qui « frappe » des jetons : des NFT (pièces uniques : missions, connexions, antennes, paliers investisseurs) et l'UR COIN (monnaie du système). Sur le papier c'est branché sur la blockchain Hedera ; dans les faits, aucune des deux trousses Hedera nécessaires n'est installée, alors tout se frappe en simulation.

16 livrées · 4 en attente · 1 déclaratives

L’inventaire

La pièceÉtatOù elle vitCe qu’elle fait
hedera_service.py — le grand service HederaH2_membrane · S2livrébackend/app/services/hedera_service.py (1177 lignes)Sait créer un jeton, frapper, brûler, transférer, gérer des comptes et écrire un journal immuable HCS.Importé par 8 fichiers non-test (hedera_routes.py:24, hcs_audit_service.py:31, sovereign_bridge_service.py:32, mission_nft_service.py:416, nft_emission_service.py:165, tokenomics_service.py:181, ur_engine.py:371+396, blockchain_service.py:53). MAIS ligne 168 : _simulation_mode = not HEDERA_SDK_AVAILABLE, et la trousse hedera n'est déclarée dans aucun requirements → simulation permanente.
hedera_mainnet_bridge.py — le seul vrai chemin de frappe d'UR COINH2_membrane · S2livrébackend/app/services/hedera_mainnet_bridge.py (296 lignes), appel réel de frappe lignes 216-224Frappe de l'UR COIN avec garde-fous : refus si montant ≤ 0 ou > 100, bilan honnête, plafond de confiance η, journal append-only /tmp/atom_mints.jsonl.Importé par 4 fichiers non-test : hedera_routes.py:30, sovereign_bridge_service.py:35, fractal_seed_treasury_consumer.py:95, babel_fractal_treasury_consumer.py:211. C'est le SEUL endroit du backend qui construit un vrai TokenMintTransaction (ligne 218). Bloqué à l'init : ligne 129 lève RuntimeError si hiero_sdk_python absent — il l'est.
hedera_routes.py — l'API blockchainH7_frontstage_external · S2livrébackend/app/api/routes/hedera_routes.py (844 lignes, 13 points d'entrée)Frapper/brûler/transférer, consulter soldes et info jeton, créer comptes, demander conversion, tableaux de bord économiques.Monté dans backend/app/main.py:1757. POST /hedera/token/mint (ligne 241) exige une signature admin HMAC (X-Hedera-Admin-Signature) et passe par hedera_mainnet_bridge (ligne 259). 3 tests d'import dans tests/test_hedera_routes_import.py.
nft_emission — les NFT investisseurs (Bronze / Argent / Or)H6_domain_vertical · S2livrébackend/app/routers/nft_emission.py (166 l., 9 points d'entrée) + backend/app/services/nft_emission_service.py (409 l.)Frappe des NFT de palier à 1 / 100 / 10 000 UR, avec montée de palier, vérification, offre en circulation, liste par détenteur.Monté main.py:1955, préfixe /api/v2/nft. Le débit UR est réel et fail-closed (nft_emission_service.py:193 _debit_owner_for_nft via ur_engine.transfer_ur). ⚠️ MAIS la fonction _try_hedera_mint_nft (ligne 163) ne construit JAMAIS de transaction de frappe : elle écrit une ligne HCS puis renvoie soit sim_inv_mint_xxx, soit — même en mode live — pending_xxx (ligne 185). Aucun NFT n'arrive sur la chaîne.
nft_trinity — Souche / Semence / SentinelleH6_domain_vertical · S4livrébackend/app/routers/nft_trinity.py (318 lignes, 13 points d'entrée)Trois familles de NFT : identité (Souche), propagation (Semence), validation (Sentinelle), avec instructions, rappel, destruction et test de résonance.Monté main.py:1808. 9 tests dans tests/routers/test_nft_trinity_router.py. Stockage 100 % en mémoire vive : lignes 59-61 _souches, _semences, _sentinelles sont des dict Python nus — tout est perdu au redémarrage. Aucune trace de Hedera dans le fichier.
nft_visual — la fabrique d'images NFTH7_frontstage_external · S4déclaratifbackend/app/routers/nft_visual.py (304 lignes, 5 points d'entrée), corps lignes 197-247Est censé générer l'image d'un NFT (organe, ou « Âme » = arbre de vie complet).Monté main.py:1811, 7 tests existants, la persistance en base fonctionne. MAIS aucune image n'est produite : la route renvoie status: "completed" et une adresse /generated/nft/{id}.png (lignes 217 et 242) sans jamais dessiner quoi que ce soit — 0 occurrence de svg/png/image/dalle dans le fichier, et le dossier frontend/generated/nft n'existe pas. L'API affirme un succès qui n'a pas eu lieu.
nft_class — les 3 classes canoniques + conformité légaleH6_domain_vertical · S3livrébackend/app/routers/nft_class_router.py (176 l., 6 points d'entrée) + backend/app/services/nft_class_service.py (418 l.)Décrit 3 classes de NFT, orchestre une demande de frappe, et sort les avertissements légaux par classe.Monté main.py:2036. 10 tests de plancher d'authentification dans tests/routers/test_nft_class_authfloor.py. Le service ne contient qu'un dictionnaire d'avertissements (_COMPLIANCE_WARNINGS ligne 94) — c'est un orchestrateur de demandes, pas un frappeur.
antenna — dNFT 15D, 144 000 parents × 144 fragmentsH6_domain_vertical · S1livrébackend/app/routers/antenna.py (23 points d'entrée)Le plus gros morceau du domaine : frappe de parents et fragments, mise à jour de métadonnées vivantes, scellement HCS, battement de cœur, « Âme » (mint/split/plant/recall), rapports de libération.Monté main.py:1655. MAIS 0 occurrence de sqlalchemy / get_db / AsyncSession / execute() dans tout le fichier : tout vit dans _FALLBACK (ligne 56), un dictionnaire en mémoire. Rien n'est conservé au redémarrage, rien ne va sur Hedera.
Tables antenne en base — créées, jamais utiliséesH3_vital_loop · S1câblé, en attentebackend/alembic/versions/v80_021_antenna_dnft.py (tables `antenna_parents` et `antenna_fragments`, ~20 colonnes chacune)Le logement en base des antennes : colonnes hedera_token_id, hedera_serial, dimensions, phases, chakras, qualité alchimique, dissonance, santé…grep de antenna_parents et antenna_fragments sur tout backend/ hors alembic → 0 résultat. La migration bâtit les tables ; aucune ligne de code ne les touche. C'est le trou le plus net du domaine.
mission_nft_service — les NFT de missionH6_domain_vertical · S8livrébackend/app/services/mission_nft_service.py (1013 lignes), ancrage lignes 395-470Frappe un NFT qui porte une mission (objectif, titre, plateformes visées, directives).Appelé par app/routers/qr_sentinel_router.py:1015 (routeur monté main.py:1962). 4 tests dans tests/unit/test_mission_nft_service.py. Mode simulé assumé : ligne 404, si HEDERA_LIVE_MODE n'est pas vrai → renvoie mock_mission_xxx / "chain_anchor_mode": "mock_by_default". En live, ce n'est PAS une frappe : c'est un reçu HCS (ligne 437 submit_hcs_message). Stockage via PersistentDict (ligne 290) = dict RAM avec vidange périodique en base.
connection_nft_service — les NFT de connexionH6_domain_vertical · S5livrébackend/app/services/connection_nft_service.py (917 lignes)Frappe un NFT par lien établi entre deux parties, avec transfert, gel, et métadonnées de chaîne.Appelé 5+ fois par app/routers/qr_sentinel_router.py (lignes 629, 654, 669, 689, 711). Contrat de base réel : table via alembic v82_230_connection_nft_contract.py, 4 tests répartis sur tests/routers/ et tests/unit/. C'est la pièce NFT la mieux persistée du lot (méthodes _db_upsert_record / _db_get_record / _db_list_records / hydrate_from_db).
pending_mint_retry — le rattrapeur de frappes échouéesH3_vital_loop · S2livrébackend/app/services/pending_mint_retry.py (324 lignes)Toutes les ~56 s, reprend les frappes d'UR restées en attente et réessaie ; abandonne après un nombre max de tentatives et signale pour intervention humaine.Démarré au démarrage de l'app : main.py:388-391 get_pending_mint_scheduler().start(), arrêté main.py:877-878. Réclame par lots de 9 (ligne 46), réclame les orphelins après 15 min (ligne 48). Table pending_mints créée par alembic v80_022 + unicité v82_042.
governed_mint.py — la frappe gouvernée d'UR/créditsH3_vital_loop · S2livrébackend/app/services/babel/governed_mint.py (82 lignes)Force toute frappe de crédits à passer par le grand livre en base (double écriture, budget durable) au lieu d'un pot en mémoire.Appelé par 3 producteurs réels : babel_fractal_treasury_consumer.py:520, babel_temple_treasury_consumer.py:184, forge_energy_consumer.py:296 — tous branchés au démarrage (main.py:663-700+). 6 tests dans tests/babel/test_governed_mint_m1.py. Si la base est absente, il REFUSE plutôt que de retomber en mémoire (ligne 66) : c'est volontaire et sain.
sovereign_bridge_service — le pont paiement → frappeH2_membrane · S2livrébackend/app/services/sovereign_bridge_service.pyTransforme un abonnement/paiement encaissé en frappe d'UR pour le membre.Appelé par app/routers/payments.py:474, app/routers/sovereign_bridge.py:23 et pending_mint_retry.py:60. Utilise les deux services Hedera (lignes 32 et 35). Lignes 319 et 464 le disent noir sur blanc : « D28: canonical mint path via hedera_mainnet_bridge, mock-by-default ».
tokenomics_hedera_bridge (version app) — signature déterministeH4_mapping_projection · S2livrébackend/app/services/tokenomics_hedera_bridge.py (50 lignes)Ne frappe rien : hache un contenu en SHA-256 pour un ancrage futur sur Hedera.Importé par app/routers/treasury_canon_router.py:33, utilisé ligne 106. Le fichier l'assume : c'est un « stub minimal », et hors mode mock il renvoie hedera_tx_id: None (ligne 51).
tokenomics_hedera_bridge (version backend/services) — le doublon orphelinH5_specialized_backstage · S2câblé, en attentebackend/services/tokenomics_hedera_bridge.py (~224 lignes), mint_nft lignes 79-140Un SECOND fichier du même nom, bien plus complet : il contient une vraie frappe de NFT sur la collection 0.0.7780274, plus 5 méthodes de journal HCS.Aucun fichier non-test ne l'importe (grep 'from services.tokenomics_hedera_bridge|backend.services…tokenomics_hedera_bridge' → seul un test le touche). Son garde-fou SIMULATION_MODE (ligne 31) vaut « true » par défaut. Code correct, complètement débranché — piège de confusion avec l'autre fichier de 50 lignes.
hedera_anchor_service — ancrage des vecteurs de mémoireH4_mapping_projection · S9livrébackend/app/services/embeddings/hedera_anchor_service.py (90 lignes)Ancre l'historique des vecteurs (mémoire longue) et permet de reconstruire la généalogie d'une adresse fractale.Instancié par app/services/embeddings/embedding_orchestrator.py:41-45. 3 tests dans tests/unit/test_hedera_anchor_success_event.py. Honnête sur son état : sans la couche atom_canon il renvoie MOCK_HEDERA_xxx et anchor_mode: "mock_no_acmi" (ligne 39).
Scripts Node Hedera — la seule vraie trousse blockchain du dépôtH5_specialized_backstage · S2câblé, en attenteservices/hedera/ : create-token.js, mint-armor.js, mintArmorToken.js, createAntennaCollections.js, sync-engine.js, validate-key.js, test-connection.jsOutils en ligne de commande pour créer un jeton, frapper une armure NFT, créer les collections d'antennes, valider une clé.Ce sont les SEULS fichiers du dépôt qui utilisent la vraie trousse officielle @hashgraph/sdk (create-token.js:15, mint-armor.js:17, mintArmorToken.js:25), déclarée en ^2.51.0 dans services/hedera/package.json. Mais services/hedera/node_modules n'existe pas (jamais installé) et aucun code backend ne les invoque — seulement des scripts npm à lancer à la main.
frontend/js/hedera-flow.js — 1847 lignes débranchéesH7_frontstage_external · S2câblé, en attentefrontend/js/hedera-flow.jsLe module d'interface censé piloter les flux Hedera côté navigateur.grep 'hedera-flow' dans frontend/js/governance-init.js → 0. Aucune page HTML ne le charge. Ses deux seules mentions dans le dépôt sont un commentaire de dépendance (agent-negotiation.js:9) et une entrée de catalogue (catalogue-modules.json). C'est le plus gros orphelin frontal du domaine.
frontend/js/dnft-antenna.js et les 3 autres modules NFT chargésH7_frontstage_external · S1livréfrontend/js/dnft-antenna.js (1667 l.), multi-nft-orchestrator.js (897 l.), chip-nft-covenant.js (806 l.), hematopoiesis-mint-loop.js (384 l.)Interface des antennes dNFT, orchestration multi-NFT, alliance des puces, boucle de frappe hématopoïétique.Les 4 sont listés dans frontend/js/governance-init.js (grep -c = 1 chacun) donc réellement chargés. Tests JS présents : frontend/js/__tests__/unit/dnft-antenna-governed.test.js et 4 autres fichiers de test NFT.
frontend/nft-mint.html — la seule page de frappeH7_frontstage_external · S2livréfrontend/nft-mint.htmlLa page où un humain demande une frappe de NFT.Charge /config.js et /js/governance-init.js (lignes 30 et 38) et appelle /api/v2/nft (ligne 371, = le routeur nft_emission bien monté) plus /api/v2/nova/chat (ligne 485). Le circuit page → API tient. C'est la seule page HTML NFT hors archives (frontend/archives/orphan-pages/ATOM-NFT-System.html est archivé).

Les chiffres, mesurés

Ce qu’on compteLa mesureComment
Trousses (SDK) Hedera déclarées dans les dépendances Python0 sur 4 fichiers requirementsannoncé ailleurs : hedera_service.py:24 dit « requires: pip install hedera-sdk-py » et hedera_mainnet_bridge.py:129 dit « pip install hiero-sdk-python ». Ni l'un ni l'autre n'est déclaré nulle part.grep -i 'hedera\|hiero' sur backend/requirements.txt, requirements-full.txt, requirements-test.txt, requirements_unified.txt → aucun résultat. Aucun pyproject.toml côté backend.
Deux trousses Hedera DIFFÉRENTES attendues par deux fichiers2 (`hedera` et `hiero_sdk_python`)backend/app/services/hedera_service.py:25 `from hedera import ...` vs backend/app/services/hedera_mainnet_bridge.py:117 `from hiero_sdk_python import ...`. Ce sont deux bibliothèques distinctes.
Points de bascule vers la simulation dans hedera_service.py18 tests `if self._simulation_mode`grep -c '_simulation_mode' backend/app/services/hedera_service.py ; la valeur vient d'une seule ligne, hedera_service.py:168 `self._simulation_mode = not HEDERA_SDK_AVAILABLE`
Points d'entrée (endpoints) HTTP du domaine, montés et joignables69antenna 23 + hedera_routes 13 + nft_trinity 13 + nft_emission 9 + nft_class 6 + nft_visual 5, comptés par grep '@router.(get|post|put|delete|patch)' sur chaque fichier
Routeurs NFT/Hedera réellement montés dans main.py6 sur 6backend/app/main.py lignes 1655 (antenna), 1757 (hedera_routes), 1808 (nft_trinity), 1811 (nft_visual), 1955 (nft_emission), 2036 (nft_class)
Fonctions de test écrites pour ce domaine84 fonctions dans 17 fichiersannoncé ailleurs : Je ne peux donc PAS certifier qu'ils passent — seulement qu'ils existent.grep -c '^\s*(async )?def test_' sur les 17 fichiers backend/tests/**/*nft*.py et *hedera*.py + test_governed_mint_m1.py. NON EXÉCUTÉES ici : Python local est nu (ni fastapi ni sqlalchemy), je n'ai pas pu lancer pytest.
Plafond de sécurité par frappe d'UR COIN100 unitésbackend/app/services/hedera_mainnet_bridge.py:25 `MAX_SAFE_AMOUNT = int(os.getenv("MAX_SAFE_AMOUNT", "100"))`, appliqué en hedera_mainnet_bridge.py:137. Toute demande > 100 est REFUSÉE.
Tables antenne créées en base mais jamais lues ni écrites par le code2 tables, 0 usagealembic/versions/v80_021_antenna_dnft.py crée `antenna_parents` et `antenna_fragments` ; grep de ces deux noms dans tout backend/ hors alembic → 0 résultat. Le routeur antenna.py contient 0 occurrence de sqlalchemy/get_db/AsyncSession.
Identifiants de jetons Hedera réels inscrits en dur3 (+1 marqué compromis)backend/services/tokenomics_hedera_bridge.py:9-11 → jeton $ATOM 0.0.7780104, collection NFT 0.0.7780274, opérateur 0.0.7774579. services/hedera/mint-existing-token.js:11 note « remplace ZAMA 0.0.7730446 compromis ».
Fichiers JS Node utilisant la VRAIE trousse Hedera3 fichiers, 0 installéservices/hedera/{create-token,mint-armor,mintArmorToken}.js font `require('@hashgraph/sdk')` ; services/hedera/package.json le déclare en ^2.51.0 ; `ls services/hedera/node_modules` → le dossier n'existe pas.

Ce sur quoi vous pouvez compter

Le squelette est vraiment là, et il est bien meilleur que la moyenne du dépôt. Les 6 routeurs du domaine sont TOUS montés dans main.py — aucun routeur orphelin, ce qui est rare ici. 69 points d'entrée HTTP répondent. 84 fonctions de test sont écrites (je ne les ai pas exécutées : le Python local est nu).

Trois choses tiennent particulièrement bien :

Les garde-fous d'argent sont réels et ils échouent du bon côté. hedera_mainnet_bridge.py refuse toute frappe ≤ 0 ou > 100 unités (ligne 137). governed_mint.py refuse de frapper si la base est absente plutôt que de retomber sur un pot en mémoire (ligne 66) — c'est exactement le bon réflexe pour de la monnaie. nft_emission_service.py débite l'UR AVANT la frappe et échoue fermé si le débit rate (ligne 193). Personne ne peut se frapper de la monnaie par accident.

Le rattrapage automatique tourne. pending_mint_retry est démarré au lancement (main.py:388) et arrêté proprement (main.py:877) : les frappes bloquées sont reprises par lots de 9 toutes les ~56 s, les orphelines récupérées après 15 min, et l'échec définitif est signalé plutôt qu'avalé.

connection_nft_service (917 lignes) est la pièce NFT la plus solide : vraie table en base, vraies méthodes de lecture/écriture/hydratation, 4 tests, appelé par un routeur monté. Si vous devez faire confiance à un NFT, c'est celui-là.

Ce qui manque

Du plus bloquant au moins :

1. RIEN NE SE FRAPPE SUR LA BLOCKCHAIN. C'est le fait central. Deux trousses Hedera différentes sont attendues — hedera (hedera_service.py:25) et hiero_sdk_python (hedera_mainnet_bridge.py:117) — et AUCUNE des deux n'est déclarée dans les 4 fichiers requirements. Conséquence en chaîne : hedera_service.py:168 fixe _simulation_mode = True définitivement, et hedera_mainnet_bridge.py:129 lève une erreur dès qu'on tente d'initialiser le client. Le HEDERA_LIVE_MODE qu'on peut activer ne change rien : sans la trousse, l'initialisation échoue et la frappe revient en statut FAILED. Le côté Node possède la vraie trousse officielle (@hashgraph/sdk dans services/hedera/) mais son node_modules n'a jamais été installé et aucun code backend ne l'appelle.

2. LES NFT INVESTISSEURS NE DEVIENDRAIENT PAS DES NFT MÊME EN LIVE. Ce n'est pas un problème de trousse, c'est un trou dans le code. _try_hedera_mint_nft (nft_emission_service.py:163) écrit une ligne de journal HCS puis renvoie pending_xxx (ligne 185) sans jamais construire de transaction de frappe. Le client paie 1 / 100 / 10 000 UR — le débit est réel — et reçoit une ligne en base. Le vrai code de frappe NFT existe pourtant, dans backend/services/tokenomics_hedera_bridge.py lignes 79-140, mais personne ne l'importe.

3. LE NFT_VISUAL MENT. La route répond status: "completed" et une adresse /generated/nft/{id}.png (lignes 217, 242) alors qu'aucune image n'est produite — zéro code de dessin dans le fichier, et le dossier frontend/generated/nft n'existe pas. Une API qui affirme un succès qui n'a pas eu lieu est pire qu'une API qui échoue.

4. LES ANTENNES VIVENT DANS LA MÉMOIRE VIVE. Le plus gros morceau du domaine (23 points d'entrée) stocke tout dans _FALLBACK, un dictionnaire Python (antenna.py:56). Zéro sqlalchemy dans le fichier. Pendant ce temps, les tables antenna_parents et antenna_fragments existent en base (alembic v80_021) et ne sont touchées par AUCUNE ligne de code — grep sur tout backend/ hors alembic : 0. Le logement est bâti, personne n'y habite. Un redémarrage efface tout. Même problème, plus léger, pour nft_trinity (lignes 59-61).

5. DEUX FICHIERS PORTENT LE MÊME NOM. app/services/tokenomics_hedera_bridge.py (50 lignes, un simple hachage) et backend/services/tokenomics_hedera_bridge.py (~224 lignes, avec une vraie frappe NFT). Seul le petit est branché. Quiconque cherche « le bridge tokenomics » a une chance sur deux de lire le mauvais.

6. 1847 LIGNES D'INTERFACE DÉBRANCHÉES. frontend/js/hedera-flow.js n'est chargé par aucune page ni par governance-init.js.

7. UN JETON MARQUÉ COMPROMIS traîne en commentaire : services/hedera/mint-existing-token.js:11 note que 0.0.7780104 « remplace ZAMA 0.0.7730446 compromis ». À vérifier avant toute activation.

Se tient avec : Trésorerie et UR COIN — treasury_service, ur_engine, governed_mint : c'est le grand livre que toute frappe doit traverser · Paiements et abonnements — payments.py + sovereign_bridge_service : l'argent encaissé devient frappe d'UR · QR Sentinel — qr_sentinel_router est le SEUL appelant de mission_nft_service et connection_nft_service ; s'il tombe, ces deux NFT deviennent orphelins · Babel et les moissonneurs d'énergie — babel_fractal / babel_temple / forge_energy_consumer déclenchent les frappes gouvernées · Antenne dNFT et sphère S1 Personnel — les 144 000 parents × 144 fragments sont la couche identité personnelle · Mémoire et vecteurs — embedding_orchestrator utilise hedera_anchor_service pour ancrer l'historique · Migrations Alembic — 5 migrations du domaine (v80_021, v80_022, v82_042, v82_116, v82_230), dont une dont les tables ne servent à rien

Domaine 8 · état : partiel

Les connexions vers l'extérieur (intégrations tierces : base de données, blockchain, paiements, banque, LLM, MCP, communications, cartes, médias)

C'est l'ensemble des portes par lesquelles AT·OM parle au monde extérieur : la base de données Supabase, la blockchain Hedera, Stripe pour l'argent, Flinks pour les banques canadiennes, une douzaine de fournisseurs d'intelligence artificielle, et une cinquantaine d'autres services (courriel, cartes, images, vidéo). Presque toutes ces portes sont bâties selon le même principe : le code d'appel existe pour de vrai, mais si la clé d'accès n'est pas fournie, la porte reste fermée et le système répond une fausse réponse au lieu de planter.

17 livrées · 5 en attente · 3 déclaratives

L’inventaire

La pièceÉtatOù elle vitCe qu’elle fait
Supabase (PostgreSQL) — côté navigateurH7_frontstage_external · S0livréfrontend/config.js:73-74 (URL + clé anon en dur) ; consommé par frontend/js/bio-state-persistence.js:347-353, scene-serializer.js:485-495, verite-historique.js:235, memory-manager.js:1042-1044, memory-cold.js:93, realtime-sync-hub.js:40-41, governance-init.js:1101-1103Le navigateur écrit et lit directement dans la base via l'API REST de Supabase (PostgREST), sans passer par le backend.7 fichiers JS lisent ATOM_CONFIG.SUPABASE_URL et font un fetch() vers /rest/v1/… avec l'en-tête apikey. Aucune bibliothèque supabase-js n'est chargée : c'est du fetch nu.
Supabase / PostgreSQL — côté serveurH1_spine · S0livrébackend/app/core/config.py:157-171 (SUPABASE_URL, SUPABASE_SERVICE_KEY ou SUPABASE_SERVICE_ROLE_KEY) ; backend/app/core/database.pyLe backend se connecte à la même base, mais en SQL direct (SQLAlchemy async sur DATABASE_URL), pas par l'API Supabase.Un seul fichier de tout le dépôt importe la trousse Python supabase : backend/services/tokenomics_db.py:47 — et ce fichier est hors de backend/app/. Le reste passe par DATABASE_URL/ASYNC_DATABASE_URL.
Stripe — paiements, côté serveurH7_frontstage_external · S2livrébackend/app/routers/payments.py (848 lignes), monté dans backend/app/main.py:1344 ; client chargé paresseusement lignes 183-204Abonnements, séances de paiement, portail client, réception des événements Stripe.Router monté dans main.py. La trousse stripe>=8.0.0 est bien dans backend/requirements.txt:72. 5 identifiants de tarif réels sont codés en dur (payments.py:110-138). Sans STRIPE_SECRET_KEY, get_stripe() retourne None et journalise « payments disabled ».
Stripe — côté navigateur (clé publiable LIVE)H7_frontstage_external · S2livréfrontend/js/stripe-client.js:28 (781 lignes) ; chargé par frontend/funder.htmlOuvre la caisse Stripe depuis la page de financement.La clé pk_live_51St8CG… est écrite en clair dans le fichier. C'est une clé publiable (normale à exposer), mais elle est en mode LIVE : ce sont de vrais paiements, pas un bac à sable.
Stripe — deuxième porte, réception des événementsH7_frontstage_external · S2livrébackend/app/routers/external_proxies_router.py:366 (/stripe/payment-intent) et :408 (/stripe/webhook) ; monté main.py:1929Un second chemin Stripe, séparé du router payments.py, avec anti-doublon d'événements.Deux routers montés touchent Stripe indépendamment (payments.py + external_proxies_router.py). C'est une duplication réelle, pas une doctrine.
Hedera — service principal UR COINH7_frontstage_external · S2câblé, en attentebackend/app/services/hedera_service.py (1177 lignes) ; routes backend/app/api/routes/hedera_routes.py (14 routes) montées main.py:1757Frappe, brûle et transfère le jeton UR ; journal d'audit inaltérable HCS.Les routes SONT montées et 22 fichiers importent le service — mais la trousse hedera-sdk-py N'EST DANS AUCUN requirements*.txt (vérifié sur les 4 fichiers). Donc HEDERA_SDK_AVAILABLE=False à la ligne 51, et self._simulation_mode=True (ligne 168). 15 branches if self._simulation_mode: renvoient des résultats simulés. Le code expose même une route /admin/simulation-state (hedera_routes.py:757).
Hedera — pont mainnet (frappe réelle)H7_frontstage_external · S2câblé, en attentebackend/app/services/hedera_mainnet_bridge.py (296 lignes), 11 importeursChemin séparé pour frapper de l'UR sur le vrai réseau, avec garde-fou MAX_SAFE_AMOUNT.Importe hiero_sdk_python (lignes 118, 218) — absent lui aussi de tous les requirements*.txt. Ligne 258 il importe from hedera import …, soit encore une TROISIÈME trousse. Aucune des trois n'est installée.
Interrupteur HEDERA_LIVE_MODEH2_membrane · S3livrébackend/app/services/sovereign_bridge_service.py:244 ; mission_nft_service.py:405 ; babel/babel_fractal_treasury_consumer.py:252Interrupteur qui décide si on écrit vraiment sur la blockchain ou si on reste local.Lu par 3 services réels (pas seulement des tests) ; couvert par ~10 tests dans backend/tests/. Fermé par défaut (default=False).
Flinks — agrégation bancaire canadienneH7_frontstage_external · S2livrébackend/app/services/canadian_banking_service.py (1065 lignes) ; routes backend/app/api/routes/banking_routes.py (16 routes) montées main.py:1756Relie les comptes des 8 grandes banques canadiennes (Desjardins, TD, RBC, BMO, Scotia, CIBC, BNC, Tangerine) — lignes 240-303.Client HTTP réel en httpx (lignes 342, 356). Ligne 323 : self._use_mock = not self.api_key — sans FLINKS_API_KEY, tout passe par _mock_response(). Par défaut FLINKS_ENV='sandbox' (ligne 185) et l'URL vise toolbox-api.private.fin.ag (bac à sable). Un test de contrat existe : backend/tests/routers/test_banking_routes_contract.py.
LLM — connecteur principal (le chemin qui sert vraiment)H7_frontstage_external · S0livrébackend/app/services/llm_connector.py (653 lignes), lignes 57-113 ; appelé par backend/app/routers/nova.py:677, 798, 1732 et par 6 services (agent_factory:166, master_mind:409, nova_pipeline:1148, result_assembler:257, routing_engine:328, agent_execution_pipeline:425)Envoie les vraies requêtes HTTP aux fournisseurs d'IA. 8 fournisseurs configurés : anthropic, openai, google, groq, deepseek, mistral, openrouter, zhipu.httpx réel (ligne 170). Ligne 152-157 : chaque fournisseur n'est actif que si sa variable de clé est présente, sinon avertissement « ✗ No API key ». C'est ce connecteur — pas llm_router — que le chat Nova utilise.
LLM — routeur multi-fournisseurs (le second chemin)H5_specialized_backstage · S0câblé, en attentebackend/app/services/llm_router.py (1196 lignes) ; enum lignes 55-84 ; adaptateurs backend/app/services/llm_adapters/ (4 fichiers)Système de routage plus ambitieux : budget, repli automatique, choix du modèle le moins cher.L'enum LLMProvider nomme 19 fournisseurs (lignes 58-84). _build_adapter() (lignes 334-365) n'en construit que 4 : openai, ollama, vllm, zhipu. Les 15 autres — dont ANTHROPIC, GOOGLE, GROQ — tombent dans _execute_completion_legacy() qui renvoie littéralement « [Mock response from …] This is a simulated response. » (ligne 760). Importé par 9 fichiers mais le chemin utilisateur passe par llm_connector.
Mandataires externes (external_proxies_router)H2_membrane · S0livrébackend/app/routers/external_proxies_router.py (993 lignes, 21 routes) ; monté main.py:1929Guichet unique gardé par authentification qui relaie vers 10 services : OpenAI (chat/image/synthèse vocale), Anthropic, ElevenLabs, Stripe, Mapbox (géocodage/itinéraire/isochrone), HubSpot, QuickBooks, Xero, Google Places, OpenStreetMap.21 routes comptées. protected_router porte Depends(get_current_user) (ligne 46-49) et internal_router exige un jeton interne (ligne 50-52) ; les deux sont bien inclus en fin de fichier. Chaque appel lit sa clé via _get_api_key() et renvoie une erreur propre si absente. Une route /config-status dit lesquelles des 18 clés sont posées.
Connecteurs applicatifs (connectors router)H7_frontstage_external · S0livrébackend/app/routers/connectors.py (1051 lignes, 23 routes) ; monté main.py:135223 routes vers Resend (courriel), Discord, Telegram, Unsplash, Pixabay, YouTube, Facebook, AlphaVantage, OpenExchangeRates, Google Calendar, Notion, Stripe, Mapbox, Moodle, Discourse.23 décorateurs @router comptés. Chaque route appelle _require_env() sur sa clé et lève une erreur explicite si elle manque.
Communications sortantes (courriel + SMS)H7_frontstage_external · S0livrébackend/app/services/comms_service.py (636 lignes) ; routeur backend/app/routers/comms_router.py monté main.py:1902Envoi de courriels via Resend / SendGrid / Brevo, et de SMS via Twilio / Vonage, avec bascule automatique.httpx réel aux lignes 311, 335, 356, 404, 423. Trois fournisseurs courriel déclarés lignes 50-62 avec leur variable d'environnement. Réutilisé par 3 autres services (twilio_voice_service, communications_topology_service, qg_transversal_infrastructure_service).
Twilio Voice (téléphonie)H7_frontstage_external · S0câblé, en attentebackend/app/services/twilio_voice_service.py (239 lignes) ; routeur backend/app/routers/twilio_voice_router.py monté main.py:2011Jetons d'appel dans le navigateur, appels sortants, provisionnement de numéros. 6 variables d'environnement requises (lignes 20-25).Le routeur EST monté, mais la trousse twilio n'est dans AUCUN requirements*.txt — l'appel Client(...) aux lignes 173 et 209 échouera à l'import. La fonction _require() (ligne 74) vérifie les variables mais pas la présence de la trousse.
Serveur MCP (agents externes entrent chez vous)H2_membrane · S0livrébackend/app/services/mcp_server.py (794 lignes) ; monté manuellement dans backend/app/main.py:2058 via app.include_router(_get_mcp_handler())Expose des outils AT·OM en JSON-RPC sur POST /mcp/ pour que Claude Desktop, n8n ou le navigateur AT·OM puissent agir.Montage explicite dans main.py (bloc try/except lignes 2057-2063). Le registre principal TOOLS_REGISTRY compte 8 outils mesurés (sphere_classifier, hz_resolver, civilization_finder, sentinel_dossier, sentinel_privacy, dnft_user_identity, vibrational_shield, qr_scanner) + 1 outil vivant (system_pulse, mcp_live_organs.py:110) + 2 outils dépôt (repo_list_files, repo_read_file, mcp_repo_tools.py:199) + 1 outil bureau = 12 outils au total.
Cartes et géolocalisationH7_frontstage_external · S0livrébackend/app/services/geo_service.py (653 lignes) ; routeur backend/app/routers/geo_router.py monté main.py:1931Géocodage par 4 fournisseurs : OpenStreetMap/Nominatim (gratuit, aucun compte), Mapbox, Amazon Location, Google Maps.Appels httpx réels lignes 204 (Nominatim), 231 (Mapbox), 251 (Amazon). Ligne 111 : repli automatique sur OSM si rien n'est configuré — donc cette porte fonctionne SANS aucune clé. Réutilisé par 3 autres services.
Recherche de lieux agrégéeH6_domain_vertical · S5livrébackend/app/services/search_aggregator_service.py (807 lignes) ; backend/app/routers/search_router.pyInterroge Google Places et l'API Overpass d'OpenStreetMap.httpx aux lignes 320 et 391. Ligne 302 : sans GOOGLE_PLACES_API_KEY, la source Google est ignorée en silence et il ne reste qu'OSM.
Registre des fournisseurs de médias (vidéo/voix/3D)H5_specialized_backstage · S4déclaratifbackend/app/services/media_providers_registry.py (230 lignes), registre ligne 40Déclare 16 fournisseurs : Veo, Kling, Seedance, Runway, Luma, HeyGen, Hedra, Fabric, D-ID, ElevenLabs, Suno, Meshy, Tripo, Hunyuan3D, Stability, OpenAI Images.Le fichier le dit lui-même (lignes 13-14) : « Aucun appel réseau n'est émis par ce module ». C'est un catalogue de slots à allumer plus tard, pas un connecteur. 5 fichiers l'importent, mais pour lire l'état, pas pour appeler.
Registre des rails d'argent (AT·OM Pay)H5_specialized_backstage · S2câblé, en attentebackend/app/services/pay/money_adapter_registry.py (274 lignes)Décrit 5 rails de valeur : atom_liquidity_bridge, canadian_banking, external_wallet_readonly, fiat_crypto_ramp, brokerage_readonly.Le seul fichier hors tests qui l'importe est lui-même ; l'unique autre importeur est backend/tests/test_atom_pay.py. AUCUN routeur ne l'expose. Statuts mesurés : 3 « mock », 2 « partial », 0 « live ».
Tableau de bord des connecteurs (côté navigateur)H7_frontstage_external · S0déclaratiffrontend/js/connector-hub.js (1702 lignes)Interface qui présente 44 connecteurs classés par sphère (Discord, Notion, HubSpot, Linear, Mastodon, Matrix, Wikipedia, GBIF, iNaturalist, Open-Meteo, etc.).44 entrées comptées. Les 44 ont status: 'disconnected' — aucune n'est branchée. Le fichier lui-même appelle sa section « ACTION STUBS » (ligne 541). PROBLÈME : _saveState() (lignes 509-522) écrit val.config — qui contient apiKey en clair — dans localStorage sous la clé atom_connector_hub.
CHE·NU™ Quantum — pont vers le système externeH7_frontstage_external · S3déclaratifhf-atom-tools/atom_canon/bridges/chenu_quantum_bridge.py:43 (473 lignes)Censé relier AT·OM à l'écosystème quantique CHE·NU annoncé comme externe.CHENU_API_URL et CHENU_API_KEY ne sont lues par AUCUN fichier du dépôt (recherche sur .py/.js : uniquement des mentions dans CLAUDE.md et docs/adr/). CHENU_LIVE_MODE n'est lue nulle part dans backend/app/ — seulement dans hf-atom-tools/…:43 et dans les tests. La documentation docs/adr/2026-05-24… affirme au contraire (D9) « prod live active » : c'est faux au regard du code.
Relais WebSocket (temps réel navigateur↔serveur)H2_membrane · S0livrébackend/app/services/atom_node_ws_relay.py (214 lignes), importé par backend/app/main.py ; côté client frontend/config.js:41-43Canal permanent pour les mises à jour vivantes.Importé par main.py. Le client vise wss://<hôte>/ws/resonance en ligne, ws://138.197.132.63/ws/resonance en local.
Redis (cache et files de travaux)H1_spine · S0livrébackend/app/core/cache.py:74, backend/app/core/redis.py:106, backend/app/core/security.py:261 ; redis==5.0.1 et arq==0.25.0 dans backend/requirements.txt:39-40Mémoire rapide partagée : cache, limitation de débit, file de travaux différés.Trousses présentes dans requirements. Repli local sur redis://localhost:6379/0 si REDIS_URL absente. Un interrupteur USE_MOCK_REDIS existe.
Chemin réel du site public (at-om.ai)H2_membrane · S0livréfrontend/config.js:29-38 (commentaire explicite) ; API_BASE='' en HTTPS, 'http://138.197.132.63' en localEn ligne, le navigateur ne parle jamais au backend directement : Vercel réécrit /api, /health, /agents et /ws vers DigitalOcean.Le backend n'a ni domaine ni certificat (commentaire config.js:29-31). C'est pourquoi API_BASE est vide en ligne : tout passe par le proxy same-origin de vercel.json.

Les chiffres, mesurés

Ce qu’on compteLa mesureComment
Variables d'environnement lues par le code backend184 distinctes, dont 66 sont des clés/jetons/secrets tiersannoncé ailleurs : .env.example ne documente que 157 lignes de la forme CLÉ= — il y a donc un écart entre ce que le code lit et ce que le modèle documentegrep -rhoE "os\.(getenv|environ\.get)\(\s*[\"'][A-Z0-9_]+[\"']" backend/app/ --include=*.py | grep -oE "[A-Z0-9_]{3,}" | sort -u | wc -l
Fournisseurs LLM nommés dans l'enum du routeur19 nommésbackend/app/services/llm_router.py lignes 55-84, comptage manuel des membres de LLMProvider
Fournisseurs LLM avec un adaptateur HTTP réel dans le routeur4 (openai, ollama, vllm, zhipu)annoncé ailleurs : Les 15 autres, dont Anthropic, renvoient la chaîne « [Mock response from …] This is a simulated response. » (ligne 760)backend/app/services/llm_router.py:334-365, _build_adapter() — tout le reste retourne None
Fournisseurs LLM réellement joignables par le chemin utilisé (llm_connector)8 configurés (anthropic, openai, google, groq, deepseek, mistral, openrouter, zhipu), actifs seulement si leur clé est poséebackend/app/services/llm_connector.py:57-113, dict PROVIDER_CONFIGS ; activation ligne 152-157
Routes de mandataires externes montées et gardées par authentification21 routesgrep -nE "@[a-z_]*router\.(get|post|put|delete)" backend/app/routers/external_proxies_router.py | wc -l
Routes de connecteurs applicatifs23 routesgrep -cE "^@router\." backend/app/routers/connectors.py
Outils exposés par le serveur MCP12 (8 canon + 1 vivant + 2 dépôt + 1 bureau)comptage des entrées à 4 espaces d'indentation dans TOOLS_REGISTRY (mcp_server.py:472), LIVE_TOOLS_REGISTRY (mcp_live_organs.py:110), REPO_TOOLS_REGISTRY (mcp_repo_tools.py:199), BUREAU_TOOLS_REGISTRY (bureau_service.py)
Connecteurs affichés dans le tableau de bord navigateur44 déclarés, 44 avec status:'disconnected', 0 branchégrep -cE "^\s+id: '" frontend/js/connector-hub.js puis grep -oE "status: '[a-z_]+'" | sort | uniq -c
Trousses blockchain installables0 sur 3 (hedera-sdk-py, hiero_sdk_python, hedera)annoncé ailleurs : CLAUDE.md annonce « Blockchain: Hedera (UR COIN) » comme un élément de la pile ; en pratique le service tourne en mode simulation (hedera_service.py:168)grep -niE "hedera|hiero" backend/requirements.txt backend/requirements-full.txt backend/requirements_unified.txt backend/requirements-test.txt → aucun résultat
Banques canadiennes déclarées dans le service Flinks8backend/app/services/canadian_banking_service.py lignes 240-303, comptage des flinks_institution_id
Fournisseurs de médias déclarés16 déclarés, 0 appelantbackend/app/services/media_providers_registry.py:40, dict PROVIDERS ; le module dit lui-même « Aucun appel réseau n'est émis par ce module » (ligne 13)
Rails d'argent du registre AT·OM Pay5 rails : 3 « mock », 2 « partial », 0 « live »grep -oE '"status": "[a-z]+"' backend/app/services/pay/money_adapter_registry.py | sort | uniq -c
Secrets en clair dans le code versionné2, tous deux publiables par naturegrep -rnoE "(sk-[A-Za-z0-9]{20,}|sk_live_|pk_live_|AKIA[A-Z0-9]{16}|eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9)" frontend/ backend/app/ → frontend/config.js:74 (clé anon Supabase) et frontend/js/stripe-client.js:28 (clé publiable Stripe, mode LIVE). Aucune clé secrète trouvée.

Ce sur quoi vous pouvez compter

Le motif de conception est bon et cohérent partout : « la clé en dernier ». Le code d'appel est écrit d'avance, il vérifie la présence de sa clé, et sans clé il répond une fausse réponse ou une erreur propre au lieu de faire tomber le système. C'est pour ça qu'AT·OM démarre et fonctionne même sans un seul compte tiers payé.

Ce qui marche pour de vrai, aujourd'hui, sans rien ajouter :
· La base de données Supabase, dans les deux sens (navigateur en direct par REST, serveur en SQL).
· Le chemin d'argent Stripe, de bout en bout, en mode LIVE — la clé publiable est posée, la trousse est installée, les routes sont montées, 5 forfaits sont définis.
· Le chat des agents, par llm_connector : 8 fournisseurs d'IA prêts, chacun s'allume dès que sa clé arrive.
· Le géocodage : il fonctionne SANS aucune clé, grâce au repli automatique sur OpenStreetMap.
· Le serveur MCP : des agents externes (Claude Desktop, n8n) peuvent réellement se brancher et appeler 12 outils.
· Deux guichets gardés par authentification (external_proxies 21 routes, connectors 23 routes) qui centralisent la sortie vers l'extérieur au lieu de laisser chaque module appeler dans son coin.
· L'envoi de courriels avec trois fournisseurs interchangeables et bascule automatique.
· La liaison Flinks aux 8 grandes banques canadiennes : le code HTTP est réel et testé par un test de contrat.

Et une bonne nouvelle sécurité : aucun secret réel n'est versionné. Les deux clés trouvées en clair sont des clés publiables, faites pour être exposées. Le .gitignore protège bien .env, .env.local et .env.production.

Ce qui manque

Du plus bloquant au moins :

1. LA BLOCKCHAIN NE TOURNE PAS. C'est le trou le plus grave, parce que c'est le seul qui trompe. Les 14 routes Hedera sont montées, 22 fichiers importent le service, la documentation annonce Hedera dans la pile — mais aucune des trois trousses (hedera-sdk-py, hiero_sdk_python, hedera) n'est dans les requirements. Résultat : hedera_service.py:168 bascule en mode simulation et 15 branches renvoient de fausses transactions. Un appel à /token/mint répond « succès » sans rien frapper. Tant que la trousse n'est pas installée, l'UR COIN n'existe que dans la base locale.

2. TWILIO EST MONTÉ MAIS N'A PAS SA TROUSSE. Même maladie, plus petite : le routeur est monté (main.py:2011), le service vérifie les 6 variables d'environnement, mais twilio n'est dans aucun requirements — les appels lignes 173 et 209 planteront à l'import. La vérification _require() teste les clés, pas la trousse. C'est le piège classique : ça a l'air configuré, ça casse à l'usage.

3. LA DOCTRINE CHE·NU MENT SUR LE CODE. docs/adr/2026-05-24… tranche (décision D9) « prod live active via CHENU_API_URL + CHENU_API_KEY ». Mesure : ces deux variables ne sont lues par AUCUN fichier .py ni .js du dépôt. Elles peuvent être posées sur le serveur, elles ne changeront rien. Il n'y a pas de client HTTP vers CHE·NU. C'est déclaratif.

4. DES CLÉS D'API DANS LE NAVIGATEUR. frontend/js/connector-hub.js:509-522 écrit l'objet config — qui contient apiKey — en clair dans localStorage. Toute extension de navigateur, tout script tiers chargé sur la page peut les lire. Aucun des 44 connecteurs n'est branché aujourd'hui, donc rien n'est exposé pour l'instant : la faille est en attente d'usage, pas en train de fuir.

5. DEUX SYSTÈMES LLM EN PARALLÈLE, ET LE PLUS BEAU N'EST PAS BRANCHÉ. llm_router.py (1196 lignes, budget, repli, choix du moins cher) nomme 19 fournisseurs mais n'en câble que 4 ; les 15 autres — Anthropic compris — renvoient littéralement « [Mock response from …] ». Pendant ce temps c'est llm_connector.py (653 lignes, 8 fournisseurs réels) qui sert les utilisateurs. Le risque : un développeur croit brancher Anthropic dans le routeur et reçoit du faux texte sans erreur.

6. DEUX CHEMINS STRIPE INDÉPENDANTS. payments.py et external_proxies_router.py touchent tous deux Stripe, montés séparément. Ce n'est pas une doctrine, c'est de la duplication — deux endroits à corriger, deux endroits à sécuriser.

7. LES RAILS D'ARGENT AT·OM PAY SONT ORPHELINS. money_adapter_registry.py (5 rails) n'est importé par aucun routeur — uniquement par lui-même et par son test. Le code est propre, personne ne l'appelle.

8. LE CATALOGUE MÉDIA EST UN CATALOGUE. 16 fournisseurs vidéo/voix/3D déclarés, zéro appel réseau — le module le dit lui-même. À lire comme une liste de courses, pas comme une capacité.

Se tient avec : L'économie et la trésorerie — Hedera, Stripe et Flinks sont les rails par lesquels la valeur entre et sort ; le registre AT·OM Pay (money_adapter_registry) attend d'être branché à ce domaine. · Les agents et orchestrateurs — Nova, Aria, Orion passent tous par llm_connector.py ; sans clé LLM posée, ils ne pensent pas. · La base de données et la persistance — Supabase est à la fois une connexion externe et le socle de tout le stockage ; le navigateur y écrit en direct, ce qui court-circuite le backend. · La sécurité et la souveraineté — les deux guichets gardés (external_proxies_router, connectors) sont la membrane de sortie ; le localStorage de connector-hub.js est le trou dans cette membrane. · Le déploiement — les réécritures de vercel.json sont ce qui rend le backend HTTP joignable depuis un site HTTPS ; sans elles, aucune connexion ne marche en ligne. · Babel et le décodage — babel_fractal_treasury_consumer.py lit HEDERA_LIVE_MODE, donc le décodeur dépend de l'état de la blockchain. · Le MCP et le bureau d'architecte — le serveur MCP est une porte d'ENTRÉE (des agents externes viennent chez vous), à l'inverse de tout le reste de ce domaine.

Domaine 9 · état : partiel

Les services internes — ce qui tourne pour le système lui-même (bus de messages, pouls bio, stigmergie, immunitaire, ouvriers de fond, observabilité)

C'est la plomberie du système : le réseau nerveux par lequel les morceaux se parlent (le bus de messages), le cœur qui bat et déclenche les tâches répétitives (le bio-tick), et les ouvriers de fond qui vont chercher des données dehors. Personne ne « visite » ces services — mais si l'un s'arrête, des pans entiers du système cessent silencieusement de vivre.

19 livrées · 8 en attente · 0 déclaratives

L’inventaire

La pièceÉtatOù elle vitCe qu’elle fait
Bus d'événements backend (event_bus)H1_spine · S0livrébackend/app/services/event_bus.py (649 lignes)Le réseau nerveux Python : publier/s'abonner avec jokers (task.*), priorités, filtrage par sphère, historique rejouable, pont WebSocket.143 fichiers .py l'importent (75 services + 15 routeurs + le reste). 3 tests dédiés : tests/unit/test_event_bus.py, test_event_bus_matcher.py, test_event_bus_sphere_token.py.
Catalogue de topics du noyau (core/bus_topics)H1_spine · S0livrébackend/app/core/bus_topics.py (1272 lignes)La liste officielle des noms d'événements du noyau — le vocabulaire commun du bus.Import Python réel exécuté : len(ALL_TOPICS) == 302. Le fichier s'auto-vérifie à l'import (assert ligne 1271). Importé par event_bus.py ligne ~45.
Les 8 autres catalogues de topicsH1_spine · S0livrébackend/app/services/{babel,bayon,bioacoustic,canon,stone_decoder,translation}/bus_topics*.py + app/services/workflow_topics.pyChaque grand domaine tient son propre vocabulaire d'événements, à côté du catalogue du noyau.Comptés un par un : babel 39 (assert L302), bayon 21 (assert L61), bioacoustic 16 (assert L58), stone_decoder 13 (assert L36), canon 11, canon/living_knowledge 18 (dict), translation 11 (dict), workflow 12 topics + 1 préfixe.
Bus de messages frontend (MessageBus)H1_spine · S0livréfrontend/js/message-bus.js (1383 lignes)Le même réseau nerveux côté navigateur : boîtes aux lettres par agent, canaux, publish/on/off, crochets avant-après, propagation « rhizome » et « cross-monde ».1157 fichiers de frontend/js/ le référencent ; 1261 appels .publish( et 1182 abonnements .on( mesurés. Mais chargé dans seulement 22 pages HTML sur 122.
Pouls bio backend (bio_tick_backend)H3_vital_loop · S0livrébackend/app/core/bio_tick_backend.py (142 lignes)Le cœur du serveur : UNE seule boucle asyncio à 432 ms, et chaque consommateur déclare à quelle cadence il veut être réveillé.Exécuté en direct : VIBE_BASE=432, VIBE_MEDIUM=4320, VIBE_LONG=43200, GUARDIAN_PULSE=4440, CYCLE_9=39000 ms. Démarré sans condition dans backend/app/main.py:415. Tests : tests/unit/test_bio_tick_backend.py + test_bio_tick_cycle9.py.
Les 17 consommateurs du pouls backendH3_vital_loop · S0livrébackend/app/main.py:342-349 et :446 ; backend/app/services/harmonic_ticker.py:66 ; backend/app/services/royalty_team/orchestrator.py:61Ce que le cœur réveille vraiment : rituels, échéances de missions, ristourne, économie circulaire, compilateur de sphères, chronos Bayon, ancre harmonique, horloge temporelle, et les 9 membres de l'équipe royalties.6 enregistrements bt.register(...) sur CYCLE_9 (main.py:342-349), + harmonic_anchor sur GUARDIAN_PULSE (main.py:446), + harmonic_ticker (harmonic_ticker.py:66), + 9 membres bouclés dans orchestrator.py:61 appelé depuis main.py:433.
Pouls bio frontend (bio-tick-master)H3_vital_loop · S0livréfrontend/js/bio-tick-master.js (795 lignes)Le même cœur dans le navigateur : un seul setInterval à 432 ms remplace les 13 minuteries concurrentes d'avant.337 fichiers de frontend/js/ le référencent. MAIS chargé dans seulement 7 pages HTML (grep sur <script src="js/bio-tick-master.js">).
Les doublons du pouls frontendH3_vital_loop · S0câblé, en attentefrontend/js/bio-tick-backup.js (657L), bio-tick-shim.js (333L), bio-tick-worker.js (46L), bio-worker.js (316L), bio-worker-bridge.js (424L)Cinq variantes du même cœur : une sauvegarde, une cale de compatibilité, et une version « web worker » (hors du fil principal).Aucune page HTML ne charge bio-tick-backup.js, bio-worker.js ni bio-worker-bridge.js (0 occurrence). bio-tick-shim.js n'est chargé que par 1 page.
Ouvrier bio fractal BabelH3_vital_loop · S0livrébackend/app/services/babel/fractal_bio_tick_worker.py (341 lignes)Une boucle séparée qui parcourt les niveaux individuel / communautaire / civilisationnel et publie un instantané d'horloge fractale.Démarré AVEC le bus dans main.py:633 (await bio_tick_worker.start(bus)), arrêté proprement main.py:887. Test : backend/tests/babel/test_fractal_bio_tick_worker.py.
Stigmergie — routeur seulH3_vital_loop · S0livrébackend/app/routers/stigmergy.py (836 lignes)Les « pistes de phéromones » : le système dépose des traces sur les chemins parcourus, elles s'affaiblissent et s'évaporent avec le temps. 8 points d'entrée API.Monté dans main.py:1661. Endpoints comptés lignes 493/535/572/587/628/677/757/788. ATTENTION : c'est le SEUL fichier stigmergie du backend — find app -iname "*stigmerg*" -name "*.py" ne renvoie que lui. Il n'y a aucun service, toute la logique est dans le routeur.
Stigmergie frontendH3_vital_loop · S0câblé, en attentefrontend/js/stigmergy-membrane.js (784L), memory-stigmergic.js (620L), bell-stigmergy-grid.js (763L)La version navigateur des pistes : membrane, mémoire stigmergique, grille de cloches.stigmergy-membrane.js chargé dans 3 pages HTML, memory-stigmergic.js dans 1, bell-stigmergy-grid.js dans AUCUNE. Contrairement à immune-system.js, stigmergy-membrane.js ne s'enregistre pas sur le bio-tick (aucun BioTick/register( dans le fichier).
Système immunitaire — frontend UNIQUEMENTH2_membrane · S0câblé, en attentefrontend/js/immune-system.js (704L), immune-cortisol-gate.js (378L), enteric-immune-guard.js (387L), skin-immune-barrier.js (430L)La défense interne : détection de menaces, barrière cutanée, garde entérique, portail cortisol.IL N'Y A AUCUN FICHIER IMMUNITAIRE BACKEND : find backend/app -iname "*immun*" -name "*.py" renvoie zéro résultat. Côté frontend, immune-system.js se branche correctement sur le pouls (ligne 466 : bioTick.register('immune', ..., GUARDIAN_PULSE)) mais n'est chargé que par 3 pages HTML ; les 3 autres modules par aucune.
Ouvriers de moisson externe (base_worker + 10 concrets)H5_specialized_backstage · S0livrébackend/app/services/base_worker.py (266L) + bible_hub_worker, energy_grid_worker, internet_archive_worker, openalex_worker, osm_worker, sefaria_worker, submarine_cables_worker, tipitaka_worker, transport_worker, wikidata_workerLes 10 ouvriers qui vont chercher des données dehors (OpenAlex, OpenStreetMap, Wikidata, Sefaria, Internet Archive...). Ils héritent d'une base commune : limitation de débit, réessais, suivi de progression, annulation.Aucun routeur ne les importe directement (0/10 mesuré) — la chaîne passe par app/services/ingest_manager.py, appelé par app/routers/ingest_router.py (monté main.py:2035) et osint_ingest.py (monté main.py:2038). Garde anti-SSRF réelle dans base_worker.py lignes 30-60. Tests : test_base_worker_ssrf.py, test_ingest_worker_imports.py.
File de jobs ARQ (Redis)H5_specialized_backstage · S0câblé, en attentebackend/app/services/arq_job_queue/ — arq_worker_pool.py (276L) + __init__.py (22L)Un vrai pool d'ouvriers asynchrones adossé à Redis, pour les tâches longues.Le mot « arq » n'apparaît NULLE PART dans backend/app/main.py. Les seules mentions hors du dossier lui-même sont un commentaire dans _url_utils.py:5 et deux fichiers de test. Rien ne le démarre.
Moteur de battement WebSocket (HeartbeatEngine)H2_membrane · S0livrébackend/app/main.py:110-230 environEnvoie un battement régulier aux navigateurs connectés pour qu'ils sachent que le serveur est vivant. Relais Redis Pub/Sub optionnel si plusieurs serveurs tournent.Démarré main.py:386 (await heartbeat_engine.start()). Boucle asyncio créée ligne 139, écouteur Redis ligne 173 sur le canal « atom:ws:heartbeat », retombe en mode mono-instance si Redis absent.
Les 7 ordonnanceurs démarrés au bootH3_vital_loop · S0livrébackend/app/main.py — lignes 386, 391, 404, 415, 436, 592, 754Battement WS, réessai de frappe monétaire en attente, vidange du magasin persistant, pouls bio, cellule royalties, alerteur d'incidents, battement du sanctum.7 appels .start() mesurés dans le lifespan, avec 7 .stop() correspondants au shutdown (lignes 868, 878, 887, 918...). Tailles : pending_mint_retry.py 324L, sanctum/heartbeat_scheduler.py 124L, incident_alerter.py 356L, persistent store flush défini app/core/persistent_store.py:267.
Observatoire du pouls système (observability_service)H4_mapping_projection · S0livrébackend/app/services/observability_service.py (72 lignes)La seule vue qui rassemble en un coup d'œil : le battement bio, la flamme active et son gardien, le niveau de chaos. Conçu pour rendre visibles les process invisibles.Seulement 2 importeurs mesurés : app/services/mcp_live_organs.py et tests/unit/test_observability_service.py. AUCUN routeur HTTP — il n'est joignable que par l'outil MCP, jamais par une URL.
Moniteur de performanceH4_mapping_projection · S0livrébackend/app/services/performance_monitor.py (713 lignes)Mesure les temps de réponse et la santé des appels.2 importeurs, tous deux montés : app/routers/metrics.py (monté main.py:1794, 5 endpoints) et app/api/v1/routes/performance_routes.py (monté main.py:1206).
Contrôle de santé (health)H2_membrane · S0livrébackend/app/routers/health.py (126 lignes)L'URL qu'un hébergeur interroge pour savoir si le service tient debout.Monté main.py:1216 avec core=True (donc un échec de chargement est fatal, pas silencieux).
Audit d'uptime au démarrageH4_mapping_projection · S0livrébackend/app/services/uptime_audit.py (198 lignes)Passe l'inventaire au boot et produit un résumé de ce qui a démarré ou non.Appelé main.py:584 (audit_summary = await audit_at_startup()).
Observatoire MPALH4_mapping_projection · S0livrébackend/app/services/mpal_observatory_service.py (813 lignes)Surveille la fragmentation du langage détectée par Babel et referme la boucle vertueuse.Instancié au démarrage main.py:567-568 — l'appel get_mpal_observatory() déclenche _ensure_babel_subscription(). Aucun routeur : il vit uniquement par le bus.
Bus de commandes spatialesH1_spine · S0livrébackend/app/services/spatial_command_bus.py (1169 lignes)Un second bus, spécialisé pour les commandes de scène/espace.8 importeurs mesurés dont 2 routeurs. Test de contrat DB : tests/unit/test_spatial_command_bus_db_contract.py.
Service d'événements (events_service)H1_spine · S0câblé, en attentebackend/app/services/events_service.py (498 lignes)Un service d'événements complet, écrit et propre.ZÉRO importeur dans tout backend/app/. La seule mention du dépôt est dans tests/unit/test_mission_center_router.py. C'est le plus gros orphelin du domaine.
Ordonnanceur générique (scheduler)H3_vital_loop · S0livrébackend/app/services/scheduler.py (226 lignes)Un planificateur de tâches générique.UN SEUL importeur dans tout le dépôt : app/routers/stigmergy.py. Il vit, mais par un seul fil.
Observateur de flamme (flame_observer)H4_mapping_projection · S0câblé, en attentebackend/app/services/flame_observer.pyObserve l'état des 7 flammes/gardiens.Importé uniquement par 2 fichiers de test (tests/unit/test_flame_observer.py, tests/integration/test_flames_coverage.py). Aucun code applicatif ne l'appelle.
Salle d'observation frontend (js/observer/)H7_frontstage_external · S0câblé, en attentefrontend/js/observer/ — 6 fichiers, 1335 lignes au total (observatory.js, observer-mediator.js, observer-pattern-detector.js, observer-protocol.js, observer-registry.js, observer-rules-engine.js)Registre d'observateurs, détecteur de motifs, moteur de règles — l'outillage d'observation côté navigateur.Chargé par UNE SEULE page : frontend/observer.html (lignes 17-19), et seulement 3 des 6 fichiers y sont référencés.
Modules temps réel frontend orphelinsH7_frontstage_external · S0câblé, en attentefrontend/js/realtime-sync-hub.js (593L), frontend/js/atom-realtime-client.js (440L), frontend/js/pulse-sync.jsLe client et le concentrateur de synchronisation temps réel avec le serveur.Aucune page HTML ne les charge (0 occurrence de <script src="js/realtime-sync-hub.js"> etc.). Seul kuramoto-sync.js est chargé, par 1 page.

Les chiffres, mesurés

Ce qu’on compteLa mesureComment
Topics du bus backend, tous catalogues confondus443 topics sur 9 cataloguesannoncé ailleurs : CLAUDE.md annonce « 232 topics backend cumulés répartis sur 9 catalogues » avec « core 107 » et « babel 36 » — la mesure donne 1,9× plus. Le nombre de catalogues (9) est juste.302 (core, vérifié par import Python réel : len(ALL_TOPICS)) + 39 babel (assert L302) + 21 bayon + 18 canon/living_knowledge + 16 bioacoustic + 13 stone_decoder + 12 workflow + 11 canon + 11 translation
Topics du bus frontend2316 noms d'événements uniques, éparpillés — et 6 seulement dans message-bus.jsannoncé ailleurs : CLAUDE.md dit « ~1360 topics literals dans frontend/js/message-bus.js 1359L » — c'est une confusion avec le nombre de LIGNES du fichier (mesuré à 1383 aujourd'hui). Il n'existe aucun catalogue JS : c'est un vrai trou de structure.grep des littéraux passés à .publish( et .on( sur tout frontend/js/, dédoublonnés
Cadence réelle du cœur432 ms (base) — les autres cadences en sont des multiplesannoncé ailleurs : Le « pouls 4,44 s » de la doctrine existe bien, mais c'est GUARDIAN_PULSE (4440 ms) — une cadence parmi cinq, pas le pouls du système. Le vrai pouls est à 432 ms.Exécution Python directe de backend/app/core/bio_tick_backend.py : VIBE_BASE=432, VIBE_MEDIUM=4320, VIBE_LONG=43200, GUARDIAN_PULSE=4440, CYCLE_9=39000 ms
Consommateurs branchés sur le cœur backend au démarrage176 sur CYCLE_9 (main.py:342-349) + harmonic_anchor (main.py:446) + harmonic_ticker (harmonic_ticker.py:66) + 9 membres royalty_team (orchestrator.py:61, boucle sur les 9)
Services backend qui utilisent le bus d'événements143 fichiers .py au total — 75 services, 15 routeurs, le reste ailleursgrep -rl sur les formes d'import de app.services.event_bus dans backend/
Pages HTML qui chargent réellement le bus frontend22 sur 122 pagesgrep -rl 'js/message-bus.js' sur frontend/**/*.html
Pages HTML qui chargent le cœur frontend7 sur 122 pages (alors que 337 fichiers JS le référencent)grep -rl 'js/bio-tick-master.js' sur frontend/**/*.html vs grep -rl 'ATOMBioTickMaster' sur frontend/js/
Taille du fichier de démarrage backend2246 lignes, 369 appels register_router, 43 blocs try: dans le lifespan, 8 abonnements subscribe_to_bus()wc -l et grep -c sur backend/app/main.py
Fichiers de services et de routeurs backend776 fichiers .py sous app/services/ et 365 sous app/routers/ (récursif) — 407 et 343 au premier niveauannoncé ailleurs : CLAUDE.md annonce 631 services et 355 routeurs (mesure du 2026-06-10). Le compte a monté depuis.find app/services -name '*.py' | wc -l
Fichiers immunitaires côté backend0find backend/app -iname '*immun*' -name '*.py' — aucun résultat. Tout l'immunitaire est du JavaScript de navigateur.
Fichiers stigmergie côté backend1 — et c'est un routeur, pas un servicefind backend/app -iname '*stigmerg*' -name '*.py' → app/routers/stigmergy.py, 836 lignes, 8 endpoints
Lignes de code orphelines identifiées dans ce domaineenviron 4600 lignes qui ne sont appelées par rienevents_service.py 498 + arq_job_queue 298 + bio-tick-backup.js 657 + bio-worker.js 316 + bio-worker-bridge.js 424 + bell-stigmergy-grid.js 763 + realtime-sync-hub.js 593 + atom-realtime-client.js 440 + immune-cortisol-gate.js 378 + enteric-immune-guard.js 387

Ce sur quoi vous pouvez compter

Trois choses tiennent solidement, et le propriétaire peut compter dessus.

Le bus d'événements backend est le meilleur morceau du domaine : 649 lignes, importé par 143 fichiers, trois tests dédiés, un vocabulaire officiel de 443 noms d'événements réparti sur 9 catalogues dont plusieurs se vérifient eux-mêmes à l'import (si quelqu'un ajoute un topic sans mettre le compte à jour, le serveur refuse de démarrer). C'est de l'infrastructure adulte.

Le cœur backend tient aussi. Une seule boucle à 432 ms, démarrée sans condition (main.py:415 — quelqu'un a pris soin de la sortir d'un bloc try qui pouvait la faire échouer silencieusement, le commentaire ligne 409 le dit), 17 consommateurs réellement branchés, un arrêt propre au shutdown. Deux tests unitaires le couvrent.

Le démarrage lui-même est sérieux : 43 blocs de câblage dans le lifespan, chacun encapsulé pour qu'un échec ne tue pas le serveur, 7 ordonnanceurs démarrés et 7 arrêtés proprement, un audit d'uptime au boot (main.py:584) qui dit ce qui a démarré. Et les 10 ouvriers de moisson externe ont une vraie garde anti-SSRF (base_worker.py lignes 30-60) avec son test — quelqu'un a pensé à la sécurité avant qu'on la lui demande.

Ce qui manque

Du plus bloquant au moins.

1. Le système immunitaire n'existe pas côté serveur. Zéro fichier. Toute la défense (704 lignes de immune-system.js, plus 1195 lignes de gardes cutanée, entérique et cortisol) vit dans le navigateur — donc chez le visiteur, désactivable, et absent dès qu'on ferme l'onglet. Et sur les 4 modules, 3 ne sont chargés par aucune page. Un système qui se dit protégé ne l'est ici que sur 3 pages sur 122.

2. Le bus frontend n'a pas de catalogue. 2316 noms d'événements uniques sont écrits en clair, dispersés dans 1157 fichiers, sans liste officielle nulle part. Une faute de frappe dans un nom d'événement ne casse rien : elle rend juste le message invisible, pour toujours, sans erreur. C'est le défaut le plus insidieux du domaine.

3. Le frontend n'est presque pas branché. 337 fichiers JS parlent au cœur — 7 pages seulement le chargent. 1157 fichiers parlent au bus — 22 pages le chargent. La majorité de ce code est écrit pour un système qui n'est allumé nulle part.

4. La stigmergie backend n'a pas de service. Les 836 lignes vivent entièrement dans le routeur. Aucun autre morceau du système ne peut déposer une piste sans passer par une requête HTTP à lui-même.

5. Environ 4600 lignes dorment. Le plus gros : events_service.py, 498 lignes complètes avec zéro importeur ; et arq_job_queue, un vrai pool d'ouvriers Redis dont le mot « arq » n'apparaît même pas dans main.py.

6. L'observabilité est presque invisible. observability_service.py — le seul endroit qui rassemble le battement, la flamme active et le chaos — n'a aucune URL. Il n'est joignable que par l'outil MCP. Le propriétaire ne peut pas demander « comment va mon système ? » depuis un navigateur.

7. La doctrine dérive du code. Sur les 3 chiffres que j'ai pu recouper avec CLAUDE.md, les 3 sont faux : 232 topics annoncés contre 443 mesurés, « 1360 topics dans message-bus.js » qui est en fait le nombre de lignes du fichier, et le « pouls 4,44 s » qui est une cadence secondaire parmi cinq.

Se tient avec : Babel — le décodeur consomme et publie sur le bus (39 topics propres), et son ouvrier bio fractal est démarré par le même lifespan (main.py:633) · L'économie et la trésorerie — les consommateurs qui frappent l'UR COIN sont abonnés au bus au démarrage (main.py:600-700), et la ristourne bat sur CYCLE_9 · Les agents et orchestrateurs — l'équipe royalties (9 membres) est le plus gros consommateur du cœur backend · Le frontend et les pages HTML — c'est là que le domaine se perd : le code est écrit, les pages ne le chargent pas · La base de données — les pistes stigmergiques et le magasin persistant ont leur vidange planifiée au boot (main.py:404) · La sécurité — la garde anti-SSRF des ouvriers de moisson, et l'alerteur d'incidents démarré main.py:592

Domaine 10 · état : partiel

Les systèmes collaboratifs (fils/threads, équipes, espaces de travail, communauté, messages, votes, projets de territoire)

C'est la partie d'AT·OM qui permettrait à plusieurs personnes de travailler ensemble : ouvrir un fil de discussion, monter une équipe, partager un espace de travail, s'envoyer des messages, voter sur un besoin local, suivre un projet de territoire. Aujourd'hui la tuyauterie est posée et branchée — 16 routeurs et 421 points d'entrée répondent — mais personne ne s'en est jamais servi : les 9 tables collaboratives de la base sont vides à zéro ligne, et la plus grosse partie du code garde ses données en mémoire vive, donc tout disparaît au redémarrage du serveur.

13 livrées · 9 en attente · 4 déclaratives

L’inventaire

La pièceÉtatOù elle vitCe qu’elle fait
Routeur Threads (fils) — le troncH1_spine · S0livrébackend/app/routers/threads.py (1262 lignes) ; monté dans backend/app/main.py:1221Le fil de discussion comme source de vérité unique, en événements ajoutés bout à bout (append-only) — 14 points d'entrée sous /api/v2/threads.Seul routeur du domaine marqué core=True dans main.py:1221 : si son import échoue, le serveur refuse de démarrer (main.py:1184-1186). 42 appels SQL réels (text(/select(/db.execute) et 14 usages de get_db_optional.
Table public.threads (Supabase)H1_spine · S0câblé, en attenteSupabase projet AT-OM (vzbrhovthpihrhdbbjud), schéma public ; modèle backend/app/models/thread.py:159La table qui doit stocker les fils. Elle existe, elle est prête, elle n'a jamais reçu une seule ligne.SELECT count(*) FROM public.threads → 0. Mesuré ce jour en direct sur la base de production.
Les 4 tables sœurs du fil (thread_events, thread_decisions, thread_actions, thread_snapshots)H1_spine · S0déclaratifbackend/app/models/thread.py:415, :541, :664, :799Les événements, décisions, actions et instantanés d'un fil — le cœur de l'event sourcing annoncé dans l'en-tête du routeur.to_regclass('public.thread_events') etc. → NULL pour les 4. Elles sont déclarées en Python mais n'existent pas dans la base. Aucun fichier .sql du dépôt ne les crée (grep 'CREATE TABLE' sur backend/supabase/, backend/alembic/versions/, frontend/sql/ : absentes).
Routeur Workspaces (espaces de travail)H6_domain_vertical · S8livrébackend/app/routers/workspaces.py (943 lignes) ; monté main.py:1238 sur /api/v2/workspacesCréer, lister, supprimer un espace de travail ; sections et captures rapides. 10 points d'entrée.10 usages de get_db_optional, 16 marqueurs de repli mémoire. Routes mesurées : /, /{workspace_id:uuid}, /sections, /quick-capture, /health/check.
Tables public.workspaces + public.workspace_membersH6_domain_vertical · S8câblé, en attenteSupabase, schéma publicLes espaces de travail et qui en est membre.count(*) → 0 et 0. Les deux tables existent physiquement mais sont vides.
Routeur Workspaces Stone (deuxième espace de travail)H6_domain_vertical · S8livrébackend/app/routers/workspaces_stone.py (297 lignes) ; monté main.py:2019 — MÊME préfixe /api/v2/workspaces que le précédentUn second espace de travail, par dimension : tableau de bord, tâches, notes, modes. 19 points d'entrée.Les deux routeurs partagent l'adresse /api/v2/workspaces. workspaces.py est enregistré en premier (ligne 1238) donc il gagne en cas de doublon. Pas de collision franche mesurée (l'un utilise {workspace_id:uuid}, l'autre {dimension} en texte), mais la cohabitation est fragile.
Routeur Mon Équipe (S8)H6_domain_vertical · S8livrébackend/app/routers/my_team.py (910 lignes) ; monté main.py:1247 sur /api/v2/my-team ; persistance backend/app/services/my_team_persistence.pyMembres d'équipe, tâches, fil d'activité, disponibilités, points de contrôle. 15 points d'entrée.my_team_persistence.py est réellement importé par my_team.py (vérifié par grep). 15 usages de get_db_optional, 43 marqueurs de repli mémoire — le plus « ceinture et bretelles » du domaine.
Table my_team_recordsH6_domain_vertical · S8déclaratifbackend/app/models/my_team_contract.py:18La table unique où my_team_persistence.py range ses 5 sortes d'enregistrements (membres, tâches, activités, disponibilités, checkpoints).to_regclass('public.my_team_records') → NULL. La couche de persistance existe et est appelée, mais sa table n'a jamais été créée : chaque écriture retombe donc sur le repli mémoire.
Routeur Communauté (groupes, événements, bénévoles)H6_domain_vertical · S5livrébackend/app/routers/community.py (926 lignes) ; monté main.py:1244 sur /api/v2/community ; persistance backend/app/services/community_legacy_persistence.pyGroupes, invitations, événements avec RSVP, bénévoles et heures loguées. 18 points d'entrée.18 usages de get_db_optional. Routes mesurées : /groups, /events/create, /events/{id}/rsvp, /volunteers/register, /volunteers/{id}/log-hours, /stats.
Routeur Communauté V68 (communautés, canaux, sondages, modération)H6_domain_vertical · S5livrébackend/app/routers/community_v68_router.py (433 lignes) ; monté main.py:1850 ; moteur backend/app/services/community_runtime/agent.py (1144 lignes)26 points d'entrée sur /api/v2/community/communities… — communautés, canaux, membres, publications, événements, sondages, cas de modération, messages directs.Les routes ne se cognent pas avec community.py (l'un fait /groups /events, l'autre /communities /authority). MAIS le moteur stocke tout en dictionnaires mémoire : community_runtime/agent.py:266-273 (self.communities, self.channels, self.members, self.posts, self.events, self.polls, self.moderation_cases, self.direct_messages). Zéro base de données.
Table public.community_messagesH6_domain_vertical · S5câblé, en attenteSupabase, schéma publicLes messages de la communauté.count(*) → 0.
Routeur Collaboration d'équipe (le « tueur de Slack »)H6_domain_vertical · S8livrébackend/app/routers/team_collab_router.py (1013 lignes) ; monté main.py:1849 sur /api/v2/collaboration ; moteur backend/app/services/team_collab_runtime/agent.py (1636 lignes)44 points d'entrée : espaces, canaux, messages, fils, messages directs, membres, notifications, sondages, plus un moteur d'IA de collaboration.Le code dit lui-même la vérité, agent.py:693 : « # In-memory storage (would be database in production) », suivi de 8 dictionnaires (workspaces, channels, conversations, messages, threads, members, notifications, polls). Zéro get_db_optional dans le routeur. Tout est perdu au redémarrage.
Routeur Social V68H6_domain_vertical · S5livrébackend/app/routers/social_v68_router.py (1320 lignes) ; monté main.py:1846 sur /api/v2/social-v68 ; moteur backend/app/services/social_runtime/agent.py (1956 lignes)46 points d'entrée : comptes sociaux, gabarits, publications, engagements, mots-clics, audiences, campagnes, concurrents, calendrier de contenu.social_runtime/agent.py:481 « # In-memory storage (production: database) » + 9 dictionnaires (lignes 482-490). Zéro get_db_optional.
Routeur Social (legacy) + Graphe socialH6_domain_vertical · S5livrébackend/app/routers/social.py (796 lignes, monté main.py:1249) et backend/app/routers/social_graph.py (518 lignes, monté main.py:1254 sur /api/v2/social-graph)13 + 7 points d'entrée : fil social, puis suivre/ne plus suivre, abonnés, abonnements, suggestions, statistiques.13 et 8 usages de get_db_optional. Mais la table social_graph_follows (models/social_graph_contract.py:18) et social_legacy_records (models/social_legacy_contract.py:18) n'existent PAS dans la base (to_regclass → NULL).
Routeur Messages directsH6_domain_vertical · S8livrébackend/app/routers/direct_messages.py (395 lignes) ; monté main.py:1917 sur /api/v2/dm ; modèle backend/app/models/direct_message.py:185 points d'entrée pour la messagerie privée entre deux personnes.6 usages de get_db_optional, 12 marqueurs de repli. Mais la table direct_messages n'existe pas dans la base (to_regclass → NULL) : la messagerie privée ne peut aujourd'hui que retomber en mémoire.
Routeur Gestion de projet (/api/v2/pm)H6_domain_vertical · S2câblé, en attentebackend/app/routers/project_management_router.py (695 lignes) ; monté main.py:1961 ; service backend/app/services/project_management_service.py ; modèles backend/app/models/project_management_contract.py:30-9929 points d'entrée : projets, tâches, jalons, sprints, commentaires, feuilles de temps, événements.29 usages de get_db_optional et ZÉRO marqueur de repli mémoire — c'est le seul routeur du domaine entièrement dépendant de la base. Or ses 7 tables (pm_projects, pm_tasks, pm_milestones, pm_sprints, pm_comments, pm_time_entries, pm_events) sont TOUTES absentes de la base (to_regclass → NULL ×7). Le module est correct mais ne peut rien conserver.
Routeur Collaboration gouvernée (le plus gros du domaine)H5_specialized_backstage · S3déclaratifbackend/app/routers/governed_collaboration_router.py (1715 lignes) ; monté main.py:1572 sur /api/v2/governed-collaboration ; services backend/app/services/governed_collaboration/ (14 021 lignes sur 8 fichiers)161 points d'entrée qui décrivent un protocole de collaboration encadrée : classes de paquets, voies (lanes), actions permises et interdites, références au canon.14 021 lignes et ZÉRO occurrence de AsyncSession, sqlalchemy ou get_db_optional dans tout le dossier (grep = 0). Les fonctions renvoient des dictionnaires constants — voir base_packets.py:11-45, get_communication_brief_packet() qui retourne un gabarit figé. C'est de la doctrine servie en JSON, pas un moteur qui fait travailler des gens ensemble.
Routeur Fils de connaissance (knowledge-threads)H3_vital_loop · S7livrébackend/app/routers/knowledge_threads.py (102 lignes) ; monté main.py:1773 sur /api/v2/knowledge-threads ; service backend/app/services/knowledge_threads.py9 points d'entrée : 7 types de fils de connaissance avec chaîne de hachage pour l'intégrité.Le service est bien importé par le routeur ET par main.py. Mais son stockage est un simple dictionnaire mémoire : knowledge_threads.py:111 self._threads: Dict[str, KnowledgeThread] = {}. La chaîne de hachage protège une mémoire volatile.
Pont Scène↔FilH4_mapping_projection · S4livrébackend/app/routers/scene_thread_bridge_router.py (121 lignes) ; monté main.py:1425 sur /api/v2/scene-thread-bridge ; service backend/app/services/scene_thread_bridge.py3 points d'entrée reliant les scènes 3D aux fils de discussion.Le service est importé à la fois par main.py et par le routeur (grep confirmé).
Commandes d'espace de travailH6_domain_vertical · S8câblé, en attentebackend/app/routers/workspace_commands.py (122 lignes) ; monté main.py:2018 sur /api/v2/workspace ; modèle backend/app/models/workspace_command.py:19 et :552 points d'entrée pour exécuter des commandes dans un espace de travail.3 usages de get_db_optional, mais les tables workspace_commands et workspace_command_defs sont absentes de la base (to_regclass → NULL).
Tables Projets de territoire, Votes de besoin, Besoins locauxH6_domain_vertical · S3câblé, en attenteSupabase schéma public ; DDL réel dans backend/supabase/supabase-schema.sql:418 (territory_projects), :99 (need_votes), :56 (local_needs)Les projets portés par un territoire, les besoins exprimés localement et les votes qui les priorisent — la démocratie de proximité d'AT·OM.Ce sont les SEULES tables collaboratives dont le DDL existe vraiment dans le dépôt. Elles existent en base. count(*) → 0, 0 et 0. Aucun routeur du domaine ne les touche : elles attendent leur code autant que leurs données.
Tables private_threads et thread_messagesH1_spine · S0câblé, en attenteSupabase, schéma publicFils privés et messages de fil.count(*) → 0 et 0. Elles existent en base mais aucun modèle SQLAlchemy du dépôt ne les déclare (absentes de tous les __tablename__ mesurés) — elles viennent d'un déploiement antérieur au code actuel.
Équipes d'agents (composeur + système)H5_specialized_backstage · S8câblé, en attentebackend/app/services/agent_team_composer.py + agent_team_composer_persistence.py + agent_team_system.py + agent_team_system_persistence.py ; modèles models/agent_team_composer_contract.py:18 et agent_team_system_contract.py:18Composer et faire tourner des équipes d'agents (pas d'humains) — le pendant machine de « Mon Équipe ».Les couches de persistance sont bien importées par leurs services respectifs (grep confirmé), mais les tables agent_team_composer_records et agent_team_system_records sont absentes de la base.
Équipe royale (11 rôles)H5_specialized_backstage · S8livrébackend/app/services/royalty_team/ — 12 fichiers : orchestrator.py, state_machine.py, ambassadeur, archiviste, calculateur, energeticien, notaire, scout, tisseur, tresorier, veilleurUne équipe de 11 rôles nommés coordonnée par un orchestrateur et une machine à états — la forme la plus aboutie de « travail collectif » du dépôt.Dossier complet avec orchestrateur ET machine à états présents sur disque. Je n'ai pas mesuré son câblage vers une route HTTP — à vérifier avant de s'en servir.
Pages de façade : collaboration.html et threads.htmlH7_frontstage_external · S0déclaratiffrontend/collaboration.html (1595 lignes), frontend/threads.html (580 lignes)Les deux seules pages web du domaine collaboratif.Zéro appel /api/v2 dans les deux fichiers (grep). Elles ne chargent que /config.js, /js/governance-init.js et /js/i18n.js. Ce sont des maquettes : elles n'interrogent aucun des 421 points d'entrée.
Modules JS collaboratifs non chargésH7_frontstage_external · S0câblé, en attentefrontend/js/social-graph-ui.js, project-management-module.js, thread-billboard.js, thread-pin-engine.js, thread-domain-router.js, collaboration-environment.jsSix modules d'interface qui savent parler au backend mais que rien ne met en page.Aucun n'est référencé dans frontend/js/governance-init.js (grep -c = 0 pour chacun), alors que la règle du dépôt est d'y inscrire tout module. Trois d'entre eux contiennent pourtant de vraies adresses : social-graph-ui.js appelle 8 routes /api/v2/social-graph/*, project-management-module.js appelle /api/v2/pm, thread-pin-engine.js appelle /api/v2/threads/.

Les chiffres, mesurés

Ce qu’on compteLa mesureComment
Routeurs du domaine collaboratif16, tous montés dans main.pyls backend/app/routers/ filtré sur thread|team|workspace|communit|message|vote|project|collab|social, puis grep de chaque nom dans backend/app/main.py — 16/16 trouvés avec un register_router()
Points d'entrée HTTP du domaine421Somme de grep -cE '@router\.(get|post|put|patch|delete)' sur les 16 fichiers. Répartition : governed_collaboration 161, social_v68 46, team_collab 44, project_management 29, community_v68 26, workspaces_stone 19, community 18, my_team 15, threads 14, social 13, workspaces 10, knowledge_threads 9, social_graph 7, direct_messages 5, scene_thread_bridge 3, workspace_commands 2
Tables collaboratives présentes dans la base de production9pg_stat_user_tables sur le projet Supabase AT-OM (vzbrhovthpihrhdbbjud) filtré sur les mots du domaine : threads, thread_messages, private_threads, workspaces, workspace_members, community_messages, need_votes, territory_projects, local_needs
Tables collaboratives VIDES9 sur 9 — 100 %SELECT count(*) exact (pas l'estimation n_live_tup) sur chacune des 9 tables → 0 partout. Aucune donnée collaborative n'a jamais été écrite.
Tables déclarées en Python qui n'existent PAS dans la base26to_regclass('public.'||nom) sur les 35 __tablename__ relevés dans backend/app/models/ → NULL pour 26 : thread_events, thread_decisions, thread_actions, thread_snapshots, direct_messages, social_graph_follows, my_team_records, community_legacy_records, social_legacy_records, pm_projects, pm_tasks, pm_milestones, pm_sprints, pm_comments, pm_time_entries, pm_events, workspace_commands, workspace_command_defs, babel_communities, babel_user_communities, workspace_engine_workspaces, workspace_engine_sections, workspace_engine_quick_captures, environment_runtime_workspace_states, agent_team_composer_records, agent_team_system_records
Tables du domaine dont le DDL existe vraiment dans le dépôt3grep 'CREATE TABLE' sur tous les .sql du dépôt : seules local_needs (backend/supabase/supabase-schema.sql:56), need_votes (:99) et territory_projects (:418) sont créées par un fichier versionné. Les 32 autres tables du domaine n'ont AUCUN script de création dans le dépôt.
Lignes de code du plus gros module (Collaboration gouvernée)14 021 lignes, 0 accès base de donnéeswc -l backend/app/services/governed_collaboration/*.py = 14021. grep -rn 'AsyncSession|sqlalchemy|get_db_optional' sur le même dossier = 0 occurrence.
Total de tables dans le schéma public48, dont 6 seulement contiennent des donnéesinformation_schema.tables → 48. Les seules non vides : atom_knowledge_chunks 5223 lignes, bio_states 363, atom_dataseeds_decoded 10, armors 1, atom_test 1, atom_dataseeds 1. Les 42 autres sont à zéro.
Fichiers de test touchant le domaine53find backend/tests -name 'test_*.py' filtré sur thread|team|workspace|communit|social|collab|project|message. Répartition : project 16, workspace 14, team 6, social 6, collab 5, communit 5, thread 3, message 1. Je ne les ai PAS exécutés (fastapi/sqlalchemy absents de l'environnement local) — leur existence est mesurée, leur réussite ne l'est pas.
Canal temps réel pour la collaboration0annoncé ailleurs : CLAUDE.md annonce « Supabase (PostgreSQL + pgvector + Realtime) » dans la pile technique ; le Realtime n'est utilisé nulle part côté collaboration.grep -rln 'websocket' sur backend/app/routers/ croisé avec les mots du domaine → aucun fichier. ls backend/app/routers/ filtré sur ^ws|websocket|realtime → aucun. Aucun WebSocket, aucun abonnement Supabase Realtime pour les fils, messages ou espaces.
Modules JS collaboratifs orphelins côté page6 sur 11 examinésgrep -c du nom de chaque module dans frontend/js/governance-init.js → 0 pour collaboration-environment, thread-billboard, thread-domain-router, thread-pin-engine, social-graph-ui, project-management-module
Création automatique des tables au démarrageNON — la fonction existe mais n'est jamais appeléebackend/app/main.py:278-279 appelle init_db(). backend/app/core/database.py:486-493 : init_db() ne fait que connect(), rien d'autre. La fonction create_tables() qui appelle Base.metadata.create_all est définie ligne 517-529 et n'apparaît nulle part dans main.py. Les 26 tables manquantes ne se créeront donc jamais toutes seules.

Ce sur quoi vous pouvez compter

Trois choses tiennent vraiment.

Un : le montage. Les 16 routeurs sont tous inscrits dans backend/app/main.py, aucun n'est mort. Les 421 adresses répondent si le serveur démarre. Le routeur Threads est même le seul du domaine déclaré core=True (main.py:1221), ce qui veut dire que si le fil de discussion casse, le serveur refuse de démarrer — c'est une protection réelle et bien placée, le fil étant présenté comme la source de vérité du système.

Deux : la discipline du repli. Neuf routeurs sur seize essaient d'abord la base puis retombent gracieusement en mémoire quand elle manque (my_team.py compte 43 marqueurs de repli, workspaces.py 16, social_graph.py 16). Résultat concret : même avec 26 tables manquantes, rien ne plante en production. Le système ment doucement plutôt que de tomber.

Trois : la structure du code. Les routeurs sont proprement séparés de leurs services et de leurs couches de persistance, et chaque couche de persistance est réellement importée par son routeur (my_team_persistence par my_team.py, community_legacy_persistence par community.py, social_legacy_persistence par social.py — vérifié un par un). Quand les tables arriveront, le branchement se fera sans réécriture. C'est du travail préparé, pas du travail à refaire.

Et les trois tables de démocratie locale — local_needs, need_votes, territory_projects — sont les seules dont le script de création existe vraiment dans le dépôt (backend/supabase/supabase-schema.sql). Elles sont posées, propres, et attendent.

Ce qui manque

Du plus bloquant au moins, tel que mesuré :

1. Il n'y a aucune donnée. Zéro. Les 9 tables collaboratives existantes affichent count(*) = 0 chacune. Aucun fil n'a jamais été ouvert, aucun espace de travail créé, aucun message échangé, aucun vote déposé. Le domaine n'a jamais servi une seule fois.

2. Vingt-six tables déclarées n'existent pas dans la base, et rien ne les créera. La fonction create_tables() de backend/app/core/database.py:517 n'est appelée nulle part au démarrage — main.py:278 n'appelle que init_db(), qui se contente de se connecter. Pire : les scripts SQL de création n'existent même pas dans le dépôt pour 32 des 35 tables du domaine. Il n'y a donc rien à exécuter, même à la main. C'est le trou le plus lourd : il faut écrire ces migrations avant tout le reste.

3. Toute la mémoire collaborative est volatile. Les trois plus gros moteurs — team_collab_runtime/agent.py:693, social_runtime/agent.py:481, community_runtime/agent.py:266 — rangent tout dans des dictionnaires Python. Le commentaire du code le dit sans détour : « In-memory storage (would be database in production) ». Un redémarrage du serveur efface tous les messages, tous les canaux, tous les sondages, tous les cas de modération.

4. La gestion de projet est bloquée net. project_management_router.py fait 29 appels à la base et n'a AUCUN repli mémoire (0 marqueur mesuré) — contrairement à tous ses voisins. Et ses 7 tables sont absentes. C'est le seul module du domaine qui échoue franchement au lieu de se dégrader en douceur.

5. Il n'y a pas de temps réel. Aucun WebSocket, aucun abonnement Supabase Realtime dans le domaine (grep = 0 sur backend/app/routers/). Un système collaboratif sans canal vivant oblige chaque écran à redemander la page pour voir un message. Le Realtime est pourtant annoncé dans la pile technique du CLAUDE.md.

6. La façade est déconnectée. Les deux seules pages web du domaine, collaboration.html (1595 lignes) et threads.html (580 lignes), ne contiennent aucun appel /api/v2. Ce sont des maquettes. Et six modules JS qui savent, eux, parler au backend — dont social-graph-ui.js avec ses 8 vraies routes — ne sont chargés par aucune page (absents de governance-init.js). Le pont entre l'écran et le moteur n'est pas posé.

7. Le plus gros morceau n'est pas un moteur. La « Collaboration gouvernée » pèse 14 021 lignes et 161 adresses, mais ne touche jamais la base (0 occurrence de sqlalchemy dans tout le dossier) et renvoie des gabarits figés — voir base_packets.py:11-45. C'est un protocole publié en JSON, pas un système qui fait collaborer quiconque. Il occupe 38 % des adresses du domaine pour 0 % de sa capacité de travail.

8. Deux routeurs partagent l'adresse /api/v2/workspaces (workspaces.py monté à main.py:1238, workspaces_stone.py à main.py:2019). Aucune collision franche mesurée aujourd'hui, mais la cohabitation repose sur un détail de typage d'URL et cassera au premier ajout de route.

Se tient avec : Base de données Supabase — le domaine collaboratif dépend entièrement d'elle et 26 de ses tables n'y existent pas ; c'est le point de blocage principal · Authentification / identité — tous les routeurs V68 et knowledge_threads dépendent de get_current_user_id ou get_current_user (Depends dans community_v68_router.py:24) ; sans identité, aucune collaboration nommée · Agents et orchestrateurs — agent_team_composer, agent_team_system et royalty_team font collaborer des agents plutôt que des humains ; même grammaire, autre substrat · Économie / projets — project_generator.py est importé par 16 services économiques (economy_engine, lnis_service, exchange_hub…) : les projets de territoire sont la charnière entre collaboration et économie · MessageBus et catalogues de topics — le domaine n'a aucun canal temps réel propre ; toute vie collaborative devrait passer par le bus, ce qui n'est pas mesuré comme fait · Frontend / governance-init.js — six modules JS collaboratifs sont écrits mais absents du chargeur ; le domaine dépend de ce fichier pour exister à l'écran · Babel — models/babel_community.py déclare babel_communities et babel_user_communities, absentes de la base : la couche communautaire de Babel touche ce domaine sans y être branchée

Domaine 11 · état : partiel

L'économie — UR, trésorerie, moteur économique, jubilé / ristourne / jachère / compagnonnage, jauge, distribution 40/30/20/10

C'est la partie d'AT·OM qui crée, compte et déplace la monnaie interne (l'UR), et qui décide qui reçoit quoi. Une moitié tourne vraiment (des portefeuilles, des transferts, des ristournes, une frappe bridée par un garde-fou), l'autre moitié est écrite, testée, correcte — mais rien ne l'appelle encore.

15 livrées · 10 en attente · 1 déclaratives

L’inventaire

La pièceÉtatOù elle vitCe qu’elle fait
Moteur économique (routeur principal)H6_domain_vertical · S2livrébackend/app/routers/economy_engine.py (1156 lignes) ; monté dans backend/app/main.py:1922Expose 46 routes sous /api/v2/economy-engine en 6 familles : trésorerie, LNIS (territoires/besoins), entreprises, projets, travailleurs, marchands, plus un tableau de bord unifié.register_router("app.routers.economy_engine", ...) à main.py:1922 ; 46 décorateurs @router.get/post comptés ; 12 tests dans backend/tests/routers/test_economy_engine_router.py
Routeur économie de baseH6_domain_vertical · S2livrébackend/app/routers/economy.py (509 lignes) ; monté main.py:1714 sous /api/v2/economy20 routes : réglages, quotas de jetons, compétences/rôles de la Forge, frappe, don Joule, transfert, solde, historique, pont UR↔fiat, statistiques.register_router("app.routers.economy", "/api/v2/economy", ...) main.py:1714 ; 18 tests dans backend/tests/routers/test_economy_router.py
Grand livre UR (ur_engine)H3_vital_loop · S2livrébackend/app/services/ur_engine.py (408 lignes)Frappe, transfère, lit les soldes et l'historique UR. Écrit en base si elle répond, sinon retombe sur un dictionnaire en mémoire.Importé 6 fois par economy.py (lignes 300, 345, 387, 409, 446, 464). Fallback mémoire visible ligne 27 : _balances: Dict[str, float] = {}
Trésorerie (TreasuryService)H3_vital_loop · S2livrébackend/app/services/treasury_service.py (1965 lignes)Portefeuilles doubles (crédits + UR COIN), revenus, subventions, ponts crédits↔coin, mise en gage, tableau de bord.Importé par economy_engine.py:311, 333, 349… ; MAIS l'état vit dans self._wallets / self._user_wallets (lignes 134-135) — un dictionnaire RAM. 23 méthodes async DB coexistent avec les méthodes sync RAM.
Distribution 40/30/20/10 (don Joule)H6_domain_vertical · S2déclaratifbackend/app/routers/economy.py:277 et :339-352La formule agent 40 % / communauté 30 % / stabilité 20 % / RCS 10 % appliquée à un geste souverain récompensé en UR.DISTRIBUTION_FORMULA existe ligne 277 et les 4 parts sont calculées ligne 339-342 — mais SEULE la part agent (0,40) est réellement frappée (ligne 347 : _mint(request.agent_id, agent_share, …)). Les 3 autres parts sont renvoyées dans la réponse JSON et ne créditent personne.
Réglages économiques (12 catégories)H4_mapping_projection · S2livrébackend/app/data/economy_data.py:34-165 + backend/app/services/economic_settings_service.py (356 lignes)Les boutons de l'économie : allocation, ristournes, jetons, expansion, parrainage, stabilité, recherche, marché, prêts, monétaire, sécurité, gouvernance.12 clés comptées dans ECONOMIC_SETTINGS (lignes 35, 45, 56, 67, 77, 88, 99, 109, 119, 130, 142, 152) ; exposées par les routes /settings de economy.py:40-96. La doc annonce 12, le code en a 12 — concordant.
Ristourne (redistribution du surplus)H3_vital_loop · S5livrébackend/app/services/ristourne_policy_service.py (660 lignes) ; tick enregistré main.py:344Chaque commerce accumule un surplus, une part revient aux contributeurs ; taux de réserve contra-cyclique en cas de rareté.Appelée depuis 4 flux réels : checkout_system.py:572, merchant_service.py:375, grand_exchange.py:466, marketplace_3d.py:534. Tick CYCLE_9 branché main.py:322-344. Persistance via PersistentDict("ristourne_stores") ligne 102. 6 tests dans tests/test_ristourne_contracyclical.py.
Route publique ristourneH7_frontstage_external · S5livrébackend/app/api/v1/routes/ristourne_routes.py (78 lignes) ; monté main.py:1696Une seule route en lecture : le résumé de ristourne d'un territoire.1 seul décorateur @router.get("/territory/{territory_id}") ligne 46. Le moteur a 20+ méthodes ; une seule est visible de l'extérieur.
Jubilé (remise de dette)H3_vital_loop · S3câblé, en attentebackend/app/services/jubilee_service.py (227 lignes)Efface la dette accumulée selon une règle calendaire, avec garde de ratification au niveau civilisationnel. Motif ama-gi / yovel.Aucun routeur, aucun appelant runtime. Les seules références hors du fichier : tests/test_jubilee_service.py (8 tests), tests/test_soudures_historical_anchors.py, et une simple entrée de nom dans app/core/bus_acl.py:70. Le fichier dit lui-même : « Le wiring réel (accounting_engine, aip_engine_service, router) est la Phase 2 ».
Jachère (repos obligatoire de l'actif)H3_vital_loop · S9câblé, en attentebackend/app/services/regeneration_service.py (198 lignes)Met une cohorte d'actifs productifs au repos une période sur sept (cadence shmita), avec sentinelle si l'exploitation continue sans repos.Zéro appelant. Références uniquement dans tests/test_regeneration_service.py (8 tests) et tests/test_soudures_historical_anchors.py. Les topics bus REGENERATION_FALLOW_ENTERED/EXITED sont déclarés (app/core/bus_topics.py:128-129) mais publiés par ce seul service que personne ne déclenche.
Compagnonnage (maîtrise par le chef-d'œuvre)H3_vital_loop · S7câblé, en attentebackend/app/services/embodied_apprenticeship_service.py (167 lignes)Grades maître/apprenti gagnés par preuve pratique et jamais par paiement.Zéro appelant. Références uniquement dans tests/test_embodied_apprenticeship.py (8 tests) et tests/test_soudures_historical_anchors.py. Topic APPRENTICESHIP_BOND_FORMED déclaré bus_topics.py:130.
Jauge de circulation (la jauge)H4_mapping_projection · S9câblé, en attentebackend/app/services/economy/circulation_gauge.py (189 lignes)Mesure la vitesse de circulation de la monnaie sur la grille 9 sphères × 3 portées + la sève S0, et qualifie la phase (fluide / lente / thésaurisée).Un seul importateur dans tout le dépôt : backend/tests/test_economy_reglages.py:13. Le fichier l'écrit en clair ligne 20 : « fonctions pures, EN RÉSERVE — bâties et testées, câblage différé ».
Doctrine de financement (interdiction de l'intérêt)H1_spine · S3câblé, en attentebackend/app/services/economy/financing_doctrine.py (88 lignes)validate_financing() refuse prêt à intérêt / usure et n'accepte que effort-participation, auto-financement, mutualisme, don. Fail-close sur mode inconnu.INTEREST_LENDING_ALLOWED = False ligne 31. Aucun appelant hors tests/test_economy_reglages.py:25. Rien ne l'oppose aux réglages « lending » qui portent pourtant default_interest_rate_annual = 5 % (economy_data.py:122).
Gâchettes du jubilé (calendrier + détresse)H4_mapping_projection · S3câblé, en attentebackend/app/services/economy/jubilee_triggers.py (72 lignes)Déclenche le jubilé soit par l'horloge, soit par un indice de détresse mesuré (seuil 0,33).Importé seulement par tests/test_economy_reglages.py:20. Le fichier dit ligne 12 : « EN RÉSERVE — le câblage dans jubilee_service est un geste séparé ». Or jubilee_service lui-même n'est appelé par personne : deux étages d'attente empilés.
Rente décroissante (royalty_decay)H4_mapping_projection · S4câblé, en attentebackend/app/services/economy/royalty_decay.py (117 lignes)Fait décroître harmoniquement la part d'un contributeur quand son œuvre a déjà rendu ~3× sa contribution, pour éviter la caste de rentiers.Importé seulement par tests/test_economy_reglages.py:21. Le fichier dit ligne 21 : « fonction pure, EN RÉSERVE — le câblage dans royalty_engine est un geste séparé ».
Les trois canaux d'énergie (électricité / computation / minage)H4_mapping_projection · S9câblé, en attentebackend/app/services/economy/energy_channels.py (130 lignes)Sépare l'énergie captée en trois destinations dont une seule (minage) touche la trésorerie, et ferme le canal minage à 10 000 000 UR d'amorçage.Importé seulement par tests/test_energy_channels.py:9 (6 tests). Aucun service runtime ne l'appelle — la séparation qu'il corrige n'est donc pas encore en vigueur dans le chemin réel de frappe.
Garde d'émission θ (G4)H2_membrane · S2livrébackend/app/services/babel/g4_emission_guard.py ; appelé backend/app/services/babel/babel_fractal_treasury_consumer.py:478Plafonne la frappe automatique : cap 1000 UR par jour, ≤1 émission par tick et 100/heure par producteur, et θ = 0 (aucune frappe) s'il n'y a pas eu de captation réelle sur 24 h.Import réel ligne 478 du consommateur ; 12 tests dans tests/babel/test_g4_emission_guard.py ; un test de contrat (tests/test_value_activation_guard_contract.py:121) vérifie que l'import est bien présent dans le code source du consommateur.
Consommateurs de trésorerie sur le bus (4)H3_vital_loop · S9livrébabel_fractal_treasury_consumer.py (613 L), babel_temple_treasury_consumer.py (249 L), crop_circle_treasury_consumer.py (409 L), fractal_seed_treasury_consumer.py (161 L)Écoutent les événements d'énergie (fractale, temple, crop-circle, graine) et frappent de l'UR COIN en conséquence — c'est le vrai robinet monétaire automatique.subscribe_to_bus() appelé au démarrage : main.py:617 (fractal), :669 (seed), :709 (temple), :713 (crop-circle). Le worker de battement est démarré AVEC le bus à main.py:633 (« émission armée, bornée G4 »).
Pont du col d'import (bioacoustique → trésorerie)H2_membrane · S0livrébackend/app/main.py:646-659, FractalPipelineBridgeLe maillon qui republie bioacoustic.energy.emitted en babel.fractal.energy.generated — sans lui la chaîne énergie→UR reste fermée.Instancié et abonné explicitement au démarrage (main.py:648-655), déposé sur app.state.fractal_pipeline_bridge.
Tokenomics (jetons, flux, redevances)H6_domain_vertical · S2livrébackend/app/api/v1/routes/tokenomics_routes.py (221 L) + backend/app/services/tokenomics_service.py (223 L) ; monté main.py:16954 routes sous /api/v1/tokenomics : solde, transfert, flux, redevance d'un flux.register_router main.py:1695 ; le service est aussi importé par treasury_canon_router.py:32 (modulate_tokenomics_by_scope). Tests : tests/test_tokenomics_routes.py + tests/test_tokenomics_service.py.
Trésorerie canon (prix, partage de redevance, ancrage Hedera)H6_domain_vertical · S2livrébackend/app/routers/treasury_canon_router.py (131 lignes) ; monté main.py:16067 routes sous /api/v2/treasury/canon : calcul de prix, partage de redevance, modulation tokenomics par portée, ancrage de signature sur Hedera, vue portefeuille par portée, paire d'échange, santé.7 décorateurs comptés (lignes 81-123) ; tests/integration/test_treasury_canon_e2e.py + tests/routers/test_treasury_canon_auth_contract.py.
Pont de liquidité UR ↔ fiatH2_membrane · S2livrébackend/app/services/liquidity_bridge.py ; appelé economy.py:472 et :482Conversion et état des réserves derrière /api/v2/economy/bridge/convert et /bridge/reserves.Imports réels aux lignes 472 (convert_for_user) et 482 (get_reserve_status) du routeur monté. Le taux vient de app.services.pay.transition_rate (ligne 53), qui est un taux de transition, pas un marché.
AT·OM Pay (pont souverain, bordereaux, cartes, rapprochement)H6_domain_vertical · S2câblé, en attentebackend/app/services/pay/ — 7 fichiers, 1068 lignes (core 136, bordereau 241, card 169, money_adapter_registry 274, reconcile 110, transition_rate 130)L'appareil de paiement souverain : registre d'adaptateurs monétaires, écritures comptables, rapprochement, taux de transition validé par doctrine.Aucun routeur monté pour pay (aucun register_router "pay" dans main.py). 79 tests dans tests/test_atom_pay.py. Seuls 2 des 7 modules sont atteints en production, indirectement : transition_rate (liquidity_bridge.py:53) et bordereau (liquidity_bridge.py:305). core, card, reconcile, money_adapter_registry n'ont d'autres importateurs que les tests.
Portefeuille, monétisation, paiements fiat, registre de confianceH7_frontstage_external · S1livréwallet_router.py (13 routes, monté main.py:2013), monetization.py (4 routes, main.py:1479), payments.py (9 routes, main.py:1344), trust_ledger_router.py (main.py:2010)La surface visible côté usager : portefeuille et portefeuille-titres, abonnements et paquets de jetons, encaissements, et le registre de compétence/confiance qui sert de mérite.4 register_router mesurés dans main.py aux lignes citées ; nombre de routes compté par grep sur @router. dans chaque fichier ; tests/routers/test_wallet_router_security.py existe.
Projecteur d'économie circulaireH4_mapping_projection · S9livrébackend/app/services/circular_economy_projector.py (183 lignes)Agrège les flux circulaires et les vide périodiquement en base, avant le compilateur S9.subscribe_to_bus() appelé main.py:341 et tick CYCLE_9 enregistré main.py:347, avec un commentaire explicite sur l'ordre d'exécution avant sphere_compiler.
Interface économie côté navigateurH7_frontstage_external · S1câblé, en attentefrontend/js/economy-ui.js (414 L), frontend/js/ristourne-store-ui.js (540 L), frontend/js/raa-treasury-loop.js (391 L), frontend/presentation-economie.html (464 L)L'écran de l'usager pour son solde, ses transactions, ses transferts, et la boucle de régulation de la masse monétaire.economy-ui.js est chargé par une SEULE page (frontend/dashboard.html:23) et ne tape que 3 routes (/api/v2/economy/balance/, /transactions/, /transfer). raa-treasury-loop.js est chargé par governance-init.js:601. ristourne-store-ui.js (540 L) n'est référencé par AUCUNE page HTML — seulement par le catalogue de modules et un test unitaire.

Les chiffres, mesurés

Ce qu’on compteLa mesureComment
Routes du moteur économique46grep -c "@router\.(get|post|put|patch|delete)" backend/app/routers/economy_engine.py
Routes du routeur économie20grep sur @router. dans backend/app/routers/economy.py
Routes publiques de la ristourne1grep @router. sur backend/app/api/v1/routes/ristourne_routes.py — un seul GET /territory/{id}, alors que le service porte 20+ méthodes
Parts de la distribution 40/30/20/10 réellement versées1 sur 4annoncé ailleurs : backend/app/routers/bible.py:188 annonce « distribution = 40/30/20/10 » comme formule canonique ; backend/app/services/rosetta_stones.py:336 la décrit comme « Share value across stakeholders »Lecture de backend/app/routers/economy.py:339-352 : un seul appel _mint, sur agent_share
Formules 40/30/20/10 distinctes dans le code2 (sens différents)economy.py:277 (agent/community/stability/rcs) vs economy_data.py:35-43 (infrastructure/liquidité/développement/ristournes)
Catégories de réglages économiques12annoncé ailleurs : Le résumé de la route dit « List all 12 economic setting categories » (economy.py:40) — concordant, cas rare12 clés de premier niveau dans ECONOMIC_SETTINGS, backend/app/data/economy_data.py lignes 35,45,56,67,77,88,99,109,119,130,142,152
Code économique doctrinal sans aucun appelant≈1190 lignesjubilee_service 227 + regeneration_service 198 + embodied_apprenticeship_service 167 + economy/ (circulation_gauge 189, energy_channels 130, royalty_decay 117, financing_doctrine 88, jubilee_triggers 72) = 1188 ; grep récursif : références uniquement dans backend/tests/
Tests couvrant ce code non branché55 fonctions de test8 (jubilé) + 8 (jachère) + 8 (compagnonnage) + 19 (réglages économie) + 6 (canaux d'énergie) + 6 (ristourne contra-cyclique) comptés par grep -c sur les def test_
AT·OM Pay — lignes livrées sans porte d'entrée1068 lignes, 79 tests, 0 routewc -l backend/app/services/pay/*.py ; aucun register_router pour pay dans backend/app/main.py ; tests/test_atom_pay.py
Plafond de frappe automatique1000 UR par jour, 100/heure/producteurMINT_URCOIN_DAILY_CAP et BEAT_RATE_LIMIT_PER_HOUR, backend/app/services/babel/g4_emission_guard.py:42-45
Cible d'amorçage de la trésorerie10 000 000 URDEFAULT_SEEDING_TARGET_UR, backend/app/services/economy/energy_channels.py:40 — mais le module n'est appelé par aucun service, donc la fermeture du canal minage n'est pas en vigueur
Consommateurs de trésorerie abonnés au bus au démarrage4subscribe_to_bus() appelés backend/app/main.py lignes 617, 669, 709, 713
Fichiers de tests touchant l'économie≈40find backend/tests -name "*.py" filtré sur econom|treasur|ristourne|jubil|token|wallet|regenerat|apprentice|ledger
Pages HTML chargeant l'interface économie1grep -rn "economy-ui.js" frontend/ → seule frontend/dashboard.html:23

Ce sur quoi vous pouvez compter

Le circuit monétaire de base tourne pour vrai. Un usager peut avoir un portefeuille, recevoir de l'UR, en transférer, voir son historique : 66 routes mesurées sur les deux routeurs principaux (46 sur /api/v2/economy-engine, 20 sur /api/v2/economy), toutes montées dans main.py.

La frappe automatique est armée ET bridée. Quatre consommateurs de bus (fractale, temple, crop-circle, graine) écoutent l'énergie captée et frappent de l'UR COIN ; le garde G4 (g4_emission_guard.py, appelé à babel_fractal_treasury_consumer.py:478) plafonne à 1000 UR par jour et met θ à zéro s'il n'y a eu aucune captation réelle sur 24 h. C'est la règle « on ne frappe que ce qu'on capte », et elle est dans le chemin d'exécution, pas seulement dans un document.

La ristourne est le seul organe « doctrinal » réellement branché : quatre flux commerciaux distincts l'appellent (caisse, marchand, grande bourse, marché 3D), elle tourne sur le tick CYCLE_9, et elle persiste.

Les douze catégories de réglages économiques existent bel et bien : douze, ni plus ni moins. C'est le rare endroit où la documentation et le code disent la même chose.

Ce qui manque

1. Trois parts sur quatre de la distribution 40/30/20/10 ne sont jamais versées. À economy.py:339-352, les quatre parts sont calculées et renvoyées dans la réponse, mais seul le 0,40 « agent » passe par _mint. Communauté, stabilité et RCS reçoivent zéro. C'est le trou le plus grave : le système affiche une redistribution qu'il n'exécute pas.

2. Deux formules 40/30/20/10 différentes cohabitent. economy.py:277 dit agent/communauté/stabilité/RCS ; economy_data.py:35-43 dit infrastructure/liquidité/développement/ristournes. Mêmes chiffres, sens opposés. Personne ne peut dire laquelle est la vraie sans trancher.

3. Une contradiction doctrinale non gardée. financing_doctrine.py:31 pose INTEREST_LENDING_ALLOWED = False et refuse le prêt à intérêt — mais les réglages actifs portent « lending / default_interest_rate_annual : 5 % » (economy_data.py:122) et rien n'appelle validate_financing pour l'en empêcher. La doctrine existe ; la garde n'est pas posée.

4. Les quatre grands organes doctrinaux sont écrits mais muets. Jubilé (227 L), jachère (198 L), compagnonnage (167 L), plus les cinq modules de app/services/economy/ (597 L au total : jauge, canaux d'énergie, doctrine de financement, gâchettes du jubilé, rente décroissante). Ensemble : environ 1190 lignes de code correct, couvert par une trentaine de tests, appelé par zéro ligne de production. Trois de ces fichiers écrivent eux-mêmes « EN RÉSERVE, câblage différé ».

5. AT·OM Pay n'a pas de porte. 1068 lignes, 79 tests, aucun routeur monté. Deux modules sur sept seulement sont atteints, et par un chemin détourné (liquidity_bridge).

6. La trésorerie vit encore en mémoire vive. treasury_service.py garde ses portefeuilles dans self._wallets (ligne 134) ; 23 méthodes async base de données coexistent avec les méthodes synchrones RAM. Un redémarrage du serveur peut faire disparaître un état monétaire qui n'a pas été écrit.

7. Le côté écran est mince. Une seule page (dashboard.html) charge l'interface économie, qui n'appelle que 3 des 66 routes. ristourne-store-ui.js, 540 lignes, n'est chargé par aucune page.

Se tient avec : Le bus d'événements et le pouls — sans le tick CYCLE_9 et le bus, la ristourne, le projecteur circulaire et toute la frappe automatique s'arrêtent (main.py:322-347, 600-720) · Babel et le décodage — les consommateurs de trésorerie (fractale, temple, crop-circle) sont dans app/services/babel/ : c'est le décodage qui produit l'énergie qui devient de l'UR · La bioacoustique et le col d'import — FractalPipelineBridge (main.py:648) est le maillon qui fait passer l'énergie captée vers la trésorerie · Hedera / la chaîne — tokenomics_hedera_bridge et l'ancrage canon (treasury_canon_router.py:33), en mode simulé par défaut sauf HEDERA_LIVE_MODE · La gouvernance et la souveraineté — le jubilé exige une ratification au scope civilisationnel (AIPEngineService), et les réglages « requires_vote » (economy_data.py) renvoient au vote · Le mérite et la formation — le compagnonnage et le registre de confiance/compétence (trust_ledger_router.py) portent le mérite qui devrait conditionner l'accès économique · Le commerce et le marché — checkout_system, merchant_service, grand_exchange, marketplace_3d sont les quatre vrais appelants de la ristourne · Le frontend — dashboard.html et presentation-economie.html sont la seule surface visible de ces 66 routes

Domaine 12 · état : partiel

La mémoire

C'est tout ce qui permet au système de retenir quelque chose et de le retrouver plus tard : une base de 5223 morceaux de texte vectorisés dans Supabase, trois paliers de mémoire (chaud/tiède/froid) côté navigateur, un WOMB qui enregistre les événements de gestation, et une couche de gouvernance qui dit ce qui a le droit d'être mémorisé. Aujourd'hui la partie « écrire » fonctionne surtout en local et en RAM ; la partie « relire intelligemment » n'est branchée nulle part.

13 livrées · 8 en attente · 3 déclaratives

L’inventaire

La pièceÉtatOù elle vitCe qu’elle fait
atom_knowledge_chunks (Supabase, pgvector)H2_membrane · S7câblé, en attentebase prod Supabase vzbrhovthpihrhdbbjud, table publique — aucun fichier du dépôt ne l'interrogeLe seul vrai stock de mémoire vivante : 5223 morceaux de docs et de mémoires du dépôt, chacun avec son vecteur.Mesuré en direct : SELECT sur pg_stat_user_tables → 5223 lignes. Colonnes : id, source_doc, chunk_index, content, embedding, tokens_estimate, metadata, ingested_at. Grep du mot atom_knowledge_chunks dans tout le code Python/JS : 3 occurrences, toutes dans des commentaires (backend/app/services/babel/local_embeddings_client.py:17 et :42, backend/app/services/babel/babel_macro_decoder.py:553). ZÉRO requête SQL. La donnée existe, rien ne la lit.
Routeur mémoire 3 paliers (chaud/tiède/froid)H1_spine · S0livrébackend/app/routers/memory.py (975 lignes), monté dans backend/app/main.py:1231 sur /api/v2/memory14 routes REST pour déposer des événements dans un fil, les relire par palier, faire des instantanés, compresser, purger.Monté et testé (backend/tests/routers/test_memory_db_contract.py, 6 tests). MAIS : il écrit dans memory_layer_events et memory_layer_snapshots (memory.py:341, :374, :459) — ces deux tables N'EXISTENT PAS dans la base prod (vérifié : absentes de la liste des 48 tables). Il retombe donc toujours sur PersistentDict (memory.py:122-123), qui écrit dans kv_store — table qui existe mais contient 0 ligne.
Routeur WOMB (backend)H2_membrane · S1livrébackend/app/routers/womb.py (109 lignes), monté dans backend/app/main.py:2016 sur /api/v1/wombDeux routes seulement : POST /events pour enregistrer un événement de gestation, GET /status pour lire les 10 derniers.Monté. Le modèle SQLAlchemy existe (backend/app/models/womb.py, 46 lignes, table womb_events). Mais womb_events N'EXISTE PAS dans la base prod → le except silencieux de womb.py:80-85 avale l'erreur et tout part dans un dict Python perdu au redémarrage.
Service de gouvernance de la mémoire (10 Lois)H3_vital_loop · S3câblé, en attentebackend/app/services/memory/memory_governance_service.py (331 lignes)Le gardien : refuse de mémoriser sans accord explicite, sans identité, sans portée d'arbre ; empêche une identité de lire la mémoire d'une autre ; clampe la confiance à 0,30 hors sphère S1.Grep de « memory_governance » dans tout backend/ : uniquement son propre __init__.py et backend/tests/test_memory_governance_service.py (18 tests). AUCUN routeur, AUCUN service ne l'appelle. De plus il stocke dans un dict en mémoire vive (memory_governance_service.py:196 self._memories) — rien ne survit au redémarrage.
13e pilier — embeddings multi-modèlesH4_mapping_projection · S7livrébackend/app/routers/embeddings.py (145 lignes, 9 routes), monté main.py:1555 ; services dans backend/app/services/embeddings/ (13 fichiers, 2248 lignes)Recherche sémantique, zoom fractal, généalogie de vecteurs, ancrage Hedera partiel. C'est le RAG « officiel » du système.Routes montées, 15 tests (backend/tests/routers/test_embeddings_router.py) + 10 fichiers de tests services. Mais son corpus réel = 5 morceaux codés en dur, un par corpus C1..C5 (backend/app/services/embeddings/corpus_ingester.py:16-42, méthode bootstrap_minimal_corpus). Cinq chunks, pas cinq mille.
MultiModelEmbedder — le vectoriseur par défautH5_specialized_backstage · S7déclaratifbackend/app/services/embeddings/multi_model_embedder.py:189-199 (_provider_from_env) et :104-109 (repli hash)Censé produire cinq vecteurs indépendants (local-minilm, gemma, glm, gemini, claude) pour mesurer une « convergence ».Par défaut il ne fait AUCUN embedding sémantique : il fabrique un vecteur à partir d'un SHA-256 du texte (ligne 46 _base_vector, ligne 105 salt = sha256(model_id)). Le vrai fournisseur ne s'active que si ATOM_EMBEDDINGS_PROVIDER est posée — grep de cette variable dans tout le dépôt : jamais définie, seulement mentionnée dans requirements.txt:109 et dans 6 notes .md. La « convergence » mesurée sur des hachages salés est un artefact arithmétique, pas un signal de robustesse.
BureauEmbeddingProvider (bge-m3 et les 4 autres)H5_specialized_backstage · S7câblé, en attentebackend/app/services/embeddings/bureau_provider.py (141 lignes), correspondance des voies lignes 39-46Le vrai câblage vers les 5 modèles du bureau Hetzner : MiniLM local (384), nomic-embed-text (768), bge-m3 (1024), mxbai-embed-large (1024), snowflake-arctic-embed (1024), via Ollama sur :11434.Code complet et testé (backend/tests/services/embeddings/test_bureau_provider.py). Mais il n'est importé QUE depuis multi_model_embedder.py:193, à l'intérieur du if qui dépend de la variable d'environnement jamais posée. C'est un moteur monté, jamais démarré.
Table de stockage atom_corpus_embeddingsH2_membrane · S7câblé, en attentebackend/alembic/versions/v82_048_embeddings_corpus.py:26 (DDL) ; lue/écrite par backend/app/services/embeddings/storage_repository.py:132, :182, :232La table pgvector prévue pour le 13e pilier, avec index HNSW cosinus.La migration existe et est testée (backend/tests/unit/test_v82_048_embeddings_corpus_migration.py). La table N'EXISTE PAS dans la base prod (absente des 48 tables mesurées) → toutes les recherches du 13e pilier tombent en repli mémoire. Défaut de conception à noter : la colonne est vector(384) fixe, alors que le code interroge en 256/768/1024/1536/2048 (multi_model_embedder.py:19-26).
Hiérarchie mémoire canon 7 tiersH4_mapping_projection · S9livrébackend/app/routers/canon_memory_hierarchy_router.py (98 lignes, 4 routes), monté main.py:1889 ; logique dans hf-atom-tools/atom_canon/memory/hierarchy.py (161 lignes)Route un contenu vers un des 7 tiers biologiques (working, episodic, semantic, procedural, emotional, collective, cosmic) et valide les 5 consolidations autorisées.Routes montées, importé aussi par acmi_router.py:55. Attention : ça ne STOCKE rien. route_memory_to_tier (hierarchy.py:73-102) renvoie un backend_hint — une chaîne de caractères comme 'hedera_dlt' ou 'filesystem_markdown'. C'est un aiguilleur qui donne un avis, pas un magasin.
Compartiments mémoire (cloisons + quarantaine)H3_vital_loop · S3livréhf-atom-tools/atom_canon/memory/compartment.py (205 lignes), utilisé par backend/app/routers/canon_compartment_router.py:30 et backend/app/services/acmi_agent_pool_persistence.py:24Crée des compartiments étanches, vérifie 4 portes avant tout accès (portée, niveau canon, ...), permet de ponter deux compartiments ou d'en mettre un en quarantaine.Import réel depuis un routeur et un service, tests dans hf-atom-tools/atom_canon/tests/test_compartment.py. C'est la pièce de gouvernance mémoire la mieux branchée.
Loi 12 — womb-perspective (le WOMB doctrinal)H0_origin · S9câblé, en attentehf-atom-tools/atom_canon/laws/law12_womb_perspective.py (143 lignes)Pose que AT·OM est une matrice gestationnelle vue de l'intérieur : pôle intérieur fertile = S0, membrane lisible = S9.CANON_FORT déclaré ligne 24. Le fichier lui-même désigne son runtime_ref à la ligne 108 : hf-atom-tools/atom_canon/memory/hierarchy.py. Aucun routeur ne l'importe. La loi décrit ; l'aiguilleur qu'elle désigne ne stocke pas ; le routeur womb.py qui porte le nom ne connaît ni S0 ni S9. Les trois « WOMB » du système ne se parlent pas.
Mémoire 3 paliers côté navigateurH1_spine · S1livréfrontend/js/memory-hot.js (374), memory-warm.js (338), memory-cold.js (561), memory-stigmergic.js (620), memory-womb.js (862), memory-manager.js (1059) — chargés par frontend/js/governance-init.js:232-237Chaud = RAM, 100 objets, 5 min. Tiède = localStorage, 5 Mo, 1 h. Froid = IndexedDB + Supabase, 24 h. memory-womb assure les transitions entre paliers.Les 6 fichiers sont dans le tableau de scripts de governance-init.js (lignes 232-238) et dans la liste d'attente ligne 862-863. Durées mesurées dans memory-manager.js:38-44. C'est la partie la plus solide du domaine.
Synchronisation froide → Supabase (bio_states)H2_membrane · S1livréfrontend/js/memory-cold.js:389-454, POST vers {SUPABASE_URL}/rest/v1/bio_statesLe seul canal qui fait réellement sortir de la mémoire du navigateur vers la base.Table bio_states mesurée en prod : 363 lignes — deuxième table la plus remplie du système. C'est la preuve que ce chemin-là fonctionne vraiment. Il se coupe tout seul si SUPABASE_URL/KEY manquent (ligne 390).
Famille womb-* frontend (7 modules)H6_domain_vertical · S1câblé, en attentefrontend/js/womb-core.js (1139), womb-progression.js, womb-cheminements.js, womb-enforcement.js, womb-civilisationnel.js, womb-auto-evaluation.js, womb-intercross.js — 1862 lignes au total hors womb-coreLe moteur de gestation : germes, classification, progression par étapes, application des règles, croisements.Vérifié un par un : aucun de ces 7 fichiers n'apparaît dans governance-init.js ni dans une page HTML vivante (uniquement dans frontend/docs/*.html, qui sont des rapports). womb-core.js n'est cité que par frontend/js/gestation-womb.js:14, et en commentaire. Environ 3000 lignes qui ne s'exécutent jamais.
Défaut de contrat womb frontend ↔ backendH7_frontstage_external · S0déclaratiffrontend/js/womb-core.js:1007 vs backend/app/routers/womb.py:36-40Le client envoie un lot d'événements, le serveur en attend un seul.womb-core.js poste {events: [...]}. Le modèle Pydantic WombEvent exige event_type à la racine. Même si womb-core était chargé, la requête serait rejetée en 422. frontend/js/womb-progression.js:131 envoie, lui, le bon format — mais ce module n'est chargé nulle part non plus.
EmbeddingService (sentence-transformers)H5_specialized_backstage · S7câblé, en attentebackend/app/services/embedding_service.py (62 lignes)Enveloppe simple autour de multilingual-e5-base (768 dimensions).Grep « from app.services.embedding_service » dans tout backend/ : zéro résultat. Personne ne l'importe. À noter : ce n'est ni bge-m3 (1024) ni MiniLM (384) — c'est un troisième modèle, une troisième dimension.
Miroir atom-fractal-canonH0_origin · S9déclaratifatom-fractal-canon/index.json + registry/ (7 fichiers, 60 Ko au total)Photo compacte de la fractalisation du code : 24 modules, 2577 feuilles, 5872 arêtes.Son propre README ligne 5 le dit : « It is not imported by the application ». Grep confirmé : seuls des scripts d'audit et le protocole de collaboration le lisent, jamais le runtime. Et il est PÉRIMÉ : index.json est daté 2026-06-02 avec repo_root = C:\Users\pro-s\Github\V\ATOM-CLEAN (une autre machine), alors que la source vivante leaves/index.json est datée 2026-06-29 et compte 2901 feuilles. Écart mesuré : 324 feuilles, 24 modules annoncés contre 26 répertoires réels dans modules/.
Registre fractal vivant (leaves/, modules/, cells/)H0_origin · S9livréleaves/index.json à la racine du dépôt, plus 26 répertoires dans leaves/ et modules/, 5 dans cells/L'inventaire réel du code par étage fractal — c'est lui qui donne la grammaire H0..H7.Mesuré : 2901 feuilles. Répartition par étage : H1_spine 1249, H5_specialized_backstage 701, H2_membrane 615, H7_frontstage_external 180, H6_domain_vertical 113, H0_origin 31, H3_vital_loop 6, H4_mapping_projection 6. Par nature : frontend_module 1107, backend_service 639, frontend_data 421, backend_router 357, backend_python 243, frontend_page 124, agent_module 10.
Semences de connaissance (knowledge-seed-*)H6_domain_vertical · S7livréfrontend/js/knowledge-seed-*.js — 422 fichiers mesurés ; chargeur frontend/js/knowledge-seed-loader.js et registre knowledge-seed-registry.jsLe corpus thématique embarqué : 422 domaines, de l'apiculture à la volcanologie.Comptage direct : ls | wc -l = 422. Le CLAUDE.md annonce « ≈440 fichiers de données knowledge-seed » — l'ordre de grandeur tient, le chiffre exact est 422.
Routeurs knowledge_* backend (6)H2_membrane · S7livréknowledge.py (321L, main.py:1674), knowledge_seeds.py (774L, main.py:1945), knowledge_threads.py (102L, main.py:1773), knowledge_graph_router.py (362L, main.py:1944), knowledge_survival_router.py (196L, main.py:1946), living_knowledge_router.py (150L, main.py:1980)La surface REST pour déposer, chercher et vérifier des semences, des fils et des faits.Les 6 sont enregistrés dans main.py aux lignes citées. Mais leur table de fond, knowledge_seed_batches (knowledge_seeds.py:295, :374, :407), N'EXISTE PAS en prod → repli mémoire systématique. Un test l'a d'ailleurs documenté : scripts/audit_knowledge_seed_query_default_memory_fallback_round449.py.
Ancrage Hedera des vecteursH5_specialized_backstage · S9câblé, en attentebackend/app/services/embeddings/hedera_anchor_service.py (90 lignes)Censé sceller l'empreinte d'un vecteur sur la blockchain Hedera pour rendre la mémoire infalsifiable.Mode par défaut « partial » (ligne 18), et il n'ancre que si authority == 'T7=A' (ligne 27). L'import de atom_canon.history est enveloppé dans un try/except qui le met à None s'il échoue (lignes 9-12). Aucun ancrage réel mesurable : atom_corpus_embeddings, qui porte la colonne hcs_anchored, n'existe pas en base.
Mémoire stigmergique (traces phéromonales)H3_vital_loop · S5livréfrontend/js/memory-stigmergic.js (620 lignes), chargé governance-init.js:235 ; envoie vers /api/v2/stigmergy/trails (ligne 172)Mémoire indirecte : au lieu de stocker un fait, on dépose une trace qui s'évapore, et les passages répétés la renforcent.Chargé et branché. Il n'envoie au serveur qu'au franchissement d'un seuil ou tous les 9 dépôts (ligne 169). Côté serveur, backend/app/routers/stigmergy.py existe et fait DB d'abord puis repli mémoire ; la table stigmergy_trails existe en prod avec 0 ligne.
PersistentDict / kv_store — le filet de sécuritéH1_spine · S0livrébackend/app/core/persistent_store.py (317 lignes), table kv_store ligne 84 ; vidage périodique par PersistentStoreFlushScheduler ligne 216Ce qui rattrape TOUS les replis mémoire du backend : chaque dict en RAM déclaré ici est reversé dans kv_store à intervalle régulier, et rechargé au démarrage (main.py:395 et :862).La table kv_store EXISTE en prod mais compte 0 ligne. Autrement dit : le filet est tendu, rien n'est jamais tombé dedans en production — ce qui veut dire soit que le vidage ne tourne pas, soit qu'aucune écriture mémoire n'a eu lieu.
Explorateur d'embeddings (interface)H7_frontstage_external · S4livréfrontend/js/embeddings-explorer.js (206 lignes), API_BASE '/api/v2/embeddings' ligne 12 ; référencé dans 1 page HTML et 3 fois dans governance-init.jsLa fenêtre par laquelle un humain peut interroger la mémoire sémantique.Chargé et pointé vers une route montée. C'est le seul chemin utilisateur vers la recherche sémantique — mais il interroge un index de 5 chunks vectorisés par hachage.

Les chiffres, mesurés

Ce qu’on compteLa mesureComment
Morceaux de mémoire réellement stockés et vectorisés en production5223annoncé ailleurs : Le chiffre est exact et cohérent avec docs/superpowers/specs/2026-06-11-runbook-rls-postgrest-remediation.md. C'est un des rares chiffres AT·OM qui tient.SELECT relname, n_live_tup FROM pg_stat_user_tables sur le projet Supabase vzbrhovthpihrhdbbjud → atom_knowledge_chunks = 5223
Requêtes du code AT·OM vers ce stock de 5223 morceaux0annoncé ailleurs : memory/2026-05-27-B707 affirme « Babel Tier 2 wired (measure_tier2.py) » ; vérification faite : measure_tier2.py interroge BabelWordCanonicalPole, pas atom_knowledge_chunks.grep -rn 'knowledge_chunks' sur backend/ frontend/ services/ scripts/ docs/ memory/ hf-atom-tools/ → 3 occurrences, toutes en commentaire ou docstring, aucune requête SQL
Morceaux dans le corpus du 13e pilier embeddings5annoncé ailleurs : La doc parle de 5 corpus (doctrine, code, vocabulaire, mémoire, externes) avec cadences commit/nightly/weekly. Il y a 5 corpus, oui — avec un chunk chacun.backend/app/services/embeddings/corpus_ingester.py:16-42, méthode bootstrap_minimal_corpus — un seed codé en dur par corpus C1..C5
Tables de la base de production48 tables, dont 6 non videspg_stat_user_tables : atom_knowledge_chunks 5223, bio_states 363, atom_dataseeds_decoded 10, armors 1, atom_test 1, atom_dataseeds 1. Les 42 autres à 0.
Tables mémoire attendues par le code mais absentes de la base5annoncé ailleurs : docs/MAP-INITIALE-ESPACES-INTERNES-2026-07-14.md:52 avait déjà relevé womb_events ; le problème est plus large que ça.womb_events (models/womb.py:19), memory_layer_events et memory_layer_snapshots (routers/memory.py:341,374), atom_corpus_embeddings (alembic v82_048), knowledge_seed_batches (routers/knowledge_seeds.py:295) — aucune dans la liste des 48 tables mesurées
Lignes dans kv_store (le filet qui rattrape tous les replis mémoire)0pg_stat_user_tables → kv_store = 0. La table existe (persistent_store.py:84) mais n'a jamais reçu d'écriture.
Modèles d'embedding distincts nommés dans le code7 nommés, 0 actif par défautannoncé ailleurs : La consigne parlait de bge-m3 comme modèle du domaine. bge-m3 existe bien, mais seulement comme voie « glm » du BureauEmbeddingProvider, qui ne démarre que si ATOM_EMBEDDINGS_PROVIDER est posée — variable jamais définie nulle part dans le dépôt.paraphrase-multilingual-MiniLM-L12-v2 384 (local_embeddings_client.py:41), multilingual-e5-base 768 (embedding_service.py:26), nomic-embed-text, bge-m3, mxbai-embed-large, snowflake-arctic-embed (bureau_provider.py:39-46), text-embedding-3-small OpenAI (historique, babel/embeddings_client.py). Par défaut le système n'en charge aucun : multi_model_embedder.py:104 fabrique un vecteur à partir d'un SHA-256.
Dimensions de vecteurs en circulation6 valeurs incompatibles384 (MiniLM, et colonne vector(384) de la migration v82_048 ligne 34), 768 (e5-base, nomic), 1024 (bge-m3, mxbai, snowflake), plus 256/1536/2048 déclarées dans multi_model_embedder.py:19-26. Le routeur embeddings.py:63-69 interroge en 256/768/1024/1536/2048 une colonne déclarée vector(384).
Feuilles du registre fractal vivant2901annoncé ailleurs : atom-fractal-canon/index.json annonce 2577 feuilles et 24 modules (généré 2026-06-02, depuis une autre machine : repo_root = C:\Users\pro-s\...). Écart : 324 feuilles, et 26 répertoires réels dans modules/ contre 24 annoncés.leaves/index.json, clé leaf_count, généré 2026-06-29
Fichiers de semences de connaissance frontend422annoncé ailleurs : CLAUDE.md annonce « ≈440 fichiers de données knowledge-seed ». L'ordre de grandeur est bon, le compte exact est 422.ls frontend/js/knowledge-seed-*.js | wc -l
Lignes de code mémoire/womb frontend qui ne s'exécutent jamais~3001 lignes sur 7 fichierswomb-core.js 1139 + womb-progression/cheminements/enforcement/civilisationnel/auto-evaluation/intercross 1862. Vérifié fichier par fichier : aucun n'apparaît dans governance-init.js ni dans une page HTML vivante (seulement dans frontend/docs/*.html, qui sont des rapports d'audit).
Tests qui gardent le domaine~60 tests répartis18 (test_memory_governance_service.py), 15 (test_embeddings_router.py), 6 (test_memory_db_contract.py), 5 (test_storage_repository.py), plus 10 fichiers de tests dans backend/tests/services/embeddings/. Le service le mieux testé du domaine (gouvernance mémoire, 18 tests) est aussi celui que personne n'appelle.
Routeurs du domaine mémoire montés dans main.py10memory (ligne 1231), embeddings (1555), knowledge (1674), knowledge_threads (1773), canon_memory_hierarchy (1889), knowledge_graph (1944), knowledge_seeds (1945), knowledge_survival (1946), living_knowledge (1980), womb (2016)

Ce sur quoi vous pouvez compter

Trois choses tiennent vraiment.

D'abord, les 5223 morceaux dans Supabase. C'est de la mémoire réelle, indexée, protégée par RLS depuis juin. Elle contient le cœur doctrinal du système : 209 morceaux du MASTER-INDEX, les plans et specs, les cosmogonies ancestrales. Elle est là, elle est bonne, elle a survécu à tout.

Ensuite, la mémoire trois paliers du navigateur. Les six modules (chaud, tiède, froid, stigmergique, womb de transition, gestionnaire) sont chargés pour de vrai par governance-init.js, avec des durées de vie nettes : 5 minutes en RAM, 1 heure en localStorage, 24 heures en IndexedDB. Et le palier froid a un débouché qui fonctionne : 363 lignes réellement écrites dans bio_states en production. C'est le seul chemin où une mémoire sort du navigateur et arrive vraiment dans la base.

Enfin, les compartiments (hf-atom-tools/atom_canon/memory/compartment.py). C'est la seule pièce de gouvernance mémoire qui soit à la fois écrite, testée ET appelée depuis un vrai routeur. Les cloisons entre identités existent et fonctionnent.

Le registre fractal vivant (leaves/, modules/, cells/) tient aussi : il donne une carte honnête et à jour du code par étage H0..H7.

Ce qui manque

Du plus bloquant au moins.

1. Le stock et le moteur ne se parlent pas. Les 5223 morceaux existent dans Supabase ; le moteur de recherche sémantique (13e pilier) existe aussi. Ils ignorent l'un l'autre. Le moteur cherche dans une table atom_corpus_embeddings qui n'a jamais été créée, et qui de toute façon ne contiendrait que 5 chunks de démarrage. Le système possède une bibliothèque et un bibliothécaire, dans deux bâtiments qui n'ont pas de porte commune.

2. Le vectoriseur par défaut n'est pas un vectoriseur. Il produit des vecteurs à partir d'un SHA-256 du texte (multi_model_embedder.py:104-109). Deux phrases qui veulent dire la même chose donnent des vecteurs sans rapport. Toute « recherche sémantique » faite dans cette configuration est du bruit propre. Le vrai câblage (bge-m3 et les quatre autres, sur le bureau Hetzner) est écrit, testé, complet — il attend une variable d'environnement, ATOM_EMBEDDINGS_PROVIDER, qui n'est posée nulle part.

3. Cinq tables manquent en base. womb_events, memory_layer_events, memory_layer_snapshots, atom_corpus_embeddings, knowledge_seed_batches. Le code écrit dedans, la base ne les a pas, l'erreur est avalée par un except silencieux, tout part en RAM et disparaît au redémarrage. Le pire signe : kv_store, le filet censé rattraper ces replis, contient 0 ligne.

4. Le WOMB est en trois morceaux qui ne se connaissent pas. La loi doctrinale (law12_womb_perspective.py, S0 fertile ⇄ S9 membrane), le routeur backend (2 routes, une table absente), et le moteur frontend (7 modules, ~3000 lignes, chargés par personne). En prime, le client womb-core.js envoie un format que le serveur refuse — un lot d'événements là où il en attend un seul.

5. Le gardien ne garde rien. memory_governance_service.py applique les 10 Lois de la Mémoire correctement, avec 18 tests qui passent. Aucun routeur ne l'appelle. Aucune écriture mémoire du système n'est aujourd'hui soumise à l'approbation explicite, au scope d'identité ou à la réversibilité. La doctrine est codée, elle n'est pas en travers du chemin.

6. Six dimensions de vecteurs incompatibles circulent (256, 384, 768, 1024, 1536, 2048), et le routeur interroge en 5 largeurs une colonne déclarée à 384.

7. Le miroir atom-fractal-canon est périmé de 324 feuilles et vient d'une autre machine.

Se tient avec : Babel (le décodeur réutilise LocalEmbeddingsClient et déclare viser le même index pgvector 384 dimensions) · Le bureau Hetzner (Ollama :11434 héberge bge-m3 et les 4 autres modèles du BureauEmbeddingProvider — sans lui, pas d'embeddings réels) · Hedera / UR COIN (hedera_anchor_service devrait sceller l'empreinte des vecteurs ; mode 'partial', jamais exercé) · ACMI / atom_canon (compartiments et hiérarchie 7 tiers viennent de hf-atom-tools ; acmi_agent_pool_persistence en dépend réellement) · Supabase / pgvector (unique support persistant réel du domaine — et la moitié des tables attendues n'y existent pas) · Le système bio (memory-cold écrit dans bio_states, la table du système bio : les deux domaines partagent le même tuyau de sortie) · Stigmergie (memory-stigmergic alimente /api/v2/stigmergy/trails) · Le registre fractal (leaves/, modules/, cells/ — c'est lui qui situe chaque pièce de mémoire dans la grammaire H0..H7)

Domaine 13 · état : partiel

Gouvernance et gardes — ce qui bloque réellement une action dans AT·OM

C'est l'ensemble des serrures du système : ce qui décide si une action passe, s'arrête, ou attend l'accord d'un humain. Il y en a de plusieurs sortes — l'authentification (qui es-tu ?), la membrane (as-tu mérité de voir ça ?), les 3 lois de l'Arbre (le système ne décide jamais à ta place), le HTTP 423 « Locked » (bloqué en attente d'approbation), et la garde OPA qui protège la monnaie.

18 livrées · 7 en attente · 2 déclaratives

L’inventaire

La pièceÉtatOù elle vitCe qu’elle fait
Authentification JWT (fail-closed)H2_membrane · S3livrébackend/app/core/auth.py:200-212 (get_current_user, allow_dev_fallback=False)Sans jeton Bearer valide → 401. Le mode « dev-user » de secours est explicitement désactivé sur cette dépendance.1331 occurrences de Depends(get_current_user*) réparties dans backend/app/routers/ ; 136 fichiers de routeur l'appliquent au routeur entier via dependencies=[...]
Trou de couverture d'authH2_membrane · S3déclaratifbackend/app/routers/ — 44 fichiers sur 343 ne mentionnent AUCUNE gardeCes routeurs n'ont ni get_current_user, ni require_admin, ni token interne, ni palier de souveraineté : leurs routes sont ouvertes.Comptage : ls *.py | wc -l = 343 ; fichiers sans aucun symbole de garde = 44
Porte globale « auth par défaut » (deny-by-default)H2_membrane · S3câblé, en attentebackend/app/core/auth_by_default.py:118-121 + branchée en middleware dans backend/app/main.py:1024Classe chaque route en public / signature / interne / utilisateur et exige un jeton pour tout le reste. Le mécanisme est complet et branché — mais éteint.Le drapeau ATOM_AUTH_REQUIRED_BY_DEFAULT_ENABLED vaut « false » par défaut (os.getenv(FEATURE_FLAG_ENV, "false")) et n'est posé dans AUCUN fichier de déploiement du dépôt. Middleware appelé mais sort immédiatement.
Les 3 lois de l'ArbreH1_spine · S3livrébackend/app/core/tree_laws.py (166 lignes) — TREE_LAWS ligne 87Human Agency, No Manipulation, Full Transparency. Détecte 31 mots-clés d'action interdite (auto_decide, dark_pattern, hidden_action…) et le cas « agent qui agit sans requires_approval ».2 appelants réels : backend/app/services/nova_pipeline.py:931 (mène à GovernanceStatus.DENIED, ligne 960, qui interrompt le pipeline ligne 1444) et backend/app/services/master_mind.py:478.
Lois de l'Arbre chez MasterMind — constat sans blocageH1_spine · S3câblé, en attentebackend/app/services/master_mind.py:478-485Même vérification, mais la violation est seulement journalisée (logger.warning) et la phase retourne success=True.Ligne 486 : return PhaseResult(phase=Phase.VALIDATION, success=True, ...) — aucun chemin de refus.
Foundation — le tronc éthique (8 principes)H0_origin · S3livrébackend/app/core/foundation.py (242 lignes)8 principes immuables + modèle d'autorité (« les agents ne peuvent pas prendre d'action irréversible ni élever leur propre portée »).2 appelants : nova_pipeline.py:914 et master_mind.py:49. Dans Nova la violation alimente la liste violations → statut DENIED.
HTTP 423 Locked — le blocage en attente d'humainH7_frontstage_external · S3livré68 occurrences de status_code=423 dans 29 fichiers de backend/app/routers/La convention canon : une action sensible ne s'exécute pas, elle renvoie 423 avec un point de contrôle à approuver.Mesuré : grep -rn "status_code=423" backend/ --include=*.py | wc -l = 68, dans 29 fichiers (dataspaces, decisions, identities, meetings, my_team, government, files, memory, griffe…).
Routeur Checkpoints (l'approbation humaine)H3_vital_loop · S3livrébackend/app/routers/checkpoints.py (1027 lignes), monté backend/app/main.py:1222 sur /api/v2/checkpointsCréer / lister / approuver / rejeter / escalader / expirer un point de contrôle. C'est l'organe qui débloque un 423.15 endpoints (@router.*). L'approbation vérifie la propriété (verify_checkpoint_access), refuse si expiré (400) et exige un utilisateur authentifié (Depends(get_current_user_id), ligne 750).
Garde OPA sur la monnaie (fail-close réel)H3_vital_loop · S2livrébackend/app/core/governance.py:133 check_governance ; appelée par ur_engine.py:136, treasury_service.py:909, hedera_routes.py:205, nova.py:1414, babel_fractal_treasury_consumer.py:340Avant de frapper de l'UR ou du crédit, on interroge le serveur de politiques. Serveur absent ou en erreur = REFUS.governance.py:112-120 renvoie allowed=False sur échec HTTP ; ur_engine.py:145-150 et treasury_service.py:928-935 renvoient explicitement « Governance unavailable — mint refused (fail-close policy) ». C'est la garde la plus dure du dépôt.
Politiques OPA (.rego)H5_specialized_backstage · S3câblé, en attentebackend/governance/opa/bundles/che_nu_v2/policies/ + backend/opa/policies/governance.rego — 24 fichiers .regoLes règles écrites (4 niveaux d'agent l0-l3, 10 sphères, 3 environnements, artefacts, exports, simulation).24 fichiers .rego comptés. Mais aucun serveur OPA n'est démarré par le dépôt : OPA_URL vaut http://localhost:8181 par défaut (config.py:195) et le middleware OPA est éteint (main.py:999, OPA_MIDDLEWARE_ENABLED défaut « false »). Les règles ne sont donc jamais évaluées ; seul l'effet fail-close ci-dessus s'applique.
La Membrane mémorielle (mérite × localisation)H2_membrane · S1livrébackend/app/services/membrane_service.py (103 lignes), fonction authorize()Décide si une lecture/écriture PASSE (permeable), n'est pas encore méritée (gestating) ou est scellée (sealed — l'intérieur d'autrui est inviolable). Croise scope ind/com/civ, identité, mérite et rôle.3 appelants réels : bureau_service.py:143, mcp_live_organs.py:38, mcp_repo_tools.py:61. Test présent : backend/tests/unit/test_membrane_service.py.
Routeur Membrane des 3 MondesH2_membrane · S1livrébackend/app/routers/membrane.py (432 lignes), monté main.py:1258 sur /api/v1/membranePassages filtrés entre Mon Monde (privé) / Notre Monde (collectif) / Le Monde (public), avec champs filtrés, champs bloqués et perméabilité read_only|comments|interactive.Auth au niveau du routeur : dependencies=[Depends(get_current_user_id)] ligne 42. Refus de propriété : _MEMBRANE_PASSAGE_FORBIDDEN.
Niveaux d'Engagement Citoyen (1-4)H2_membrane · S3livrébackend/app/core/engagement.py (131 lignes) — require_participant / require_contributeur / require_gardienObservateur / Participant / Contributeur / Gardien, lus du claim roles du JWT signé. Sans rôle → Observateur, jamais puni.20 usages, mais seulement dans 4 routeurs : economy_engine.py, governance.py, health_center_router.py, sentinel.py. Test : backend/tests/test_engagement_bus_acl_socle.py.
Paliers de souveraineté (1-7)H2_membrane · S3livrébackend/app/services/auth/sovereignty_dep.py (104 lignes) — require_sovereignty_level(min_tier)Refuse 403 si le palier du citoyen est sous le minimum. Utilisé sur les routes Hedera, ristourne et tokenomics.17 usages hors du module lui-même. Attention : le palier par défaut est 1 pour tout utilisateur inconnu (politique MVP assumée, docstring §3) ; le registre est un PersistentDict (backend/app/core/persistent_store.py:278) — persistance « best-effort », les données restent en mémoire si la base échoue.
ACL du bus d'événementsH2_membrane · S0câblé, en attentebackend/app/core/bus_acl.py (152 lignes), branchée dans backend/app/services/event_bus.py:466Empêche une source inconnue d'émettre un topic privilégié (economy., treasury., governance.vote, immune.threat, canon.seal…).Réellement appelée par le bus, MAIS le mode par défaut est OBSERVE : elle journalise sans bloquer. Il faut BUS_ACL_ENFORCE=1 pour qu'elle refuse (docstring du module, §DISCIPLINE).
Garde des endpoints internesH5_specialized_backstage · S3livrébackend/app/core/internal_auth.py (91 lignes) — require_internal_tokenProtège /internal/*. Si INTERNAL_API_TOKEN n'est pas configuré → 404 (on cache l'existence de la route, pas 401). Comparaison en temps constant (hmac.compare_digest).21 références dans le dépôt. Fail-closed par conception, documenté §Design point 1.
Porte adminH2_membrane · S3livrébackend/app/core/auth.py:253-280 (_ADMIN_ROLE_NAMES, _is_admin_access_token)Exige un JWT d'accès signé portant le rôle admin.135 usages de require_admin/require_internal_token dans les routeurs ; 28 fichiers de routeur portent require_admin.
Limitation de débit par routeH2_membrane · S3livrébackend/app/core/ratelimit.py (49 lignes) + SlowAPIMiddleware, main.py:962Limite par utilisateur authentifié (clé user:<sub>) ou à défaut par IP, sur les routes coûteuses / monétaires.19 références. Stockage par défaut memory:// (RATELIMIT_STORAGE_URI) — donc non partagé entre plusieurs instances.
Discipline η — le tampon discipline_flagH1_spine · S0livrébackend/app/core/discipline.py (69 lignes), fabrique unique stamp()Tout payload sortant porte discipline_flag + statut_epistemique à sa racine (Output Boundary Principle §4.4.1).3045 occurrences de discipline_flag dans 638 fichiers Python ; 746 valeurs "eta_stricte". Ce n'est PAS une garde qui bloque : c'est un marquage d'honnêteté épistémique.
Plafond de confiance interprétative ηH1_spine · S0livrébackend/app/services/atom_vibration_engine.py:67 (MAX_INTERPRETIVE_CONFIDENCE = 0.3) ; appliqué p.ex. babel_macro_decoder.py:621 et 672Hors sphère S1, aucune sortie interprétative ne peut se déclarer sûre à plus de 0,3. C'est un frein réel contre l'invention.Condition exécutable : if discipline_flag != "S1" and confidence > MAX_INTERPRETIVE_CONFIDENCE. Marqué is_invariant=TRUE dans la migration backend/alembic/versions/v82_037_babel_cluster_h_tuning_maturity.py:118.
Loi 4 anti-S3 câblée dans BabelH6_domain_vertical · S0livrébackend/app/services/babel/eta_law4_anti_s3.py (172 lignes)La seule des 12 lois canon η qui traverse jusqu'au runtime : elle refuse un décodage par bloc au lieu de par dimension.Importée par measure_cascade.py:74 et babel_router.py:59 ; le refus apparaît dans audit_trace["eta_law4"]["allowed"] et le test backend/tests/babel/test_measure_cascade.py:1029 assert allowed is False.
Les 12 lois canon η (couche Python)H0_origin · S3câblé, en attentehf-atom-tools/atom_canon/laws/ — 7 fichiers de loi + __init__.py (282 lignes)Lois 1, 2, 4, 5, 7, 10, 12 en primitives Python ; les 5 autres (3, 6, 8, 9, 11) ne sont que des entrées d'énumération pointant vers un .md.Comptage de fichiers : law1, law2, law4, law5, law7, law10, law12 = 7 sur 12. Hors des tests, le paquet n'est importé que 2 fois par le backend : canon_router.py:27 (exposition en lecture) et babel/eta_law4_anti_s3.py:24. Aucune loi ne bloque une écriture.
Porte d'accès canon (5 gardes composées)H2_membrane · S3livréhf-atom-tools/atom_canon/access/canon_access_gate.py (193 lignes) + backend/app/routers/canon_access_router.py (106 lignes), monté main.py:1888Compose 5 filtres : niveau canon, portée trinité (ind/com/civ), dimensions de polymorphisme, grammaire des 8, distance géomagnétique.Routeur monté. Réserve mesurée : la garde 5 (distance géomag) est un simulacre — commentaire du module « geomag distance (mock pour P0) ».
Moteur constitutionnel (quorums de vote)H3_vital_loop · S3livrébackend/app/core/constitution_engine.py (227 lignes) + backend/app/routers/constitution.py, monté main.py:12824 types de décision avec quorum et durée : opérationnel 50%/24h, structurel 2/3/72h, constitutionnel 3/4 + quorum 0,618/7 jours, urgence 2/3/4h. Veto de gardien sur les 3 derniers.Un seul appelant : le routeur constitution.py:16. Le moteur calcule des seuils ; il n'intercepte aucune écriture ailleurs dans le système.
Souveraineté observée, non imposée (IC-N10)H0_origin · S3câblé, en attentehf-atom-tools/atom_canon/sovereignty/canon_sovereignty.py (374 lignes)Quaternité cardinale anti-concentration (3 rôles sur 4 minimum), 7 paliers d'initiation, passage de flambeau volontaire, aucune capacité de destitution.Grep sur backend/ : aucun import de atom_canon.sovereignty. Le module vit hors du chemin d'exécution du backend.
RLS SupabaseH2_membrane · S3câblé, en attentebackend/supabase/*.sql (31 ENABLE ROW LEVEL SECURITY, 81 CREATE POLICY) + frontend/sql/*.sql (42 / 51)Sécurité au niveau de la ligne : chaque citoyen ne voit que ses lignes, imposé par la base elle-même.CRITIQUE — les 257 migrations Alembic (backend/alembic/versions/), qui sont le chemin de schéma réellement appliqué, contiennent ZÉRO ENABLE ROW LEVEL SECURITY et ZÉRO CREATE POLICY. Les fichiers .sql RLS sont hors de la chaîne de migration ; rien dans le dépôt ne prouve qu'ils sont appliqués en production.
Gardes côté navigateurH7_frontstage_external · S0déclaratiffrontend/js/ — 47 fichiers nommés *guard*/*gate*/*governance*/*sentinel* (agent-guards.js, governance-checkpoint.js, immune-cortisol-gate.js, golem-guardian.js…)Affichent l'état de gouvernance, les points de contrôle, les votes.Ce sont des scripts vanilla exécutés dans le navigateur du visiteur : ils ne peuvent rien bloquer, seulement montrer. Toute vraie garde doit être côté serveur.

Les chiffres, mesurés

Ce qu’on compteLa mesureComment
Fichiers de routeur dans le backend343ls backend/app/routers/*.py | wc -l
Routeurs enregistrés dans main.py366grep -c "^register_router" backend/app/main.py
Occurrences de Depends(get_current_user*)1331grep -rc "Depends(get_current_user" backend/app/routers/*.py, somme
Fichiers de routeur SANS aucune garde d'auth44 sur 343boucle : fichier sans get_current_user, require_admin, require_internal_token ni require_sovereignty_level
Blocages HTTP 423 (Locked)68 occurrences dans 29 fichiersgrep -rn "status_code=423" backend/ --include=*.py | wc -l
Lois canon η avec une primitive Python7 sur 12annoncé ailleurs : CLAUDE.md annonce « 12/12 référencées » — exact au sens des entrées d'énumération, mais seules 7 sont du code exécutable, et une seule (loi 4) est branchée sur un chemin runtime.ls hf-atom-tools/atom_canon/laws/law*.py — law1, 2, 4, 5, 7, 10, 12
Lois canon η importées par le backend hors tests2grep -rn "atom_canon.laws" backend/ : canon_router.py:27 et babel/eta_law4_anti_s3.py:24
Politiques OPA écrites (.rego)24 fichiersfind backend/governance backend/opa -name "*.rego" | wc -l
Middleware OPA activé par défautnonbackend/app/main.py:999 — os.getenv("OPA_MIDDLEWARE_ENABLED", "false")
Porte auth-par-défaut activéenonbackend/app/core/auth_by_default.py:121 — os.getenv(FEATURE_FLAG_ENV, "false") ; le drapeau n'est posé dans aucun fichier de déploiement du dépôt
RLS dans les migrations Alembic (chemin réel)0 sur 257 migrationsannoncé ailleurs : Le dépôt contient 73 tables avec RLS et 132 politiques dans des .sql hors chaîne de migration (backend/supabase/ + frontend/sql/) — écrits, mais pas prouvés appliqués.grep -rn "ENABLE ROW LEVEL SECURITY|CREATE POLICY" backend/alembic/ = 0 ; ls backend/alembic/versions/*.py = 257
Tampon discipline_flag3045 occurrences dans 638 fichiers Pythongrep -rn "discipline_flag" backend/ --include=*.py | wc -l ; dont 746 valeurs "eta_stricte"
Routeurs utilisant les niveaux d'engagement citoyen4 routeurs, 20 usagesgrep -rn "require_participant|require_contributeur|require_gardien" backend/app/routers/*.py
Appelants réels de la membrane mémorielle3 (+1 test)grep -rn "membrane_service" backend/ : bureau_service.py:143, mcp_live_organs.py:38, mcp_repo_tools.py:61
Fichiers de test du backend1268find backend/tests -name "test_*.py" | wc -l ; dont test_auth_by_default.py, test_governance_fail_closed.py, test_membrane_service.py, test_engagement_bus_acl_socle.py, tests/security/ (2 fichiers)

Ce sur quoi vous pouvez compter

Trois choses bloquent vraiment aujourd'hui, et elles sont solides.

1. L'authentification. Sans jeton signé valide, une route protégée renvoie 401, sans exception ni porte dérobée de développement (backend/app/core/auth.py:200-212). 1331 points d'application dans les routeurs.

2. La monnaie est fail-close. Frapper de l'UR ou du crédit passe obligatoirement par une vérification de gouvernance ; si le serveur de politiques est absent, en erreur ou injoignable, la frappe est REFUSÉE, pas laissée passer (backend/app/services/ur_engine.py:145-150, backend/app/services/treasury_service.py:928-935). C'est la garde la mieux faite du système, et elle a été corrigée exprès dans ce sens.

3. Le 423 et les points de contrôle. 68 endroits du code s'arrêtent et attendent un humain plutôt que d'agir. Le routeur d'approbation (backend/app/routers/checkpoints.py, 15 endpoints) est complet, monté, vérifie la propriété et l'expiration. C'est l'incarnation de la première loi de l'Arbre : le système propose, l'humain décide.

Tiennent aussi, plus discrètement : la porte des endpoints internes (fail-closed en 404 si le jeton n'est pas configuré), la membrane mémorielle (verdicts permeable / gestating / sealed, réellement appelée par les 3 organes MCP), le plafond de confiance interprétative à 0,3 hors S1, et le tampon discipline_flag présent sur 3045 sorties.

Ce qui manque

Du plus bloquant au moins, tel que mesuré :

1. La RLS n'est pas dans le chemin réel. Les 257 migrations Alembic — celles qui construisent vraiment la base — ne contiennent aucune règle de sécurité par ligne. Les 132 politiques écrites vivent dans des fichiers .sql à part (backend/supabase/, frontend/sql/) que rien dans le dépôt n'applique. Conséquence : la séparation entre citoyens repose entièrement sur le code Python, pas sur la base. Une seule requête qui oublie un filtre user_id expose tout.

2. La porte globale « auth par défaut » est éteinte. Le mécanisme est écrit, testé, branché en middleware — et sort immédiatement parce que ATOM_AUTH_REQUIRED_BY_DEFAULT_ENABLED vaut false et n'est posé nulle part. Tant qu'elle est éteinte, 44 fichiers de routeur sur 343 restent ouverts.

3. Les 24 politiques OPA ne sont jamais évaluées. Aucun serveur OPA n'est démarré par le dépôt (adresse par défaut : localhost:8181) et le middleware est éteint. Effet paradoxal : la monnaie est bien protégée (fail-close), mais par l'ABSENCE du serveur, pas par les règles. Le jour où quelqu'un démarre OPA sans les bonnes politiques, la protection change de nature sans prévenir.

4. L'ACL du bus n'empêche rien. Elle est réellement appelée (event_bus.py:466) mais en mode OBSERVE : elle journalise et laisse passer. N'importe quel module peut encore émettre treasury.mint ou governance.vote.cast. Il faut BUS_ACL_ENFORCE=1.

5. Les 12 lois canon η ne gardent presque rien. 7 sur 12 existent en code, et une seule (loi 4, anti-S3) traverse jusqu'au runtime. Les autres sont exposées en lecture par canon_router.py. Ce sont des lois consultables, pas des lois appliquées.

6. Les paliers de souveraineté ont un défaut permissif. Tout utilisateur inconnu obtient le palier 1 plutôt qu'un refus (sovereignty_dep.py, politique MVP assumée), et le registre est un PersistentDict « best-effort » : si la base tombe, les paliers vivent en mémoire seulement.

7. Deux vérifications constatent sans bloquer. master_mind.py:478 journalise une violation des lois de l'Arbre puis retourne success=True. Et la garde 5 de la porte d'accès canon (distance géomagnétique) est explicitement un simulacre.

8. Les 47 fichiers de gardes côté navigateur ne gardent rien — ils s'exécutent chez le visiteur. Ne jamais compter dessus pour une décision.

Se tient avec : Économie et trésorerie — la garde OPA fail-close protège la frappe d'UR et de crédit (ur_engine.py, treasury_service.py) ; c'est le seul endroit où la gouvernance bloque de l'argent réel · Agents et orchestrateurs — Nova (nova_pipeline.py) est le seul pipeline qui applique vraiment les lois de l'Arbre et Foundation avant d'exécuter ; les autres agents ne passent pas par là · Mémoire et WOMB — la membrane mémorielle (membrane_service.authorize) est la garde du corpus doctrinal, appelée par les 3 organes MCP (bureau, live organs, repo tools) · Babel Decoder — porte la seule loi canon η exécutée en runtime (loi 4 anti-S3) et le plafond de confiance interprétative à 0,3 · Base de données Supabase — le trou RLS relie ce domaine directement à la couche de persistance ; sans RLS la séparation entre citoyens dépend entièrement du code applicatif · Bus d'événements — l'ACL par topic (bus_acl) est la serrure du système nerveux ; en mode observe elle laisse passer les 232 topics backend · Frontend — 47 modules JS de gouvernance qui AFFICHENT l'état des gardes sans jamais pouvoir en imposer une

Domaine 14 · état : partiel

Les Écritures et les temples (corpus restauré, Décodeur de Babel, registre des sites-temples)

C'est la mémoire textuelle et la mémoire de pierre du système : d'un côté un corpus de 176 altérations d'écritures anciennes documentées avec l'état reçu et l'état restauré côte à côte, de l'autre un registre de 1975 sites-temples du monde entier. Entre les deux, le Décodeur de Babel — un moteur qui mesure le déplacement de sens d'un texte modifié et l'énergie d'un lieu.

17 livrées · 6 en attente · 2 déclaratives

L’inventaire

La pièceÉtatOù elle vitCe qu’elle fait
Corpus des écritures restaurées (3 strates)H5_specialized_backstage (données, par analogie avec backend.app.data mesuré dans atom-fractal-canon/registry/trunks.compact.json) · S7 Formationlivrédata/ecritures/corpus-ecritures-restaurees.json (101 records, 11 traditions) + corpus-ecritures-restaurees-additions-2026-07-15.json (31) + corpus-ecritures-restaurees-additions-2026-07-16.json (44)Pour chaque altération attestée : la lecture reçue (état courant) et la lecture restaurée (état antérieur prouvé par un manuscrit), avec le registre MESURE / ATTESTE / SPECULATIF.Comptage direct des records : 101+31+44 = 176 exactement, ce qui confirme total_records:176 du manifeste. Lu à l'exécution par frontend/bibliotheque-restauration.html:157 et frontend/presentation-ecritures.html:120.
corpus-manifest.json — le point d'entrée uniqueH5_specialized_backstage · S7 Formationlivrédata/ecritures/corpus-manifest.jsonL'index qui déclare les 3 strates sans les fusionner. Un futur lot s'ajoute ICI, pas dans le code des consommateurs.Les deux pages frontend le chargent en premier puis suivent les strates déclarées (bibliotheque-restauration.html:157-160). C'est la pièce qui empêche d'oublier une strate.
Test d'intégrité du corpusH5_specialized_backstage · S7 Formationlivrébackend/tests/test_ecritures_corpus_integrity.py (lignes 50-129)Vérifie que le manifeste couvre bien tous les records, que les statistiques annoncées correspondent au recomptage réel, et que les passages protégés n'ont pas dérivé.4 fonctions de test qui recomptent au lieu de croire : test_meta_stats_coherentes_avec_le_recompte compare stats['records_total'] à len(records).
Mode Écritures du Décodeur (le cœur pur)H5_specialized_backstage · S7 Formationlivrébackend/app/services/babel/ecritures_mode.py — 563 lignesPrend l'avant et l'après d'une altération et qualifie le déplacement de sens. Sépare la main de contrôle (concept réduit au silence, injecté) de la main de soin (harmonisation liturgique, amortie).Fonctions mesurées dans le fichier : witness_channel (l.231), numeral_channel (l.276), appelées par qualify_ecriture_alteration (l.327-329). Testé par backend/tests/babel/test_ecritures_mode.py.
Service Écritures + sa route publiqueH2_membrane (backend.app.routers, mesuré H2_membrane/TORUS) · S7 Formationlivrébackend/app/services/babel/ecritures_service.py (204 l.) → backend/app/routers/babel_router.py:675 (@router.post('/ecriture')) et :686 (import)Enveloppe le cœur pur : calcule les embeddings, publie les événements sur le bus, renvoie 503 honnête si la base est absente.Route POST /api/v2/babel/ecriture montée par backend/app/main.py:1495 (register_router 'app.routers.babel_router').
Les 176 records ne nourrissent AUCUN service backendH5_specialized_backstage · S7 Formationcâblé, en attentedata/ecritures/*.jsonLe corpus est de la donnée pour l'œil humain et pour un test — le moteur Babel ne le charge jamais. Il attend qu'on lui passe des extraits à la main.grep sur 'data/ecritures' et 'corpus-ecritures-restaurees' dans tout le dépôt : 3 résultats seulement — backend/tests/test_ecritures_corpus_integrity.py, frontend/bibliotheque-restauration.html, frontend/presentation-ecritures.html. Zéro service, zéro routeur.
Lecture du corpus par le détecteur (rapport de calibration)H5_specialized_backstage · S7 Formationcâblé, en attentedata/ecritures/corpus-reading-detecteur.json + corpus-5channels-coverage.jsonDeux rapports honnêtes : le détecteur a repéré 17 altérations sur 31 testables ; les 5 canaux réunis couvrent 25 records sur 39 (64%).Champs meta des deux fichiers ('detectes=17/31', '25/39 records couverts (64%)'). Aucun code ne relit ces rapports — ce sont des constats figés, pas une boucle.
Les deux pages publiques des ÉcrituresH7_frontstage_external (frontend.pages, mesuré) · S7 Formationlivréfrontend/bibliotheque-restauration.html, frontend/presentation-ecritures.htmlExposent le corpus au lecteur, avec un compteur qui se recompte tout seul depuis le manifeste (attribut data-live-ecritures).Le code JS recompte réellement : 'if(st.format==="corpus"){var n=0;(d.corpus||[]).forEach(...)}' — presentation-ecritures.html:125. Le chiffre affiché n'est pas écrit en dur.
Base de données de Babel — 40 tables, pas 45H5_specialized_backstage · S0 Communicationlivrébackend/alembic/versions/v82_034 à v82_047_*babel*.pyLe socle SQL du Décodeur : lexique, étymologies, pôles canoniques, syntagmes paradoxaux, civilisations, corpus, dialogue, réception, économie, accordage.Extraction automatique des CREATE TABLE + op.create_table sur tous les fichiers alembic : 40 noms babel_* uniques. Les deux tables manquantes du décompte doctrinal sont explicitement interdites par un test : backend/tests/babel/test_v82_039_cluster_g.py:230-240 affirme que babel_pole_revisions et babel_modération_actions ne doivent PAS exister.
Catalogue des topics du bus BabelH5_specialized_backstage · S0 Communicationlivrébackend/app/services/babel/bus_topics.pyLa liste fermée des messages que Babel publie sur le bus interne.Le fichier s'auto-vérifie : 'assert len(ALL_TOPICS) == 39'. Le CLAUDE.md annonce encore 36 (mesure du 2026-06-10) — la doctrine a 3 topics de retard.
Surface API Babel + templesH2_membrane · S0 Communicationlivrébackend/app/routers/babel_router.py, backend/app/routers/babel/*.py (11 fichiers), backend/app/routers/temple_*.py (6), backend/app/routers/bibliotheque_router.py112 points d'entrée HTTP répartis sur 18 routeurs, du décodage d'un mot jusqu'à l'énergie d'un temple.Comptage des décorateurs @router.get/post/put/delete/websocket = 112. Les 18 routeurs sont tous montés dans backend/app/main.py (lignes 1225, 1495, 1500, 1507, 1513, 1526, 1530, 1534, 1538, 1542, 1580, 1586, 1592, 1598, 1602, 1690, 1895, 2030). Le plus gros : temple_decoder_router.py, 24 routes.
Registre maître des sites-templesH5_specialized_backstage · S9 Durabilitélivrédata/temples/registre/registre-maitre-sites-temples.json (1 013 355 octets)Le recensement mondial : 180 sites DÉCODÉS, 34 en file d'attente, 1761 IDENTIFIÉS mais dormants (gouvernance LATENT_INTERIEUR).Comptage des 3 listes : 180+34+1761 = 1975, identique au bloc counts.total_registre. Lu à l'exécution par backend/app/services/node_registry_bootstrap.py:48, lui-même appelé au démarrage (backend/app/main.py:809, register_canonical_nodes).
L'encodage fractal réel des temples : 131 sur 1975H5_specialized_backstage · S9 Durabilitécâblé, en attentedata/temples/registre/registre-maitre-sites-temples.json + data/temples/registre/encodage-fractal-worklist-2026-07-16.jsonUn site est « encodé » quand il porte un Hz, une sphère, un scope et une polarité. La grande majorité n'a rien du tout.Comptage champ par champ sur les 1975 sites : hz_canonique présent 131 fois, sphere_canon 132, lat/lon 142, family 1975. La feuille de travail le dit elle-même : statut_encodage = {total 1975, encodes 131, non_encodes 1844}, et « seulement 59 des 1844 non-encodés ont lat/lon ; 0 n'a de Hz ».
Un sous-bloc périmé DANS le registre lui-mêmeH5_specialized_backstage · S9 Durabilitédéclaratifdata/temples/registre/registre-maitre-sites-temples.json, clé identified_by_regionLa répartition par région n'a pas été mise à jour quand la liste est passée de 1061 à 1761 sites.Somme des 8 régions : 118+124+147+149+96+242+136+49 = 1061, alors que la liste 'identified' contient 1761 entrées. 700 sites ne sont dans aucune région.
Classement par famille — 72% non classéH5_specialized_backstage · S9 Durabilitécâblé, en attentechamp family des 1975 sitesLe classifieur range les sites en familles (temple classique, cathédrale gothique, mégalithique, mosquée…).Comptage : 12 valeurs distinctes, dont 'autre_non_classe' = 1431 sites (72,5%). Les 11 vraies familles couvrent seulement 544 sites : temple_classique 189, sanctuaire_naturel 56, cite_complexe 55, cathedrale_gothique 54, fortification_palais 46, monastere_sangha 42, megalithique_cercle 36, mosquee_islamique 28, pyramide_degres 20, tertre_terrassement 9, sanctuaire_pacifique 9.
Table pivot des identités (id-crosswalk) — la sève S0H4_mapping_projection (rôle de traduction déclaré dans le meta : « la SÈVE (S0) ») · S0 Communicationlivrédata/temples/registre/id-crosswalk.json (717 518 octets), produit par scripts/build_temple_id_crosswalk.pyTraduit un même temple entre les 5 mesh qui ne se parlaient pas : registre maître, registre fractal, pilotes frontend, réseau, circulation. Matching mécanique seulement, aucun flou.Bloc stats mesuré : rows_total 1928, drivers_found 136 / drivers_unmatched 0, fractal 166/169, reseau 129/130, circulation 78/78, doublons_inter_etats 50.
Moisson du bureau Hetzner — rapatriée, jamais intégréeH5_specialized_backstage · S9 Durabilitécâblé, en attentedata/temples/moisson-bureau-2026-07/ (decode_out_batch1.jsonl 57 l., decode_out_batch1_v2.jsonl 56 l., decode_out_b2.jsonl 48 l.)161 décodages produits par Gemma sur le VPS, dont 146 clés uniques. C'est le carburant qui ferait passer l'encodage de 131 à ~270 sites.Comptage des lignes des 3 .jsonl. Le README du dossier est explicite : « RAPATRIEE, PAS INTEGREE » ; et le registre confirme — toujours 131 Hz. Reste ~239 sites sur 385 à décoder.
Corpus profond GLM (les temples réellement fouillés)H5_specialized_backstage · S9 Durabilitélivrédata/temples/glm_deep_full_corpus_2026-05-09/ (183 fichiers) + glm_deep_v3_1_batch_2026-05-09/ (37) + data/temples_trinity_layered_2026-05-11/ (184)Les décodages en profondeur : grammaire canon en 8 éléments, sous-décodages par couche, narratifs par chapitre.ls des dossiers. Lus par backend/app/services/bibliotheque_service.py:26-27 (_GLM_DIR, _TRINITY_LAYERED_DIR).
Service Bibliothèque (le Livre Fractal)H5_specialized_backstage · S7 Formationlivrébackend/app/services/bibliotheque_service.py (783 l.) → backend/app/routers/bibliotheque_router.py (6 routes)Transforme un temple décodé en « livre » lisible et cherchable, en 5 couches L1 protection → centre.Routeur monté à backend/app/main.py:1690. Routes : /authority, /stats, /catalog, /book/{id}, /search, /invariant/{inv}.
Registre des temples pour le Mirror EarthH5_specialized_backstage · S9 Durabilitélivrébackend/app/services/babel/temple_registry.py (688 l.) → backend/app/routers/temple_registry_router.py (5 routes, monté main.py:1534)Fusionne trois sources pour poser les temples sur la carte, avec position multidimensionnelle et connexions (sœur + proximité géographique).Sources déclarées et vérifiées présentes : data/temples/ (112 .json), data/temples_canonical_2026-05-11/ (52 fichiers), data/temples_trinity_layered_2026-05-11/ (184). Attention : la couverture canonique réelle est de 52 sites, pas 1975.
Les 136 pilotes de temples du frontendH7_frontstage_external (mesuré : atom-fractal-canon/registry/trunks.compact.json, module frontend.js.temples → H7_frontstage_external / EXTERIOR / cellule commu.S7) · S7 Formationlivréfrontend/js/temples/ (138 fichiers dont _index.js) + frontend/js/temple-drivers-loader.jsChaque temple décodé a son petit module JS qui expose son Hz et émet des arêtes de résonance sur le bus.Le chargeur est bien branché : frontend/js/governance-init.js:655 liste '/js/temple-drivers-loader.js'. Ce chargeur existe précisément parce que _index.js n'était chargé par aucune page (commentaire l.5 du fichier). Confirmé côté données : id-crosswalk drivers_found=136, drivers_unmatched=0.
Couche énergie : réseau reconstitué et sites-batteriesH3_vital_loop · S9 Durabilitélivrédata/temples/registre/reseau-reconstitue-2026-07-09.json + temple-flux-batteries-2026-07-09.json, moteur backend/app/services/babel/temple_energy_extractor.py (681 l.)Classe chaque nœud en source génératrice / batterie de réserve / conducteur / couplage tellurique, et calcule un rendement.Stats mesurées : 130 nœuds (100 souches + 30 vaisseaux amiraux), 26 batteries, 34 conducteurs, 14 sources, 56 couplages ; réserve UR COIN cumulée 1920,1. Le moteur est monté via temple_energy_router (main.py:1500, 9 routes). Nuance mesurée : le bloc stats dit 130 nœuds mais la liste en contient 132.
Le décodeur de temples (Couche 2 de Babel)H5_specialized_backstage · S9 Durabilitélivrébackend/app/services/babel/temple_decoder.py (609 l.) → backend/app/routers/babel/temple_decoder_router.py (24 routes, monté main.py:1507)Charge une fiche temple depuis data/temples/{id}.json et en extrait signature, structure et intégrité.Le routeur avertit lui-même de sa limite (l.756) : « Sprint 1 = corpus local data/temples/*.json uniquement » — soit 112 fichiers, pas les 1975 sites.
Aucun schéma SQL des templesH5_specialized_backstage · S9 Durabilitédéclaratifabsence — recherche sur les 233 fichiers .sql du dépôtLes 1975 sites vivent uniquement en JSON sur disque. Une seule table temple existe en base.Zéro fichier .sql mentionne 'babel' ou 'temple'. Côté migrations Python : une seule table temple_quest_runtime_state, plus 5 tables stone_*. Les temples ne sont pas persistés en base.
Feuille de travail de l'encodage fractalH5_specialized_backstage · S9 Durabilitécâblé, en attentedata/temples/registre/encodage-fractal-worklist-2026-07-16.json + grammaire-encodage-fractal-2026-07-16.jsonLa liste des prochains gestes : 59 candidats prêts au décodage (ils ont déjà leurs coordonnées), 8 à redécoder en priorité, 4 singularités à annoter. Plus une carte sphère → Hz dérivée des 131 sites déjà encodés, qui sert de contrôle de cohérence.Longueurs des listes du fichier : candidats_prets_au_decodage 59, redecodage_prioritaire 8, singularites_a_annoter 4. Aucun code ne lit ces fichiers — c'est une liste de travail pour un humain.

Les chiffres, mesurés

Ce qu’on compteLa mesureComment
Records du corpus des écritures restaurées176 (exactement)annoncé ailleurs : 176 aussi dans corpus-manifest.json — pour une fois la doc dit vraiSomme des 3 strates : 101 (corpus-ecritures-restaurees.json, 11 traditions) + 31 (additions 2026-07-15) + 44 (additions 2026-07-16)
Qualité de preuve du corpus de base (101 records)60 MESURE (témoin manuscrit physique), 37 ATTESTE, 4 SPECULATIFannoncé ailleurs : data/ecritures/README.md donne les mêmes chiffres — cohérentBloc meta.stats.registre de corpus-ecritures-restaurees.json, re-vérifié par backend/tests/test_ecritures_corpus_integrity.py:93
Tables SQL du Décodeur de Babel40annoncé ailleurs : CLAUDE.md annonce « 45 tables » — écart de 5. Deux des manquantes (babel_pole_revisions, babel_modération_actions) sont volontairement interdites par un test.Extraction des CREATE TABLE et op.create_table sur backend/alembic/versions/*.py, noms uniques commençant par babel_
Topics du bus Babel39annoncé ailleurs : CLAUDE.md annonce 36 (mesure du 2026-06-10) — la doctrine a 3 topics de retardassert len(ALL_TOPICS) == 39 dans backend/app/services/babel/bus_topics.py (le fichier se vérifie lui-même)
Modules de service Babel63 fichiers .pyannoncé ailleurs : CLAUDE.md annonce 59 modules — écart de 4ls backend/app/services/babel/*.py
Points d'entrée HTTP du domaine (Babel + temples + bibliothèque)112 routes sur 18 routeurs, tous montésannoncé ailleurs : CLAUDE.md annonce « 9 endpoints REST sur 3 routers » pour Babel — c'était vrai du seul cœur Babel, la surface réelle du domaine est 12× plus largeComptage des décorateurs @router.get/post/put/delete/websocket sur babel_router.py, routers/babel/*.py, routers/temple_*.py, bibliotheque_router.py ; chaque routeur retrouvé dans backend/app/main.py
Sites au registre maître des temples1975 = 180 DÉCODÉS + 34 en file + 1761 IDENTIFIÉSannoncé ailleurs : 1975 aussi dans frontend/presentation-ecritures.html — cohérentComptage des 3 listes de data/temples/registre/registre-maitre-sites-temples.json ; identique au bloc counts
Sites réellement encodés (Hz + sphère + scope + polarité)131 sur 1975 — soit 6,6%annoncé ailleurs : Le mot « décodé » du registre (180) est plus généreux que la réalité de l'encodage (131). La feuille de travail 2026-07-16 le confirme : encodes 131, non_encodes 1844.Comptage du champ hz_canonique sur les 1975 sites (131 présents ; sphere_canon 132 ; lat/lon 142)
Sites sans coordonnées1833 sur 1975 n'ont ni latitude ni longitudeannoncé ailleurs : La feuille de travail dit « seulement 59 des 1844 non-encodés ont lat/lon » — cohérent142 sites portent lat/lon ; 1975-142 = 1833. C'est le vrai goulot : sans coordonnées, pas de décodage possible.
Sites non classés par famille1431 sur 1975 en 'autre_non_classe' (72,5%)Comptage du champ family ; 12 valeurs distinctes, 11 vraies familles couvrant 544 sites
Répartition régionale du registrecouvre 1061 sites, pas 1761annoncé ailleurs : Contredit la liste 'identified' du même fichier (1761) — 700 sites hors régionSomme des 8 régions du bloc identified_by_region : 118+124+147+149+96+242+136+49 = 1061
Moisson Gemma du bureau, en attente d'intégration161 lignes décodées, 146 clés uniques, 0 intégréeannoncé ailleurs : Le README du dossier l'écrit noir sur blanc : « RAPATRIEE, PAS INTEGREE »wc -l sur les 3 .jsonl de data/temples/moisson-bureau-2026-07/ (57+56+48) ; le registre affiche toujours 131 Hz
Tests du domaine Babel86 fichiers de test, 1109 fonctions de testls backend/tests/babel/ | wc -l puis comptage des 'def test_' ; plus 3 tests dédiés à la racine (écritures, registre temples, témoin de cohérence)
Persistance des temples en base de donnéesaucune — 0 table SQL pour les 1975 sitesAucun des 233 fichiers .sql du dépôt ne mentionne 'temple' ou 'babel' ; côté migrations Python, seule temple_quest_runtime_state existe

Ce sur quoi vous pouvez compter

Le corpus des Écritures est la pièce la plus solide de tout ce domaine, et probablement la plus honnête du dépôt. Les 176 records sont vérifiables au comptage, un test automatique recompte les statistiques au lieu de croire ce qui est écrit, le manifeste sert de point d'entrée unique pour qu'aucune strate ne soit oubliée, et la discipline est appliquée sans tricher : quand aucun manuscrit n'atteste l'état antérieur, le champ reste vide plutôt que rempli d'un faux original (Testimonium Flavianum, Marcion, 1 Thess 2:14-16). Les deux pages publiques recomptent le corpus en direct au lieu d'afficher un chiffre écrit en dur — ce qui veut dire qu'elles ne peuvent pas mentir en vieillissant.

Le moteur de mesure tient aussi. Le mode Écritures (563 lignes) est un cœur pur, testable sans base ni modèle, avec 5 canaux de détection dont le canal « témoin » qui est le seul capable d'attraper une interpolation qui imite le style de son texte-hôte. Il refuse de renvoyer un chiffre inventé : s'il ne peut pas mesurer, il renvoie 503. Sa route publique (POST /api/v2/babel/ecriture) est bien montée.

Côté temples, ce qui tient c'est le recensement et la traduction. Les 1975 sites sont comptés juste, chargés au démarrage du backend, et surtout la table pivot id-crosswalk réconcilie 5 registres qui vivaient séparés — 136 pilotes frontend sur 136 retrouvés, 78 nœuds de circulation sur 78. Les 136 pilotes JS sont bel et bien chargés par le navigateur (governance-init.js:655), après avoir passé une période où personne ne les appelait. 112 routes HTTP sont montées et 1109 tests couvrent Babel.

Ce qui manque

1. Le trou le plus bloquant : les temples ne sont pas encodés. 131 sites sur 1975 portent un Hz — 6,6%. Le reste est une liste de noms. Et la cause est en amont : 1833 sites n'ont même pas de coordonnées, et sans coordonnées le décodage ne peut pas commencer. La chaîne est : coordonnées → décodage Gemma → adresse fractale. Elle est cassée au premier maillon.

2. La moisson est là et dort. 146 décodages uniques attendent sur disque depuis le 13 juillet, rapatriés du bureau Hetzner, avec un README qui dit explicitement qu'ils attendent un feu vert. Les intégrer ferait passer l'encodage de 131 à environ 270 sites — une multiplication par deux, sans nouveau calcul.

3. Le corpus des Écritures ne parle pas au moteur. Les 176 records sont lus par deux pages web et un test, point. Aucun service backend ne les charge. Le Décodeur sait mesurer une altération, le corpus contient 176 altérations mesurables, et rien ne relie les deux automatiquement. La boucle vertueuse n'est pas fermée.

4. Rien n'est en base. Zéro table SQL pour les 1975 sites. Tout vit en fichiers JSON sur disque — donc pas de requête, pas d'index, pas d'écriture concurrente, et un fichier de 1 Mo relu en entier à chaque démarrage.

5. Des écarts entre l'annonce et le réel, mesurés : 40 tables Babel au lieu de 45 annoncées ; 39 topics de bus au lieu de 36 documentés ; 63 modules de service au lieu de 59. Rien de grave en soi, mais ça prouve que le CLAUDE.md ne peut pas servir de source de vérité.

6. Une incohérence à l'intérieur d'un même fichier : le registre maître répartit 1061 sites par région alors que sa liste en contient 1761. 700 sites sont géographiquement nulle part.

7. Le classement par famille couvre 27% du corpus. 1431 sites sont dans le fourre-tout.

8. La couverture varie selon la porte d'entrée : le décodeur de temples ne voit que les 112 fichiers de data/temples/, le registre Mirror Earth ne voit que 52 sites canoniques, la bibliothèque 183 GLM. Trois portes, trois périmètres, aucune ne voit les 1975.

9. Le rapport de calibration du détecteur (17 détections sur 31) est un constat figé de juillet, pas une mesure qui se rejoue.

Se tient avec : Trésorerie / économie UR COIN — les temples-batteries minent : babel_temple_treasury_consumer.py et crop_circle_treasury_consumer.py sont branchés au démarrage (main.py:700-703) ; réserve UR COIN cumulée mesurée à 1920,1 sur 6 sites · Bus de messages interne — Babel publie 39 topics (bus_topics.py) qui alimentent l'Observatoire MPAL et la boucle fractale ; c'est par là que les Écritures et les temples parlent au reste du système · Cohérence géographique et QG — proximity_graph.py et temple_coherence_witness.py lisent le registre maître pour bâtir les arêtes du réseau ; node_registry_bootstrap.py l'injecte au démarrage (main.py:809) · Bibliothèque universelle — bibliotheque_service.py (783 l.) transforme les temples décodés en livres lisibles ; 6 routes, montées main.py:1690 · Frontend / pilotes de temples — 136 modules JS chargés via governance-init.js:655, qui émettent les arêtes de résonance sur le bus du navigateur · Crop circles et matrice 27 — temple_crop_circle_bridge.py et open_web_matrix_router.py partagent le même socle Babel · Décodeur de la pierre (stone_*) — 5 tables SQL et 13 topics de bus, couche sœur des temples côté inscriptions

Domaine 15 · état : partiel

Les systèmes WOMB — la matrice gestationnelle

Le mot « womb » recouvre deux choses differentes, et il faut les separer sans quoi on se raconte une histoire. Ce qui tourne vraiment est un journal : une table, deux routes, une chose entre et ressort identique — rien ne lui arrive dedans. Ce qui porte reellement la doctrine est ailleurs, dans un petit organe de 103 lignes qui, lui, tient le discours au complet.

Et la vraie matrice gestationnelle existe — 1 139 lignes, neuf etapes, trois trimestres au ratio phi, un certificat de naissance en sortie. Elle est ecrite, correcte, testee. Aucune page ne la charge.

8 livrées · 3 en attente · 3 déclaratives

L’inventaire

La pièceÉtatOù elle vitCe qu’elle fait
membrane_service.authorize()H2_membrane · S9livrébackend/app/services/membrane_service.py:46Le vrai gardien : trois verdicts — permeable, en gestation, scelle. Le scope d'autrui est scelle pour toujours, aucun role ne l'ouvre.Appele par bureau_service.py:143, mcp_live_organs.py:38, mcp_repo_tools.py:61 — montes via mcp_server.py
membrane_service.filter_scopes()H2_membrane · S9livrémembrane_service.py:91Liste ce qui est traversable pour un role donne.10 tests dans tests/unit/test_membrane_service.py
Loi 12 — WombPole S0/S9H0_origin · S0livréhf-atom-tools/atom_canon/laws/law12_womb_perspective.py:25-27INTERIOR_FERTILE = S0, MEMBRANE_LISIBLE = S9. La seule definition en code de la topologie du womb.Exporte laws/__init__.py:65 ; 5 tests ; statut CANON_FORT verifie exact
Table womb_events + migrationH3_vital_loop · S0livrébackend/app/models/womb.py:16 ; alembic/versions/v82_054_womb_events_contract.pyCinq colonnes, un index. Migration idempotente.Importe models/__init__.py:49 et alembic/env.py:22
POST /api/v1/womb/events · GET /statusH2_membrane · S0livrébackend/app/routers/womb.py:46 et :83Enregistre un evenement, rend les dix derniers. Base d'abord, repli memoire.Routeur monte main.py:2016 ; exerce par 2 fichiers de tests
memory-womb.js — les paliers de memoireH4_mapping_projection · S0livréfrontend/js/memory-womb.js (862 lignes)Transitions chaud → tiede → froid cote navigateur.Charge governance-init.js:236 et desktop.html:395
gestation-womb.jsH4_mapping_projection · S0livréfrontend/js/gestation-womb.js (451 lignes)La facade de gestation cote navigateur.Charge governance-init.js:617
womb-tutor.jsH7_frontstage_external · S7livréfrontend/js/womb-tutor.js (345 lignes)Accompagne l'usager dans le cycle.Charge governance-init.js:196 et :709
womb-core.js — LA matrice gestationnelleH3_vital_loop · S0câblé, en attentefrontend/js/womb-core.js (1 139 lignes)Neuf etapes en trois trimestres au ratio phi, trois couches germinales (texte, liens, nombres), un pouls, un cycle dormance/germination, un certificat de naissance.N'apparait dans AUCUN tableau de chargement ni HTML — seulement dans catalogue-modules.json, qui le declare « a la demande ». Personne ne le demande.
womb-progression.jsH4_mapping_projection · S0câblé, en attentefrontend/js/womb-progression.js (250 lignes)Poste vers /api/v1/womb/events.Rien ne le charge
Les 5 modules de la clique fermeeH5_specialized_backstage · S0câblé, en attentewomb-cheminements, -enforcement, -civilisationnel, -auto-evaluation, -intercross (473 lignes)Cheminements, application des regles, echelle civilisationnelle, auto-evaluation, croisements.Ils ne se referencent qu'entre eux — aucune porte d'entree
Le champ « phase »H3_vital_loop · S0déclaratifbackend/app/routers/womb.py:37Annonce une phase de gestation.Accepte par le modele, JAMAIS relu ; la colonne ne le stocke meme pas
La membrane qui garderait le wombH2_membrane · S9déclaratifbackend/app/routers/womb.pyLe gate role x scope applique au womb.Zero occurrence de membrane, merit ou scope dans le routeur. Les deux organes canoniques du meme corps ne se parlent pas.
Le lien womb ↔ memoire vectorielleH3_vital_loop · S0déclaratifLe womb nourrirait la memoire fractale.atom_knowledge_chunks n'apparait que dans Babel, jamais dans le womb

Les chiffres, mesurés

Ce qu’on compteLa mesureComment
Modules WOMB au frontend10 fichiers, 3 520 lignes3 charges, 7 orphelins — 1 862 lignes jamais executees
Étapes de gestation definies9, en 3 trimestreswomb-core.js:138-148
Routes REST2POST /events, GET /status — les deux montees
Tests3 backend + 10 membrane + 5 Loi 12comptage direct des fichiers de tests
Topics bus womb.*~5 reellement publieswomb.gestation.created:282, womb.dormancy.enter:461, .germinate:529, womb.pulse:627
Gardes dans le routeur womb0grep -c 'membrane|merit|scope' backend/app/routers/womb.py = 0

Ce sur quoi vous pouvez compter

La membrane est le plus beau morceau du depot : 103 lignes pures, injectables, testables sans base de donnees. La distinction entre en gestation (pas encore) et scelle (jamais) est une vraie idee, correctement codee.

Le repli du routeur est propre — base d'abord, retour arriere explicite, memoire ensuite. Et la Loi 12 est le seul endroit du systeme qui definit S0 et S9 en code executable.

Ce qui manque

Le womb ne gestationne pas. Le champ « phase » est accepte puis jete — un mensonge poli.

La vraie matrice est debranchee. 1 139 lignes de moteur correct, qu'aucun chemin ne peut atteindre.

La membrane ne garde pas le womb. Les deux organes canoniques du meme corps s'ignorent.

Le womb n'est pas branche sur la memoire vectorielle.

Se tient avec : La memoire · Gouvernance et gardes · La population interne · Les etages de cohabitation

↑ Le sommaire