wiki-lint

Kit de diagnostic et de réparation pour un wiki scientifique au format Markdown (compatible Obsidian) : 33 vérifications de santé sur les liens, la provenance, le frontmatter, les tableaux, l'encodage, les blocs de synthèse et les sceaux.

Qu'est-ce que wiki-lint ?

wiki-lint est un kit complet de diagnostic et de réparation conçu pour les wikis scientifiques au format Markdown, compatible avec Obsidian. Il effectue 33 vérifications de santé couvrant les liens cassés, les métadonnées (frontmatter), les tableaux, l'encodage, les blocs de synthèse et les sceaux de vérification. Le kit fonctionne exclusivement avec la bibliothèque standard Python, ce qui garantit une portabilité sur Windows, macOS et Linux. Sa logique est entièrement pilotée par la configuration (fichier `wiki.config.json`), ce qui permet d'ajouter de nouveaux champs, dossiers ou vérifications sans modifier le code. Il propose également trois outils de réparation : la proposition d'index, la correction des rétroliens et la promotion de brouillons. La vitesse d'exécution est optimisée pour rester rapide même avec plus de 3 000 notes.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/MinorBaek/science-wiki-kit/tree/HEAD/skills/wiki-lint

Installed? Explore more Recherche et analyse de données skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Que fait wiki-lint ?

