# XION RELATIVISTE — spec v0 du protocole de réconciliation causale > Deux space-cubions qui se retrouvent ont vécu des durées propres différentes, et aucune montre > n'a raison contre l'autre (@ref{space-cubion:10}). Ce qu'on gèle ici : l'horloge logique de > chaque space-cubion, l'estampille causale de chaque tsoin, et la sémantique de merge — dont la > **décision RS-7 gelée** : le conflit est un **fork visible**, jamais un écrasement silencieux. > > J0bot · Août 2026 · AGPL-3.0 · **spec — v0** · `xion-relativiste-v0` · 🛸 > Convention : `[POSÉ]` = gelé/décidé · `[HYPOTHÈSE]` = attendu mais non prouvé. > Régimes : RÉEL (physique/informatique établies) · PRÉSENT (à câbler dans le repo) · TURFU. ## 0. Ce que ce document gèle La relativité interdit l'horloge universelle (relativité de la simultanéité, Einstein) ; l'informatique distribuée a résolu exactement ce problème en l'abandonnant : ce qui compte n'est pas le temps absolu mais l'**ordre causal** (Lamport, « Time, Clocks, and the Ordering of Events in a Distributed System », CACM 1978). Le XION relativiste applique cette solution au réseau des space-cubions : chaque événement est un tsoin estampillé d'un **vector clock**, le merge de deux historiques est un **CRDT**, le transport est **DTN** (aucune simultanéité supposée, aucune connexion permanente supposée). Tout est RÉEL au sens des régimes : chaque brique de ce protocole est de l'informatique éprouvée — la seule nouveauté est de la brancher sur un problème de physique. Le même mécanisme qui réconcilie deux forks d'une base réconcilie deux vaisseaux qui ont vécu des temps propres différents. ## 1. L'horloge : le vector clock `[POSÉ]` Chaque space-cubion `i` maintient un **vector clock** VC_i (Fidge 1988, Mattern 1989) : une map `{id_cubion → compteur}` sur les cubions qu'il connaît. Règles gelées (les règles canoniques) : 1. **Événement local** (tout tsoin émis) : VC_i[i] += 1. 2. **Émission** : le tsoin part avec une copie du VC_i courant. 3. **Réception/merge** : VC_i ← max composante-par-composante(VC_i, VC_reçu), puis VC_i[i] += 1. Ce que ça donne, et c'est tout ce qu'il faut (RÉEL) : - **happened-before décidable** : e₁ → e₂ ssi VC(e₁) < VC(e₂) (≤ partout, < quelque part). - **concurrence détectable** : e₁ ∥ e₂ ssi ni VC(e₁) ≤ VC(e₂) ni VC(e₂) ≤ VC(e₁). Deux tsoins concurrents ont été émis dans des branches causalement disjointes — des lignes d'univers qui ne se sont pas parlé. Le VC capture la **causalité complète**, pas une approximation. Aucun champ « temps absolu » ne participe aux décisions du protocole. Le temps propre (horloge de bord) reste enregistré à titre de témoin humain, jamais d'arbitre. ## 2. Le tsoin estampillé `[POSÉ]` L'unité répliquée est le triplet gelé (@ref{adressage-generatif-triplet-v0:1}), enveloppé : ``` tsoin-relativiste = { triplet : ( hash_générateur , coordonnées , hash_résidu ), // le format éternel, inchangé vc : { id_cubion → compteur }, // l'estampille causale (§1) auteur : empreinte GPG, // qui l'a émis signature : GPG(triplet ‖ vc) // intégrité + non-répudiation } ``` Le triplet lui-même **ne change pas** : le VC est une enveloppe de transport/merge, pas une modification du format éternel. Le résidu reste chiffré GPG au repos et en transit ; les générateurs restent des communs publics (@ref{adressage-generatif-triplet-v0:3}). ## 3. L'ALIGNEMENT décide quoi diffuser `[POSÉ]` Au contact (amarrage §3 du CDS, ou simple passage radio), deux cubions comparent leurs `hash_générateur` : l'ALIGNEMENT du triplet est une égalité de hash, décidable au bit. Tout générateur commun ne sera jamais retransmis ; on ne diffuse que les tsoins dont le VC n'est pas déjà dominé par le VC du récepteur, et pour ceux-là uniquement `(coordonnées, hash_résidu, vc, signature)` + le résidu chiffré. C'est la réplication diff-only du triplet (@ref{adressage-generatif-triplet-v0:5}), avec le VC comme filtre anti-doublon : **on ne transporte que la surprise causalement neuve.** ## 4. Le merge `[POSÉ]` — et la décision RS-7 gelée Le merge de deux historiques doit être **déterministe, commutatif, associatif, idempotent** — les propriétés CRDT (Shapiro, Preguiça, Baquero, Zawirski, « Conflict-free Replicated Data Types », SSS 2011). Conséquence : l'ordre des retrouvailles ne compte pas, re-merger ne coûte rien, N cubions qui se retrouvent dans n'importe quel ordre convergent vers le même état. C'est la propriété qui rend l'essaim possible : aucun coordinateur, aucune session globale, jamais. Cas par cas : - **e₁ → e₂** (causalement ordonnés) : e₂ raffine e₁. Aucun conflit, le merge est l'union des logs — l'histoire est simplement plus complète d'un côté. - **e₁ ∥ e₂ sur des points différents** : union, trivialement. - **e₁ ∥ e₂ sur le MÊME point** (même `hash_générateur` + mêmes `coordonnées`, résidus différents) : c'est LE cas dur, la décision ouverte du triplet-v0 (« sémantique de merge des résidus », @ref{adressage-generatif-triplet-v0}). **DÉCISION RS-7, GELÉE (11.08) :** > **Multi-Value Register : les DEUX branches sont conservées et exposées comme FORK VISIBLE.** > Jamais d'écrasement silencieux, jamais d'arbitrage automatique qui jette de l'information. > **Divergence = branche, retrouvaille = merge, conflit = fork visible — au sens git.** Le MV-Register est un CRDT spécifié (Shapiro et al. 2011 ; c'est la sémantique des « siblings » de Dynamo/Riak, DeCandia et al., SOSP 2007) : la valeur d'un point devient l'ensemble des versions concurrentes maximales, chacune avec son VC. La **résolution** d'un fork n'est jamais le fait du protocole : c'est un **nouveau tsoin**, émis par un humain ou une règle de domaine explicite, dont le VC domine toutes les branches — le fork se referme comme un merge commit, tracé, signé, event-sourcé. Deux équipages qui ont pris des décisions incompatibles pendant des années de désynchronisation relativiste retrouvent leurs deux histoires **intactes et côte à côte**, puis tranchent en connaissance. Le protocole garantit qu'aucune branche ne disparaît sans un acte explicite ; la gouvernance du choix reste politique, et c'est voulu (@ref{space-cubion:15}). ## 5. Le transport : DTN / Bundle Protocol `[POSÉ]` Le réseau des space-cubions ne suppose **aucune simultanéité et aucune connectivité de bout en bout** — exactement le modèle du Delay-/Disruption-Tolerant Networking : architecture RFC 4838 (Cerf et al., 2007), Bundle Protocol version 7 RFC 9171 (2022). Store-and-forward : chaque cubion porte les bundles qu'il ne peut pas encore livrer, et tout contact (amarrage, survol, relais laser @ref{space-cubion:11}) est une opportunité de livraison. Le DTN tourne déjà sur l'ISS — « tsoin over Bundle Protocol » est une phrase de câblage, pas un programme de recherche. Latence des heures, des années : indifférent — le VC ordonne, le bundle attend, le merge converge. Un tsoin est un bundle ; un amarrage est un contact à très haut débit ; un cubion en croisière est un nœud DTN qui muletise l'histoire de l'essaim. ## 6. Chemin de migration : du LWW au VC/MVR **État réel du repo** : `StateReplicationController` (`app/Http/Controllers/StateReplicationController.php`) fait du **newer-wins par horloge murale** — chaque entrée KV porte un `savedAt` ISO8601, `cmpAt()` compare les instants, le plus récent gagne, et le cas « local plus récent » est déjà remonté dans un tableau `conflicts` (kept: local). C'est du LWW : déterministe et idempotent, oui, mais il **jette silencieusement une des deux écritures concurrentes** et fait confiance à des horloges murales que la relativité (et le simple clock-skew) désynchronise. La STRUCTURE pull/apply est bonne ; l'arbitre est le maillon à remplacer. Migration en quatre pas, chacun shippable : 1. **Double-estampille** : chaque entrée gagne un champ `vc` à côté de `savedAt` (les nœuds sont les boxions/cubions du registre). Aucun comportement ne change — on pose l'horloge. 2. **VC d'abord, savedAt en secours** : `pull` compare les VC quand les deux entrées en ont un ; dominance → apply/skip comme aujourd'hui. Sans VC des deux côtés, `cmpAt` reste l'arbitre (rétrocompatibilité avec les nœuds non migrés — éternelle, comme il se doit). 3. **MVR** : VC concurrents → **plus d'écrasement ni de kept-local** : l'entrée devient multi-branches `{branches: [{data, vc, savedAt, auteur}, …]}`, le rapport de pull expose le fork, l'UI le montre comme git montre deux branches. 4. **Résolution = tsoin** : choisir/fusionner écrit une nouvelle valeur dont le VC domine toutes les branches. Le fork se referme en merge tracé — jamais en oubli. ## 7. Garde-fous honnêtes `[HYPOTHÈSE]` 1. **Taille des VC.** Un VC croît avec le nombre de cubions rencontrés (O(n) par estampille). À l'échelle de l'essaim (10⁶+ nœuds), il faudra de la compaction : deltas de VC, dotted version vectors, ou VC hiérarchiques par agrégat (l'agrégat comme nœud composite). Non gelé — le format §2 réserve la place, la stratégie reste ouverte. 2. **GC des branches et des logs.** Un MVR n'oublie jamais tout seul : sans résolution, les forks s'accumulent. Politique de rétention/archivage à définir — mais l'oubli sera toujours un acte explicite (droit au silence), jamais un effet de bord. 3. **Snapshots.** Rejouer un log de plusieurs années de croisière à chaque merge est absurde : checkpoints d'état signés + log depuis le checkpoint. La profondeur de Bennett du triplet s'applique ici aussi — déplier coûte du calcul, c'est le prix assumé. 4. **Perf du merge à l'amarrage.** Le handshake du CDS (§3) borne le temps d'ouverture du passage ; le merge complet peut continuer en tâche de fond après l'ouverture — l'ordre causal le permet, à prouver en charge. 5. **Sybil/identités.** Le VC fait confiance aux `id_cubion` ; la signature GPG de chaque tsoin (§2) est la ligne de défense. Un cubion qui ment sur son VC signe son mensonge — détectable, attribuable. L'audit systématique reste à spécifier. --- *Ne pas nuire. Aucune montre n'a raison contre l'autre ; aucune branche ne meurt en silence.* *AGPL-3.0 · Août 2026 · xion-relativiste-v0*