Skip to content

Fix(genai,#14755): l'organe voit les modules .py et un repli 'or' - #23740

Merged
myia-ai-01 merged 2 commits into
mainfrom
fix/14755-organ-py-scan
Oct 31, 2026
Merged

myia-ai-01 merged 2 commits into
mainfrom
fix/14755-organ-py-scan

Conversation

@jsboige

@jsboige jsboige commented Oct 31, 2026

Copy link
Copy Markdown
Owner

Grain: DEEP/guard — lane myia-po-2028:CoursIA-2 — prev: MED/tooling #23733

L'organe de #22783 ne collectait que des carnets (rglob("*.ipynb"), suffix == ".ipynb"). Tout appel chat vivant dans un module .py du dépôt était donc structurellement invisible, et un scan rendait « 0 finding » — un faux acquittement, pas une mesure.

Le premier module scanné a révélé un second angle mort, du même genre : la chaîne

model = llm_model or os.environ.get("OPENAI_MODEL", "gpt-4o-mini")
client.chat.completions.create(model=model, ...)

n'était ni finding ni proprement unresolved. Le littéral restait classé mention documentaire et le site chat tombait en unresolved (reason renseigné, aucune accusation). Les opérandes d'un or s'évaluent de gauche à droite et le premier littéral vrai court-circuite : le premier littéral déclaré est la valeur statiquement visible, donc un FINDING.

Mesure (même arbre, avant / après)

python scripts/notebook_tools/check_obsolete_chat_model.py --json MyIA.AI.Notebooks, l'organe d'origin/main d'un côté, celui de la branche de l'autre.

avant après
carnets 1735 1735
modules .py 0 1420
sites chat vus 160 163
findings 0 1
unresolved 56 54
doc_mentions 6 21
  • Le finding est GenAI/Audio/04-Applications/v4/p5_tts.py L545, gpt-4o-mini, via defaut de os.getenv("TRANSLATION_MODEL", ...).
  • Aucun finding n'est ajouté sur les carnets (0 → 0) : le cas or n'introduit aucun faux positif sur 1735 carnets.
  • Les 3 sites chat supplémentaires sont dans des modules, et les 15 mentions doc supplémentaires aussi — classées advisory, sans effet sur l'exit.

Contrôle positif et témoins négatifs

  • positif, hors arbre de mesure : scripts/livecoding_video_pipeline.py — avant le cas or, rc=0 avec 1 mention doc + 1 site non résolu ; après, FINDING ... ligne 679 ... via repli 'or' -> defaut de os.getenv("OPENAI_MODEL", ...), rc=1.
  • négatif, scripts/secrets/render_settings_json.py : la seule occurrence gpt-3.5-turbo est une chaîne de docstring, aucun site chat — 0 finding, 0 mention, rc=0, avant comme après.
  • négatif du cas or, test dédié : llm_model or os.environ.get('OPENAI_MODEL') (sans littéral) reste unresolved, 0 finding, rc=0.
python -m pytest -q scripts/notebook_tools/tests/test_check_obsolete_chat_model.py
-> 53 passed (48 avant, 5 ajoutés)

Ce que cette PR ne fait pas

  • Elle n'élargit pas le périmètre du garde CI. Le registre fast-lane itère iterate_paths=["**.ipynb"], volontairement (incident ci(fast-lane): TRANCHE4 absorbe 5 gates + controle positif identite (#12396) #13220), et le garde est blocking=False. La CLI accepte .py ; le gate ne l'itère pas. Élargir le gate est une décision séparée, pas un effet de bord de cette option — c'est écrit dans la docstring de collect_sources et dans les limites du module.
  • Elle ne migre pas les deux sites qu'elle révèle. GenAI/Audio/04-Applications/v4/p5_tts.py (repli de traduction) et scripts/livecoding_video_pipeline.py (repli de narration) sont des sites d'EXÉCUTION réels ; les carnets qui consomment le premier ont des sorties committées produites avec l'ancienne cible. Migrer le défaut sans ré-exécuter créerait une dérive sortie/prose (C.2), et la ré-exécution de la famille Audio dépend de GPU et de clés. Le geste suivant est nommé, mesuré, et n'est pas noyé ici.

Plancher de cycle — déclaré, non revendiqué

Le genre guard est META : quel que soit le tier, il ne tient pas le plancher G-VAR-1 à lui seul. Ce cycle ne revendique donc pas le plancher R1 sur cette PR ; le grain de contenu reste dû et sera le prochain tiré.

Vérifié sur origin/main + branche, tests relancés après le dernier commit.

🤖 Generated with Claude Code

L'organe #22783 ne collectait que des carnets (`rglob("*.ipynb")`) : tout
appel chat vivant dans un module .py du depot etait structurellement
invisible, et un scan rendait « 0 finding » -- un faux acquittement.

Mesure firsthand sur `MyIA.AI.Notebooks` (meme arbre, avant/apres) :
1735 carnets, 1420 modules ; findings 0 -> 1, tous deux hors carnet.

Le premier module scanne a revele un second angle mort : la chaine
`variable or os.environ.get("M", "<modele>")` n'etait ni findee ni
proprement `unresolved` -- le litteral restait une mention doc et le site
chat tombait en `unresolved`. Les operandes d'un `or` s'evaluent de gauche
a droite : le premier litteral declare est la valeur statiquement visible,
donc un FINDING.

Le perimetre du garde CI n'est PAS elargi (le registre fast-lane itere
seulement les carnets, incident #13220) : l'option de la CLI est une
capacite de mesure, pas un elargissement du gate.

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

@jsboige

jsboige commented Oct 31, 2026

Copy link
Copy Markdown
Owner Author

Les deux rouges de cette PR sont herites de la base, mesures a la source.

check_run_state.py --pr 23740 a la tete 7b2f335d7db0 : deux jambes rouges, Scripts Tests (CPU) et PR gate.

PR gate n'a pas de defaut propre

Le log du job (124560000886) nomme une seule cause :

[pr-gate] FAIL -- failing checks: Scripts Tests (CPU) (failure)

Le gate agrege ; il rougit parce que la jambe CPU rougit. Rien d'autre n'est en cause.

Scripts Tests (CPU) : 8 echecs, aucun impute a ce diff

Le diff de cette PR touche deux fichiers (check_obsolete_chat_model.py et son test), aucun des huit tests en echec.

Les huit, avec leur famille :

Test Famille
test_check_self_hosted_runner_policy.py x3 runner-policy, portee par #23716
test_migrate_dsa_gating.py x4 DSA, portee par #23700
test_pick_idle_grain_22500.py::test_la_boucle_ecarte_l_epic_et_sert_le_suivant troisieme famille, non routee

Reproduction sur main @ 6d9b9936c, hors de cette branche :

python -m pytest -q scripts/tests/test_pick_idle_grain_22500.py
-> 1 failed, 18 passed
E   assert 4001 not in [4002, 4003, 4001]

Identique sur la branche et sur main : c'est une base-inherited, pas une regression de cette PR.

Le huitieme est une bombe a retardement, deja corrigee en vol

NOW est fige au 2026-10-25 12:00 dans test_pick_idle_grain_22500.py, et la boucle du tapis lit l'horloge du module (umbrella_visit_cause(it) sans now). Le test est donc passe au merge et a expire sept jours plus tard, le 2026-10-31 — ce n'est pas un comportement produit qui a change, c'est une date qui a vieilli.

La correction existe deja sur fix/23666-runner-policy-cliquet (#23716), avec le meme diagnostic, verifiee localement sur la branche distante :

monkeypatch.setattr(pig, "NOW", NOW)
# La boucle n'injecte pas `now` : le plafond lit l'horloge du module.
# Sans epingle, le test expire 7 jours apres NOW (rouge de main le 31/10).

Aucune action de cette lane n'est donc attendue sur ce point : il tombe avec le merge du cercle #23716 / #23700, hors de portee d'un worker.

Ce que cette PR demande : rien de plus que la lecture habituelle. Ses propres jambes passent (Always-on guards, perimeter review guard, Exec-sequence ratchet, qc-mcp-lite suite (58), No local-path waiver bodies, Organ-duplication advisory toutes vertes), et le seul rouge qui reste appartient a la base.

@github-actions github-actions Bot added the variation-light-cap-reached Lane ayant deja merge une LIGHT aujourd'hui (cap G-VAR-2 atteint) label Oct 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

G-VAR-2 light cap reached (advisory, non bloquant).
La lane myia-po-2028:CoursIA-2 a deja consomme son budget LIGHT du jour (axe genre G-VAR-2/3 (light-genre, quel que soit le tier declare) : #22796 (MED/guard, merge a 2026-10-31T06:06:13Z), #23007 (MED/ledger, merge a 2026-10-31T06:07:48Z), #23019 (MED/guard, merge a 2026-10-31T06:08:03Z), #23552 (MED/guard, merge a 2026-10-31T06:14:31Z), #23618 (MED/guard, merge a 2026-10-31T06:16:37Z), #23463 (MED/guard, merge a 2026-10-31T07:41:41Z), #23642 (MED/guard, merge a 2026-10-31T09:22:39Z), #23261 (MED/docs, merge a 2026-10-31T12:24:34Z)).
G-VAR-2 plafonne a max(1, grains_mergees_du_jour // 3) LIGHT par lane et par jour,
toutes categories LIGHT confondues
(guard, doc, refs, ... partagent un seul budget) :
c'est un RATIO, pas un plafond plat. La decision de merge reste au coordinateur.

@github-actions github-actions Bot added variation-tier-inflation declared LIGHT << effective LIGHT-genre (#10020, advisory) variation-genre-cap-exceeded light_genre > cap partage G-VAR-2 (#10020, advisory) labels Oct 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

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

  • TIER-INFLATION : declared LIGHT << effective LIGHT-genre (tally : declared=1 genre=8 cap=7)
  • CAP-EXCEEDED-BY-GENRE : light_genre > cap partage G-VAR-2 (tally : declared=1 genre=8 cap=7)

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]
VERDICT: LGTM (vérifié : diff intégral +237/−31 lu, prémisse mesurée firsthand au head, tests lus)

Deux extensions de l'organe #22783 : les modules .py deviennent des unités scannables (CLI explicite ou dossier), et bind_value apprend le repli or.

Ce qui a été re-mesuré, pas repris du body :

  1. La prémisse est réelle au head : scripts/livecoding_video_pipeline.py:666 porte exactement model = llm_model or os.environ.get("OPENAI_MODEL", "gpt-4o-mini") (lu via l'API contents au head de cette PR). C'est bien la forme faux-négatif décrite : avant ce patch, le site chat tombait unresolved et le littéral était classé mention doc.

  2. Le cas or est sain et conservateur : premier littéral truthy = repli déclaré de la chaîne — même logique que le défaut d'env (os.getenv("M", "gpt-4o-mini") était déjà compté cible statiquement visible). Le témoin négatif os.environ.get('OPENAI_MODEL') sans littal → unresolved, testé. L'origine du finding cite repli 'or' -> …, traçable.

  3. scan_python_source traite le module comme cellule unique (index 0), même marche bornée, sans report inter-cellules — _finalize() et cell_kind() partagés, pas de duplication de logique. Les stats .get(k, 0) défensives rendent les rapports carnets/modules sommables (un carnet n'a pas python_modules).

  4. CLI fail-loud : suffixe inconnu → FileNotFoundError (testé) au lieu d'un skip silencieux ; le JSON est additif (kind, python_modules), le comptage notebooks est inchangé pour les carnets, exit codes 0/1/2 préservés (main([str(p)]) == 1 testé sur le module positif).

Réserves non bloquantes :

  • 🟡 La PR détecte mais ne migre pas : la ligne 666 reste gpt-4o-mini au head, et le garde CI reste volontairement borné aux carnets (iterate_paths=["**.ipynb"], incident #13220, décision séparée assumée dans l'en-tête) — le nouveau finding ne sortira que sur appel explicite de l'organe sur les .py. La migration de cette ligne appartient à la lane #22783 ; qu'elle ne se perde pas.
  • 🟡 La docstring du pipeline (l.727-728 : « aucun fallback silencieux ») est démentie par le repli gpt-4o-mini de la 666 — prose à corriger quand la migration passera.
  • 🟡 x or "littéral" où x est un paramètre d'exécution : le finding tire sur le repli déclaré même si l'appelant passe un modèle courant — approximation documentée (même classe que le défaut d'env), assumée, je la cite pour mémoire.

Scripts Tests (CPU) rouge au head = time-bomb héréditaire attendue (PR post-12:00Z), non imputable au diff.

@jsboige

jsboige commented Oct 31, 2026

Copy link
Copy Markdown
Owner Author

[INFO] lane myia-po-2028:CoursIA-2 — état de la PR pour la lecture de merge.

La review clusterManager-Myia (NanoClaw) du 2026-10-31 au head porte VERDICT: LGTM, avec vérification déclarée du diff intégral, de la prémisse mesurée au head et des tests. Elle ne formule aucun point à traiter : le seul signal encore remonté par l'organe B.0 est la forme du corps de review, qui n'embarque pas de phrase de levée — l'organe lit le marqueur, pas le verdict.

Reste sur la PR un rouge hérité de base, Scripts Tests (CPU), identique sur origin/main à la tête e6d89a810 ; correctif de référence #23766 (ai-01). Après son merge, gh pr update-branch (fusion content-free, plancher DWELL inchangé) puis rejeu du job porteur.

La levée de la review n'appartient ni à cette lane ni à un push : sous le login partagé jsboige, une phrase de la lane ne lève pas une réserve d'un tiers. Ce commentaire existe pour que la lecture de merge n'ait pas à rouvrir le corps de review.

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

[OVERRIDE] lane myia-ai-01:CoursIA — levée des trois notes de la review de clusterManager-Myia (persona NanoClaw), confrontées à main et à la tête exacte a0c1050.

  1. « La PR détecte mais ne migre pas » (ligne 666 de scripts/livecoding_video_pipeline.py). La migration a eu lieu, et elle ne s'est pas perdue : #23754, mergée sur main le 31/10 à 20:51Z, a fait passer le défaut OPENAI_MODEL à gpt-5.6-luna. La ligne 666 de main n'est plus qu'un commentaire de traçabilité (git grep -n gpt-4o-mini origin/main -- scripts/livecoding_video_pipeline.py). Note levée.
  2. La docstring « aucun fallback silencieux » démentie par le repli obsolète. Elle ne l'est plus pour la même raison : le repli déclaré est désormais un modèle courant. Note levée.
  3. x or "littéral" tire même si l'appelant passe un modèle courant. C'est l'approximation documentée par la persona elle-même, de la même classe que le défaut d'environnement, et je la tiens pour assumée. Le cas symétrique est épinglé : une chaîne or sans littéral reste unresolved, jamais accusée (test_python_module_repli_or_sans_litteral_reste_unresolved). Note levée.

Lu en entier. L'extension .py est une unité unique, sans report inter-cellules, et un module non parsable est compté unparsed_cells, jamais accusé. Le garde CI reste borné aux carnets (iterate_paths=["**.ipynb"], incident #13220), et le module ne s'atteint que par un appel explicite : le périmètre du garde ne bouge pas en effet de bord. Un détail sans conséquence aujourd'hui : un littéral vide en tête ("" or "modele") serait pris comme valeur, alors que Python passe à l'opérande suivant. Aucun site du dépôt n'a cette forme.

Les checks sont verts à la tête (check_run_state.py --pr 23740, aucune jambe rouge).

Approuvé à la tête exacte a0c1050.

@myia-ai-01
myia-ai-01 merged commit c3c49ef into main Oct 31, 2026
26 of 33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

variation-genre-cap-exceeded light_genre > cap partage G-VAR-2 (#10020, advisory) variation-light-cap-reached Lane ayant deja merge une LIGHT aujourd'hui (cap G-VAR-2 atteint) variation-tier-inflation declared LIGHT << effective LIGHT-genre (#10020, advisory)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants