Un renvoi porté par la javadoc ne se perd pas¶
scripts/adr/4395-renvois-en-javadoc.pyContexte¶
L'article A30 pose que l'ADR dit pourquoi, et que la javadoc la cite au lieu de la redire. Le
renvoi #N est cette citation : il donne au lecteur d'un contrat l'accès à la discussion qui a
produit la règle. La javadoc de production cite 3 111 issues distinctes, dans 983 fichiers.
Le même article ouvre un cliquet de 3 641 lignes de prose narrative, sur 713 blocs. Les résorber demande de raccourcir ces blocs, et c'est là que les deux exigences se croisent : la citation vit dans la prose qu'on coupe.
Le défaut¶
Un renvoi perdu ne casse rien. Il ne fait pas échouer la compilation, ne rougit aucun test, et n'apparaît dans aucun diff comme autre chose qu'une ligne de prose en moins. Il cesse simplement d'ouvrir, et personne ne s'en aperçoit avant de chercher pourquoi une règle est ce qu'elle est.
La mesure d'ouverture du lot 2 chiffre le danger. La ligne d'origine a déjà résorbé sa propre dette de javadoc, et 367 fichiers porteurs de dette ici ont là-bas un code identique à l'octet près : sa javadoc contractée est donc une référence de rédaction directement applicable, pour 55 % de la dette. Mais elle ne porte aucun renvoi. Sa rupture les a tous retirés, parce qu'ils n'ouvraient plus rien dans un dépôt détaché de ses issues.
Reprendre cette javadoc en bloc effacerait 1 572 de ces renvois, qui ouvrent ici de vraies issues. C'est la perte que l'ADR 4334 a refusée au grain du commit, revenue au grain du bloc de javadoc.
Décision¶
Le nombre d'issues distinctes que cite la javadoc de chaque fichier de src/main/java, sommé
sur le dépôt, ne descend pas. Il est tenu par un plancher déclaré, que
scripts/adr/4395-renvois-en-javadoc.py vérifie à chaque passage.
Distinctes, et non occurrences : ce qui se perd est qu'un fichier cesse d'ouvrir une discussion, pas qu'il l'ouvre une fois au lieu de deux.
Le plancher vaut 3 304. Il se relève de ce qu'un chantier
ajoute, et #4441 lui a rendu quinze renvois d'un coup : le dépôt portait cinquante-trois
(#…), le caractère de suspension au lieu d'un numéro, qu'aucun motif ne voyait puisque celui de ce
garde exige des chiffres. Chacun a été retrouvé par git blame, le commit qui a introduit la ligne
nommant son issue dans cinquante-trois cas sur cinquante-trois.
3 136 → 3 160 (#4646). Le plancher annonçait « à relever » depuis on ne sait quand, et personne
ne le voyait : rapport.py n'avait aucun motif pour les lignes de plancher, et son verdict était
jeté avec celui des trois autres scripts qu'il ne savait pas lire (#4635).
Les vingt-quatre renvois gagnés ont été triés avant d'être verrouillés, le comptage sommant les issues distinctes par fichier : déplacer un bloc d'un fichier à l'autre aurait fait monter le total sans qu'aucun renvoi n'ait été ajouté.
| Nature | Fichiers | Renvois |
|---|---|---|
| fichiers neufs au corpus | 6 | +9 |
| fichiers qui montent | 11 | +15 |
| fichiers qui baissent | 0 | 0 |
| fichiers disparus | 0 | 0 |
Aucun fichier n'a baissé ni disparu : le déplacement redouté ne s'est pas produit, et les vingt-quatre sont des ajouts. Le plancher les verrouille.
3 160 → 3 193, et le plancher de test 996 → 1 009, relevés au fil des lots qui ont posé des renvois. Ces relevés-là sont restés à la main, et deux d'entre eux ont laissé la prose de l'ADR en arrière pendant que l'en-tête suivait : c'est ce que #4683 a outillé plutôt que corrigé une fois de plus.
L'abaisser est possible, et c'est une décision : la justifier dans cette ADR, comme on justifie un cliquet qui monte.
Conséquences¶
Sa polarité est l'inverse de celle des cliquets du dépôt, et le champ le dit. Un cliquet compte
ce qu'on tolère : il borne par le haut, monter est la régression, et l'article A9 demande de le
resserrer. Un plancher compte ce qu'on possède : il borne par le bas, descendre est la perte, et
la bonne nouvelle est de le relever. Les deux ne peuvent pas partager un champ sans qu'un lecteur
pressé lise le mauvais sens, d'où floor à côté de ratchet dans l'en-tête, et
rapporte_plancher à côté de rapporte dans le socle.
Trois verdicts, et deux d'entre eux refusent (#4683). perte refuse parce qu'on a perdu ;
a-relever refuse parce qu'on n'a pas encore gardé ; seul ok passe. La deuxième moitié manquait :
un plancher périmé annonçait sa péremption et rendait 0. Celui-ci l'a annoncée de #4441 à #4646
sans que personne ne la lise, et pendant tout ce temps le garde n'aurait rougi qu'en dessous de
3 136 : les vingt-quatre renvois gagnés au-dessus se reperdaient sans qu'il dise rien. Un gain n'est
gardé qu'une fois le seuil relevé.
Ce que cette annonce ignorée ne prouve pas (#4710). Elle était invisible. rapport.py n'avait
aucun motif pour les lignes de plancher, et leur verdict était jeté avec ceux qu'il ne savait pas
lire, jusqu'à ce que #4635 le corrige. Ce qui a échoué est donc un avertissement muet, et un
avertissement muet ne dit rien d'un avertissement qui parle. Garder a-relever sans conséquence,
maintenant que le rapport l'affiche à chaque passage, n'a jamais été essayé : cette option est
écartée par choix, pas par mesure, et l'écrire autrement ferait passer une préférence pour un
résultat.
Ce que ce refus coûte, et pourquoi il est accepté. Ajouter un renvoi fait désormais rougir la
CI jusqu'à ce que le plancher suive. C'est le reproche que cette ADR adresse plus haut à une valeur
figée par fichier : faire payer la discipline à chaque geste honnête. Il est accepté ici parce que le
relevé est un geste et non trois - scripts/methode/releve-les-planchers.py --ecrire lit le verdict
du garde et pose la mesure aux trois endroits où un seuil s'écrit : l'en-tête floor:, la balise du
corps, celle du journal. Sans lui, le refus se paierait trois fois, et il y a un précédent : deux
balises restées en arrière ont fait rougir DocumentationAJourTest sous #4646, parce que le chiffre
y porte une espace insécable que le remplacement littéral manquait - et que le grep de
vérification manquait pour la même raison.
Combien de fois ce prix se paie (#4710). Du 24 au 29 août 2026, le plancher a pris onze valeurs :
4 076, 3 111, 3 112, 3 127, 3 129, 3 136, 3 160, 3 165, 3 167, 3 193, 3 196. Cinq de ces relevés
viennent de commits qui ne parlent pas de renvois - deux lots d'alertes CodeQL, la lecture d'une
position collée depuis une carte, une clôture, la reprise d'un avis de qualification. Ils ont ajouté
de la javadoc qui cite des issues, et c'est tout ce qu'il faut. La friction ne tombe donc pas sur les
chantiers de javadoc, elle tombe partout. La série se rejoue en lisant floor: à chaque commit qui a
touché cette ADR.
Ce qui rouvrirait la question. Le refus tient tant que ce prix reste supportable à l'usage. S'il cesse de l'être - une PR sur deux arrêtée par un garde étranger à son sujet, le relevé exécuté sans être lu - l'avertissement visible redevient le candidat, avec l'avantage de n'avoir pas encore été jugé. Ce paragraphe existe pour que la porte reste trouvable : une décision qui garde une option ouverte doit dire laquelle, sinon elle se referme au premier lecteur pressé.
Le total est global, pas figé par fichier. Figer 983 valeurs et les tenir à chaque édition légitime ferait payer la discipline à chaque geste honnête, pour attraper une faute qui ne se commet qu'en masse. Le garde ne voit donc pas dix renvois perdus dans un fichier compensés par dix ajoutés dans un autre. Ce n'est pas la menace ; la menace est la reprise de tranche, et un plancher global la voit au premier passage.
Ce que la première application a corrigé. La version posée comptait les occurrences. Elle a
été réfutée par le premier fichier où elle pouvait l'être, dans l'heure : AttenteTuiles.java citait
#3068 deux fois dans un bloc, la version contractée le cite une fois, et le garde a rougi sur une
réécriture qui ne perdait rien. Mesuré sur les deux états : 4 076 occurrences contre 4 075, et
3 111 renvois distincts dans les deux cas. Le plancher est passé de 4 076 à 3 111 sans qu'aucun
renvoi ne disparaisse - les deux nombres ne mesurent pas la même chose, et il faut le dire pour qu'on
ne lise pas cette baisse comme une perte. C'est #4398, et c'est
2941 à la lettre : sa première application est ce qui
révèle sa définition.
Seules les lignes /// comptent. Déplacer un renvoi d'un /// vers un commentaire
d'implémentation sera compté comme une perte, alors que ce n'est qu'un choix de rédaction. La
contrepartie est assumée : elle pousse à garder la citation là où le lecteur du contrat la trouve,
et c'est exactement ce que A30 demande.
src/test/java est hors champ, comme pour le cliquet du même article. La javadoc de test n'a pas
encore de décision, et lui en donner une par ricochet serait légiférer sans avoir mesuré.
Le niveau est certaine et non probable : compter des renvois n'appelle aucun tri humain. Un
renvoi est là ou il n'y est pas.
Alternatives écartées¶
- Figer une valeur par fichier, 983 en tout. Plus fin, et plus fragile : la table périmerait à chaque édition légitime, et une table qu'on met à jour sans la lire ne garde plus rien.
- Comparer au commit de base plutôt qu'à un plancher. Cela verrait la perte au fichier près, mais ferait dépendre le garde d'une référence git que le poste local n'a pas toujours. Un garde qui ne se lance pas en local n'est lancé qu'en CI, c'est-à-dire trop tard pour celui qui coupe.
- Ne rien garder et relire. C'est ce qui a produit le défaut que cette décision prévient : la relecture voit une prose plus courte, elle ne voit pas un renvoi absent.
La jurisprudence¶
4334 refuse la perte des renvois au grain du commit, et chiffre ce qu'elle coûterait : 1 589 renvois. Celle-ci applique le même refus à la prose.
2867 et 2941 posent le cliquet et disent que sa valeur d'ouverture se mesure. Le plancher leur emprunte la mécanique et lui rend le sens inverse.