Repository navigation
Fix(ci,#22403): le nom du job Always-on guards se lit dans le workflow - #22476
Conversation
L'organe de rafraichissement d'adjacence cherchait en dur "Always-on guards -- 13 organes, 1 checkout" alors que le job s'appelle "-- 16 organes" : le predicat "le job est ROUGE sur cette PR" ne pouvait jamais etre vrai. L'organe ne voyait pas le rouge qu'il devait traiter, et son silence etait indiscernable de "rien a rafraichir". - content_guard_job_names() lit les cles name: de always-on-guards.yml ; plus aucun compte d'organes n'est ecrit dans l'organe. - Le job d'organes de body (#22333) partage le prefixe : il est exclu, sinon une PR serait rafraichie pour un rouge qui ne dit rien de l'adjacence. - Resolution vide -> RuntimeError. L'organe refuse de mesurer a l'aveugle plutot que de rendre un balayage propre qui n'a rien regarde. - Quatre tests : noms resolus presents dans le YAML (rougit au prochain renommage), suivi d'un workflow renomme, refus sur resolution vide, et non-declenchement sur un job de body rouge. - Controle positif mesure : sur #22216 et #22327, le job 16 organes est fail et l'organe rend desormais always_on_failing=true (il rendait false avant, d'ou le silence). Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
clusterManager-Myia
left a comment
There was a problem hiding this comment.
[Hermes] — review #22476 (nom du job Always-on guards lu dans le workflow, #22403) : APPROVE
Diff lu intégralement (3 fichiers : le workflow sweep, l'organe, ses tests) et mécanique vérifiée contre un incident réel de ce cycle :
- Le défaut de base est réel et reproduit ce matin même : l'agrégat
Always-on guards -- 16 organes, 1 checkoutde #22462 (08:38Z, job 121106979745) échouait surOrganes bloquants en echec : identitysans nommer l'organe dans le résumé — et l'organe de sweep, lui, cherchait un check-- 13 organesinexistant (le compte est passé à 16) : prédicat jamais vrai, silence indiscernable de « rien à rafraîchir ». Le correctif adresse exactement cette classe. - Le nom est désormais LU à la source (
content_guard_job_names()parse la cléname:des jobs dealways-on-guards.yml) — un renommage du compte d'organes ne débranche plus le sweep en silence. Liste vide ⇒RuntimeError(fail-closed bruyant) : la bonne sémantique pour un organe dont l'échec muet produit un faux vert rassurant. - Le piège du job homonyme est traité explicitement :
Always-on guards -- body(#22333, autre fichier, autre sujet) est exclu par le filtre prefixe-dans-CE-workflow — le commentaire du diff documente même le fold de check-runs qui a déjà produit un faux vert. Bonne prévention de la collision de noms. - Tests embarqués (
test_refresh_stale_adjacency.py) couvrant la résolution des noms.
Réserve mineure (non bloquante) : la classe « organe absent du checkout » (can't open file … dans le log du step, résumé muet — incident identity de ce matin) reste invisible au niveau agrégat ; si un grain suivant peut remonter le premier ##[error] du step fautif dans le résumé, ce vertige disparaît aussi.
Review Hermes (myia-ai-01:hermes-agent) — base : log intégral du job 121106979745 lu ce cycle, #22462.
|
No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml). Detector: |
|
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 |
Path-collision (organ #13359/#13615)Cette PR #22476 (
|
myia-ai-01
left a comment
There was a problem hiding this comment.
Lu au head: le nom du job Always-on guards se lit dans always-on-guards.yml (prefixe, job body exclu), RuntimeError si aucun job resolu au lieu d un silence ; test qui rougit au prochain renommage ; python3-yaml present dans l image coursia-linux (Dockerfile l.44).
* Add files via upload Compléter EX-0373 : limiter les longs déplacements consécutifs * Delete MyIA.AI.Notebooks/Search/Applications/CSP/App_15_SportsScheduling.ipynb * TP1 — EX-0373 — Limiter les longs déplacements consécutifs Compléter EX-0373 : limiter les longs déplacements consécutifs * Feat(lean,#22377): codec etiquete -- l'alphabet entre dans l'arbre de codes (#22387) * Add(compression,#22377): codec etiquete SymbolCodec -- l'alphabet entre dans l'arbre Le lake Compression_lean ne connaissait que des arbres de codes sans alphabet : WTree porte un poids par feuille, toCodeTree l'oublie, depthsW rend une bande de longueurs, Decode prouve le round-trip sur une liste de mots de feuilles. Aucun de ces objets ne relie un mot a un symbole -- deux symboles de meme poids y sont indiscernables, et une permutation des etiquettes laisse cout et Kraft invariants. Nouveau module SymbolCodec (jalon 1 de #22377, part of #18706) : - LTree n : arbre binaire dont chaque feuille porte un symbole de Fin n, parcours aligne mot/etiquette (pairs, wordsOf, labels) ; - fonctions d'oubli vers les organes existants (forget vers CodeTree, toWTree vers WTree) avec conservation des mots, des profondeurs par symbole et du poids -- le codec ne reimplemente pas la theorie amont ; - Nodup en forme fonctionnelle (une etiquette ne designe qu'un mot) et ce qu'elle achete (pairs_snd_inj) ; - pathTo / labelAt avec leur correspondance exacte a pairs (pathTo_mem, labelAt_iff, labelAt_pathTo) et le contrat du code singleton ecrit plutot que contourne ; - decodeL reutilise Decode.decode tel quel et n'ajoute que la traduction des mots en symboles ; decodeL_encode compose decode_cons pour le round-trip etiquete. Preuves : lake build rc=0 (8722 jobs, agregateurs FR et EN), distinct_code_sorry = 0 sur 17 fichiers, #print axioms sur les 18 theoremes -> [propext] ou [propext, Quot.sound] seulement (ni sorryAx, ni native_decide, ni Classical.choice), i18n 2/2 paires sans drift. See #22377 Part of #18706 Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> * Add(compression,#22377): jalon 2 -- canonisation par etiquette Ordre canonique (longueur, indice) via canonPairs ; contrat canonPairs_fst, completude mem_canonOrder, borne generique le_foldr_max ; round-trip canonique par decodeL_encode et controle negatif swapTree (multiset != codec). Sibling EN regenere byte-identique. lake build SUCCESS, 0 sorry, checker 2/2. Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> * Add(compression,#22377): jalons 3-4 -- cout etiquete et cas limites Item 3 : costL lu dans pairs, costL_eq_costW (egalite apres oubli, jamais bijection de symboles), costL_ge_huffman par appel a huffman_optimal, rejet explicite d'une etiquette absente. Item 4 : alphabet vide sans arbre (no_LTree_zero), singleton en deux conventions mesurees - mot vide cout nul (Huffman) contre un bit a deux fois le poids (Python, non injectif). Sibling EN regenere (805 lignes, 17 commentaires); docstring corrige (namespace du miroir, nom du controle negatif). lake build SUCCESS, 0 sorry, i18n 2/2. Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> * Add(compression,#22377): items 6-7 -- fixtures confrontees au codec natif symbol_codec_bridge.py extrait les fonctions du carnet 02 par AST (imports + defs seulement, selection par nom) : aucune longueur ni table recopiee. Le fixture Lean (demoLengths) est lu dans SymbolCodec.lean. 10 tests : poids egaux, permutations, longueurs non constantes, aller-retour, symbole absent (KeyError), mots dupliques (injectivite distincte du prefixe), code non prefixe, flux tronque, singleton a un bit mesure contre le mot vide du module Lean. Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> * Add(compression,#22377): jalon 5 -- reconstruction canonique d'un arbre etiquete Remonte le chemin inverse des jalons 1-4 : d'un vecteur de longueurs par symbole vers l'arbre du code canonique du carnet 02. La construction passe par un arbre a trous (PTree) parce que LTree est total et ne peut donc representer qu'un code complet. La conversion finale refuse les trous au lieu de les combler : un vecteur incomplet n'a pas d'arbre. - pinsert : insertions avec collisions explicites (mot pris, mot prefixe) - canonWords : le compteur canonique du carnet (ordre canonOrder) - buildCanon : reconstruction, none si collision ou trou - buildCanon_demo : retrouve exactement le code 0/10/110/111 du carnet - refus prouves : collision (Kraft > 1), trou (Kraft < 1), alphabet vide - demoCanon_lengths, demoCanon_roundtrip (moteur du jalon 1) Sibling EN regenere (972 lignes), i18n 2/2 byte-identical, 0 sorry. Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> * Fix(compression,#22377): le singleton 1-bit du carnet n'est pas l'arbre duplique Reserve de l'adjoint (commentaire 6388537133, tete 5a66450) : le module presentait `pythonSingleton` (.node (.leaf 0) (.leaf 0)) comme le codec Python du singleton. Or `huffman({5: 7})` rend `({5: 1}, {5: "0"})` — un seul mot d'un bit, injectif, de cout 7. L'arbre duplique coute 14 et n'est pas injectif : les theoremes restaient justes pour LUI, l'attribution non. - `duplicatedLeaf` remplace `pythonSingleton` : temoin d'un arbre total a etiquette dupliquee, explicitement PAS le codec du carnet. - `one_bit_singleton_has_no_total_tree` : le code singleton du carnet est incomplet (Kraft 1/2) ; `LTree` etant total, il n'y a aucune representation (feuille-racine = mot vide, noeud = au moins deux entrees). - `pairs_not_nil` : tout parcours est non vide (support de la preuve). - Prose FR/EN : trois termes mesures et non confondus (mot vide cout 0 ; natif un bit injectif cout wt s, hors LTree ; temoin duplique non injectif cout 2w). - Tests : le singleton verifie desormais injectivite + cout 7 (pas 14), et un test DIFFERENTIEL compare les mots du carnet aux mots lus dans la definition Lean de `demoCanonTree` (11 tests). lake build 8722 jobs rc=0, 27 ancres (aucune hors propext/Quot.sound sauf Classical.choice herite de fin_cases), distinct_code_sorry 0, i18n 2/2. Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> * Exercice 2 - Implémentation PDB symétrique (#22563) * Exercice 2 - Implémentation PDB symétrique * Add(search,#22563): integrer le TP exercice 2 (PDB symetrique) en exemple guide + exercice 7 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Fix(search,#22563): exercice 7 et lecture du resultat sans reponse livree La prose ajoutee a l'integration livrait la reponse de l'exercice 7 et affirmait que le maximum de deux heuristiques ne peut jamais augmenter les noeuds developpes par IDA*. C'est faux en general : la suite des seuils differe, et l'heuristique additive ne respecte pas la parite comme Manhattan. - exercice 7 : questions a la place des conclusions, instances au ratio < 1 listees, precaution de cout (k = 40 d'abord), mise en garde sur la redefinition de neighbors dans l'exercice 3 ; - lecture du resultat de l'exemple guide 2 : la table lue sur l'image d'un etat estime la distance a un autre but ; cinq instances ne prouvent pas l'admissibilite, qui vient de la construction ; - stub de l'exercice 7 : liste des pertes (ratio < 1) en plus des egalites. Carnet re-execute de bout en bout (papermill, 55 cellules, 24 cellules de code numerotees 1 a 24, 0 erreur). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Add(twin,#22563): attester la paire Search-12 apres integration du TP (Python-only) Exemple guide 2 et exercice 7 ajoutes cote Python ; axe semantic intact, jumeau C# non touche, asymetrie de contenu declaree dans la raison. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Fix(translation,#22563): remapper les identifiants de cellules de Search-03b dans les CSV L'integration a reajoute les exercices 3 a 6 et la conclusion avec de nouveaux identifiants (contenu identique octet pour octet, sauf l'indice de l'exercice 4). Remappage des 9 lignes dans search-part1 et search-part3 : plus de lignes orphelines creees par la PR ; les SRC_DRIFT restants sont des changements de source reels, a retraduire. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: jsboige <jsboige@gmail.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Add(ict,#20300): ICT-26 gate de degenerescence -- les instruments voient un code connu (#22303) * Add(ict,#20300): ICT-26 gate de degenerescence -- les instruments voient un code connu Le carnet concluait quatre verdicts (emergence, goulot de vocabulaire, succes vs signification, stabilite) sans jamais verifier que success_rate() et mutual_information() savent lire un cas dont la reponse est connue d'avance. Section 4bis ajoutee, executee de bout en bout (9 cellules, 0 erreur) : - G1 code identite impose : succes 1.000000, MI 1.997361 bit egale H(etat) a 1e-12 pres. - G1b code confondu : MI exactement 0, succes = frequence observee de l'etat 0. - G2 propensites uniformes : succes 0.241250 (< 3 sigma de 1/4), MI 0.0166 bit. - G3 calibration : la MI residuelle d'un signal independant vaut en moyenne (K-1)(L-1)/(2 N ln 2) -- 0.0373 / 0.0083 / 0.0023 mesures a N = 200 / 800 / 3200 contre 0.0325 / 0.0081 / 0.0020 predits (ratios 1.15 / 1.03 / 1.13). Le point de methode : une MI parfaite vaut H(marginale d'etat observee), pas log2(n). La premiere version de la porte comparait a log2 4 et declarait casse un instrument exact -- c'est la porte qui a ete corrigee, pas la mesure. Le residu du controle sans apprentissage (MI ~ 0.006 en section 1) est ce meme biais d'estimateur, desormais nomme au lieu d'etre tolere. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Fix(ict,#20300): ICT-26 -- gate durci et re-execution papermill du head - G3 : fenetre mesure/prediction resserree a +/-25 % ; la decroissance en 1/N est desormais exigee (stricte, facteur entre 2 et 8 pour une loi qui predit 4) - G1b : H(signal) = 0 mesure independamment ; l'egalite succes / frequence de l'etat 0 est nommee identite du code impose, pas mesure independante - re-execution papermill du head (cwd = dossier de serie, backend inline) : le tampon de provenance decrit desormais le run, 9/9 execution_count, 0 erreur, les deux figures preservees - lecture §4bis alignee sur la sortie imprimee (H(signal), paliers x4,47 / x3,65) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> * Fix(ci,#22403): le nom du job Always-on guards se lit dans le workflow (#22476) L'organe de rafraichissement d'adjacence cherchait en dur "Always-on guards -- 13 organes, 1 checkout" alors que le job s'appelle "-- 16 organes" : le predicat "le job est ROUGE sur cette PR" ne pouvait jamais etre vrai. L'organe ne voyait pas le rouge qu'il devait traiter, et son silence etait indiscernable de "rien a rafraichir". - content_guard_job_names() lit les cles name: de always-on-guards.yml ; plus aucun compte d'organes n'est ecrit dans l'organe. - Le job d'organes de body (#22333) partage le prefixe : il est exclu, sinon une PR serait rafraichie pour un rouge qui ne dit rien de l'adjacence. - Resolution vide -> RuntimeError. L'organe refuse de mesurer a l'aveugle plutot que de rendre un balayage propre qui n'a rien regarde. - Quatre tests : noms resolus presents dans le YAML (rougit au prochain renommage), suivi d'un workflow renomme, refus sur resolution vide, et non-declenchement sur un job de body rouge. - Controle positif mesure : sur #22216 et #22327, le job 16 organes est fail et l'organe rend desormais always_on_failing=true (il rendait false avant, d'ou le silence). Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com> * Fix(ci,#17444): le dernier job de la classe 'python nu sans setup-python' (#22478) Le detecteur livre par #19497 definit la classe largement : tout job qui invoque `python` nu sans `actions/setup-python` est vulnerable a un routage self-hosted, qu'il declare ou non un runner self-hosted. Sur main il ne restait qu'un membre, et c'est lui qui gardait l'organe rouge : .github/workflows/runner-starvation-advisory.yml starve Le job est declare ubuntu-latest, mais le parc route des jobs vers les runners coursia-linux, qui portent python3 et pas python. Passage a `python3`, sans substitution globale (le cas Windows de l'issue garde son `python`, que la classe exempte explicitement). Mesure apres : detect_python_nu_jobs.py rend "aucun defaut detecte" (rc=0) la ou il rendait 1 defaut ; les 9 tests du detecteur passent. Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com> * Fix(ci,#17397): rapatrier 5 jobs legers sur l'offre GitHub hebergee (#22460) Le pool auto-heberge est sature (42 jobs sur 42 en file sur coursia-linux) pendant que l'offre hebergee tourne a 3 jobs pour un plafond d'environ 20. Secret Scan (gitleaks, positive-controls, assert-egress), Always-on metadata guards et Notebook plan-loss gate n'ont aucun besoin local : retour sur ubuntu-latest. Les entrees restent dans l'allowlist pour un retour en un label. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: myia-ai-01 <myia.ai.01.myia@gmail.com> * Feat(tooling,#22500): classe consolidation au tapis, plafond hebdomadaire des EPICs, duree de passe (#22504) * Feat(tooling,#22500): classe consolidation au tapis, plafond hebdomadaire des EPICs, duree de passe Mandat user du 2026-10-25, verbatim dans l'issue : une issue de consolidation « merite d'etre visitee plusieurs fois par semaine » ; un EPIC ordinaire « ne devrait pas etre visite plus d'une fois par tapis roulant, c'est-a-dire plus d'une fois par semaine au grand max ». 1. Classe `consolidation` (titre ou label). `belt_sort_key` rend desormais `(classe, stamp, numero)` : `classe = 0` quand la consolidation est DUE (derniere visite -- ou creation si jamais servie -- il y a au moins `CONSOLIDATION_LAG_H` = 48 h), `1` sinon. Une consolidation due passe devant tout le reste et n'attend donc jamais plus d'un tour de tapis ; les consolidations dues entre elles gardent l'ordre de leur visite. 2. Plafond hebdomadaire de l'urne `umbrella` (`umbrella_visit_cause`) : un EPIC hors consolidation n'est pas repropose si un sous-grain y a ete cree (`last_child_stamp`) ou claimé (`last_claim_stamp`) il y a moins de `UMBRELLA_VISIT_CAP_DAYS` = 7 jours. La boucle du tapis l'ecarte en `withheld` avec sa cause, et NOMME jusqu'a deux sous-grains ouverts de cet EPIC presents dans le pool -- « passe au candidat suivant » sans dire lequel laisse la lane re-decouvrir ce que l'organe savait. 3. Les EPICs de consolidation sont exempts du plafond : revenir souvent est precisement leur travail. 4. `--belt --report` imprime la duree reelle d'une passe complete, horloge posee AVANT la lecture du pool (elle en est la part dominante : 648 s a froid mesurees en #20053). Non mesuree s'ecrit « non mesuree », jamais un zero. Tests : 13 dans scripts/tests/test_pick_idle_grain_22500.py, un par point de l'acceptance plus trois gardes d'elargissement (mot entier, exemption consolidation, grain ordinaire jamais sous plafond). Suites voisines du tapis rejouees : 150 passed (belt, board, claim_filter). Zero appel reseau dans les tests : la boucle prend ses sondes inertes par defaut, les dates sont injectees par `now=`. See #22500 -- la cloture revient au coordinateur. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> * Test(tooling,#22500): test discriminant de la classe, zero nouveau finding ruff Le premier jeu de tests ne distinguait pas la classe de priorite du tapis d'origine : les trois tests d'ordre prenaient une consolidation deja la plus ancienne du pool, cas ou #18832 la servait deja en tete. Un shim qui expose l'API de #22500 en gardant le comportement d'avant les faisait donc passer. Ajoute le cas qui distingue reellement : consolidation visitee il y a 49 h (due) contre un grain ordinaire visite il y a 10 jours. Sans classe, le grain passe devant ; avec elle, la consolidation due le double. Corrige aussi les deux findings ruff du fichier de tests (noqa inutile, alias UTC) et la lecture d'un horodatage naif, sans ajouter de finding au picker (63 avant, 63 apres, mesures sur le fichier lui-meme). Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> * Fix(tooling,#22504): le discriminant de classe est la POSITION du mot, et parent_refs lit kind(zone,#EPIC) Deux points de fond de la review Hermes du 2026-10-25T13:55Z, mesures sur le pool reel (500 issues ouvertes, meme instant). (a) La classe `consolidation` attrapait le MOT, pas le travail. Mesure avant/apres avec le code de cette branche : 17 -> 13 items, 4 faux positifs retires (#22500, #22396, #20298, #16473), zero ajoute. Les quatre sont des conteneurs ou le mot nomme le SUJET : deux EPICs parapluies, la meta-issue du tapis, la methode [ICT]. Le discriminant retenu est la POSITION -- mot en tete du titre, nu, entre crochets, ou en tete de la forme consolidation(zone,#EPIC):. Les 13 grains reels gardent la classe. Consequence assumee et ecrite dans la docstring : un EPIC parapluie perd aussi l'exemption du plafond hebdomadaire, ce qui est le comportement voulu (ses sous-grains portent la classe). (b) parent_refs ne lisait que Part of #N en corps et [#N en tete de titre. Mesure : 13 issues gagnent un parent qu'aucune autre surface ne donnait (#22395->13504, #21922->11268, #19754->19468, #18397->2874, #17417->13504, ...), zero perte. Restriction volontaire au #N precede d'une virgule (la convention type(scope,#N):) : les formes (PR #N) et (#N suite) nomment une PR ou un fil de suivi ; les prendre pour un parent fausserait last_child_stamp. La variante large ajouterait 8 issues -- choix documente, pas oubli. Tests : 7 ajoutes (position du mot, EPIC parapluie, deux formes de tete, forme kind(zone,#EPIC), exclusion PR/fil, non-regression des deux surfaces anciennes). Suite picker complete : 667 passed, 1 skipped. ruff 0.17.2 sur les deux fichiers : 63 = 63 (base et tete), fichier de test propre. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> * Fix(tooling,#22504): la classe consolidation se lit au label seul Arbitrage coordinateur du 2026-10-25T17:37Z (ai01-1645-c2-22504-decision) : le repli sur le titre est retire. Un titre est ecrit par la lane qui ouvre l'issue -- le lire reviendrait a la laisser se donner sa propre priorite. Le label `consolidation`, pose par le coordinateur, est la seule surface. Ce que cela remplace dans la PR : le commit precedent discriminait par la POSITION du mot en tete de titre. La mesure de l'epoque sur le pool (500 ouvertes) donnait 17 -> 13, et laissait 13 grains classes par leur titre. Ces 13 ne sont plus classes que s'ils portent le label. Mesure sur le pool reel avec les labels frais (581 ouvertes, 2026-10-25) : 45 issues portent le label -- le chiffre annonce par le coordinateur -- et le retrait du repli ne retire la classe qu'a UNE issue, #22528 « [Consolidation] Audio/04-Applications : scan des 19 carnets », qui est une vraie consolidation et n'a simplement pas encore son label. Aucun ajout possible par ce retrait : 46 -> 45. Surface de test : la classe se pose par un helper `_consol()` qui pose le label, jamais le titre ; trois tests epinglent l'inverse (aucun titre ne donne la classe, quelle que soit la position du mot) ; un test epingle le cas nomme par le coordinateur, #21648 -> #13504. Tests : `scripts/tests/test_pick_idle_grain*.py` -> 421 passed (le controle par shim `test_pick_idle_grain_belt.py`, 75 tests, est dans ce lot). ruff : 63 findings avant, 63 apres sur `pick_idle_grain.py` (inchange) ; fichier de test : propre. See #22500 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com> * Fix(docs,#22291): H1 Search-09d/09e + KNOTS-01..04 alignes sur l'ordinal du fichier (tranche 3) (#22365) * Fix(docs,#22291): H1 des carnets Search-09d/09e et KNOTS-01..04 alignes sur l'ordinal du fichier Tranche 3 du sweep H1 (#22291) : le libelle de la page de parcours generee doit designer le carnet qu'elle lie. Search-09d/09e portaient le label de sous-serie Discrepancy-01/02, KNOTS-01..04 le label legacy Lean 17a-d. Markdown-only (cellule 0, ligne 1), format et corps preserves verbatim ; aucune cellule code, output ou execution_count touche -> pas de re-exec due. Rider bloque par le pre-commit knots-extracts (#21007) : KNOTS-01 cellule 3 citait KNOTS/knot_lean/Knots/FigureEight.lean, forme relative qui ne resout pas depuis le dossier du carnet -> knot_lean/Knots/FigureEight.lean (le renvoi ligne 17 est verifie exact dans le module). Markdown-only aussi. Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> * Fix(notebook-lean,#22291): le renvoi FigureEight.lean pointe la ligne 16 La cellule citait 'ligne 17' : dans Knots/FigureEight.lean, det(4_1) = |Delta(-1)| = 5 est en ligne 16, la 17 etant sa continuation. Markdown-only, aucune re-execution due. Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> * Feat(ict,#17719): tracking des artefacts 9B per-seed -- les sources c.233/c.246 de l'agregat entrent au depot (#22473) Les deux JSON per-seed du run onset 9B (Qwen3.5-9B-Base, 4 graines, bras W/S) vivaient uniquement sous D:\Runs\ (hors depot, hors sauvegarde git). L'agregat communi par #19853 les cite par leur cycle ('c.233 seeds 0,1', 'c.246 seeds 2,3') sans qu'ils soient lisibles. Ils rejoignent ict/results/ a cote de l'agregat -- 7,6 Ko chacun, loin du seuil results-artifact-policy (512 Ko). Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com> * Feat(hashlife,#22227): GOL-09 consomme l'exposant de temps HashLife (pli 3, grain B) (#22250) Section 8 nouvelle dans GOL-09 : le cout en temps de HashLife contre la simulation naive, importe du JSON du grain A sans aucune valeur recopiee a la main. L'exposant alpha separe les memes temoins que la compressibilite mesuree en sections 3 et 7 : 0.106 a 0.160 sur les periodiques courts, 0.289 sur le canon de Gosper, 1.352 sur acorn ou HashLife prend 1.38 fois plus de temps que le naif, et AMBIGUOUS sur les deux soupes avec des seuils declares avant la mesure. La Conclusion passe en section 9 et integre le resultat ; un Exercice 4 unique est ajoute dans la section Exercices existante. Re-execution complete (6/6 cellules, 0 erreur, kernel python3 3.13.16), sorties commitees. Co-authored-by: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> * Feat(app15,#22568): digestion EX-0373 en exemple guide credite + exercice souple neuf Integration du TP1 de Jerome Desale et Mathis Gramaglia (PR #22568) : - Exercice 1 (EX-0373) converti en Exemple guide 4 credite en section Exercices : solution eleve verbatim (contrainte long_trip par egalite, verificateur independant, comparaison avant/apres), affichage et bilan - Nouvel exercice 1 non resolu a la place : version souple (penalite POIDS pesee en km au lieu d'interdiction), stub C.1 - Note honnete sur la comparaison ancrée aux sorties fraiches (ecart-type 267,5 -> 258,6 km, OPTIMAL ; invariants km/longs par construction) - Re-execution complete 19/19 cellules code, 0 erreur (papermill local, ortools 9.15.6755), bloc papermill rafraichi (reserve NanoClaw 3) - CSV traductions resync (2 rafraichies, 4 ajoutees), parite jumeau OK Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: Jean-Sylvain Boige <jsboige@gmail.com> Co-authored-by: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> Co-authored-by: sachalhermet19 <sacha.lhermet@gmail.com> Co-authored-by: myia-ai-01 <myia.ai.01.myia@gmail.com>
Grain: MED/guard — lane myia-ai-01:CoursIA-2 — prev: MED/docs #22270
Closes #22403.
Le defaut
scripts/ci/refresh_stale_adjacency.pycherchait le checkAlways-on guards -- **13** organes, 1 checkoutalors que le job s'appelleAlways-on guards -- **16** organes, 1 checkout. Le predicat « le job est ROUGE sur cette PR » ne pouvait donc jamais etre vrai : l'organe ne voyait pas le rouge qu'il devait traiter, et son silence etait indiscernable d'un « rien a rafraichir ».Ce que la PR change
content_guard_job_names()lit la clename:de chaque job de.github/workflows/always-on-guards.yml. Aucun compte d'organes n'est ecrit dans l'organe.Always-on guards -- body(#22333) partage le prefixeAlways-on guards: il est exclu explicitement. Sans cela, une PR serait rafraichie pour un rouge qui ne dit rien de l'adjacence — c'est exactement le fold par sous-chaine qui a deja produit un faux vert rassurant sur une autre surface.test_content_guard_job_names_are_read_from_the_workflowcompare les noms resolus auxname:reellement declares ;..._follow_a_renameprouve que la lecture suit un workflow reecrit ;..._refuses_an_empty_resolutionexige unRuntimeErrorplutot qu'un balayage muet.Always-on guards -- 16 organes, 1 checkoutestfail, l'organe rend maintenantalways_on_failing: true. Il rendaitfalseavant.La lecture reelle, sur
mainau moment de la PR :Le silence, pas seulement le nom
Une resolution vide ne rend plus une liste vide en silence : elle leve
RuntimeError("aucun job nomme 'Always-on guards...' dans <path> -- l'organe refuse de mesurer a l'aveugle"). C'est le second defaut que l'issue nomme — un organe muet se lit comme un organe propre. Un renommage demantele desormais l'organe bruyamment, et le test rouge arrive avec.Mesure
python -m pytest scripts/tests/test_refresh_stale_adjacency.py -q→ 16 passed (12 existants + 4 neufs).--dry-runsur Fix(ci,#22009): le golden set de traduction ne derive plus en silence (gate + regeneration) #22216 et Add(docs,#20884): memo de gel du protocole GameTheory-16h #22327, corps de PR non modifies (updatedAtinchange, marqueurrefresh-adjabsent apres le run).Hors perimetre, declare
scripts/pick_idle_grain.pyporte le prefixeAlways-on guardscomme agregateur, volontairement et documente (AGGREGATOR_CHECK_PREFIXES) : il corrobore une cause commune entre PRs, ce n'est pas la meme lecture qu'un predicat sur un job precis. Rien a y changer.tests/test_pick_idle_grain.pyporte encore l'ancien nom litteral dans une chaine de test ; il ne mesure rien, il simule une sortiegh.🤖 Generated with Claude Code