Portes et fenêtres — quatre échelles, et qui frappe vraiment
ouvrir la planche en plein écran → · 30 pièces · 25 traverses · 9 marges
Le mécanisme complet — porte|fenêtre, les deux sens jugés séparément, le reçu durable — existe entier dans UN organe que rien n'expose ; aux quatre échelles, les FENÊTRES de contrôle sont câblées (6 sites d'appel) tandis que les PORTES D'OCTROI d'appartenance sont à zéro appelant sur les sept arbres — mais deux portes que l'on croyait mortes respirent (l'ancrage, la membrane des 3 Mondes) et trois fenêtres que l'on croyait bâties n'ont aucun appelant.
Ce que cette collecte N'A PAS pu voir. (1) LA PRODUCTION : tout est mesuré sur le commit 8addf1c94 de la branche integration/fondateur-p0, en lecture seule, sans toucher au VPS 138.197.132.63 ni à la base atom_db. Je ne sais donc PAS combien de lignes portent atom_positions, passage_outbox_receipts, community_relation ou membrane_passages en vrai — trinity_geo_router.py:214 affirme « 0 ligne » mais c'est une mesure DATÉE du 2026-07-31 que je n'ai pas refaite. Une porte fail-close bâtie peut n'avoir jamais été franchie. (2) L'ARBRE DE TRAVAIL : 60+ fichiers sont modifiés non commités (dont .github/workflows/ci.yml, backend/app/main.py, backend/app/core/auth.py) ; mes mesures de montage et de CI sont celles du COMMIT, pas de ce qui tourne sous les doigts de Jonathan en ce moment. (3) LES ONZE PORTES D'ADHÉSION une par une : j'ai vérifié que local_steward_router.py:120 lève un 503 inconditionnel ; les dix autres sont comptées, pas auscultées — leur état individuel reste NON ÉTABLI. (4) LES APPELANTS DYNAMIQUES : je cherche des appels écrits en clair. Un appel construit par concaténation d'URL, par table de routage, ou via importlib m'échappe — tous mes « 0 appelant » sont des zéros de grep statique sur sept arbres nommés, pas des zéros d'exécution. (5) LE SECOND ARBRE EN PROFONDEUR : j'ai compté ses 280 fichiers et ses 29 racines, je n'ai pas relu ses imports un par un — les deux autres nombres du cliquet (51 app→2, 10 2→app) ne sont PAS re-mesurés ici, ils demandent l'exécution du script. (6) LES 122 PAGES HTML : j'ai trouvé par recherche ciblée que desktop.html et onboarding.html chargent deux modules clés ; je n'ai pas inventorié les balises <script> des 120 autres pages, donc d'autres organes que je n'ai pas examinés pourraient être chargés par une page que je n'ai pas ouverte.
ne pas dessiner
| frontend/js/membrane-manager.js:201 appelle | → | backend/app/routers/membrane.py:155 (POST /passages)frontend/desktop.html:392 charge le module ; backend/app/main.py:1721 monte le routeur | |
| backend/app/routers/membrane.py:155 alimente | → | table passage durable (MembranePassage)backend/app/routers/membrane.py:156-180 — fail-close 503 sans base | |
| MembranePassage (le reçu) autorise | → | une décision d'autorisationbackend/app/models/v80/spheres.py:547 — 0 lecteur hors routers/membrane.py | |
| frontend/onboarding.html:1146 appelle | → | POST /api/v2/trinity-geo/ancrerfrontend/onboarding.html:34 (script) · frontend/js/atom-ancrage.js:48+130 · backend/app/routers/trinity_geo_router.py:204 | |
| backend/app/routers/trinity_geo_router.py:262 alimente | → | atom_positions (presence=ancrage)backend/app/services/position_registry.py:87 — contrainte uq_atom_positions_ancrage_actif_terre | |
| backend/app/routers/trinity_geo_router.py:167 alimente | → | atom_positions (presence=station)backend/app/services/position_registry.py:77 | |
| la colonne `monde` (42 tables) autorise | → | une décision d'accèsbackend/app/models/v80/canonical_base.py:56 ; seul where() de monde = routers/membrane.py:198-200, filtre de liste | |
| backend/app/routers/local_steward_router.py:148 appelle | → | backend/app/middleware/identity_boundary.py:164 (verify_monde_access)le verdict est écrasé par le 503 inconditionnel de local_steward_router.py:159-162 | |
| backend/app/services/membrane_service.py:190 (membrane C) alimente | → | backend/app/core/conduit_membranes.py:117 (declarer)backend/app/services/membrane_service.py:198 | |
| backend/app/services/babel/fractal_pipeline.py:410 (membrane B) alimente | → | backend/app/core/conduit_membranes.py:117 (declarer)backend/app/services/babel/fractal_pipeline.py:410 | |
| backend/app/core/conduit_membranes.py:251 (publier) alimente | → | les 3 topics membrane.*0 appelant de publier() en production ; 0 abonné aux 3 topics | |
| frontend/js/airway-conduction.js (membrane A) traverse | → | le bus backendbackend/app/routers/event_bus.py:90 — FRONTEND_BRIDGE_ALLOWED_TOPICS = frozenset() | |
| frontend/js/desktop-shell.js:3088 (switchMonde) appelle | → | le serveuraucun appel réseau dans la fonction — et c'est la doctrine : naviguer n'est pas se déplacer | |
| 6 appelants (routeurs + services) appelle | → | avalidate_active_membership (la fenêtre de contrôle)fractal_websocket_router.py:103 · canon_coherence_router.py:173 · fractale_communautaire.py:161 · babel/fractal_pipeline.py:596 · fractal_scope_guard.py:86 · relation_mutuelle_service.py:195 | |
| n'importe quel appelant appelle | → | agrant_membership / amark_face_authoritative / arevoke_contractbackend/app/services/person_position_membership_authority.py:1015 / :889 / :1086 — 0 occurrence hors leur propre def, 7 arbres fouillés, tests exclus | |
| relation_service.add_relation (l'écrivain de la maille) alimente | → | table community_relationbackend/app/services/relation_service.py:78 — 0 appelant de production | |
| projection_scope_context_service.py:36 appelle | → | relation_service (lecture de la maille)backend/app/services/projection_scope_context_service.py:11-36 | |
| backend/app/services/babel/inter_village_bridge.py:285 (register_peer) alimente | → | un registre durable de pairsbackend/app/services/babel/inter_village_bridge.py:267 — `self._peers = {}`, dict de processus | |
| routers/babel/inter_village_router.py:87 et :153 (la fenêtre) appelle | → | le dict RAM des pairsmontée core=True main.py:1688, mais 0 appelant navigateur et rien de durable à lire | |
| PassageDecisionAuthority alimente | → | passage_outbox (le reçu durable)backend/app/services/passage_outbox.py:47+320 — le lien existe en code, et passage_outbox n'a aucun importeur de production | |
| un routeur de main.py appelle | → | PassageDecisionAuthoritybackend/app/services/passage_decision.py — 0 route, 0 composition root ; les ports sont câblés ABSENTS | |
| backend/app/services/relation_service.py:32 appelle | → | hf-atom-tools/atom_canon/primitives/relation_kind.pyimport dans un try/except à repli silencieux — unique pont entre le canon de l'arête et le code | |
| backend/app/routers/knowledge_gate_router.py:19 appelle | → | backend/app/services/knowledge_gate/porte.py (la porte patron)monté backend/app/main.py:1965 | |
| backend/app/services/knowledge_gate/porte.py:206 appelle | → | backend/app/services/membrane_service.py:190 (membrane C)backend/app/services/knowledge_gate/porte.py:24+206 | |
| data/urbanisme/anatomie-lieux-stages-2026-07-15.json (510 portes) alimente | → | un lecteur de codegit grep du nom de fichier sur backend/ frontend/ scripts/ agents/ hf-atom-tools/ = 0 |
| 1 | Les SIX SCÈNES — `quai` (la porte) et `frontstage` (la fenêtre) en énum fermée6 scènes ; refus fail-close en 6 modules de service (instance_passport.py:223, enclosure_birth_membrane_adapters.py:315/2308/3260, enclosure_birth_place_seat_issuer.py:1812, enclosure_place_seat_plan_authority.py:824, enclosure_situated_seat_authority.py:1314/1436, enclosure_team_birth_edge_codec.py:1434) + 4 contraintes CHECK SQL (v82_268:36, v82_281:80, v82_283:63, v82_289:77). Atteignable : routers/enclosure_router.py et enclosure_runtime_commands.py importent la famille.backend/app/core/instance_passport.py:41-43 · confirmé dans le code | |
| 2 | ÉCHELLE 2 — POINTS 0 : la PORTE des 3 Mondes (passage membrane)CHAÎNE COMPLÈTE RE-VÉRIFIÉE : frontend/desktop.html:392 charge /js/membrane-manager.js ; membrane-manager.js:201 fait atomPost('/api/v1/membrane/passages') ; le routeur est monté ; l'écriture est FAIL-CLOSE — 503 `membrane_database_unavailable` si db est None (membrane.py:156-163) et 503 `membrane_persistence_failed` si le commit échoue (:170-180). Auth au niveau du routeur (membrane.py:42).backend/app/routers/membrane.py:155 — monté backend/app/main.py:1721 · confirmé dans le code | |
| 3 | MEMBRANE C (dedans → lecteur) — « ce lecteur l'a-t-il MÉRITÉ ? »8 importeurs de production : coquille_router.py:51 (monté main.py:2342), knowledge_gate/porte.py:24+206, bureau_service.py:145, community_trunk_service.py:293, coquille_service.py:58, mcp_carte_tools.py:70, mcp_live_organs.py:40, mcp_repo_tools.py:64. Vocabulaire natif fermé permeable|gestating|sealed, inconnu ⇒ `absent` (fail-close).backend/app/services/membrane_service.py:190-230 (authorize_axes, _verdict) · confirmé dans le code | |
| 4 | MEMBRANE B (bas → haut) — « cela a-t-il le DROIT de sortir ? »atteinte par 2 routeurs montés : routers/babel/fractal_decode_router.py:60 (main.py:2002) et fractal_websocket_router.py (main.py:2001). Vocabulaire natif allowed|blocked.backend/app/services/babel/fractal_pipeline.py:410 · confirmé dans le code | |
| 5 | ÉCHELLE 3 — LAYERS : la PORTE de l'ancrage (ancrage = le CORPS)⚑ REMONTÉ DE PARTIEL — chaîne complète re-vérifiée : frontend/onboarding.html:34 charge /js/atom-ancrage.js (et governance-init.js:482+1169 aussi) ; onboarding.html:1146 appelle ATOMAncrage.ancrer() ; atom-ancrage.js:48+130 POSTe /api/v2/trinity-geo/ancrer ; routers/trinity_geo_router.py:204 est l'endpoint, :262 appelle enregistrer_ancrage ; monté main.py:2303. Garde d'unicité uq_atom_positions_ancrage_actif_terre (position_registry.py:42), refus nommé `ancrage_actif_deja_present` (:191). L'identité vient du jeton, pas du payload.backend/app/services/position_registry.py:87 (enregistrer_ancrage) · confirmé dans le code | |
| 6 | ÉCHELLE 3 — LAYERS : la FENÊTRE inter-mondes (station = l'AVATAR)la nature de la ligne vient de la FONCTION SERVEUR, jamais du payload (docstring :80-83) ; appelée routers/trinity_geo_router.py:167 (POST /locate), monté main.py:2303 ; appelant navigateur frontend/js/trinity-geo-explorer.js, chargé governance-init.js:483 et :1170 (2 entrées).backend/app/services/position_registry.py:77 (enregistrer → presence=station) · confirmé dans le code | |
| 7 | La LENTILLE — `switchMonde` : naviguer n'est pas se déplacer, et le code le respectechargé frontend/desktop.html:492 ; 3 boutons rendus desktop-shell.js:647-653, câblés :745-747 ; aucun appel réseau dans la fonction — localStorage, publish('desktop.monde.changed'), teinte CSS, _refreshBureauZones. Le transfert est ailleurs (membrane), exactement comme la doctrine l'exige.frontend/js/desktop-shell.js:3088 · confirmé dans le code | |
| 8 | Le pont frontend→bus — une PORTE fermée par construction, et c'est justeFRONTEND_BRIDGE_ALLOWED_TOPICS = frozenset() — 0 topic autorisé ; tenu par backend/tests/unit/test_pont_frontend_portier.py:43 et par une épreuve de forme sur le source dans test_conduit_membranes.py:185. Le commentaire :71-80 dit pourquoi : un topic ouvert pouvait aboutir à une frappe monétaire non plafonnée.backend/app/routers/event_bus.py:90 · confirmé dans le code | |
| 9 | La PORTE PATRON — celle qui, quand elle ne sait pas, devient une fenêtre5 importeurs de production : knowledge_gate_router.py:19 (monté main.py:1965), babel_router.py:47, embeddings.py:22, knowledge.py:26, knowledge_seeds.py:35, plus mcp_principal.py:62. Fail-close à LATENT ; `derive_contract` LIT les critères sur des champs typés, la Porte n'en définit aucun ; importeur UNIQUE de `_raw_store` verrouillé par backend/tests/test_raw_store_single_importer.py:49.backend/app/services/knowledge_gate/porte.py · confirmé dans le code | |
| 10 | PassageDecisionAuthority — le mécanisme ENTIER, en un seul fichier1319 lignes ; 18 refus publics en énum fermée ; 0 route ; 2 importeurs de production — mirror_envelope.py:61 et passage_outbox.py:47 — dont aucun n'est atteint depuis main.py. Règle : git grep au commit 8addf1c94 sur backend/ frontend/ agents/ scripts/ hf-atom-tools/ rosetta-core/, backend/tests/ exclu des appelants.backend/app/services/passage_decision.py:1-1319 · confirmé dans le codeaucun composition root : son propre en-tête déclare que les ports S9, positions, contrats et Covenant sont câblés sur des ports ABSENTS ; et aucun routeur ne monte l'autorité. La chaîne s'arrête avant la première requête. | |
| 11 | ModePassage — le 4ᵉ axe de cardinalité (fenêtre = information | porte = énergie)2 lecteurs seulement : passage_decision.py:910 et mirror_envelope.py:104. 0 routeur, 0 topic de bus, 0 widget. Et mirror_envelope n'a qu'un importeur — mirror_crypto.py:105 — qui n'en prend que DEUX CONSTANTES (PROFIL_RESERVE, REFUS_PROFIL_NON_CONFORME), jamais l'enveloppe.backend/app/services/passage_decision.py:70-74 · confirmé dans le code⚑ DÉGRADÉ DE BATI. L'énum est complète et injoignable : rien ne l'expose. C'est le genre SURFACE, et docs/inventaires/MISSION-CLOUD-LA-SURFACE-DECLAREE-SANS-APPELANT-2026-10-02.md le nomme déjà ainsi (« complet et injoignable — 2 lecteurs, 0 routeur ») — j'ai re-mesuré, c'est exact. | |
| 12 | Le mode gouverne l'EFFET, pas seulement l'étiquette1 site où le mode change le verdict (`if demande.mode is ModePassage.FENETRE and demande.mute`) ; modes_autorises au contrat passage_decision.py:477 ; REFUS_MODE_INTERDIT en vocabulaire fermé.backend/app/services/passage_decision.py:910 · confirmé dans le code⚑ DÉGRADÉ DE BATI. `_evaluer()` est un évaluateur pur jamais atteint depuis une requête HTTP ou WS : l'effet est réel dans le code et inaccessible en service. Un effet que personne ne peut déclencher n'est pas bâti, il est écrit. | |
| 13 | RelationKind — le canon de l'arête, et il ne sait PAS dire le mode8 types au noyau verrouillé + zone d'extension ; 5 axes portés (direction, topologie, lecture_directe/inverse, merit_gated, consenti) ; 0 champ `mode`. UN SEUL importeur de production : backend/app/services/relation_service.py:32 — et il est dans un try/except à repli silencieux (`except Exception: _ARBRE_TYPES = {"abrite"}`).hf-atom-tools/atom_canon/primitives/relation_kind.py:40-110 · confirmé dans le codele quatrième axe (fenêtre|porte) manque ; et le canon n'est relié au code que par un import tolérant à l'échec : si le paquet n'est pas sur le path, le backend continue avec un vocabulaire de UN mot sans rien dire. | |
| 14 | Les PORTS de la spec existent en code — comme texte libre`add_relation` exige une `liaison` non vide (test unit test_relation_service.py:38 le gèle) mais son type est `str` libre, pas une pétale.backend/app/services/relation_service.py:78 · confirmé dans le codele vocabulaire fermé ; et plus grave : `add_relation` a 0 appelant de production sur les sept arbres (seuls backend/tests/unit/test_relation_service.py et test_projection_scope_context_service.py l'appellent). | |
| 15 | Le reçu de la porte des 3 Mondes n'autorise RIEN — personne ne le litMembranePassage : 0 lecteur hors routers/membrane.py (ses propres list/detail) et models/v80/__init__.py:45 (ré-export). Aucune autorisation ne le consulte.backend/app/models/v80/spheres.py:547 · confirmé dans le codele consommateur : la porte écrit un consentement durable que rien ne relit pour décider. Le reçu existe, la flèche retour n'existe pas. | |
| 16 | ÉCHELLE 2bis — la FENÊTRE de la coquillemonté et gardé par membrane_service ; 0 appelant : git grep 'api/v2/coquille|api/v1/coquille' sur frontend/ + agents/ (hors __tests__) = 0.backend/app/routers/coquille_router.py:51 — monté backend/app/main.py:2342 · confirmé dans le codel'appelant navigateur. La fenêtre est percée et personne ne regarde par elle. | |
| 17 | MEMBRANE A (dehors → dedans) — « est-ce assez propre pour ENTRER ? »le module EST chargé (1 entrée de chargement confirmée) ; ses 2 topics ne traversent pas : FRONTEND_BRIDGE_ALLOWED_TOPICS = frozenset() vide (backend/app/routers/event_bus.py:90).frontend/js/airway-conduction.js — chargé frontend/js/governance-init.js:759 · confirmé dans le codedeux maillons, et le premier est VOULU : (1) le portier frontend→bus est vide par construction (interdit I-1), donc A ne peut rien déclarer côté serveur ; (2) A ne transporte pas l'identité du paquet — elle ne pourrait pas nommer son sujet même si le pont existait (conduit_membranes.py:283). | |
| 18 | Le CONDUIT des trois membranes — le reçu déclaré, jamais publié, jamais écouté`declarer()` : 2 appelants (fractal_pipeline.py:410, membrane_service.py:198) — il ne fait qu'ajouter un dict `franchissement` dans la réponse. `publier()` : 0 appelant de production. 0 abonné aux 3 topics ; seul backend/tests/unit/test_conduit_membranes.py:247 les voit passer. Les 3 vocabulaires sont DISJOINTS et le test le gèle.backend/app/core/conduit_membranes.py:251 (publier) · confirmé dans le codel'appel à `publier()` et un abonné. Le conduit traduit un verdict en déclaration lisible, et la déclaration ne quitte jamais la réponse HTTP. | |
| 19 | La colonne `monde` — un axe déclaré sur 42 tables, ZÉRO lecture décisionnelle⚑ CHIFFRE CORRIGÉ — 42 classes ORM la portent, pas 22 : 41 héritent de TraceabilityMixin + Thread (base.py:235). Règle : git grep '^class \w+\(.*TraceabilityMixin' sur backend/app/models. Et 0 lecture décisionnelle : les seuls where() sur un monde portent sur source_monde/target_monde de MembranePassage (routers/membrane.py:198-200) — un filtre de LISTE, deux colonnes différentes.backend/app/models/v80/canonical_base.py:56 (TraceabilityMixin) + backend/app/models/v80/base.py:76 et :235 · confirmé dans le codela lecture. 42 tables étiquetées, indexées, par défaut `mon_monde` — et aucune décision ne consulte l'étiquette. | |
| 20 | `verify_monde_access` — la garde des layers : un appelant, et son verdict est SANS EFFET3 règles (owner|group|public), fallback privé par défaut ; 1 appelant sur les sept arbres.backend/app/middleware/identity_boundary.py:164 — appelant unique backend/app/routers/local_steward_router.py:148 · confirmé dans le codeson verdict est encadré de deux 503 : local_steward_router.py:144 refuse déjà `cell_membership_authority_unassigned` avant elle pour notre_monde, et :159-162 lève un 503 INCONDITIONNEL juste après son retour. La garde ne peut rien décider — ni ouvrir, ni fermer. | |
| 21 | ÉCHELLE 4 — SYSTÈMES : la PORTE inter-villages (fédération sans centre)8 endpoints ; MAX_PEERS borné ; refus nommés (village_id vide, déjà enregistré, plafond).backend/app/services/babel/inter_village_bridge.py:285 (register_peer) — routers/babel/inter_village_router.py:58, monté backend/app/main.py:1688 core=True · confirmé dans le codele registre durable : inter_village_bridge.py:267 `self._peers = {}` — un dict de PROCESSUS. Rien ne survit au redémarrage, rien ne se partage entre les workers de prod. Une appartenance fédérale « enregistrée » peut disparaître sans trace. C'est exactement le repli que CLAUDE.md interdit à ce qui ENGAGE. | |
| 22 | La FENÊTRE de l'échelle systèmes — nommée, et sans personne derrière⚑ DÉGRADÉE DE BATI. Montée et atteignable (core=True), mais 0 appelant : git grep 'inter-village|inter_village' sur frontend/ hors __tests__ ne rend que de la documentation (etat-technique.html, FEATURE_MAP). Et elle ne lit que le dict RAM de inter_village_bridge.py:267.backend/app/routers/babel/inter_village_router.py:87 (GET /peers) et :153 (GET /federation/stats) · confirmé dans le codedeux : l'appelant navigateur, et un registre durable à lire. La fiche disait « à nommer » : la fenêtre est nommée — elle n'est pas pour autant bâtie. | |
| 23 | LA MAILLE — le registre que la fenêtre lit et qu'AUCUNE porte n'écritla LECTURE a un consommateur : projection_scope_context_service.py:36 (`self._mesh = mesh or get_relation_service()`) et relation_mutuelle_service.py:214 (communities_of). L'ÉCRITURE a 0 appelant de production sur les sept arbres.backend/app/services/relation_service.py:78 (add_relation) · confirmé dans le codel'écrivain. Table community_relation (v82_254), DB-first, upsert idempotent, refus de `abrite` — et rien n'y a jamais écrit depuis le code de production. | |
| 24 | L'ARBRE — une fenêtre câblée six fois, une porte d'octroi câblée zéro foisla FENÊTRE `avalidate_active_membership` : 6 sites d'appel confirmés — fractal_websocket_router.py:103, canon_coherence_router.py:173, fractale_communautaire.py:161, babel/fractal_pipeline.py:596, fractal_scope_guard.py:86, relation_mutuelle_service.py:195. La PORTE d'octroi : 0.backend/app/services/person_position_membership_authority.py:1668 · confirmé dans le codel'octroi. Le système sait refuser une appartenance six fois et ne sait l'accorder nulle part. | |
| 25 | La FENÊTRE de la communauté — six vitres, et personne devant⚑ DÉGRADÉE DE BATI. 6 endpoints, TOUS en GET (ma-coordonnee, ma-portee-projection, mes-communautes, grille-27, communaute/{id}/membres, communaute/{id}/tronc) : 0 écriture, elle n'ouvre effectivement rien. Mais aussi 0 appelant : git grep 'api/v2/fractale' sur frontend/ agents/ scripts/ backend/ hors tests = 0.backend/app/routers/fractale_communautaire.py:193-426 — monté backend/app/main.py:2007 · confirmé dans le codel'appelant. Elle dit elle-même qu'elle n'ouvre rien — c'est juste ; ce qui manque, c'est quelqu'un qui regarde. | |
| 26 | Les PORTES d'adhésion — onze dans l'arbre app/, zéro dans le second⚑ CHIFFRE CORRIGÉ — ONZE, pas cinq. Règle : @router.post|put dont le chemin contient join|adher|rejoin|membre|member, au commit. backend/app/ : cleanup.py:295, community_v68_router.py:195 et :226, governance.py:801, jeunesse_router.py:230, local_steward_router.py:120, my_team.py:516, team_collab_router.py:716 / :1176 / :1269, territory_raid_router.py:231. Hors backend/app/ (le second arbre) : ZÉRO.backend/app/routers/local_steward_router.py:120 (et dix autres) · confirmé dans le codeau moins une de ces onze n'ouvre rien : local_steward_router.py:120 lève un 503 inconditionnel (:159) — l'autorité d'appartenance environnementale n'est pas attribuée. Les dix autres ne sont pas vérifiées une par une ici. | |
| 27 | Le REÇU DURABLE du passage — la table existe, le protocole existe, rien n'y écrittable `passage_outbox_receipts` : PK = le nonce UUIDv4, 7 contraintes CHECK, 2 triggers (guard_passage_outbox_initial, guard_passage_outbox_monotone : refus de DELETE, refus de mutation d'un reçu, refus de régression d'horloge), RLS FORCE. passage_outbox.py : 0 importeur de production (seuls backend/tests/services/test_passage_outbox_p4.py et test_passage_outbox_pg_p4b1.py).backend/alembic/versions/v82_294_passage_outbox_receipts.py:48 · backend/app/models/passage_outbox_receipt.py:49 · backend/app/services/passage_outbox.py · confirmé dans le codel'écrivain. Le reçu le plus rigoureux du dépôt — immuable, monotone, non supprimable — et aucune main de production n'y dépose une ligne. | |
| 28 | Le second arbre — et le cliquet a bien cédéMESURÉ PAR MOI au commit 8addf1c94, sous la règle EXACTE du script (fichiers .py suivis par git sous backend/, hors app/, hors */tests/*, hors */alembic/*) : 280 fichiers — plafond 278, DÉPASSÉ DE 2. Le même compte sur l'index git donne 280. backend/app/ = 1726 fichiers .py (CLAUDE.md annonce 1627). 29 racines au second arbre (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).scripts/compteur_second_arbre.py:62 (PLAFOND_FICHIERS = 278) · .github/workflows/ci.yml:332 · confirmé dans le codele cliquet existe, il est en CI, et il ne garde pas cette branche : ci.yml:2-7 ne déclenche que sur push master|main|develop et PR vers master|main (plus un cron quotidien). La branche integration/fondateur-p0 n'est jamais gatée — le second arbre s'est étendu de 2 fichiers en silence, exactement ce que le cliquet devait rendre impossible. | |
| 29 | ÉCHELLE 1 — PIÈCES : l'anatomie des 3 faces, et son zéro lecteurRE-MESURÉ PAR MOI au commit : 510 portes, clés exactement {entre, garde_actuelle, trou} sur les 510, 301 `trou` non vides (59,0 %), ZÉRO clé `fenetre` (les 2 occurrences du mot sont de la prose descriptive). Et 0 lecteur : git grep du nom de fichier sur backend/ frontend/ scripts/ agents/ hf-atom-tools/ = 0 résultat.data/urbanisme/anatomie-lieux-stages-2026-07-15.json · confirmé dans le code | |
| 30 | LES PORTES D'OCTROI D'APPARTENANCE — zéro appelant, quand leurs fenêtres en ont sixRE-MESURÉ PAR MOI : `amark_face_authoritative` (:889), `agrant_membership` (:1015), `arevoke_contract` (:1086) — chacun 0 appelant. Règle : git grep du nom sur backend/ frontend/ agents/ scripts/ hf-atom-tools/ rosetta-core/, backend/tests/ exclu ; la seule occurrence de chaque nom est sa propre `def`. S'y ajoutent `EnclosurePlaceMembershipAuthority` (enclosure_place_membership_authority.py:166 — 0 instanciation hors son fichier) et `resolve_descendants` (scope_membership_service.py:565 — 0 appelant ; world_canon.py:1107 n'en parle qu'en commentaire).backend/app/services/person_position_membership_authority.py:889, :1015, :1086 · confirmé dans le code |
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-1-TECHNIQUE-2026-10-03.json (sha256 b29a3dc78614) — planche de matière « Portes et fenêtres — quatre échelles, et qui frappe vraiment ». 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.