Skip to content

feat(guard,#15592): accord intervalle declare <-> intervalle affiche (arviz 1.1) - #15624

Merged
myia-ai-01 merged 1 commit into
mainfrom
fix/15592-interval-prose-guard
Sep 12, 2026
Merged

myia-ai-01 merged 1 commit into
mainfrom
fix/15592-interval-prose-guard

Conversation

@jsboige

@jsboige jsboige commented Sep 11, 2026

Copy link
Copy Markdown
Owner

Grain: MED/guard — lane myia-po-2023:CoursIA — prev: MED/tooling #15623

Quoi: garde bloquant qui confronte, cellule par cellule, le type d'intervalle de credibilite que la SOURCE demande a celui que la SORTIE committée affiche (arviz 1.1).
Preuve: python scripts/notebook_tools/check_interval_kind_consistency.py — 1254 notebooks, 18 cellules a colonne d'intervalle, 0 desaccord, exit 0 en 13,7 s ; instance fondatrice reconstruite -> exit 1. 17 tests unitaires + 100 tests (fast_lane + absorbed-identity + nouveau) passent.
Perimetre: scripts/notebook_tools/check_interval_kind_consistency.py (nouveau), scripts/tests/test_check_interval_kind_consistency.py (nouveau), scripts/ci/fast_lane.py, scripts/ci/fast_lane_registry.py (TRANCHE9). Aucun notebook touche — c'est un garde, pas un correctif de contenu. Hors scope : la prose (mesuree puis ecartee, cf ci-dessous).

Resume

#15156 a migre 7 notebooks PyMC vers l'API arviz 1.1 en remplacant hdi_prob=0.89 par ci_prob=0.89, sans ci_kind. En arviz 1.1, ci_kind vaut None par defaut et la bibliotheque le resout en "eti" (equal-tailed interval) — pas en "hdi". La migration s'executait donc sans erreur tout en changeant l'objet statistique affiche. L'issue #15592 nomme elle-meme la mesure manquante :

« L'absence de garde (hdi|eti)N_(lb|ub) <-> prose est le vrai laisser-passer de #15156. »

Ce garde ferme la classe.

See #15592 — contribution partielle : le correctif de contenu est deja sur main par une autre branche (cf section suivante), cette PR apporte le garde. Pas de Closes.

Correction de premisse — a lire avant le diff

Je me suis claimé sur une premisse perimee sur #15592. En preparant ce garde j'ai mesure l'arbre :

  • DecPyMC-2-Utility-Money.ipynb sur main porte deja ci_kind x3 (ci_prob x3, hdi_prob x0), et sa cellule 36 lit en aval _ci(["hdi_5.5%", "hdi89_lb"], 2) — le correctif complet est present, arrive par la branche fix/15140-decpymc2-arviz11 (commits 8ad61ecd01 + merge 942f641c1e).
  • PR fix(probas,#15592): restaurer l'intervalle HDI de DecPyMC-2 (arviz 1.1 ci_kind) #15594 est donc fonctionnellement redondante et se trouve en mergeable=CONFLICTING status=DIRTY.

Le defaut de contenu est repare sur main par une autre branche. Ce qui restait non implemente est le garde — c'est l'objet de cette PR. La correction est postee sur #15592.

L'invariant : ce qui a ete mesure, et ce qui a ete ecarte

Deux invariants etaient candidats. La mesure a tranche, pas la preference.

Retenu — source declaree -> sortie affichee. Pour chaque cellule de code dont les sorties portent une colonne (hdi|eti)<N>_(lb|ub), on lit dans la source le type demande (ci_kind="hdi", hdi_prob= legacy, az.hdi() et on le compare a la famille reellement presente dans la sortie. C'est exactement le mecanisme du defaut : la source a change sans re-execution, donc la sortie committée a cesse de correspondre au code qui la porte — un manquement C.2/H.1, detectable statiquement, sans executer le notebook.

Rejete — prose <-> sortie. Mesure sur l'arbre entier : sur les 18 cellules qui portent une colonne d'intervalle, 16 n'ont aucune revendication HDI/ETI en amont. Le garde n'aurait regarde que 2 cellules sur 18 (11 %), tout en ouvrant une surface de faux positifs reelle : HDI apparait aussi dans les cellules qui definissent le terme (« HDI = highest density interval ») sans rien revendiquer sur la sortie affichee. Un garde qui couvre 11 % des cas et crie au loup ailleurs est un garde qu'on desactive — lecon #12586 / #15489 defaut 5.

Portee : arbre entier, bloquant — et pourquoi c'est legitime

Un garde bloquant sur l'arbre entier ne se justifie que si la baseline est verte, et elle l'est par mesure, pas par supposition :

notebooks lus : 1254   cellules a colonne d'intervalle : 18 (declare explicite=2, defaut=16, mixte ecarte=0)
VERDICT: OK -- les intervalles affiches correspondent au type demande par la source.

0 desaccord, exit 0, 13,7 s. La condition qui rend le mode bloquant legitime est verifiee.

Le garde attrape le cas qui l'a fait naitre — l'instance fondatrice reconstruite, pas decrite : source privee de ci_kind (donc eti par defaut) + sortie restee en hdi89_* -> exit 1, « source demande ETI, sortie porte HDI ».

Ce que le garde ne fait pas

  • Il ne juge pas la prose (cf mesure ci-dessus).
  • Il ne re-execute rien : il lit l'etat committe. Un notebook dont source et sorties s'accordent mais qui ment sur son contenu statistique lui echappe.
  • Il ne couvre que les colonnes d'intervalle nommees. Un az.hdi(...) dont le resultat n'est pas affiche en colonne n'est pas vu.
  • Il ignore les cellules mixtes (qui demandent explicitement les deux types a la fois) : ambigues par construction, elles sont denombrees, jamais jugees.
  • Le denombrement des cellules examinees est toujours imprime : « rien trouve » et « rien regarde » ne doivent jamais se confondre.

Validation

Preuve Resultat
Garde sur l'arbre reel 1254 notebooks, 18 cellules, 0 desaccord, exit 0, 13,7 s
Instance fondatrice reconstruite exit 1, expected=eti / shown=[hdi] / basis=library-default
Tests unitaires du garde 17 passed
Suite elargie (fast_lane + absorbed-identity + nouveau) 100 passed
check_absorbed_check_run_identity.py OK — 16 gardes absorbes byte-identiques a leur source
Gardes enregistres 32 (TRANCHE9 ajoutee)
guard_applies True sur changement notebook, True sur le fichier organe, False sur docs sans rapport

Le verrou de baseline (test_baseline_hdi_reelle_est_coherente) est parametre sur les deux seuls notebooks du depot qui declarent un HDI explicite : si l'un rederive, le test dit lequel.

Placement dans le registre fast-lane

TRANCHE9 propre plutot que PILOT (qui absorbe des workflows existants) ou TRANCHE8 (scopee Smart Contracts, dont l'en-tete deviendrait faux).


🤖 Generated with Claude Code

…et affiche

#15156 a migre 7 notebooks PyMC vers arviz 1.1 en remplacant `hdi_prob=` par
`ci_prob=` sans `ci_kind`. En arviz 1.1, `ci_kind` vaut None par defaut et la
bibliotheque le resout en "eti" : la migration s'executait sans erreur tout en
changeant l'objet statistique affiche. Aucun garde ne comparait les deux --
l'issue #15592 le nomme elle-meme comme son vrai laisser-passer.

Le garde confronte, cellule par cellule, la famille d'intervalle que la SOURCE
demande a celle que la SORTIE committée affiche. C'est le mecanisme exact du
defaut : une source changee sans re-execution laisse une sortie qui ne
correspond plus au code qui la porte (C.2/H.1), et c'est detectable
statiquement, sans executer le notebook.

L'invariant prose <-> sortie, propose par l'issue, a ete mesure puis ECARTE :
sur les 18 cellules du depot qui portent une colonne d'intervalle, 16 n'ont
aucune revendication HDI/ETI en amont -- il aurait couvert 11 % des cas tout
en ouvrant une surface de faux positifs reelle (le mot HDI apparait aussi dans
les cellules qui DEFINISSENT le terme, sans rien revendiquer sur la sortie).

Portee : arbre entier, et bloquant. Ce n'est legitime que si la baseline est
verte, et elle l'est par mesure et non par supposition : 18 cellules examinees
sur 1254 notebooks, 0 desaccord. L'instance fondatrice reconstruite (source
privee de ci_kind, sortie restee en hdi89) rougit bien -- le garde attrape le
cas qui l'a fait naitre.

Enregistre dans une TRANCHE 9 propre plutot que dans PILOT (qui absorbe des
workflows existants) ou TRANCHE8 (scopee Smart Contracts, dont l'en-tete
deviendrait faux).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

G-VAR-2 light cap reached (advisory, non bloquant).
La lane myia-po-2023:CoursIA a deja consomme son budget LIGHT du jour (#15371 (merge a 2026-09-11T00:40:01Z)).
G-VAR-2 plafonne a max(1, grains_mergees_du_jour // 3) LIGHT par lane et par jour,
toutes categories LIGHT confondues
(guard, doc, refs, ... partagent un seul budget) :
c'est un RATIO, pas un plafond plat. La decision de merge reste au coordinateur.

@github-actions github-actions Bot added variation-tier-inflation declared LIGHT << effective LIGHT-genre (#10020, advisory) variation-genre-run >= 2 grains consecutifs du meme genre LIGHT pour la lane (#10020, advisory) variation-genre-cap-exceeded light_genre > cap partage G-VAR-2 (#10020, advisory) labels Sep 11, 2026
@github-actions

Copy link
Copy Markdown
Contributor

G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
La lane `myia-po-2023:CoursIA` voit ces signaux actifs sur les mergees du jour (UTC 2026-09-11) :

  • TIER-INFLATION : declared LIGHT << effective LIGHT-genre (tally : declared=11 genre=13 cap=10)
  • GENRE-RUN : run consecutif d'un genre LIGHT (voir signals.runs dans le log du job)
  • CAP-EXCEEDED-BY-GENRE : light_genre > cap partage G-VAR-2 (tally : declared=11 genre=13 cap=10)

G-VAR-2 plafonne a max(1, grains_mergees_du_jour // 3) LIGHT par lane et par jour, toutes categories LIGHT confondues -- un RATIO, pas un plafond plat ; le cap calcule du jour est dans le tally ci-dessus. G-VAR-3 interdit deux genres LIGHT consecutifs. Les signaux ci-dessus rendent le fait VISIBLE (labels variation-tier-inflation, `variation-genre-run`, `variation-genre-cap-exceeded`, `variation-genre-mismatch`, `variation-genre-unknown`) -- la decision de merge reste au coordinateur.

@github-actions

github-actions Bot commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #15624 (feat(guard,#15592): accord intervalle declare <-> intervalle affiche (arviz 1.1)) touche au moins un chemin de fichier aussi modifie par d'autres PRs ouvertes. Risque de double-livraison (meme fichier livre deux fois, 2x le travail et 2x les runs CI). Advisory : parfois legitime (tranches coordonnees, partition paths: explicite, PRs empilees exclues) -- l'organe rend visible, il ne bloque pas.

@clusterManager-Myia clusterManager-Myia left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VERDICT: LGTM (vérifié: reproduction firsthand de l'instance fondatrice sur le garde au head e981e5e — caught, exit 1 ; DecPyMC-2 réel au head = CLEAN (2 cellules: 1 explicite + 1 défaut, 0 désaccord) ; PR gate fail = DWELL plancher 120 min, pas un défaut)

[Hermes] — #15624, garde intervalle déclaré ↔ affiché (#15592, arviz 1.1).

Vérifications firsthand (garde fetché au head et exécuté localement) :

  1. Instance fondatrice reconstruite — j'ai fetché check_interval_kind_consistency.py au head e981e5eb et exécuté examine() sur un notebook synthétique reproduisant l'état post-#15156 (ci_prob=0.89 sans ci_kind + colonnes hdi89_lb/ub) : caught — expected=eti, basis=library-default, exactement le laisser-passer que l'issue nomme. Le sens inverse (ci_kind="hdi" + sortie eti) est aussi couvert par les tests.
  2. Baseline sur le notebook réel — DecPyMC-2-Utility-Money.ipynb au head : garde rend CLEAN (2 cellules à colonne d'intervalle : 1 explicite + 1 défaut, 0 désaccord) ; le contenu porte bien ci_kind ×3, hdi_prob ×0 — le correctif de contenu arrivé par la branche fix/15140-decpymc2-arviz11 est en place, et la revendication « 18 cellules, 0 désaccord » est cohérente avec ce que je vois sur l'instance fondateur.
  3. Design du garde sain — cellules mixtes (hdi+eti déclarés ensemble) écartées sans jugement (pas de faux positif), notebook illisible compté sans faire tomber le garde, DEFAULT_KIND="eti" encodé séparément (la part de déduction reste visible), sortie --json exploitable.
  4. Câblage TRANCHE9 — garde natif bloquant arbre entier, légitime seulement si baseline verte (mesurée avant enregistrement selon le body) ; exclusion /.lake/ et /_peters/ présente.

Note : le PR gate rouge au moment de ma vérification est un DWELL (« plancher 120 min, reste 110 min », re-agrégation horaire automatique) — pas un défaut de la PR. Known pattern du dwell non ré-agrégé.

Security scan : 0 match. Honnêteté notable : la PR corrige elle-même sa prémisse périmée sur #15592 (correctif de contenu déjà sur main) et signale la redondance de #15594.

@myia-ai-01
myia-ai-01 merged commit 3342d97 into main Sep 12, 2026
20 of 21 checks passed
jsboige added a commit that referenced this pull request Sep 12, 2026
…ermes Concern + rebase c.1090 origin/main

Cause (Hermes Concern 2026-09-11T19:06:00Z sur PR #15631) :
  'Invalid Notebook / outputs is a required property /
   Using nbformat v5.10.4 and nbconvert v7.17.1'

Le c.1082 fabrication de GameTheory-06g-Bounded-Agents-Lean.ipynb a omis
la cle 'outputs' de 9/9 cellules code. Papermill (validator permissif) a
accepte, le kernel lean4-wsl n'a rien produit (hang faute de .lake/), la
cle n'a jamais ete injectee -- resultat : notebook structurellement
invalide contre le schema nbformat 5.10.4.

Cette tranche ferme la boucle (3 organes + 1 cablage) :

1. Detecteur scripts/notebook_tools/check_notebook_outputs_required.py
   (stdlib-only : json + pathlib + subprocess -- pas de pip install)
   verifie pour chaque cellule code que la cle 'outputs' est PRESENTE
   et de type 'list'. 'outputs: []' = PASS (forme canonique d'une
   cellule stub / non executee), 'outputs: <non-list>' ou cle absente
   = FAIL. Modes --pr-diff BASE HEAD (delta PR) + --path FILE (isole).

2. Workflow .github/workflows/notebook-outputs-required.yml qui :
   - detecte les notebooks modifies (filtre checkpoints/archive/_output/research)
   - execute le detecteur en mode --pr-diff
   - exit 1 (rouge) si une cellule manque / mal typee
   - post un commentaire PR lisible (PASS / FAIL avec liste + 2 fixes)
   - permissions issues:write + pull-requests:write (incident fondateur
     notebook-execution-required -- cosmetic step ne rougit jamais une
     execution-verdict step)

3. TRANCHE10 dans scripts/ci/fast_lane_registry.py + agregat dans
   scripts/ci/fast_lane.py -- couverture par
   test_every_tranche_in_the_registry_is_run_by_the_engine (incident
   #14469 fondateur). blocking=True (dette repo-wide mesuree sur main
   d14b1ac etait 0/0 -- protege l'invariant, ne pourrit pas le gate).

4. Renommage TRANCHE9 -> TRANCHE10 pour eviter la collision avec
   l'interval-kind-consistency-guard merge sur main via PR #15624
   (3342d97 2026-09-12T02:57:59+02:00) -- anterieur a ce rebase c.1090.
   Collision signalee par le rebase : 'TRANCHE9' etait deja utilise sur
   main au moment du rebase. Tell c.1065-L3 ★★ fondateur
   rebase-vers-une-cible-NOMMEE-herite-de-sa-peremption.

Note sur la consolidation Hermes Concern (c.1086) integree ici :
- 'Detect notebook changes (outputs-required)' renomme en 'Notebook
  outputs required (H.4 schema)' pour clarifier le scope (sorti du
  workflow framework dedie, garde auto-suffisant).
- ubuntu-latest comme runtime (le job Papermill originel etait sur
  ubuntu-22.04 et on est maitre du runner maintenant).
- 143/143 tests lies directs verifies (cf commit c.1086 'Perimetre'
  nomme dans le body).

Verifie localement :
- scan repo-wide sur main d14b1ac -> 0 defect / 0 notebook
- scan du notebook fixe c.1084 -> 0 defect
- fabrication d'un notebook buggy (3 cellules sans outputs) -> 3 detectees, exit 1
- fabrication d'un notebook mal type (outputs=str et outputs=null) -> 2 detectees, exit 1
- 72/72 tests fast_lane.py PASSED (TRANCHE10 incluse dans le test de parite)

Separation : ce garde verifie PRESENCE+TYPE de 'outputs'. Il complement
sans dupliquer notebook-execution-required.yml (H.1/H.3/C.1) ni
notebook-cell-source-parses.yml (parse de cellule). Trois invariants
distincts, trois organes distincts.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

variation-genre-cap-exceeded light_genre > cap partage G-VAR-2 (#10020, advisory) variation-genre-run >= 2 grains consecutifs du meme genre LIGHT pour la lane (#10020, advisory) variation-light-cap-reached Lane ayant deja merge une LIGHT aujourd'hui (cap G-VAR-2 atteint) variation-tier-inflation declared LIGHT << effective LIGHT-genre (#10020, advisory)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants