v0.3.14-pre.015

This commit is contained in:
2026-09-12 23:07:58 +02:00
parent 8d8b6b9bcb
commit cd7cf2c4c6
11 changed files with 406 additions and 52 deletions

View File

@@ -1,12 +1,12 @@
# file: Cargo.toml # file: Cargo.toml
# version: 590 # version: 591
[workspace] [workspace]
resolver = "3" resolver = "3"
members = ["crates/ksp-app-backfill-desk", "crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-store-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-job-api", "crates/ksp-job-backfill-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-raw-transaction-lib", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib", "crates/ksp-worker-api", "crates/ksp-worker-raw-transaction-ingest-lib"] members = ["crates/ksp-app-backfill-desk", "crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-store-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-job-api", "crates/ksp-job-backfill-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-raw-transaction-lib", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib", "crates/ksp-worker-api", "crates/ksp-worker-raw-transaction-ingest-lib"]
[workspace.package] [workspace.package]
version = "0.3.14-pre.14" version = "0.3.14-pre.15"
edition = "2024" edition = "2024"
license = "MIT" license = "MIT"
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"

View File

@@ -1,5 +1,5 @@
<!-- file: crates/ksp-worker-raw-transaction-ingest-lib/README.md --> <!-- file: crates/ksp-worker-raw-transaction-ingest-lib/README.md -->
<!-- version: 11 --> <!-- version: 12 -->
# ksp-worker-raw-transaction-ingest-lib # ksp-worker-raw-transaction-ingest-lib
@@ -84,7 +84,7 @@ La construction est sans I/O et refuse notamment :
Le runtime-resource aggregate public accepte une collection validée de 1 à 32 sources logiques et les démarre simultanément sous un supervisor privé. La collection est validée entièrement avant spawn ; aucun sous-ensemble silencieux, source primaire implicite ou standby n'est choisi. La collection interne, les `source_key`, les URLs, les filtres et les clients inférieurs ne sont pas exposés. Le runtime-resource aggregate public accepte une collection validée de 1 à 32 sources logiques et les démarre simultanément sous un supervisor privé. La collection est validée entièrement avant spawn ; aucun sous-ensemble silencieux, source primaire implicite ou standby n'est choisi. La collection interne, les `source_key`, les URLs, les filtres et les clients inférieurs ne sont pas exposés.
Le supervisor possède toutes les tâches source. Une source qui échoue est terminale pour le Worker et déclenche l'arrêt coopératif puis le join des autres sources, car cette release ne suppose aucune équivalence de coverage. Une fermeture propre d'une source alors que le Worker n'est pas en arrêt est également traitée comme une perte de source configurée et devient terminale. Le supervisor possède toutes les tâches source. Une perte de source n'est plus assimilée automatiquement à un fault : lorsqu'elle porte une plage de continuité bornée, le Worker l'inscrit dans son ledger run-local puis n'autorise la continuation des siblings que si la coverage passée de cette perte est réconciliée et si les sources encore actives couvrent explicitement tout le `TargetCoverage` futur. Une perte sans plage sûre, une coverage insuffisante ou un gap encore ouvert reste terminal. Le Worker ne respawn jamais lui-même une source Transport.
Un inventaire privé `source_key -> latest processing/source state`, borné à 32 entrées, agrège la projection run-local. La frontier agrégée reste conservative : elle n'expose un `processing_frontier_slot` que lorsque toutes les sources en possèdent un, choisit le minimum des frontiers connus et le plus ancien pending. Les sources reference-bearing partagent en plus un registre global d'hydration borné : une même clé `(network, signature, commitment)` ne déclenche qu'un leader HTTP, puis chaque signal source conserve sa propre provenance lors de la finalisation. Un inventaire privé `source_key -> latest processing/source state`, borné à 32 entrées, agrège la projection run-local. La frontier agrégée reste conservative : elle n'expose un `processing_frontier_slot` que lorsque toutes les sources en possèdent un, choisit le minimum des frontiers connus et le plus ancien pending. Les sources reference-bearing partagent en plus un registre global d'hydration borné : une même clé `(network, signature, commitment)` ne déclenche qu'un leader HTTP, puis chaque signal source conserve sa propre provenance lors de la finalisation.
@@ -187,6 +187,8 @@ Les signaux partageant le même `(network, signature, commitment)` sont coalesc
Les retries/reroutages HTTP appartiennent à `ksp-onchain-transport-lib`. Le Worker ne possède pas une seconde boucle de retry autour de `getTransaction`. Les retries/reroutages HTTP appartiennent à `ksp-onchain-transport-lib`. Le Worker ne possède pas une seconde boucle de retry autour de `getTransaction`.
Le trafic nominal et le trafic de réparation partagent le même registre global d'hydration, les mêmes permits, la même admission et la même persistence. Un gate de fairness privé alterne les deux classes lorsqu'elles attendent simultanément, sans réserver une fraction fixe de capacité ; une capacité existante de `1` doit donc encore permettre la progression des deux classes.
## Processing frontier run-local ## Processing frontier run-local
Le snapshot expose : Le snapshot expose :
@@ -209,11 +211,41 @@ getTransaction -> Available puis ingress envoyé avec succès vers l'admission c
Un `BlockMeta` ou `Slot` continuity-only est settled localement sans produire de RAW. La frontier n'avance jamais à travers le plus ancien pending connu. Un `BlockMeta` ou `Slot` continuity-only est settled localement sans produire de RAW. La frontier n'avance jamais à travers le plus ancien pending connu.
## Reconnect, replay et continuité ## Reconnect, replay, gaps et réparation run-local
Le reconnect/replay Yellowstone appartient à Transport. Le Worker n'écrit pas `from_slot` et n'interprète pas directement `SubscribeReplayInfo`. Le reconnect/replay Yellowstone appartient à Transport. Le Worker n'écrit pas `from_slot`, ne traite pas directement `SubscribeReplayInfo` et ne transforme jamais une simple reconnexion en preuve de continuité.
Le snapshot Worker projette uniquement des informations sûres et source-neutral : Le Worker maintient séparément la processing frontier et une continuity frontier gap-aware. Les gaps sont des intervalles inclusifs bornés du run courant ; ils ne constituent ni une campagne historique ni une liste présumée de transactions manquantes. Les bornes internes sont :
```text
open gaps <= 64
range d'un gap <= 4096 slots
discovery HTTP par fenêtre <= 512 slots
getBlock logiques concurrents <= 4
repair actif simultané <= 1
```
Les mécanismes admissibles restent conservatifs : replay Transport lorsqu'il est réellement adressable, preuve de coverage d'une autre source compatible, scan HTTP borné, récupération de bloc produit et hydration d'une référence connue. Une réponse `getTransaction = null` reste une obligation manquante et `getBlock = null` pour un slot prouvé produit ne devient jamais une preuve d'absence.
Les types publics source-neutral `RawTransactionIngestGapId`, `RawTransactionIngestGapState`, `RawTransactionIngestGapReason`, `RawTransactionIngestRepairMethod` et `RawTransactionIngestGapSnapshot` permettent d'observer les gaps sans exposer `source_key`, provider, endpoint, filtre, signature ou payload. Le snapshot concret expose notamment :
```text
gaps()
open_gap_count()
repairing_gap_count()
repaired_gap_total()
unresolved_gap_total()
replay_repair_total()
redundant_coverage_repair_total()
http_scan_repair_total()
repair_block_fetch_total()
repair_transaction_hydration_total()
oldest_open_gap_start_slot()
```
La liste détaillée reste bornée ; tous les gaps ouverts sont retenus et les entrées réparées récentes peuvent occuper la capacité restante. Les compteurs utilisent une arithmétique checked.
Le snapshot conserve également les informations source-neutral suivantes :
```text ```text
source_total source_total
@@ -228,21 +260,11 @@ source_replay_attempt_total
source_continuity_gap_total source_continuity_gap_total
``` ```
Les quatre comptes de sources sont des gauges latest-value et ne contiennent aucune identité de source. `source_total` reste le nombre de sources logiques configurées pour le run. Tant que toutes les sources attendues ne sont pas `Active`, la health publique reste conservative : un reconnect transitoire projette `Degraded`, une source `Failed` projette `Unhealthy`, et le retour de toutes les sources attendues à `Active` permet de revenir à `Healthy`. `RawTransactionIngestSourceState` distingue `Active`, `Reconnecting`, `Closing`, `Closed` et `Failed`. Un replay attempt, une redelivery de frontière et une coverage d'intervalle restent des preuves différentes.
`RawTransactionIngestSourceState` distingue : La health publique est volontairement stricte dès que la policy de continuité est active : reconnect en cours, gap ouvert, continuity frontier différente de la processing frontier ou `TargetCoverage` futur non couvert donnent `Unhealthy`. `Healthy` exige toutes les sources attendues actives et aucune lacune de continuité. `Degraded` n'est permis qu'après perte de source explicitement réconciliée, lorsque les sources restantes couvrent encore tout le `TargetCoverage` futur.
```text Une source perdue peut donc rester absente uniquement si sa perte est bornée, si ses gaps sont fermés, si la continuity frontier rejoint la processing frontier et si la coverage future reste prouvée. Dans tous les autres cas, le Worker fault avec une erreur source sûre. Il ne lance jamais `ksp-job-backfill-lib` ni une campagne historique automatique.
Active
Reconnecting
Closing
Closed
Failed
```
Un replay attempt n'est pas une preuve de replay réussi ni de continuité parfaite. Si Transport augmente son compteur de continuity gap parce que la borne de rétention prouve que le slot demandé n'est plus rejouable, le Worker classe la source en failure et termine avec `worker_raw_transaction_ingest.source_failed`.
Le Worker ne lance alors ni Job Backfill ni campagne historique automatique.
## Persistence Store ## Persistence Store

