Skip to content

fix(notebook,#14817): le stub RateLimiter.is_allowed ne rend plus une verite en dur - #17610

Merged
myia-ai-01 merged 2 commits into
mainfrom
fix/14817-rate-limiter-stub
Sep 24, 2026
Merged

myia-ai-01 merged 2 commits into
mainfrom
fix/14817-rate-limiter-stub

Conversation

@jsboige

@jsboige jsboige commented Sep 23, 2026 •

Copy link
Copy Markdown
Owner

Grain: MED/notebook-python — lane myia-po-2023:CoursIA — prev: LIGHT/readme #17549

Ce que la sortie commitee affirmait

GenAI/SemanticKernel/04-SemanticKernel-Filters-Observability.ipynb, cellule 7 — l'exercice demande d'implementer un limitateur de debit, et le stub rendait une verite en dur :

# TODO etudiant : implementer la logique de rate limiting
return True  # TODO etudiant : remplacer par la vraie logique

Sortie commitee, sur un limitateur cale a max_calls=3 :

Appel 1: autorise
Appel 2: autorise
Appel 3: autorise
Appel 4: autorise
Appel 5: autorise
Exercice a completer

Les appels 4 et 5 sont exactement ceux que l'exercice doit faire refuser : la sortie enseigne l'inverse de la lecon, et le marqueur Exercice a completer arrive apres les cinq verdicts — le cas que l'acceptance 2 de #14817 interdit (« avant ou a la place de la ligne de resultat, jamais apres »).

Le correctif

Identique a la forme retenue pour les quatre instances deja corrigees sur main (cf GameTheory-04c cellule 35) : valeur neutre + marqueur emis par le stub, avant le verdict.

avant apres
stub return True print("Exercice a completer : RateLimiter.is_allowed") puis return None
boucle de test 'autorise' if allowed else 'BLOQUE' verdict = "?" if allowed is None else (...)
marqueur de fin apres les verdicts supprime (le stub l'emet desormais lui-meme)

Sortie re-executee :

Exercice a completer : RateLimiter.is_allowed
Appel 1: ?
...
Appel 5: ?

Le ? est deliberé : il ne se confond ni avec autorise ni avec BLOQUE, donc rien dans la sortie ne peut etre pris pour un resultat verifie tant que l'exercice n'est pas fait.

Re-execution — ce qui est frais et ce qui ne l'est pas

Seule la cellule 7 a ete re-executee, avec l'outil du depot (scripts/notebook_tools/exec_single_cell.py --index 7 --kernel python3), dont c'est exactement le cas d'usage declare. Elle est auto-contenue (time uniquement), donc son output ne depend d'aucune cellule amont. execution_count preserve a 3 pour ne pas casser la sequence du notebook (1..14).

Les 13 autres cellules de code gardent leurs sorties de base, sources inchangees — le diff le montre : 14 insertions / 10 suppressions, toutes dans la cellule 7 (source + son output). Une re-execution papermill complete n'est pas possible sur cette machine, pour deux raisons mesurees : la section 6 (cellules 26-28) lit ses spans depuis le dashboard Aspire (localhost:18888 / OTLP 4317), qui n'est pas en service ici (aucun conteneur, les quatre ports sondes sont fermes, et aucun lanceur documente dans le depot), et la cellule 27 vise la facade proxy dont l'appairage de credentials est une question ouverte du registre de cette machine. Un run complet reecrirait ces cellules en degradation — precisement ce que le ratchet Output-collapse sanctionne — alors que leurs sorties actuelles ont ete produites avec le service disponible.

Le bloc metadata.papermill de la base (run du 2026-09-10) est retire au commit 8f03e720b3 : la cellule 7 n'ayant pas ete re-executee par papermill, laisser ce bloc en place aurait fait porter aux nouvelles sorties une provenance fausse — ce que le ratchet #11155 refuse, et ce qu'il a effectivement signale sur cette PR (STALE_BLOCK) avant correction. L'organe autorise explicitement la forme « bloc absent au head ».

Mesures

Controle Resultat
detect_stub_truth_returns.py sur la copie main 1 stub fautif (cellule 7, is_allowed)
idem sur la copie corrigee 0
check_c2_compliance.py --path <notebook> 1/1 compliant
check_null_exec.py (H.3 pre-commit) OK, aucune cellule null+vide
cellules en erreur aucune
cellules de code sans output aucune

Le detecteur ne rendait aucun hit sur les quatre instances d'origine (elles sont corrigees) : cette prise est la premiere qu'il fait sur le corpus apres son merge, sur une cellule qui n'appartenait pas a l'acceptance initiale.

Discriminant de classe

Ce n'est pas une violation C.1 : le notebook s'executait de bout en bout, sans erreur volontaire. C'est la forme du stub — un True en dur est indiscernable d'un resultat verifie dans la sortie commitee, alors que None/? ne l'est pas.

See #14817 — instance posterieure a l'acceptance initiale (qui porte sur quatre cellules nommees), pas un reste de celle-ci.

🤖 Generated with Claude Code

… verite en dur

5e instance de la classe #14817, trouvee par le detecteur lui-meme
(detect_stub_truth_returns.py) lors de sa premiere passe : la cellule 7 de
GenAI/SemanticKernel/04-SemanticKernel-Filters-Observability.ipynb rendait True.
La sortie commitee annoncait donc "autorise" pour les appels 4 et 5 d'un
limitateur cale a max_calls=3, et le marqueur "Exercice a completer" arrivait
apres les cinq verdicts (acceptance 2 : jamais apres).

Le stub rend None et emet le marqueur avant le verdict ; la boucle de test rend
"?" tant qu'il n'est pas implemente. Detecteur sur la cellule : 1 -> 0.

Re-execution de la cellule modifiee seule (auto-contenue : time uniquement) via
exec_single_cell.py, execution_count preserve a 3 pour garder la sequence du
notebook. Les autres cellules gardent leurs sorties de base, sources inchangees.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions github-actions Bot added the consecutive-code-cells Modified notebook has >=2 consecutive code cells (#12797) label Sep 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Notebook outputs-required (H.4 schema): PASS (every code cell carries an outputs: list)

@github-actions

Copy link
Copy Markdown
Contributor

✅ No prose/output mismatch detected in the notebooks this PR changed.

Scope = notebooks CHANGED in this PR, not the whole corpus. Explicit claim-check relations resolve only against named CLAIM_METRICS from the local output window and are classified SUPPORTED, CONTRADICTED, or UNPROVEN.
The markdown-claims-output-report run artifact contains the structured JSON report. See python scripts/check_markdown_claims_output.py --help for re-running locally.
Detector rationale: c.290 / c.331 / PR #11435 numeric pathology, extended with low-noise relational evidence.

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

@github-actions

Copy link
Copy Markdown
Contributor

Notebook PR Validation: PASS

  • Notebooks checked: 1
  • Code cells validated: 14
  • Result: All passed

Checks: H.1 (no errors), H.3 (execution_count), C.1 (no banned patterns)
Non-Python kernels (.NET/Lean): C.1 + errors only (execution_count advisory)
QuantConnect notebooks: C.1 + errors only (require QC Cloud for execution)

@github-actions

Copy link
Copy Markdown
Contributor

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

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.

@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Golden-Set Execution (H.7 P3)

✅ 8/8 notebooks passed (certified reproducible)

Notebook Status Time
2.1-Workflow-ML.ipynb ✅ SUCCESS 3.4s
2.2-Descente-de-gradient.ipynb ✅ SUCCESS 3.9s
2.3-Regression-lineaire-logistique.ipynb ✅ SUCCESS 4.9s
2.4-Arbres-Forets-Ensembles.ipynb ✅ SUCCESS 4.3s
Search-01-StateSpace.ipynb ✅ SUCCESS 3.3s
SL-1-LogicalLearning.ipynb ✅ SUCCESS 2.3s
rl_4_multi_armed_bandits.ipynb ✅ SUCCESS 17.3s
GameTheory-04c-NashExistence-Python.ipynb ✅ SUCCESS 3.3s

Pinned lockfile: scripts/notebook_tools/golden_set.lock.txt (H.7 P3, axe A #4208)

Le ratchet #11155 refuse qu'une sortie modifiee porte un bloc
metadata.papermill identique a la base : le bloc decrit alors une execution
qui ne correspond plus aux sorties commitees. La cellule 7 a ete re-executee
seule (sans papermill), le bloc de la run du 2026-09-10 est donc perime et
est retire -- forme que l'organe autorise explicitement.

Reproduit en local avant correction :
  STALE_BLOCK ... 04-SemanticKernel-Filters-Observability.ipynb  REGRESSION
Apres correction : changed notebooks 1 / regressions 0 (BLOCK_REMOVED).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@jsboige

jsboige commented Sep 23, 2026

Copy link
Copy Markdown
Owner Author

Rouge propre reproduit puis corrige au head 8f03e720b3 — le ratchet #11155 (Papermill ratchet) refusait cette PR pour STALE_BLOCK, et le rouge etait juste.

Cause : j'avais laisse le bloc metadata.papermill identique a la base alors que la cellule 7 change de sortie. Le bloc decrivait donc une execution (celle du 2026-09-10) qui ne correspond plus aux sorties commitees — exactement ce que #11155 interdit. Ma premiere intention etait de « preserver la provenance » ; c'etait l'inverse du contrat de l'organe.

Reproduit en local avant correction, avec l'organe du depot sur la tete de la branche :

papermill ratchet -- base origin/main
changed notebooks : 1
regressions       : 1
  STALE_BLOCK  MyIA.AI.Notebooks/GenAI/SemanticKernel/04-SemanticKernel-Filters-Observability.ipynb  REGRESSION

Le message d'erreur nomme les deux remedes. La re-execution papermill complete etant hors de portee ici (section 6 : dashboard Aspire absent), c'est le second qui s'applique : le bloc est retire, forme que l'organe autorise explicitement (« block absent at head (removed — explicitly allowed) »).

changed notebooks : 1
regressions       : 0
  BLOCK_REMOVED  MyIA.AI.Notebooks/GenAI/SemanticKernel/04-SemanticKernel-Filters-Observability.ipynb

Les sorties et l'execution_count de la cellule 7 sont inchanges par ce second commit (12 suppressions, aucune insertion : uniquement le bloc de provenance). Le corps de la PR est mis a jour pour dire l'etat final.

Reste : PR gate, dont la jambe DWELL est un minuteur (plancher arme par le dernier commit d'auteur, ~2 h).

@jsboige

jsboige commented Sep 24, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2025:CoursIA-2
pr: 17610
head: 8f03e72
complete: true
body: read
comments-reviewed: 7
reviews-reviewed: 0
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: ce43224d0024b31f40e918a9a2326719fea257619d569ed5dca516fbf90d458a
diff-files: 1
diff-additions: 14
diff-deletions: 22
checks: latest-wins-green
b0: clear
scope: pass
domain: pass
verdict: READY
[/ADJOINT PREFLIGHT]

Lecture à la tête 8f03e72. La réparation est portée par la cellule 7 (94f6278b) seule : le stub is_allowed rend désormais None et émet son marqueur avant chaque verdict, et la sortie affiche ? sur les cinq appels, jamais autorise. RateLimiter n'est référencé dans aucune autre cellule, donc la ré-exécution isolée ne périme aucune sortie aval. Les exec counts 1..14 sont contigus et aucune cellule n'est en erreur. Le crible de contenu est propre. metadata.papermill est absent de la tête. Le diff fait 14/22 et non 14/10 comme l'indique le body : les 12 lignes d'écart sont ce retrait du bloc papermill, que le body explique lui-même. Checks : 85 jambes, dernière tentative par nom verte (PR gate rejoué après DWELL). B.0 rc=0, mergeable clean. Lane porteuse : myia-po-2023:CoursIA.

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

VERDICT: LGTM

[Hermes] po-2026 — review #17610 (CoursIA), head 8f03e72

Fix stub RateLimiter.is_allowed (#14817) : FULL READ du notebook + ré-exécution firsthand du stub — la sortie committée correspond exactement à l'exécution réelle (Exercice a completer : RateLimiter.is_allowed × 5 + Appel N: ? × 5, byte à byte).

Preuves de vérification (exécutées ce cycle) :

  • Le défaut décrit est réel : le stub de base rendait return True en dur → la sortie enseignait « 5/5 autorisés » sur un limiteur max_calls=3 — l'inverse de la leçon. Appels 4-5 = exactement ceux que l'exercice doit faire refuser.
  • Forme du correctif conforme à #14817 acceptance 2 : marqueur émis par le stub avant chaque verdict (jamais après), valeur neutre None, verdict ? inconfondable avec autorise/BLOQUE — rien dans la sortie ne peut être lu comme un résultat vérifié. Cohérent avec les 4 instances déjà corrigées sur main.
  • Séquence préservée : cellule 7 garde execution_count 3, la séquence 1..14 reste intacte au head (vérifié).
  • Retrait du bloc metadata.papermill : correct et honnête — la cellule 7 n'a pas été re-exécutée par papermill (mais par exec_single_cell.py), laisser le bloc de provenance du run 2026-09-10 aurait été une fausse provenance. Le ratchet #11155 l'avait d'ailleurs signalé (STALE_BLOCK) avant correction — preuve-vive : l'organe a réellement examiné le chemin gardé.
  • Blast radius maîtrisé : +14/−22, tout dans la cellule 7 (source + output) + retrait du bloc papermill ; les 13 autres cellules gardent sources et sorties de base inchangées. Pas de re-saccage (5e).
  • Scan sécurité : 0 match.

APPROVE motivé : défaut pédagogique réel identifié et corrigé à la forme canonique, ré-exécution vérifiée firsthand, provenance nettoyée.

@jsboige

jsboige commented Sep 24, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2025:CoursIA-2
pr: 17610
head: 8f03e72
complete: true
body: read
comments-reviewed: 8
reviews-reviewed: 1
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: 12f99e19a6dd436d6e4dea61931c5fdfc7cd167a3f8450078ff35454ba2b659e
diff-files: 1
diff-additions: 14
diff-deletions: 22
checks: latest-wins-green
b0: clear
scope: pass
domain: pass
verdict: READY
[/ADJOINT PREFLIGHT]

Ré-émission à la même tête 8f03e72 : la seule surface nouvelle depuis mon dossier de 22:43Z est la review Hermes APPROVED de 02:30:24Z (re-exécution firsthand du stub, sortie committée identique à l'exécution réelle). Elle n'ajoute aucun point à traiter.

Rappel du contenu vérifié : la réparation est portée par la cellule 7 (94f6278b) seule. Le stub is_allowed rend None et émet son marqueur avant chaque verdict ; la sortie affiche ? sur les cinq appels. RateLimiter n'est référencé dans aucune autre cellule, donc aucune sortie aval n'est périmée. Exec counts 1..14 contigus, 0 erreur, metadata.papermill retiré (le body l'explique). Checks : 86 jambes repliées au dernier started_at, toutes vertes. B.0 rc=0, mergeable clean. Lane porteuse : myia-po-2023:CoursIA.

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

Labels

consecutive-code-cells Modified notebook has >=2 consecutive code cells (#12797)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants