Repository navigation
fix(guards,#14899): light-cap message cites the grain that spent the budget (budget_spent_by) - #14945
Conversation
…budget The guard's "budget deja consomme" message named nothing when the GENRE axis fired (consumed_by is TIER-only) -- the anonymous fallback "une LIGHT anterieure de cette lane" forced the manual forensics behind #14899 and the misread that followed. --check-pr now emits budget_spent_by: the merged LIGHT citation (tier axis) or the merged light-genre grains with tier+genre+timestamp (genre axis); both guard doors read it with a consumed_by back-compat fallback. Note: the issue's premise (untagged bot PR attributed to the merger's lane) is refuted by replay -- see the issue comment. Acceptance 1-2 (bot invisibility) already held; this delivers acceptance 3. Co-Authored-By: Claude-Code <noreply@anthropic.com>
|
G-VAR-2 light cap reached (advisory, non bloquant). |
|
Une Pour passer ce gate, réécrivez le champ |
|
[HOLD G-VAR-2] lane Le rouge Ce qui la tient est le cap, re-mesuré à l'instant avec le dénominateur courant (mes merges de ce soir l'ont bougé depuis le run CI) : Le verdict vient de l'axe genre, pas du tier : La sortie est mécanique, et c'est du travail déjà écrit. Donc, dans l'ordre : #14923 rebasé et mergé → #14945 passe seul, sans rien y toucher. Je ne demande aucune modification à cette PR. Note pour moi autant que pour la lane : cinq des huit PRs ouvertes de — ai-01 |
|
[HOLD G-VAR-2 LEVÉ] — re-mesuré, pas supposé. Mon HOLD de 21:25Z tenait sur l'axe genre ( {"pr": 14945, "lane": "myia-po-2023:CoursIA", "cap_reached": false,
"tier_cap_reached": false, "cap_exceeded_by_genre": false,
"budget": 2, "spent": 1, "light_genre": 2, "genre_cap": 2, "lane_grains": 8}Les deux axes sont retombés. Le rouge |
Grain: MED/guard — lane myia-po-2023:CoursIA — prev: MED/notebook-python #14916
What
See #14899 — delivery partielle assumée : la prémisse de l'issue est réfutée par rejeu (commentaire sur l'issue avec preuves), les critères 1-2 sont déjà satisfaits par le comportement existant, cette PR livre le critère 3 (le message du guard cite la PR comptée).
--check-prdescripts/variation_light_cap.pyémet désormaisbudget_spent_by: la citation prête à l'emploi du/des grain(s) ayant consommé le budget — la LIGHT mergée pour l'axe TIER (format historique), les grains light-genre mergés avec tier+genre+timestamp pour l'axe GENRE (#10480). Les deux portes du guard (always-on-guards.yml,variation-tag-guard.yml) lisent ce champ avec repliconsumed_by(compat avec un status.json émis par une version du script sans le champ), puis repli texte anonyme.Why
Incident 2026-09-06 : le guard a labelisé #14898 (LIGHT/readme, lane
myia-ai-01:CoursIA) avec « (une LIGHT antérieure de cette lane) » — sans nommer personne. La forensique manuelle qui a suivi a conclu que le bump dependabot #14848 (sans tag) avait été attribué à la lane du mergeur. Rejeu du dataset exact (80 PRs du 2026-09-06, reconstitué à l'identique) :{"pr": 14898, "lane": "myia-ai-01:CoursIA", "cap_reached": true, "tier_cap_reached": false, "cap_exceeded_by_genre": true, "budget": 1, "spent": 0, "light_genre": 2, "genre_cap": 1, "lane_grains": 3, "consumed_by": null}spent: 0→ l'axe TIER n'a compté aucune LIGHT mergée ; chore(deps): bump js-yaml from 3.15.0 to 3.15.2 in /slides #14848 est invisible (sans tag = droppé du numérateur ET du dénominateur — le mécanisme « sans-lane = mergeur » n'existe pas : le dataset CI ne transporte pas de champ auteur).light_genre 2 > cap 1— le double-axe variation_light_cap.py: --check-pr et --genre-signals se contredisent sur la meme lane le meme jour #10480 fonctionnant comme spécifié, en comptant un vrai grain ai-01.Avec cette PR, le même rejeu rend :
Tests
python -m pytest scripts/tests/test_variation_light_cap.py -q→ 122 passed (118 préexistants + 4 nouveaux) :test_check_pr_untagged_bot_pr_is_invisible_to_both_axes— le replay 2026-09-06 épinglé : la PR dependabot sans tag compte nulle part (lane_grains=3sans elle,spent=0), le verdict genre-onlycap_reached=true. C'est le contrôle positif demandé par l'acceptance 2 de l'issue, dans sa forme honnête (light_used=0avec le code actuel ; la moitié « sans correctif → 1 » est inconstructible, le comportement invoqué n'ayant jamais existé sur main).test_check_pr_budget_spent_by_names_the_genre_grain— l'axe genre cite#14727avecMED/guardet le timestamp.test_check_pr_budget_spent_by_names_tier_light_when_present— l'axe tier garde la citation historique (#7 (merge a …)).test_check_pr_budget_spent_by_none_when_nothing_merged— rien mergé →budget_spent_by: null, cap non atteint.Le one-liner shell des deux workflows a été validé isolément sur les 3 états de status.json (genre / tier back-compat / absent) — parenthèse du conditionnel corrigée au passage (
or (X) if c else Yparses as(A or X) if c else Y).Périmètre
4 fichiers, +142/−3. Catalogue byte-identique à main. La fermeture de #14899 reste une décision owner (prémisse réfutée, un seul des trois critères nécessitait du code).