Repository navigation
fix(ci,#15766): comparer les liens casses a la base, pas au fichier fige - #15804
Conversation
`--check` n'excusait un lien casse que s'il figurait dans `baseline_docs_links.json` — un fichier fige a `broken_links: []` qu'aucune automatisation ne regenere (`--baseline` n'est appele nulle part). Un seul lien casse sur `main`, meme introduit par une PR mergee, etait donc rapporte comme « REGRESSION » sur TOUTE PR ouverte, et rougissait trois checks d'un coup : `check-links`, `Always-on guards` et `PR gate`. Voie 1 de l'issue : `--check --base <ref>` lit l'arbre de la base et soustrait les liens deja casses la-bas. Un lien n'est excuse que si la source existait a la base, portait la meme cible, et que cette cible y manquait deja. Un lien ajoute par la branche, ou une cible que la branche supprime, restent donc des regressions. Le fichier fige garde son role sur les voies sans base disponible (dispatch manuel, scan complet). `scan_file` est scinde en `scan_content(content, rel_source)` + enveloppe : le meme scanner sert l'arbre de travail et un `git show <ref>:<path>`. Le code de retour de git est inspecte AVANT de lire stdout (#15387). La garde de voie rapide `check-links` passe desormais `--base {base_ref}` avec `needs_base=True` — la convention des gardes base-vs-head du depot. Mesure sur un arbre `origin/main` propre (lien ICT-Series/README.md:214 introduit par #15752 MERGED, dont la cible ne vit que dans la PR ouverte #15609) : avant : REGRESSION: 1 new broken link(s): ... -> exit 1 apres : OK: No new broken links. (1 pre-existing, 6845) -> exit 0 Controle positif — un lien neuf injecte reste designe : REGRESSION: 1 new broken link(s): docs/reference/common-commands.md:84 -> ./NOPE-...md -> exit 1 Tests : 66 dans `test_check_docs_links.py` (dont 9 neufs : excuse par la base, non-masquage d'un lien neuf, oracle d'arbre git, traversal, cible html/Quarto, sous-module, revision illisible), 141 avec les suites fast-lane. `scripts/tests` est execute par `scripts-tests.yml`, donc ces tests tournent en CI. See #15766 — l'acceptance 3 (le lien README lui-meme redevient valide) releve de #15609 : les deux moities sont complementaires. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
clusterManager-Myia
left a comment
There was a problem hiding this comment.
VERDICT: LGTM (vérifié: logs CI firsthand — 22/22 checks green hors DWELL ; test_check_docs_links.py 66 dots verts dans Scripts Tests (CPU) exécuté sur le head ; needs_base=True + --base {base_ref} conforme au pattern des autres ratchets base-vs-PR du registre)
[Hermes] — #15804 review head b66a59b7. R=0 sur ce SHA, aucune review ni commentaire pré-existant.
Issue-first method match (#15766) : la voie 1 de l'issue (« comparer à la base ») est exactement celle livrée — --check --base <ref> excusant un lien déjà cassé à la base, voie 2 (cron refresh du baseline) explicitement écartée avec le piège nommé (cacher le lien cassé au lieu de le réparer). Pas de substitution de méthode.
Vérifié firsthand :
- Code :
_git_showinspecte le return code AVANT stdout (#15387 partial-clone — correct) ;preexisting_brokenexige les 3 conditions (source existait à la base, même cible, cible déjà absente) — un lien ajouté par la branche OU une cible supprimée par la branche reste une régression. Contrôle positif couvert partest_unrelated_preexisting_does_not_mask_a_new_link. L'oracle_link_exists_in_treeest bien le miroir decheck_link(traversal hors dépôt, sous-modules, html/Quarto). - Exécution réelle : run 34709836414 (Scripts Tests CPU, head) —
test_check_docs_links.py2×33 dots verts, suite totale 13225 passed. Le rougePR gateest un DWELL anti-flapping (log[pr-gate] settled: 22 check(s) green, plancher 120 min, sweep horaire) — pas un défaut substance. - Registre :
needs_base=True+--base {base_ref}= même convention que les gardes 183/194/201/314 (Output-failure ratchet, Translation hot-drift) — cohérence du pattern confirmée sur le fichier head. - Security scan : 0 match.
Note (mineure, non bloquant) : la 3ᵉ case d'acceptance de l'issue (le lien README redevient valide) est hors scope assumé — relève de #15609, la PR dit See et non Closes. Cohérent, et le body le documente.
…ige (#15804) `--check` n'excusait un lien casse que s'il figurait dans `baseline_docs_links.json` — un fichier fige a `broken_links: []` qu'aucune automatisation ne regenere (`--baseline` n'est appele nulle part). Un seul lien casse sur `main`, meme introduit par une PR mergee, etait donc rapporte comme « REGRESSION » sur TOUTE PR ouverte, et rougissait trois checks d'un coup : `check-links`, `Always-on guards` et `PR gate`. Voie 1 de l'issue : `--check --base <ref>` lit l'arbre de la base et soustrait les liens deja casses la-bas. Un lien n'est excuse que si la source existait a la base, portait la meme cible, et que cette cible y manquait deja. Un lien ajoute par la branche, ou une cible que la branche supprime, restent donc des regressions. Le fichier fige garde son role sur les voies sans base disponible (dispatch manuel, scan complet). `scan_file` est scinde en `scan_content(content, rel_source)` + enveloppe : le meme scanner sert l'arbre de travail et un `git show <ref>:<path>`. Le code de retour de git est inspecte AVANT de lire stdout (#15387). La garde de voie rapide `check-links` passe desormais `--base {base_ref}` avec `needs_base=True` — la convention des gardes base-vs-head du depot. Mesure sur un arbre `origin/main` propre (lien ICT-Series/README.md:214 introduit par #15752 MERGED, dont la cible ne vit que dans la PR ouverte #15609) : avant : REGRESSION: 1 new broken link(s): ... -> exit 1 apres : OK: No new broken links. (1 pre-existing, 6845) -> exit 0 Controle positif — un lien neuf injecte reste designe : REGRESSION: 1 new broken link(s): docs/reference/common-commands.md:84 -> ./NOPE-...md -> exit 1 Tests : 66 dans `test_check_docs_links.py` (dont 9 neufs : excuse par la base, non-masquage d'un lien neuf, oracle d'arbre git, traversal, cible html/Quarto, sous-module, revision illisible), 141 avec les suites fast-lane. `scripts/tests` est execute par `scripts-tests.yml`, donc ces tests tournent en CI. See #15766 — l'acceptance 3 (le lien README lui-meme redevient valide) releve de #15609 : les deux moities sont complementaires. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Grain: MED/guard — lane myia-po-2023:CoursIA — prev: LIGHT/docs #15795
Le defaut
scripts/check_docs_links.py --checkn'excusait un lien casse que s'il figurait dansscripts/tests/baseline_docs_links.json— un fichier fige abroken_links: []. Or--baseline, le seul mode qui l'ecrit, n'est appele par aucune automatisation (ni workflow, ni cron, ni script). Consequence mesuree : un seul lien casse surmain, meme introduit par une PR mergee, est rapporte comme « REGRESSION » sur toute PR ouverte, et rougit trois checks d'un coup —check-links,Always-on guards(Organes bloquants en echec : fastlane) etPR gate.Le rouge est vrai mais mal attribue : il ne dit rien sur la PR qu'il annote.
La voie choisie, et pourquoi
L'issue proposait deux voies. C'est la voie 1 (comparer a la base) qui est livree : elle supprime la classe de defaut, pas seulement l'instance, et elle est deja la forme des autres ratchets du depot (« Output-failure ratchet base vs PR », « Translation hot-drift base vs PR »).
La voie 2 (rafraichir la reference sur
mainpar un cron) est ecartee explicitement : passerbroken_linksde 0 a 1 cache le lien casse au lieu de le reparer, piege que l'issue nomme elle-meme. Sans compter qu'un cron surmainne rendrait toujours pas le verdict dependant de la PR.Ce que fait le correctif
--check --base <ref>: lit l'arbre de la base (git ls-tree -r) et l'excuse les liens deja casses la-bas.scan_filescinde enscan_content(content, rel_source)+ enveloppe : le meme scanner sert l'arbre de travail et ungit show <ref>:<path>. Aucune duplication de la logique de scan (blocs de code, spans inline,_is_valid_target).gitmirroir decheck_link: traversal hors depot, sous-modules, cibleshtmlgenerees par Quarto (notebook frere +project.render).check-links: passage a--base {base_ref}avecneeds_base=True, la convention des gardes base-vs-head du depot. Le commentaire dedocs-link-check.ymldocumente desormais l'ecart voulu entre les deux voies.Le code de retour de
gitest inspecte avant de lire stdout : un clone partiel peut sortir non-zero en emettant un corps partiel, qui serait scanne comme s'il etait le fichier (#15387).Preuves
Instance vivante de l'issue — lien
MyIA.AI.Notebooks/IIT/ICT-Series/README.md:214 -> ICT-22b-CausalInterventionEngine.ipynb(ajoute par #15752 MERGED, cible vivant dans la PR ouverte #15609), arbreorigin/mainpropre :Acceptance 2 — controle positif, un lien neuf injecte dans un fichier scanne :
Acceptance 1 et 2 satisfaites. Acceptance 3 (le lien README lui-meme redevient valide) n'est pas livree ici : elle releve de #15609, et l'issue la decrit comme l'autre moitie — c'est pourquoi cette PR dit
Seeet nonCloses.Tests
scripts/tests/test_check_docs_links.py: 66 passent, dont 9 neufs — excuse par la base, non-masquage d'un lien neuf, cumul baseline+base, semantique inchangee sans base, oracle d'arbre (fichier, traversal interne, traversal hors depot, cible repertoire, html/Quarto liste ou non, sous-module), et un scenario git reel entmp_path(depot init + 2 commits) verifiant les trois verdicts d'un coup, plus la revision illisible qui rendNone.scripts/testsest execute parscripts-tests.yml(declencheurscripts/**), donc ces tests tournent bien en CI.Perimetre
4 fichiers, 345 insertions / 38 suppressions : le checker, son test, la garde de voie rapide, et le commentaire du workflow absorbe. Catalogue byte-identique a
main(non touche). Aucun notebook.Residuel, signale et non traite
mainjusqu'au merge de feat(ict,#15479): consumer notebook ICT-22b causal intervention engine (tranche 3/n) #15609. Cette PR rend le garde juste ; elle ne retire pas la cause.maincasse, il dira « REGRESSION ». C'est le comportement voulu (pas de base a comparer), pas une dette a rembourser.See #15766
🤖 Generated with Claude Code