Résumé
Sur la build 31076cc86, address.statement détecte correctement que son scan
de transferts a échoué et l'expose dans diagnostic.status: "partial" — mais
result_confidence reste "complete". Le signal de dégradation n'atteint pas
le champ sur lequel les consommateurs branchent leur garde-fou.
La 1.25.0 publiée a le défaut symétrique : elle dégrade bien
result_confidence à partial, mais laisse diagnostic.status: "complete".
Aucune des deux versions n'a les deux champs cohérents ; la build régresse sur
celui qui est actionnable.
Régression vraisemblablement introduite par 4c8b240a6 fix(mcp): juger la confiance sur l'appel métier, pas sur les tentatives (alter#71) — le correctif
#71 est par ailleurs excellent et mesurable (cf. mon commentaire sur #71), c'est
un effet de bord, pas une remise en cause.
Cas de test
Wallet réel : emprunteur RMM v3 portant ~$1,3M de collatéral. Adresses en dur,
fenêtre de blocs figée — rejouable tel quel.
$BUILD/alter-cli mcp address.statement --json '{
"wallet":"0x309ccbc93c8211c7dabfffb2fa96aaa78f9c7910",
"network":"gnosis",
"tokens":["0xeD56F76E9cBC6A64b821e9c016eAFbd3db5436D1",
"0x0cA4f5554Dd9Da6217d62D8df2816c82bba4157b"],
"from_block":47700325,"to_block":47820325
}' --mcp-binary $BUILD/alter-mcp --timeout 880
Observé vs attendu
3 répétitions consécutives de chaque côté, résultat stable 3/3 :
build 31076cc86 : rc=complete diag=partial lims=['incomplete_transfer_logs' x2]
1.25.0 installée : rc=partial diag=complete lims=[]
Message de limitation rendu par la build :
{"code":"incomplete_transfer_logs",
"message":"Le scan des transferts pour le token 0xed56... a dépassé la limite autorisée ou a rencontré des erreurs RPC, limitant l'exhaustivité du relevé."}
Observé : result_confidence = "complete" alors que diagnostic.status = "partial"
et que 2 limitations incomplete_transfer_logs sont remontées
Attendu : result_confidence != "complete" dès lors que diagnostic.status != "complete"
Source de l'attendu : le contrat documenté de result_confidence — c'est le
champ qui signale qu'un résultat est incomplet. Un scan qui abandonne sur une
limite interne est exactement ce cas. La preuve que la build sait que le scan
a échoué est dans sa propre sortie (diagnostic).
La cause est bornée
Sur une fenêtre étroite, le scan aboutit réellement et les deux champs sont
cohérents :
# même wallet, même token, 2 000 blocs
--json '{"wallet":"0x309ccbc93c8211c7dabfffb2fa96aaa78f9c7910","network":"gnosis",
"tokens":["0xeD56F76E9cBC6A64b821e9c016eAFbd3db5436D1"],
"from_block":47818325,"to_block":47820325}'
rc=complete diag=complete lims=[]
Ce n'est donc pas la détection qui manque, uniquement sa propagation vers
result_confidence sur le chemin « scan tronqué ».
Pourquoi c'est le défaut le plus coûteux pour un consommateur
Ce n'est pas une panne : c'est un résultat incomplet annoncé comme fiable.
Le projet RMM alimente des documents publiés (positions RMM v3, historique du
marché secondaire, rapports) et route tous ses appels via un helper qui lève une
exception et bascule sur un fallback RPC direct dès que result_confidence est
dégradé. Ce garde-fou existe précisément parce qu'Alter peut rendre des chiffres
faux sans lever d'erreur quand ses RPC échouent — constaté en août sur
lending_risk_score (total_active_borrowers: 0 sur un pool à 14,7 M$).
Un complete sur un scan tronqué désarme silencieusement ce mécanisme.
C'est pire qu'une erreur franche : une erreur déclenche le fallback, un faux
complete publie la donnée incomplète.
Impact RMM aujourd'hui : nul — address.statement n'est appelé par aucun
script du projet (vérifié par grep sur l'ensemble du dépôt). Je remonte au titre
du beta-test, pas parce qu'un pipeline est cassé. Cela ne bloque pas l'adoption
de la build de notre côté.
✅ Test d'acceptation
1. Sur la commande de repro (120 000 blocs) :
diagnostic.status == "partial" ⟹ result_confidence != "complete"
2. Plus généralement, l'invariant doit tenir dans les deux sens :
result_confidence == "complete" ⟺ diagnostic.status == "complete"
ET diagnostic.limitations == []
3. Anti-régression fenêtre étroite (2 000 blocs, même wallet, même token) :
rc == "complete" ET diag == "complete" ET lims == []
— un scan qui aboutit ne doit pas être déclassé par ce correctif
4. Anti-régression #71 : address.inspect sur
0xFb9b496519fCa8473fba1af0850B6B8F476BFdB3 (network gnosis) doit rester
result_confidence == "complete" sur 3 appels consécutifs
5. La valeur émise sur le chemin tronqué appartient à un ensemble documenté
(voir note ci-dessous)
Le critère 4 est important : le correctif ne doit pas se faire en re-dégradant
tout ce que 4c8b240a6 a légitimement rendu complete.
Note connexe — nouvelles valeurs de result_confidence
Toujours sur cette build, address.transfers émet capped_at_limit, valeur que
la 1.25.0 n'émettait pas (elle rendait partial).
C'est une amélioration — plus précis que partial, ça dit pourquoi le
résultat est tronqué — et je ne demande pas de revenir dessus. Mais côté
consommateur, elle est passée entre les mailles de notre garde-fou : inconnue de
nos ensembles « fiable » / « dégradé », elle tombait dans une branche permissive
qui acceptait le résultat. Corrigé chez nous.
Si le chemin tronqué de address.statement doit émettre une valeur non-complete
(critère 5), capped_at_limit conviendrait bien. Et de façon générale, signaler
en release notes l'ajout d'une valeur à cette énumération aiderait les
intégrations qui en font un point de contrôle.
Environnement
- Build :
phoenix_0 HEAD 31076cc86, v1.25.0 +94 commits, compilée localement
(dart compile exe), invoquée avec --mcp-binary pour ne pas taper le binaire
Homebrew. ⚠️ --version affiche 1.25.0, identique à la release publique.
- Comparaison :
alter-cli 1.25.0 installée via brew (visialis/alter).
- Chaîne Gnosis (100) provisionnée via
chain.add avant chaque scénario.
- macOS 26.6.1 (arm64), RPC publics Gnosis, pas de clé API explorer configurée.
Réserves
- 3 répétitions par version, une seule machine, une seule fenêtre horaire.
- Je n'ai pas isolé
4c8b240a6 par bissection : l'imputation vient de la lecture
du message de commit et de la nature du changement, pas d'un build intermédiaire.
- Non testé sur un wallet à fort volume de mouvements — les invariants ressortent
ici balanced, ce qui est numériquement correct (vérité terrain eth_getLogs
direct : 0 transfert sur la fenêtre).
Résumé
Sur la build
31076cc86,address.statementdétecte correctement que son scande transferts a échoué et l'expose dans
diagnostic.status: "partial"— maisresult_confidencereste"complete". Le signal de dégradation n'atteint pasle champ sur lequel les consommateurs branchent leur garde-fou.
La 1.25.0 publiée a le défaut symétrique : elle dégrade bien
result_confidenceàpartial, mais laissediagnostic.status: "complete".Aucune des deux versions n'a les deux champs cohérents ; la build régresse sur
celui qui est actionnable.
Régression vraisemblablement introduite par
4c8b240a6 fix(mcp): juger la confiance sur l'appel métier, pas sur les tentatives (alter#71)— le correctif#71 est par ailleurs excellent et mesurable (cf. mon commentaire sur #71), c'est
un effet de bord, pas une remise en cause.
Cas de test
Wallet réel : emprunteur RMM v3 portant ~$1,3M de collatéral. Adresses en dur,
fenêtre de blocs figée — rejouable tel quel.
Observé vs attendu
3 répétitions consécutives de chaque côté, résultat stable 3/3 :
Message de limitation rendu par la build :
{"code":"incomplete_transfer_logs", "message":"Le scan des transferts pour le token 0xed56... a dépassé la limite autorisée ou a rencontré des erreurs RPC, limitant l'exhaustivité du relevé."}Source de l'attendu : le contrat documenté de
result_confidence— c'est lechamp qui signale qu'un résultat est incomplet. Un scan qui abandonne sur une
limite interne est exactement ce cas. La preuve que la build sait que le scan
a échoué est dans sa propre sortie (
diagnostic).La cause est bornée
Sur une fenêtre étroite, le scan aboutit réellement et les deux champs sont
cohérents :
Ce n'est donc pas la détection qui manque, uniquement sa propagation vers
result_confidencesur le chemin « scan tronqué ».Pourquoi c'est le défaut le plus coûteux pour un consommateur
Ce n'est pas une panne : c'est un résultat incomplet annoncé comme fiable.
Le projet RMM alimente des documents publiés (positions RMM v3, historique du
marché secondaire, rapports) et route tous ses appels via un helper qui lève une
exception et bascule sur un fallback RPC direct dès que
result_confidenceestdégradé. Ce garde-fou existe précisément parce qu'Alter peut rendre des chiffres
faux sans lever d'erreur quand ses RPC échouent — constaté en août sur
lending_risk_score(total_active_borrowers: 0sur un pool à 14,7 M$).Un
completesur un scan tronqué désarme silencieusement ce mécanisme.C'est pire qu'une erreur franche : une erreur déclenche le fallback, un faux
completepublie la donnée incomplète.Impact RMM aujourd'hui : nul —
address.statementn'est appelé par aucunscript du projet (vérifié par grep sur l'ensemble du dépôt). Je remonte au titre
du beta-test, pas parce qu'un pipeline est cassé. Cela ne bloque pas l'adoption
de la build de notre côté.
✅ Test d'acceptation
Le critère 4 est important : le correctif ne doit pas se faire en re-dégradant
tout ce que
4c8b240a6a légitimement renducomplete.Note connexe — nouvelles valeurs de
result_confidenceToujours sur cette build,
address.transfersémetcapped_at_limit, valeur quela 1.25.0 n'émettait pas (elle rendait
partial).C'est une amélioration — plus précis que
partial, ça dit pourquoi lerésultat est tronqué — et je ne demande pas de revenir dessus. Mais côté
consommateur, elle est passée entre les mailles de notre garde-fou : inconnue de
nos ensembles « fiable » / « dégradé », elle tombait dans une branche permissive
qui acceptait le résultat. Corrigé chez nous.
Si le chemin tronqué de
address.statementdoit émettre une valeur non-complete(critère 5),
capped_at_limitconviendrait bien. Et de façon générale, signaleren release notes l'ajout d'une valeur à cette énumération aiderait les
intégrations qui en font un point de contrôle.
Environnement
phoenix_0HEAD31076cc86, v1.25.0 +94 commits, compilée localement(
dart compile exe), invoquée avec--mcp-binarypour ne pas taper le binaireHomebrew.
--versionaffiche1.25.0, identique à la release publique.alter-cli 1.25.0installée via brew (visialis/alter).chain.addavant chaque scénario.Réserves
4c8b240a6par bissection : l'imputation vient de la lecturedu message de commit et de la nature du changement, pas d'un build intermédiaire.
ici
balanced, ce qui est numériquement correct (vérité terraineth_getLogsdirect : 0 transfert sur la fenêtre).