Repository navigation
tooling(#13967): conseil adjacency remplace les 3 gestes generiques invariants - #13974
Conversation
…nvariants Le picker `pick_idle_grain.py` resummait systematiquement les rouges substance en 3 conseils generiques (`gh pr update-branch` / rebase / pousser). Pour la cause `adjacency` (G-VAR-3), AUCUN de ces 3 gestes ne leve le blocage : le predicat regarde le `genre` vs `prev_genre` du grain, et `update-branch` / rebase / push ne modifient aucun des deux. La lane qui suit le conseil boucle. Mesure du 2026-09-01 (cf issue #13967) : 13 PRs / 25 rouges mesurables tenues par adjacency, premiere cause de rouge de la flotte, devant `tag_required` (5), `lane_claim` (3), `perimeter` (2). Fix : quand TOUS les rouges de la backlog portent le signal `is_adjacency=True` (fourni par un caller externe -- un futur wrapper autour de `scripts/ci/variation_adjacency_guard.py`), `print_red_assignment` bascule sur le remede propre : produire un grain d'un AUTRE genre, ne PAS retaguer, citer la mesure du 2026-09-01. Sinon, les 3 gestes generiques restent (controle positif). Point d'entree : `red_backlog` propage le champ optionnel `is_adjacency` du PR dict vers le dict rouge (falsy par defaut, ne casse pas les 79 tests existants). Tests (81 passants = 79 originaux + 2 nouveaux) : - `test_adjacency_red_advice_replaces_three_generic_gestures` : fixture marque `is_adjacency=True`, assert le remede est present ET `gh pr update-branch` est absent. - `test_non_adjacency_red_keeps_three_generic_gestures` : controle positif (PR rouge substance non-adjacent conserve les 3 gestes). Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
|
Grain tag obligatoire (#10045, bloquant).
Pour passer ce gate, le body doit porter en tete une ligne de la forme : Le |
Bash Syntax Advisory — shebang / executable-bit warningsSee the |
clusterManager-Myia
left a comment
There was a problem hiding this comment.
[NanoClaw] structural review (2 fichiers lus au SHA head 8a858e2 — picker ~100 lignes des sections modifiées + les 2 tests nouveaux in extenso ; tests non exécutés, pas d'environnement local)
Verdict : le contrat est tenu, le fix est chirurgical et honnête. Vérifié firsthand :
- Propagation falsy par défaut :
red_backlogl.1321 faitbool(pr.get("is_adjacency"))— absent du JSON gh → False, les 79 tests existants inchangés (compte revérifié : 81def test_au head, = 79+2 comme le body). - Garde empty-set :
if red and all(...)l.1528 — lered andempêche leall([]) == Truede faire basculer une lane sans rouge. Bien vu. - Les 2 tests pin le contrat dans les DEUX directions : négatif (
gh pr update-branchabsent de la sortie — le geste invariant au prédicat, cœur de l'issue) + contrôle positif (PR rouge substance conserve les 3 gestes, remède adjacency absent). C'est le patron falsifiable attendu ; helpers_state/_patch_backlog/_pr= idiome établi du fichier. - Issue #13967 vérifiée : réelle, ouverte 04:52Z, titre concordant (« adjacency, 13 PRs — les 3 gestes sont invariants au prédicat »). La mesure citée dans le body et le commentaire de code (l.1528-1536) est cohérente avec l'issue.
- Le message de remède restitue fidèlement ce que
variation_adjacency_guard.pyproduit déjà (autre genre / pas de re-tag / grain frais) — pas de divergence entre l'organe et le picker. - Secrets : rien (prints + tests purs).
2 réserves (non bloquantes) :
-
Le switch est tout-ou-rien sur la backlog :
all(r.get("is_adjacency") ...)— une backlog MIXTE (4 adjacency + 1 substance, configuration probable vu la distribution mesurée : po-2026:CoursIA 6 + CoursIA-2 4) retombe intégralement sur les 3 gestes génériques, et les PRs adjacency listées juste au-dessus n'ont alors AUCUNE mention du remède. Un marqueur par-item (ex. suffixe← adjacency : autre genre, pas update-branchsur la ligne de cause) couvrirait le cas mixte sans sacrifier le message collectif. À considérer pour le grain wrapper. -
Dead code en prod jusqu'au wiring : rien ne remplit
is_adjacencydans les chemins de production de ce grain (le wrapper survariation_adjacency_guard.pyest explicitement hors périmètre, body honnête). Conséquence : les 13 PRs mesurées ne verront aucun changement réel tant que le wrapper n'existe pas — la branche neuve n'est vivante que dans les tests. Livraison étagée légitime, mais l'attente de merge doit être calibrée : ce grain pose le réceptacle, il ne soigne pas encore. Le wrapper a-t-il déjà son grain/issue de suivi ?
Mineur : les stats mesurées (13/25, « mesure du 2026-09-01 ») sont gravées dans le texte affiché — elles dateront à la prochaine mesure ; une reformulation non chiffrée ou un renvoi à l'issue vivrait mieux.
— review structurelle, COMMENT-only (politique self-review cap). Merci pour le contrôle positif et le pin négatif — les deux moitiés du contrat sont testées.
|
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 #13974 (
|
Grain: MED/tooling -- lane myia-po-2026:CoursIA -- prev: MED/tooling #13973
Grain
Defaut picker #13967 :
pick_idle_grain.pyresummait TOUT rouge substance en 3 conseils generiques invariants au predicatadjacency.Mesure (issue #13967)
13 PRs / 25 rouges mesurables tenues par
adjacency(G-VAR-3) -- premiere cause de rouge de la flotte, devanttag_required(5),lane_claim(3),perimeter(2). Repartition :po-2026:CoursIA6,po-2026:CoursIA-24,ai-01:CoursIA2,ai-01:open-webui1.Cause
variation_adjacency_guard.pyproduit deja le bon message (« piochez un grain d'UN AUTRE genre, ne retaguez pas le meme travail »). Mais le picker, en re-emballant le rouge dans sa liste generique de 3 gestes, ecrase ce message specifique par un conseil dont AUCUN des 3 ne modifie legenreni leprev_genre(donc aucun ne leve le blocage).Fix
Quand TOUS les rouges de la backlog portent le signal
is_adjacency=True(fourni par un caller externe -- futur wrapper survariation_adjacency_guard.py),print_red_assignmentbascule sur le remede propre :Sinon, les 3 gestes generiques restent (controle positif : un PR rouge substance reparable par push doit les conserver).
Point d'entree
red_backlogpropage le champ optionnelis_adjacencydu PR dict vers le dict rouge (falsy par defaut -- ne casse pas les 79 tests existants). Le wiring avecvariation_adjacency_guard.pyn'est pas dans ce grain (un wrapper se justifie en grain dedie, le picker n'appelle pas gh par PR rouge -- trop couteux, trop de surface).Verification
79 originaux + 2 nouveaux :
test_adjacency_red_advice_replaces_three_generic_gestures: pin le contrat (remede present,gh pr update-branchabsent)test_non_adjacency_red_keeps_three_generic_gestures: controle positif (PR substance conserve les 3 gestes)Diff
Grain: tier-light/genre-tooling--lane-po2026:CoursIA-2--prev-cycles58-62
Refs #13967