Commit Graph

5 Commits

Author SHA1 Message Date
Sylvain Duchesne 8fe8c052da docs: dire par situation ce qu'un appelant voit changer, pas les deux ensemble
Le texte disait que les deux situations passaient de `isSuccess` a
`isPending`. Verifie : seul le second `configure()` publiait un succes
(vide ou perime). Sur un refus tardif du courtier la lecture etait deja
retenue - ce qui change est la sortie, la nouvelle tentative se
re-souscrit au lieu d'etre bloquee pour la session.
2026-09-24 13:03:33 +02:00
Sylvain Duchesne de9b8a0d67 feat!: une seule reponse a « ce document est-il ouvert dans cette session »
Trois reponses coexistaient et pouvaient se contredire : un ensemble de
souscriptions bootstrap et une carte d'etat de barriere dans `open-repo`, et les
auditeurs du fan-out dans `surface/subscribe`. Les deux premieres survivaient a
la disparition de la troisieme, parce que `resetDocSubscriptions()` - ce que fait
le `configure()` publie - largue ses auditeurs sans rien dire a personne.

Il n'en reste qu'une, l'etat de l'unique souscription reelle du document, exposee
par `docChannel(nuri)`. `open-repo` n'enregistre plus que l'auditeur qu'il a pose
- « est-ce que j'ecoute encore », rien de plus - et derive `getSyncState` a chaque
lecture, si bien qu'aucune reponse ne peut survivre au canal qu'elle decrit.
Disparaissent : `held`, `syncState`, `inFlight`, `settleInFlight` et le compteur
de generation, remplace par l'identite de l'enregistrement.

Les deux echecs prouves deviennent des tests qui echouent sans le changement :
un second `configure()` apres une synchro reussie (`"synced"` au lieu de
`"timed-out"`, zero re-souscription, et `isSuccess` cote application), et un
etablissement encore en cours quand la couche de souscription est demontee - cas
que le canal `onSetupFailed` ne peut pas rattraper, puisqu'il ne rapporte que la
tentative encore attendue.

La ligne qui ne casse pas : un document synchronise qui ne contient rien repond
toujours un succes a zero objet. `1.0.0-dev.10`, les deux non-garanties
nommees sont retirees et la garantie livree porte le test qui l'epingle.
2026-09-24 12:57:43 +02:00
Sylvain Duchesne 52ac4d974e docs: le contrat descend a ce que le code tient vraiment, et T01.j est scindee
La sixieme revue a refute la reparation du tour 6 et a trouve la famille sur
laquelle nous nous etions engages a scinder. `held` n'est pas le registre unique :
il y en a trois, et celui que personne n'avait compte est `fanOuts` dans
`subscribe.ts`. `configure()`, qui est PUBLIE, vide les auditeurs sans le dire a
`open-repo` ; et `held.set()` s'execute avant meme que `establish` atteigne
`doc_subscribe`. `held` veut donc toujours dire « on a demande » - le sens plus
lache pour lequel j'avais supprime `opened`. J'ai remplace l'un des deux registres
qui se contredisaient ; il y en avait trois.

Aucun code touche ici. Le defaut de registre part dans T01.m, avec ses deux echecs
prouves comme tests d'acceptation.

Le contrat dit desormais ce que le code tient : la moitie « le document a-t-il
repondu » vaut DANS UNE SESSION ordinaire, et pas apres un second `configure(...)`
ni quand le courtier refuse un abonnement tardivement. Les deux situations sont
nommees en non-garanties avec leur cause et le renvoi vers T01.m. La moitie
« peut-on joindre le document » n'a pas cette reserve : elle est verifiee deux fois
contre un vrai courtier, et la retirer ramenerait un succes vide silencieux
partout, ce qui est pire qu'une garantie partielle honnetement enoncee.

Pas de changement de version : aucun comportement publie ne bouge, seule la
justesse de sa description.

Et une faute de compte-rendu consignee, parce que c'est un motif : trois fois j'ai
affirme qu'un changement avait reduit ou simplifie quelque chose, trois fois la
mesure disait le contraire. Regle desormais mecanique - toute affirmation
structurelle porte son `wc -l` ou son `--numstat` dans la meme phrase, sinon elle
ne s'ecrit pas.
2026-09-24 11:55:12 +02:00
Sylvain Duchesne 4af0be433d fix!: joindre un document n-est pas en avoir des nouvelles, et une reinit invalide ce qu-elle abandonne
Deux defauts, aucun des deux sur la reprise - elle a passe cette revue intacte et
n'a pas ete rouverte.

