0.3.15-pre.014-fix.001

This commit is contained in:
2026-09-17 23:09:21 +02:00
parent ad24cb36fa
commit 6d820bf0d7
14 changed files with 648 additions and 67 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md -->
<!-- version: 100 -->
<!-- version: 101 -->
# Séquence des releases fonctionnelles KSP
@@ -587,7 +587,9 @@ La séquence effective a évolué par sizing et validation réels. La référenc
0.3.13 cinq familles live + convergence multi-source/fairness/health/hardening
0.3.14 tranche suivante de la trajectoire RAW selon prompt dédié
0.3.15 ksp-app-raw-transaction-ingest-desk
0.3.16 Backfill multi-source / multi-stratégie
0.3.16 RAW resilience / conflict variants / Store Desk conflict management
0.3.17 ksp-job-backfill-lib multi-route / multi-stratégie
0.3.18 ksp-app-backfill-desk adapté au Backfill multi-route
```
Cette série ferme la couche RAW et ses outils d'exploitation avant l'ouverture fonctionnelle de STRUCTURAL. Le Worker live RAW reste distinct des jobs historiques et ne constitue pas encore une transformation RAW -> STRUCTURAL.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/031-V0_3_10_RAW_TRANSACTION_INGEST_PLAN.md -->
<!-- version: 14 -->
<!-- version: 15 -->
# Plan v0.3.10 — RAW Transaction commune + qualification cross-source
@@ -1084,9 +1084,17 @@ Nouvelle release/session : replay natif, source redondante, scan HTTP blocs, hyd
Ancienne cible `0.3.11`, décalée après finalisation complète du Worker.
### `0.3.16` — Backfill multi-source/multi-stratégie
### `0.3.16` — RAW resilience / conflict management
Ancienne cible `0.3.12`, décalée sans changer la frontière Job historique paramétré / Worker live.
Nouvelle tranche intercalée après le live `0.3.15` : variantes RAW durables, résolution automatique des représentations partielles prouvées, quarantaine des vrais conflits, historique de promotion/résolution, retry Store, reconnexion Transport configurable et vues de gestion dans Store Desk.
### `0.3.17` — Backfill multi-route/multi-stratégie
Ancienne cible Backfill multi-source, décalée sans changer la frontière Job historique paramétré / Worker live.
### `0.3.18` — Backfill Desk multi-route
Adapter `ksp-app-backfill-desk` au Job `0.3.17` en réutilisant les patterns de composition/supervision du Raw Transaction Ingest Desk sans dupliquer la logique Worker.
### Note durable de génération des prompts `0.3.12` à `0.3.15`
@@ -1169,7 +1177,7 @@ Les smokes live restent séparés et opt-in.
```text
ksp-app-raw-transaction-ingest-desk # 0.3.15
nouvelles stratégies historiques Backfill # 0.3.16
nouvelles stratégies historiques Backfill # 0.3.17
paramètres métier historiques dans Worker
Backfill checkpoint dans Worker
RawAccountState ingest worker

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/036-V0_3_15_RAW_TRANSACTION_INGEST_DESK_PLAN.md -->
<!-- version: 22 -->
<!-- version: 23 -->
# Plan v0.3.15 — Raw Transaction Ingest Desk
@@ -956,3 +956,16 @@ La cause est la même pour les deux routes et se situe dans le drain Worker comm
Le fault Yellowstone Devnet observé dans le même gate reste distinct : OrbitFlare répond `onchain_transport.grpc_status` avec refus de permission dès louverture du Subscribe, avant toute demande de Stop. Il nest pas reclassé par ce correctif.
## 23. Handoff durable après `pre.014-fix.001`
Le diagnostic inter-provider de `pre.014` et sa correction minimale `fix.001` ouvrent une évolution Store/Worker qui ne doit pas être absorbée par `0.3.15`. Le cas démontré de `logMessages` tronqués est fermé localement, mais la politique générale de divergence durable est réservée à `0.3.16`.
Trajectoire retenue :
```text
0.3.16 RAW resilience + conflict variants/resolution + Store Desk conflicts
0.3.17 ksp-job-backfill-lib multi-route / multi-stratégie
0.3.18 ksp-app-backfill-desk adapté au Job multi-route
```
Le contrat complet de handoff est enregistré dans `docs/plans/037-V0_3_16_RAW_RESILIENCE_CONFLICT_HANDOFF.md`. La préparation de publication `0.3.15` doit générer le prompt `0.3.16` depuis ce handoff et non depuis l'ancienne cible Backfill historique.

