v0.3.6-pre.009

This commit is contained in:
2026-09-01 16:04:58 +02:00
parent d89aee9910
commit b861a1e3b8
16 changed files with 1846 additions and 86 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/027-V0_3_6_JOB_API_BACKFILL_PLAN.md -->
<!-- version: 15 -->
<!-- version: 16 -->
# Plan v0.3.6 — Job API et premier backfill RAW
@@ -482,7 +482,7 @@ La tranche matérialise 29 tests unitaires et 8 canaries d'intégration au total
### `pre.008` — Concurrence, frontier et checkpoint
**Statut : réalisé ; corrigé par `pre.008-fix.001`, gate opérateur du fix à rejouer.**
**Statut : clôturé ; corrigé par `pre.008-fix.001`, gate opérateur du fix vert.**
Budget cible : **15-20 min**. Entrée : résultats Store typés et gate `pre.007` vert. La tranche ajoute `BackfillCheckpoint`, `BackfillExecutionBatch` et `execute_backfill_discovery`. Le checkpoint est opaque, caller-owned et validé contre `JobId` + fingerprint de scope ; aucune table ou persistance durable de Job n'est créée. `BackfillRequest::with_checkpoint` reste additif afin de préserver les constructeurs existants.
@@ -494,13 +494,17 @@ La reprise suit les quatre sémantiques figées : Latest repart de la vue couran
**Statut : matérialisé ; gate opérateur à rejouer.**
Le gate opérateur de `pre.008` confirme `cargo fmt`, les audits Rust/Markdown et `cargo check --workspace`, puis la compilation des targets de test échoue en `E0618`/`E0282` : dans `pre_008_checkpoint_is_bound_to_job_and_scope_fingerprint`, la variable locale `request` masque le helper homonyme avant la construction du second scope. Le fix renomme uniquement cette liaison locale en `primary_request` et synchronise ses usages ; aucun contrat, test, comportement runtime, checkpoint, dépendance ou feature ne change. Comme un fichier Rust est corrigé, la version workspace devient `0.3.6-pre.8.fix.1`. Les arbres Cargo de `pre.008` ont déjà été inspectés puisque cette tranche ajoutait `futures-util`; ils n'ont pas à être rejoués pour ce fix sans changement de graphe.
Le gate opérateur de `pre.008` confirme `cargo fmt`, les audits Rust/Markdown et `cargo check --workspace`, puis la compilation des targets de test échoue en `E0618`/`E0282` : dans `pre_008_checkpoint_is_bound_to_job_and_scope_fingerprint`, la variable locale `request` masque le helper homonyme avant la construction du second scope. Le fix renomme uniquement cette liaison locale en `primary_request` et synchronise ses usages ; aucun contrat, test, comportement runtime, checkpoint, dépendance ou feature ne change. Comme un fichier Rust est corrigé, la version workspace devient `0.3.6-pre.8.fix.1`. Le gate réduit du fix est ensuite intégralement vert : audits, `cargo check`, Clippy sans warning, 39 unitaires et 9 canaries d'intégration passent. Les arbres Cargo de `pre.008` avaient déjà été inspectés puisque cette tranche ajoutait `futures-util`; ils n'avaient pas à être rejoués pour ce fix sans changement de graphe.
### `pre.009` — Annulation et snapshots concrets
**Statut : planifié.**
**Statut : matérialisé ; gate opérateur à rejouer.**
Budget cible : **15-20 min**. Entrée : frontière prouvée. Intégrer annulation sur les phases critiques et progression Backfill latest-value. Sortie : courses terminales, drainage Store et listener lent couverts.
Budget cible : **15-20 min**. Entrée : frontière prouvée et gate `pre.008-fix.001` vert. La tranche matérialise `BackfillJobRuntime`, `BackfillJobHandle`, `BackfillJobSnapshot` et `BackfillSnapshotSource` comme runtime concret du vertical RAW transaction. `ksp-job-api` reste inchangée, passive et runtime-neutral ; Tokio devient uniquement un détail d'implémentation normal de `ksp-job-backfill-lib` (`macros` + `sync`) et aucun type Tokio n'est exposé dans la racine publique. Le canal concret est un `watch` latest-value O(1) : les progressions intermédiaires peuvent être coalescées, chaque listener possède son receiver cloné, et la dernière valeur terminale reste lisible tant que le handle/source existe.
L'annulation réutilise `JobCancellationToken` et ajoute un signal réveillable privé. Les attentes de découverte et d'hydratation pré-Store sont abandonnables ; une vérification supplémentaire intervient après hydratation et avant soumission Store. Dès que `persist_backfill_hydration` est appelée, l'écriture atomique n'est plus sélectionnée contre l'annulation : toute opération Store déjà soumise est drainée jusqu'à un résultat connu. L'exécuteur arrête ensuite les nouvelles admissions, draine l'in-flight et publie frontier/checkpoint sûrs. Une arbitration atomique sépare `ACTIVE`, demande d'annulation et états terminaux : une annulation acceptée avant la décision terminale gagne sur une complétion normale, une complétion déjà réclamée refuse l'annulation tardive, et une erreur fatale peut remplacer une annulation pendante afin de ne pas masquer un échec Transport/Store.
Le snapshot complet reste sûr : phase, catégorie de scope, borne de découverte, compteurs d'admission/fin, dispositions entité/observation, missing/conflits/annulations/trous, maximum in-flight, préfixe contigu, checkpoint et éventuel code d'erreur stable ; aucune URL, endpoint/provider, payload RAW ou message fournisseur n'y entre. La tranche matérialise 47 tests unitaires et 10 canaries d'intégration au total, dont listener lent/multi-listeners, rétention terminale, courses terminales, attente pré-Store longue, attente de page RPC pendante et drainage après annulation. Leur exécution Rust reste à confirmer par le gate opérateur. `pre.010` reste fermé au hardening et aux canaries externes.
### `pre.010` — Hardening et canaries externes

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/023-V0_3_6_JOB_API_BACKFILL.md -->
<!-- version: 15 -->
<!-- version: 16 -->
# Validation v0.3.6 — Job API et premier backfill RAW
@@ -90,7 +90,7 @@ Aucune entrée absolue, traversée, avec séparateur inversé ou lien symbolique
## 6. Notifications multi-listeners
`pre.003` fige le contrat public et ses canaries de resynchronisation. Les cases portant sur le stockage/réveil concret restent volontairement ouvertes jusqu'au producer `ksp-job-backfill-lib` ; un fake de test n'est pas traité comme preuve runtime de production.
`pre.003` fige le contrat public et ses canaries de resynchronisation. `pre.009` matérialise maintenant le producer concret `ksp-job-backfill-lib` avec un `tokio::sync::watch` privé, un handle clonable et des canaries latest-value ; leur gate Rust opérateur reste à rejouer, donc les critères comportementaux ci-dessous restent ouverts jusqu'à exécution.
- [ ] Stockage O(1) de la dernière valeur, sans historique non borné.
- [ ] Un listener lent ne bloque jamais le producteur.
@@ -106,14 +106,14 @@ Aucune entrée absolue, traversée, avec séparateur inversé ou lien symbolique
- [X] `LatestAddress`, `BeforeAddress`, `AfterAddress` et `ExplicitSignatures` couverts.
- [X] Adresse validée par le type Core existant.
- [ ] Signature Base58 décodée vers exactement 64 octets.
- [X] Signature Base58 décodée vers exactement 64 octets, prouvée par le gate `pre.006-fix.002`.
- [X] Engagement limité à `Confirmed` ou `Finalized`.
- [X] Taille de page entre 1 et 1 000.
- [X] Nombre de pages entre 1 et 10 000.
- [X] Nombre de candidats entre 1 et 10 000.
- [X] Concurrence d'hydratation entre 1 et 64.
- [X] `min_context_slot` transmis sans en changer le sens.
- [ ] Checkpoint rejeté si son JobId ou son fingerprint de scope diffère ; canarie corrigée par `pre.008-fix.001`, gate opérateur du fix à rejouer.
- [X] Checkpoint rejeté si son JobId ou son fingerprint de scope diffère ; canarie `pre.008-fix.001` exécutée avec succès.
- [X] Aucun défaut d'application silencieux dans la bibliothèque.
## 8. Pagination, ordre et déduplication
@@ -175,20 +175,22 @@ Aucune entrée absolue, traversée, avec séparateur inversé ou lien symbolique
## 12. Concurrence, frontière et checkpoint
`pre.008` matérialise un checkpoint opaque caller-owned, sans table Store ni promesse de reprise crash-safe. `BackfillRequest::with_checkpoint` valide `JobId` et fingerprint avant usage. L'exécuteur utilise une collection `FuturesUnordered` strictement bornée par `hydration_concurrency`, réconcilie les fins hors ordre par index stable et draine les futures déjà admises après la première erreur fatale. Le gate opérateur confirme format, audits et `cargo check`, mais la compilation des tests échoue en `E0618`/`E0282` parce qu'une liaison locale `request` masque le helper homonyme dans la canarie checkpoint. `pre.008-fix.001` renomme uniquement cette liaison en `primary_request`; le gate du fix reste à rejouer.
`pre.008` matérialise un checkpoint opaque caller-owned, sans table Store ni promesse de reprise crash-safe. `BackfillRequest::with_checkpoint` valide `JobId` et fingerprint avant usage. L'exécuteur utilise une collection `FuturesUnordered` strictement bornée par `hydration_concurrency`, réconcilie les fins hors ordre par index stable et draine les futures déjà admises après la première erreur fatale. Le gate initial révèle uniquement un shadowing de helper dans une canarie ; `pre.008-fix.001` le corrige sans changer le contrat. Le gate réduit du fix est intégralement vert : audits, `cargo check`, Clippy sans warning, 39 unitaires et 9 canaries d'intégration passent sur `0.3.6-pre.8.fix.1`.
- [ ] Nombre d'hydratations en vol borné par la requête.
- [ ] Aucune file de candidats ou notifications non bornée.
- [ ] Résultats hors ordre réconciliés par index stable.
- [ ] Frontière avance sur insert, already present et purged skip durables.
- [ ] Missing, conflit, conversion, Transport, Store et annulation créent un trou.
- [ ] Frontière ne saute jamais un trou même si des résultats ultérieurs terminent.
- [ ] Latest rejoue la vue courante de façon idempotente.
- [ ] Before reprend au curseur contigu.
- [ ] After et explicite rejouent le scope borné avec préfixe validé.
- [X] Nombre d'hydratations en vol borné par la requête, prouvé par `pre.008-fix.001`.
- [X] Aucune file de candidats non bornée dans l'exécuteur `pre.008`; les notifications concrètes restent à valider avec `pre.009`.
- [X] Résultats hors ordre réconciliés par index stable.
- [X] Frontière avance sur insert, already present et purged skip durables.
- [X] Missing, conflit, conversion, Transport et Store créent un trou ; la branche annulation est matérialisée dans `pre.009` et reste à exécuter.
- [X] Frontière ne saute jamais un trou même si des résultats ultérieurs terminent.
- [X] Latest rejoue la vue courante de façon idempotente.
- [X] Before reprend au curseur contigu.
- [X] After et explicite rejouent le scope borné avec préfixe validé.
## 13. Annulation et résultats terminaux
`pre.009` matérialise le runtime concret, le canal latest-value et les chemins d'annulation/drainage. Les canaries couvrent l'attente RPC de découverte, une future pré-Store longue, le drainage des candidats déjà admis, les listeners lents/indépendants, la rétention terminale et les arbitrations terminales ; le gate Rust opérateur reste à rejouer avant de cocher ces critères comportementaux.
- [ ] Annulation idempotente et état `Cancelling` observable.
- [ ] Admissions arrêtées après observation du token.
- [ ] Attente de page et hydratation RPC longues abandonnables.
@@ -204,10 +206,10 @@ Aucune entrée absolue, traversée, avec séparateur inversé ou lien symbolique
- [X] `ksp-job-api` dépend exactement de Core et n'a aucune feature, dev-dependency ou build-dependency.
- [X] `ksp-job-backfill-lib` ne dépend pas de Config, App, Wallet, Program, Interface ou backend Store ; `ksp-store-lib` est consommée avec `default-features = false`.
- [ ] Aucun retour de dépendance vers Job depuis les couches basses.
- [X] Versions/features auditées : aucune nouvelle version externe ; `sha2`, `futures-util` et `tokio` réutilisent les entrées workspace existantes. `futures-util` devient un détail normal privé de `pre.008`, Tokio reste dev-only.
- [X] Versions/features auditées : aucune nouvelle version externe ; `sha2`, `futures-util` et `tokio` réutilisent les entrées workspace existantes. `futures-util` reste un détail normal privé depuis `pre.008` et `pre.009` promeut Tokio en dépendance normale privée limitée à `macros` + `sync`; aucun type Tokio n'est exposé.
- [X] `pre.005` matérialise 11 tests unitaires et 6 canaries dintégration ; le gate opérateur les exécute tous avec succès.
- [X] `pre.006` matérialise 19 tests unitaires et 7 canaries dintégration ; le gate opérateur les exécute tous avec succès, avec uniquement le warning Clippy corrigé par `pre.006-fix.001`.
- [X] `cargo clippy --workspace --all-targets` warning-free sur `pre.007` ; `pre.008` atteint la compilation des tests puis échoue sur le shadowing corrigé par `pre.008-fix.001`.
- [X] `cargo clippy --workspace --all-targets` warning-free sur `pre.008-fix.001` avec 39 unitaires et 9 canaries vertes ; le gate `pre.009` reste à rejouer.
- [ ] `cargo fmt --all -- --check` vert.
- [X] `scripts/audit_rust_workspace_rules.py` vert sur `pre.005` dans l'environnement d'assemblage et dans le gate opérateur.
- [X] `scripts/audit_markdown_tables.py` vert sur `pre.005` dans le gate opérateur (264 tables / 147 fichiers, delta inclus).
@@ -219,7 +221,7 @@ Aucune entrée absolue, traversée, avec séparateur inversé ou lien symbolique
## 15. Preuves d'intégration et fermeture
- [X] Fake Transport et fake Store déterministes sans backend direct exécutés avec succès au gate `pre.007`; fake processor concurrent `pre.008` matérialisé, gate à rejouer.
- [X] Fake Transport et fake Store déterministes sans backend direct exécutés avec succès au gate `pre.007`; fake processor concurrent `pre.008-fix.001` exécuté avec succès.
- [ ] Vertical découverte, hydratation, conversion, persistance et observation couvert.
- [ ] Smoke Devnet plus PostgreSQL configuré exécuté si l'environnement explicite est disponible.
- [ ] Aucun endpoint payant, credential ou donnée sensible requis par les tests normaux.