Plan dossier — CVN-N014-ED-S03 · Cleanup opportuniste large-data (borné)¶
Story : CVN-N014-ED-S03 (wp#244, GH #1107) · Epic : CVN-N014-ED · Dépend de : S01 (audit/flip, Closed) + S02 (s43 Route Y, Closed). Statut : plan — pour
plan_review. Standard : ADR-0101. Nature : cleanup opportuniste borné. S03 se ferme lorsque l'inventaire des workarounds large-data cross-pod est publié, vide, ses faux positifs justifiés, et les reliquats hérités de S01/S02 traités ou waivés. Les régressions futures ne maintiennent pas S03 ouverte : elles sont captées par le gate S04 et ouvrent une Story ciblée si besoin. (Pas de « Story rolling ouverte à vie ».)
Partie I — Cadrage (lecteur)¶
0. Problématisation (sans jargon)¶
Une fois le transport inter-tâches passé au standard (S01 : object-storage XCom ; S02 : s43 en pass-by-référence S3), il reste à vérifier qu'aucun DAG ne bricole encore son propre contournement pour les grosses données (chemins S3 écrits à la main, fichiers locaux, npz maison…), et à simplifier ceux qui restent au fil de l'eau — dans le même PR que la retouche, jamais en big-bang (strangler-fig). S03 publie l'inventaire, traite ce qui reste, puis ferme ; la prévention des réintroductions est portée par S04.
0bis. Les constats sur lesquels on construit (vérifiés)¶
- Le flip object-storage XCom est live (S01) ; s43 est S3-clean (S02, Route Y, prouvé cross-pod). Le seul payload tableau du parc est traité.
- Le parc est JSON-only (audit S01 : 129 sites, 0 numpy_suspect).
s43_ion'a qu'UN consumer (le DAG s43) —git grepdes appelspersist_predictions(store,prefix,…)/load_cohort_predictions(store,prefix,…)⇒dags/dag_diagnostic__s43.pyseul (lespersist_predictionsd'ablation_runner/persistence/regime_trainersont une autre fonction, la persistance DB decommun.finetune.persistence).
Inventaire — protocole (auditable)¶
- Date / base : re-scan 2026-06-07, branche
feat/CVN-N014-ED-S03-*depuismain@91acb5ef(post-S02). - Scope :
dags/**,src/commun/finetune/**(modules consommés par les DAGs). - Patterns :
np.savez·np.load(·upload_fileobj·put_object·to_parquet(·to_pickle(·pickle.dump·/tmp/tempfile/Path(·do_xcom_push=True/ objets non-JSON en XCom. - Critères de classification :
- non-conformant = transport large-data cross-pod non-standard (producteur et consommateur dans des pods différents, via un chemin bricolé) — à nettoyer ;
- conformant = pass-by-référence vers le S3 partagé (
cvntrade_s3_manager), ou usage local-only single-pod explicitement borné (cf. règle ci-dessous) ; - faux positif = le pattern matche mais la sémantique XCom ne transporte que des références JSON (run_ids, params), pas un payload large-data.
| Hit | Classement |
|---|---|
s43_io.py (np.savez) + dag_diagnostic__s43 (upload_fileobj) |
conformant — S3 partagé via cvntrade_s3_manager, prouvé cross-pod (S02) ; module partagé, pas bespoke par-tâche |
dag_diagnostic__s18_step1_3_chain / s18_step1_4_chain (to_parquet/Path) |
conformant — capture+forensics single-pod borné (cf. règle) |
launch__* (do_xcom_push) |
faux positif (sémantique XCom) — transportent des run_ids / params / références JSON, pas des arrays |
→ Inventaire vide : aucun workaround large-data cross-pod non-conformant restant.
Règle single-pod (le critère qui sépare s18-conforme de s43-cassé) : un usage
/tmp/FS-local est conformant uniquement si producteur et consommateur sont dans le MÊME pod, dans une même unité d'exécution bornée, sans dépendance inter-task / inter-pod. s43 était cassé parce que producteur (5 pods acq) et consommateur (pod gate) étaient dans des pods différents ; les chaînes s18 écrivent et relisent dans le même pod (PR #935) →/tmpy est légitime.
1. User stories¶
- En tant qu'archi, je veux l'inventaire prouvé vide + la garantie qu'aucun DAG ne réintroduit un transport large-data bricolé, pour que la classe de bug
/tmp/cible-fausse ne revienne pas. - En tant que dev touchant un DAG large-data, je veux un pattern de référence (
s43_io) + un gate de review (S04) pour mettre au standard dans le même PR, sans migration forcée.
2. Hypotheses (testable, EN)¶
- H1 — The inventory is empty post-S02. No DAG transports large data cross-pod via a non-standard path. Test: the §0bis scan (named patterns, named scope) yields only conformant modules + single-pod-bounded chains + JSON-semantics launcher false-positives.
- H2 — Generalizing the pass-by-ref layer is premature at one consumer.
s43_iohas a single caller. Test: grep of its consumers = 1. Project threshold (more conservative than the classic rule-of-three): revisit at the 2nd independent consumer. - H3 — Regression prevention is S04's, not S03's, and not a runtime check. S03 transmits the normative rule "no new large-data cross-pod workaround"; S04 enforces it at the review gate. Test: S03 carries no enforcement code; the requirement is referenced into S04.
3. State of the art (EN)¶
- Strangler-fig (Fowler): replace a legacy pattern incrementally at touch-time, never big-bang. Here the expected end-state is reached early — the inventory is already empty.
- YAGNI, with an explicit project threshold (more conservative than rule-of-three's 3): don't extract a shared policy layer until the 2nd independent consumer — premature abstraction for a single caller is a cost.
- Reference pattern:
s43_io(S02) — pass-by-ref to S3, run-isolated prefix, schema-versioned fail-loud, expected-keys manifest. A future 2nd consumer generalizes from it.
4. Definition of Done — critères de FERMETURE testables¶
S03 est Closed dès que :
1. Inventaire publié (§0bis) — méthode auditable (commande/scope/patterns/classification).
2. Inventaire vide au scan, faux positifs justifiés (sémantique, pas seulement par nom).
3. A(ii) tranché : généralisation s43_io → couche-policy différée au 2ᵉ consumer indépendant (décision tracée, pas une dette sine die).
4. Prévention des régressions transférée à S04 (exigence normative documentée + référencée) — S03 ne bloque pas sur l'implémentation de S04 (Option A : S03 ferme avant ; l'enforcement est hors-scope S03).
5. Reliquat S01 — lifecycle xcom/ : soldé. Closed exige (a) get-bucket-lifecycle-configuration prouve xcom/ actif, ou (b) waiver daté, owner, échéance, lié à S04/Sxx.
Une régression future n'est pas un motif de garder S03 ouverte : S04 la capte → nouvelle Story ciblée.
5. Consolidation¶
S03 constate que le cleanup opportuniste prévu par l'Epic est déjà soldé par S01+S02. Le re-scan 2026-06-07 ne trouve aucun workaround large-data cross-pod non-conforme : s43 — seul payload tableau identifié — utilise désormais un pass-by-référence S3 prouvé cross-pod ; les chaînes s18 restent des captures single-pod explicitement bornées ; les launchers ne transportent que des références JSON.
La Story ne crée donc pas de couche-policy spéculative pour un unique consommateur : la généralisation A(ii) est différée jusqu'au 2ᵉ consumer indépendant, moment où s43_io servira de pattern de référence. S03 solde en revanche le reliquat opérationnel hérité de S01 (lifecycle xcom/, avec preuve ou waiver daté owner+échéance), transfère la prévention des régressions à S04 (sans bloquer dessus), puis ferme. Le résultat attendu d'un strangler-fig est atteint plus tôt que prévu : l'inventaire courant est vide, donc aucun chantier de migration large-data n'est justifié.
Partie II — Plan¶
6. Décisions¶
- A(ii) : différée au 2ᵉ consumer indépendant (YAGNI, seuil projet ;
s43_io= pattern de référence). Pas de décorateur/helper spéculatif. - Lifecycle
xcom/(reliquat S01, pas le cœur de S03) : appliquerinfra/scaleway/s3-lifecycle-xcom.json(7j), merge avec les règles actives (cleanup-old-artifacts,s43-predictions-7d-retention) — preuveget-bucket-lifecycle-configuration. Sinon waiver daté owner+échéance. - Gate anti-régression : transmis à S04 (exigence normative « no new large-data cross-pod bespoke transport »). S03 le référence, ne l'implémente pas, ne bloque pas dessus.
7. Actions¶
| Action | |
|---|---|
| Doc-set S03 (hub + ce plan) | publier l'inventaire vide + le protocole + les décisions |
Lifecycle xcom/ |
appliquer in-pod (boto3 merge+put+get, comme S02) + preuve, ou waiver daté |
| OP | inventaire vide consigné ; A(ii) re-tracé « différé au 2ᵉ consumer » ; exigence anti-régression transmise à S04 |
8. Risques¶
- R1 — fausse complétude : un workaround échappe au scan. Mitigation : protocole §0bis (patterns + scope nommés, classification explicite) + le gate S04 attrape les nouveaux à la review.
- R2 — abstraction prématurée : extraire une policy pour 1 consumer. Mitigation : H2 (seuil 2ᵉ consumer).
- R3 — Story zombie : rester
openà vie. Mitigation : DoD §4 = critères de fermeture ; une régression rouvre une Story ciblée, pas S03. - R4 — dépendance circulaire S03↔S04 : S03 bloque sur S04. Mitigation : Option A — S03 ferme avant, ne fait que transmettre l'exigence.
9. Done-criteria (rappel)¶
Inventaire publié+vide (auditable) · faux positifs justifiés (sémantique) · A(ii) différé au 2ᵉ consumer · enforcement transféré à S04 (sans blocage) · lifecycle xcom/ appliquée+preuve ou waiver daté owner+échéance → S03 Closed.