Files
khadhroony-solana-project/deltas/0.3.14/pre.008.md
2026-09-12 09:00:36 +02:00

9.9 KiB

Delta 0.3.14-pre.008 — réconciliation et supervisor source-loss

Base requise

0.3.14-pre.007-fix.001
workspace.package.version = 0.3.14-pre.7.fix.1
deltas/0.3.14/pre.007-fix.001.md présent

Gate de la base

Le gate opérateur de 0.3.14-pre.007-fix.001 est validé avant ouverture de cette tranche :

cargo fmt --all : PASS
cargo fmt --all -- --check : PASS
audit Rust workspace rules : PASS
audit Markdown tables : PASS
cargo check --workspace : PASS
cargo clippy --workspace --all-targets --all-features -- -D warnings : PASS
cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features : PASS

Le gate Worker comprend notamment :

133 unit tests : PASS
cross_layer_completeness : 8 PASS
dependency_boundary : 19 PASS
hardening : 32 PASS
public_api : 20 PASS
release_completeness : 9 PASS

Objectif

Implémenter strictement la tranche pre.008 du plan 035 :

unifier les preuves replay/redondance/discovery HTTP/hydration autour du ledger de continuité
maintenir un continuity frontier distinct du processing frontier
conserver les Missing known-reference comme gaps single-slot après libération du processing frontier
réconcilier les gaps uniquement depuis des coverage epochs réellement prouvés
remplacer la terminalité « first source failure » uniquement lorsqu'une TargetCoverage présente et future est explicitement prouvée
ne jamais respawn une source Transport depuis le Worker
rester fail-closed lorsque la plage de perte est non bornée ou qu'une preuve manque

Continuity frontier distinct du processing frontier

Le gap ledger calcule désormais un continuity_frontier à partir du processing frontier courant :

aucun gap ouvert <= processing frontier
    -> continuity frontier = processing frontier

gap ouvert commençant à S <= processing frontier
    -> continuity frontier = S - 1

gap ouvert commençant à 0
    -> aucun continuity frontier

Le processing frontier reste donc un indicateur de traitement et ne peut jamais, à lui seul, fermer une discontinuité historique.

Coverage epochs réellement prouvés

Le ledger pre.005 reçoit désormais les epochs produits pendant l'exécution.

La source HTTP Block Polling full-ledger enregistre un epoch uniquement lorsqu'une fenêtre bornée de pre.006 a été effectivement prouvée :

fenêtre discovery bornée
+ tous les blocs produits de la partie prouvée effectivement matérialisés
+ aucun getBlock observed = null bloquant la fenêtre
= coverage epoch admissible

Un epoch adjacent ou chevauchant du même source/scope/commitment est fusionné. L'enregistrement d'un nouvel epoch déclenche immédiatement une tentative de réconciliation des gaps déjà ouverts.

Aucune source filtrée n'obtient un epoch par sa simple présence ou sa configuration.

Missing known-reference raccordé au ledger

Le résultat Missing introduit en pre.007 devient un gap de continuité single-slot :

source_key exact
commitment exact
scope configuré exact de la source
range = [slot, slot]
reason = KnownReferenceMissing

Le pending de processing peut ensuite être soldé normalement. Le gap reste toutefois ouvert dans le ledger jusqu'à une preuve de coverage distincte.

Un epoch full-ledger d'une autre source couvrant ce slot peut donc réconcilier cette obligation sans inventer une observation de transaction et sans assimiler getTransaction = null à une absence prouvée.

Aucun second registre d'hydration, scheduler, semaphore ou pipeline n'est ajouté.

Source-loss bornée et supervisor

Les tâches source supervisées retournent désormais leur source_key avec leur résultat terminal. Les projections source existantes restent l'autorité pour déterminer les sources réellement Active au moment de la décision.

Les incidents WS déjà bornés en pre.003 transportent leurs bornes inclusives jusqu'au supervisor. Une perte classifiée et bornée est enregistrée comme gap selon le scope/commitment exacts de la source perdue.

Le supervisor peut continuer sans cette source uniquement si, après réconciliation :

aucun gap connu ne reste ouvert
continuity frontier == processing frontier
chaque requirement de TargetCoverage est couvert par au moins une source encore Active
la source perdue n'est pas utilisée comme source active de remplacement
les relations de scope restent celles de pre.005 : Exact ou Superset explicitement démontré
le commitment reste strictement identique

Sinon, la politique précédente reste fail-closed et les sources sœurs sont arrêtées puis jointes comme auparavant.

Pertes qui restent terminales

