Skip to content

Feature: valorisation d'une detention — valuation_policy.required:true est accepte mais jamais servi (statut not_requested, result_confidence complete) #81

Description

@spouletmathis

Feature : valorisation d'une ligne RealT — valuation_policy.required: true est accepté mais jamais servi

Build : 31076cc86 (2026-08-20), 94 commits après v1.25.0, compilée localement.

Besoin métier

Produire la valeur d'une détention RealT à une date donnée, pour la déclaration 3916 et
la valorisation annuelle du patrimoine. Concrètement : « au 31/12, mes 51 RealTokens valent
combien ? ». C'est le livrable pour lequel ce projet utilise Alter.

État actuel

address.portfolio répond parfaitement à la partie détention — 51 tokens détenus sur 812
scannés en 2 secondes, avec balance_raw et balance_fmt :

{"token":"0x304bee450c2d116696d8b442981e7a300dfdf1cb",
 "symbol":"REALTOKEN-S-11965-LAKEPOINTE-ST-DETROIT-MI",
 "decimals":18,"holder":"0x15ED1e0c…","balance_raw":"1000000000000000000","balance_fmt":"1"}

Mais aucune valorisation : ni value_usd, ni prix unitaire, ni référence de source.

address.statement expose bien un valuation_policy, et l'accepte :

$BUILD/alter-cli mcp address.statement --json '{
  "network":"gnosis","wallet":"0x15ED1e0c61Ca2fbB98b0ad2F6eD549fE0ee175c7",
  "tokens":["0x304bee450c2d116696d8b442981e7a300dfdf1cb"],
  "from":"2026-06-01","to":"2026-07-31",
  "valuation_policy":{"currency":"EUR","required":true}
}' --mcp-binary $BUILD/alter-mcp --timeout 600

La policy est renvoyée telle quelle dans policies, mais :

result_confidence : "complete"
balances          : [{"opening_raw":"1000000000000000000","closing_raw":"1000000000000000000"}]
                    → aucun champ de valorisation
accounting_entries: valuation = {"valuation_status":"not_requested"}   ← alors que required:true

Deux choses distinctes ici :

  1. required: true n'est pas honoré — aucune valorisation n'est produite ;
  2. et l'échec est silencieuxresult_confidence reste complete et le statut
    d'entrée dit not_requested alors que la valorisation a été demandée et exigée.
    Un required non satisfait devrait faire échouer l'appel ou dégrader la confiance.

Recherche préalable, conformément à la règle de ce projet (chercher un tool avant de
contourner) : inventaire des tools de la build filtré sur price|value|valuation|oracle
→ seuls address.portfolio, address.statement, address.statement.translate et
lending.spread ressortent, aucun ne rend un prix unitaire.
capabilities.search "prix d'un token RealToken" → vide (comportement attendu, cf. #78 :
le catalogue indexe les capacités métier, pas ce besoin).

Le contournement en place

Prix maintenus à la main dans conformite/patrimoine/realtokens.yaml (1,9 Mo), à partir
de l'API RealT et des exports Tediji. Coût : une reprise manuelle à chaque valorisation, une
donnée qui périme en silence, et aucune traçabilité on-chain de la valeur retenue — c'est
précisément ce qu'un justificatif fiscal exige.

À noter : le trou est déjà connu côté produit sous une autre forme (« prix oracle par
RealToken », issue #41 mentionnée dans nos notes). Cette demande-ci est plus étroite : je ne
demande pas un oracle de prix, je demande que la policy déjà exposée soit servie ou refuse
explicitement
.

Proposition

Par ordre de préférence, et du moins coûteux au plus complet :

  1. Minimum — honorer le contrat existant : si valuation_policy.required: true ne peut
    pas être satisfait, retourner une erreur explicite ou result_confidence: "partial" avec
    une limitation nommée (valuation_source_unavailable) et la remédiation. Aujourd'hui
    l'appelant ne peut pas distinguer « pas valorisable » de « valorisation à zéro ».
  2. Utile — un champ value optionnel sur les lignes de address.portfolio, alimenté
    quand une source de prix est configurée, avec price_source + priced_at (bloc ou
    horodatage) pour la traçabilité.
  3. Complet — une source de prix déclarable par l'utilisateur (endpoint RealT, oracle
    on-chain, ou table fournie), pour que la valorisation soit reproductible et auditable
    plutôt que dépendante d'un tiers non nommé.

Je reste ouvert sur la forme : le point qui compte est qu'une valeur affichée soit
sourcée et datée, ou absente et dite absente.

Compromis acceptés

Fraîcheur : un prix daté de la veille convient parfaitement pour un usage fiscal annuel.
Exhaustivité : une valorisation qui ne couvre qu'une partie des tokens est utile si elle
dit lesquels. Clé API : configurer une clé est acceptable, à condition que l'absence soit
signalée comme le fait déjà token.holders — c'est le bon modèle.

✅ Test d'acceptation

1. address.statement avec valuation_policy {"currency":"EUR","required":true} :
   soit les entrées portent une valorisation (montant + devise + source + date),
   soit l'appel échoue explicitement avec un code nommé.
   Dans tous les cas : result_confidence != "complete" si aucune valorisation n'est produite.

2. Aucune entrée ne porte valuation_status "not_requested" quand la policy a été fournie
   avec required: true — l'état doit refléter la demande réelle
   ("unavailable", "failed", ou une valorisation).

3. Cas nominal address.portfolio (si option 2 retenue) : sur le wallet
   0x15ED1e0c61Ca2fbB98b0ad2F6eD549fE0ee175c7 (51 RealTokens détenus sur Gnosis),
   chaque ligne valorisée expose price_source et priced_at.

4. Sans source de prix configurée, la réponse expose explicitement l'absence et la
   remédiation — même contrat que la note de token.holders, qui est le bon précédent.

5. Anti-régression : address.portfolio reste sous 5 s sur les 812 adresses du preset
   realtokens (aujourd'hui 2 s), la valorisation ne devant pas rendre le tool inutilisable
   pour le simple inventaire de détention.

Le critère 5 compte : address.portfolio est aujourd'hui excellent sur la détention. Une
valorisation qui le ferait passer de 2 s à plusieurs minutes serait une régression nette
pour l'usage principal — mieux vaut un champ optionnel qu'un tool ralenti.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions