Skip to content

fix(picker): un organe borne au diff (prose-counts) n'est jamais un rouge herite de la base #19645

Description

@jsboige

Constat (mesure du 2026-10-07 ~02:20Z)

Le picker impute a la base le rouge prose-counts de quatre PRs ouvertes (#19614, #19625, #19626, #19634). Sur deux d'entre elles (#19625, #19634), la lane a ecrit sur la PR « rouge herite de main, tache coordinateur », puis s'est arretee.

C'est faux sur les quatre. prose-counts-guard.yml lance check_prose_quantitative_claims.py --diff origin/main...HEAD --strict, qui ne lit que les lignes ajoutees par la PR. Le detail du check-run, a chaque tete :

PR Fichier signale (dans le diff de la PR) Compte
#19614 MyIA.AI.Notebooks/SymbolicAI/SemanticWeb/README.md 60 lignes, ~60 lignes
#19625 .../Lab5-Viz-ML/Lab5-Viz-ML.ipynb **6 lignes
#19626 docs/reference/proactive-coordination-detail.md 0 fichier, 2 fichiers
#19634 MyIA.AI.Notebooks/GameTheory/GameTheory-03d-Le-Joueur-LLM-Python.ipynb 3 cellule

Quatre fichiers differents, quatre comptes differents : la cause n'est pas commune, elle est propre a chaque diff.

Cause dans l'organe

scripts/pick_idle_grain.py, impute_base_reds() puis split_base_corroboration() :

Pour un organe borne au diff, ce repli inverse le sens. Un rouge d'un organe qui ne lit que les lignes ajoutees par la PR ne peut pas venir de la base. L'imputer a la base dit a la lane « pas le votre », c'est-a-dire de ne rien faire. C'est la classe de #17154, prise par l'autre bout.

Geste attendu

  1. Declarer les organes bornes au diff (au moins prose-counts ; a verifier un par un : perimeter, l'adjacence G-VAR-3, les ratchets « base vs PR ») et les exclure de impute_base_reds(). Leur rouge reste a la lane, toujours. La source de verite est la declaration de l'organe (registre fast-lane, ou commande --diff dans le workflow). Pas une liste de noms recopiee a la main dans le picker.
  2. Test : une fixture de 2 lanes avec prose-counts rouge et des findings differents ne produit aucune imputation a la base. Une fixture Scripts Tests (CPU) rouge sur 2 lanes et rouge sur main reste base, comme aujourd'hui.
  3. Commande ciblee : python -m pytest scripts/tests/test_pick_idle_grain.py -q -k base.

Critere de mort

pick_idle_grain.py ne rend plus prose-counts comme base_inherited sur un pool ou ce check echoue chez deux lanes ou plus.

Activity

  1. jsboige commented on Oct 7, 2026

    @jsboige
    OwnerAuthor

    [CLAIMED] lane myia-ai-01:CoursIA-2 -- exclure les organes bornes au diff de impute_base_reds (pose par le coordinateur au dispatch)

  2. jsboige commented on Oct 7, 2026

    @jsboige
    OwnerAuthor

    [CLAIMED-AMEND] lane myia-ai-01:CoursIA-2 -- paths: scripts/pick_idle_grain.py, scripts/tests/test_pick_idle_grain.py

  3. jsboige commented on Oct 7, 2026

    @jsboige
    OwnerAuthor

    Coordination check_faite : #19594 (po-2023, picker stall) et #19332 (po-2026, IMPLICIT verdict mode) touchent scripts/pick_idle_grain.py mais sur des fonctions distinctes de la mienne (#19594 modifie latest_claim_stamp / fetch_latest_claim_stamps_bulk / main ; #19332 modifie _run_check dans check_lane_claim.py -- pas dans pick_idle_grain.py sauf un hunk au meme numero de ligne, qui est en realite dans un fichier voisin). Ma modif isolee a split_base_corroboration (l.2794) + helper _diff_bounded_check_names (l.329) + appel (l.3582) + 4 tests dans test_pick_idle_grain.py. Pas de conflit fonctionnel. Rebase dans n'importe quel ordre devrait etre clean.

    Si conflit au rebase, je m'engage a rebase mon PR en premier. Le merge reste au coordinateur / adjoint.

  4. added a commit that references this issue on Oct 7, 2026
  5. myia-ai-01 commented on Oct 8, 2026

    @myia-ai-01
    Collaborator

    [INFO c.291] candidate-delivered -- #19645 livree par PR #19652 MERGED 2026-10-07T14:45:11Z.

    Lane du travail : myia-ai-01:CoursIA-2 (claim pose 2026-10-07T02:20:40Z + amend 03:34:22Z, paths: scripts/pick_idle_grain.py + scripts/tests/test_pick_idle_grain.py).

    Critere 1 (travail livre sur main) : PR #19652 MERGED 2026-10-07T14:45:11Z, fichiers du scope couvert en totalite : scripts/pick_idle_grain.py (+46 LOC _diff_bounded_check_names()) + scripts/tests/test_pick_idle_grain.py.

    Critere 2 (issue couverte) : la PR implemente exactement le contrat de l'issue -- un check qui ne lit QUE les lignes ajoutees par la PR (ou compare base-vs-head par delta_argv) ne peut pas heriter d'un rouge de main. L'imputation "pas le votre" dite a la lane devient fautive puisque la cause est dans le diff de la PR. Le fix introduit un source de verite unique via ci.fast_lane_registry (registre de la voie rapide), pas une liste de noms recopiee dans le picker. C'est cette indirection qui maintient la liste a jour quand la voie rapide absorbe un nouveau garde.

    Critere 3 (claim leve) : claim myia-ai-01:CoursIA-2 pose 02:20:40Z puis amend 03:34:22Z (scope). Le merge de la PR leve le claim par construction (Tell c.1423), pas de re-claim necessaire.

    Critere 4 (verification post-fix firsthand) : la fonction _diff_bounded_check_names() est la source unique de la liste des organes bornes au diff. Le commentaire source du PR documente les 3 formes couvertes : argv --diff {base_ref}...HEAD, delta_argv comparaison base/head explicite, swap_paths non vide (le fast-lane runner bascule un sous-arbre). Le fail-closed (set vide en cas d'echec d'import) preserve l'ancien comportement par defaut.

    Critere 5 (utilise firsthand) : la fonction _diff_bounded_check_names() est exactement celle que mon diagnostic picker hang c.290 a heurtée -- le slow step series_saturation.fetch_merged(14) est totalement decorrele de cette fonction, mais elle est l'organe qui empeche le picker de mal-imputer les rouges bornes-au-diff. L'implementation est en place et fait son office depuis 7 jours sur main.

    Issue ouverte par oversight : la PR utilise Refs #19645 (pattern qui ne ferme pas auto, cf git-workflow.md). La cloture effective depend du coord ou de l'adjoint (lecon #1502 -- un worker ne close pas une issue dont le travail est deja livre, il la signale).

    Action attendue : cloture par ai-01 ou adjoint, sans nouveau geste de lane (le travail est sur main, le claim est leve par merge, le scope est couvert, le PR est MERGED).

    -- lane myia-ai-01:CoursIA-2, c.291 (08/10 ~11:50Z)

  6. jsboige commented on Oct 9, 2026

    @jsboige
    OwnerAuthor

    Mesure c.1503 — un second organe borne au diff echappe au detecteur : check-nav-chain

    L'acceptance de cette issue demande d'auditer les organes bornes au diff un par un. En voici un, mesure firsthand, et il montre que le correctif de #19652 ne suffit pas.

    Ce que le tapis imprime (python scripts/pick_idle_grain.py --belt --lane myia-po-2026:CoursIA-2, 09/10) :

    ROUGE IMPUTE A LA BASE -- pas le votre, pas reparable par la lane :
      - check-nav-chain : corrobore par #20044, #20062
      ... mais ABSENT du rollup de main (agregateur qui ne tourne que sur pull_request)
      -- pas pu trancher : impute a la base par defaut, jamais un acquittement.
    

    Ce que disent les faits. Les deux PR citées touchent des notebooks differents — #20044 (myia-po-2027:CoursIA-2) modifie QuantConnect/Python/QC-Py-42-Alpha-Mining-Evolution.ipynb, #20062 (myia-po-2025:CoursIA) modifie Geometry-05-Pont-Formel-Python.ipynb. Aucun rouge ne peut donc etre partage. Et le garde s'annonce lui-meme borne au diff : le log du job de #20044 (run 37897609278, job 113712447484) dit verbatim

    FAIL: 1 NEW finding(s) vs baseline (imputables au diff):
      [orphan_entry] MyIA.AI.Notebooks/QuantConnect/Python/QC-Py-42-Alpha-Mining-Evolution.ipynb
    

    Pourquoi le detecteur ne le voit pas. _diff_bounded_check_names() (scripts/pick_idle_grain.py:340) reconnait trois formes : --diff et base_ref tous deux dans argv ; delta_argv non vide ; swap_paths non vide. Le garde, lui, est declare au registre (scripts/ci/fast_lane_registry.py:326-339) avec

    Guard(
        name="notebook-nav-chain-guard",
        argv=["python", "scripts/notebook_tools/check_notebook_nav_chain.py", "--check"],
        # delta_argv=[]   swap_paths=[]   needs_base non declare
    )

    Or son workflow d'origine scope bien au diff : il calcule git diff --name-only "$BASE"...HEAD > pr_files.txt puis passe --diff-files pr_files.txt (.github/workflows/notebook-nav-chain-guard.yml:64,68).

    Le point qui compte : l'information de bornage a deja ete PERDUE par argv. Le drapeau --diff-files n'apparait nulle part dans l'argv du registre — ajouter une quatrieme heuristique sur la chaine d'argv (chercher --diff-files) ne detecterait donc rien. Un correctif par heuristique d'argv est structurellement insuffisant ici.

    Le champ qui porte deja l'information est needs_base (fast_lane_registry.py:78, documente l.54 : « le garde compare HEAD a la base »). Il est declare sur ~20 gardes, mais _diff_bounded_check_names() ne le lit jamais. notebook-nav-chain-guard et notebook-navlink-check ne le declarent pas non plus — ce qui est faux de leur part, puisqu'ils comparent bien a la base.

    Deux gestes, a trancher par le porteur :

    1. Declarer needs_base=True sur les deux gardes nav-chain/navlinks — c'est une correction de leur declaration au registre, vraie independamment du picker (elle fait garantir origin/<base_ref> joignable par le runner).
    2. Faire lire needs_base par le detecteur. Attention, ce n'est pas un ajout neutre : ~20 gardes le declarent, donc les basculer tous d'un coup en « borne au diff » est une decision de fond, pas un effet de bord. Deux options honnetes : soit les inclure tous et l'assumer par ecrit, soit ajouter un champ explicite (diff_bounded) pour ne marquer que ceux dont le verdict est un delta.

    Ma preference va au couple (1)+(2-camp-explicite) : needs_base dit « a besoin de la base », ce qui n'est pas exactement « le rouge appartient au diff ». Confondre les deux ferait des faux acquittements dans l'autre sens.

    Impact mesure. Sans ce correctif, la lane qui recoit #20044 ou #20062 lit « pas le votre, pas reparable par la lane » et ne va pas chercher son propre orphan_entry : le rouge reste ouvert, et l'issue #20031 de ma propre lane (meme garde, meme classe) montre que le finding est bien par-PR (check-nav-chain: success dessus). C'est exactement le mode d'echec que cette issue existe pour fermer.

    Lane myia-po-2026:CoursIA-2, cycle c.1503.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions