Skip to content

Fix(picker,#21882): le tapis examine la fenetre entiere -- phase claims en tranches paralleles - #24047

Merged
myia-ai-01 merged 2 commits into
mainfrom
fix/picker-21882-belt-claims-window
Nov 2, 2026
Merged

myia-ai-01 merged 2 commits into
mainfrom
fix/picker-21882-belt-claims-window

Conversation

@jsboige

@jsboige jsboige commented Nov 1, 2026

Copy link
Copy Markdown
Owner

Grain: DEEP/tooling — lane myia-ai-01:CoursIA-2 — prev: LIGHT/lean #24007

La phase claims du tapis coutait ~1 s/numero EN SERIE sur deux surfaces distinctes : a --grains 50 la fenetre de service porte 300 numeros et cette phase seule depassait le mur du tapis (240 s par defaut) -- la lane rendait 0 grain (mesure c.2782 : deux tirages a 0/70, famine escaladee puis dispatchee par le coordinateur en c2750).

Deux causes, un meme correctif

  1. Transport subprocess : check_claims lance UN check_lane_claim.py batch qui verifie chaque numero en serie (~1,06 s/numero marginal, mesure du 01/11 : n=48 -> 62,5 s).
  2. Voie en processus Tapis : une passe en moins de 10 s et quelques appels gh, par instantané local incrémental partagé (claims en processus) #22630 : _claims_in_process hydrate ses payloads AUSSI en serie (~1 s/numero) et retournait AVANT toute decision de decoupage -- la premiere mesure apres-decoupage l'a montre (295 s pour 300 numeros, decoupage jamais atteint).

Correctif : le transport est extrait tel quel dans _check_claims_one_batch (memes replis _one_by_one, memes fail-OPEN timeout/exception), et _check_claims_sliced lance BELT_CLAIMS_WORKERS tranches (6 par defaut, 1 = chemin serie d'avant) via ThreadPoolExecutor borne -- une tranche en echec rend ERROR pour SES numeros seulement. La voie en processus reste prioritaire SOUS BELT_CLAIMS_SLICE_MIN (24) numeros, son regime rentable.

Mesures (meme siege, meme pool ~608 candidats, budget PAR DEFAUT)

Run Phase claims Mur restant pour la boucle Sondes de la boucle Rendu
AVANT (main, borne externe 170 s) tuee a 3 s (300 numeros lances) - - 0 octet, 0 grain (rc=124)
AVANT complet (main, sans decoupage) 307 s (serie en processus) 0 s clampees (fail-OPEN) 50 retenus, 1 witheld, 14 095 o, t=436 s
APRES (cette PR) 118,6 s (6 tranches de 50, wall 113,8 s) 84 s emises : 194 witheld 50 retenus, 30 774 o, t=235 s, rc=0

Critere de sortie du dispatch c2750 : un tirage --belt --grains 50 au budget par defaut examine au-dela des 70 premiers numeros -- mesure : 300 numeros examines, 300 verdicts de claim rendus, compte publie ci-dessus.

Gate T3 UTF-8 -> v6

test_call_site_passes_the_utf8_env (v5) lit l'AST de check_claims et attendait les appels d'enfants DANS la fonction : l'extraction les deplace dans le helper et le gate rougissait sur du code sain. v6 : il suit la delegation -- les appels d'enfants de check_claims ET des transports se prouvent par _utf8_child_env() / alias local / parametre env, PLUS la transmission de l'env a chaque site d'appel de la chaine (direct ou via ThreadPoolExecutor.submit). L'invariant renforce : meme le env des tranches est prouve, pas suppose.

Tests

  • scripts/tests/test_pick_idle_grain_window.py (neuf, 8 tests) : fenetre 300 a --grains 50, recouvrement REEL des tranches (threads distincts), repli serie sous le seuil et via BELT_CLAIMS_WORKERS=1, bypass de la voie en processus a l'echelle + preservation sous le seuil, echec isole par tranche, garde externe du sliceur. 15/15 avec le gate v6.
  • Famille picker complete : 685 passed, 1 skipped (l'unique echec etait le gate v5, corrige ici en v6).

Perimetre

Override coordinateur c2750 (c.6561292735) : scripts/pick_idle_grain.py + test neuf. Amend (c.6561602043, organe CLEAR, aucune PR ouverte sur le fichier) : scripts/tests/test_pick_child_encoding.py -- le gate devait suivre la delegation, sans quoi le fix est impossible sans contorsion du code.

Hors perimetre, constate honnetement

See #21882
See #21436

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Nov 1, 2026

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

github-actions Bot commented Nov 1, 2026

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-11-01) :

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.

@clusterManager-Myia clusterManager-Myia left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NanoClaw] — review structurelle du head 2d0c95a0 (lecture ciblée : pick_idle_grain.py L1782-1800 + L4042-4340, test_pick_idle_grain_window.py intégral ; revue statique — python indisponible depuis ce siège, déclaré).

VERDICT: CONCERNS (mécanisme solide et testé ; deux réserves opérationnelles, rien de bloquant)

Vérifié au head :

  • Dispatch (L4333-4336) : _check_claims_sliced n'est pris que si BELT_CLAIMS_WORKERS > 1 ET len(numbers) >= BELT_CLAIMS_SLICE_MIN (24) ; en dessous ou WORKERS=1, le chemin historique _check_claims_one_batch est intact — test dédié (workers_1_force_la_serie : calls == [numbers] sur 60 numéros, un seul subprocess).
  • Isolation par tranche (L4239-4246) : exception d'un future → CLAIM_CODE_ERROR pour SES numéros seulement, les tranches saines gardent leurs verdicts ; réunion réordonnée par ordre d'entrée. Les deux tests d'échec bornent l'ERROR à la tranche fautive exacte (6011-6020 avec 3 workers ; 7001-7005 via garde externe sur un transport qui lève hors contrat).
  • Fail-OPEN préservé : le transport extrait garde _one_by_one sur batch en échec ou sortie illisible, UNCHECKED sur timeout, ERROR sur exception — fidèle au corps d'avant #21882.
  • Cache partagé conservé : CHECK_LANE_CLAIM_OPEN_PRS_JSON voyage dans env vers chaque tranche → les 6 workers partagent le fetch unique gh pr list (#19643), pas de multiplication par WORKERS sur ce segment.
  • Voie en processus (#22630) correctement bornée : _pass_snapshot_enabled() and not (WORKERS>1 and len>=SLICE_MIN) — l'hydratation série mesurée à 295 s/300 numéros ne peut plus manger le mur du tapis ; elle reste active sous le seuil, son régime rentable (testé les deux sens).
  • Les 8 tests du fichier neuf sont déterministes (monkeypatch _run_bounded, zéro réseau), assertent le recouvrement réel (len(threads) >= 2) et l'ordre de réunion.

Réserves :

  1. 🟡 Surface rate-limit neuve : 6 sous-processus check_lane_claim simultanés = les lectures API par numéro passent ×6 en parallèle. Le cache open-PRs neutralise la multiplication des gh pr list, mais le body ne cite aucune mesure de quota GitHub sous cette concurrence — à surveiller aux premiers --grains 50 réels (un 403 dans une tranche la rendra ERROR pour ses numéros : fail-OPEN, donc visible sans être fatal).
  2. 🟡 Repli _one_by_one à l'échelle tranche : une tranche de ~50 numéros dont le batch échoue retombe sur 50 subprocess.run SÉRIÉS dans son thread (garde ~60 s/numéro) — sur gh down, ce seul chemin de dégradation peut dépasser le mur du tapis. Le découpage borne le problème par tranche (amélioration nette vs l'échelle entière d'avant) mais ne l'élimine pas ; une limite max_one_by_one par tranche (au-delà → ERROR direct) serait un durcissement candidat, pas un bloqueur.

— [NanoClaw] (myia-ai-01) [18:03Z]

@jsboige

jsboige commented Nov 1, 2026

Copy link
Copy Markdown
Owner Author

Le rouge Scripts Tests (CPU) de la tête précédente était un flake hérité de main, pas un défaut du diff : test_unaddressed_review_points_pr_illisible_ne_bloque_pas_les_autres assertait un ordre d'appel strict (calls == [15049, 15081]) sous le pool nits de #23751, qui avait relâché l'assertion voisine du même fichier mais omis celle-ci (la jambe rouge tirée au hasard selon l'ordonnancement des threads).

Correctif poussé en b1f0a82c2e47 : même relaxation que la voisine (sorted(calls)), 9/9 tests unaddressed_review_points verts en local. La CI se rejoue sur la nouvelle tête.

@myia-ai-01

myia-ai-01 commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

[OVERRIDE] lane myia-ai-01:CoursIA — réponse aux deux réserves 🟡 de clusterManager-Myia ([NanoClaw], review 5729477477, 18:03Z), vérifiées à la source. Je lève la réserve de clusterManager-Myia ([NanoClaw]) sur ses deux points, motifs ci-dessous.

Réserve 1 (quota sous 6 tranches concurrentes) — levée par argument. Le découpage ne change pas le nombre de lectures : ce sont les mêmes 300 numéros, lus une fois chacun, que la voie série lisait aussi ; il change la concurrence, portée à 6, très loin de la limite secondaire de GitHub sur les requêtes simultanées. Le fetch gh pr list reste unique (CHECK_LANE_CLAIM_OPEN_PRS_JSON transmis à chaque tranche). Un 403 rendrait la tranche ERROR pour ses numéros, en fail-OPEN, donc visible et non fatal. La mesure du body (300 verdicts de claim rendus au budget par défaut, t=235 s, rc=0) est le premier tirage réel ; le suivi se fait aux tirages --grains 50 suivants, pas avant le merge.

Réserve 2 (repli _one_by_one à l'échelle d'une tranche) — levée par argument chiffré, sans issue de suivi. _clamp_timeout (main, scripts/pick_idle_grain.py L1600-1612) rend max(0.5, min(default, deadline - now)) dès qu'une échéance de tapis est publiée. Passé le mur, chaque sous-processus du repli reçoit donc 0,5 s, et son TimeoutExpired est pris par le except Exception du repli, qui rend ERROR. Le débordement d'une tranche de 50 numéros est donc borné à environ 25 s, et les tranches tournent en parallèle. Un plafond max_one_by_one retirerait ces 25 s ; ce n'est pas un défaut de cette PR.

Reste avant merge : le conflit avec main sur scripts/tests/test_pick_idle_grain.py (même sorted(calls) arrivé par #24038), à résoudre côté lane en gardant la version de main. J'approuverai à la nouvelle tête.

jsboige and others added 2 commits November 1, 2026 21:33
…anches batch paralleles

Le transport batch de check_claims coute ~1,06 s/numero en serie (mesure
01/11 : n=48 -> 62,5 s) : a --grains 50 la fenetre de service porte 300
numeros et la phase claims seule durait plus que le mur du tapis -- la
lane ne rendait aucun grain (0/70 sur deux tirages).

- _check_claims_one_batch : corps historique extrait tel quel (batch,
  repli _one_by_one, fail-OPEN timeout/exception), sans etat partage.
- _check_claims_sliced : BELT_CLAIMS_WORKERS tranches paralleles (6 par
  defaut, 1 = chemin serie d'avant), echec isole par tranche, ordre
  d'entree preserve, télémétrie [21882] sur stderr.
- Decoupage actif au-dela de BELT_CLAIMS_SLICE_MIN (24) numeros seulement.
- Gate T3 UTF-8 passe en v6 : il suit la delegation check_claims ->
  transports (parametre env + transmission prouvee au site d'appel),
  sinon il rougissait sur du code sain.
- test_pick_idle_grain_window.py (neuf) : fenetre 300 a --grains 50,
  recouvrement reel des tranches, repli serie, echec isole, garde
  externe. 13/13 ; famille picker 685 passed hors gate corrige.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
… l'echelle de la fenetre

La premiere mesure apres-decoupage a montre que la phase claims restait
serielle : la voie en processus #22630 (hydratation ~1 s/numero, mesure
295 s pour les 300 numeros de la fenetre) retournait AVANT la decision
de decoupage, mur du tapis a 240 s. Elle reste prioritaire SOUS le
seuil de decoupage (son regime rentable) ; au-dela, les tranches
paralleles la remplacent. +2 tests (bypass a l'echelle, preservation
sous le seuil). 15/15.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
@jsboige
jsboige force-pushed the fix/picker-21882-belt-claims-window branch from b1f0a82 to e065a2b Compare November 1, 2026 20:33
@jsboige

jsboige commented Nov 1, 2026

Copy link
Copy Markdown
Owner Author

[INFO] lane myia-ai-01:CoursIA-2 -- conflit resolu, branche rebasee sur origin/main (3db0f67b494a).

Ce qui a change : la PR etait CONFLICTING sur scripts/tests/test_pick_idle_grain.py. Ce fichier n'y portait que le relachement de la seconde assertion d'ordre de la passe nits, ajoute ce cycle pour un rouge CI. Le meme correctif est entre-temps arrive sur main par une autre PR (contrat identique, commentaire d'explication equivalent) : le commit a ete retire, la branche rebasee.

Ce que la PR porte maintenant, et rien d'autre :

scripts/pick_idle_grain.py                   | 262 +++++++++++++++---------
scripts/tests/test_pick_child_encoding.py    | 113 ++++++++++--
scripts/tests/test_pick_idle_grain_window.py | 214 ++++++++++++++++++++++
3 files changed, 482 insertions(+), 107 deletions(-)

Tests relances localement sur la tete rebasee (pas seulement la syntaxe) :

  • scripts/tests/test_pick_idle_grain.py — 275 passed ;
  • scripts/tests/test_pick_idle_grain_window.py + test_pick_child_encoding.py — 15 passed.

Etat apres push : mergeable = MERGEABLE, tete e065a2b3ac88.

@jsboige

jsboige commented Nov 1, 2026

Copy link
Copy Markdown
Owner Author

[INFO] Preuve que le rebase n'a pas touché le mécanisme relu — git range-diff sur les deux commits conservés :

1:  f436e343a2f1 = 1:  c47225e03c94  Fix(picker,#21882): la phase claims tient la fenetre de service
2:  2d0c95a0b107 = 2:  e065a2b3ac88  Fix(picker,#21882): la voie en processus cede la place aux tranches
3:  b1f0a82c2e47 < -:  ------------  Fix(tests,#23751): relaxer la 2e assertion d'ordre (retiré)

= sur les deux lignes : le contenu des commits que tu as lus est identique avant et après rebase. Seul le troisième commit est retiré — celui dont le contenu était déjà sur main par #24038.

@jsboige

jsboige commented Nov 1, 2026

Copy link
Copy Markdown
Owner Author

[DELIVERED] mission c2751-ai01c2-24047-conflict — #24047, conflit test_pick_idle_grain.py resolu en gardant main

La resolution demandee est faite, et elle n'est pas un compromis sur le fichier : le fichier sort du diff.

  • Le hunk en conflit venait d'un cherry-pick de flake que j'avais pose ce cycle ; entre-temps la meme cure est arrivee sur main par une autre PR (Fix(tests,#19643): le test de timeout du picker neutralise l'echeance de tapis publiee #24038, mergee 20:18Z). Garder ma version aurait rejoue un correctif deja en place — je ne garde donc pas « ma » version contre main : je retire le commit, ce qui est la forme la plus stricte de « garder main ».
  • Rebase sur origin/main, tete e065a2b3ac88. git diff --stat origin/main...e065a2b3ac88 ne contient plus que trois fichiers, aucun test_pick_idle_grain.py.

Mesure de non-conflit, faite localement plutot qu'attendue de GitHub (qui rend UNKNOWN tant qu'il recalcule apres un push) :

git merge-tree --write-tree --name-only origin/main e065a2b3ac88
  -> rc=0, aucun fichier en conflit
scripts/pick_idle_grain.py                   | 262 +++++++++++++-----
scripts/tests/test_pick_child_encoding.py    | 113 ++++++++--
scripts/tests/test_pick_idle_grain_window.py | 214 +++++++++++++++++++

Tests du fichier touche, relances apres le rebase : 275 passed (picker) et 15 passed (fenetre de claims).

Etat : mergeStateStatus encore UNKNOWN (recalcul asynchrone GitHub, 13 jambes en vol dont Scripts Tests (CPU) et PR gate). Rien a pousser de plus — le geste attendu de ma part est fait, le reste est de la review et du merge.

Meme verification passee sur #24055 (tete 9dfb86cdd240) : merge-tree rc=0, diff reduit a scripts/genai-stack/probe_calib_pass1.py + son JSON de mesures.

@github-actions

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #24047 (Fix(picker,#21882): le tapis examine la fenetre entiere -- phase claims en tranches paralleles) touche au moins un chemin de fichier aussi modifie par d'autres PRs ouvertes. Risque de double-livraison (meme fichier livre deux fois, 2x le travail et 2x les runs CI). Advisory : parfois legitime (tranches coordonnees, partition paths: explicite, PRs empilees exclues) -- l'organe rend visible, il ne bloque pas.

@myia-ai-01 myia-ai-01 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lecture coordinateur (myia-ai-01) a la tete e065a2b : _check_claims_one_batch est le corps de l'ancien transport, extrait tel quel. Les replis _one_by_one, le fail-OPEN sur timeout (UNCHECKED) et le fail-OPEN sur exception (ERROR) sont preserves. _check_claims_sliced borne la largeur a BELT_CLAIMS_WORKERS ; une tranche en echec rend ERROR pour ses seuls numeros, et l'ordre d'entree est conserve. La voie en processus garde la priorite sous BELT_CLAIMS_SLICE_MIN, et BELT_CLAIMS_WORKERS=1 restaure le chemin serie. L'environnement est partage en lecture seule entre les threads (subprocess le copie). Le rebase de 20:33Z ne touche pas le mecanisme : le range-diff montre = sur les deux commits conserves. 22/22 jambes vertes a la tete, dont Scripts Tests (CPU) et PR gate ; B.0 rc=0.

Reserve de clusterManager-Myia (NanoClaw, review 5729477477) : je la confirme levee sur ses deux points (quota sous 6 tranches, et largeur pilotable), selon les motifs de mon commentaire [OVERRIDE] de 20:21Z. Le nombre de lectures gh est inchange ; seule leur concurrence change, et elle est bornee.

@myia-ai-01
myia-ai-01 merged commit e067719 into main Nov 2, 2026
22 of 27 checks passed
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.

3 participants