1. La barriere verifiait qu'un document nomme peut etre JOINT, jamais qu'il a
   REPONDU. Elle attendait `ensureRepoOpen` puis demandait `assertMayReach`, qui
   est la question de la capacite, et ne consultait pas l'etat de synchro que
   l'ouverture venait de produire. Un document dont l'abonnement a reussi mais dont
   le premier `State` n'est jamais venu publiait donc `isSuccess` avec `data: []` :
   le defaut d'origine, dans le cas precis pour lequel la barriere a ete ajoutee.

   La verification rejoint le reste de la decision, dans `publish`, donc rejouee a
   chaque publication au lieu d'etre memorisee. Les trois valeurs, enumerees avant
   d'ecrire la condition : `"synced"` fait autorite - zero ligne VEUT DIRE zero
   objet, la ligne tenue depuis cinq revues -, `"timed-out"` et `"syncing"` non, et
   `"unknown"` PASSE deliberement, parce qu'il veut dire « pas de semantique de
   `State` sur ce `ng` » et que le traiter autrement est exactement la regression
   du cas inerte livree aux tours 1 et 3.

   `isPending` plutot que `isError`, des deux que le contrat autorise : rien n'a
   echoue, il manque l'autorite de dire que le document est vide.

   Le test (t) EPINGLAIT le defaut - il attendait `isSuccess` apres trois
   barrieres expirees. Corrige. Ce n'est pas un test affaibli : l'ancienne
   assertion etait fausse.

   Et un trou dans ma propre suite, trouve par mutation : inverser la condition
   pour refuser `"unknown"` passait tous les tests, faute d'un `ng` SANS
   `doc_subscribe` nulle part. (cc) le couvre.

2. Regression de mon correctif du tour 4. Terminer une ouverture abandonnee
   faisait tourner sa continuation juste apres que la reinit avait vide les
   tables, donc elle ecrivait une entree `opened` perimee dans le registre neuf -
   et toute ouverture ulterieure de ce nuri court-circuitait dessus. Le depot
   n'etait jamais abonne dans la nouvelle session. Une epoque de registre corrige
   cela : une reinit l'incremente, une continuation dont l'epoque ne correspond
   plus n'ecrit rien. Une reinit INVALIDE ce qu'elle abandonne, en plus de le
   terminer.

`getSyncState` reste interne, et la doctrine cesse de l'offrir : elle pointait sur
un symbole qu'aucun appelant ne peut importer.
2026-09-24 11:03:07 +02:00
Sylvain Duchesne b0eec7b4dc docs: le contrat passe en 1.0.0-dev.9, et ce qu'une lecture echouee repond est consigne
Majeur : trois appels existants se resserrent. `useShapeQuery` publie `isError`
pour un document NOMME qu'il ne peut pas lire, la ou il rendait `isSuccess` avec
`data: []` - la seule image que cette surface reserve a « ce scope ne contient
rien ». `inbox.postToDocument`, `readForDocument` et `readSyncedForDocument`
rejettent la ou elles annoncaient « pas d'inbox ». Rien de ce qui etait deja une
reponse ne bouge : un document vide, `graphs: []`, un document sans inbox, un
document public qui n'expose aucune cle.

Deux non-garanties corrigees parce que le changement les rend fausses : « aucune
des deux lectures par forme ne va chercher la cle d'un store public » ne vaut
plus que pour `useShape` et pour `did:ng:i`, et le pending eternel d'un demarrage
refuse se referme sur le cas nomme.

Nouveau `knowledge_what-a-failed-read-answers-upstream` : ce que la cible repond
pour un document injoignable, non synchronise ou vide, et les deux collisions que
l'appelant ne peut pas demeler - « n'existe pas » contre « pas connu de moi »
d'un cote, « non synchronise » contre « vraiment vide » de l'autre. C'est le fait
durable qui justifie la direction prise, et il vaut quel que soit le remede.

`docs/internal-contract.md`, section open-repo seulement : numeros de ligne,
`ensurePhysicalRepoOpen` qui n'a jamais ete un export de ce module,
`ensureReposOpen` supprime, `openRepoUnguarded` absent, et le second parametre de
`ensureRepoOpen`. Le reste du document porte une derive du meme age, laissee.
2026-09-21 15:09:50 +02:00