Repository navigation
fix(guard,#17185): le verdict de drift nomme l'env canonique epingle de la serie - #17237
Conversation
…de la serie Le garde nommait les CAUSES du drift (« un autre interpreteur, 3.11 -> 3.13 », « NumPy 1.x -> 2.x ») sans jamais dire OU rejouer. Une serie qui epingle son environnement obtenait donc un verdict qui la renvoyait a sa propre introspection, et la lane re-executait avec son env local -- reproduisant le drift signale. canonical_env_hint() remonte depuis le dossier du notebook (au plus 3 niveaux : au-dela on nommerait un artefact qui ne couvre plus la serie) et rend le pyproject.toml / requirements.txt le plus proche, avec requires-python et le pin numpy quand ils sont declares. La cause est ajoutee dans la branche --explain, celle que consomme le workflow (--explain --json). Correction du constat de l'issue, verifiee avant d'ecrire : l'env canonique ICT EXISTE deja, epingle et documente (IIT/ICT-Series/pyproject.toml : Python 3.9, pyphi==1.2.0, numpy>=1.21,<2.0 ; IIT/requirements.txt porte en plus pyemd==0.5.1 avec le pourquoi). Ce qui manquait n'est pas l'artefact, c'est le pointeur vers lui au moment ou la lane lit le verdict. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Path-collision (organ #13359/#13615)Cette PR #17237 (
|
|
Grain tag obligatoire (#10045, bloquant).
Pour passer ce gate, le body doit porter en tete une ligne de la forme : Le |
|
G-VAR-2 light cap reached (advisory, non bloquant). |
|
G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
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 |
|
[ADJOINT PREFLIGHT] |
Grain: LIGHT/guard -- lane myia-po-2026:CoursIA -- prev: FIX/infra #17230
See #17185— le constat de l'issue est corrige avant d'ecrire, et ce qui restait vraiment manquant est livre.Ce que l'issue impute, et ce que le depot porte deja
L'issue conclut : « le depot n'epingle pas d'env canonique pour les re-executions de la serie ICT, donc chaque lane re-execute avec son env local ». Verification firsthand : c'est faux, l'env existe et il est soigneusement epingle.
MyIA.AI.Notebooks/IIT/ICT-Series/pyproject.tomlrequires-python = ">=3.9,<3.10",pyphi==1.2.0,numpy>=1.21,<2.0— avec le pourquoi de chaque pin (pyphi 1.2.0 exige ≤ 3.9,collections.Iterableretire en 3.10)MyIA.AI.Notebooks/IIT/requirements.txtpyemd==0.5.1et le piege documente (sdist compilee contre numpy 2.x →numpy.dtype size changed)L'env canonique ICT est l'artefact executable que l'acceptance demande. Rien a creer de ce cote.
Ce qui manquait : le pointeur, au moment ou la lane lit le verdict
Le garde nommait le mecanisme du drift et jamais ou rejouer :
Une lane qui lit ca n'a qu'une issue : re-executer avec son env local — ce qui reproduit exactement le drift signale. L'information existait, elle n'etait pas rejoignable depuis le verdict.
Le correctif
canonical_env_hint(nb_path, root)remonte depuis le dossier du notebook et rend lepyproject.toml(prioritaire) ou lerequirements.txtle plus proche, avecrequires-pythonet le pinnumpyquand ils sont declares. La cause est ajoutee dans la branche--explain— celle que le workflow consomme (--explain --json).Borne assumee : la remontee s'arrete a 3 niveaux. Au-dela, on nommerait un artefact qui ne couvre plus la serie (racine du depot) — un chemin qui a l'apparence d'une reponse. Aucun artefact trouve ⇒
None, et aucun chemin n'est invente : l'absence est une information.Preuves
1. Suite complete —
43 passed(test_check_kernel_drift.py14,test_check_kernel_drift_fixes.py23, le nouveau fichier 6).2. Execution reelle du vrai garde (A/B dans un seul run) — depot git synthetique, deux series subissant le meme drift, l'une avec un
pyproject.toml, l'autre non (temoin) :Le temoin recoit 2 causes, aucune nommant un artefact : la troisieme cause est bien produite par la presence de l'artefact, pas par le drift.
3. Falsification des deux pins — une garde qui ne rougit jamais quand le code est faux ne pinne rien :
env_hint = None)test_explain_branch_calls_the_env_hintFAILEDparents[:_ENV_WALK_LEVELS]→parents)test_walk_stops_at_the_series_boundaryFAILEDRestauration par
cpdepuis une copie, puis6 passedetgit diff --statau perimetre attendu.Perimetre
Un seul sujet. 3 fichiers — le garde (
+70), un fichier de tests neuf (le fichier de tests existant est modifie par la PR #17236 ouverte sur le meme organe ; je n'y touche pas pour ne pas creer de conflit d'append), et le workflow du garde (paths+ invocation pytest).Correction d'une affirmation fausse de ma premiere redaction
J'y ecrivais que ce workflow etait le seul a lancer les tests du garde, et qu'ajouter le fichier neuf a son invocation etait necessaire pour qu'ils tournent en CI. Faux, et verifie apres coup :
pytest.iniportetestpaths = scripts/notebook_tools/tests— un repertoire — etscripts-tests.ymlpasse explicitement ce repertoire (pytest ... scripts/notebook_tools/tests ...). Tous les fichiers de tests du dossier, le mien comme le_fixespreexistant, sont donc deja collectes et lances parScripts Tests (CPU). Le grep sur.github/workflows/qui m'avait fait conclure a un fichier orphelin ne voyait pas ce cablage : il ne passe par aucun chemin nomme.L'edition du workflow reste dans cette PR, mais pour une raison plus etroite : donner au garde un signal local et rapide sur ses propres tests (quand ce fichier change, c'est le workflow du garde qui tourne en premier, pas seulement la suite large). Si le relecteur prefere le diff minimal, cette partie peut etre retiree sans rien casser — les tests tourneraient quand meme, par
Scripts Tests (CPU).🤖 Generated with Claude Code