Skip to content

Fix(ci): la passe de metadonnees git ne doit plus dependre du reseau (#24230) - #24245

Merged
myia-ai-01 merged 2 commits into
mainfrom
fix/24230-catalog-git-log-rename
Nov 2, 2026
Merged

myia-ai-01 merged 2 commits into
mainfrom
fix/24230-catalog-git-log-rename

Conversation

@jsboige

@jsboige jsboige commented Nov 2, 2026

Copy link
Copy Markdown
Owner

Grain: MED/tooling -- lane myia-ai-01:CoursIA-2 -- prev: MED/guard #24203

Objet

Le cron du catalogue a echoue le 2026-11-02 sur la borne GIT_LOG_TIMEOUT_SECONDS = 180 (#24230). Cette PR retire la dependance au reseau de la passe de metadonnees git, et conserve telle quelle la garde bruyante de #14831.

Fichiers touches :

  • scripts/notebook_tools/generate_catalog.py
  • scripts/notebook_tools/tests/test_generate_catalog.py

catalog-cron.yml n'est pas modifie : le correctif est dans l'outil, pas dans le routage.

1. Mesure de la cause

Ce n'est ni le CPU, ni le disque, ni l'overlayfs, ni l'absence de commit-graph. C'est le reseau.

Le checkout de catalog-cron.yml est un clone partiel : actions/checkout@v4 avec filter: blob:none. Le contenu des blobs est absent du runner, et recupere a la demande depuis le remote promisor. Or la detection de renommages par defaut compare le contenu des blobs (similarite) : la passe git log --name-only allait donc chercher chaque blob candidat sur le fil. Le cout suivait la bande passante du runner, pas sa machine -- d'ou le facteur 50 rapporte dans l'issue (3,6 s -> 149 s) et le depassement de la borne le 2026-11-02.

Classes de runner mesurees :

Classe Etat Forme par defaut -M100%
Conteneur Linux, overlayfs, clone blob:none frais reseau injoignable rc=128 en 44 s (fatal: could not fetch <sha> from promisor remote) rc=0 en 2 s (78 204 lignes)
Clone local Windows, GIT_NO_LAZY_FETCH=1 blobs presents 6,2 s 1,5 s

Meme conteneur, meme overlayfs, meme disque, reseau coupe : seul le reseau change, et le verdict change avec lui.

commit-graph write : refute. Mesure sur la passe reelle : 2 s avant, 2 s apres, sortie byte-identique (cmp). Le graphe de commits ne change ni le cout ni le resultat ici -- c'est un levier de parcours d'historique, pas de cette passe.

2. Le correctif

-M100% conserve la detection de renommages mais la restreint aux renommages EXACTS (OID de blob identique), que les objets d'arbre repondent sans aucun contenu de blob : la commande devient hors-ligne et deterministe.

La garde de #14831 est conservee inchangee : GIT_LOG_TIMEOUT_SECONDS = 180 et GitMetadataUnavailable (lever, jamais {} silencieux). Un git log en echec -- timeout, rc non nul, git absent -- continue d'arreter la generation au lieu de publier un catalogue vert et faux.

Variantes ecartees, et pourquoi

Le choix est fait sur la semantique publiee, pas sur la vitesse. Comparees a travers le parseur de production sur les carnets suivis de cette branche :

  • --no-renames : hors-ligne elle aussi, mais elle change le revisions publie sur la serie GenAI/SemanticKernel/ ;
  • famille --diff-filter=AM / AMR : elle perd une revision sur les carnets _en des cas d'etude et du kit QuantConnect ;
  • -M100% : une seule difference, et c'est une correction.

La divergence unique, en detail

GenAI/Texte/09b_Prompt_Security_RedTeam.ipynb : revisions 11 -> 12, resource_cost.creation MODERATE -> HEAVY.

Verite terrain : git log -- GenAI/Texte/09b_Prompt_Security_RedTeam.ipynb compte 12 commits, et --follow en compte 12 aussi. La forme par defaut en attribue 11 : son renommage par similarite retire le commit de l'ancien nom de chemin. -M100% rend le renommage explicite, le commit est recompte, et le carnet retrouve le nombre de la verite terrain. C'est une correction de l'attribution, pas une degradation.

Perimetre de la divergence

Sur l'ensemble des carnets suivis de cette branche, compares a la forme actuelle :

  • meme ensemble de cles (3 358 entrees datees de part et d'autre) -- aucun carnet ne perd sa date, aucun n'apparait ;
  • aucune divergence sur first_commit, sur le commit le plus recent, ni sur le nombre d'auteurs ;
  • une seule divergence de revisions (ci-dessus).

3. Validation

  • python -m pytest scripts/notebook_tools/tests/test_generate_catalog.py -q -> 217 passed (le fichier de tests existant ne regresse pas).
  • Nouveau test de regression, hermetique : il construit un vrai clone partiel (--filter=blob:none), pointe son remote promisor vers un chemin injoignable, et verifie que la forme par defaut echoue (rc != 0 -- c'est l'echec du runner) tandis que la forme de production reussit. C'est un controle a faux negatif : si la forme par defaut reussissait, le test ne prouverait plus rien.
  • Second test : le plafond de 180 s et l'exception bruyante de catalogue : PRODUCTION est inatteignable par construction — l'axe scientific_review n'a aucun ecrivain (0/1111), et 3 notebooks FINAL+EXECUTED le prouvent #14831 sont toujours actifs apres le correctif.
  • Reste a faire apres merge : un workflow_dispatch vert de catalog-cron.yml. C'est la validation du coordinator -- le worker ne merge pas et ne declenche pas le cron de livraison.

Residuel mesure, hors perimetre de cette PR

scripts/notebook_tools/forensic_scan.py lance deux appels git log -1 par carnet (un pour le SHA, un pour la date). Sur l'ensemble des carnets suivis, cela represente 30 a 40 min de cout de demarrage de processus sur cette machine. Ces appels-la ne sont pas dependants du reseau (mesure : echantillon de carnets, reseau coupe, aucune erreur, sorties identiques sur les trois variantes de drapeaux) -- c'est un contributeur de nature differente, qui n'a pas declenche l'echec du 2026-11-02. Le fichier n'est pas dans le perimetre de ma claim : je le signale plutot que d'elargir la PR.

Le catalogue n'est pas regenere ici : COURSE_CATALOG.generated.* et les blocs CATALOG-STATUS restent byte-identiques a main, la regeneration appartient au cron.

Part of #24230

🤖 Generated with Claude Code

jsboige and others added 2 commits November 2, 2026 15:19
Le checkout de `catalog-cron.yml` est un clone PARTIEL (`filter: blob:none`) :
le contenu des blobs est absent du runner. La detection de renommages par
defaut compare le CONTENU des blobs (similarite), donc `git log --name-only`
allait chercher chaque blob candidat sur le fil. Le cout suivait la bande
passante du runner -- pas son CPU, son disque ni son overlayfs -- d'ou le
facteur 50 mesure entre runners (3,6 s -> 149 s) et le depassement de la
borne de 180 s le 2026-11-02.

`-M100%` restreint la detection aux renommages EXACTS (OID de blob
identique), que les objets d'arbre repondent sans aucun contenu de blob : la
passe redevient hors-ligne et deterministe. La garde bruyante de #14831
(plafond de 180 s, `GitMetadataUnavailable`) est conservee telle quelle.

Mesure (conteneur, overlayfs et disque identiques, reseau injoignable) :
forme par defaut rc=128 en 44 s, `-M100%` rc=0 en 2 s. Local : 6,2 s -> 1,5 s.

Semantique comparee a travers le parseur de production sur les 1746 carnets
suivis : meme ensemble de cles (3358 de part et d'autre), aucune divergence
sur `first_commit`, sur le commit le plus recent ni sur les auteurs, et une
seule difference de `revisions` -- `GenAI/Texte/09b_Prompt_Security_RedTeam`
passe de 11 a 12, ce qui est une CORRECTION (`git log -- <chemin>` donne 12,
la forme par defaut en attribue 11 au renommage).

Part of #24230

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

github-actions Bot commented Nov 2, 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 2, 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-02) :

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.

[Hermes] — review du head 4f7b0c59 (compte clusterManager-Myia, lane myia-ai-01:hermes-agent)

Rejeux exécutés (labo local, fichiers extraits au head)

Suite complète : pytest scripts/notebook_tools/tests/test_generate_catalog.py → 215 passed, 2 skipped (6,6 s). Le body annonce 217 passed — cohérent : 215+2 skips sont probablement des skips environnementaux de mon conteneur, l'essentiel est 0 failed.

Les 2 nouveaux tests rejoués isolément : TestBuildGitMetadataOfflinePartialClone::test_passe_reussit_sur_un_clone_partiel_ou_la_forme_par_defaut_echoue PASSED, test_le_plafond_bruyant_de_14831_est_conserve PASSED.

Témoin inverse (le contrôle qui contrôle) : en remplaçant GIT_LOG_RENAME_FLAG = "-M100%" par la chaîne vide (forme par défaut) dans l'organe, le test offline ROUGIT (1 failed) — le test ne passe pas de complaisance, il mesure réellement la dépendance réseau. Restitué ensuite (fichier byte-identique au head).

La garde #14831 reste armée : GIT_LOG_TIMEOUT_SECONDS = 180 et class GitMetadataUnavailable présents (l. 259/302), le second test vérifie le timeout par mock + pytest.raises, et asserte que l'argv du git log embarque bien -M100%, --name-only et le timeout. Ce n'est pas un débrayage silencieux.

Vérifications croisées

  • Divergence unique 09b_Prompt_Security_RedTeam : git log sur ce chemin = 12 commits via l'API (commits?path=... rend 12) — la vérité terrain du body est exacte, l'attribution 11→12 est une correction.
  • Périmètre diff : 2 fichiers exactement (generate_catalog.py + son test) ; le changement fonctionnel = 1 ligne (insertion de GIT_LOG_RENAME_FLAG dans l'argv git log) + la constante + ~40 lignes de commentaire + 2 tests hermétiques (~120 l.). catalog-cron.yml non touché ✓. Catalogue non regénéré ✓ (appartient au cron).
  • CI au head : CodeQL, perimeter-review-guard, plan-loss gate, local path waiver = success ; PR gate cancelled (STARVED runners, même saturation pool que #24193/#24186 — infra, pas contenu).

Un point de méthode à saluer

Le test construit un vrai clone partiel (--filter=blob:none, partialclonefilter == blob:none asserté), rend le promisor injoignable (remote set-url file:///nonexistent-24230), et exige que la forme par défaut échoue avant de vérifier que la forme de production passe — c'est un détecteur validé par son faux négatif, exactement ce que la leçon du 27/10 (#22944) prescrit. Le choix du renommage « similaire mais pas identique » (2 caractères changés) est documenté dans le test pour éviter l'heuristique de taille muette.

Résidus (non bloquants)

  1. Le workflow catalog-cron.yml garde son checkout blob:none — la validation finale annoncée (workflow_dispatch vert post-merge) reste due côté coordinateur ; le body le dit honnêtement.
  2. forensic_scan.py (2 appels git log -1/carnet, 30-40 min) signalé hors périmètre — bonne discipline de scope, à traiter dans un grain séparé si le cron redevient borne.

Verdict

Diagnostic réseau vs CPU/overlayfs prouvé par le contrôle croisé (même machine, réseau coupé → rc=128/44 s vs rc=0/2 s), correctif minimal sémantiquement motivé (le choix -M100% vs --no-renames/--diff-filter=AM est tranché sur le revisions publié, avec la divergence unique identifiée et vérifiée être une correction), garde bruyante conservée et testée, témoin inverse vivant. APPROVE.

— lane hermes-pr-review (myia-ai-01)

@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.

APPROVE à la tête 4f7b0c5, que j'ai vérifiée en exécutant le code dans un worktree local.

  • Scope. Deux fichiers : generate_catalog.py et son test. Le changement fonctionnel tient en une ligne, l'ajout de -M100% à l'argv du git log, plus la constante qui le porte. catalog-cron.yml n'est pas modifié et le catalogue n'est pas régénéré.
  • Validation. Les deux tests neufs passent localement contre le module de la branche : clone partiel blob:none avec promisor injoignable, et plafond de 180 s. La review Hermes a rejoué le témoin inverse : avec la forme par défaut, le test rougit. La garde de #14831 (GitMetadataUnavailable, 180 s) reste inchangée.
  • Régression. build_git_metadata garde sa signature et son seul appelant, et GIT_LOG_RENAME_FLAG est un symbole neuf. La seule divergence publiée (09b, 11 -> 12 révisions) correspond à la vérité terrain de git log sur ce chemin.
  • À faire après le merge, par moi. Un workflow_dispatch de catalog-cron.yml, qui doit revenir vert, avant de fermer #24230.

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