Skip to content

Feat(picker): le tapis cesse de servir les grains dont la livraison est un carnet neuf (regime consolidation) - #23180

Closed
jsboige wants to merge 2 commits into
mainfrom
feature/regime-consolidation-picker
Closed

jsboige wants to merge 2 commits into
mainfrom
feature/regime-consolidation-picker

Conversation

@jsboige

@jsboige jsboige commented Oct 28, 2026 •

Copy link
Copy Markdown
Owner

Grain: MED/tooling -- lane myia-ai-01:CoursIA-2 -- prev: DEEP/notebook-python #23173

Résumé

Le tapis roulant (scripts/pick_idle_grain.py) cesse de servir les grains dont la livraison est un carnet neuf, tant que le régime consolidation tient.

Le classement est porté par un module dédié, scripts/consolidation_regime.py, qui oppose le dépôt à l'issue : le dépôt (git ls-tree -r origin/main) est l'oracle, la prose de l'issue est un témoignage daté de sa rédaction.

Trois oracles, dans cet ordre :

# Oracle Exemple Verdict
O1 série + rang « Serre 100 — carnet 30 », « NLP — carnet 07 », « Riemann200 R-11 » rang livré sur origin/main → carnet existant ; rang absent → carnet neuf
O2 fichier cité l'issue cite un .ipynb absent du dépôt et son titre annonce une création carnet neuf
O3 phrase l'issue déclare la création (« premier numéro libre », « Slot: », « nouveau carnet ») carnet neuf

Un veto de réparation (audit, correction, renumérotation, collision, prose, déplacement, suppression…) l'emporte sur les trois oracles : un grain de réparation n'est jamais sauté. Le sens de l'erreur est donc choisi — on saute un carnet neuf quand on le sait, on ne saute pas un grain qu'on ne sait pas classer.

Le module est sans effet tant qu'on ne l'appelle pas. Deux interrupteurs, tous deux posés par le coordinateur et retirés quand le user lève le régime :

  • --consolidation-regime — pour une lane qui le veut sur sa ligne de commande ;
  • COURSIA_CONSOLIDATION_REGIME=1 — pour toute la flotte d'un coup (sans elle, le coordinateur devrait demander à chaque lane de modifier sa propre ligne de commande : le régime tiendrait alors à la mémoire de douze lignes, ce que l'organe pretend précisément supprimer).

Sans l'interrupteur, le comportement du picker est inchangé — la PR n'impose rien par défaut.

Ce qui n'est pas un organe neuf

La sélection des grains a déjà son organe : scripts/pick_idle_grain.py. Cette PR ne crée pas un second sélecteur — elle branche une règle sur l'organe existant, dans un module séparé (le picker est modifié par ailleurs dans #23098 ; un module dédié garde le conflit minimal).

Mesure

Le régime est-il justifié par la réalité, ou par une intention ? Mesure sur les PRs ouvertes (donc sur ce qui est en train de se passer, pas sur ce qui a été dit) :

Jour PRs ouvertes qui ajoutent un .ipynb
26/10 12
27/10 5
28/10 13
total 30 (et ça croît)

Contrôle négatif : 120 PRs ouvertes modifient un carnet existant sans en ajouter aucun.

Jeu de contrôle du détecteur, dérivé de ces PRs (une issue présente dans les deux lots est exclue) :

  • positifs = issues citées par une PR Add|Feat qui ajoute un .ipynb absent de main aujourd'hui → grain de création ;
  • négatifs = issues citées par une PR Fix|Docs|Refactor|Rename|Update qui modifie un .ipynb présent sur main → grain de réparation.

Sur 19 positifs et 55 négatifs :

precision 1,00   (0 faux positif sur 55 négatifs)
rappel    0,92   (11 des 12 positifs classables ; 7 indéterminés)

Les 7 indéterminés sont des issues dont la livraison n'est pas nommée (3 EPIC — un conteneur, dont le classement se fait sur le sous-grain — et 4 « livrable non nommé »). La direction de l'erreur est assumée : un faux positif ferait perdre un grain de réparation ; un faux négatif laisse passer un carnet neuf, que la lane déclare alors sur l'issue.

La métrique ne suffisait pas — la liste réelle a été lue à l'œil

Appliqué aux 629 issues ouvertes, le classement écarte 28 candidats. Cette liste a été lue ligne à ligne : elle a révélé deux faux positifs que le jeu de contrôle ne pouvait pas porter (il est lui-même dérivé des PRs, donc biaisé vers les formes que les PRs couvrent) :

Issue Ce qui a été lu Faux positif Correction
#22056 « Collision d'identifiant 04-17 dans GenAI/Audio » la livraison est une renumérotation de carnets existants — c'est un grain de consolidation le corps cite « Slot: palier 17 » (la cause de la collision) veto : le mot collision rejoint la liste de réparation
#21871 « … le PDF a été archivé 11 jours après la PR » le « 11 » est une durée, pas un rang de carnet — c'est un grain d'audit sur un carnet existant le couple « archive 11 » résolvait une série et un rang garde d'unité : un rang suivi d'une unité de durée n'est pas un rang

