Repository navigation
fix(picker,#17474): fetch_open_prs — plafond aligné sur le pool, troncature dite - #17568
Conversation
…ncature dite `fetch_open_prs()` demandait `--limit 300` a `gh pr list`, qui rend du plus RECENT au plus ancien : un plafond franchi faisait disparaitre les PRs les plus ANCIENNES, en silence -- precisement la traine que la file de reparation (`unattributed_blocked_prs`) et le compte WIP de lane (Q41, #17457) existent pour voir. - `OPEN_PRS_FETCH_LIMIT = POOL_FETCH_LIMIT` (meme garde que le pool d'issues, qui la portait deja avec le commentaire decrivant ce risque). - `[PRS TRONQUEES]` sur stderr au plafond, nommant l'inversion recent/ancien. - Cout nul sous le plafond : `GH_DEBUG=api` mesure 2 requetes pour 158 ouvertes aux deux plafonds (`gh` pagine par 100 et s'arrete a l'epuisement). - Tests : faux `gh` qui reproduit la troncature reelle (`population[:limit]`), avec controle de falsification -- au plafond de 300 la meme fixture ne voit rien, au plafond aligne elle voit l'orpheline la plus ancienne. 156 passed sur le fichier, 204 sur la suite picker ; ruff identique a `origin/main`. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
|
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 |
…e dite sur les DEUX transports Conflit unique dans `scripts/pick_idle_grain.py` : #17158 (abf1555) a restructure `fetch_open_prs` (try GraphQL / bascule REST). Resolution en UNION, ni --ours ni --theirs : - voie GraphQL : `--limit 300` code en dur remplace par `OPEN_PRS_FETCH_LIMIT = POOL_FETCH_LIMIT` (2000) + signature de troncature ; - voie REST (nouvelle sur main) : conservee telle quelle, et son propre plafond (POOL_REST_PAGE x POOL_REST_MAX_PAGES = 400) se dit desormais lui aussi -- sinon la bascule de #17038 rouvrait la troncature muette par l'autre porte, qui est exactement le defaut corrige ici ; - message extrait en `_warn_open_prs_truncated(rendered, ceiling, remedy)` : deux appelants, un seul texte. Verifie apres resolution : 0 marqueur de conflit, AST OK, 161 passed (dont le controle NEGATIF : sous le plafond, rien n'est dit). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Path-collision (organ #13359/#13615)Cette PR #17568 (
Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur |
|
[ADJOINT PREFLIGHT] |
…pus d'issues ouvertes (#17860) L'organe livre par #13937 ne mesure plus rien. `list_open_epics` demandait `--limit 500` puis levait des que la reponse atteignait ce plafond, et le depot est passe a 506 issues ouvertes (mesure firsthand : `search/issues` -> `total_count: 506`). `python scripts/epic_body_staleness.py` sortait donc rc=1 avec `open-issue corpus reached its 500-issue fetch limit`, sans aucun resultat : le mandat de curation de #13906 (les bodies d'Epic qui ignorent leurs propres livraisons) n'etait plus mesurable au niveau programme. Un `--limit` fixe ne peut pas distinguer « le depot a N issues ouvertes » de « la lecture s'est arretee a N ». La sonde elargit la requete jusqu'a ce qu'une reponse revienne plus courte que demandee -- seul observable qui prouve l'epuisement -- et refuse au plafond plutot que de presenter un corpus tronque comme complet. Le refus reste fail-CLOSED : la borne de 500 etait sous la donnee, donc elle n'etait plus un garde mais un interrupteur. Un payload qui n'est pas une liste est desormais refuse lui aussi : `null` est un corpus non lu, jamais un corpus vide (l'ancien `or []` confondait les deux). Classe deja rencontree sur ce depot : #17474 (`fetch_open_prs` tronque a 300 PRs, corrige par #17568 pour le picker, sans traiter la classe). See #13906 Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Grain: LIGHT/tooling -- lane myia-po-2026:CoursIA -- prev: LIGHT/tooling #17457
Probleme
fetch_open_prs()demandait--limit 300agh pr list. Orghrend du plusRECENT au plus ancien -- mesure firsthand du 2026-09-23 sur
jsboige/CoursIA:158 PRs ouvertes, tete #17565 (
2026-09-23T13:29:52Z), queue #15942(
2026-09-13T08:33:00Z). Un plafond franchi fait donc disparaitre les PRs lesplus ANCIENNES, en silence et sans erreur -- exactement celles que les deux
appelants existent pour voir : la file de reparation (
unattributed_blocked_prs,une PR bloquee depuis plus de 24 h est d'abord une candidate de reparation) et le
compte WIP de lane (Q41, #17457). Le fichier definissait deja
POOL_FETCH_LIMIT = 2000cote issues, avec un commentaire decrivant ce risque motpour mot ; cote PRs, la garde manquait.
Ce que fait la PR
OPEN_PRS_FETCH_LIMIT = POOL_FETCH_LIMIT, demande agha la place du300litteral.
[PRS TRONQUEES]sur stderr quand le nombre rendu atteint le plafond (memeconvention que
[POOL TRONQUE]), nommant l'inversion recent/ancien.voie
gh api repos/.../pullsa son propre plafond (POOL_REST_PAGExPOOL_REST_MAX_PAGES= 400) et s'arrete sans rien lever. Le meme message y estemis, avec le remede qui nomme
POOL_REST_MAX_PAGES. Le texte est extrait en_warn_open_prs_truncated(rendered, ceiling, remedy): deux appelants, un seulmessage.
GH_DEBUG=api gh pr list --limit 300et--limit 2000sur 158 ouvertes = 2 requetes dans les deux cas (ghpaginepar 100 et s'arrete a l'epuisement de la population comme au plafond). Aucun
avertissement, payload identique.
Merge
origin/main(union avec #17158, commitb749e72116)#17158 (
abf155556) a restructurefetch_open_prs--gh pr listentry,gh api repos/.../pullsen bascule -- et entrait en conflit textuel sur la memefonction. Resolution en union, ni
--oursni--theirs:--limit 300(main) / plafond nomme (branche)La seconde ligne est un ajout de la fusion, pas un elargissement de sujet : le
defaut corrige ici est « un plafond franchi se tait », et la bascule de #17038 en
ouvrait une seconde porte avec le meme silence. Nommer le plafond d'une voie en
laissant l'autre muette aurait rendu la correction dependante du transport.
Preuve
python -m pytest scripts/tests/test_pick_idle_grain.py -q: 161 passed ;suite picker complete (
test_pick_*) : 204 passed.test_the_oldest_blocked_orphan_survives_the_cap) : unfaux
ghreproduit la troncature REELLE (il rendpopulation[:limit]), lapopulation portant 320 PRs taggees devant une orpheline bloquee. Controle de
falsification dans le test : au plafond historique de 300, la meme fixture ne
voit RIEN (plafond vs 300 ->
unattributed_blocked_prs() == []) ; au plafondaligne, elle voit la traine. Un test qui serait vert avec le bug ne mord pas.
test_open_prs_truncation_is_said_not_silent: silence sous le plafond,[PRS TRONQUEES]au plafond.test_truncation_rest_est_dite_comme_celle_de_graphql: pages pleines jusqu'aepuisement du quota REST -> message ; puis controle NEGATIF (
max_pagesreleve d'une unite, pages inchangees) -> silence sous le plafond. Sans ce
controle, un avertissement inconditionnel passerait le test.
fetch_open_prs()sur l'ouvert reel rend 158 PRs, sans avertissement.ast.parseOK, 161passed. Pre-commit au commit de fusion (
gitleaks,text=Truesansencoding, H.3) : passed.ruff: distribution de regles identique aorigin/main(31 findingspre-existants, aucun nouveau) -- verifie par diff des listes
--output-format=concise.Perimetre
Périmètre : 2 fichiers --
scripts/pick_idle_grain.py(+49/-2) etscripts/tests/test_pick_idle_grain.py(+129/-5), mesures surgit diff --numstat origin/main...HEADa la teteb749e72116. Aucun workflow CItouche ; catalogue byte-identique a
main(R1).Hors scope (signale, non touche)
Le meme litteral
300sur l'ouvert existe dansscripts/review_coverage.py:234(autre organe, autre appelant) : meme classe de defaut, PR dediee si confirme.
Le cap WIP lui-meme (#17457) et le reste du picker restent hors scope, comme
l'issue le pose.
Closes #17474