v0.3.14-pre.008
This commit is contained in:
285
deltas/0.3.14/pre.008.md
Normal file
285
deltas/0.3.14/pre.008.md
Normal file
@@ -0,0 +1,285 @@
|
||||
<!-- file: deltas/0.3.14/pre.008.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# 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.
|
||||
Reference in New Issue
Block a user