name: vérification-citations description: Vérifie chaque citation et citation textuelle d'un brouillon d'article par rapport aux sources réelles — jurisprudence via CourtListener + recueils officiels, doctrine via la bibliothèque Zotero de l'utilisateur puis le web ouvert — et renvoie un rapport gradué, note par note, avec une section « nécessite votre attention » en premier, ainsi qu'une section de forme des citations (citations courtes selon Bluebook R. 10.9/4.2 et italiques/petites capitales selon R. 2.1(a)) déterminée à partir du seul brouillon. Déclenchement lorsque l'utilisateur souhaite une vérification des citations d'un brouillon (« vérifie les citations de ce brouillon », « vérifie les citations/citations textuelles dans ce brouillon », « fais un cite-check sur »). Entrée : un .docx avec de vraies notes de bas de page Word (repli markdown/texte brut). N'est pas un vérificateur Bluebook complet — l'ordre des signaux, l'ordre des citations et la composition des citations restent exclus.
Vérification des citations
Une passe de vérification sur un brouillon d'article terminé ou en cours. Chaque autorité est vérifiée pour son existence ; chaque citation textuelle est vérifiée mot pour mot par rapport à la source réelle ; chaque URL est confirmée comme résolvable ; les renvois à des pages sont vérifiés pour leur cohérence lorsque la pagination de la source est récupérable. Des scripts déterministes effectuent l'extraction et la résolution des références croisées pour un coût en jetons quasi nul ; des agents de modèle effectuent la vérification des citations textuelles/renvois dans un éventail de sources uniques, avec une seconde vérification obligatoire sur chaque constatation de gravité élevée afin qu'un artefact de vérification n'atteigne jamais le rapport.
Elle réutilise les mécanismes de la compétence recherche-juridique (check_cite.py, fetch_page.py, le jeton CourtListener, l'échelle de dégradation budgétaire) et ses règles de conduite (web ouvert uniquement, ne jamais vérifier de mémoire, une source non récupérable est signalée comme non vérifiée — jamais supposée).
Ce qu'elle vérifie : que chaque citation renvoie à la source revendiquée, que les rubriques/auteurs/titres sont correctement orthographiés, que le recueil/volume/première page/cour/année sont corrects, que les citations textuelles sont textuelles ou honnêtement marquées, que les références croisées supra/id. sont intactes, et que les URL sont actives.
Registre de couverture (ajouté le 2026-09-06) — et ce qui n'est TOUJOURS PAS vérifié. Les unités de vérification des citations sont construites à partir de citations textuelles ; seules, elles ont laissé chaque source secondaire non citée sans compte. Désormais, scripts/citation_ledger.py inventorie chaque instance de citation dans chaque note de bas de page (jurisprudence ou source secondaire, citée ou non, avec les chaînes Id./supra/forme courte résolues), une passe d'existence des sources secondaires couvre les articles/lois/URL non cités, et la section H du rapport donne à chaque instance une disposition — vérifiée, problème, existence-uniquement, invérifiable, non-vérifié, réf-croisée, réf-croisée-non-résolue — et liste les instances non vérifiées par note de bas de page. Deux limites subsistent et le rapport doit le mentionner : (1) le soutien à une proposition — si une citation non textuelle étaye réellement la phrase à laquelle elle se rattache — n'est jamais évalué (c'est ce que signifie existence-uniquement) ; (2) les renvois à des pages ne sont vérifiés que lorsqu'une citation textuelle les ancre. Traitez existence-uniquement comme « source réelle, non lue », jamais comme « approuvée ».
Plus les problèmes de FORME évidents (verrouillage de périmètre levé par l'utilisateur, 2026-08-10 — « annulez le verrouillage dans la mesure où il vous empêche de vérifier les choses évidentes »). Une phase Forme signale ce qui est décidable à partir du seul brouillon, sans consulter de source :
- Formes courtes — une citation complète répétée dans la fenêtre de cinq notes de bas de page du Bluebook R. 10.9 où la forme courte devrait être ; une forme courte de jurisprudence échouée au-delà de cette fenêtre ou sans aucune citation complète avant elle nulle part ; une source secondaire citée deux fois in extenso alors que R. 4.2 exige
Auteur, supra note N. - Typographie (
.docxseulement) — signaux /Id./supra/quotinglaissés en romain, lenote Naprès unsupraen italique incorrectement en italique, les italiques débordant sur la virgule avant une citation, les petites capitales cassées en milieu de mot, et l'italique des noms d'affaires selon R. 2.1(a) (romain dans une citation complète se trouvant dans une proposition de citation, italique dans une phrase textuelle ou une forme courte — le seul appel qui nécessite un agent, car un modèle ne peut pas les distinguer).
Ces vérifications s'exécutent via ${CLAUDE_PLUGIN_ROOT}/skills/legal-research/citeform.py, le même module qu'utilise /proofread, de sorte que les deux compétences ne peuvent pas donner d'avis contradictoires. Les règles appliquées sont explicitées dans ${CLAUDE_PLUGIN_ROOT}/skills/legal-research/bluebook-typeface-and-short-forms.md. Les constatations de forme obtiennent leur propre section de rapport vers la fin et n'entrent jamais dans « Nécessite votre attention » — il s'agit de rangement, pas de fond.
Ce qu'elle n'est TOUJOURS PAS : un vérificateur Bluebook complet (l'ordre des signaux, l'ordre des citations et la question de savoir si une citation est correctement composée restent exclus), un éditeur de fond, ou un substitut à la vérification de la revue. La division avec /proofread reste inchangée pour tout le reste : proofread lit la prose, cite-check vérifie les autorités — ils partagent désormais la couche de forme des citations.
Comment exécuter
1. Analyser la demande
- draftPath — chemin vers le brouillon (obligatoire).
.docxavec de vraies notes de bas de page Word est canonique ;.md/.txtavec des notes de bas de page de style[^n]pandoc fonctionne comme repli. - footnotes — passe partielle facultative, par exemple « notes de bas de page 45–80 » ou une liste. Par défaut : brouillon entier.
- deep — facultatif ; vérification plus lourde (agents de vérification à effort moyen, plafond souple plus élevé). Activez pour un brouillon quasi final ou lorsque l'utilisateur dit « profond »/« approfondi ».
- Si le brouillon comporte des modifications suivies, dites-le et demandez s'il faut toutes les accepter avant la vérification (l'analyseur lit le texte actuel/accepté et ignore les suppressions suivies, mais un brouillon fortement marqué mérite un avertissement).
1b. Demander le niveau de profondeur (décision de l'auteur, 2026-08-09 — reflète /proofread étape 1b)
À moins que la demande ne le précise déjà, DEMANDEZ en amont — un AskUserQuestion, en-tête Profondeur, avant le pré-vol. Intégrez l'avertissement concernant les modifications suivies (étape 1) dans le même appel lorsque cela s'applique, afin que l'utilisateur réponde à tout en une seule interaction plutôt que d'être interrompu deux fois.
Ignorez la demande lorsque le libellé choisit déjà un niveau (« profond », « approfondi », « quasi final », « pré-soumission », « rapide », « standard »), lors d'une nouvelle exécution partielle d'un niveau déjà choisi dans cette session, ou lorsque l'utilisateur n'a demandé qu'une plage étroite de notes de bas de page.
Deux options — cite-check n'a pas d'escalade fable, donc l'échelle est plus courte que celle de proofread :
| Option | Arguments | Ce qu'il faut dire |
|---|---|---|
| Standard | deep:false | Agents de vérification à effort faible, plafond souple 650k. Bon pour un brouillon de travail. |
| Profond | deep:true | Agents de vérification à effort moyen, plafond souple 900k. Lecture plus attentive de chaque citation textuelle par rapport à sa source — pour un brouillon quasi final. |
Ne réutilisez PAS la justification de /proofread ici — les deux deep sont des mécanismes différents. Le deep de proofread ajoute une deuxième passe d'extraction de décalage (un jeu de rappel, soutenu par la découverte de chevauchement d'environ 75-80 % du même modèle). Le deep de cite-check n'ajoute pas de passe et ne récupère rien : il augmente l'effort des agents de vérification de low à medium (ligne 557 du workflow) et relève le plafond souple. Il achète du soin par citation textuelle, pas plus de citations textuelles. La couverture des citations textuelles est identique dans les deux cas — chaque citation textuelle est vérifiée dans les deux niveaux — alors n'insinuez pas que le Standard saute quelque chose.
Le timing est moins important ici que dans proofread (deep ne change pas l'extraction, donc une nouvelle exécution ultérieure peut rejouer le segment/l'existence à partir du cache via resumeFromRunId), mais la vérification représente la majeure partie de l'exécution — 26 des 33 agents sur le brouillon National Muffler — donc un changement de niveau signifie toujours une réexécution de l'étape coûteuse. Demandez d'abord.
2. Pré-vol (à faire AVANT le lancement — une invite d'autorisation en cours d'exécution peut tuer un agent)
- Lire
~/.claude/settings.json; assurez-vous quepermissions.allowcontient"WebFetch"et"WebSearch"(fusionnez ce qui manque — ne remplacez jamais le tableau). Configuration de routine ; ne demandez pas. - Confirmer que le jeton CourtListener fonctionne. Testez-le, n'allez pas chercher un fichier — exécutez
python3 ${CLAUDE_PLUGIN_ROOT}/skills/legal-research/check_cite.py "347 U.S. 483"; un code de sortie 0 avec"found": truesignifie qu'il fonctionne et qu'il n'y a rien à signaler.check_cite.pyrésout le jeton à partir deCOURTLISTENER_API_TOKEN, puisCOURTLISTENER_TOKEN, puis le fichier~/.config/courtlistener/token— dans cet ordre, et la voie de la variable d'environnement (généralement définie dans le blocenvde~/.claude/settings.json) est l'installation normale, donc un répertoire~/.config/courtlistener/manquant ne prouve rien. Si la sonde échoue réellement, l'exécution fonctionne quand même (l'existence de l'affaire revient au web), mais mentionnez-le une fois au moment de la livraison. Page du jeton : https://www.courtlistener.com/profile/api-token/ - Résoudre la bibliothèque Zotero du projet (les projets diffèrent — certains sont des bibliothèques de groupe co-écrites, d'autres un travail de bibliothèque personnelle solo) :
a. Cherchez une ligne
Zotero library:dansCLAUDE.mddu dossier du projet (ouAGENTS.md). Si présente, utilisez le serveur MCP qu'elle nomme et passez à (c). b. Si absente, DEMANDEZ à l'utilisateur quelle bibliothèque Zotero ce projet utilise (bibliothèque personnelle, ou une bibliothèque de groupe nommée), puis enregistrez la réponse sous la forme d'une ligneZotero library: <nom> → MCP server <serveur>dansCLAUDE.mddu dossier du projet afin que les exécutions futures ne la redemandent pas. c. Confirmez que ce serveur MCP existe réellement (personnel =zotero; les bibliothèques de groupe ont leur propre serveur, par exemplezotero-grouppour « 5A general law », ID de groupe dans~/.claude.json). Si la bibliothèque du projet n'a PAS encore de serveur, c'est MAINTENANT qu'il faut proposer d'en ajouter un : dupliquez l'entréezoterodans~/.claude.jsonsouszotero-<slug>avecZOTERO_LIBRARY_TYPE=groupet leZOTERO_LIBRARY_IDdu groupe (trouvez-le via l'URL du groupe zotero.org ou les codes de champ du brouillon) ; notez que cela nécessite un redémarrage de Claude Code, donc les agents reviennent au web pour cette exécution. d. Passez le nom du serveur commezoteroServer(etzotero:falsesi aucun serveur utilisable pour cette exécution).
2b. Instantané du brouillon (toujours)
Un fichier OneDrive/Word co-écrit en direct peut changer entre l'extraction et la livraison, ce qui ferait décrire le rapport des octets qui n'ont jamais été vérifiés. Copiez le brouillon une fois, protégez la copie en écriture, hachez-la, et exécutez tout ce qui suit en aval à partir de l'instantané. Le chemin d'origine est utilisé ici et nulle part ailleurs — jamais dans les arguments du workflow ou une invite d'agent.
cp "<draftPath>" "<scratch>/snapshot.docx" && chmod a-w "<scratch>/snapshot.docx"
shasum -a 256 "<scratch>/snapshot.docx" # enregistrez ceci ; il va dans le pied de page du rapport
3. Extraire et préparer (scripts déterministes — exécutez-les vous-même, coût en jetons quasi nul)
Placez le JSON intermédiaire à un endroit où les agents du workflow peuvent le lire (le bloc-notes de session convient). Utilisez les chemins de script installés pour que cela fonctionne depuis n'importe quel dossier (draftName reste le nom de fichier d'origine, pas « snapshot ») :
python3 ${CLAUDE_PLUGIN_ROOT}/skills/cite-check/scripts/extract_cites.py "<scratch>/snapshot.docx" "<scratch>/extract.json"
python3 ${CLAUDE_PLUGIN_ROOT}/skills/cite-check/scripts/prepare_units.py "<scratch>/extract.json" "<scratch>/units.json"
python3 ${CLAUDE_PLUGIN_ROOT}/skills/cite-check/scripts/citation_ledger.py "<scratch>/extract.json" "<scratch>/ledger.json"
python3 ${CLAUDE_PLUGIN_ROOT}/skills/cite-check/scripts/citation_ledger.py "<scratch>/extract.json" --compact > "<scratch>/ledger_args.json"
citation_ledger.py affiche instance_count / by_kind / unique_secondary_cites / unresolved_xrefs. Jetez un œil à by_kind : un nombre important de other ou text signifie que les notes de bas de page utilisent une forme de citation que le séparateur ne reconnaît pas — ces instances voyagent toujours dans le registre (comme unchecked / not-a-citation), donc le rapport reste honnête, mais dites-le au moment de la livraison. Le fichier --compact contient les deux tableaux que le workflow prend (instances, secondary).
extract_cites.py affiche un résumé (footnote_count, body/footnote quote counts, unique_case_cite_count, supra_problem_candidates, plus form_findings / form_short_form / form_typeface / formatting_available / case_name_candidates de la couche de forme). prepare_units.py affiche unit_count / case_cites / supra_problems. Lisez extract.json pour extraire les tableaux dont le workflow a besoin : unique_case_cites, supra_problem_candidates, et tout le bloc form_checks.
formatting_available: false signifie un brouillon markdown/texte brut — les formes courtes s'exécutent toujours, la typographie non ; dites-le au moment de la livraison. Si formatting_unaligned_footnotes apparaît, c'est le nombre de notes de bas de page qui n'ont pas eu d'analyse typographique (leur texte formaté ne correspondait pas au texte de l'analyseur validé, donc la couche a refusé plutôt que de risquer des décalages mal alignés) — mentionnez-le uniquement si le nombre est non négligeable. Pour une passe partielle, résolvez la plage de notes de bas de page en identifiants d'unité :
python3 ${CLAUDE_PLUGIN_ROOT}/skills/cite-check/scripts/prepare_units.py "<scratch>/extract.json" --footnotes 45-80
(affiche unit_ids — passez-les comme unitIds).
4. Lancer le workflow
Workflow({
scriptPath: "${CLAUDE_PLUGIN_ROOT}/skills/cite-check/cite-check.workflow.js",
args: {
skillsDir: "${CLAUDE_PLUGIN_ROOT}/skills", // là où résident les scripts d'aide groupés
extractPath: "<scratch>/extract.json", // les agents lisent les unités + le contexte complet depuis ici
draftName: "<nom du brouillon sans extension>",
footnoteCount: <extract.footnote_count>,
unitCount: <prepare.unit_count>,
caseCites: <extract.unique_case_cites>, // tableau
supraProblems: <extract.supra_problem_candidates>, // tableau
formChecks: <extract.form_checks>, // typographie + formes courtes (bloc entier)
ledger: <ledger_args.instances>, // chaque instance de citation (forme compacte)
secondaryCites:<ledger_args.secondary>, // sources secondaires uniques non citées
unitIds: <null | [ids de --footnotes]>, // passe partielle uniquement
deep: false,
zotero: true, // false si aucun serveur Zotero utilisable pour cette exécution
zoteroServer: "<du pré-vol 2.3>" // par ex. "zotero-group" (5A) ou "zotero" (personnel)
}
})
Pipeline (toutes les étapes de modèle Sonnet sauf le rapport, qui hérite du modèle de session) :
- Segmentation/résolution — en morceaux ; chaque citation textuelle est associée à la source SPÉCIFIQUE dont elle dépend, en parcourant les chaînes
Id.jusqu'à leur véritable antécédent (qui peut être une affaire deux notes plus haut) et en suivant les redirectionssupra note N, en utilisant