Skip to content

Fix(guard,#24410): scan des citations de doc dans les commentaires de code (py/lean/cs) - #24718

Open
jsboige wants to merge 1 commit into
mainfrom
feature/docs-links-code-citations
Open

jsboige wants to merge 1 commit into
mainfrom
feature/docs-links-code-citations

Conversation

@jsboige

@jsboige jsboige commented Nov 4, 2026 •

Copy link
Copy Markdown
Owner

Grain: MED/guard — lane myia-po-2027:CoursIA — prev: MED/guard #24711

Défaut (#24410)

check_docs_links.py ne lit que du markdown : un chemin de doc cité dans un commentaire de code (.py, .lean, .cs) est structurellement invisible, vivant ou mort. Mesure de l'issue : 4 citations pointant un chemin déménagé, et 118 faux positifs pour un scan naïf.

Correctif — une passe dédiée --code, pas un élargissement du glob

Nouvelle passe séparée du scan markdown (les deux verdicts ne se mélangent pas : main porte déjà des liens markdown cassés que la baseline n'excuse pas, et fusionner les comptes rendrait un finding code indiscernable de ce rouge préexistant — contrainte explicite du body).

Extraction des commentaires, un correctif pour les trois langages :

  • Python : tokenize (les # hors chaînes) + ast (docstrings module/classe/fonction) — les deux stdlib et exacts ;
  • Lean : -- en ligne, /- -/ en bloc avec imbrication (s'arrêter au premier -/ scannerait du code comme commentaire) ;
  • C# : // et /* */. Un marqueur précédé d'un nombre impair de " est dans une chaîne, pas un commentaire.

Les trois familles de faux positifs, exclues par construction (pas par liste) :

  1. Fixtures de test — les arbres tests/, test/, __tests__/, testdata/, fixtures/ et les fichiers test_*/*_test.py ne sont pas scannés ;
  2. Positions de sortie — un chemin précédé sur sa ligne de --out, -o , >/>>, open(, write_text(, savefig(, to_csv(… est une écriture, pas une citation ;
  3. Chemins d'un dépôt tiers — une citation doit être ancrée à une entrée de notre racine (lean/docs/132.md appartient à openai/math) ; les formes .//../ sont résolues contre le fichier citant. Les segments doivent commencer par un alphanum : docs/...md (la forme dont la PROSE parle) ne matche pas, et l'instrument ne se signale donc pas lui-même.

Ancrage double : docs/x.md cité depuis un fichier profond signifie le plus souvent la racine du dépôt. Résoudre contre le seul répertoire du fichier rendait 224 citations « mortes » sur 230 (mesuré pendant la PR) ; une citation est morte seulement si ni l'ancre fichier ni l'ancre racine ne la trouvent. Un .//../ explicite nomme une seule ancre et n'est pas ré-ancré.

Périmètre : fichiers suivis par git (git ls-files) — un walk non élagué de ce checkout énumérait 93 876 entrées de code (paquets installés) contre 4 339 suivies par git ; repli sur un walk élagué quand git est injoignable (tests en arbre tmp).

Les trois attendus de l'issue

Attendu Livré
1. Passe dédiée aux commentaires de code, trois exclusions par construction --code (run_scan(code=True), find_code_files, scan_code_content)
2. Verdict différentiel --check --base REF --code : preexisting_broken route son scanner et son oracle d'existence vers la passe code (scanner=/exists_in_tree=, oracle miroir _citation_exists_in_tree à double ancre)
3. Contrôle positif branché sur le nouveau chemin --expect-broken N s'évalue sur le résultat de la passe sélectionnée ; testé par test_positive_control_arms_the_code_pass

Preuves (mesures sur ce siège, worktree origin/main + ce diff)

  • 127 passed (python -m pytest scripts/tests/test_check_docs_links.py -q), dont 33 nouveaux tests : extraction par langage, les trois exclusions, l'ancrage double, le dispatch différentiel, le contrôle positif.
  • Les 4 cas fondateurs de l'issue sont détectés et morts — test paramétré TestIssueReproducibleCases (m13_ms_har, hmm_regime_vol, s2_gsp_cross_asset_vol, comfyui_client).
  • Passe pleine : 231 citations, 203 vivantes / 28 mortes (vs 245/30 Python+Lean du body — écart attendu : arbres de tests exclus, docstrings inclus, ancrage racine), 13 s.
  • python scripts/check_docs_links.py --code --quiet → rc=1 (28 casses réels) ; --check --base origin/main --code → rc=0 (les 28 préexistants excusés, une PR sans rapport ne rougit pas) ; --expect-broken 40 --code → rc=2 (contrôle positif armé sur cette passe).
  • Aucune régression du scan markdown : run_scan() sans --code n'ouvre aucun fichier de code (testé).

Résiduel déclaré

  • Câblage CI (job fast-lane invoquant --check --base origin/main --code) : hors périmètre de ce grain (paths du claim limités à l'organe et ses tests). C'est la tranche suivante — sans elle, la passe est livrée mais pas encore exécutée par un gate. Je la note sur l'issue.
  • Les 28 citations mortes trouvées sont le signal livré, pas la dette réparée : leur correction (rediriger vers le chemin déménagé) est une fournée distincte, par série propriétaire.

Closes #24410

🤖 Generated with Claude Code

… code (py/lean/cs)

`--code` ouvre une seconde passe dediee de check_docs_links sur les
commentaires (.py via tokenize+ast, .lean/-- avec blocs imbriques, .cs),
avec les trois exclusions par construction (arbres de tests, positions de
sortie, chemins d'un depot tiers), l'ancrage double (fichier OU racine du
depot), le verdict differentiel via --check --base, et le controle positif
--expect-broken branche sur cette passe.

Closes #24410

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

github-actions Bot commented Nov 4, 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 4, 2026 •

Copy link
Copy Markdown
Contributor

Avertissements consultatifs

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

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

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.

G-VAR-2 light cap reached (advisory, non bloquant).
La lane myia-po-2027:CoursIA a deja consomme son budget LIGHT du jour (axe genre G-VAR-2/3 (light-genre, quel que soit le tier declare) : #24127 (LIGHT/ledger, merge a 2026-11-04T05:01:42Z), #24129 (LIGHT/docs, merge a 2026-11-04T05:04:20Z), #24555 (MED/guard, merge a 2026-11-04T07:18:58Z), #24582 (MED/docs, merge a 2026-11-04T12:33:06Z), #24642 (MED/docs, merge a 2026-11-04T20:16:47Z)).
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.

Une section par organe ; ce commentaire est reecrit en place, il n'est pas empile.

@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) coursia-advisory-lock-195e6112780 lane-claim-absent Closing issue carries no claim at all (#10223) and removed coursia-advisory-lock-195e6112780 labels Nov 4, 2026

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

Review [Hermes] — rejeu sur arbre réel (extraction tarball head 1b0bc924 + fichiers de base pour contraste)

APPROVE — les 3 attendus de #24410 vérifiés par exécution, pas par lecture du diff.

Passe réelle rejouée : --code trouve bien les 4 citations fondateurs de l'issue dans le rapport (m13_ms_har ×2, hmm_regime_vol, s2_gsp_cross_asset_vol, comfyui_client), toutes mortes. TestIssueReproducibleCases 6/6 verts une fois l'arbre reconstitué.

Les deux propriétés différentielles, mesurées :

  • --check --base HEAD --code → rc=0 : le dispatch scanner=/exists_in_tree= route bien la comparaison vers la passe code (testé aussi unitairement : test_preexisting_accepts_the_code_scanner exige que le fake_scanner soit appelé — seen == {"scanned": ..., "oracle": True}).
  • --expect-broken 999 --code → rc=2 « POSITIVE CONTROL FAILED » : le contrôle positif est armé sur la passe sélectionnée, pas sur la markdown.

Suite de tests : 119 passed au head sur mon arbre. 8 échecs identiques en base main sur le même arbre (DeckScope/SelfCheck/archive — tous exigent des dossiers que mon extraction partielle ne porte pas : slides/, curriculum, archives réelles) → artefacts d'extraction, pas de régression. Les 33 nouveaux tests + les classes TestDocCitationPattern/TestCommentSpans/TestCitationScope/TestCitationAnchoring/TestCodeScan : tous verts.

Le design, aux endroits où il aurait pu casser :

  • docs/...md (la forme dont la prose parle) ne matche pas : chaque segment doit commencer par alphanum/underscore — l'instrument ne se signale pas lui-même (testé : test_equivalence_shape_is_not_matched).
  • -> dans une signature n'est pas lu comme un redirect : le lookbehind (?<![-=]) l'exclut (testé : test_arrow_is_not_an_output_redirect).
  • Lean /- -/ imbriqué correctement géré (test_lean_nested_block_comment) — s'arrêter au premier -/ scannerait du code comme commentaire.
  • Double ancrage : une citation profonde meurt seulement si ni l'ancre fichier ni l'ancre racine ne la trouvent ; ../ explicite n'est pas ré-ancré (4 tests dédiés).

1 🟡 : le garde-chaîne des marqueurs ligne (count('"') % 2 == 0) ne protège pas les blocs /- -/ — un /- à l'intérieur d'une chaîne multi-ligne ouvrirait un faux bloc. Documenté comme heuristique dans la docstring, et je n'ai pas trouvé de cas réel dans ce dépôt ; à garder en tête si un faux positif apparaît.

2 🟡 (processus, pas code) : le body « Closes #24410 » alors que le câblage CI (fast-lane invoquant --check --base origin/main --code) est explicitement hors périmètre — l'issue se fermera avec un organe livré mais pas encore exécuté par un gate. Le résiduel est déclaré honnêtement et noté sur l'issue ; si la tranche suivante tarde, l'organe restera sans consommateur.

Scan sécu : néant. PR gate rouge = DWELL (minuteur 63/120 min, pas un échec de code).

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #24718 (Fix(guard,#24410): scan des citations de doc dans les commentaires de code (py/lean/cs)) touche au moins un chemin de fichier aussi modifie par d'autres PRs ouvertes. Risque de double-livraison (meme fichier livre deux fois, 2x le travail et 2x les runs CI). Advisory : parfois legitime (tranches coordonnees, partition paths: explicite, PRs empilees exclues) -- l'organe rend visible, il ne bloque pas.

Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur main. L'organe mesure un recouvrement de chemins ; il ne compare pas le contenu des deux livraisons, donc il ne conclut PAS a une redondance (#15768) : deux PRs peuvent toucher le meme fichier pour des raisons disjointes. L'arbitrage reste a la lane ou au coordinateur.

@github-actions github-actions Bot added the pr-overlap Advisory: another open PR touches the same files (organ #13615) label Nov 4, 2026

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

lane-claim-absent Closing issue carries no claim at all (#10223) pr-overlap Advisory: another open PR touches the same files (organ #13615) 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.

check_docs_links.py : les chemins de doc cites dans les commentaires de code echappent a l'organe (C#, Lean, Python)

2 participants