Que fait org-lint ?
Linter pour les règles de formatage de prose des fichiers org/md, documentées dans ~/.claude/rules/org-babel.md. Le but est de ne pas se reposer à chaque fois sur la mémoire manuelle de chaque règle individuelle (d'où le risque : corriger celle qu'on vient de citer et en oublier les autres), mais de passer le texte dans une liste explicite.
Quand l'appliquer
- Immédiatement après avoir modifié ou écrit un nouveau paragraphe de prose dans un fichier
.org/.md(au lieu de vérifier manuellement chaque règle de mémoire) — avant de montrer le résultat à l'utilisateur. - Sur demande explicite de l'utilisateur ("vérifie les règles org", "lance le lint", comparaison avec
clippy, etc.). - Ne s'applique pas au contenu des blocs
#+begin_src/#+begin_example(code) — uniquement aux paragraphes de prose et titres.
Étape 1 — Vérification mécanique
Lance le script sur le(s) fichier(s) modifié(s) :
python3 ~/.claude/skills/org-lint/scripts/lint.py CHEMIN/VERS/FICHIER.org
Le script détecte par regex :
/sans espaces autour de~...~/=...=(~a~/~b~au lieu de~a~ / ~b~) — INFRACTION CERTAINE.[[file:../— lien relatif au répertoire courant au lieu de l'abréviationroot:— INFRACTION CERTAINE.- absence de newline final dans le fichier — INFRACTION CERTAINE.
- acronyme en capitales à l'intérieur de
=...=(ex.=CSS=) — nécessite confirmation (rares exceptions autorisées). - italique
/Mot/— nécessite vérification : s'agit-il vraiment d'un terme du glossaire du projet (y a-t-il une section dansspcfctn/glossary.org? un lien vers celui-ci à la première mention dans ce fichier ?), ou s'agit-il par erreur d'un lien non converti vers une section/fichier (aurait dû être[[*Section][...]]). - mention de fichier comme
=chemin/fichier.org=— nécessite vérification : n'aurait-il pas dû s'agir d'un véritable lien[[file:...]]. - mot "paramètre"/"paramètres"/... — nécessite vérification : s'il s'agit des propriétés d'un composant Rust/Yew (
struct ...Props), la traduction correcte est "propriétés"/"propriété", pas "paramètres"/"paramètre" (terme obsolète). En dehors des composants Yew (paramètres de fonction, CLI, procédure REST, etc.), "paramètre" est OK, ne pas toucher. - le bloc
:noweb-ref Définitionse trouve dans une section avant le bloc:noweb-ref Déclarations— nécessite vérification : la déclaration doit venir en premier, dans l'ordre de lecture du fichier de haut en bas (voir org-babel.md). - plusieurs blocs
#+begin_srcavec le MÊME:tangle CHEMINet sans aucun:noweb yes/<<...>>dans le fichier — INFRACTION CERTAINE (concaténation obsolète, comme dans l'anciengitignore.org— voir org-babel.md). À refaire en un bloc conteneur:tangle+:noweb yesavec un/des placeholder(s)<<Nom>>et des sections avec:noweb-ref Nom. - le fichier se tangle dans PLUSIEURS fichiers cibles différents, dont AU MOINS DEUX consomment eux-mêmes noweb (ont
:noweb yessur un#+begin_srcsquelette, ex.config.org→.env.example+parameters.php), mais au moins un bloc:noweb-ref/<<...>>est nommé sans préfixe de cible (Nomau lieu deenv:Nom) — INFRACTION CERTAINE (voir org-babel.md, règle sur les préfixes dans les fichiers org multi-cibles). Pour les fichiers avec UN SEUL fichier cible, ainsi que pour les fichiers où UNE SEULE cible consomme noweb et les autres sont des cibles:tangleautonomes en un seul bloc sans<<...>>(ex.gitignore.org: 5 cibles:tangle, mais seul le.gitignoreracine utilise un squelette noweb) — le préfixe n'est pas nécessaire, car aucune ambiguïté réelle n'existe. - les paramètres dans l'en-tête
#+begin_srcsont dans un ordre incorrect — INFRACTION CERTAINE. Ordre correct : type de bloc →:noweb yes→:noweb-sep "..."→ autres paramètres →:tangle CHEMINou:noweb-ref Nom(tout à la fin, voir org-babel.md). - le fichier s'appelle
cargo.org— INFRACTION CERTAINE (nom obsolète pour les projets Rust ; renommer enconfig.org, voir org-babel.md). :tangleutilise un chemin absolu (/...,~/...) ou ascendant..— INFRACTION CERTAINE (voir org-babel.md) ; la cible doit être un chemin relatif strictement descendant depuis le fichier org. Si la cible est vraiment en dehors de l'arborescence source, il faut un lien symbolique ou une autre structure de répertoires, pas../chemin absolu (épisode :farba-override→farba-themevia../farba-theme/..., tâcheFS-1085).- capitales en dehors de
=...=(ex.NON,SEULEMENT) — nécessite vérification : s'il s'agit d'une emphase de mot et non d'un acronyme/abréviation, remplacer par du gras Org (*non*), pas de capitales. - mot "hook" — obsolète ; la traduction correcte est "accroche" (concerne uniquement la prose, pas les identifiants de code comme
use_effect_with). - lignes de prose de plus de 105 caractères — nécessite
fill-paragraphviaemacsclient(voir ci-dessous).
Les trouvailles "CERTAINES" doivent toujours être corrigées. "Nécessite vérification manuelle" — examine chacune, mais elles ne sont pas toutes des erreurs (ex. =rest=/=forge-yew= sont une abréviation/nom de crate légitimes, pas une infraction).
Étape 2 — Checklist manuel (ce que le script ne détecte pas)
- Identifiants/types/fonctions/variables/modules de code — et tout fragment ou expression de code (ex.
id=1,value == 0,items()) — tilde~...~. Abréviations/acronymes et nom "public" du crate/bibliothèque (avec trait d'union) — signe égal=...=. Chemin qualifiécrate::Typeest un nom de type issu du code, donc entièrement dans le tilde, même avec le préfixe du crate. - Abréviations/acronymes — en minuscules à l'intérieur d'une phrase, seule la première lettre en majuscule en début de phrase (pas de capitales complètes), sauf rares exceptions établies.
- Lien vers une section dans le même fichier —
[[*Nom du titre][Nom]], pas d'italique ni de texte simple. Lien vers un fichier dans le même répertoire — simplement[[file:fichier-voisin.org][description]]; vers un fichier dans un autre répertoire (surtout un autre dépôt git dans le répertoire de travail commun) — via l'abréviationroot:([[root:code/ads-back/fichier.org::N][description]]), pas../../../relatif au répertoire courant. L'abréviation est déclarée dans.dir-locals.elà la racine du répertoire de travail (formeevalaveclocate-dominating-file) — si elle n'existe pas encore dans le projet, crée-la. - Italique
/.../— uniquement pour les termes du glossaire du projet (avec traduction(/translation/)immédiatement après) ; à la première mention du terme dans chaque fichier —[[file:.../spcfctn/glossary.org::*Terme][...]]vers la section correspondante, pas de répétition de définition.
Étape 3 — Alignement
Pour chaque paragraphe modifié, appelle le véritable fill-paragraph via emacsclient --eval, ne l'aligne pas manuellement (voir la règle correspondante dans org-babel.md). Écris le texte du paragraphe dans new_string / lors de la création du fichier sur une seule ligne, sans essayer de deviner toi-même les coupures — cela détermine de toute façon entièrement fill-paragraph.
Appelle impérativement (font-lock-ensure) AVANT org-fill-paragraph : un buffer ouvert en mode headless via find-file-noselect ne subit pas la fontification, donc les liens Org [[chemin][description]] ne sont pas encore "pliés" en texte visible court description — sans font-lock-ensure, fill-paragraph calculera la coupure sur le texte cru long du lien, pas sur sa largeur visible, et le résultat divergera de ce que donne M-q dans un Emacs interactif. Exemple :
emacsclient --eval '
(let ((buf (find-file-noselect "CHEMIN/VERS/FICHIER.org")))
(with-current-buffer buf
(org-mode)
(font-lock-ensure)
(goto-char (point-min))
(search-forward "fragment unique du paragraphe")
(org-fill-paragraph)
(save-buffer)))
'