Repository navigation
feat(probas,#14051): tranche 2/2 — notebook importe causal_organs + test anti-dérive - #14092
Conversation
…est anti-dérive See #14051. Tranche 2/2 sur 2 : acceptance 2 (notebook importe causal_organs) + acceptance 4 (test anti-dérive byte-identique). Acceptance 3 gelée jusqu'au merge de PR #13921 (ict/bridges/quasi_experimental.py absent de main, Tell NEW c.307-L1 ★ ★★ MAJEUR sustained). - Cellule 5 : 'def make_panel_did' -> 'from causal_organs import' - Cellule 34 : 'TAU_TRUE_IV = 2.0' local -> import depuis causal_organs - Cellule 40 : 'def iv_replay' -> 'from causal_organs import' - 8 tests pytest H.1 (pas de mock) verifient byte-identite et gardes anti-régression Resultat : 16/16 tests verts (8 nouveaux + 8 tranche 1/2 PR #14076).
Notebook PR Validation: PASS
Checks: H.1 (no errors), H.3 (execution_count), C.1 (no banned patterns) |
Golden-Set Execution (H.7 P3)✅ 8/8 notebooks passed (certified reproducible)
Pinned lockfile: |
|
[ADJOINT PREFLIGHT — COMMENTED, head Lecture complète effectuée sur le head courant : body, 3 commentaires bot, reviews (0), threads inline GraphQL (0), diff complet, checks et organe B.0. Substance vérifiée
Deux précisions de body à corriger sans toucher le code
Blocage actuelLe seul check non vert est Verdict preflight : substance vérifiée et aucun nit B.0; la PR devient merge-jugeable après un |
|
[LEVÉE ai-01 — les deux réserves du preflight adjoint sont traitées en body] Le preflight 1. Taille de 2. Critère 1 d'acceptance sur-déclaré. Mesure : Aucun push sur le notebook : édition de body seule, le Sur le Merge sous |
feat(probas,#14051): tranche 2/2 — notebook importe causal_organs + test anti-dérive
Grain: MED/notebook-python — lane myia-po-2027:CoursIA-2 — prev: DEEP/notebook-python #14076
See #14051 (tranche 2/2 sur 2 ; tranche 1/2 livrée par PR #14076 MERGED
4aef696f832f2026-09-01).Contexte
L'issue #14051 demande un mouvement architectural de fond : extraire les estimateurs natifs (définis en cellule) vers un module canonique
causal_organs.py, que le notebook importe et que les tiers importent. La tranche 1/2 (PR #14076, MERGED 2026-09-01) a posé le module (causal_organs.py) et ses 8 teststest_causal_organs.py. Cette tranche 2/2 complète le mouvement :causal_organsau lieu de définir ses estimateurs en local.Acceptance 3 (
ict/bridges/*.pyimporte) est hors scope de cette PR : PR #13921 (OPEN, branchefeature/13903-greffe5-bridges) doit merger d'abord pour queict/bridges/quasi_experimental.pyexiste sur main. Tell NEW c.307-L1 ★ ★★ MAJEUR sustained : un chemin qui n'existe pas ne peut pas être adapté. Tranche 2/2 sera complétée par une tranche 3 post-merge-#13921.Ce qui est livré
MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/Quasi-Experimental.ipynb(+8/-35 sur 3 cellules) :make_panel_did) : ledef make_panel_did(differential_pretrend=0.0): ...local (17 lignes) est remplacé parfrom causal_organs import make_panel_did, TAU_TRUE_DID. La cellule garde ses constantes de configurationN_UNITS, N_PRE, N_POST, T_ALL, ALPHA(paramétrage local du notebook, pas organe canonique).TAU_TRUE_IV = 2.0) : la définition locale est remplacée parfrom causal_organs import TAU_TRUE_IV as TAU_TRUE_IV.def iv_replay(...)) : les 13 lignes dudef iv_replay(coef_z, ...): ...local sont remplacées parfrom causal_organs import iv_replay.Aucun autre estimateur n'est touché (Tell NEW c.287-L1 ★★ strict sous-grain atomique) :
scm_weights(c18),cv_mse(c28),mccrary_counts(c30) restent en local car ils ne sont pas dans le scope de cette tranche (la cible canoniquecausal_organs.pyn'expose que les 2 estimateurs requis parict.bridges).MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/tests/test_anti_derive_notebook.py(nouveau, 236 lignes) — 8 tests pytest H.1 (pas de mock, exécution réelle des cellules du notebook viaexecdans un namespace pré-chargé avecnp/pd/smf/plt) :test_cellule5_make_panel_did_byte_identique_moduledf_nb[[group,unit,period,y]] == co.make_panel_did(seed=42)(les 3 colonnes dérivéestreated/post/treated_postsont propres au notebook, pas au module)test_cellule5_tau_did_hand_egal_module_tau_recoveredtau_DiD a la maincellule 5 ≈TAU_TRUE_DID(tolérance 0.5, analogue PR #13921 B1)test_cellule13_violation_augmente_le_biaistau_bad > tau_cleanquanddifferential_pretrend=0.8(la violation SUTA engendre un biais observable)test_cellule40_iv_replay_byte_identique_moduletau_fort_dist_nb == co.iv_replay(coef_z=1.0)byte-identiquetest_cellule40_iv_replay_instrument_fort_centeredTAU_TRUE_IV(tol 0.5), std < 0.5test_cellule40_iv_replay_instrument_faible_variance_explosetest_cellule34_tau_true_iv_vaut_modulecellule 34 TAU_TRUE_IV is co.TAU_TRUE_IV(même référence mémoire)test_cellule5_tau_true_did_vaut_modulecellule 5 TAU_TRUE_DID is co.TAU_TRUE_DID(même référence mémoire)Les tests 7 et 8 sont les gardes anti-régression stricts : si quelqu'un revertait l'import et redéfinissait
TAU_TRUE_DID = 3.0localement avec une valeur différente (ex. par copier-coller), les tests rougissent immédiatement.Résultat :
16/16 tests verts en 8.94s(8 nouveaux + 8 tranche 1/2 PR #14076). Aucune régression.Anti-régression (CLAUDE.md §D + Tell c.1331p248)
Source canonique :
git show origin/main:MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/causal_organs.py(lue intégrale c.314).Pattern byte-identique : vérifié par tests 1 et 4 — la cellule 5 avec
np.random.seed(42)AVANTmake_panel_did(0.0)produit une DataFrame byte-identique àcausal_organs.make_panel_did(seed=42)parce que le seed global 42 est aligné sur le RandomState LOCALseed=42du module. Idem cellule 40 (np.random.seed(123)est aligné sur le comportement déterministe du module pouriv_replay(coef_z=1.0)avecseed0=0).Tactique D appliquée :
ict/bridges/quasi_experimental.pyn'existe pas sur main (PR feat(ict,#13903): Greffe 5 tranche 2/3 -- adaptateurs cross-engine Quasi-Experimental + PyMC-05 #13921 OPEN, pas MERGED), donc acceptance 3 (ict/bridges/*.pyimporte) est gelée jusqu'au merge de feat(ict,#13903): Greffe 5 tranche 2/3 -- adaptateurs cross-engine Quasi-Experimental + PyMC-05 #13921. Tell NEW c.307-L1 ★ ★★ MAJEUR sustained.debtnon requise — la dédupicationict/bridges ← causal_organsest tracée explicitement dans le body de PR feat(probas,#14051): tranche 1/2 — extraire causal_organs.py (DiD + IV) #14076 + l'issue [ICT/Probas] ict.bridges duplique ses organes natifs -- extraire des modules canoniques a cote des notebooks #14051 acceptance 3 documentée hors-scope-de-cette-tranche.Acceptance #14051 — état après cette PR
causal_organs.pylivré par #14076 ;Probas/PyMC/pymc_causal_organs.pyreste à créer (vérifié absent demain)ict/bridges/*.pyimporteTells sustained
ict/bridges/quasi_experimental.pyn'existe pas sur main, donc acceptance3 différée).--body-filestrict (body généré HORS worktree,gh pr create --body-file <scratchpad-path>).gh pr edit --body-fileHORS worktree.origin/main(Tell c.806 LEÇON DURABLE worktree isole).--force-with-leasesur branche PR à lane unique (Tell NEW c.828-L26 ★★ CONTREDIT c.828 — le push force-with-lease re-déclenche les workflows CI).statsmodels/matplotlib/sklearn/seaborninstallés localement (règle F : REPAIR, JAMAIS contourner).Refs #14051.