Skip to content

Fix(sudoku,#20356): stubs booleens C.1 -- return False -> return None (5 carnets) - #20360

Open
jsboige wants to merge 3 commits into
mainfrom
fix/20356-sudoku-stub
Open

jsboige wants to merge 3 commits into
mainfrom
fix/20356-sudoku-stub

Conversation

@jsboige

@jsboige jsboige commented Oct 11, 2026 •

Copy link
Copy Markdown
Owner

Grain: LIGHT/notebook-python — lane myia-po-2027:CoursIA-2 — prev: LIGHT/tooling #20297

Part of #17073

Constat (re-verifie firsthand sur origin/main)

Provenance : audit externe (ChatGPT, 11/10), re-verifie selon audit-reassessment. Le defaut est CONFIRME : le stub retournait False, une valeur de retour plausible pour une fonction booleenne.

Sudoku-01-Backtracking-Python.ipynb, cellule 10 (exercice non resolu) :

return False  # TODO étudiant : remplacer par l'implémentation

Sortie committee :

Solution valide (puzzle de test) : False
Grille incomplète valide : False

Les deux lignes affichent False — dont la seconde correcte par accident. Le carnet vient de demontrer un solveur backtracking fonctionnel : la lecture naturelle du livrable est « la solution produite n'est PAS valide ». L'etudiant ne peut pas distinguer le verdict reel du verdict de stub. None s'affiche au contraire comme « non implemente ».

Correction

return False -> return None, pattern C.1 canonique pour une fonction booleenne. Aucune erreur volontaire introduite (raise / assert False / 1/0 interdits) ; le carnet reste executable de bout en bout.

Carnet Cellule stub Sortie du stub apres correction
Sudoku-01-Backtracking 10 Solution valide (puzzle de test) : None / Grille incomplete valide : None
Sudoku-10-ORTools 14 Solution valide : None / Exercice a completer
Sudoku-02-DancingLinks 19 inchangee (le stub n'est appele dans aucune sortie)
Sudoku-05-PSO 31 inchangee (idem)
Sudoku-12-Z3 15 inchangee (idem)

Perimetre etendu au-dela du titre (5 carnets au lieu de 1). #20356 ne nomme que Sudoku-01 ; le meme stub (return False # TODO) est present a l'identique dans 4 autres carnets de la serie Sudoku. Traiter la cause une fois evite 4 allers-retours. Les 3 carnets dont la sortie du stub ne change pas sont inclus parce que leur source change (C.3 : on committe les carnets dont on a modifie une cellule source).

Deuxieme correctif : sortie portable de Sudoku-12 (commit 778ba5a6465b)

La re-execution de Sudoku-12 a fait rougir le ratchet Output-failure : MACHINE_PATH: 0 -> 1 dans Sudoku-12-Z3-Python.ipynb cellule 6, qui imprimait Path.cwd() / "Puzzles", donc le chemin absolu de la machine d'execution.

La sortie de la cellule 6 de Sudoku-12 a donc bel et bien change — la ligne du tableau ci-dessus ne vaut que pour la cellule 15 (le stub). Cure par Stop & Repair : la source n'affiche plus que le nom du dossier (PUZZLES_DIR.name), le chemin complet reste calcule dans PUZZLES_DIR pour les entrees/sorties, puis re-execution complete. Aucune sortie n'a ete hand-editee.

Troisieme correctif : re-attestation de la parite twin (commit 3289999e1722)

Les 5 carnets Python touches deplacent leur blob, donc l'organe Twin parity audit (#8057) signalait 5 DRIFT_INTRODUCED. Re-attestation par l'organe dedie (check_twin_parity.py --update --pair, une entree append-only par paire) apres --check : OK=16 DRIFT=0 MISSING=0 sur la famille Sudoku.

Asymetrie declaree, pas tairee. Le jumeau C# n'est pas touche : sa convention de stub est return null; // TODO partout ou le type le permet, et return false; / return 0; la ou le type l'interdit (bool et int ne sont pas nullables en C#). C'est une contrainte de langage, pas une divergence pedagogique — la serie C# entiere porte ces litteraux (Sudoku-09 cell 27, Sudoku-12 cell 37/41, Sudoku-18 cell 23, entre autres). Les deux cotes restent des exercices non implementes ; seul le litteral de retour a change cote Python, d'un resultat fabrique vers une absence explicite. Chaque fiche de paire porte cette declaration dans ses known_differences.

Preuve d'execution (C.2, H.3)

Sudoku-01-Backtracking : Success 1 / Failed 0 / 22.9s
Sudoku-02-DancingLinks : Success 1 / Failed 0 /  4.2s
Sudoku-05-PSO          : Success 1 / Failed 0 / 72.4s
Sudoku-10-ORTools      : Success 1 / Failed 0 /  8.1s
Sudoku-12-Z3           : Success 1 / Failed 0 / 35.9s  (re-execution apres correctif cellule 6)

Executeur canonique scripts/notebook_tools/notebook_tools.py execute --python-only, cwd par defaut = dossier du carnet. Cellules modifiees re-executees, execution_count contigus, 0 erreur, 0 chemin machine dans les sorties. Ratchet local check_output_failure_text.py origin/main : 0 regressed. Dependances manquantes installees localement (ortools, mealpy) plutot que contournees (regle F).

Perimetre

15 fichiers : les 5 carnets Python ci-dessus, plus 10 fiches de registre twin (5 fiches de paire completees d'une declaration + 5 entrees d'audit append-only). Aucun jumeau C# modifie.

Criteres d'acceptation #20356

  • Le stub retourne None (pattern C.1 canonique pour une fonction booleenne) ; les prints de test affichent un resultat clairement « non implemente »
  • Alternative (conditionner les prints a l'implementation) non necessaire : None remplit deja l'objectif sans branchement
  • Re-execution de la cellule modifiee avant commit — le carnet reste executable de bout en bout

Closes #20356

🤖 Generated with Claude Code

… (5 carnets)

La sentinelle False d'un stub est une valeur de retour plausible pour une
fonction booleenne : la sortie commitee se lit comme un verdict (« la solution
du solveur n'est PAS valide »), alors qu'un None se lit comme « non
implemente ». None est le pattern canonique C.1, sans erreur volontaire.

Sites normalises : Sudoku-01/02/05/10/12. Les carnets 01 et 10 surfacaient le
verdict dans leur sortie ; les trois autres portent le meme motif sans appel,
leur sortie est inchangee.

Re-execution complete des 5 carnets (C.2) : 0 erreur, execution_count non nul
partout, aucune banniere degradee, aucun chemin machine.

Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the consecutive-code-cells Modified notebook has >=2 consecutive code cells (#12797) label Oct 11, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Prose/output review needed in the notebooks this PR changed: a numeric value is not anchored, an explicit relation is contradicted, or its evidence is missing. These cases remain distinct in the JSON report; the signal is advisory, NOT a merge gate.

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

⚠️ Stale-claim review needed: a markdown cell claims a measurement value that appears in NO committed output of the notebook. Advisory, NOT a merge gate — triage against the JSON artifact.

Scope = notebooks CHANGED in this PR, not the whole corpus. The stale-claim-report run artifact holds the structured JSON.
Rationale: the sibling detector above only compares a claim to the outputs of the cells that PRECEDE it; a claim written in a cell that precedes its code (App-5-Timetabling c.2/c.4) is invisible to it, and a value imported from a twin notebook is never produced locally. See python scripts/check_stale_claims.py --help.

@github-actions

Copy link
Copy Markdown
Contributor

✅ No factual mislabel detected in the notebooks this PR changed (entity counts and tuple formulas checked against nearby committed streams).

Scope = notebooks CHANGED in this PR, not the whole corpus. The factual-mislabel-report run artifact holds the structured JSON.
Rationale: pure ABSENCE of a claimed value is the sibling stale-claim detector's job; this one only reports CONTRADICTIONS between an adjacent code cell's stream and the markdown that describes it. See python scripts/check_factual_mislabel.py --help.

@github-actions

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Golden-Set Execution (H.7 P3)

✅ 9/9 notebooks passed (certified reproducible)

Notebook Status Time
2.1-Workflow-ML.ipynb ✅ SUCCESS 5.0s
2.2-Descente-de-gradient.ipynb ✅ SUCCESS 4.0s
2.3-Regression-lineaire-logistique.ipynb ✅ SUCCESS 4.1s
2.4-Arbres-Forets-Ensembles.ipynb ✅ SUCCESS 4.1s
Search-01-StateSpace.ipynb ✅ SUCCESS 2.8s
SL-1-LogicalLearning.ipynb ✅ SUCCESS 2.0s
RL-04-Bandits-Manchots-Python.ipynb ✅ SUCCESS 18.8s
GameTheory-04c-NashExistence-Python.ipynb ✅ SUCCESS 8.0s
GameTheory-13d-Optimistic-CFR-Python.ipynb ✅ SUCCESS 10.8s

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

@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: 5
  • Code cells validated: 65
  • 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)

@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é: extraction protocole v2 des 5 carnets base+head, alignement cellule-à-cellule byte-à-byte, recherche repo-wide des stubs, empreintes des outputs)

Review structurelle + protocole v2 (carnets extraits via raw contents API, markdown lu intégralement, outputs réduits à des empreintes — jamais de JSON brut/base64 en contexte).

Ce qui est vérifié

  • Uniformité du fix : exactement 1 cellule code modifiée par carnet (Sudoku-01 is_valid_solution [10], Sudoku-02 verify_dlx_solution [19], Sudoku-05 has_converged [31], Sudoku-10 verify_solution_with_ortools [14], Sudoku-12 solve_with_sum_constraint [15]) ; toutes les autres cellules — code ET markdown — sont byte-identiques base↔head. Chaque changement est exactement return False → return None # TODO étudiant… (commentaire préservé).
  • Complétude repo-wide : recherche "return False # TODO" sur tout le dépôt = 0 occurrence — la classe des stubs booléens trompeurs est éteinte, l'audit externe du 11/10 est bien traité sur ses 5 fichiers.
  • Outputs honnêtes : les sorties des cellules stub modifiées impriment désormais None (« Solution valide (puzzle de test) : None », « Grille incomplète valide : None »), avec execution_count réels (5, 7). Le compte de caractères stdout suit exactement la substitution (74→72, 45→44).
  • Dérive des outputs inchangés = bénigne et classée : les sorties divergent base↔head sur ~13 cellules à source identique — intégralité vérifiée : timings de benchmarks (ex. 0.23→0.17 ms, 1517→2627 ms), bump d'environnement (numpy 2.4.2→2.4.6), et rattrapage d'un output base périmé (Sudoku-12 cell 6 : la ligne « Dossier Puzzles : … » existe dans la source des deux côtés mais manquait à l'output base). Cohérent avec une re-exécution complète et séquentielle, aucune valeur pédagogique altérée.
  • Markdown intact : zéro cellule markdown modifiée — les gates #17040 (1 lecture par output, valeurs citées présentes dans les outputs committés) restent satisfaites par construction.

Réserves mineures (non bloquantes)

  1. Typage : les signatures -> bool des 5 fonctions stub retournent désormais None — -> bool | None serait plus honnête envers les étudiants. (NotImplementedError sacrifierait l'exécutabilité du carnet ; le choix None est défendable, seule l'annotation est en retard.)
  2. Re-exécution au-delà du périmètre stub : les outputs regénérés touchent aussi les cellules benchmark/environnement hors des 5 cellules modifiées (timings, numpy 2.4.6). Bénin — et le rattrapage de l'output périmé de Sudoku-02/12 est un mieux — mais un mot dans le body l'aurait déclarée explicitement.

Lane myia-po-2027:CoursIA-2, grain LIGHT/notebook-python — périmètre respecté (5 fichiers, 5 cellules), partie de #17073, corrige l'issue #20356.

— NanoClaw (myia-ai-01) [11:05Z]

…ATH)

La cellule 6 imprimait `Path.cwd() / "Puzzles"`, donc le chemin absolu de la
machine d'execution. Toute re-execution le regenere : c'est ce qui a fait
rougir le ratchet Output-failure (MACHINE_PATH 0 -> 1) sur ce carnet lors de
la re-execution des stubs booleens.

La source n'affiche plus que le nom du dossier ; le chemin complet reste
calcule dans PUZZLES_DIR pour les entrees/sorties. Re-execution complete
(11/11 cellules, 0 erreur, 0 chemin machine).

Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
Les 5 carnets Python touches par #20356 deplacent leur blob -> l'organe
Twin parity signalait 5 DRIFT_INTRODUCED. Re-attestation par l'organe dedie
(--update --pair, une entree append-only par paire), plus la declaration de
l'asymetrie de stub cote C# dans les known_differences : C# garde
`return null; // TODO` la ou le type le permet et `return false;`/`return 0;`
la ou il l'interdit (bool et int ne sont pas nullables) -- contrainte de
langage, pas divergence pedagogique.

Controle : OK=16 DRIFT=0 MISSING=0 sur la famille Sudoku.

Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
@jsboige

jsboige commented Oct 11, 2026

Copy link
Copy Markdown
Owner Author

Perimetre mis a jour a la tete 3289999e1722 — et une mesure anterieure est desormais perimee.

La revue de clusterManager-Myia porte une assertion « 5 fichier(s) ». Elle etait exacte a sa date, a la tete 1dd84cb957de (les 5 carnets). Deux commits de contenu sont arrives depuis, donc le perimetre effectif est maintenant de 15 fichiers :

  • 778ba5a6465b — sortie portable de la cellule 6 de Sudoku-12-Z3-Python.ipynb (le ratchet Output-failure signalait MACHINE_PATH: 0 -> 1 apres la re-execution ; cure par correction de source puis re-execution, aucune sortie hand-editee) ;
  • 3289999e1722 — re-attestation de la parite twin des 5 paires Sudoku (OK=16 DRIFT=0 MISSING=0 apres --check), soit 10 fiches de registre.

Detail dans le body, section « Perimetre ». check_pr_perimeter.py 20360 --scan-thread rend VERDICT: OK et ne retient cette assertion qu'en SIGNAL non bloquant, impute a son auteur.

Note pour la lecture B.0 : la ligne « Sudoku-12-Z3, inchangee » du tableau des sorties ne vaut que pour la cellule 15 (le stub). La sortie de la cellule 6 a bel et bien change ; c'est ecrit dans le body.

This branch has not been deployed

No deployments
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.

notebook(sudoku): Sudoku-01 -- stub is_valid_solution retourne False, la sortie commitee affiche un contre-verdict pedagogique

3 participants