Skip to content

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)

  1. 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é.
  2. Le parc est JSON-only (audit S01 : 129 sites, 0 numpy_suspect).
  3. s43_io n'a qu'UN consumer (le DAG s43) — git grep des appels persist_predictions(store,prefix,…) / load_cohort_predictions(store,prefix,…)dags/dag_diagnostic__s43.py seul (les persist_predictions d'ablation_runner/persistence/regime_trainer sont une autre fonction, la persistance DB de commun.finetune.persistence).

Inventaire — protocole (auditable)

  • Date / base : re-scan 2026-06-07, branche feat/CVN-N014-ED-S03-* depuis main@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) → /tmp y 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_io has 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) : appliquer infra/scaleway/s3-lifecycle-xcom.json (7j), merge avec les règles actives (cleanup-old-artifacts, s43-predictions-7d-retention) — preuve get-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.