View File

@@ -0,0 +1,178 @@
<!-- file: docs/plans/037-V0_3_16_RAW_RESILIENCE_CONFLICT_HANDOFF.md -->
<!-- version: 1 -->
# Handoff v0.3.16 — RAW resilience, variantes et gestion des conflits
## 1. Origine de la version
Le live `0.3.15-pre.014` a démontré qu'une même transaction du même bloc peut être renvoyée avec une qualité de représentation différente selon le nœud RPC. Le cas observé n'était pas un fork : même slot, même identité de bloc, même transaction et mêmes métadonnées hors `logMessages`. Une acquisition contenait les logs complets ; l'autre contenait un marqueur `Log truncated`.
`0.3.15-pre.014-fix.001` ferme uniquement le cas où la version complète est déjà canonique et où une version tronquée strictement compatible arrive ensuite. La généralisation ci-dessous appartient à `0.3.16`.
## 2. Principe directeur
```text
une divergence de données != une panne d'acquisition
```
Le pipeline ne doit plus arrêter un Worker simplement parce qu'un N-ième RAW d'identité `(network, signature)` diffère du canonique. Store doit d'abord classifier la divergence, préserver les données et seulement exposer un conflit durable lorsqu'aucune convergence automatique sûre n'est démontrée.
Un provider n'est jamais déclaré « toujours correct ». La préférence porte sur la qualité prouvée de la représentation, indépendamment de l'ordre d'arrivée et de la provenance.
## 3. Classification de convergence
Le comparateur partagé vise au minimum :
```text
Exact
CompatibleLessComplete
CompatibleMoreComplete
Conflict
```
Règles :
- `Exact` : contenu canonique identique ; observation idempotente/nouvelle ;
- `CompatibleLessComplete` : conserver le canonique plus complet et l'observation entrante ;
- `CompatibleMoreComplete` : promotion atomique vers la représentation plus complète, sans détruire l'ancienne variante ;
- `Conflict` : conserver le canonique courant, conserver intégralement la variante entrante et ouvrir/compléter un dossier de conflit.
La comparaison est champ-spécifique. Il est interdit d'utiliser une règle générique « valeur la plus longue gagne ». `logMessages` peut utiliser une relation de troncature explicitement prouvée ; les autres champs ne deviennent enrichissables que lorsque leur contrat permet de distinguer absence informationnelle et contradiction.
## 4. Modèle Store cible
Le modèle conceptuel devient :
```text
RawTransaction identity (network, signature)
|
+-- Variant A <- canonical current
| +-- observations/provenances
|
+-- Variant B
| +-- observations/provenances
|
+-- Variant C
+-- observations/provenances
Conflict case
+-- status
+-- canonical variant
+-- classification
+-- resolution history
```
Les noms physiques exacts restent à décider en `0.3.16-pre.001`, mais les responsabilités doivent couvrir : identité canonique, variantes de contenu, observations rattachées à la variante réellement reçue, dossier de conflit et historique de résolution/promotion.
Une résolution ou promotion n'efface jamais l'ancienne valeur canonique. Un `A -> B` doit pouvoir être suivi plus tard d'un `B -> A` sans reconstruire les bytes depuis une source externe.
## 5. Résolution automatique
Le cas `logMessages` sert de première preuve :
```text
FULL + TRUNCATED compatible
-> garder FULL
TRUNCATED + FULL compatible
-> promouvoir FULL
TRUNCATED A + TRUNCATED B compatibles
-> promouvoir uniquement si la relation de qualité est formellement démontrée
```
Les champs scalaires présents avec des valeurs différentes restent des conflits. Les listes ne sont jamais fusionnées par longueur seule. Une absence peut devenir enrichissable uniquement si le contrat RPC/source prouve que l'absence signifie « non fourni » et non une valeur métier différente.
## 6. Conflit durable et santé Worker
Un conflit durablement quarantiné n'est pas terminal :
```text
content conflict
-> variant persisted
-> conflict case unresolved
-> Worker Running
-> health Degraded
```
Les snapshots doivent pouvoir exposer au minimum des compteurs source-neutral et sans identité métier, par exemple `unresolved_content_conflict_count`, `auto_resolved_conflict_count` et `canonical_promotion_count`. Les signatures, payloads et variantes restent Store-owned.
La complétude doit distinguer :
```text
acquisition_complete
= toute donnée attendue est durablement capturée, variantes comprises
canonical_complete
= aucune obligation de réconciliation canonique n'est ouverte
```
Un conflit non résolu ne doit pas bloquer l'acquisition des autres transactions. Le passage RAW -> STRUCTURAL décidera séparément comment traiter une identité encore conflictuelle.
## 7. Store indisponible, retry et backpressure
Un Store temporairement indisponible est différent d'un content conflict. Le Worker ne doit ni perdre silencieusement les données ni continuer à consommer indéfiniment sans durabilité.
Le contrat `0.3.16` doit prévoir une politique Store bornée : pause/backpressure des admissions, retry, délais/backoff configurables dans la couche propriétaire appropriée, observabilité `Degraded/Blocked`, puis terminal seulement si la politique explicite est épuisée ou si l'erreur est structurellement irréconciliable.
## 8. Reconnexion Transport
La reconnexion Transport doit être explicitement configurable et distincte de la politique Store. Paramètres conceptuels à auditer en `pre.001` :
```text
initial_delay
max_delay
backoff_multiplier
max_attempts
reset_after_stable_duration
jitter borné si retenu
```
Une perte de connexion ne doit pas provoquer un arrêt immédiat tant que la politique de reconnexion n'est pas épuisée. Les gaps éventuels continuent à utiliser les mécanismes de continuité/repair du Worker ; aucune reconnexion ne vaut preuve de couverture.
## 9. `ksp-app-store-desk`
`0.3.16` étend Store Desk avec une ou plusieurs vues dédiées, au minimum autour de deux responsabilités : conflits ouverts et historique de résolution.
Pour une identité, l'UI doit pouvoir présenter le canonique, les variantes, leurs différences structurées et leurs provenances sans charger arbitrairement tout le RAW dans les tables. Actions visées : promouvoir une variante, conserver le canonique et résoudre, fusion assistée uniquement pour des champs dont la compatibilité est définie, rouvrir/restaurer une résolution antérieure.
Une fusion manuelle produit une nouvelle variante explicitement marquée comme synthétique/manuelle avec ses parents ; elle ne prétend jamais être une observation provider native. Aucune action utilisateur ne doit rendre les anciennes variantes irrécupérables.
## 10. Frontières de crates
```text
ksp-store-api
-> DTO/contrats backend-neutral variantes, conflits, résolutions
ksp-store-lib
-> façade unique et moteur de convergence exposé aux producteurs
ksp-store-postgres-lib
-> atomicité physique, schema/migrations, variantes et historique
ksp-worker-raw-transaction-ingest-lib
-> continue sur conflits locaux durables, retry/reconnect selon contrats existants
ksp-app-store-desk
-> inspection/résolution via ksp-store-lib uniquement
```
Aucun Worker ou Job ne dépend directement du backend PostgreSQL. Le moteur de convergence est partagé afin que les futurs producteurs n'implémentent pas chacun leur propre arbitrage.
## 11. Versions suivantes
La trajectoire retenue est désormais :
```text
0.3.16 RAW resilience / conflict variants / Store Desk conflict management
0.3.17 ksp-job-backfill-lib multi-route / multi-stratégie
0.3.18 ksp-app-backfill-desk adapté au Job multi-route
```
`0.3.17` conserve le Job borné et paramétré, mais lui permet de composer plusieurs routes/stratégies d'acquisition sur la même convergence Store `0.3.16`. Il ne dépend pas du Worker.
`0.3.18` adapte le Desk Backfill à ce Job : inventaire/composition de routes, sélection, supervision, progression et résultats, en réutilisant les patterns applicatifs prouvés par `ksp-app-raw-transaction-ingest-desk` sans dupliquer la logique métier du Job.
## 12. Hors périmètre de `0.3.15-pre.014-fix.001`
Le fix courant ne crée aucune table de variante, ne promeut pas un canonique tronqué vers une version plus complète, ne modifie pas le health model Worker, n'ajoute pas de retry Store et ne change pas la politique de reconnexion Transport. Il ferme seulement le cas live démontré où une observation entrante tronquée et strictement compatible arrive après un canonique complet.