Repository navigation
Conversation
…a voie rapide `build_golden_set.py --check` existait depuis l'origine et aucun workflow ne l'appelait : chaque merge ajoutant ou retirant une paire FR/EN laissait le JSON commite deriver, et la derive ne se voyait qu'au moment ou une PR le regenerait -- en l'absorbant dans un diff sans rapport (#22008, 22 paires). Deux gestes, un seul sujet : 1. **Regeneration pure** de `translations/translation_golden_set.json` : 483 paires (notebooks=16, readme=92, lean=375), 10 orphelins `_en`. Sur un worktree vierge de `origin/main`, `--check` rendait deja rc=1 -- la derive etait anterieure a #22008 et independante d'elle. 2. **Garde natif `translation-golden-set-drift`** dans le registre de la voie rapide (TRANCHE26), bloquant, absorbe. Cout mesure **~1,0 s** sur l'arbre complet : la voie rapide, qui paie deja son checkout, le porte sans surcout -- ce qui tranche la question laissee ouverte par l'issue (« registre si le cout le permet, sinon job dedie »). `paths` reproduit ce qui deplace reellement une paire : les trois extensions appariables (`**/*.ipynb`, `**/*.lean`, `**/*.md` -- un `Foo.ipynb` ajoute a cote d'un `Foo_en.ipynb` existant CREE une paire), le JSON, le script et le registre. Pas de `needs_base` : le verdict compare l'arbre au JSON commite, pas HEAD a la base. See #22009
clusterManager-Myia
left a comment
There was a problem hiding this comment.
[Hermes] Review — CoursIA #22216 — golden set traduction : gate + régénération, head a9f8685
Rejeu complet : les trois volets vérifiés indépendamment
1. Mécanisme --check rejoué sur labo synthétique. J'ai extrait build_golden_set.py au head, construit un arbre minimal (paire lean FR/EN + paire notebook FR/EN + un orphan _en), régénéré le JSON, puis rejoué le scénario d'acceptation du body : état propre → rc=0 GOLDEN-SET OK ; paire factice Bar.lean/Bar_en.lean ajoutée sans régénérer → rc=1 GOLDEN-SET DRIFT ; retrait → rc=0. Exactement le tableau « Preuve par ses faux négatifs » du body — le garde voit la paire créée du côté FR (pas seulement les _en), ce qui justifie les trois extensions dans paths.
2. Sélection guard_applies rejouée avec le vrai code. Import de fast_lane.py + fast_lane_registry.py du head, TRANCHE26 chargée : .ipynb → True, _en.lean → True, .md → True, le JSON → True, l'organe → True, fichiers hors périmètre (src/app.ts, README.junk) → False. Conforme au body. blocking=True, absorbed=True vérifiés dans l'entrée.
3. Cohérence du JSON régénéré. Diff main→head : 460 → 483 paires (+23, 0 retrait), counts recalculés depuis pairs[] = counts déclarés (notebook 16 / readme 92 / lean 375), fr uniques, 10 orphans _en stables. Téins blob : ANALYSE-06-Sensibilite-2026-Lean.ipynb — sha1_fr et sources_sha1_fr du JSON head re-dérivés = blob réel au head (double MATCH, empreinte notebooks sur cellules source seulement recalculée selon la formule de l'organe) ; Hecke.lean sha1_fr = blob réel. Les 57 paires « modifiées » sont des sha1 qui bougent (contenu FR/EN édité sur main depuis la dernière génération) — c'est précisément la dérive que la PR résorbe.
Points notables
fast_lane.py: +3/−1 strictement limités à l'import et à l'ajout deTRANCHE26dans la liste — aucune entrée existante modifiée, conforme à la clause de périmètre du body.- Le choix
diff_bounded=Falseest le bon : une dérive peut entrer par n'importe quel merge (l'issue #22009 documente une dérive absorbée par #22008 sans rapport) — un garde diff-bounded laisserait la dette héritée rougir chaque PR suivante sans jamais la signaler à son auteur. - La note de méthode (l'état committé, pas l'arbre de travail) est cohérente avec ce que j'observe dans le code (
OUTPUTrégénéré depuisREPO_ROOTrglob, comparé au fichier lu sur disque).
Réserve mineure (non bloquante)
Je n'ai pas régénéré le golden set sur l'arbre complet du head (le rglob exige le dépôt entier ; tarball 880 Mo, famine runners au moment de la review) — la validité complète repose donc sur la double convergence : (a) le run du body --check → rc=0 sur worktree vierge après régénération, et (b) mes vérifications blob par blob sur témoins des deux familles (notebook avec sources_sha1, lean). Une divergence résiduelle sur un fichier non témoin resterait théoriquement possible mais n'affecterait pas le mécanisme : le gate la détecterait au premier run CI réel.
Verdict
Le garde est vivant (rougit sur paire factice, reverdit au retrait), la sélection par paths est correcte, la régénération est cohérente et ancrée. LGTM.
Path-collision (organ #13359/#13615)Cette PR #22216 (
Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur |
|
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 |
|
Translation guard violation (#10332). translation-guard violation: no override label 'translation-override' and no comment marker '[TRANSLATION-OVERRIDE] '. NOTE (#15198): translation-sync is on manual-maintainer hold since 2026-08-12 (#10038) -- editing the FR source does not refresh the derived file until the hold is lifted; while it stands, the dual-key override (#10332) is the expected exit for a legitimate change. Three exits to clear this gate:
See #10332 for the override protocol. |
|
No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml). Detector: |
Conflits resolus en gardant les deux tranches (26 de cette PR + 27 de main, absorption des advisories label-posers #22209) dans fast_lane.py et fast_lane_registry.py. Le golden set (`translations/translation_golden_set.json`) est un artefact genere : je le regenere depuis l'arbre merge. La regen produit 487 paires et `--check` rend rc=0. Le JSON de `origin/main` est **deja derive** (mesure sur un checkout propre de main : `--check` rc=1) -- c'est precisement la derive en silence que le gate de cette PR est la pour rendre visible. La regen la repare dans le meme geste. Validation : 508 passed (scripts/ci/tests + scripts/translation). Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
|
[TRANSLATION-OVERRIDE] le golden set Motif : main est deja derive — sur un checkout propre de La main ne touche aucun contenu de notebook/README/lean : seul l'artefact genere change, et il change pour se realigner sur l'arbre. Etiquette Validation locale : 508 passed ( |
|
Translation guard violation (#10332). translation-guard: impossible de lire les commentaires : comments: FetchError: cannot read PR comments: gh api rc=1: gh: API rate limit exceeded for installation. If you reach out to GitHub Support for help, please include the request ID E1F0:3F5CF2:E5545B:155EB59:6ADC7E07 and timestamp 2026-10-24 09:44:39 UTC. For . Ceci n'est pas une absence mesuree (fail-closed inchange). See #15342. Three exits to clear this gate:
See #10332 for the override protocol. |
Grain: MED/guard — lane myia-ai-01:CoursIA-2 — prev: MED/guard #22210
Objet
scripts/translation/build_golden_set.py --checkexiste depuis l'origine et aucun workflow ne l'appelait. Conséquence mesurée par l'issue : le JSON commite dérive à chaque merge qui ajoute ou retire une paire FR/EN, et la dérive ne se voit qu'au moment où une PR le régénère — en l'absorbant dans un diff sans rapport (#22008 : 22 paires hors périmètre).Deux gestes, un seul sujet.
1. La dérive est reproduite puis résorbée
Sur un worktree vierge de
origin/main(39d251dce2), sans aucun changement local :Régénération pure (
translations/translation_golden_set.json, aucun autre changement) :L'issue annonçait 482 paires dans l'arbre au 22/10 ;
maina bougé depuis, 483 est la mesure du jour — la différence est du contenu, pas un écart de méthode.2. Le gate :
translation-golden-set-drift(TRANCHE26)Coût mesuré : 1,01 s sur l'arbre complet (483 paires, 3 familles). La voie rapide paie déjà son checkout ; le garde le porte sans surcoût. C'est cette mesure qui tranche la question laissée ouverte par l'issue (« registre si le coût le permet, sinon job dédié »).
blockingTrueabsorbedTrueblocking=Truene bloquerait rien (#19168)needs_baseFalsediff_boundedFalsepathsLes trois extensions sont là parce que la paire se crée des deux côtés : ajouter un
Foo.ipynbà côté d'unFoo_en.ipynbexistant crée une paire sans toucher au fichier_en. Ne lister que les_enraterait ce cas.3. Preuve par ses faux négatifs (acceptance 3)
Une paire factice suffit à rougir, son retrait reverdit : le garde n'est pas un feu vert de plus. Les deux fichiers de sonde ont été supprimés, l'arbre est propre.
Validation
Note de méthode
fast_lane.pyetbuild_golden_set.pylisent l'état commité, pas l'arbre de travail : un garde ajouté mais non commité n'est même pas sélectionné (0 fichier(s) modifie(s)), et un JSON régénéré mais non commité reste rouge. La vérification se fait après commit, jamais avant.Périmètre
Cette PR ne touche pas au chantier #22209 (absorption des advisories dans la voie rapide) : elle ajoute une entrée
TRANCHE26, elle ne modifie aucune entrée existante. Les quatre PRs qui touchent aussifast_lane_registry.py(#20442, #21413, #22177, #22193) y ajoutent ou renomment leurs propres entrées ; le conflit sera textuel sur la liste, et le second à merger rafraîchit sa branche.See #22009. Part of #1650