bd48b16e31
Cause racine du bug de reconnexion (probe contrôlé répété) : le shim d'un compte accumule des `docPublic`/`docProtected` EN DOUBLE (forks passés), et resolveAccount/indexDocOf les choisissaient de façon NON-DÉTERMINISTE → l'écrivain et le lecteur (page fraîche) ancraient sur des docs d'index DIFFÉRENTS → lecture 0. Fix : - `canonicalDoc()`/`recordFromRows()` : parmi plusieurs valeurs d'un scope, choisir le NURI lexicographiquement le plus petit (les NURIs sont content-addressed → ordre total stable). Écrivain et lecteur résolvent TOUJOURS le même doc, même sur un shim corrompu par des doublons. - `resolveAccountReliably` RESTAURÉ (retry borné avant provision sur read shim 0 à froid) : j'avais retiré l'anti-fork à tort (`38b1521`) — le gap EST exhibé (fork non-déterministe au cold-read), et la barrière `user_connect` n'est PAS accessible côté JS → un retry borné est la compensation légitime (pas la barrière-store cassée de `45dbd9a`). Budget injecté `provisionRetry` ; défaut attempts:1 (fakes synchrones), app/e2e attempts:8. anti-fork.test.ts réécrit : docPublic dupliqué → même canonique ; retry sur lag → réutilise ; neuf → provision 1×. gate : tsc 0 ; bun test 122 ; test:e2e 42/42 (CONTRACT 2 non-fork vert). Portée : corrige la couche docPublic de la reconnexion. Une couche PROTECTED distincte (watchShape protected ne converge pas à froid) reste — diagnostic en cours. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>