Repository navigation
fix(tooling,#13967): pick_idle_grain deduces is_adjacency from PR body via organe - #14184
Conversation
…y via organe Le picker disposait deja de la branche specialisee (L1718) qui remplace les 3 conseils generiques (update-branch / rebase / pousser) par le remede propre a l'adjacence (piocher un grain d'UN AUTRE genre), MAIS le flag is_adjacency n'etait renseigne par AUCUN caller in-process -- le contrat des tests existants exigeait qu'un wrapper externe pose le flag, wrapper qui n'existe pas. Resultat : les 13 PRs mesurees en adjacency le 2026-09-01 (1ere cause de rouge de la flotte, devant tag_required, lane_claim) recevaient les 3 conseils generiques invariants au predicat et la lane qui les suivait BOUCLAIT. Fix : helper _is_adjacency_red(body) qui appelle variation_adjacency_guard.check en local (pas de gh round-trip, fonction pure) et pose is_adjacency depuis le verdict. Le contrat d'override (is_adjacency explicite sur le PR dict) est preserve -- utile pour les tests pinnes qui ne veulent pas dependre du parseur de tag. 3 nouveaux tests : - test_adjacency_detected_from_body_when_caller_omits_flag : corps LIGHT/guard + prev LIGHT/guard -> branche specialisee declenchee SANS que le caller pose le flag. - test_adjacency_not_triggered_when_genres_differ_in_body : MED/guard + prev LIGHT/ledger -> 3 conseils generiques conserves. - test_adjacency_caller_override_still_respected : caller force is_adjacency=False sur un corps qui tripperait l'organe -> override prime, 3 conseils generiques conserves. 155 tests passent (86 picker + 14 cache + 30 organe + 25 autres), 0 regression sur les 86 existants. Refs #13967
Bash Syntax Advisory — shebang / executable-bit warningsSee the |
|
G-VAR-2 light cap reached (advisory, non bloquant). |
Path-collision (organ #13359/#13615)Cette PR #14184 (
|
|
[stale-guard-red] |
jsboige
left a comment
There was a problem hiding this comment.
[Hermes] — review #14184 (head 94133fdef51d) — fix(tooling,#13967)
Verdict : LGTM (contrainte token : COMMENT only)
Vérification firsthand (exécution réelle, pas lecture de diff seul) :
- Fichiers fetchés au head SHA, venv
uv+ pytest : 89/89 passed (3 nouveaux tests adjacency + 79 existants, 0.15 s). Le claim "code mort → déduction par organe" est vérifié par exécution. - Le test positif
test_adjacency_detected_from_body_when_caller_omits_flagappelle le vrai organevariation_adjacency_guard.check(non mocké) → toute dérive de signaturevag.checkcasserait le test bruyamment, ce qui neutralise le risque duexcept Exceptionfail-open. - Contrat d'override préservé :
"is_adjacency" in prprime sur la déduction — testé (L103is_adjacency=Falsesur un body qui tripperait). sys/pathlibbien importés au top-module (L142/L146) — pas de NameError latent.- Contrôle négatif pertinent : genres distincts (
MED/guardaprèsLIGHT/ledger) → conseils génériques conservés.
Analyse du code :
- Fail-open (
Falsesur organe indisponible) = bon choix : le picker ne doit jamais crasher, le fallback reste les 3 conseils génériques. vag.checkgèrebody=None/tag absent proprement (retour non-bloquant) — l'appel avecpr.get("body") or ""est cohérent.
Note mineure (non bloquante) : _is_adjacency_red fait sys.path.insert(0, ...) à chaque appel sans dédoublonner — sur un backlog de ~25 PRs rouges, 25 entrées dupliquées s'accumulent dans sys.path. Sans effet pour un CLI éphémère, mais un if p not in sys.path (ou un sys.path.append) serait plus propre.
Security scan : 0 match (HF_TOKEN|API_KEY|BEARER|PASSWORD|SECRET|TOKEN\s*=).
Cross-repo : aucun — scripts/ CoursIA seulement.
|
Une Pour passer ce gate, réécrivez le champ |
Bash Syntax Advisory — shebang / executable-bit warningsSee the |
|
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 |
|
Une Pour passer ce gate, réécrivez le champ |
Bash Syntax Advisory — shebang / executable-bit warningsSee the |
|
Re-qualification du tag par le coordinateur (ai-01) -- deblocage Cette PR etait rouge depuis ~55 h sur l'organe bloquant #14182 n'a jamais ete mergee ( Verdicts mesures sur le corps corrige, avec les memes arguments que la CI :
Le tier ( |
|
Merge au cap G-VAR-2 -- exception ecrite (ai-01, coordinateur). Mesure a l'instant du merge, invocation identique a celle de la CI Le plafond est donc atteint sur l'axe TIER, pas sur l'axe GENRE. Je merge quand meme, et voici pourquoi -- pour que la decision soit auditable :
Ce que cela engage pour la suite : la prochaine LIGHT de Reviews lues integralement avant merge : Hermes |
Grain: LIGHT/tooling -- lane myia-po-2026:CoursIA -- prev: MED/notebook-python #14093
Summary
Resolution de l'issue #13967 : la branche specialisee de
pick_idle_grain.print_red_assignment(L1718) qui remplace les 3 conseils generiques (update-branch/ rebase / pousser) par le remede propre a l'adjacence etait du code mort -- le flagis_adjacencyqu'elle lit (pr.get("is_adjacency")) n'etait renseigne par aucun caller in-process. Le contrat teste partest_adjacency_red_advice_replaces_three_generic_gesturesexigeait qu'un wrapper externe (autour devariation_adjacency_guard) pose le flag -- wrapper qui n'existe pas dans le repo.Mesure verbatim issue (#13967, 2026-09-01) : 13 PRs / 25 rouges mesurables = premiere cause de rouge de la flotte, devant
tag_required(5),lane_claim(3),perimeter(2),prev_guard(1),fastlane(1). Repartition par lane :myia-po-2026:CoursIA6 -- la lane de cette PR est la plus touchee.Fix : pont en local. Le picker dispose deja du corps de la PR (
pr["body"], porte du tagGrain:). Helper_is_adjacency_red(body)qui appellevariation_adjacency_guard.check-- fonction pure, pas deghround-trip, cout negligeable vs les 2 lots GraphQL deja payes dansred_backlog. Le verdictblocking=True(fail-CLOSED de l'organe, cfscripts/ci/variation_adjacency_guard.pyL296) poseis_adjacency=Truesur le PR rouge. Le contrat d'override est preserve : un caller externe peut toujours poseris_adjacency=Falsesur le dict PR pour court-circuiter (utile pour les tests pinnes).Acceptance issue #13967
adjacency, le picker affiche le remede propre ("Piocher un grain d'UN AUTRE genre", "Ne PAS retaguer la PR") et PAS les 3 gestes generiques. Test :test_adjacency_detected_from_body_when_caller_omits_flag.LIGHT/guard + prev LIGHT/guard, sortie contientPiocher un grain d'UN AUTRE genreet NE contient PASgh pr update-branch.test_a_clean_lane_is_not_sent_to_repair(existant) + nouveautest_adjacency_not_triggered_when_genres_differ_in_body.test_adjacency_caller_override_still_respectedverifie qu'un caller peut poseris_adjacency=Falsesur un corps qui tripperait l'organe, et que l'override prime.Changement
scripts/pick_idle_grain.py_is_adjacency_red+ appel local dansred_backlogscripts/tests/test_pick_idle_grain.pyDiff conceptuel :
_is_adjacency_red(body)-- import tardif (sys.path.insert(0, parent / "ci")puisimport variation_adjacency_guard as vag), gardetry/exceptautour de l'import et de l'appel (panne organe =>False, picker robuste).is_adjdans la bouclered.append. Override preserve :if "is_adjacency" in prcourt-circuite la deduction.Verification post-fix
pytest scripts/tests/ -k "pick_idle_grain or variation_adjacency"= 155 passed, 1 skipped.pig._is_adjacency_red("Grain: LIGHT/guard -- lane x -- prev: LIGHT/guard #1") == True; meme avec MED/guard apres LIGHT/ledger = False.Pourquoi cette PR (contexte verbatim issue #13967)
Le diagnostic de l'issue identifie deux couches : (a) l'organe qui produit le bon verdict, (b) le picker qui le re-emballe dans 3 conseils generiques invariants au predicat. Le fix touche (b) : le picker consulte l'organe localement et restitue son verdict specifique. (a) est deja OK.
Conventions respectees
raisenon garde dans le helper, picker reste robuste si l'organe est indisponible (try/exceptautour de l'import ET de l'appel).scripts/pick_idle_grain.pyn'est pas un artefact catalogue.is_adjacency; cette PR la reveille en supprimant la condition manquante (le caller qui pose le flag).test_adjacency_red_advice_replaces_three_generic_gestures(avecpr["is_adjacency"] = Truepose a la main) ettest_non_adjacency_red_keeps_three_generic_gesturescontinuent de passer (override path teste explicitement par le nouveautest_adjacency_caller_override_still_respected).Residuel / suite
lane_claim,tag_required,prev_guardproduisent des conseils generiques potentiellement faux aussi (meme symptome : invariants au predicat), mais l'issue [tooling] pick_idle_grain : le conseil de reparation est faux pour la cause ROUGE la plus frequente (adjacency, 13 PRs) — les 3 gestes sont invariants au predicat #13967 est scopee aadjacency. Issue ouverte par l'auteur de [tooling] pick_idle_grain : le conseil de reparation est faux pour la cause ROUGE la plus frequente (adjacency, 13 PRs) — les 3 gestes sont invariants au predicat #13967 pour les 3 autres causes plausibles mais non mesurees._is_adjacency_redrendFalseet le picker conserve les 3 conseils generiques. Comportement anterieur preserve dans le pire cas.Rotation R6
c151 = MED/notebook-csharp SemanticWeb ; c152 = LIGHT/cleanup tooling ; c153 = MED/notebook-lean GameTheory ; c154 = MED/notebook-dotnet Tweety-7a ; c155 = MED/notebook-search CSP-2 ; c156 = LIGHT/cleanup Search-debt ; c157 = LIGHT/cleanup data-registry ; c158 = LIGHT/tooling pick_idle_grain adjacency deduction.
La regle 6 (variete obligatoire) tient :
Liens
scripts/ci/variation_adjacency_guard.py(verdictblocking=True<=> LIGHT adjacency reelle, fail-CLOSED)scripts/tests/test_pick_idle_grain.py(3 nouveaux, 86 pre-existants)scripts/tests/test_variation_adjacency_guard.py(30 tests, contrat inchange)is_adjacency(cfgit log -p scripts/pick_idle_grain.pyrechercheis_adjacency)