Les planches d’ancrage · série II · feuille 1 / 19

Le joint bilatéral

L'architecture bilatérale — le joint interne/externe

Planche 1 · Le joint bilatéral
21 pièces · 6 bâties · 10 partielles · 5 absentes · 0 non établies
Planche 1 — Le joint bilatéral

ouvrir la planche en plein écran → · 21 pièces · 17 traverses · 12 marges

La thèse une ligne, écrite dans la matière

Les deux côtés sont bâtis et chacun nomme l'autre ; les trois traverses qui devaient les joindre ne tiennent pas — l'une n'a aucun appelant, l'une a son écrivain sans importateur, et la troisième n'existe que dans l'arbre de travail, non commitée, branchée sur le mauvais axe.

Les marges 12 arbitrages ouverts, entiers
  • ⚑ DÉGRADATION PRINCIPALE — `salle_machines_connector.py` annoncé BÂTI est PARTIEL. Au COMMIT, le connecteur n'a AUCUN joint : `git show HEAD:backend/app/services/babel/salle_machines_connector.py | grep -c 'declare_joint\|portee'` rend 0. Les 7 lignes qui en font « l'orchestrateur du joint » ne sont pas commitées. Et l'appel qui l'atteint (HEAD measure_cascade.py:608) est dans un `try: ... except Exception: pass` étiqueté « never break cascade » : l'orchestrateur peut tomber sans que rien ne le dise.
  • ⚑ DEUXIÈME DÉGRADATION — `person_position_bindings` annoncé BÂTI (« le dossier à deux faces, EN BASE ») est PARTIEL. La DDL existe (v82_291:24) et le code l'écrit et la relit ; mais AUCUNE base n'a été interrogée par cette collecte, et la seule révision de production nommée dans le dépôt est `v82_260_atom_positions` (CLAUDE.md, 2026-08-08) — 31 révisions AVANT v82_291. Dire « en base » sans nommer la base interrogée est exactement ce que la loi d'Ibn Khaldūn interdit. Pour qu'une planche écrive BÂTI ici, il faut une ligne : `SELECT version_num FROM alembic_version` sur `compose-atom-db-1/atom_db`.
  • ⚑ LE JOINT NEUF EST PLUS FRAGILE QUE DIT — il ne manque pas seulement un commit : il manque DEUX noms au commit. `declare_joint` ABSENT de HEAD:cube_venus.py, et `VALID_PORTEES` ABSENT de HEAD:event_bus.py (+14 lignes non commitées). Le joint neuf dépend d'une constante qui n'existe pas davantage. Quatre fichiers non commités le portent : event_bus.py, cube_venus.py, salle_machines_connector.py, measure_cascade.py.
  • ⚑ CORRECTION DANS L'AUTRE SENS — `/ws/resonance` : « aucune entrée permanente » est FAUX. Le gestionnaire traite 5 types entrants au commit (ping, situer, subscribe, unsubscribe, geo_coherence) et son client permanent `atom-realtime-client.js` est listé dans LES DEUX tableaux de HEAD:governance-init.js (:254, :1101). Mieux : c'est par cette entrée que passe la SEULE lecture vivante du drapeau de frontière (main.py:3375 → geo_coherence_service.py:98). Une planche qui dessinait cette traverse en pointillé l'aurait sous-estimée.
  • ⚑ CORRECTION D'ÉTAT — `inner_world / outer_world` n'est pas NON ÉTABLI : c'est ÉTABLI à zéro. 0 occurrence dans tout backend/**.py (les deux arbres) et 0 dans frontend/js/**.js. « NON ÉTABLI » serait un aveu d'ignorance là où j'ai une mesure. La leçon pour la planche : le vocabulaire de la thèse est absent, mais la FONCTION existe sous quatre autres noms — c'est un problème de NOM, pas d'organe. Ne pas dessiner un trou là où il y a une synonymie.
  • Chiffres que j'ai re-mesurés moi-même et qui tiennent : 5216 entités de l'épine (= 1 civ:atom + 217 pays + 3567 subdivisions + 1431 villes, recalculé sur data/countries/) ; `exposition_externe` = 61 occurrences dans 20 fichiers de backend/app/ mais 2 lignes seulement le comparent ; `commu:atom` = 0 occurrence.
  • Chiffres de l'agent que j'ai confirmés sans correction : `amark_face_authoritative` 0 appelant de production (16 appels, tous dans un seul banc) ; `PassageDecisionAuthority.adecider` 0 appelant de production ; `place_projection_binding_authority` 0 IMPORTATEUR (plus fort que « 0 appelant ») ; black-box-recorder.js et village-map-generator.js 0 entrée de chargement. Dans tous les cas LES DEUX arbres ont été fouillés : backend/app/ et les 29 racines hors app/ nommées une à une.
  • ARBITRAGE OUVERT POUR JONATHAN — `POST /ancrer` est BÂTI et atteignable, mais il rend **200 avec `persiste: false`** quand la base est absente (position_registry.py:113-114 `return {"enregistre": False, "raison": "no_db_position_refusee"}` → trinity_geo_router.py:275-277). Un ancrage ENGAGE (c'est une appartenance), donc la règle du dépôt dit : en base, ou l'opération échoue. Le dépôt a choisi l'honnêteté nommée plutôt que le fail-close. À trancher : la planche doit-elle peindre `/ancrer` en BÂTI (la route tient et dit la vérité) ou en PARTIEL (un 200 qui n'a rien écrit) ? J'ai gardé BÂTI parce que l'aval le lit — atom-ancrage.js:150-157 répercute `persiste` — mais c'est le seul endroit où j'ai résisté à la dégradation.
  • PIÈGE DE DESSIN — `atom-ancrage.js` publie le topic `ancrage.pose` (:157) même quand `persiste === false`. Le champ dit la vérité, le NOM du topic non. Un abonné qui compte les `ancrage.pose` compterait des ancrages non gardés. À ne pas dessiner comme une flèche pleine.
  • PIÈGE DE DESSIN — les 5215 lieux pendent d'une racine de portée `civ`, sans palier `commu`. Si la planche montre trois portées emboîtées (indiv ⊂ commu ⊂ civ), l'épine mesurée la contredit : elle est PLATE, deux niveaux, 795 parents intermédiaires au plus 3 sauts selon les inventaires — mais aucun nœud `commu:atom` au sommet du palier communautaire. Le joint communautaire n'a pas de côté DEDANS.
  • PIÈGE DE DESSIN — trois organes différents s'appellent « le joint » et travaillent sur TROIS axes distincts : PositionFace (physical↔numerical, l'axe bilatéral), VALID_PORTEES (indiv/commu/civ, l'axe des portées), et exposition_externe (dedans/dehors, l'axe de frontière). Les peindre du même trait reproduirait exactement la confusion que la planche doit dissiper. Le seul organe qui exige l'axe BILATÉRAL est passage_decision.py — et il n'a aucune entrée.
  • DÉCISION QUI ATTEND — `cosmic_circuit`, `FractalClockService` et les autres attaches de démarrage sont toutes dans des `try/except Exception: ... logger.warning("non-fatal")` (main.py:1019-1030 pour les deux que j'ai lues). Un circuit qui ne s'attache pas laisse un serveur « sain ». Faut-il que la planche marque ces attaches d'un signe particulier — bâti mais révocable au silence ?
Les blancs déclarés ce que la mesure n’a pas pu voir

Ce que cette collecte N'A PAS pu voir. (1) AUCUNE BASE INTERROGÉE : zéro requête sur `compose-atom-db-1/atom_db` (138.197.132.63) ni ailleurs. Donc je ne sais pas si v82_291 est appliquée en production, ni combien de lignes portent `person_position_bindings`, ni si `atom_positions` est encore vide, ni si `scope_membership` contient réellement les 5216 nœuds de l'épine. Le 5216 que je rends est un compte de FICHIERS (data/countries/), recalculé par moi — pas un compte de base. (2) AUCUN SERVEUR SONDÉ : aucune route n'a été appelée. « Monté dans main.py » n'est pas « répond 200 » — `register_router` avale les ImportError, donc un routeur listé peut être absent à l'exécution ; je n'ai pas lancé le serveur pour le vérifier. (3) AUCUN BANC LANCÉ : je n'ai exécuté aucun test. Quand je dis « testé », je dis « un fichier de test existe et le nomme », pas « il passe ». (4) LE DEUXIÈME ARBRE, FOUILLÉ PAR NOMS CHOISIS : j'ai cherché `amark_face_authoritative`, `adecider`, `PassageDecisionAuthority`, `passage_decision`, `place_projection_binding`, `world_blueprint_position`, `inner_world`, `outer_world` dans les 29 racines hors `backend/app/`, et je les ai nommées une à une. Je n'ai PAS inventorié ce que ces 29 racines contiennent par ailleurs : un porteur de face pourrait y vivre sous un nom que je n'ai pas deviné. (5) LE FRONTEND PAR CHARGEMENT, PAS PAR EXÉCUTION : j'ai vérifié la présence dans les deux tableaux de `governance-init.js` et les balises `<script>` des pages. Je n'ai pas ouvert un navigateur : un module listé peut échouer à l'initialisation. Et je n'ai lu que `governance-init.js` et `onboarding.html` ; les ~120 autres pages HTML pourraient charger directement un module que je déclare ABSENT — je n'ai grepé que les noms de fichier des deux modules de l'Arche. (6) `exposition_externe` : les 61 occurrences sont comptées sur `backend/app/` seulement, et mes « 2 gardes » ne retiennent que les comparaisons à la constante `EXPOSITION_EXTERNE` ; une garde écrite autrement (comparaison à un littéral, truthiness) m'échapperait. (7) LES FICHES DE MÉMOIRE : aucune n'a servi de source à un chiffre rendu ici. Les seuls nombres que j'avance viennent du dépôt, et le 5216 a été recalculé par exécution.

Les traverses 17 relations, de source à source
atom-ancrage.js — le seul appelant frontend de /ancrer, et il est honnête
appelle
→POST /api/v2/trinity-geo/ancrer — l'ancrage du corps sur « terre » (côté DEHORS du joint individuel)frontend/js/atom-ancrage.js:48 + :130 (atomPost) ; déclenché par frontend/onboarding.html:1144-1146
POST /api/v2/trinity-geo/ancrer — l'ancrage du corps sur « terre » (côté DEHORS du joint individuel)
alimente
→person_position_bindings — le dossier à deux faces, en basetrinity_geo_router.py:263 appelle enregistrer_ancrage → position_registry.py:87, qui écrit atom_positions. Aucune ligne de trinity_geo_router.py ne mentionne person_position_bindings ni PositionFace : les deux organes ne se touchent pas.
amark_face_authoritative — la seule porte de promotion d'une face
alimente
→person_position_bindings — le dossier à deux faces, en baseperson_position_membership_authority.py:889 → :458 (INSERT) / :505 (UPDATE). Le trait existe en code ; il n'est jamais emprunté : 0 appelant de production des deux arbres.
La face NUMÉRIQUE — refusée trois fois, dont une par le code de la porte elle-même
traverse
→amark_face_authoritative — la seule porte de promotion d'une faceperson_position_membership_authority.py:896 — la porte refuse NUMERICAL par 409 `numerical_position_authority_absent`. Le trait est fermé à la source.
L'épine des lieux — 5216 entités (côté DEHORS du joint communautaire)
contient
→commu:atom — la racine communautaire (côté DEDANS du joint communautaire)country_spine_importer.py:64 `add(CIV_ROOT, "civ", None, ...)` — la racine est civ:atom. Mesure refaite : 5215 nœuds commu, aucun nommé commu:atom. Les 5215 pendent directement d'une racine civ.
PlaceProjectionBindingAuthority.abind — l'écrivain du joint civilisationnel
autorise
→L'épine des lieux — 5216 entités (côté DEHORS du joint communautaire)place_projection_binding_authority.py:218 ; 0 importateur du module dans les deux arbres. Le trait n'est câblé nulle part.
measure_cascade (Babel)
appelle
→salle_machines_connector.py — l'orchestrateur du jointgit show HEAD:backend/app/services/babel/measure_cascade.py:608-609 — l'appel existe au commit, mais sous `try: ... except Exception: pass` : tout échec de l'orchestrateur est invisible.
salle_machines_connector.py — l'orchestrateur du joint
appelle
→cube_venus.py — la barre transversale ANKH : le joint est NOMMÉ dans sa docstring, et nulle part dans le code commitésalle_machines_connector.py:191 `venus.declare_joint(portee)` — non commité, et portee y arrive toujours None (measure_cascade: `getattr(result, 'portee', None)`, commentaire du code : « CascadeResult ne produit pas encore de portée »).
declare_joint + VALID_PORTEES — un joint neuf, non commité, et il passe par le mauvais axe
traverse
→PositionFace {physical, numerical} — l'énum de l'axe bilatéralcube_venus.py:295 importe VALID_PORTEES depuis app.services.event_bus — jamais PositionFace. Le joint neuf ne touche pas l'axe bilatéral.
passage_decision.py — le SEUL organe du dépôt qui EXIGE une face, et personne n'y entre
autorise
→PositionFace {physical, numerical} — l'énum de l'axe bilatéralpassage_decision.py:66 (import), :330, :346-347 (refus de type), :463/:468 (les deux faces du contrat), :506-507. Le trait entre l'organe et l'énum est réel et typé strictement (`type(x) is not PositionFace`).
passage_decision.py — le SEUL organe du dépôt qui EXIGE une face, et personne n'y entre
traverse
→backend/app/main.py (la surface atteignable)0 routeur ne construit une DemandePassage ; `adecider` (:1161) et `construire_autorite_par_defaut` (:1296) ont 0 appelant de production dans les deux arbres.
/ws/resonance — la sortie vers les navigateurs, et elle a bien une entrée
traverse
→exposition_externe — le drapeau de frontière : partout déclaré, deux fois luHEAD main.py :3128+71 (`type == "geo_coherence"`) → main.py:3375 `get_geo_coherence_service().ingest(...)` → geo_coherence_service.py:98, la garde `is not EXPOSITION_EXTERNE`. C'est la seule traverse vivante mesurée entre le dehors (navigateur) et une garde de frontière.
atom-realtime-client.js
appelle
→/ws/resonance — la sortie vers les navigateurs, et elle a bien une entréegit show HEAD:frontend/js/governance-init.js:254 et :1101 (chargé dans LES DEUX tableaux) ; frontend/js/atom-realtime-client.js:30 construit l'URL wss://…/ws/resonance
cosmic_circuit.py — le circuit α↔Ω, branché au bus et aveugle aux faces
traverse
→exposition_externe — le drapeau de frontière : partout déclaré, deux fois luHEAD main.py:1023-1024 attache le circuit au bus ; cosmic_circuit.py:224 compare `circulation.get("exposition_externe") is EXPOSITION_EXTERNE`
g4_emission_guard — le garde d'émission, bâti et appelé, sur l'axe monétaire
autorise
→PositionFace {physical, numerical} — l'énum de l'axe bilatéral0 occurrence de PositionFace dans backend/app/services/babel/g4_emission_guard.py. Le seul garde d'émission réellement appelé du dépôt ne connaît pas l'axe bilatéral : il garde la monnaie, pas la frontière.
external_proxies_router.py — le sas sortant, monté et conditionnel
traverse
→exposition_externe — le drapeau de frontière : partout déclaré, deux fois lu0 occurrence d'`exposition_externe` dans backend/app/routers/external_proxies_router.py. Le sas qui SORT vraiment ne consulte pas le drapeau de frontière ; ses gardes sont les clés d'environnement (:696-1001).
black-box-recorder.js — le coffre qui garde (la moitié DEDANS de la figure de l'Arche)
alimente
→village-map-generator.js / le QG-Djed — le couvercle qui publie (la moitié DEHORS)aucun des deux n'est listé dans frontend/js/governance-init.js ; les deux ne cohabitent que dans frontend/archives/orphan-pages/keli-dashboard.html. Les deux moitiés de la figure sont sur le disque et aucune n'est chargée.
La nomenclature 21 pièces, chacune avec sa source
1PositionFace {physical, numerical} — l'énum de l'axe bilatéral2 valeurs ; 11 déclarations de champ `face: PositionFace` dans le même fichier ; 1 CHECK en base déclaré (v82_291:160-162) ; 1 seul autre module de production l'importe : passage_decision.py:66backend/app/services/person_position_membership_authority.py:46-48 (présent au commit 8addf1c94) · confirmé dans le code
2POST /api/v2/trinity-geo/ancrer — l'ancrage du corps sur « terre » (côté DEHORS du joint individuel)8 routes dans le fichier (/locate :148, /ancrer :204, /correspondances/{identite} :285, /bascule :350, /mondes :357, /health :378) ; world="terre" et scope="indiv" sont écrits en dur (:255-256)backend/app/routers/trinity_geo_router.py:204 ; monté au commit : git show HEAD:backend/app/main.py → ligne 2303 `register_router("app.routers.trinity_geo_router", "", ["Trinity Geo"], "trinity_geo")` · confirmé dans le code
3atom-ancrage.js — le seul appelant frontend de /ancrer, et il est honnête1 seul appelant HTTP de /trinity-geo/ancrer dans frontend/ (les 4 autres occurrences sont : un commentaire device-master.js:239, 2 tests, et le déclencheur UI onboarding.html:1144) ; il lit `persiste` et le répercute (:150-157)frontend/js/atom-ancrage.js:48 (ROUTE) ; listé au commit dans LES DEUX tableaux de chargement : git show HEAD:frontend/js/governance-init.js → :482 et :1169 ; chargé aussi en direct par frontend/onboarding.html:34 (cette page ne charge PAS governance-init.js, dit son propre commentaire :33) · confirmé dans le code
4L'épine des lieux — 5216 entités (côté DEHORS du joint communautaire)5216 — RE-MESURÉ par moi en exécutant la même lecture sur data/countries/ : 1 racine (civ:atom) + 217 pays (profiles.json) + 3567 subdivisions (admin_divisions.json) + 1431 villes (major_cities.json) = 5216 ; portées : commu 5215, civ 1backend/app/services/country_spine_importer.py:45 (`extraire_epine`, fonction pure) ; amorcée au commit : git show HEAD:backend/app/main.py → `_amorcer_epine_lieu` défini :1090, `extraire_epine()` :1100, `amorcer_epine_lieu(db=...)` :1122, lancé par `asyncio.create_task` :1195 ; exposé par /health :2642 · confirmé dans le code
5/ws/resonance — la sortie vers les navigateurs, et elle a bien une entréeCORRECTION : 5 types de messages ENTRANTS traités au commit — ping, situer, subscribe, unsubscribe, geo_coherence (HEAD main.py, décalages +34/+36/+53/+62/+71 après :3128). Ce n'est pas « aucune entrée permanente » : l'entrée existe, elle est chargée dans les deux tableaux de governance-init.js, et c'est par elle que passe la seule lecture vivante d'exposition_externegit show HEAD:backend/app/main.py → :3128 `@app.websocket("/ws/resonance")` ; relais poussé vers elle à :1234 ; client permanent chargé au commit : git show HEAD:frontend/js/governance-init.js → :254 et :1101 `/js/atom-realtime-client.js` (qui s'y connecte, atom-realtime-client.js:30) ; repli de kernel-bridge.js:67 · confirmé dans le code
6g4_emission_guard — le garde d'émission, bâti et appelé, sur l'axe monétaire11 fonctions publiques (compute_theta :55, compute_allowance :66, rate_limit_ok :86, reset_rate_limit_state :95, grants_au_ledger :134, reserve_emission_in_transaction :190, record_committed_grant :279, emission_allowance :284, …) ; governed_mint est lui-même appelé par 4 consommateurs (babel_fractal_treasury_consumer:593, babel_temple_treasury_consumer:291, forge_energy_consumer:407, mission_reward_consumer:103) ; 0 occurrence de PositionFacebackend/app/services/babel/g4_emission_guard.py ; appelé au commit depuis git show HEAD:backend/app/services/babel/governed_mint.py:447 et git show HEAD:backend/app/routers/babel/emission_state_router.py:282 ; routeur monté au commit main.py:1988 · confirmé dans le code
7person_position_bindings — le dossier à deux faces, en baserevision = v82_291_person_position_membership_authority, down_revision = v82_290_enclosure_mandate_preparationsbackend/alembic/versions/v82_291_person_position_membership_authority.py:24 (CREATE TABLE), :97 index, :257 et :324 déclencheurs ; écritures ppma.py:458 (INSERT), :505 (UPDATE), lecture :684 (SELECT) · confirmé dans le codeDÉGRADÉ depuis BÂTI : la table est déclarée, écrite et relue en code, mais son existence EN PRODUCTION n'est pas établie par cette collecte. La seule révision de production nommée est `v82_260_atom_positions` (CLAUDE.md, mesure du 2026-08-08), antérieure de 31 révisions à v82_291. Aucune base n'a été interrogée ici. Le maillon manquant est la preuve d'application de la migration.
8amark_face_authoritative — la seule porte de promotion d'une face16 appels mesurés, TOUS dans backend/tests/unit/test_person_position_membership_authority_g1.py. 0 appelant de production — les DEUX arbres fouillés : backend/app/ et les 29 racines hors app/ (agents, audit, causal_engine, core, core_engines, deploy, education, enterprise, entertainment, feedback, frontiers, governance, industrialisation, library, middleware, models, modules, schemas, scholar, scripts, security, services, slot_fill, systems, verticals, workspace_integration, world_engine, xr_pack, xr_ui)backend/app/services/person_position_membership_authority.py:889 · confirmé dans le codel'appelant. La fonction est complète et testée ; rien dans le dépôt ne l'invoque hors du banc.
9PlaceProjectionBindingAuthority.abind — l'écrivain du joint civilisationnel0 importateur. Le nom de module `place_projection_binding_authority` n'apparaît dans AUCUN fichier de backend/app/ hors le sien, et dans aucune des 29 racines du second arbre. Seule référence du dépôt : backend/tests/services/test_place_projection_binding_authority.pybackend/app/services/place_projection_binding_authority.py:214 (classe), :218 (abind) — présent au commit · confirmé dans le codel'importateur. Ce n'est pas seulement « l'écrivain est absent » : personne ne charge même le module.
10cosmic_circuit.py — le circuit α↔Ω, branché au bus et aveugle aux faces5 occurrences de `exposition_externe` dans le fichier, dont 1 seule est une garde (:224) ; 0 occurrence de PositionFacebackend/app/services/cosmic_circuit.py ; attaché au commit : git show HEAD:backend/app/main.py → :1023-1024 `attach_to_bus()` ; exposé par backend/app/routers/qg_fractalization_router.py:1350 (routeur monté main.py:2240) · confirmé dans le codela face. Le circuit tourne et lit le drapeau de frontière, mais ne voit jamais PositionFace. Et son attache est dans un try/except non-fatal (main.py:1029-1030) : un échec au démarrage est un avertissement journalisé, pas un refus.
11cube_venus.py — la barre transversale ANKH : le joint est NOMMÉ dans sa docstring, et nulle part dans le code commité0 occurrence de `declare_joint` dans git show HEAD:backend/app/services/babel/cube_venus.py ; le fichier est modifié non commité (+13 lignes) ; la docstring annonce « API publique (6 fonctions) » et declare_joint serait la 7ᵉ, non annoncéebackend/app/services/babel/cube_venus.py:3-4 — « entre Métatron (externe) et Mercure (interne) dans l'anatomie ANKH ☥ » ; `declare_joint` à :293 dans l'ARBRE DE TRAVAIL seulement · confirmé dans le codele joint lui-même au commit. Et dans l'arbre de travail il travaille sur VALID_PORTEES (indiv/commu/civ), pas sur PositionFace : l'axe des PORTÉES, pas celui des FACES.
12salle_machines_connector.py — l'orchestrateur du jointDÉGRADÉ depuis BÂTI. Au COMMIT : 0 occurrence de `portee` et 0 de `declare_joint` dans le connecteur — il n'orchestre aucun joint. Les 7 lignes qui le font sont non commitées. Et l'appel depuis measure_cascade est enfermé dans `try: ... except Exception: pass` (« never break cascade »)backend/app/services/babel/salle_machines_connector.py (333 lignes au commit, 340 dans l'arbre) ; appelé au commit : git show HEAD:backend/app/services/babel/measure_cascade.py → :608-609 · confirmé dans le codedeux maillons. (1) Au commit le connecteur ne porte pas de joint du tout. (2) Dans l'arbre de travail il est nourri par `portee=getattr(result, 'portee', None)` — et le commentaire du code dit lui-même « CascadeResult ne produit pas encore de portée : None reste None », donc declare_joint reçoit toujours None et rend toujours joint=None.
13passage_decision.py — le SEUL organe du dépôt qui EXIGE une face, et personne n'y entre0 appelant de production de `adecider` et de `construire_autorite_par_defaut` — les DEUX arbres fouillés (backend/app/ et les 29 racines hors app/). Son aval `passage_outbox.py` : 0 appelant de production aussi (seules références hors tests : la migration v82_294). Les seuls appelants sont 2 bancs : test_passage_decision_p3.py, test_passage_outbox_p4.pybackend/app/services/passage_decision.py:330 (`face: PositionFace`), :346-347 (`raise TypeError("face de position doit etre un PositionFace")`), :463/:468 (source_position_face / target_position_face du contrat), :1096 (PassageDecisionAuthority), :1161 (adecider), :1296 (construire_autorite_par_defaut) · confirmé dans le codela porte d'entrée. Aucune route, aucun service ne construit une DemandePassage. L'exigence de face est réelle et ne s'applique à rien.
14exposition_externe — le drapeau de frontière : partout déclaré, deux fois lu61 occurrences / 20 fichiers / 2 gardes. Les plus denses : stone_decoder/temple_fractal_connector.py 12, stone_decoder/temple_control_center.py 8, qg_fractalization_router.py 8, cosmic_circuit.py 5, coherence/temple_coherence_witness.py 561 occurrences dans 20 fichiers de backend/app/ ; les 2 SEULES lignes qui le comparent : backend/app/services/cosmic_circuit.py:224 et backend/app/services/geo_coherence_service.py:98 · confirmé dans le codela lecture. CORRECTION dans l'autre sens : les 2 gardes ne sont pas mortes — geo_coherence_service est atteint depuis /ws/resonance (main.py:3375) et depuis canon_coherence_router.py:147/291. Le drapeau garde vraiment, mais 2 portes sur 61 mentions.
15external_proxies_router.py — le sas sortant, monté et conditionnelles sorties dépendent de clés d'environnement lues à :696-698, :727, :762, :801-803, :831, :865, :966, :996-1001 ; 2 refus 503 déclarés (:51, :455) ; 1 lecture générique de variable à :144backend/app/routers/external_proxies_router.py (1019 lignes au commit) ; monté au commit : git show HEAD:backend/app/main.py → :2444 · confirmé dans le codeles clés. Le sas existe et est atteignable ; sans variable d'environnement il refuse (503). Le canal sortant est donc réel et conditionnel, pas bâti au sens d'un flux qui coule.
16declare_joint + VALID_PORTEES — un joint neuf, non commité, et il passe par le mauvais axe0 occurrence de `declare_joint` ET 0 de `VALID_PORTEES` dans le COMMIT (vérifié par git show HEAD sur cube_venus.py, salle_machines_connector.py et event_bus.py). Le joint dépend donc d'un nom qui n'existe pas non plus au commit. Il rend `f"{portee}↔matrix"` — un joint portée↔matrix, jamais face↔face4 fichiers modifiés NON COMMITÉS : backend/app/services/event_bus.py:299 (`VALID_PORTEES = frozenset({"indiv","commu","civ"})`, +14 lignes), babel/cube_venus.py:293 (declare_joint, +13), babel/salle_machines_connector.py:191 (appel, +7), babel/measure_cascade.py (+2) · confirmé dans le codedeux maillons. (1) Le commit : rien de tout cela n'y est. (2) L'axe : declare_joint valide contre VALID_PORTEES (indiv/commu/civ) et non contre PositionFace (physical/numerical) — il nomme un joint sur l'axe des portées, pas sur l'axe bilatéral que la planche doit montrer.
17La face NUMÉRIQUE — refusée trois fois, dont une par le code de la porte elle-même0 écrivain de production d'une face NUMERICAL ; 2 refus explicites en code ; les seules occurrences de PositionFace.NUMERICAL hors ces refus sont 2 lignes de test (test_passage_decision_p3.py:1032-1033)backend/app/services/person_position_membership_authority.py:896 et :1473 — `if proof.face is PositionFace.NUMERICAL: raise self._error("numerical_position_authority_absent", 409, ...)` ; et trinity_geo_router.py:255 écrit world="terre" en dur · confirmé dans le code
18commu:atom — la racine communautaire (côté DEDANS du joint communautaire)0 occurrence de `commu:atom` ; l'épine que j'ai recalculée produit 1 nœud de portée `civ` et 5215 de portée `commu`, et aucun d'eux ne s'appelle `commu:atom`mesure négative : 0 occurrence de la chaîne `commu:atom` dans backend/app/**.py et frontend/js/**.js. La seule racine déclarée est `CIV_ROOT = "civ:atom"`, en deux endroits : backend/app/services/country_spine_importer.py:27 et person_position_membership_authority.py:40 · confirmé dans le code
19black-box-recorder.js — le coffre qui garde (la moitié DEDANS de la figure de l'Arche)0 des 2 tableaux de chargement de governance-init.js le mentionne ; 1 page le référence, et elle est sous archives/orphan-pages/frontend/js/black-box-recorder.js existe sur disque ; 0 entrée dans frontend/js/governance-init.js (ni au commit, ni dans l'arbre) ; seule référence HTML du dépôt : frontend/archives/orphan-pages/keli-dashboard.html · confirmé dans le code
20village-map-generator.js / le QG-Djed — le couvercle qui publie (la moitié DEHORS)même mesure que le coffre : 0 entrée de chargement, 1 page orpheline archivéefrontend/js/village-map-generator.js existe sur disque ; 0 entrée dans frontend/js/governance-init.js ; seule référence HTML : frontend/archives/orphan-pages/keli-dashboard.html · confirmé dans le code
21inner_world / outer_world — le vocabulaire de la thèse n'a aucun porteur, et c'est MESURÉ0 / 0. CORRECTION d'état : ce n'était pas NON ÉTABLI — c'est établi, et ça vaut zéro. La FONCTION, elle, est bien portée, sous quatre autres noms : exposition_externe (le drapeau), external_proxies_router (le sas), PositionFace.PHYSICAL/NUMERICAL (les deux faces), et « Métatron (externe) / Mercure (interne) » dans cube_venus.py:3-4mesure négative exhaustive : 0 occurrence de `inner_world` et de `outer_world` dans backend/**.py (les deux arbres) et 0 dans frontend/js/**.js · confirmé dans le code
Le lexique de cette planche 21 termes à deux registres · 5 avec un jumeau

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.

portée (axe POSITION — ind / com / civ)Jusqu'où une chose compte — pour moi seul, pour un groupe, ou pour tous — et c'est l'endroit où l'on agit qui le décide, pas une case à cocher.trinity_scope (la portée-LENTILLE) — La mesure de combien une même chose pèse à la fois pour une personne, pour son groupe et pour tous — trois nombres ensemble, pas un choix…
scope / tree_scopeLe champ qui enregistre la portée d'une chose, et qui lui donne un contenant différent dans chacun des trois classements empilés.
Face (d'une portée)Le nom sous lequel une même portée se présente selon qui la regarde : la base, l'écran, l'agent, ou le livre du lecteur.
identiteLe nom lisible d'une chose, laissé en clair exprès, pour qu'on retrouve la même chose dans un autre espace en comparant simplement ce nom.
agent (type de nœud)Le genre de place qu'occupe un agent qui agit au nom de quelqu'un, avec l'endroit auquel il est rattaché.
civ:atom (CIV_SINGLETON)Le nom du centre unique auquel tout finit par se rattacher.
scope_membershipLa table qui dit qui est contenu par qui, avec un contenant différent par portée, et c'est elle qui tranche quand l'adresse dit autre chose.
atom_positionsLa table où survit l'adresse d'une chose, avec son espace et sa portée dans deux colonnes séparées, et la mention de si c'est un corps posé ou un visiteur.
face (enum Face)Elle dit sous quel angle on nomme une sphère : le même objet reçoit un nom différent selon l'angle choisi.
canalC'est par quel moyen un message voyage : le réseau interne, le web, le courriel, le SMS, l'écran, et onze autres.
bus (valeur de canal)C'est la valeur qui dit : ce message ne sort pas de la machine, il passe d'un module à l'autre dans le même programme.bus (l'organe de distribution) — C'est la pièce de code qui reçoit un message et le remet à tous ceux qui s'y sont abonnés.
bus (l'organe de distribution)C'est la pièce de code qui reçoit un message et le remet à tous ceux qui s'y sont abonnés.canal — C'est par quel moyen un message voyage : le réseau interne, le web, le courriel, le SMS, l'écran, et onze autres.bus (valeur de canal) — C'est la valeur qui dit : ce message ne sort pas de la machine, il passe d'un module à l'autre dans le même programme.
topicC'est le nom exact d'un message, celui qui décide qui le recevra ; il s'écrit en trois morceaux séparés par des points.
portée (VALID_PORTEES : indiv | commu | civ)C'est la taille de l'espace qu'un message concerne : une personne, un groupe, ou tout le monde.
fail-closeQuand l'outil ne peut pas faire le travail pour de vrai, il refuse et dit pourquoi, au lieu de repondre « c'est fait ».
porteUn passage qu'on traverse vraiment : il faut une permission pour le franchir, et il laisse une trace de ce qui est passe.porte (Porte de la Connaissance, knowledge_gate/porte.py) — Elle decide combien d'un document on montre a quelqu'un — de rien du tout jusqu'au texte complet — en six crans, et par defaut elle ne…
porte (Porte de la Connaissance, knowledge_gate/porte.py)Elle decide combien d'un document on montre a quelqu'un — de rien du tout jusqu'au texte complet — en six crans, et par defaut elle ne montre rien.porte — Un passage qu'on traverse vraiment : il faut une permission pour le franchir, et il laisse une trace de ce qui est passe.fenetre — Une vue sur ce qui se passe ailleurs : on voit, on ne prend rien, et rien ne change de main.
gardeUn controle pose sur le chemin d'une action, qui la laisse passer ou la refuse.
Djedregistre spirituelLe mât du village : on le voit de loin, il publie l'état du groupe, et il ne promet jamais plus que ce que les machines du lieu peuvent tenir.
ANKHregistre spirituelUne boucle qui revient à son point de départ : le système se nourrit de ce qu'il a près de lui et referme son cycle au lieu de tirer une ligne droite.
Babel (Décodeur de Babel)L'outil qui mesure comment les mots ont été retournés, et qui refuse de répondre plutôt que de deviner quand sa base manque.

Matière : PLANCHES-MATIERE-1-TECHNIQUE-2026-10-03.json (sha256 b29a3dc78614) — planche de matière « L'architecture bilatérale — le joint interne/externe ». 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.