# Delta `0.3.14-pre.008` — réconciliation et supervisor source-loss ## Base requise ```text 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 : ```text 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 : ```text 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` : ```text 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 : ```text 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 : ```text 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 : ```text 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 : ```text 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 : ```text 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 : ```text 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 : ```text 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 : ```text 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é ```text 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 ```text deltas/0.3.14/pre.008.md ``` ## Fichiers modifiés ```text 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 ```text aucun ``` ## Version Cargo Conformément à `VER-ID-009` : ```text 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 : ```text 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 ```text 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 ```text 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 ```text aucune pour cette tranche ``` ## Gate opérateur après application ```bash 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.