Avant la première exécution, lisez docs/GOTCHAS.md dans le kit (faux positifs connus, notes d'exploitation).

Un scan de santé en lecture seule du wiki (wiki_root dans wiki.config.json) ainsi que trois outils de réparation. Tout est basé sur la bibliothèque standard Python et fonctionne à l'identique sur Windows, macOS et Linux. Toutes les règles spécifiques au wiki (dossiers, taxonomie des statuts, plan de champs, exemptions, liste de verbes, motifs de substitution, seuils) sont définies dans la configuration, de sorte que la logique ne change pas lorsque le wiki acquiert un nouveau champ, dossier ou vérification. Conçu pour rester rapide au-delà de 3 000 notes (une exécution complète prend quelques secondes, sauf la vérification 13 qui prend environ une demi-minute à cette échelle).

Compétences connexes

  • wiki-ingest, wiki-ingest-book : écrivent les notes que cette compétence vérifie (même configuration pour les décisions de statut et le routage d'index).
  • wiki-synthesize : la vérification 15 produit sa liste de travail ; la vérification 32 audite ses sceaux.
  • vocabulary-update : le correctif pour la vérification 30.

Structure

skills/wiki-lint/
  SKILL.md
  scripts/
    lint.py        # exécute les vérifications (--only, --out-dir, --self-test)
    fix.py         # outils de réparation : proposition d'index, rétroliens de la vérification 12, promotion des brouillons
  references/
    check-origins.md   # POURQUOI chaque vérification existe (autorité unique)
    cli-reference.md   # drapeaux, clés de configuration, fichiers de sortie, structure du rapport
wikikit/lint/        # l'implémentation : context.py, checks_*.py, fixes.py, defaults.json
tests/fixtures/lint/ # mini-wiki synthétique exerçant chaque vérification + expected_counters.txt

Où vit chaque type d'information (ne jamais dupliquer entre ces emplacements) : references/check-origins.md = pourquoi une vérification existe ; ce fichier = ce qu'elle fait ; wikikit/lint/checks_*.py = comment elle est implémentée ; tests/fixtures/lint/expected_counters.txt = pourquoi la valeur de la fixture est ce qu'elle est. À la fin d'une exécution en conditions réelles, l'outil affiche le pointeur check-origins.md pour chaque vérification déclenchée, de sorte que la raison arrive au moment où vous décidez si un résultat est réel ou du bruit.

Invariants d'ingénierie (ne pas casser)

  1. Toutes les E/S fichier passent par wikikit.textio (UTF-8 au niveau octet, pas de BOM, retours à la ligne jamais traduits). N'utilisez jamais open() en mode texte avec le traitement de nouvelles lignes par défaut : lire et réécrire un fichier CRLF de cette façon le convertit silencieusement.
  2. N'utilisez jamais une expression régulière multiligne avec $ sur du texte pouvant contenir du CRLF : $ se place entre le CR et le LF et divise la paire. Éditez par lignes (frontmatter.set_key, fixes._insert_backlinks).
  3. La configuration est la source unique de vérité. Lorsque le wiki gagne un champ, un dossier, un statut ou une exemption, modifiez wiki.config.json (section lint), pas le code. Les valeurs par défaut se trouvent dans wikikit/lint/defaults.json.
  4. L'exemption de brouillon est uniforme. lint.stub_exempt_checks liste les numéros de vérification qui ignorent les notes avec status: stub ; lisez la liste depuis la configuration, ne la répétez jamais en prose. Les vérifications 10 et 11 excluent les brouillons en ligne (décomptes du système de fichiers).
  5. La détection des espaces réservés est conditionnée à la non-résolution. Un lien wiki dont la cible se résout dans l'index du coffre n'est JAMAIS signalé comme espace réservé, même si son nom correspond à un motif ; les notes d'abréviations légitimes en MAJUSCULES ne doivent pas être signalées.
  6. Auto-test avant de publier des modifications de logique. Toute modification d'une vérification (nouvelle vérification, seuil modifié, heuristique remaniée) doit passer le test vert : python skills/wiki-lint/scripts/lint.py --self-test. Mettez à jour tests/fixtures/lint/ et expected_counters.txt ensemble lorsque le changement est intentionnel. Prouvez que la fixture discrimine : annulez la modification de logique, relancez et confirmez que le compteur bouge. Une fixture qui réussit à la fois avant et après ne protège rien.
  7. Un zéro est une mesure du détecteur, pas du wiki. Avant de faire confiance au zéro d'une nouvelle vérification, injectez un cas positif et voyez-le se déclencher.
  8. La propriété du marqueur d'avertissement est positionnelle, jamais basée sur une chaîne d'expressions régulières (vérification 22). Le wiki peut utiliser à la fois [[Paper]]⚠ et ⚠[[Paper]]. Le propriétaire d'un glyphe est le lien immédiatement à sa GAUCHE si le texte coupé à gauche se termine par ]], sinon le lien à sa DROITE ; un glyphe adjacent à aucun lien est une mise en garde dans le texte courant. Ne résolvez pas cela avec deux expressions régulières chaînées (la deuxième mange le marqueur du lien voisin et désactive silencieusement un drapeau pour une source non vérifiée). Toute édition en masse de marqueurs nécessite un recensement par clef de citation avant et après.

Fonctionnement des vérifications

#NomCe qu'il signaleExemption
1Concepts orphelinsAucun rétrolien depuis un article/livre (lien en ligne ou concepts_touched) ET aucun d'un concept frère (en ligne ou related_concepts) ; la branche frère empêche les hubs de synthèse de déclencher un faux positifbrouillon
2Méthodes orphelinesAucun rétrolien depuis un article/livre ET aucun lien sortant vers un article/livrebrouillon
3concepts_touched videUne note d'article avec le champ nul, vide ou [] (également le canari pour la corruption du frontmatter lors des importations par lot)brouillon
4Affirmations non sourcéesNotes de concept avec au moins unsourced_threshold lignes portant un verbe de revendication (verb_list) et aucun lien wiki dans un rayon de +/-unsourced_radius lignes ni sous un titre lié par wikibrouillon
5Liens wiki cassés / espaces réservésCible absente de l'index de tout le coffre (cassé), ou correspondant à placeholder_wikilink_patterns lorsqu'elle ne résout pas (espace réservé), ou vide ([[]], cible-vide)link_target_ignore_patterns (embeds Bases)
6Brouillonspromouvoir : un brouillon citant au moins min_distinct_sources_for_final sources DISTINCTES (un livre et ses chapitres comptent pour une œuvre). obsolète : un brouillon plus vieux que stale_days en dessous de ce seuil, ou sans dateaucun
7Couverture de l'indexUne note dont le nom de base n'est pas un lien wiki dans index.mdbrouillon ; ignoré quand index_mode est bases
7aDéplacement de section d'indexUn - [[X]] sous la mauvaise section ## (index_sections)ignoré en mode bases
8Synchronisation des book:chapters_ingestedL'ensemble déclaré diffère des fichiers {book}_ChNN.md sur le disquechapitres brouillons
9Chapitre sans book:Une note *_ChNN dont le lien book: est manquant ou ne résout pasaucun
10Dérive de Quick StatsUn nombre déclaré dans ## Quick Stats diffère du nombre réel de fichiers dans le dossier mappé (quick_stats_labels)aucun
11Dérive de Couverture par domaineLes colonnes Concepts/Méthodes de ## Coverage by Field diffèrent des comptes réels non-brouillons (lignes de domaine par field:, lignes de sous-domaine -> par subfield: basées sur le lien [[MOC_*]] ; un sous-domaine avec des notes et sans ligne est MISSING-ROW)brouillons ; les notes sans domaine sont INFO
12concepts_touched bidirectionnelarticle -> concepts_touched[token] dont la cible manque du rétrolien [[article]] (asymétrie, auto-corrigeable) ou résout en aucune note (cible-manquante, trier le token)aucun
13Alias sans lienUn alias documenté (acronyme distinctif ou phrase multi-mots) utilisé dans la prose d'un autre concept/méthode sans lien vers sa note canonique. INFObrouillon ; alias_link_stoplist ; les blockquotes ne sont pas recherchés
14Radar de langueUn titre (H2-H6) dans une langue autre que celle du wiki, ou au moins prose_threshold hits de mots vides dans la prose. Rapport uniquement ; désactivé sauf si language_radar.enabledbrouillon
15Radar de synthèseSur les concepts/méthodes final : manquant = qualifié pour un bloc État-des-Connaissances et n'en a aucun ; obsolète = bloc plus vieux que le last_verified le plus récent de ses œuvres citéesnon-final
16Vocabulaire des statutsstatus pas dans status_by_type[type], status ou type manquants, ou fuite de modèle (draft | final)aucun
17Pas de source_verificationUn article sans sceau ; une valeur commençant par abstract n'est PAS un sceau. INFO backlogbrouillon
18Vérifié mais incompletUn article scellé sans volume ou pages et sans exemption datée check18_exempt: "YYYY-MM-DD, reason" ; les articles de conférence et les thèses sont exemptés par type et formebrouillon
19evidence_level hors vocabulaireValeur pas dans evidence_level_vocab (articles seulement)aucun
20]] dans des citations utilesUn blockquote sous ## Useful Quotes avec un ]] qui a fuiaucun
21Cohorte pré-texte intégralUn article daté avant synthesis.prefulltext_cutoff sans sceau de texte intégral. INFObrouillon
22Marqueur pré-texte intégral obsolèteUn ⚠ dont le lien wiki propriétaire est un article qui a déjà un sceau de texte intégral, après trois exemptions de queue (mise en garde dans la prose, annotation italique datée, confiance (N src). A de vrais faux positifsaucun
23Espace réservé d'affirmation non rempliUne ligne correspondant à unfilled_claim_patterns (une source nommée mais aucune affirmation écrite)aucun
24Clé de frontmatter obsolèteUne clé dans deprecated_frontmatter_keys (par défaut journal vers venue) ; correspondance exacte, donc pas de faux positifsaucun
25Figure non citéeUne figure statistique (numeric_claim_patterns) sans lien wiki dans le rayon, classée citée / bloc / méthodes / domaine. INFO. Rien n'est exemptébrouillon ; blockquotes ignorés
26Mésappariement de colonnes de tableauUn tableau dont les lignes ont un nombre de cellules différent de la ligne de délimitation (la seule vérification structurelle)aucun
27MojibakeUne ligne qui, après un round-trip via encode('cp1252').decode('utf-8'), devient une chaîne différenteaucun
28Sceau sans last_verifiedUn article/livre avec source_verification et sans last_verified (invisible pour la vérification 15 obsolète). INFOaucun
29Lien slug hors coffreUn lien wiki vers un slug dans memory_slug_prefixes, à l'échelle du coffre. Désactivé sauf si la liste est non vidememory_slug_exempt_files
30Synchronisation du vocabulaire_VOCABULARY.md manque un concept/méthode existant (manquant) ou contient une ligne pour une note qui n'existe plus (fantôme). INFO ; correctif /vocabulary-updateaucun
31Sceau sans texteUn sceau d'au plus 60 caractères sans texte de vérification descriptif dans aucun canal. INFOaucun
32Paire sans sceauUne paire (note, œuvre citée dans son bloc État-des-Connaissances) dont le sceau de la note source ne nomme pas la note. Bloquant ; les dettes déclarées dans seal_debt_file sont signalées mais non comptéesdette déclarée
33Pas de titre ou de revueUn article avec un title ou venue videbrouillon

Invocation

Depuis le coffre (le wiki.config.json le plus proche en remontant est la configuration) :

python skills/wiki-lint/scripts/lint.py                 # toutes les vérifications ; les listes vont dans _temp/
python skills/wiki-lint/scripts/lint.py --only 5,12     # vérifications sélectionnées
python skills/wiki-lint/scripts/lint.py --self-test     # fixtures vs expected_counters.txt
python skills/wiki-lint/scripts/fix.py check12 --dry-run
python skills/wiki-lint/scripts/fix.py promote _temp/promote_batch.txt
python skills/wiki-lint/scripts/fix.py index            # nécessite index_mode "manual" et une exécution préalable de lint

Drapeaux, clés de configuration et fichiers écrits par chaque vérification : references/cli-reference.md.

Quand modifier quoi

  • Nouveau dossier wiki (par exemple datasets/) : ajoutez-le à folders dans wiki.config.json. Il doit être enregistré AVANT la création de notes, sinon chaque lien vers lui sera considéré comme cassé.
  • Nouvelle valeur de statut : ajoutez-la à lint.status_by_type.{type}. Nouveau type de note : ajoutez le type avec ses statuts autorisés.
  • Nouveau champ pour concepts/méthodes : ajoutez le slug à field_titlecase_map.
  • Affiner la vérification 4 : lint.verb_list. Assouplir/resserrer sa tolérance : lint.defaults.unsourced_radius.
  • Nouveau motif d'espace réservé : lint.placeholder_wikilink_patterns (rappelez-vous qu'il ne s'applique qu'aux cibles non résolvantes).
  • Une vérification doit ignorer les brouillons : ajoutez son numéro à lint.stub_exempt_checks.
  • Activer le radar de langue : copiez examples/languages/es.json (ou écrivez vos propres listes) dans lint.language_radar.
  • Ajouter une nouvelle vérification : implémentez-la dans wikikit/lint/checks_*.py, ajoutez ses compteurs à expected_counters.txt, ajoutez une fixture qui l'exerce, écrivez son entrée dans references/check-origins.md. Une vérification dont le motif n'est pas écrit sera désactivée la première fois qu'elle semblera bruyante. Si le motif ne peut pas être sourcé, écrivez "non documenté" ; n'en inventez jamais.

Règles de sécurité

  • Le lint est en lecture seule vis-à-vis du wiki ; il écrit seulement les listes par vérification dans --out-dir (par défaut _temp/).
  • fix.py ne modifie les notes que là où il le signale (rétroliens, statut), conserve les fins de ligne de chaque fichier et journalise tout changement pour annulation.
  • En cas de doute sur la justesse d'une modification d'heuristique, écrivez d'abord la fixture, regardez l'auto-test échouer, puis effectuez la modification.
  • Les répertoires de cache ne sont jamais versionnés (_temp/ et autres restent dans .gitignore). Une mesure versionnée sera lue des mois plus tard comme si elle datait d'aujourd'hui.

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

Skills associés