Cette tranche ne fabrique aucune plage lorsqu'elle n'est pas connue.

Restent donc terminales, entre autres :

source transport perdue sans borne de continuité sûre
replay Yellowstone dont la coverage reste non prouvée sans range sûr
fermeture configurée sans range historique démontré
join failure / task-set invariant
content conflict
persistence failure
counter/invariant exhaustion

Le simple fait qu'une autre source soit configurée ou Active ne constitue jamais une preuve historique de l'intervalle perdu.

Aucun respawn Worker

Le Worker ne recrée aucune source terminale. Transport conserve l'ownership de ses propres reconnect/replay mechanisms.

Après une décision Continue, le supervisor conserve uniquement les tâches sœurs déjà vivantes. La source perdue reste absente du run.

Les frontières historiques restent inchangées :

aucun set_from_slot dans Worker
aucun SubscribeReplayInfo dans Worker
aucun socket WebSocket/gRPC créé par Worker
aucun retry loop réseau Worker
aucun accès Config
aucun Job Backfill
aucun backend Store physique

Tests ajoutés

Les unit tests couvrent notamment :

continuity frontier bloqué par un gap puis rétabli après coverage epoch redondant
source-loss refusée si les sources actives ne couvrent plus toute TargetCoverage
source-loss refusée tant qu'un gap reste ouvert malgré une source future-capable
source HTTP full-ledger prouvée permettant la survie d'une source filtrée perdue sans respawn
seules les pertes classifiées entrent dans la décision de coverage
Missing known-reference transféré au continuity ledger sans bloquer le processing frontier
Missing single-slot réconcilié seulement après epoch full-ledger réellement prouvé par une autre source

Les canaris hardening et release_completeness vérifient en plus :

présence du continuity frontier privé
présence du gate TargetCoverage dans la décision source-loss
présence de record_known_reference_gap sur le chemin runtime Missing
aucune croissance de surface publique
aucun respawn source Worker
aucun ownership replay Transport déplacé vers Worker

Hors périmètre inchangé

aucune health policy Healthy/Degraded/Unhealthy/Faulted de pre.009
aucune fairness spécifique pendant réconciliation de pre.010
aucune observabilité publique détaillée des gaps de pre.011
aucun mécanisme EARLY/shred
aucun backfill historique caller-driven
aucune nouvelle source/provider

Fichiers ajoutés

deltas/0.3.14/pre.008.md

Fichiers modifiés

Cargo.toml
crates/ksp-worker-raw-transaction-ingest-lib/src/continuity.rs
crates/ksp-worker-raw-transaction-ingest-lib/src/lib.rs
crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs
crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs
crates/ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs
crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/continuity.rs
crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs

Fichiers supprimés

aucun

Version Cargo

Conformément à VER-ID-009 :

header Cargo.toml : 575 -> 576
workspace.package.version : 0.3.14-pre.7.fix.1 -> 0.3.14-pre.8

Versions des fichiers modifiés :

continuity.rs : 7 -> 8
lib.rs : 31 -> 32
runtime_resources.rs : 34 -> 35
unit_tests/continuity.rs : 5 -> 6
unit_tests/runtime_resources.rs : 28 -> 29
tests/hardening.rs : 31 -> 32
tests/release_completeness.rs : 26 -> 27

Validation exécutée dans l'environnement de préparation

python3 scripts/audit_rust_workspace_rules.py : PASS
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas : PASS
scan des frontières Worker/Transport/Backfill/Store : PASS
scan de la crate-root historique : PASS
comparaison exacte pre.007-fix.001 -> pre.008 : PASS

Les gates Cargo ne sont pas déclarés PASS dans l'environnement de préparation lorsqu'ils ne peuvent pas y être exécutés. Ils restent obligatoires côté opérateur avant pre.009.

Décisions prises

une source active n'est pas une preuve historique de coverage
les coverage epochs doivent provenir d'une observation réellement prouvée pendant le run
le processing frontier peut avancer avec un Missing, mais le continuity frontier reste bloqué par son gap
la continuation source-loss exige à la fois réconciliation historique et TargetCoverage future par les sources encore Active
les pertes sans range sûr restent fail-closed
aucun respawn Worker

Questions ouvertes

aucune pour cette tranche

Gate opérateur après application

cargo fmt --all
cargo fmt --all -- --check
python3 scripts/audit_rust_workspace_rules.py
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features

Prochaine tranche

pre.009 : appliquer la health policy multi-source Healthy / Degraded / Unhealthy / Faulted selon coverage présente et future, avec retour à Healthy seulement après source active et gaps fermés.