Les deux sont verrouillés par test (test_collision_d_identifiant_nest_pas_saute, test_une_quantite_en_prose_nest_pas_un_rang).

Le cas de l'umbrella — une cascade est une machine à faux positifs

Une EPIC qui cite une sous-issue de création hérite de son classement, et l'EPIC qui cite une EPIC qui cite une sous-issue hérite aussi. Sur les 629 issues, cette cascade a retourné plus de 60 EPIC du dépôt — dont des EPIC de gouvernance (« Les body d'Epic ne sont jamais réécrits »). L'umbrella est donc traitée comme un conteneur : jamais sautée, son classement se fait sur le sous-grain que la lane tirera. (Le même raisonnement que la règle du tapis : « un EPIC en tête se sert par un sous-grain ».)

Validation

Contrôle Résultat
Tests du module python -m pytest scripts/tests/test_consolidation_regime.py → 21 passed
Interrupteur fleet COURSIA_CONSOLIDATION_REGIME=1 python scripts/pick_idle_grain.py --belt --ignore-red --lane … → mêmes 22 écarts que par le drapeau : les deux voies passent par le même code
Non-régression picker python -m pytest scripts/tests/ -k "pick or belt or consolidation" → 870 passed, 1 skipped, 9130 deselected (97 s)
Lint python -m ruff check scripts/consolidation_regime.py scripts/tests/test_consolidation_regime.py → All checks passed
Exécution réelle python scripts/pick_idle_grain.py --belt --ignore-red --consolidation-regime --lane myia-ai-01:CoursIA-2 → [regime consolidation] 22 candidat(s) ecarte(s) sur 579 ; 557 restent admissibles, chaque écart nommé (issue + preuve), puis le bandeau de rappel dans le récapitulatif du tapis

Extrait de l'exécution réelle :

[regime consolidation] 22 candidat(s) ecarte(s) sur 579 (livraison = carnet neuf) ; 557 restent admissibles.
   ECARTE #22940 — l'issue declare la creation d'un carnet
   ECARTE #22867 — rang 11 absent de la serie Riemann200
   ECARTE #22810 — carnet cite absent du depot : MyIA.AI.Notebooks/GameTheory/GameTheory-04i-Equilibre-Correle-Python.ipynb
   ECARTE #22768 — rang 09 absent de la serie NLP
   ...
   REGIME CONSOLIDATION : 22 candidat(s) ecarte(s) — livraison = carnet neuf (detail plus haut) ;
   ils restent au pool pour le prochain tour, une fois le regime leve.

Anti-régression

  • Diff d'ajout pur : 3 fichiers, 694 insertions, 0 suppression. Aucun code existant n'est remplacé, aucun carnet n'est touché.
  • Comportement par défaut inchangé : l'interrupteur est opt-in ; sans lui, filter_pool n'est jamais appelé.
  • Une garde de sécurité : un catalogue du dépôt indisponible (un git muet) ne fait sauter personne — le régime ne peut pas vider le tapis parce qu'un git a échoué.

Ce que cette PR ne fait pas

  • Elle ne pose pas le régime : les deux interrupteurs (drapeau de ligne de commande, variable d'environnement) restent à poser par le coordinateur, et à retirer quand le user lève le régime.
  • Elle ne ferme aucune issue et ne sert aucun grain : la ligne d'écart (« régime consolidation, grain d'extension différé ») se pose sur l'issue, puis la lane tire le suivant.
  • Elle ne remplace pas le plancher G-VAR-1 : ce PR est MED/tooling (genre META) et ne le tient donc pas seul ; le plancher du cycle reste porté par la réparation de fond d'un carnet existant (PR Feat(arganalysis,#23163): carnet 06c -- revision de croyance AGM (contraction de noyau, Levi) #23173, gelée sous le régime).

Traçabilité

  • Arbitrage user du 2026-10-28 relayé par le coordinateur myia-ai-01|CoursIA sur le dashboard workspace CoursIA (tag [TASK][STEER], 20:23Z).
  • L'issue dédiée à l'organe, annoncée par le coordinateur dans ce cycle, n'est pas encore arrivée sur le dépôt : la PR est ouverte sur l'arbitrage relayé, et l'issue pourra être rattachée à la suite.

🤖 Generated with Claude Code

…st un carnet neuf (regime consolidation)

Arbitrage user du 2026-10-28, propage par le coordinateur sur le dashboard
workspace : « on a un besoin enorme de consolidation et les issues d'audit
s'accumulent, les agents continuent a produire de nouveaux Notebooks a un
rythme encore superieur a celui qui m'a fait ticker sur la serie Serre. On
deraille completement ».

Sans organe, la regle reste une phrase : elle depend de la memoire de la
lane. `scripts/consolidation_regime.py` classe chaque candidat du tapis en
opposant le DEPOT a l'ISSUE (le depot est l'oracle, pas la prose) :

  O1 serie + rang  -> rang livre sur `origin/main` = carnet existant
  O2 fichier cite  -> `.ipynb` absent du depot + titre qui annonce la creation
  O3 phrase        -> l'issue DECLARE la creation (« premier numero libre »)