View File

@@ -1,5 +1,5 @@
<!-- file: crates/ksp-worker-raw-transaction-ingest-lib/USAGE.md --> <!-- file: crates/ksp-worker-raw-transaction-ingest-lib/USAGE.md -->
<!-- version: 11 --> <!-- version: 12 -->
# Utilisation de ksp-worker-raw-transaction-ingest-lib # Utilisation de ksp-worker-raw-transaction-ingest-lib
@@ -117,7 +117,7 @@ if let std::result::Result::Err(error) = resources.try_push_http_block_polling_s
} }
``` ```
La validation est transactionnelle à chaque ajout : limite globale 32, réseau unique et `source_key` logique unique. Au démarrage, toutes les sources présentes sont supervisées ensemble. La défaillance d'une source est terminale pour le Worker ; les autres sources sont arrêtées et jointes, car le Worker ne suppose pas qu'elles couvrent les mêmes filtres ou le même univers de transactions. La validation est transactionnelle à chaque ajout : limite globale 32, réseau unique et `source_key` logique unique. Au démarrage, toutes les sources présentes sont supervisées ensemble. Une défaillance de source ne permet la continuation des siblings que lorsqu'une plage de perte sûre est disponible, que cette perte est entièrement réconciliée et que les sources encore actives prouvent tout le `TargetCoverage` futur. Sinon le Worker arrête et joint les autres sources. Aucune équivalence n'est déduite du seul provider, protocole ou nom de filtre.
### Source Standard Logs productive ### Source Standard Logs productive
@@ -331,6 +331,12 @@ let backpressure = snapshot.backpressure_wait_total();
let reconnects = snapshot.source_reconnect_total(); let reconnects = snapshot.source_reconnect_total();
let replay_attempts = snapshot.source_replay_attempt_total(); let replay_attempts = snapshot.source_replay_attempt_total();
let proven_gaps = snapshot.source_continuity_gap_total(); let proven_gaps = snapshot.source_continuity_gap_total();
let gaps = snapshot.gaps();
let open_gaps = snapshot.open_gap_count();
let repairing_gaps = snapshot.repairing_gap_count();
let repaired_gaps = snapshot.repaired_gap_total();
let unresolved_gaps = snapshot.unresolved_gap_total();
let oldest_gap = snapshot.oldest_open_gap_start_slot();
``` ```
`admission_queue_depth()`, `in_flight_persistence()`, `hydration_pending()`, `source_total()`, `source_active()`, `source_reconnecting()` et `source_failed()` sont des gauges latest-value. Les compteurs cumulés et les agrégats multi-source ne wrapent ni ne saturent silencieusement ; l'épuisement est terminal avec `worker_raw_transaction_ingest.counter_exhausted`. `admission_queue_depth()`, `in_flight_persistence()`, `hydration_pending()`, `source_total()`, `source_active()`, `source_reconnecting()` et `source_failed()` sont des gauges latest-value. Les compteurs cumulés et les agrégats multi-source ne wrapent ni ne saturent silencieusement ; l'épuisement est terminal avec `worker_raw_transaction_ingest.counter_exhausted`.
@@ -354,7 +360,7 @@ Un `Missing` HTTP règle le signal du point de vue source-processing sans créer
`source_state()` peut retourner `Active`, `Reconnecting`, `Closing`, `Closed` ou `Failed` comme état agrégé source-neutral. Les gauges `source_total()`, `source_active()`, `source_reconnecting()` et `source_failed()` permettent d'interpréter une composition multi-source sans exposer provider, endpoint, filtre ou `source_key`. `source_state()` peut retourner `Active`, `Reconnecting`, `Closing`, `Closed` ou `Failed` comme état agrégé source-neutral. Les gauges `source_total()`, `source_active()`, `source_reconnecting()` et `source_failed()` permettent d'interpréter une composition multi-source sans exposer provider, endpoint, filtre ou `source_key`.
La health commune est conservative : pendant `Running`, au moins une source `Failed` donne `Unhealthy`; au moins une source `Reconnecting`, ou une composition dont toutes les sources attendues ne sont pas encore `Active`, donne `Degraded`; toutes les sources attendues `Active` permettent `Healthy`. Une transition Worker `Faulted` reste `Unhealthy`. Lorsque la policy de continuité est active, la health commune est plus stricte qu'une simple lecture des états source. Pendant `Running`, reconnect en cours, gap ouvert, continuity frontier différente de la processing frontier ou `TargetCoverage` futur non couvert donnent `Unhealthy`. Toutes les sources attendues `Active` avec continuité réconciliée permettent `Healthy`. Une source `Failed` ne donne `Degraded` que si sa perte est entièrement réconciliée et si les sources restantes couvrent encore tout le `TargetCoverage` futur. Une transition Worker `Faulted` reste `Unhealthy`.
Les compteurs ont des sémantiques distinctes : Les compteurs ont des sémantiques distinctes :
@@ -366,7 +372,9 @@ source_continuity_gap_total gaps de rétention prouvés par Transport
Une tentative de replay n'est pas une preuve de continuité. Le Worker ne choisit pas `from_slot` et ne traite pas directement `SubscribeReplayInfo` ; ces mécanismes appartiennent à Transport. Une tentative de replay n'est pas une preuve de continuité. Le Worker ne choisit pas `from_slot` et ne traite pas directement `SubscribeReplayInfo` ; ces mécanismes appartiennent à Transport.
Si `source_continuity_gap_total` augmente, le Worker fault avec `worker_raw_transaction_ingest.source_failed`. Il ne déclenche pas automatiquement `ksp-job-backfill-lib`. Un gap est projeté via `gaps()` avec un état `Pending`, `Repairing`, `Repaired` ou `Unresolved`, une raison source-neutral et éventuellement la dernière méthode de réparation. Les mécanismes publics décrits par `RawTransactionIngestRepairMethod` sont `Replay`, `RedundantCoverage`, `HttpScan`, `BlockFetch` et `TransactionHydration`.
Une perte source ou un gap de rétention ne déclenche jamais `ksp-job-backfill-lib`. Le Worker continue seulement lorsqu'il peut prouver la réconciliation passée et la coverage future dans les bornes du run courant ; sinon il fault.
## Demander un stop et attendre le terminal ## Demander un stop et attendre le terminal

