Was macht wiki-lint?
Vor dem ersten Ausführen
docs/GOTCHAS.mdim Kit lesen (bekannte Fehlalarme, Betriebshinweise).
Ein schreibgeschützter Gesundheitscheck des Wikis (wiki_root in wiki.config.json) plus drei Reparaturwerkzeuge. Alles ist Python-Standardbibliothek und läuft auf Windows, macOS und Linux gleich. Jede Wikispezifische Regel (Ordner, Statustaxonomie, Feldzuordnung, Ausnahmen, Verbliste, Platzhaltermuster, Schwellenwerte) lebt in der Konfiguration, sodass die Logik nicht geändert werden muss, wenn das Wiki ein neues Feld, einen neuen Ordner oder eine neue Prüfung erhält. Entwickelt, um auch bei über 3.000 Notizen schnell zu bleiben (ein vollständiger Lauf dauert Sekunden, außer Check 13, der bei dieser Größe etwa eine halbe Minute benötigt).
Verwandte Skills
wiki-ingest,wiki-ingest-book: Schreiben die Notizen, die dieser Skill prüft (gleiche Konfiguration für Statusentscheidungen und Indexweiterleitung).wiki-synthesize: Check 15 erstellt dessen Arbeitsliste; Check 32 prüft dessen Siegel.vocabulary-update: Die Abhilfe für Check 30.
Aufbau
skills/wiki-lint/
SKILL.md
scripts/
lint.py # Führt die Prüfungen aus (--only, --out-dir, --self-test)
fix.py # Reparaturwerkzeuge: Indexvorschlag, Check 12 Backlinks, Entwürfe befördern
references/
check-origins.md # WARUM jede Prüfung existiert (eine einzige Autorität)
cli-reference.md # Flags, Konfigurationsschlüssel, Ausgabedateien, Berichtsform
wikikit/lint/ # Die Implementierung: context.py, checks_*.py, fixes.py, defaults.json
tests/fixtures/lint/ # Synthetisches Mini-Wiki, das jede Prüfung testet + expected_counters.txt
Wo welche Art von Information lebt (niemals über diese hinweg duplizieren): references/check-origins.md = warum eine Prüfung existiert; diese Datei = was sie tut; wikikit/lint/checks_*.py = wie sie implementiert ist; tests/fixtures/lint/expected_counters.txt = warum der Fixture-Wert genau das ist. Am Ende eines Live-Laufs druckt das Tool den check-origins.md-Verweis für jede ausgelöste Prüfung, sodass das Motiv sichtbar ist, wenn Sie entscheiden, ob ein Treffer echt oder Rauschen ist.
Engineering-Invarianten (nicht brechen)
- Die gesamte Datei-E/A erfolgt über
wikikit.textio(Byte-Ebene UTF-8, ohne BOM, Zeilenumbrüche niemals übersetzt). Verwenden Sie niemals den Textmodusopen()mit standardmäßiger Zeilenumbruchbehandlung: Das Lesen und Neuschreiben einer CRLF-Datei auf diese Weise konvertiert sie stillschweigend. - Verwenden Sie niemals einen mehrzeiligen Regex mit
$über Text, der CRLF enthalten kann:$sitzt zwischen CR und LF und spaltet das Paar. Bearbeiten Sie zeilenweise (frontmatter.set_key,fixes._insert_backlinks). - Die Konfiguration ist die einzige Quelle der Wahrheit. Wenn das Wiki ein Feld, einen Ordner, einen Status oder eine Ausnahme erhält, bearbeiten Sie
wiki.config.json(lint-Abschnitt), nicht den Code. Standardwerte leben inwikikit/lint/defaults.json. - Die Stub-Ausnahme ist einheitlich.
lint.stub_exempt_checkslistet die Prüfnummern, diestatus: stub-Notizen überspringen; lesen Sie die Liste aus der Konfiguration, nie in Prosa wiederholen. Checks 10 und 11 schließen Stubs inline aus (Dateisystemzählungen). - Die Platzhaltererkennung ist an die Nicht-Auflösung gebunden. Ein Wikilink-Ziel, das im Vault-Index aufgelöst wird, wird NIEMALS als Platzhalter gekennzeichnet, selbst wenn sein Name einem Muster entspricht; legitime GROSSBUCHSTABEN-Abkürzungsnotizen dürfen nicht gekennzeichnet werden.
- Selbsttest vor dem Ausliefern von Logikänderungen. Jede Bearbeitung einer Prüfung (neue Prüfung, geänderter Schwellenwert, überarbeitete Heuristik) muss grün laufen:
python skills/wiki-lint/scripts/lint.py --self-test. Aktualisieren Sietests/fixtures/lint/undexpected_counters.txtgemeinsam, wenn die Änderung beabsichtigt ist. Beweisen Sie, dass das Fixture unterscheidet: Kehren Sie die Logikänderung um, führen Sie es erneut aus, und bestätigen Sie, dass sich der Zähler bewegt. Ein Fixture, das sowohl vorher als auch nachher besteht, schützt nichts. - Eine Null ist eine Messung des Detektors, nicht des Wikis. Bevor Sie einer Null einer neuen Prüfung vertrauen, injizieren Sie einen positiven Fall und sehen Sie, ob sie auslöst.
- Die Eigentümerschaft von Warnmarkierungen ist positionsbasiert, niemals über verkettete Regex (Check 22). Das Wiki kann sowohl
[[Paper]]⚠als auch⚠[[Paper]]verwenden. Der Eigentümer eines Glyphen ist der Link unmittelbar LINKS davon, wenn der linksgetrimmte Text auf]]endet, andernfalls der Link RECHTS davon; ein Glyph ohne benachbarten Link ist eine Prosa-Warnung. Lösen Sie dies nicht mit zwei verketteten Regexes (der zweite frisst die Markierung des benachbarten Links und entflaggt stillschweigend eine ungeprüfte Quelle). Jede Massenbearbeitung von Markierungen benötigt eine Zählung pro Citekey vor und nachher.
Wie die Prüfungen funktionieren
| # | Name | Was wird geprüft | Ausnahme |
|---|---|---|---|
| 1 | Verwaiste Konzepte | Kein Backlink von einem Paper/Buch (Inline-Link oder concepts_touched) UND keiner von einem Schwesterkonzept (Inline oder related_concepts); der Schwesterzweig verhindert Fehlalarme bei Synthese-Hubs | stub |
| 2 | Verwaiste Methoden | Kein Backlink von einem Paper/Buch UND kein ausgehender Link zu einem Paper/Buch | stub |
| 3 | Leeres concepts_touched | Eine Paper-Notiz mit dem Feld null, leer oder [] (auch der Indikator für Frontmatter-Korruption bei Batch-Imports) | stub |
| 4 | Unbelegte Behauptungen | Konzeptnotizen mit mindestens unsourced_threshold Zeilen, die ein Behauptungsverb (verb_list) enthalten, und kein Wikilink innerhalb von +/-unsourced_radius Zeilen und auch nicht unter einem verlinkten Heading | stub |
| 5 | Kaputte / Platzhalter-Wikilinks | Ziel nicht im gesamten Vault-Index (broken) oder passend zu placeholder_wikilink_patterns bei Nicht-Auflösung (placeholder) oder leer ([[]], empty-target) | link_target_ignore_patterns (Bases-Einbettungen) |
| 6 | Entwürfe | promote: Ein Entwurf, der mindestens min_distinct_sources_for_final UNTERSCHIEDLICHE Quellwerke zitiert (ein Buch plus seine Kapitel ist ein Werk). stale: Ein Entwurf älter als stale_days darunter, oder ohne Datum | keine |
| 7 | Indexabdeckung | Eine Notiz, deren Basisname kein Wikilink in index.md ist | stub; übersprungen, wenn index_mode bases ist |
| 7b | Indexabschnitt-Fehlplatzierung | Ein - [[X]] unter dem falschen ##-Abschnitt (index_sections) | übersprungen im Modus bases |
| 8 | Buch chapters_ingested-Synchronisation | Deklarierte Menge unterscheidet sich von den {book}_ChNN.md-Dateien auf der Festplatte | Stub-Kapitel |
| 9 | Kapitel ohne book: | Eine *_ChNN-Notiz, deren book:-Link fehlt oder nicht aufgelöst wird | keine |
| 10 | Quick Stats-Abweichung | Eine deklarierte Anzahl in ## Quick Stats unterscheidet sich von der Live-Dateianzahl des zugeordneten Ordners (quick_stats_labels) | keine |
| 11 | Coverage by Field-Abweichung | Spalten Konzepte/Methoden von ## Coverage by Field unterscheiden sich von den Live-Anzahlen ohne Stubs (Feldzeilen nach field:, -> Unterfeldzeilen nach subfield: ausgehend vom [[MOC_*]]-Link; ein Unterfeld mit Notizen und ohne Zeile ist MISSING-ROW) | Stubs; unfeldierte Notizen sind INFO |
| 12 | Bidirektionale concepts_touched | paper -> concepts_touched[token], dessen Ziel den [[paper]]-Backlink vermissen lässt (asymmetry, automatisch korrigierbar) oder zu keiner Notiz auflöst (missing_target, Token triagieren) | keine |
| 13 | Alias ohne Link | Ein dokumentierter Alias (unterscheidbares Akronym oder mehrwortiger Ausdruck), der im Prosa eines anderen Konzepts/Methode ohne Link zu seiner kanonischen Notiz verwendet wird. INFO | stub; alias_link_stoplist; Blockzitate werden nicht durchsucht |
| 14 | Sprachradar | Eine Überschrift (H2-H6) in einer anderen Sprache als der des Wikis oder mindestens prose_threshold Stoppworttreffer im Prosa. Nur Bericht; deaktiviert, außer language_radar.enabled | stub |
| 15 | Syntheseradar | Über final Konzepte/Methoden: missing = qualifiziert für einen State-of-Knowledge-Block und hat keinen; stale = Block älter als das neueste last_verified seiner zitierten Werke | nicht-final |
| 16 | Statusvokabular | status nicht in status_by_type[type], fehlendes status oder type, oder ein Template-Lek (draft | final) | keine |
| 17 | Kein source_verification | Ein Paper ohne Siegel; ein Wert, der mit abstract beginnt, ist KEIN Siegel. INFO-Backlog | stub |
| 18 | Verifiziert, aber unvollständig | Ein versiegeltes Paper ohne volume oder pages und ohne datierte check18_exempt: "YYYY-MM-DD, reason"; Konferenzpapiere und Thesen sind nach Veranstaltungsort und Form ausgenommen | stub |
| 19 | evidence_level außerhalb des Vokabulars | Wert nicht in evidence_level_vocab (nur Papers) | keine |
| 20 | Nützliche Zitate ]] | Ein Blockzitat unter ## Useful Quotes mit einem durchgestellten ]] | keine |
| 21 | Pre-Volltext-Kohorte | Ein Paper vor synthesis.prefulltext_cutoff ohne Volltext-Siegel. INFO | stub |
| 22 | Veraltete Pre-Volltext-Markierung | Ein ⚠, dessen besitzender Wikilink ein Paper ist, das bereits ein Volltext-Siegel hat, nach drei Ausnahmen für den Nachlauf (Prosa-Vorbehalt, datierte kursive Anmerkung, (N src-Vertrauen). Hat echte Fehlalarme | keine |
| 23 | Ungefüllter Behauptungsplatzhalter | Eine Zeile, die auf unfilled_claim_patterns passt (eine Quelle benannt, aber keine Behauptung geschrieben) | keine |
| 24 | Veralteter Frontmatter-Schlüssel | Ein Schlüssel in deprecated_frontmatter_keys (Standard journal zu venue); exakte Übereinstimmung, daher keine Fehlalarme | keine |
| 25 | Unzitierte Abbildung | Eine statistische Abbildung (numeric_claim_patterns) ohne Wikilink innerhalb des Radius, klassifiziert als cited / block / methods / domain. INFO. Nichts ist ausgenommen | stub; Blockzitate übersprungen |
| 26 | Tabellenspalten-Mismatch | Eine Tabelle, deren Zeilen eine andere Anzahl von Zellen haben als die Trennzeile (die einzige strukturelle Prüfung) | keine |
| 27 | Mojibake | Eine Zeile, die durch encode('cp1252').decode('utf-8') in eine andere Zeichenkette rundläuft | keine |
| 28 | Siegel ohne last_verified | Ein Paper/Buch mit source_verification und keinem last_verified (unsichtbar für Check 15 stale). INFO | keine |
| 29 | Vault-fremder Slug-Link | Ein Wikilink zu einem Slug in memory_slug_prefixes, vault-weit. Deaktiviert, außer die Liste ist nicht leer | memory_slug_exempt_files |
| 30 | Vokabular-Synchronisation | _VOCABULARY.md vermisst ein Live-Konzept/Methode (missing) oder enthält eine Zeile für eine nicht mehr vorhandene Notiz (ghost). INFO; Abhilfe /vocabulary-update | keine |
| 31 | Siegel ohne Text | Ein Siegel von maximal 60 Zeichen ohne beschreibenden Verifikationstext in irgendeinem Kanal. INFO | keine |
| 32 | Paar ohne Siegel | Ein Paar (Notiz, in ihrem State-of-Knowledge-Block zitiertes Werk), dessen Quellnotiz-Siegel die Notiz nicht benennt. Blockierend; deklarierte Schulden in seal_debt_file werden gemeldet, aber nicht gezählt | deklarierte Schulden |
| 33 | Kein Titel oder Veranstaltungsort | Ein Paper mit leerem title oder venue | stub |
Aufruf
Vom Vault aus (die nächstgelegene wiki.config.json aufwärts ist die Konfiguration):
python skills/wiki-lint/scripts/lint.py # alle Prüfungen; Listen gehen nach _temp/
python skills/wiki-lint/scripts/lint.py --only 5,12 # ausgewählte Prüfungen
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 # benötigt index_mode "manual" und einen vorherigen lint-Lauf
Flags, Konfigurationsschlüssel und die Dateien, die jede Prüfung schreibt: references/cli-reference.md.
Wann was bearbeiten
- Neuer Wiki-Ordner (z. B.
datasets/): Fügen Sie ihn zufoldersinwiki.config.jsonhinzu. Er muss registriert sein, BEVOR Notizen erstellt werden, sonst wird jeder Link darauf als defekt gelesen. - Neuer Statuswert: Fügen Sie ihn zu
lint.status_by_type.{type}hinzu. Neuer Notiztyp: Fügen Sie den Typ mit seinen erlaubten Statuswerten hinzu. - Neues Feld für Konzepte/Methoden: Fügen Sie den Slug zu
field_titlecase_maphinzu. - Check 4 verfeinern:
lint.verb_list. Seine Toleranz lockern/straffen:lint.defaults.unsourced_radius. - Neues Platzhaltermuster:
lint.placeholder_wikilink_patterns(denken Sie daran, es gilt nur für nicht-auflösende Ziele). - Eine Prüfung soll Stubs überspringen: Fügen Sie ihre Nummer zu
lint.stub_exempt_checkshinzu. - Sprachradar aktivieren: Kopieren Sie
examples/languages/es.json(oder schreiben Sie eigene Listen) inlint.language_radar. - Neue Prüfung hinzufügen: Implementieren Sie sie in
wikikit/lint/checks_*.py, fügen Sie ihre Zähler zuexpected_counters.txthinzu, fügen Sie ein Fixture hinzu, das sie testet, schreiben Sie ihren Eintrag inreferences/check-origins.md. Eine Prüfung, deren Motiv nicht dokumentiert ist, wird beim ersten Mal deaktiviert, wenn sie verrauscht erscheint. Wenn das Motiv nicht gefunden werden kann, schreiben Sie "nicht dokumentiert"; erfinden Sie niemals eines.
Sicherheitsregeln
- Der Lint ist schreibgeschützt gegen das Wiki; er schreibt nur die listen pro Prüfung in
--out-dir(Standard_temp/). fix.pymutiert Notizen nur dort, wo es berichtet (Backlinks, Status), behält die Zeilenumbrüche jeder Datei bei und protokolliert jede Änderung für ein Rollback.- Wenn Sie unsicher sind, ob eine Heuristikänderung richtig ist, schreiben Sie zuerst das Fixture, beobachten Sie den Fehlschlag des Selbsttests, dann nehmen Sie die Änderung vor.
- Cache-Verzeichnisse werden niemals versioniert (
_temp/und ähnliche bleiben in.gitignore). Eine versionierte Messung wird Monate später gelesen, als wäre sie von heute.