L’INSTITUTION ET L’ENTREPRISE — une pièce à deux faces : l’entreprise est un output de l’institution
ouvrir la planche en plein écran → · 34 pièces · 35 traverses · 23 marges
FACE A — L’INSTITUTION · Les 22 services institutionnels sont 22 dossiers de délibération — pas 22 organes — accrochés à UN clocher aveugle à l'échelle (publish() = 11 paramètres, sphère + canal, jamais la portée) ; le « second clocher » n'existe pas, c'est un artefact de règle de comptage ; et les deux sorties économiques ne sont pas « encryption + forge » mais UR (écrite) et OR-PLATINE (jamais écrite, trou nommé par le code lui-même) — l'encryption est une station, pas une sortie, et la forge est coupée trois fois avant d'atteindre la monnaie.
FACE B — L’ENTREPRISE, son output · La colonne de gestion n'a pas « une adresse et pas de voix » : elle a une adresse DÉCLARÉE (29 modules dans une liste littérale que rien ne vérifie), un registre d'entreprises dont l'UNIQUE producteur est du code mort derrière un `raise`, et un refus 503 qui porte sa raison dans le journal du serveur pendant que l'appelant reçoit « Internal server error » — tandis que la SORTIE ÉCONOMIQUE voisine, le Trésor, est elle BÂTIE et fail-close, et que l'autre sortie, la forge alchimique, est close à la mutation.
FACE A — L’INSTITUTION — CE QUE CETTE COLLECTE N'A PAS PU VOIR. (1) L'arbre de travail est SALE — 422 fichiers modifiés. Tout ce qui précède est mesuré au COMMIT a09f620b2 par `git show HEAD:` / `git grep HEAD` / `git archive HEAD`, sauf une seule chose dite explicitement : les listings de répertoires de `data/urbanisme/projets-services/` et la lecture des JSON de conseil, faits DANS L'ARBRE (ces fichiers ne figurent pas parmi les 422 modifiés, mais je ne l'ai pas prouvé fichier par fichier). (2) AUCUNE BASE, AUCUNE PROD : je n'ai ouvert ni atom_db ni le VPS. Donc : combien de comptes portent `admin` en production, si ATOM_SEAL_PRIVATE_KEY est provisionnée, si ADMIN_SEED_KEY est posée, et si une seule ligne de captation existe au grand-livre — NON ÉTABLI. Les fiches de mémoire disent « 0 admin en prod le 2026-09-25 » et « 429 des 448 tables vides » : je n'ai pas pu re-vérifier. (3) LA LANE GEMMA (176 lieux, ~90 dossiers) VIT HORS DÉPÔT, sur le bureau Hetzner — ses verdicts sont invérifiables ici ; je n'ai mesuré que les 22 dossiers rapatriés. (4) LE GRAPHE DE L'ÉTOILE COUVRE UN SEUL ARBRE : backend/app/services/**/*.py (870 fichiers). Les ~278 .py vivants hors backend/app/ ne sont PAS dans ce graphe ; tout « 0 entrant » qui en vient ne vaut que pour cet arbre. En revanche, chaque « 0 appelant » cité sur l'économie, la forge, les rôles et le sceau a été re-grepé sur `backend/` ENTIER (les deux arbres), et c'est dit à chaque fois. (5) CÔTÉ FRONTEND je n'ai vérifié le chargement que contre governance-init.js et les balises <script> des pages que j'ai nommées — pas contre les 122 pages HTML. Un module que je dis « non chargé » (forge-generator-pool.js, ristourne-store-ui.js) pourrait être inclus par une page que je n'ai pas ouverte. (6) Je n'ai pas lancé un seul test ni démarré l'application : « monté » ici signifie « register_router(...) présent dans main.py au commit » — et register_router avale les ImportError, donc un routeur listé peut échouer silencieusement à l'import en runtime. Je n'ai pas prouvé l'import effectif d'un seul des routeurs cités. (7) Le chiffre « 28 des 36 dossiers partagent un radical » (la forme exacte du manque) n'a PAS été re-mesuré ; sa propre fiche le déclare plancher.
ne pas dessiner
FACE B — L’ENTREPRISE, son output — Ce que cette collecte N'A PAS pu voir. (1) Aucun processus lancé, aucune base interrogée, aucune prod touchée : tout « monté » signifie « présent et appelé dans backend/app/main.py au commit 8addf1c94 », jamais « répond 200 ». Les quatre routeurs de cette planche sont enregistrés avec core=False, donc un ImportError les tuerait sans faire échouer le démarrage. (2) Les 429/448 tables vides mesurées en prod (fiche mémoire 2026-09) n'ont PAS été re-mesurées ici — je ne sais pas si `enterprise_marketplace_records` existe dans atom_db@138.197.132.63, seulement que sa migration v82_219 et son modèle existent au commit. (3) L'encryption comme sortie économique : NON ÉTABLI, aucun fichier de la chaîne de scellement ouvert. (4) Je n'ai pas lancé un seul test : aucune garde de cette planche n'est étiquetée « verte » — je n'ai jamais vu sa sortie. (5) Périmètre des « zéro appelant » : les DEUX arbres de backend/ (backend/app/ et les ~278 .py hors app/), via `git grep … HEAD`, hors archives/ et hors backend/tests/ ; les matchs tests ont été comptés séparément quand ils existaient. (6) Le frontend n'a pas été exécuté : « chargé » = présent dans un tableau de governance-init.js au commit, pas observé dans un navigateur. (7) Je n'ai pas vérifié si une épreuve FIGE l'un des défauts ci-dessus (tests `preserves_memory_fallback` cités par la fiche du 08-28 : non relus).
ne pas dessiner
| [A] les 22 dossiers de services institutionnels traverse | → | event_bus (le clocher)data/urbanisme/projets-services/ sont des JSON de délibération ; aucun ne porte de code ni de topic. Le lien entre les 22 et le bus est doctrinal, pas mesuré. | |
| [A] event_bus.publish() gouverne | → | la portée (indiv/commu/civ)backend/app/services/event_bus.py:407-421 — 11 paramètres, aucun de portée | |
| [A] les 870 services alimente | → | event_busgraphe AST au commit a09f620b2 : in=66, 1er carrefour ; son retrait fait passer la géante de 526 à 478 et crée 14 morceaux | |
| [A] les 870 services traverse | → | services/__init__.pybackend/app/services/__init__.py — 0 publish/subscribe ; in=62 sous la règle A, in≈0 sous la règle B ; « 89 » irreproductible | |
| [A] backend/services/__init__.py (2e arbre) contient | → | backend/services/agent/agent_registrybackend/services/__init__.py:27 importe un paquet qui n'existe ni au commit ni sur disque ; 0 entrant dans les deux arbres | |
| [A] fractal_scope_guard gouverne | → | les 870 services0 importateur service ; 3 importateurs routeurs (fractal_decode_router.py:22, fractal_websocket_router.py:37, fractale_communautaire.py:67), tous montés | |
| [A] captation temple + captation forge alimente | → | θ (g4_emission_guard.py:54)2 seuls écrivains : babel_temple_treasury_consumer.py:299 et forge_energy_consumer.py:415 ; mais leurs topics d'entrée ont une ACL vide (bus_acl.py:84-87) | |
| [A] θ autorise | → | governed_reward (la seule frappe)g4_emission_guard.py:237 → reserve_emission_in_transaction:187 → governed_mint.py:452, dans la transaction de l'appelant | |
| [A] governed_reward produit | → | les 4 producteurs (fractal, temple, forge, mission)babel_fractal_treasury_consumer.py:598 · babel_temple_treasury_consumer.py:296 · forge_energy_consumer.py:412 · mission_reward_consumer.py:124 | |
| [A] forge-alchemy.js (navigateur) alimente | → | forge_energy_consumer (serveur)forge-alchemy.js:913 publie sur le bus navigateur ; 0 appel réseau dans le fichier ; pont fail-close à liste vide (bus_acl.py:86) ; main.py:910 : « boucle ouverte » | |
| [A] le sceau Ed25519 (aip_seal_service) autorise | → | la frappe UR (governed_mint)0 occurrence de hashlib/hmac/ed25519/signature/nonce dans governed_mint.py et g4_emission_guard.py ; _SEAL_SCOPES = {"sitl"} (aip_seal_service.py:128) | |
| [A] le prélèvement 0,3 % produit | → | le trésortreasury_models.py:249 → treasury_service.py:2204,:2218 → economy_engine.py:503 (route montée, authentifiée, 5/min, fail-close base) | |
| [A] l'or-platine (2e sortie) produit | → | le grand-livreemission_state_router.py:160-162, verbatim : « aucune ligne ne l'écrit encore. Trou nommé. » | |
| [A] l'encryption (effective_capacity) produit | → | une sortie économiqueeffective_capacity vit dans 1 seul fichier (qg_fractalization/cluster_temple.py), 0 consommateur ; sentinel.fuel.available (sentinel-network-bridge.js:1004) a 0 abonné | |
| [A] les 11 FORGE_ROLES autorise | → | une personne qui les tienne2 GET seulement (economy.py:205,:226) ; 0 POST/PUT/PATCH sous /forge dans les deux arbres | |
| [A] les 17 rôles d'engagement autorise | → | les 16 gardes poséesengagement.py:54-76 (17 rôles) ; 16 sites de garde sur 4 routeurs montés ; mais seul `admin` est attribuable, via POST /api/v1/auth/seed-admin (auth_routes.py:535) → 2 marches atteignables sur 4 | |
| [A] l'inscription d'un citoyen autorise | → | un niveau d'engagementauth_service.py:126 accorde roles=["user"], absent de _ROLE_TO_LEVEL → Observateur à perpétuité ; User.add_role (models/user.py:272) a 0 appelant | |
| [A] p0p2_admission_gate (wrong_lieu) gouverne | → | le trajet d'un servicep0p2_admission_gate.py:489-492 compare request.lieu à passport.lieu — admission d'un AGENT dans une enceinte, position ①, pas ④ | |
| [A] spatial_command_bus (le patron du trajet) gouverne | → | les 22 services institutionnelsspatial_command_bus.py (1169 L, routeur monté main.py:1938) pilote des dispositifs ; aucun service institutionnel n'en dérive | |
| [A] mission_center (le gabarit) produit | → | la position ② (remontée)mission_center_service.py:641 « territory_id is always None » ; :765 « all collectors are called with territory_id=None » ; 10 collecteurs en dur | |
| [A] Communication Center (sève S0) alimente | → | le navigateurrouteur monté main.py:2418 ; chargé par balises <script> de frontend/communication-center.html, PAS par les tableaux de governance-init.js | |
| [B] POST /api/v2/economy-engine/enterprise/register autorise | → | EnterpriseRegistryService._enterpriseseconomy_engine.py:727 (raise) précède :748 (seul appel) — le trait est coupé par un raise, pas par une absence de code | |
| [B] Enterprise (le type) alimente | → | EnterpriseRegistryServiceenterprise_registry.py:280-290 (`self._enterprises[ent.enterprise_id] = ent`) — le trait existe, il n'est jamais parcouru | |
| [B] EnterpriseRegistryService.list_enterprises() alimente | → | Flux INVEST (Mission Center)adapters/invest_adapter.py:37 + mission_center_service.py:725 — câblé, source vide | |
| [B] app/core/agent_mandate.py (mandat P2) autorise | → | admission d'enceinte (P0+P1+P2)agent_mandate.py docstring E4 + p0p2_admission_gate.py:44 — schéma et validateur purs, aucune activation avant T4 | |
| [B] app/core/agent_mandate.py autorise | → | Enterprise / enterprise_id0 occurrence de `enterprise` dans agent_mandate.py et enclosure_mandate_registry.py ; MANDATE_SCOPES = {indiv, commu, civ} | |
| [B] PLACEMENT_ATLAS['trinity_palace'] contient | → | les 29 modules nommésgovernment_campus_service.py:126-155 + :318-323 — déclaration recopiée, aucun import ni garde qui confronte un module_id à un module réel | |
| [B] Refus 503 (code + reason) traverse | → | l'appelant HTTPmain.py:1537-1591 → refus_publics.py:88-92 (1 code admis, aucun des nôtres) → main.py:1475-1482 : l'appelant reçoit `internal_error` | |
| [B] Refus 503 (code + reason) produit | → | journal du serveurmain.py:1543-1553 (`logger.error` avec code_public et route bornée) | |
| [B] routers/enterprise_marketplace_router (7 portes d'écriture) alimente | → | table enterprise_marketplace_recordsenterprise_marketplace_router.py:78,115,133,160,172,182,192 — 7 refus 503 ; v82_219 crée la table | |
| [B] POST /treasury/mint · /treasury/transfer produit | → | base atom_db (ledger Trésor)economy_engine.py:145-150 (_require_treasury_db fail-close) + :398-470 | |
| [B] PUT /alchemy/root-coherence · POST /alchemy/transmute produit | → | la forge (transmutation)routers/alchemy.py:344 et :381 — `_alchemy_mutation_not_active()` en première instruction | |
| [B] governance-init.js alimente | → | frontend/js/entreprise-module.jsgovernance-init.js:78 (SPHERE_MODULE_MAP['entreprise']) — le module EST chargé sur entreprise.html | |
| [B] entreprise-module.js alimente | → | backend (economy-engine)entreprise-module.js:150-156 — `_syncToBackend` best-effort, 0 occurrence de `economy-engine` dans le fichier ; tout vit en localStorage | |
| [B] PersistentDict (labor_center, government_center) produit | → | base atom_dbcore/persistent_store.py:278-300 — dict RAM auto-enregistré, flush périodique best-effort (56 s par défaut, PERSISTENT_STORE_FLUSH_INTERVAL_SECONDS) ; « si la DB échoue, la donnée reste en mémoire » |
| A1 | L'INVENTAIRE DES 22 — la règle de comptage22 dossiers. RÈGLE : un répertoire = un service institutionnel, chacun portant conseil_3.json (6 esprits) + conseil_6.json (9 esprits) + conseil_9.json (verdict) + projet_du_lieu.md. Ce sont des DOSSIERS DE DÉLIBÉRATION, pas des organes de code.data/urbanisme/projets-services/ (22 répertoires, comptés) · confirmé dans le code | |
| A2 | LES 22 VERDICTS — l'étage entier est ratifié SOUS CONDITIONS22/22 exactement, valeur littérale `ratifie_sous_conditions` au niveau RACINE du JSON (vérifié par parse, pas par grep). ⚠ Un enum de verdict observé à 22/22 une seule valeur ne discrimine RIEN — c'est la loi que la REPRISE du 2026-08-26 a payée sur la lane Gemma (~98 % identiques = « reconnaissance de forme, pas jugement »). Ici la lane qui devait JUGER rend aussi 22/22. Le compte est juste ; sa portée probante est nulle.data/urbanisme/projets-services/*/conseil_9.json, clé .verdict · confirmé dans le code | |
| A3 | L'ÉTOILE — le clocher du bus, et il est AVEUGLE À L'ÉCHELLEpublish() = 11 paramètres EXACTEMENT : event_name, data, source, user_id, sphere_id, scene_id, sphere_primary, sphere_affluent, sphere_ratio, canal, status. ZÉRO paramètre de portée/scope — grep `portee|portée|scope` sur le fichier entier : 0 occurrence pertinente. VALID_CANALS = 16 (enum fermée, un canal hors enum est forcé à `bus` ET marqué status=red, :467). Le clocher voit la SPHÈRE et le CANAL ; il ne peut pas voir à quelle échelle l'événement se passe.backend/app/services/event_bus.py:407-421 (signature publish) · :289-295 (VALID_CANALS) · confirmé dans le code | |
| A4 | ⚠ CORRIGÉ — LES PAROISSES : le corps n'a pas de squelette (chiffres rafraîchis)AU COMMIT, règle B (feuille prioritaire, paquet seulement si aucune feuille ne résout) : 870 modules · 1137 arêtes · 211 composantes faiblement connexes · géante 526 = 60,5 % · 166-168 modules sans aucun lien interne = 19,3 % · densité 1,31. Arêtes internes à un sous-paquet 443 / plat↔plat 516 / traversant une frontière 178. Paroisses les plus scellées : babel (69 modules, 111 int / 32 sortantes) · stone_decoder (26, 52/9) · qg_fractalization (25, 26/12) · bioacoustic (17, 36/3) · embeddings (13, 15/0 sortante) · bayon (10, 17/0 sortante). ⚠ LE DOC SOURCE (2026-08-29) ANNONÇAIT 846/1050/213/490/167/1,24 — PÉRIMÉ de +24 modules et +87 arêtes. LA FORME, elle, se reproduit exactement : on retire event_bus → géante 526→478 (−48) et composantes 211→225 (+14 morceaux) ; le doc disait 490→442 (−48) et +14 morceaux. Même effilochage, même clocher unique.graphe AST reconstruit au commit a09f620b2 sur backend/app/services/**/*.py (870 fichiers, 0 échec de parse) · confirmé dans le code | |
| A5 | ÉCARTÉ PAR MESURE — ce ne sont PAS les centres, ni les trois niveauxL'organe de la portée a 3 importateurs, TOUS des routeurs, TOUS montés — et 0 importateur dans les 870 services. Les 4 services qui le « citent » le citent EN COMMENTAIRE (fractal_position_resolver.py:565, position_registry.py:287, relation_mutuelle_service.py:150 et :178 ; le doc d'août n'en nommait que 2). La portée est une douane de frontière, pas un organe irrigué : décidée à l'entrée, jamais transportée.backend/app/services/fractal_scope_guard.py (0 entrant service) · backend/app/routers/babel/fractal_decode_router.py:22 · babel/fractal_websocket_router.py:37 · fractale_communautaire.py:67 · montés main.py:2001,2002,2007 · confirmé dans le code | |
| A6 | LE PATRON DU TRAJET EXISTE — et il a été bâti pour du matériel1169 L confirmées au commit. Le seul service dont les quatre positions sont des CHAMPS exigés : `requires_spatial` impose lat/lon (10 occurrences de la clé dans la table des commandes), `issuer_id` sans défaut, `target_device_id` vérifié à l'accusé, status/result/history reviennent dans le même enregistrement. Ce n'est pas du vocabulaire de lieu : c'est un bus de commandement de dispositifs.backend/app/services/spatial_command_bus.py (1169 lignes) · routeur monté main.py:1938 (app.routers.spatial_command_bus_router, préfixe /api/v2/spatial-commands) · confirmé dans le code | |
| A7 | LE GOULOT θ — tout ce qui produit de la valeur converge sur une seule ligne (et c'est MIEUX bâti qu'annoncé)θ = min(1, captation_24h / max(MA7j,1)) à g4_emission_guard.py:54. UN SEUL appel de production : :237, dans reserve_emission_in_transaction. Celui-ci a UN SEUL appelant de production : governed_mint.py:452. Et governed_reward est la seule frappe des QUATRE producteurs : fractal (babel_fractal_treasury_consumer.py:598), temple (babel_temple_treasury_consumer.py:296), forge (forge_energy_consumer.py:412), mission (mission_reward_consumer.py:124). ⚠ LA FICHE DU 2026-09-10 EST PÉRIMÉE sur ce point et DANS LE BON SENS : elle disait « emission_allowance, exactement trois appelants » ; au commit emission_allowance n'a plus qu'UN appelant (mission_reward_consumer.py:111) et la garde est passée DANS la transaction, sérialisée par le verrou du master, avec cadence lue au grand-livre durable (grants_au_ledger, fail-close à -1). Deux seuls écrivains de captation (le numérateur de θ) dans tout le dépôt : temple (:299) et forge (:415), via CAPTATION_PREFIX (governed_mint.py:36) — les lignes 263 et 341 de la fiche ont bougé.backend/app/services/babel/g4_emission_guard.py:54 (compute_theta) · :237 (seul appel de production) · :187 (reserve_emission_in_transaction) · backend/app/services/babel/governed_mint.py:447-452 · confirmé dans le code | |
| A8 | ⚑ LE CLAPET FERMÉ — les quatre topics qui nourrissent θ ont une liste d'autorisation VIDEVerbatim, quatre lignes consécutives : "babel.temple.energy.generated": frozenset() · "mission.rewarded": frozenset() · "forge.product.distributed": frozenset() · "forge.pierre.philosophale": frozenset(). Fail-close inconditionnel. Ce sont EXACTEMENT les quatre sujets dont dépend l'économie.backend/app/core/bus_acl.py:84-87 · confirmé dans le code | |
| A9 | LE PRÉLÈVEMENT AU PASSAGE — bâti, vivant, atteignable, et contraire à la doctrine du lieufee_rate = Decimal("0.003") — 0,3 % sur chaque conversion, dans LES DEUX SENS, décrit en commentaire comme « 7e prélèvement du dépôt, jamais nommé ailleurs ». Appliqué à treasury_service.py:2204 (_quote_credits_to_coin) et :2218 (_quote_coin_to_credits). Atteignable par POST /api/v2/economy-engine/treasury/bridge/credits-to-coin — authentifié (get_current_user_id_str), limité à 5/minute, et fail-close sur la base (_require_treasury_db). Le routeur est monté. La doctrine du lieu dit « souveraine, sans impôt » : ce prélèvement est le seul organe de recette câblé.backend/app/services/treasury_models.py:247-249 · backend/app/services/treasury_service.py:2204 et :2218 · backend/app/routers/economy_engine.py:503-524 et :548 · monté main.py:2437 · confirmé dans le code | |
| A10 | LE MINEUR N'EST PAS UNE PREUVE DE TRAVAIL_estimate_ur_coin = (longueur de la sérialisation UTF-8 en octets ÷ 1024) × 10 × (1,0 si sphère cible, 0,5 sinon). Aucun nonce, aucune difficulté, aucun tiers. La seule occurrence de hashlib du fichier (:244) est un sha256 tronqué à 16 hexadécimaux qui sert d'identifiant d'idempotence, pas de preuve. Le « mineur » est fractal_bio_tick_worker, une HORLOGE : asyncio.sleep sur VIBE_LONG_INDIV=56 s / COMMU=600 s / CIV=3600 s.backend/app/services/babel/fractal_pipeline.py:261-265 · :244 · backend/app/services/babel/fractal_bio_tick_worker.py:52-54 · confirmé dans le code | |
| A11 | LA FRAPPE S'ÉMET SANS UN OCTET SIGNÉ — pendant que le sceau Ed25519 existe, monté, avec UN seul scopeCÔTÉ MONNAIE : grep hashlib|hmac|ed25519|nacl|signature|sign(|digest|nonce sur governed_mint.py → 0 ; sur g4_emission_guard.py → 0. treasury_service.py importe hashlib à la ligne 50 et ne l'utilise JAMAIS (1 seule occurrence dans tout le fichier). CÔTÉ SCEAU : aip_seal_service.py:52 importe le vrai ed25519 de `cryptography` ; :128 déclare `_SEAL_SCOPES = {"sitl"}` — une allowlist d'UN SEUL scope ; l'enveloppe entière est signée (_attestation_view, :135-156) avec `requested_by` dans les octets ; fail-close à None sans ATOM_SEAL_PRIVATE_KEY. Trois routes montées : POST /seal (:489), POST /seal/verify (:512), GET /seal/status (:520). Son unique consommateur frontend est lesser-key.js:421. ZÉRO câble entre le sceau et la frappe.backend/app/services/babel/governed_mint.py et g4_emission_guard.py (0 occurrence crypto) · backend/app/services/treasury_service.py:50 · backend/app/services/aip_seal_service.py:52,128 · backend/app/routers/aip_router.py:489,512,520 · monté main.py:2383 · frontend/js/lesser-key.js:421 · confirmé dans le code | |
| A12 | LA SÈVE S0 — le Communication Center est bâti et monté (chemin de chargement corrigé)BACKEND : routeur monté à main.py:2418, service sous backend/app/services/communication_center/ (paroisse scellée, 0 arête sortante). FRONTEND : les DEUX modules (communication-center.js et communication-center-governed.js) sont chargés par des balises <script> de frontend/communication-center.html. ⚠ PRÉCISION QUE LA PLANCHE N'AVAIT PAS : ils ne sont PAS dans les tableaux de modules de governance-init.js ; governance-init.js:150-152 ne fait que mapper paresseusement la page `communication-center` vers `/js/communication-center-governed.js`. Le chargement est par la PAGE, pas par le chargeur global.backend/app/routers/communication_center_router.py monté main.py:2418 · frontend/communication-center.html (balises script) · frontend/js/governance-init.js:150-152 · confirmé dans le code | |
| A13 | LE REMÈDE DIFFÈRE, ET C'EST LA LOI DE LECTURE DE LA PLANCHEDEUX DÉFAUTS, DEUX REMÈDES, et cette planche les porte tous les deux côte à côte. BÂTI ET DÉBRANCHÉ = du CODE sans appelant → le remède est une COUTURE (ex. la forge : un producteur serveur + une inscription d'autorité ; l'or-platine : une ligne de grand-livre). POSTE NON TENU = une STRUCTURE sans occupant → le remède est une NAISSANCE, aucune ligne de code ne le comble (ex. les 11 postes de forge, les 16 rôles inattribuables, les 2 marches manquantes de l'escalier). Confondre les deux fait écrire du code là où il faut un passeport, et attendre un agent là où il faut un appel.memory/les-postes-existent-personne-ne-les-tient.md · confirmé par mesure sur l'escalier et la forge · confirmé dans le code | |
| A14 | LA FORME EXACTE DU MANQUE — la faiblesse d'un lieu EST sa fonction constitutive28 des 36 dossiers (14 lieux civiques + 22 services) partagent un radical entre le nom du lieu et sa dimension la plus faible — la fiche elle-même déclare ce 28 comme un PLANCHER, le proxy comparant des MOTS. Non re-mesuré par moi.memory/les-postes-existent-personne-ne-les-tient.md (fiche datée 2026-08-26) · non confirmé dans le codeLe proxy est lexical, pas fonctionnel : il ne voit pas « Porte Oudjat → LE GARDIEN » (aucun radical commun) alors que l'heuristique y tient. L'heuristique est utilisable ; son chiffre n'est pas une mesure. | |
| A15 | ⚠ CORRIGÉ — TRAJET : le refus « mauvais lieu » existe, mais c'est la position ①, pas ④`wrong_lieu` (403) compare `request.lieu` à `passport.lieu` — c'est OÙ L'INSTANCE S'OPÈRE (position ①), pas À QUI LE SERVICE EST DESTINÉ (position ④). Occurrences dans tout backend/ : 2, dont 1 de test. Il a DEUX FRÈRES que la planche n'annonçait pas (wrong_sphere, wrong_environment). La garde EST installée (main.py:572, au niveau module) et le runtime est activé au démarrage (main.py:593).backend/app/services/p0p2_admission_gate.py:489-492 (wrong_lieu) · :481-484 (wrong_sphere) · :485-488 (wrong_environment) · main.py:572 (_wire_enclosure_admission) · main.py:593 (_activate_enclosure_runtime) · main.py:470-472 · confirmé dans le codeTrois maillons. (a) Ce n'est pas un garde de SERVICE : il garde l'admission d'un AGENT dans une enceinte. (b) `enclosure_runtime_status` naît `{"status":"inert","reason":"enclosure_runtime_not_activated"}` (main.py:470-472) — l'exécuteur reste volontairement non assigné. (c) La position ④ reste tenue partout par `user_id` seul, et la position ③ (redescente) n'a toujours aucun garde en vigueur. | |
| A16 | ⚠ DÉGRADÉ — LE MISSION CENTER : le gabarit est MONTÉ, mais sa position ② est un champ toujours nulMONTÉ : oui, confirmé. Mais le service dit verbatim à la ligne 641 : « territory_id is always None (ADR D2: null accepted for MVP) » et à la 765 : « All collectors are called with territory_id=None at registration time ». 10 sites `lambda: collect_…` au commit (la fiche de mémoire du 2026-08-29 en annonçait 11 — chiffre périmé).backend/app/routers/mission_center.py monté main.py:2193 (préfixe /api/v2/mission-center) · backend/app/services/mission_center_service.py:641 · :765 · :244,:250,:824,:828 · confirmé dans le codeLa position ② (où l'information remonte) EST un champ — et ce champ est câblé à None au point d'enregistrement. Un blanc qui se déclare, mais un blanc. | |
| A17 | ⚑ L'ESCALIER D'ENGAGEMENT — 4 niveaux, 17 rôles, 16 gardes, et DEUX marches atteignables sur quatre17 rôles EXACTEMENT dans _ROLE_TO_LEVEL (4 Gardien : admin/gardien/guardian/steward · 7 Contributeur : contributeur/contributor/mentor/healer/soignant/arbitre/moderator · 6 Participant : participant/member/membre/citoyen/citizen/voter). 16 GARDES POSÉES, comptées : 20 lignes d'usage moins 4 lignes d'import = 16 sites de endpoint (economy_engine 8, governance 2, health_center_router 3, sentinel 3) ; les 4 routeurs sont montés (main.py:1741, 2131, 2437, 2451) — donc les 16 gardes sont ATTEIGNABLES. ⚑ ET LA MÉCANIQUE DU MANQUE N'EST PAS CELLE ANNONCÉE : l'inscription accorde `roles=["user"]` (auth_service.py:126) et « user » N'EST PAS DANS LA TABLE → tout citoyen inscrit est Observateur, à perpétuité. `User.add_role`/`remove_role` existent (models/user.py:272-284) et ont ZÉRO appelant dans les deux arbres. Le SEUL geste d'attribution du dépôt est `POST /api/v1/auth/seed-admin`, gardé par la variable d'environnement ADMIN_SEED_KEY, qui accorde ["user","admin","creator"]. Comme admin→GARDIEN et que level_of prend le MAXIMUM, l'escalier n'a que DEUX marches atteignables sur quatre : Observateur et Gardien. PARTICIPANT et CONTRIBUTEUR — les niveaux qu'exigent 15 des 16 gardes — ne peuvent être atteints par personne.backend/app/core/engagement.py:44-49 (EngagementLevel) · :54-76 (_ROLE_TO_LEVEL) · backend/app/services/auth/auth_service.py:126 · backend/app/models/user.py:272-284 · backend/app/api/v1/routes/auth_routes.py:535-589 (POST /seed-admin, monté main.py:1666) · confirmé dans le codePas « aucun geste d'attribution » : UN geste, et c'est une porte d'amorçage à clé d'environnement. Ce qui manque est l'organe qui fait MONTER quelqu'un d'une marche — un appelant à add_role, ou une route de promotion. 16 des 17 rôles restent importables ; aucun n'est attribuable. | |
| A18 | LES 11 POSTES DE FORGE — 11 rôles, 2 GET, et ZÉRO geste d'attribution dans LES DEUX ARBRES11 RÔLES EXACTEMENT, codes vérifiés : GUARDIAN_INFRA, GUARDIAN_SECURITY, ARCHITECT_LEGAL, ARCHITECT_FINANCE, MEDIATOR_ONBOARD, MEDIATOR_SUPPORT, EXPLORER_LAND, EXPLORER_TECH, DEV_LEAD, DEV_BLOCKCHAIN, DEV_AI. Servis par 2 GET, sur un routeur monté. ⚑ ZÉRO POST/PUT/PATCH sous /forge dans les DEUX arbres (backend/app/ ET les 278 .py hors app/) — grep `(post|put|patch)("/forge` sur backend/ entier : aucune ligne. Et les deux îlots ne se touchent pas : match_role (worker_matching.py:701) prend une liste de compétences libre ; les `required_skills` des FORGE_ROLES ne lui sont jamais passés, et `min_resonance_score` (échelle 0-60+) n'est croisé avec aucun `reputation_score` (échelle 0-1).backend/app/data/economy_data.py:243 (FORGE_ROLES) · backend/app/routers/economy.py:205 (GET /forge/roles) et :226 (GET /forge/roles/{category}) et :505 (compte) · monté main.py:2208 (préfixe /api/v2/economy) · backend/app/services/worker_matching.py:701 (match_role) · confirmé dans le codeLe geste d'attribution. Les postes sont déclarés, lisibles, catégorisés, et nul ne peut y être nommé — ni par un humain, ni par le matching, qui ne les lit pas. | |
| A19 | ⚑ RÉFUTÉ — LE SECOND CLOCHER, services/__init__.py, « 89 entrants »TROIS raisons, chacune suffisante. (1) CE N'EST PAS UN CLOCHER : backend/app/services/__init__.py ne porte AUCUN publish/subscribe/REGISTRY — ses seules fonctions sont _load_export, _load_agent_distribution, _load_derived_export, __getattr__, __dir__ ; c'est un shim d'import paresseux à 20 entrées. (2) LE 89 EST UN ARTEFACT DE RÈGLE : graphe AST reconstruit au commit a09f620b2, périmètre backend/app/services/**/*.py — sous la règle A (l'arête vers le PAQUET est comptée) services.__init__ a in=62 et devient 2e carrefour ; sous la règle B (feuille prioritaire — celle qu'employait le doc source du 2026-08-29) il DISPARAÎT du classement (in≈0). 89 n'est reproductible sous aucune des deux. Hors périmètre, repo entier : 222 fichiers écrivent `from app.services import X`, dont 171 pour `event_bus` seul. (3) L'AUTRE services/__init__.py EST MORT : backend/services/__init__.py (2e arbre, 126 L) importe `backend.services.agent.agent_registry` à la ligne 27 — et backend/services/agent/ N'EXISTE PAS, ni au commit ni sur disque ; l'import lève ModuleNotFoundError. Entrants mesurés dans les DEUX arbres (`from services import` / `from backend.services import`) : 0.backend/app/services/__init__.py:20-99 (_LAZY_EXPORTS) · :136 (__getattr__) · backend/services/__init__.py:27 · confirmé dans le codeIl n'y a qu'un clocher : event_bus (in=66, inchangé depuis août). Le second n'est pas « débranché » — il n'a jamais été un clocher. | |
| A20 | ⚑ RÉFUTÉ — LA DEUXIÈME SORTIE ÉCONOMIQUE N'EST PAS L'ENCRYPTION : c'est l'OR-PLATINE, et sa ligne n'est pas écriteLE CODE LE DIT LUI-MÊME, verbatim à emission_state_router.py:160-162 : « elle a deux SORTIES, l'UR (énergétique) et l'or-platine (transactionnel, l'alchimie du plomb). Ce cadran ne lit que ce que le grand livre porte aujourd'hui, c'est-à-dire l'UR. La sortie alchimique n'y est pas — non parce qu'elle vaut zéro, mais parce qu'aucune ligne ne l'écrit encore. Trou nommé. » ET L'ENCRYPTION N'EST PAS UNE SORTIE : l'« énergie de chiffrement » agrégée en pool `effective_capacity` est référencée dans EXACTEMENT UN fichier de tout le dépôt (qg_fractalization/cluster_temple.py) — zéro consommateur cryptographique ; et `sentinel.fuel.available`, qui relaie le produit de forge vers le chiffrement, est publié à sentinel-network-bridge.js:1004 et n'a AUCUN abonné (3 occurrences au total : le publish, la liste events_out :1210, le catalogue). Le carburant meurt au relais.backend/app/routers/babel/emission_state_router.py:156-162 (verbatim) · backend/app/services/qg_fractalization/cluster_temple.py (seul fichier portant effective_capacity) · frontend/js/sentinel-network-bridge.js:1004 · docs/DEUX-SORTIES-DE-LA-FORGE-VERDICT-2026-08-28.md · confirmé dans le codeLa ligne de grand-livre de l'or-platine. Et, pour l'encryption : un consommateur d'effective_capacity, ou un abonné à sentinel.fuel.available. L'encryption est une STATION de l'échelle (à la source dans l'armure, en 7e à l'activation) — jamais une sortie de la forge. | |
| A21 | ⚑ RÉFUTÉ — LA FORGE ALCHIMIQUE N'EST PAS UNE SORTIE ÉCONOMIQUE : elle est coupée TROIS FOISCOUPURE 1 — les producteurs sont dans le NAVIGATEUR seulement : forge-alchemy.js:913 publie `forge.product.distributed` sur le bus in-process ; grep atomPost|atomFetch|fetch( sur forge-alchemy.js → 0, sur forge-energy-bridge.js → 0. Aucun fichier de forge ne parle au serveur. COUPURE 2 — le seul pont navigateur→serveur (POST /api/v2/event-bus/publish) est fail-close avec une liste VIDE sur ces deux topics (bus_acl.py:86-87). COUPURE 3 — le consommateur backend est abonné et attend dans le vide : main.py:910 dit verbatim « Le producteur frontend et forge.cycle.completed restent non branchés : boucle ouverte. » Le consommateur (forge_energy_consumer, abonné au démarrage main.py:908-910) est bâti, monté, et n'entendra jamais rien.frontend/js/forge-alchemy.js:913 (_pub) · frontend/js/forge-alchemy.js et forge-energy-bridge.js (0 appel réseau) · backend/app/core/bus_acl.py:86-87 · backend/app/main.py:908-910 · confirmé dans le codeUn producteur SERVEUR pour la captation forge, et l'inscription de sa source dans EXACT_TOPIC_SOURCES. Ouvrir le pont navigateur est refusé par trois mécanismes indépendants et DÉLIBÉRÉS — c'est une décision de sécurité, pas une ligne de code. | |
| B1 | Entreprise (l'objet) — le type `Enterprise`695 lignes au fichier ; 7 EnterpriseType, 9 EnterpriseStatus, 4 EnterpriseOrigin, 15 IndustryCategory, 6 SubsidyType — comptés à l'énum, HEADbackend/app/services/enterprise_registry.py:106-212 (commit 8addf1c94) · confirmé dans le codeAucun. Le `__post_init__` (ligne 172) engendre bien l'uuid et les horodatages ; le type est importé par `routers/economy_engine.py:731` et `services/adapters/invest_adapter.py:4`. C'est la seule pièce de la planche qui tient telle qu'annoncée. | |
| B2 | Colonne de gestion, face DIRECTION — Trinity Palace et sa carte de placement29 trinity_palace · 7 government_campus · 19 bridge_modules — comptés par AST (`ast.literal_eval`) sur le littéral au commit, pas au grep. Le 29 annoncé est EXACT. 4 PALACE_BRIDGES (lignes 94-124).backend/app/services/government_campus_service.py:126-290 (PLACEMENT_ATLAS) ; routers/government_campus_router.py:53-55 ; monté main.py:2063 · confirmé dans le codeLa carte est lisible par route — `GET /api/v2/government-campus/placement-atlas`, routeur monté — mais c'est un littéral que RIEN ne vérifie : `get_placement_atlas()` (ligne 318) recopie le dict, n'importe aucun des modules qu'il place, et aucune garde ne lie un `module_id` à un module réel. La carte place `enterprise_registry` en `trinity_tower / palace_comm` — c'est-à-dire qu'elle donne une adresse de direction à un registre qu'aucun code atteignable ne peut remplir. La carte ne peut pas se tromper parce que personne ne la confronte. | |
| B3 | La première sortie économique — Trésor (mint / transfer / bridge / stake)6 endpoints non-GET de Trésor, 6 DB-first ; mint sous `require_admin` ; limiteur 5/minute sur mint et transferbackend/app/routers/economy_engine.py:145-150 (_require_treasury_db, 503 fail-close), :128-142 (_bind_source_to_caller, 403 BOLA), :398-422 (mint, require_admin + limiter 5/min), :423-470 (transfer) · confirmé dans le codeRien sur ce trait — et c'est le point que la planche devait montrer pour que le reste se voie : la monnaie, ce qui engage le plus, est le morceau le MIEUX bâti de la colonne (base obligatoire, source liée au porteur, admin pour la création, limiteur). C'est l'entreprise, pas le Trésor, qui n'a pas de voix. | |
| B4 | ⚑ REFUTÉ — le mandat de représentation EXISTE : `app/core/agent_mandate.py`335 lignes ; 20 champs autorisés (`_ALLOWED_KEYS`) ; 3 portées (`MANDATE_SCOPES = {indiv, commu, civ}`) ; 6 clés de statut refusées nommément ; 2 tables alembic (v82_266 `enclosure_agent_mandate_versions` + `enclosure_agent_mandate_authority`), 1 clé d'émetteur (v82_270)backend/app/core/agent_mandate.py:1-335 ; importé par 8 services de production (control_plane_mandate_issuer:33, enclosure_birth_membrane_adapters:23, enclosure_mandate_preparation_registry:21, enclosure_team_birth_prepare_mandate_port:15, enclosure_team_birth_register_mandate_port:17, instance_team_composer:58, p0p2_admission_gate:44, supervisor_p0p2_admission_gate:21) · confirmé dans le codeDEUX maillons, et aucun n'est « le fichier n'existe pas ». (1) Son propre docstring, clause E4 : « schéma + validateur PURS, aucune activation… le mandat devient exécutable en T4 ». (2) Il ne parle pas d'entreprise : 0 occurrence de `enterprise`/`entreprise` dans `agent_mandate.py`, 0 dans `enclosure_mandate_registry.py`. Le mandat bâti lie `owner_principal_id` → `agent_instance_ref` → `sandbox_id` : c'est le mandat d'un AGENT dans une ENCEINTE, jamais le mandat d'un représentant d'une ENTREPRISE — aucun `enterprise_id` dans le contrat. Le code NOMME lui-même celui qui manque : `routers/economy_engine.py:1135-1139` (« representative mandate », raison `durable_enterprise_or_external_attestation_and_representative_mandate_required ») et `routers/accounting_router.py:63` (« Keep public writes closed until their representation mandate exists »). La thèse « n'existe dans AUCUN fichier .py » est littéralement fausse ; la bonne phrase est : le mandat existe, il est câblé, et il n'a pas d'entreprise à représenter. | |
| B5 | ⚑ REFUTÉ — « TOUTES les écritures qui engagent sont fermées » : 6 sur 2448 endpoints · 24 non-GET · 6 refusent (enterprise/register L710, enterprise/subsidy/request L788, project/{id}/fund L917, merchant/register L1128, merchant/pay L1184, merchant/{id}/settle L1238) · 18 restent OUVERTSbackend/app/routers/economy_engine.py — relevé par AST/regex sur le fichier au commit ; prefix `/api/v2/economy-engine` (ligne 37) ; monté main.py:2437 · confirmé dans le codeLe tri. Les 18 ouverts ne sont pas un bloc : (a) `POST /treasury/mint` (L398, admin-only + `_require_treasury_db` → 503 si pas de base) et `/treasury/transfer` (L423, source liée au JWT par `_require_owned_financial_subject`, destinataire résolu en base) sont DB-first et FAIL-CLOSE — correctement BÂTIS, ce sont les écritures les plus engageantes du système et elles tiennent ; (b) `POST /project/create` (L851), `/project/{id}/approve` (L907), `/worker/create` (L975), `/worker/match` (L1077) écrivent dans des dicts RAM purs — `project_generator.py:442-447`, `worker_matching.py:246-251`. C'est là que le fail-open survit, pas chez l'entreprise. | |
| B6 | La voix commerciale de l'entreprise — table durable `enterprise_marketplace_records`1 table, 15 colonnes, 6 index ; 7 endpoints d'écriture, 7 qui refusent (L78, L115, L133, L160, L172, L182, L192) ; 3 lectures ouvertes (L101, L151, L202)backend/app/models/enterprise_marketplace_contract.py:15-45 ; alembic/versions/v82_219_enterprise_marketplace_contract.py:19 ; enregistré alembic/env.py:307 ; routers/enterprise_marketplace_router.py (prefix /api/v2/marketplace), monté main.py:2440 · confirmé dans le codeLes producteurs. La seule table durable du dossier entreprise existe, est migrée et est déclarée à alembic — et aucune des 7 portes qui l'alimenteraient n'est ouverte. « Une surface déclarée sans producteur n'est pas bâtie » : ici la surface est en BASE, ce qui est mieux qu'en RAM, et toujours sans un seul écrivain. | |
| B7 | ⚑ L'AUTRE SORTIE ÉCONOMIQUE (axe Jonathan) — la forge alchimique6 lectures ouvertes (root-coherence, quality, transmutation, history, dashboard…) · 2 mutations, 2 refusées — 0 transmutation possiblebackend/app/routers/alchemy.py:24 (router), :48-59 (_alchemy_mutation_not_active, 503), :338-344 (PUT /root-coherence), :375-381 (POST /transmute) ; monté main.py:2306 · confirmé dans le codeLa mutation. La forge LIT sa cohérence de racine, sa qualité, son historique et son tableau de bord ; les deux seuls gestes qui FORGENT (`PUT /root-coherence`, `POST /transmute`) lèvent `_alchemy_mutation_not_active()` en première instruction. Et comme son code n'est pas dans `CODES_5XX_PUBLIABLES`, l'appelant reçoit lui aussi « Internal server error ». La deuxième sortie économique nommée par Jonathan est donc un tableau de bord sans four. | |
| B8 | Frontend entreprise — chargé, et qui fabrique son propre succèsentreprise.html 1201 lignes ; entreprise-module.js 1007 lignes ; 8 `src=` dans la page, dont governance-init.js ; 0 occurrence de `keli` dans l'ORCHESTRATOR_GUIDE du modulefrontend/js/governance-init.js:54 (GOVERNANCE_PAGES contient 'entreprise') + :78 (SPHERE_MODULE_MAP 'entreprise' → /js/entreprise-module.js) ; frontend/js/entreprise-module.js:150-156 (_syncToBackend) ; :137 (localStorage) ; :142 (_generateId côté client) ; frontend/entreprise.html · confirmé dans le codeDeux maillons. (1) `_syncToBackend` avale l'erreur (`.catch(… console.warn('offline mode'))`) et, si `atomPost` est absent, rend `{success:true, stub:true}` — un succès fabriqué ; combiné à la loi mémoire `atompost-rend-la-reponse-il-ne-leve-pas`, un 503 assaini devient un `console.warn` pendant que l'écran garde la facture. Tout vit en `localStorage`, avec des identifiants engendrés côté navigateur. (2) `ORCHESTRATOR_GUIDE` (ligne 612) n'a pas `keli` : quaternité cardinale à 3 pôles, un des 1114 cas d'arrière décrits dans CLAUDE.md. | |
| B9 | ⚑ REFUTÉ — « registre en RAM » : le registre n'est pas en RAM, il est INATTEIGNABLE1 seul appelant de `.register()` dans les DEUX arbres de backend/ hors tests (`app/` : 1 ; les ~278 .py hors `app/` : 0) — et cet appelant est à la ligne 748, derrière le `raise` de la ligne 727backend/app/services/enterprise_registry.py:245-266 (dict RAM) + backend/app/routers/economy_engine.py:727 (raise) vs :748 (seul appel à .register()) · confirmé dans le codeLe producteur. `enterprise_register` lève `_funding_path_not_active` AVANT toute logique ; les lignes 731-763 (coercition d'enums, `_bind_source_to_caller`, l'appel `.register()`) sont du CODE MORT conservé dans le fichier. Aucun autre chemin ne remplit `_enterprises` : `register_from_lnis` n'est appelé par personne. Un dict RAM qu'aucun code atteignable n'écrit n'est pas « un registre volatil » — c'est un registre vide par construction. La fiche mémoire `entreprise-institution-colonne-de-gestion.md` (2026-08-28) diagnostiquait ici un fail-open H7 fabriquant des fantômes : cette mesure-ci la PÉRIME — il n'y a plus de fantômes, il n'y a plus rien du tout. Et elle cite `enterprise_router.py:73` : ce fichier N'EXISTE PAS au commit (0 résultat `git ls-tree HEAD backend/app/routers/`). | |
| B10 | ⚑ LE DÉFAUT QUE LA PLANCHE MANQUAIT — « refus honnête » : la raison n'atteint jamais l'appelant1 — c'est le nombre de codes 5xx publiables au commit (`privacy_violation_registry_closed`). Les 6 codes de economy_engine, les 3 du marketplace, celui de l'alchimie : 0 inscrit.backend/app/core/refus_publics.py:88-92 (CODES_5XX_PUBLIABLES) + backend/app/main.py:1537-1591 (sanitized_http_exception_handler) + main.py:1475-1482 (_internal_error_content) · confirmé dans le codeL'inscription. Chaque refus lève `HTTPException(503, detail={"code":…, "reason":…})` — propre, nommé, traçable. Puis `sanitized_http_exception_handler` intercepte tout `status_code >= 500`, appelle `code_publiable(detail)`, ne trouve pas le code dans la liste positive, et renvoie `{"status":"internal_error","message":"Internal server error","request_id":…}`. Le `reason` ne part JAMAIS, même pour le code admis. Donc : refus honnête DANS LE CODE ET DANS LE JOURNAL, indiscernable d'une panne AU FIL. Un appelant — frontend, agent, gérant — ne peut pas distinguer « l'organe refuse parce que la durabilité manque » de « le serveur a planté ». Loi mémoire applicable : `gestionnaires-5xx-assainissent-la-raison`. | |
| B11 | Flux INVEST de Mission Center — alimenté par un registre vide1 source déclarée pour le flux INVEST, 0 producteur atteignable en amontbackend/app/services/adapters/invest_adapter.py:37 (`self._service.list_enterprises()`) ; backend/app/services/mission_center_service.py:725 (origin: enterprise_registry) ; routeur mission_center monté main.py:2193 · confirmé dans le codeL'amont. L'adaptateur est réel, correctement typé, documenté jusqu'à son défaut connu (pas de porte `seeking_investment`, cf docs/adr/2026-04-22-wave-b-adapters-source-gaps.md). Il lit un registre que rien ne remplit : le flux INVEST est structurellement VIDE, pas fail-open. Correction de la fiche 2026-08-28 : elle annonçait des opportunités fabriquées à partir de fantômes ; au commit, il n'y a plus d'opportunité du tout. | |
| B12 | ⚑ REFUTÉ — « homonymie tranchée par un ADR » : il n'y a pas d'ADR52 ADR dans docs/adr/ au commit ; 0 portant sur l'homonymie « entreprise » ; 0 contenant « homonym » (git grep sur docs/adr/*)docs/adr/ — les 52 fichiers listés au commit, aucun sur entreprise/institution ; l'arbitrage vit dans memory/entreprise-institution-colonne-de-gestion.md (2026-08-28) + docs/VERDICT-AUDIT-PASSATION-8-HYPOTHESES-2026-08-28.md · confirmé dans le codeL'autorité. La distinction entreprise/institution est une PAROLE de Jonathan (2026-08-28, citée verbatim dans la fiche mémoire) et un verdict d'audit — pas une décision d'architecture scellée. En revanche la séparation EXISTE en code, ailleurs qu'annoncé : `government_campus_service.py:94-124`, les 4 PALACE_BRIDGES posent que la légitimité publique reste du côté gouvernement et l'opération du côté palais. Dire « tranchés par un ADR » promeut une parole au rang B ; la planche doit dire PAROLE + SÉPARATION EN CODE, et nommer l'ADR comme manquant. | |
| B13 | L'encryption comme sortie économique (3ᵉ axe nommé par Jonathan)NON_ETABLInon mesuré dans cette collecte — pistes repérées sans ouverture : backend/app/services/aip_seal_service.py, aip_signing.py, aip_key_registry.py, backend/app/modules/quantum/ (post-quantum) · non confirmé dans le codeLa mesure. Jonathan a nommé l'encryption comme sortie économique à côté de la forge ; je n'ai ouvert ni `aip_seal_service.py`, ni la chaîne post-quantique, ni vérifié quel routeur les expose ni s'il est monté. Ce qu'il faut pour l'établir : (a) le ou les routeurs qui exposent le scellement, et leur ligne dans main.py ; (b) si le sceau est produit ou seulement vérifié ; (c) si une valeur économique (θ, UR, redevance) est attachée à un sceau émis. ⛔ Je ne le devine pas. |
On ne remplace pas le nom canon, on le double : le terme reste l’autorité, la glose est une poignée. Le lexique entier est sur sa propre page.
Matière : PLANCHES-MATIERE-2-INSTITUTIONNEL-2026-10-03.json (sha256 5cc49a404485) — planche de matière « PLANCHE 9 — LES SERVICES INSTITUTIONNELS : l'étoile, ses paroisses, et les deux sorties économiques (version réfutée) » · PLANCHES-MATIERE-2-INSTITUTIONNEL-2026-10-03.json (sha256 5cc49a404485) — planche de matière « L'ENTREPRISE AT·OM — une adresse sur une carte, un registre que rien ne peut remplir, et un refus que le demandeur ne reçoit jamais ». Générée par scripts/generer-planches-ancrage.py ; la version « avant » (avant le passage du sceptique) que la matière conserve n’est pas dessinée — c’est la version dégradée au doute qui l’est, et les marges portent les dégradations.