194
deltas/0.3.14/pre.015.md Normal file
View File

@@ -0,0 +1,194 @@
<!-- file: deltas/0.3.14/pre.015.md -->
<!-- version: 1 -->
# Delta `0.3.14-pre.015` — réconciliation documentaire
## 1. Base requise
```text
0.3.14-pre.014
workspace.package.version = 0.3.14-pre.14
```
Le gate opérateur communiqué le **12 septembre 2026** sur `pre.014` est vert pour toutes les commandes déterministes exécutées. Le workspace complet totalise `1931` tests passés, `0` échec et `15` ignored ; les deux smokes keyless HTTP/WebSocket Devnet passent chacun `1/1` lorsqu'ils sont exécutés explicitement avec `--ignored`.
## 2. Objectif
`pre.015` réconcilie la documentation durable avec l'état réellement livré par `0.3.14`.
Cette tranche ne change aucun comportement runtime. Elle corrige notamment les descriptions héritées de `0.3.13` qui affirmaient encore qu'une perte de source ou un gap de rétention provoquait systématiquement un fault immédiat, alors que `0.3.14` autorise désormais une continuation uniquement sous preuves de réconciliation passée et de `TargetCoverage` futur.
Conformément au forecast, `CHANGELOG.md`, `ROADMAP.md` et le prompt de la version suivante restent hors de cette tranche et sont réservés à `pre.016`.
## 3. Version workspace
Cette prerelease non-fix synchronise Cargo conformément à `VER-ID-009` :
```text
0.3.14-pre.14
->
0.3.14-pre.15
```
Le header racine de `Cargo.toml` passe de `590` à `591`.
## 4. Documentation Worker réconciliée
`crates/ksp-worker-raw-transaction-ingest-lib/README.md` et `USAGE.md` documentent désormais l'état `0.3.14` :
```text
processing frontier != continuity frontier
gaps run-local inclusifs et bornés
TargetCoverage conservative
replay Transport != coverage d'intervalle
coverage redondante uniquement par preuve structurale
scan HTTP / block fetch / transaction hydration bornés
source-loss continuation uniquement après réconciliation complète
health gap-aware et future-coverage-aware
fairness nominal/repair sur les mêmes ressources
snapshots publics gap/repair source-neutral
aucun Worker -> Job Backfill
aucun checkpoint ou historique caller-paramétrable
```
Les bornes documentées restent :
```text
open gaps <= 64
range <= 4096 slots
discovery HTTP <= 512 slots par fenêtre
getBlock logiques concurrents <= 4
repair actif simultané <= 1
```
## 5. Architectures réconciliées
Les documents réellement affectés sont alignés :
```text
docs/architecture/004-COMPONENT_INVENTORY.md
Worker RAW étendu jusqu'à 0.3.14
docs/architecture/005-DEPENDENCY_GRAPH.md
dépendances inchangées ; continuité/coverage/repair final documenté
docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md
cinq familles live + séparation Worker/Backfill conservée
source-loss non terminale uniquement sous preuves explicites
docs/architecture/011-RAW_TRANSACTION_ACQUISITION.md
état Worker après 0.3.14
réconciliation run-local et reports actualisés
```
Aucune nouvelle dépendance d'architecture n'est introduite.
## 6. Plans et validation réconciliés
`docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md` remplace le placeholder `0.3.14` par son rôle réellement livré : gap repair / continuité run-local multi-source + observabilité/hardening.
`docs/plans/035-V0_3_14_MULTI_SOURCE_GAP_REPAIR_HARDENING_PLAN.md` enregistre le forecast effectivement exécuté de `pre.001` à `pre.015`, les bornes finales et l'absence d'expansion EARLY/provider/historique.
`docs/validation/031-V0_3_14_MULTI_SOURCE_GAP_REPAIR_HARDENING.md` enregistre le gate final `pre.014` et les smokes keyless réellement exécutés.
## 7. Gate opérateur `pre.014` enregistré
```text
cargo fmt --all : PASS
cargo fmt --all -- --check : PASS
General Rust rule audit : clean
Rust export completeness audit : 0 candidate(s)
KSP workspace Rust rule audit : clean
Markdown table audit : clean (340 tables / 882 files)
cargo check --workspace : PASS
cargo clippy --workspace --all-targets --all-features -- -D warnings : PASS
cargo test --workspace --all-targets --all-features : PASS
workspace tests : 1931 passed / 0 failed / 15 ignored
cargo tree -p ksp-worker-raw-transaction-ingest-lib --edges normal : exécuté
cargo tree -p ksp-worker-raw-transaction-ingest-lib -e features : exécuté
cargo tree --duplicates : exécuté
HTTP Devnet smoke explicite : 1 passed / 0 failed
WebSocket Devnet smoke explicite : 1 passed / 0 failed
```
Les smokes OrbitFlare/PublicNode Yellowstone, Helius transactionSubscribe, PostgreSQL live et Worker repair -> Store live restent explicitement `NON EXÉCUTÉ` sans environnement/credential provisionné.
## 8. Fichiers ajoutés
```text
deltas/0.3.14/pre.015.md
```
## 9. Fichiers modifiés
```text
Cargo.toml
crates/ksp-worker-raw-transaction-ingest-lib/README.md
crates/ksp-worker-raw-transaction-ingest-lib/USAGE.md
docs/architecture/004-COMPONENT_INVENTORY.md
docs/architecture/005-DEPENDENCY_GRAPH.md
docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md
docs/architecture/011-RAW_TRANSACTION_ACQUISITION.md
docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md
docs/plans/035-V0_3_14_MULTI_SOURCE_GAP_REPAIR_HARDENING_PLAN.md
docs/validation/031-V0_3_14_MULTI_SOURCE_GAP_REPAIR_HARDENING.md
```
## 10. Fichiers supprimés
```text
aucun
```
## 11. Surfaces explicitement inchangées
```text
CHANGELOG.md
ROADMAP.md
README.md racine
RULES.md
prompts/**
config/**
crates/**/src/**
crates/**/tests/**
crates/**/unit_tests/**
Cargo.toml de crates
features/dépendances
schemas/migrations
```
Aucun delta publié antérieur n'est modifié.
## 12. Validations exécutées localement
Sur l'état exact `pre.015` avant packaging :
```text
General Rust rule audit : clean
Rust export completeness audit : 0 candidate(s)
KSP workspace Rust rule audit : clean
Markdown table audit : clean (340 tables / 883 files)
diff pre.014 -> pre.015 : 1 ajout / 10 modifications / 0 suppression
Cargo.toml : hors header, seule workspace.package.version change
CHANGELOG.md : byte-identique à pre.014
ROADMAP.md : byte-identique à pre.014
prompts/** : byte-identiques à pre.014
aucun fichier Rust/test/config/schema/migration/manifest de crate modifié
```
Le toolchain Cargo/Rustfmt n'est pas disponible dans l'environnement d'assemblage ; aucun nouveau PASS Cargo post-bump n'est revendiqué localement.
Le gate opérateur `pre.014` reste la preuve technique précédente ; un gate minimal `pre.015` est demandé après application pour confirmer le bump/documentation exacts.
## 13. Décisions prises
- `0.3.14` est techniquement fermé par le gate `pre.014` et documentairement réconcilié par `pre.015` ;
- les cinq familles live restent inchangées ; `0.3.14` durcit leur continuité dans le run actif ;
- reconnect, replay natif et retries réseau restent Transport-owned ;
- le Worker ne lance jamais de Job Backfill et ne reçoit aucune campagne historique caller-paramétrable ;
- une source perdue ne peut rester absente que sous réconciliation passée complète et coverage future prouvée ;
- les détails de `0.3.15`, le prochain prompt, CHANGELOG et ROADMAP sont différés à `pre.016`.
## 14. Questions ouvertes
Aucune question ouverte bloquante pour `pre.015`.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/004-COMPONENT_INVENTORY.md --> <!-- file: docs/architecture/004-COMPONENT_INVENTORY.md -->
<!-- version: 40 --> <!-- version: 41 -->
# Inventaire initial des composants KSP # Inventaire initial des composants KSP
@@ -46,7 +46,7 @@ Ce document maintient l'inventaire synthétique des composants retenus ou presse
| Store Desk | `ksp-app-store-desk` | app | Implémenté | `0.3.8` | inspection RAW read-only Transaction/Account/Observation via façade Store | | Store Desk | `ksp-app-store-desk` | app | Implémenté | `0.3.8` | inspection RAW read-only Transaction/Account/Observation via façade Store |
| RAW transaction common | `ksp-raw-transaction-lib` | lib | Implémenté | `0.3.10` | canonicalisation/wire RAW Transaction v1 source-neutral partagé entre producteurs | | RAW transaction common | `ksp-raw-transaction-lib` | lib | Implémenté | `0.3.10` | canonicalisation/wire RAW Transaction v1 source-neutral partagé entre producteurs |
| Worker lifecycle | `ksp-worker-api` | API | Implémenté | `0.3.9` | lifecycle/health/progression génériques des services continus | | Worker lifecycle | `ksp-worker-api` | API | Implémenté | `0.3.9` | lifecycle/health/progression génériques des services continus |
| RAW transaction worker | `ksp-worker-raw-transaction-ingest-lib` | worker/lib | Implémenté | `0.3.11``0.3.13` | fondation + 5 familles live, convergence multi-source, fairness, health et shutdown bornés | | RAW transaction worker | `ksp-worker-raw-transaction-ingest-lib` | worker/lib | Implémenté | `0.3.11``0.3.14` | 5 familles live + gaps/coverage/repair run-local, fairness, health et shutdown bornés |
| RAW ingest Desk | `ksp-app-raw-transaction-ingest-desk` | app | Retenu | `0.3.15` | choix/supervision dune ou plusieurs sources/méthodes sans réimplémenter le worker | | RAW ingest Desk | `ksp-app-raw-transaction-ingest-desk` | app | Retenu | `0.3.15` | choix/supervision dune ou plusieurs sources/méthodes sans réimplémenter le worker |
| STRUCTURAL job | nom à fixer | job/lib | Retenu | couche STRUCTURAL | normalisation Solana générique RAW -> STRUCTURAL bornée/rejouable | | STRUCTURAL job | nom à fixer | job/lib | Retenu | couche STRUCTURAL | normalisation Solana générique RAW -> STRUCTURAL bornée/rejouable |
| STRUCTURAL worker | nom à fixer | worker/lib | Retenu | fin couche STRUCTURAL | backlog RAW -> STRUCTURAL continu | | STRUCTURAL worker | nom à fixer | worker/lib | Retenu | fin couche STRUCTURAL | backlog RAW -> STRUCTURAL continu |

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/005-DEPENDENCY_GRAPH.md --> <!-- file: docs/architecture/005-DEPENDENCY_GRAPH.md -->
<!-- version: 29 --> <!-- version: 30 -->
# Graphe de dépendances KSP # Graphe de dépendances KSP
@@ -433,9 +433,9 @@ ksp-worker-control-lib # composant retenu, non matérialis
-> ksp-core-lib -> ksp-core-lib
``` ```
`ksp-worker-api` est ouvert en `0.3.9` comme contrat générique de services continus et ne connaît ni Solana, ni Transport, ni Store, ni Tauri. `ksp-worker-raw-transaction-ingest-lib` est son premier consumer concret : sa fondation `0.3.11` possède admission/persistence/snapshots/shutdown ; `0.3.12` ouvre la première verticale Yellowstone + hydration HTTP ; `0.3.13` matérialise la composition live multi-source. Config et le backend physique restent hors du Worker. `ksp-worker-api` est ouvert en `0.3.9` comme contrat générique de services continus et ne connaît ni Solana, ni Transport, ni Store, ni Tauri. `ksp-worker-raw-transaction-ingest-lib` est son premier consumer concret : sa fondation `0.3.11` possède admission/persistence/snapshots/shutdown ; `0.3.12` ouvre la première verticale Yellowstone + hydration HTTP ; `0.3.13` matérialise la composition live multi-source ; `0.3.14` ferme la continuité run-local par gaps bornés, preuves de coverage, repair conservatif, health gap-aware et shutdown/fairness durcis. Config et le backend physique restent hors du Worker.
La verticale actuelle n'est ni « un worker WebSocket » ni un moteur historique : `RawTransactionIngestRuntimeResources` contient de `1` à `32` sources logiques validées d'un même réseau parmi cinq familles — Yellowstone, Standard WS `logsSubscribe`, Standard WS `blockSubscribe`, Helius `transactionSubscribe` et HTTP live block polling. Yellowstone, Standard Logs et Helius convergent vers une registry globale d'hydration HTTP `getTransaction`; Standard Block et HTTP Block Polling qualifient directement le wire Base64 Legacy/V0/V1 vers Common RAW. Toutes les acquisitions rejoignent la même admission/persistence, la convergence canonique `(network, signature)` et des observations distinctes par provenance. Reconnect, `from_slot` et `SubscribeReplayInfo` restent propriétaires de Transport ; le Worker observe leur projection sûre, conserve une processing frontier run-local, applique des bornes/fairness globales et fault sur un gap de rétention prouvé sans appeler le Job Backfill. La verticale actuelle n'est ni « un worker WebSocket » ni un moteur historique : `RawTransactionIngestRuntimeResources` contient de `1` à `32` sources logiques validées d'un même réseau parmi cinq familles — Yellowstone, Standard WS `logsSubscribe`, Standard WS `blockSubscribe`, Helius `transactionSubscribe` et HTTP live block polling. Yellowstone, Standard Logs et Helius convergent vers une registry globale d'hydration HTTP `getTransaction`; Standard Block et HTTP Block Polling qualifient directement le wire Base64 Legacy/V0/V1 vers Common RAW. Toutes les acquisitions rejoignent la même admission/persistence, la convergence canonique `(network, signature)` et des observations distinctes par provenance. Reconnect, `from_slot`, replay natif et retries réseau restent propriétaires de Transport. Le Worker observe leurs preuves sûres, maintient processing/continuity frontiers distinctes, réconcilie uniquement des gaps du run courant avec coverage explicite et mécanismes bornés, et n'appelle jamais le Job Backfill. Une source perdue ne peut rester absente que si sa perte passée est réconciliée et si les sources restantes prouvent encore tout le `TargetCoverage` futur.
RAW worker puis STRUCTURAL worker sont introduits à la fin de leur couche respective, lorsque persistence/backlog sont disponibles. Le traitement RAW -> STRUCTURAL borné est porté par un STRUCTURAL job distinct du service continu. Les workers DECODED/DOMAIN sont introduits avec les groupes Program concernés plutôt que tous anticipés en bloc. RAW worker puis STRUCTURAL worker sont introduits à la fin de leur couche respective, lorsque persistence/backlog sont disponibles. Le traitement RAW -> STRUCTURAL borné est porté par un STRUCTURAL job distinct du service continu. Les workers DECODED/DOMAIN sont introduits avec les groupes Program concernés plutôt que tous anticipés en bloc.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md --> <!-- file: docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md -->
<!-- version: 19 --> <!-- version: 20 -->
# Acquisition, workers, jobs et pipelines spécialisés # Acquisition, workers, jobs et pipelines spécialisés
@@ -131,9 +131,9 @@ normalisation RawTransaction commune
ksp-store-lib ksp-store-lib
``` ```
Le modèle général autorise des stratégies alternatives, complémentaires ou redondantes, mais la verticale productive actuelle est volontairement plus étroite : **une** source Yellowstone + **une** voie HTTP d'hydration. Ce choix n'inscrit pas le provider ou le protocole dans l'identité RAW et ne ferme pas l'architecture future multi-source. La verticale productive accepte désormais de `1` à `32` sources logiques d'un même réseau parmi cinq familles : Yellowstone, Standard WS `logsSubscribe`, Standard WS `blockSubscribe`, Helius `transactionSubscribe` et HTTP live block polling. Ces sources peuvent être complémentaires ou redondantes, mais aucune équivalence n'est supposée par le seul provider/protocole : la convergence canonique reste `(network, signature)` et la coverage utilise des scopes structuraux explicites.
Le reconnect/replay du stream est une capacité Transport. Le Worker conserve une processing frontier run-local sur le travail réellement observé, projette `Active/Reconnecting/Closing/Closed/Failed` et des compteurs reconnect/replay/gap, mais ne possède ni checkpoint durable ni campagne de gap repair. Un gap de rétention prouvé par Transport devient un fault `source_failed` ; une récupération historique éventuelle reste une responsabilité séparée du Job Backfill. Le reconnect/replay du stream est une capacité Transport. Le Worker conserve une processing frontier run-local sur le travail réellement observé et une continuity frontier séparée, projette des gaps bornés et leurs méthodes de réparation, mais ne possède aucun checkpoint durable ni campagne historique. Un gap du run courant peut être réconcilié par replay Transport, coverage redondante prouvée, scan HTTP borné, block fetch ou hydration d'une référence connue. Une perte de source ne devient non terminale que si sa plage passée est entièrement réconciliée et si les sources restantes couvrent encore tout le `TargetCoverage` futur. Toute lacune non bornable/non couverte reste terminale ; aucune récupération n'appelle le Job Backfill.
#### Résultat de l'audit `0.3.9` #### Résultat de l'audit `0.3.9`

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/011-RAW_TRANSACTION_ACQUISITION.md --> <!-- file: docs/architecture/011-RAW_TRANSACTION_ACQUISITION.md -->
<!-- version: 14 --> <!-- version: 15 -->
# Acquisition et alimentation `RawTransaction` # Acquisition et alimentation `RawTransaction`
@@ -187,7 +187,7 @@ Yellowstone BlockMeta / Slot
-> continuité run-local uniquement -> continuité run-local uniquement
``` ```
La composition est caller-owned : le Worker ne lit pas Config et ne reçoit pas de secret. `RawTransactionIngestRuntimeResources` accepte de `1` à `32` sources logiques d'un même réseau, refuse les identités source dupliquées et supervise toutes les sources simultanément. Une faute source reste terminale pour le Worker faute d'équivalence de coverage prouvée. La composition est caller-owned : le Worker ne lit pas Config et ne reçoit pas de secret. `RawTransactionIngestRuntimeResources` accepte de `1` à `32` sources logiques d'un même réseau, refuse les identités source dupliquées et supervise toutes les sources simultanément. Une faute source n'autorise la continuation des siblings que lorsque sa plage de perte est sûre, que la coverage passée est réconciliée et que les sources restantes couvrent encore tout le `TargetCoverage` futur. Aucune équivalence n'est déduite du provider ou du protocole.
Il ne lance pas de campagne historique arbitraire. Il ne lance pas de campagne historique arbitraire.
@@ -204,17 +204,20 @@ Store durable = persistence des acquisitions admises
blockchain completeness = non prouvée par les métriques ci-dessus blockchain completeness = non prouvée par les métriques ci-dessus
``` ```
Une tentative de replay ne prouve ni succès ni continuité parfaite. Si Transport prouve qu'un slot demandé est antérieur à `first_available`, son compteur de continuity gap augmente ; le Worker projette ce gap puis termine avec un fault `source_failed`. Une tentative de replay ne prouve ni succès ni continuité parfaite. Si Transport prouve qu'un slot demandé est antérieur à `first_available`, son compteur de continuity gap augmente ; le Worker ouvre ou enrichit alors un gap run-local sans considérer la reconnexion comme une réparation.
Il n'existe pas de délégation automatique vers Backfill : La réconciliation reste bornée au run :
```text ```text
gap de rétention prouvé gap de continuité borné
-> Worker fault/stop -> replay Transport si preuve exploitable
-> aucun lancement de campagne historique -> coverage redondante structurale si prouvée
-> scan HTTP borné / getBlock / getTransaction selon capability
-> même Common RAW / admission / Store
-> Repaired ou Unresolved explicite
``` ```
Inversement, une demande telle que « récupère les transactions du programme X depuis le slot Y » reste une campagne `ksp-job-backfill-lib`. Il n'existe toujours aucune délégation automatique vers Backfill. Une demande telle que « récupère les transactions du programme X depuis le slot Y » reste une campagne `ksp-job-backfill-lib`, tandis qu'un gap non bornable ou non réconciliable du run courant fait fault le Worker.
### 3.4 Absence de relation Job ↔ Worker ### 3.4 Absence de relation Job ↔ Worker
@@ -734,7 +737,7 @@ RAW v1 complet -> hydration HTTP avant persistence
Cette qualification cross-source a préparé le contrat sans créer d'edge Common RAW -> Transport. L'extension Worker live utilise désormais cette décision conservative : Yellowstone produit des signaux structurés dans le Worker concret, puis HTTP `getTransaction` fournit le matériau RAW complet avant canonicalisation. Common RAW reste entièrement Transport-neutral. Cette qualification cross-source a préparé le contrat sans créer d'edge Common RAW -> Transport. L'extension Worker live utilise désormais cette décision conservative : Yellowstone produit des signaux structurés dans le Worker concret, puis HTTP `getTransaction` fournit le matériau RAW complet avant canonicalisation. Common RAW reste entièrement Transport-neutral.
## 14. État du Worker live après `0.3.13` ## 14. État du Worker live après `0.3.14`
### 14.0 Verticale matérialisée ### 14.0 Verticale matérialisée
@@ -756,11 +759,14 @@ convergence canonique par (network, signature) + disagreement explicite
persistence atomique via ksp-store-lib en mode Normal + observations supplémentaires idempotentes persistence atomique via ksp-store-lib en mode Normal + observations supplémentaires idempotentes
quotas pending/in-flight par source et bornes globales exactes quotas pending/in-flight par source et bornes globales exactes
fairness minimale / anti-starvation sous duplicate storm fairness minimale / anti-starvation sous duplicate storm
processing frontier run-local multi-source conservative processing frontier et continuity frontier run-local distinctes
ledger de gaps inclusifs bornés + TargetCoverage conservative
replay Transport / coverage redondante / scan HTTP / block fetch / hydration comme preuves distinctes
observabilité publique source-neutral des gaps, raisons, états, dernière méthode et compteurs checked
projection source-neutral Active/Reconnecting/Closing/Closed/Failed + gauges source_total/active/reconnecting/failed projection source-neutral Active/Reconnecting/Closing/Closed/Failed + gauges source_total/active/reconnecting/failed
observation des compteurs reconnect/replay/gap Transport health Healthy/Degraded/Unhealthy fondée sur gaps, frontiers et coverage présente/future
health conservative Healthy/Degraded/Unhealthy fairness nominal/repair sur les mêmes admission/hydration/persistence
fault sur gap de rétention prouvé source loss non terminale uniquement après réconciliation complète et coverage future prouvée
shutdown deadline + abort/join sans tâche orpheline ni late persistence shutdown deadline + abort/join sans tâche orpheline ni late persistence
``` ```
@@ -790,7 +796,8 @@ acquérir à partir du démarrage
normaliser et persister RawTransaction + observations normaliser et persister RawTransaction + observations
publier snapshots/notifications concrètes Worker publier snapshots/notifications concrètes Worker
laisser reconnect/from_slot/replay au Transport laisser reconnect/from_slot/replay au Transport
fault proprement lorsqu'un gap de rétention est prouvé réconcilier uniquement les gaps bornés du run courant avec des preuves de coverage explicites
fault proprement lorsqu'une lacune reste non bornable, non couverte ou unresolved
``` ```
Il ne doit pas : Il ne doit pas :
@@ -805,7 +812,7 @@ hardcoder un provider unique
### 14.2 Sources Worker V1 matérialisées et reports ### 14.2 Sources Worker V1 matérialisées et reports
Matérialisé dans `0.3.13` : Matérialisé dans `0.3.13` puis durci dans `0.3.14` :
```text ```text
Yellowstone transactions / blocks / status + HTTP hydration Yellowstone transactions / blocks / status + HTTP hydration
@@ -815,14 +822,18 @@ Helius transactionSubscribe Full + HTTP hydration
HTTP live block polling getSlot/getBlocksWithLimit/getBlock observed HTTP live block polling getSlot/getBlocksWithLimit/getBlock observed
HTTP hydration partagée et coalescée cross-source HTTP hydration partagée et coalescée cross-source
replay Yellowstone conservé propriétaire de Transport pour continuité du run replay Yellowstone conservé propriétaire de Transport pour continuité du run
gaps run-local bornés et continuity frontier distincte de la processing frontier
coverage exacte/superset conservative avec epochs prouvés
repair borné réutilisant Transport/Common RAW/admission/Store existants
source-loss continuation uniquement sous TargetCoverage prouvée
snapshots gap/repair source-neutral et health gap-aware
``` ```
Reste hors de cette verticale et nécessite une tranche dédiée : Reste hors de cette verticale et nécessite une tranche dédiée :
```text ```text
sources EARLY / pre-execution sources EARLY / pre-execution
coverage-equivalence ou failover non-terminal entre sources campagne historique multi-source ou caller-paramétrable
repair historique multi-source
Worker multi-source -> Store live E2E avec environnement complet provisionné Worker multi-source -> Store live E2E avec environnement complet provisionné
``` ```

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md --> <!-- file: docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md -->
<!-- version: 99 --> <!-- version: 100 -->
# Séquence des releases fonctionnelles KSP # Séquence des releases fonctionnelles KSP

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/035-V0_3_14_MULTI_SOURCE_GAP_REPAIR_HARDENING_PLAN.md --> <!-- file: docs/plans/035-V0_3_14_MULTI_SOURCE_GAP_REPAIR_HARDENING_PLAN.md -->
<!-- version: 3 --> <!-- version: 4 -->
# Plan v0.3.14 — gap repair / hardening multi-source du Worker RawTransaction # Plan v0.3.14 — gap repair / hardening multi-source du Worker RawTransaction
@@ -1058,3 +1058,41 @@ cargo check --workspace
Le toolchain Cargo n'est pas disponible dans l'environnement d'assemblage actuel. Les commandes Cargo post-bump restent donc `NON EXÉCUTÉ LOCAL` jusqu'au gate opérateur. Le toolchain Cargo n'est pas disponible dans l'environnement d'assemblage actuel. Les commandes Cargo post-bump restent donc `NON EXÉCUTÉ LOCAL` jusqu'au gate opérateur.
Les audits Python locaux et l'intégrité du delta sont exécutés avant livraison. Les audits Python locaux et l'intégrité du delta sont exécutés avant livraison.
## 27. Réconciliation d'implémentation `pre.015`
Le forecast `pre.001 -> pre.014` a été exécuté sans rescinder la release. L'état réellement obtenu est :
```text
pre.001 audit / sizing / threat model
pre.002 contrats gap/range/TargetCoverage
pre.003 observabilité de continuité WebSocket
pre.004 preuves replay Yellowstone attempt/delivery/coverage
pre.005 coverage redondante exacte/superset conservative
pre.006 discovery HTTP bornée
pre.007 known-reference hydration/missing obligation
pre.008 réconciliation + décision source-loss
pre.009 health gap-aware / future coverage
pre.010 fairness nominal/repair et partage des ressources
pre.011 snapshots publics gap/repair source-neutral
pre.012 races/shutdown/drain hardening
pre.013 completeness/security cross-layer
pre.014 gate technique workspace + smokes keyless
pre.015 réconciliation documentaire
```
Les bornes finales restent celles fixées dès les contrats `0.3.14` :
```text
MAX_OPEN_REPAIR_GAPS = 64
MAX_REPAIR_RANGE_SLOTS = 4096
MAX_REPAIR_DISCOVERY_WINDOW_SLOTS = 512
MAX_REPAIR_BLOCK_FETCH_IN_FLIGHT = 4
MAX_REPAIR_ACTIVE_GAPS = 1
```
La release n'a introduit ni EARLY, ni nouveau provider SDK, ni edge Worker -> Job Backfill, ni backend Store direct, ni retry réseau parallèle dans le Worker. Les cinq familles live `0.3.13` restent les seules familles productives ; `0.3.14` durcit leur continuité dans le run actif.
Le gate opérateur `pre.014` du 12 septembre 2026 ferme le critère technique déterministe : fmt/audits/check/Clippy sont verts, `cargo test --workspace --all-targets --all-features` totalise `1931` tests passés, `0` échec et `15` ignored, les trois commandes `cargo tree` prévues sont exécutées, et les deux smokes keyless HTTP/WS Devnet passent chacun `1/1`. Les smokes provider/resource-gated restent explicitement non revendiqués sans provisionnement.
`pre.015` ne change aucun comportement ; il aligne les README/USAGE et architectures sur cet état réellement livré. `CHANGELOG.md`, `ROADMAP.md` et le prompt de la version suivante restent réservés à `pre.016`.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/031-V0_3_14_MULTI_SOURCE_GAP_REPAIR_HARDENING.md --> <!-- file: docs/validation/031-V0_3_14_MULTI_SOURCE_GAP_REPAIR_HARDENING.md -->
<!-- version: 5 --> <!-- version: 6 -->
# Validation v0.3.14 — gap repair / hardening multi-source RawTransaction # Validation v0.3.14 — gap repair / hardening multi-source RawTransaction
@@ -715,3 +715,84 @@ Markdown table audit : clean (340 tables / 882 files)
Le toolchain Cargo/Rustfmt n'est pas disponible dans l'environnement d'assemblage. Aucun PASS Cargo post-bump n'est donc revendiqué localement. Le toolchain Cargo/Rustfmt n'est pas disponible dans l'environnement d'assemblage. Aucun PASS Cargo post-bump n'est donc revendiqué localement.
Le gate Cargo complet et les smokes live de `pre.014` restent `À EXÉCUTER` par l'opérateur avant `pre.015`. Le gate Cargo complet et les smokes live de `pre.014` restent `À EXÉCUTER` par l'opérateur avant `pre.015`.
## 26. Gate opérateur final de `pre.014`
Gate exécuté le **12 septembre 2026 à 21:07 +02:00** sur `workspace.package.version = 0.3.14-pre.14` :
```text
cargo fmt --all : PASS
cargo fmt --all -- --check : PASS
General Rust rule audit : clean
Rust export completeness audit : 0 candidate(s)
KSP workspace Rust rule audit : clean
Markdown table audit : clean (340 tables / 882 files)
cargo check --workspace : PASS
cargo clippy --workspace --all-targets --all-features -- -D warnings : PASS
cargo test --workspace --all-targets --all-features : PASS
workspace tests : 1931 passed / 0 failed / 15 ignored
cargo tree -p ksp-worker-raw-transaction-ingest-lib --edges normal : exécuté
cargo tree -p ksp-worker-raw-transaction-ingest-lib -e features : exécuté
cargo tree --duplicates : exécuté
```
L'arbre normal confirme que le Worker conserve les dépendances directes documentées :
```text
ksp-core-lib
ksp-logging-lib
ksp-onchain-transport-lib
ksp-raw-transaction-lib
ksp-store-lib
ksp-worker-api
sha2
tokio
```
La commande `cargo tree --duplicates` est un inventaire des duplications transitives du workspace, pas une exigence de zéro duplication ; son exécution n'a révélé aucune nouvelle dépendance directe introduite par `0.3.14`.
### 26.1 Smokes keyless réellement exécutés
HTTP Devnet :
```text
cargo test -p ksp-onchain-transport-lib --test transport_devnet_smoke -- --ignored --nocapture
1 passed / 0 failed
```
WebSocket Devnet :
```text
cargo test -p ksp-onchain-transport-lib --test websocket_devnet_smoke -- --ignored --nocapture
1 passed / 0 failed
```
Ces deux smokes prouvent les canaris Transport keyless accessibles. Ils ne constituent pas un smoke Worker -> Store end-to-end.
### 26.2 Non-claims finaux
Restent explicitement `NON EXÉCUTÉ` faute de provisionnement opérateur dans ce gate :
```text
OrbitFlare Yellowstone Devnet live/replay
PublicNode Yellowstone Mainnet/Testnet live/replay
Helius transactionSubscribe live
PostgreSQL live Store
Worker gap repair -> Store live end-to-end
```
Les tests ignored correspondants présents dans le workspace ne sont pas requalifiés en PASS.
## 27. Réconciliation documentaire `pre.015`
`pre.015` ne modifie aucun Rust, test, dépendance, feature, Config, schema ou comportement runtime. Elle réconcilie seulement les documents durables avec les preuves `0.3.14` effectivement livrées :
```text
README/USAGE Worker : source-loss conditionnel, gaps/repair, health et snapshots publics
architecture : composant/graph/Worker-vs-Job/RawTransaction acquisition
functional release sequence : rôle réel de 0.3.14
plan 035 : forecast exécuté et invariants finaux
validation 031 : gate workspace + smokes keyless réellement exécutés
```
`CHANGELOG.md`, `ROADMAP.md` et le prompt `0.3.15` restent volontairement inchangés jusqu'à `pre.016`.