Un VETO de reparation (audit, correction, renumerotation, collision, prose)
annule le classement : un grain de reparation n'est JAMAIS saute. Le sens de
l'erreur est donc choisi — on saute un carnet neuf quand on le sait, on ne
saute pas un grain qu'on ne sait pas classer.

Mesure (2026-10-28, `origin/main` = 8e9eaaa), jeu de controle derive des
PRs OUVERTES (positifs = `Add|Feat` qui ajoutent un `.ipynb` absent de main ;
negatifs = `Fix|Docs|Refactor` qui modifient un `.ipynb` present) :

  precision 1,00 (0 faux positif sur 55 negatifs)
  rappel    0,92 (11 des 12 positifs classables ; 7 indetermines)
  28 ecarte(s) sur les 629 issues ouvertes — tous des creations verifiees

La metrique ne suffit pas : la liste reelle des ecarts a ete lue a l'oeil et
a revele deux faux positifs absents du jeu de controle — #22056 (collision
d'identifiant = renumerotation) et #21871 (« archive 11 jours » : une
DUREE lue comme un rang). Les deux sont corriges et verrouilles par test.

Le module est sans effet tant qu'on ne l'appelle pas : le picker expose
`--consolidation-regime`, pose par le coordinateur pendant le regime et
retire quand le user leve le regime.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml).

Detector: python scripts/audit/detect_organ_duplication.py --base <merge-base> --body-file <pr body>
Rationale: #16776 / #13564 (rule merged in #16778).

@github-actions

Copy link
Copy Markdown
Contributor

G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
La lane `myia-ai-01:CoursIA-2` voit ces signaux actifs sur les mergees du jour (UTC 2026-10-28) :

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 variation-tier-inflation, `variation-genre-run`, `variation-genre-cap-exceeded`, `variation-genre-mismatch`, `variation-genre-unknown`) -- la decision de merge reste au coordinateur.

…URSIA_CONSOLIDATION_REGIME)

Le drapeau `--consolidation-regime` ne vaut que pour la lane qui le pose :
sans autre voie, le coordinateur devrait demander a chaque lane de modifier
sa propre ligne de commande, et le regime tiendrait a la memoire de douze
lignes -- precisement ce que l'organe pretend supprimer.

La variable d'environnement `COURSIA_CONSOLIDATION_REGIME=1` pose le regime
pour toute la flotte d'un coup. Les deux interrupteurs restent sans effet
tant qu'ils ne sont pas poses, et la decision de poser (ou de lever) le
regime reste celle du coordinateur.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
@jsboige

jsboige commented Oct 28, 2026

Copy link
Copy Markdown
Owner Author

Fermée : la règle que cette PR implémente a été retirée après sa rédaction.

Ce que cette PR faisait : le tapis écartait tout grain dont la livraison est un carnet neuf, sans condition — un drapeau --consolidation-regime / COURSIA_CONSOLIDATION_REGIME=1 suffisait à l'activer.

Ce qui a changé : l'arbitrage user a été rectifié le 2026-10-28 à 21:38Z (message ai01-c2726-regime-rectifie relayed par le coordinateur). Le verbatim rectifié : « ralentir la création de carnets, qui ne doit correspondre qu'au rythme auquel les issues ouvertes le proposent » et « il faut faire quelque chose pour ralentir les nouvelles créations (pas les arrêter, juste ralentir) ». Le DM de 20:23Z, sur lequel cette PR s'appuyait, parlait d'un « régime aucun carnet neuf » : cette formulation a été corrigée par l'user lui-même, sur la demande de « Mesure stp avant de steerer au doigt mouillé ».

Ce qui survit de ce travail — et qui part dans la PR de #23174 (See #23174), qui est le grain annoncé par le coordinateur :

Ce qui change dans #23174 : le carnet neuf ne saute plus inconditionnellement. Le saut devient conditionné à un budget de création à l'échelle de la flotte, dérivé d'une mesure, avec la cause nommée BUDGET CRÉATION. Rien n'est arrêté : la création reprend dès que le compte redescend. Et la détection réutilise la polarité existante — dont la précision vient d'être mesurée sur le pool réel : précision 0,67, rappel 0,11 sur le jeu de contrôle, et 13 issues que la polarité classe « consolidation » livrent en réalité un carnet neuf. La polarité seule ne suffit donc pas : le critère retenu est « EPIC hors consolidation ou livraison = carnet neuf ».

Le canal de sortie reste le même : une cause nommée, jamais un silence.

lane myia-ai-01:CoursIA-2

@jsboige

jsboige commented Oct 28, 2026

Copy link
Copy Markdown
Owner Author

Fermée : la règle « aucun carnet neuf » a été retirée par l'arbitrage rectifié du 2026-10-28 21:38Z. Le classifieur et la mesure repartent dans la PR de #23174 (budget de création dérivé d'une mesure).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant