MinorBaek/wiki-lint

Kit de diagnóstico y reparación para un wiki científico en Markdown (compatible con Obsidian): 33 comprobaciones de salud sobre enlaces, procedencia, frontmatter, tablas, codificación, bloques de síntesis y sellos.

¿Qué es wiki-lint?

wiki-lint es un conjunto de herramientas de análisis y reparación diseñado para mantener la integridad y consistencia de un wiki científico basado en Markdown, compatible con Obsidian. Realiza 33 comprobaciones de salud exhaustivas que cubren enlaces rotos o huérfanos, procedencia (atribución de fuentes), consistencia del frontmatter (metadatos), estructura de tablas, codificación de caracteres (mojibake), bloques de síntesis y sellos de verificación. Está construido con la biblioteca estándar de Python, por lo que funciona de manera idéntica en Windows, macOS y Linux, y está diseñado para mantenerse rápido incluso con más de 3,000 notas. La lógica se configura externamente, lo que permite adaptar reglas específicas del wiki (carpetas, estados, campos, exenciones) sin modificar el código. Además de la exploración de solo lectura, incluye herramientas de reparación para corregir problemas comunes como enlaces bidireccionales faltantes y promoción de borradores. Se integra con otros skills como wiki-ingest y wiki-synthesize, y está pensado para equipos de investigación que gestionan un conocimiento estructurado y necesitan garantizar la calidad de su wiki de forma automatizada y confiable.

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

Installed? Explore more Investigación y análisis de datos skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

¿Qué hace wiki-lint?

Antes de la primera ejecución, lea docs/GOTCHAS.md en el kit (falsos positivos conocidos, notas operativas).

Un escaneo de salud de solo lectura del wiki (wiki_root en wiki.config.json) más tres herramientas de reparación. Todo es biblioteca estándar de Python y funciona igual en Windows, macOS y Linux. Cada regla específica del wiki (carpetas, taxonomía de estados, mapa de campos, exenciones, lista de verbos, patrones de marcador de posición, umbrales) vive en la configuración, por lo que la lógica no cambia cuando el wiki agrega un nuevo campo, carpeta o verificación. Diseñado para mantenerse rápido más allá de 3000 notas (una ejecución completa toma segundos, excepto la Verificación 13 que tarda alrededor de medio minuto en ese tamaño).

Skills relacionados

  • wiki-ingest, wiki-ingest-book: escriben las notas que este skill verifica (misma configuración para decisiones de estado y enrutamiento de índice).
  • wiki-synthesize: la Verificación 15 produce su lista de trabajo; la Verificación 32 audita sus sellos.
  • vocabulary-update: el remedio para la Verificación 30.

Diseño

skills/wiki-lint/
  SKILL.md
  scripts/
    lint.py        # ejecuta las verificaciones (--only, --out-dir, --self-test)
    fix.py         # herramientas de reparación: propuesta de índice, Verificación 12 backlinks, promocionar borradores
  references/
    check-origins.md   # POR QUÉ existe cada verificación (autoridad única)
    cli-reference.md   # banderas, claves de configuración, archivos de salida, forma del informe
wikikit/lint/        # la implementación: context.py, checks_*.py, fixes.py, defaults.json
tests/fixtures/lint/ # mini-wiki sintético que ejercita cada verificación + expected_counters.txt

Dónde vive cada tipo de hecho (nunca duplicar entre estos): references/check-origins.md = por qué existe una verificación; este archivo = qué hace; wikikit/lint/checks_*.py = cómo se implementa; tests/fixtures/lint/expected_counters.txt = por qué el valor del fixture es el que es. Al final de una ejecución en vivo, la herramienta imprime el puntero check-origins.md para cada verificación que se activó, para que el motivo llegue cuando esté decidiendo si un acierto es real o ruido.

Invariantes de ingeniería (no romper)

  1. Todo I/O de archivos pasa por wikikit.textio (UTF-8 a nivel de bytes, sin BOM, los finales de línea nunca se traducen). Nunca use open() en modo texto con el manejo de newline predeterminado: leer y reescribir un archivo CRLF de esa manera lo convierte silenciosamente.
  2. Nunca use una expresión regular multilínea con $ sobre texto que pueda contener CRLF: $ se sienta entre el CR y el LF y divide el par. Edite por líneas (frontmatter.set_key, fixes._insert_backlinks).
  3. La configuración es la única fuente de verdad. Cuando el wiki gane un campo, carpeta, estado o exención, edite wiki.config.json (sección lint), no el código. Los valores predeterminados viven en wikikit/lint/defaults.json.
  4. La exención de stub es uniforme. lint.stub_exempt_checks enumera los números de verificación que omiten las notas status: stub; lea la lista de la configuración, nunca la repita en prosa. Las Verificaciones 10 y 11 excluyen stubs inline (cuentas del sistema de archivos).
  5. La detección de marcador de posición está condicionada a no resolución. Un wikienlace que se resuelve en el índice del vault NUNCA se marca como marcador de posición, incluso si su nombre coincide con un patrón; las notas de abreviaturas legítimas en MAYÚSCULAS no deben marcarse.
  6. Autoprueba antes de enviar cambios de lógica. Cualquier edición a una verificación (nueva verificación, umbral cambiado, heurística refactorizada) debe ejecutarse en verde: python skills/wiki-lint/scripts/lint.py --self-test. Actualice tests/fixtures/lint/ y expected_counters.txt juntos cuando el cambio sea intencional. Demuestre que el fixture discrimina: revierta el cambio de lógica, vuelva a ejecutar y confirme que el contador se mueve. Un fixture que pasa tanto antes como después no protege nada.
  7. Un cero es una medición del detector, no del wiki. Antes de confiar en el cero de una nueva verificación, inyecte un caso positivo y vea que se active.
  8. La propiedad del marcador de advertencia es posicional, nunca encadenada con regex (Verificación 22). El wiki puede usar tanto [[Paper]]⚠ como ⚠[[Paper]]. El propietario de un glifo es el enlace inmediatamente a su IZQUIERDA si el texto recortado a la izquierda termina en ]], de lo contrario, el enlace a su DERECHA; un glifo adyacente a ningún enlace es una advertencia en prosa. No resuelva esto con dos regex encadenados (el segundo se come el marcador del enlace vecino y desmarca silenciosamente una fuente no verificada). Cualquier edición masiva de marcadores necesita un censo por citekey antes y después.

Cómo funcionan las verificaciones

#NombreQué marcaExención
1Conceptos huérfanosSin backlink de ningún artículo/libro (enlace inline o concepts_touched) Y ninguno de un concepto hermano (inline o related_concepts); la pata hermano evita que los hubs de síntesis marquen falsos positivosstub
2Métodos huérfanosSin backlink de un artículo/libro Y sin enlace saliente a ningún artículo/librostub
3concepts_touched vacíoUna nota de artículo con el campo nulo, vacío o [] (también el canario para corrupción de frontmatter en ingestas por lotes)stub
4Afirmaciones sin fuenteNotas de concepto con al menos unsourced_threshold líneas que contienen un verbo de afirmación (verb_list) y sin wikienlace dentro de +/-unsourced_radius líneas ni debajo de un encabezado con wikienlacestub
5Wikienlaces rotos / marcador de posiciónDestino no en el índice de todo el vault (roto), o coincide con placeholder_wikilink_patterns cuando no se resuelve (marcador de posición), o vacío ([[]], destino-vacío)link_target_ignore_patterns (embebidos de Bases)
6Borradorespromocionar: un borrador que cita al menos min_distinct_sources_for_final obras fuente DISTINTAS (un libro más sus capítulos es una obra). obsoleto: un borrador más antiguo que stale_days por debajo de eso, o sin fechaninguna
7Cobertura del índiceUna nota cuyo nombre base no es un wikienlace en index.mdstub; omitido cuando index_mode es bases
7bMala ubicación de sección del índiceUn - [[X]] bajo la sección ## incorrecta (index_sections)omitido en modo bases
8Sincronización de chapters_ingested del libroEl conjunto declarado difiere de los archivos {book}_ChNN.md en discostub capítulos
9Capítulo sin book:Una nota *_ChNN cuyo enlace book: falta o no se resuelveninguna
10Desviación de Estadísticas RápidasUn conteo declarado en ## Quick Stats difiere del conteo en vivo de archivos de la carpeta mapeada (quick_stats_labels)ninguna
11Desviación de Cobertura por CampoLas columnas de Conceptos/Métodos de ## Coverage by Field difieren de los conteos en vivo no stub (filas de campo por field:, filas de subcampo -> por subfield: clave desde el enlace [[MOC_*]]; un subcampo con notas y sin fila es MISSING-ROW)stubs; notas sin campo son INFO
12concepts_touched bidireccionalpaper -> concepts_touched[token] cuyo destino carece del backlink [[paper]] (asimetría, auto-reparable) o se resuelve a ninguna nota (missing_target, triaje del token)ninguna
13Alias sin enlaceUn alias documentado (acrónimo distintivo o frase de varias palabras) usado en la prosa de otro concepto/método sin un enlace a su nota canónica. INFOstub; alias_link_stoplist; las citas en bloque no se buscan
14Radar de idiomaUn encabezado (H2-H6) en un idioma diferente al del wiki, o al menos prose_threshold aciertos de stopword en prosa. Solo informe; deshabilitado a menos que language_radar.enabledstub
15Radar de síntesisSobre conceptos/métodos finales: falta = califica para un bloque de Estado del Conocimiento y no tiene ninguno; obsoleto = bloque más antiguo que el last_verified más reciente de sus obras citadasno final
16Vocabulario de estadostatus no en status_by_type[type], falta status o type, o una fuga de plantilla (draft | final)ninguna
17Sin source_verificationUn artículo sin sello; un valor que comienza con abstract NO es un sello. INFO backlogstub
18Verificado pero incompletoUn artículo sellado que carece de volume o pages y sin un check18_exempt: "YYYY-MM-DD, reason" fechado; los artículos de conferencias y tesis están exentos por sede y formastub
19evidence_level fuera de vocabularioValor no en evidence_level_vocab (solo artículos)ninguna
20Citas Útiles ]]Una cita en bloque bajo ## Useful Quotes con un ]] filtradoninguna
21Cohorte previo a texto completoUn artículo fechado antes de synthesis.prefulltext_cutoff sin sello de nivel de texto completo. INFOstub
22Marcador pre-texto completo obsoletoUn ⚠ cuyo wikienlace propietario es un artículo que ya tiene un sello de texto completo, después de tres exenciones de cola (advertencia en prosa, anotación itálica fechada, confianza (N src). Tiene falsos positivos realesninguna
23Marcador de posición de afirmación sin llenarUna línea que coincide con unfilled_claim_patterns (una fuente nombrada pero ninguna afirmación escrita)ninguna
24Clave de frontmatter obsoletaUna clave en deprecated_frontmatter_keys (por defecto journal a venue); coincidencia exacta, por lo que no hay falsos positivosninguna
25Figura sin citarUna cifra estadística (numeric_claim_patterns) sin wikienlace dentro del radio, clasificada cited / block / methods / domain. INFO. Nada está exentostub; citas en bloque omitidas
26Discrepancia de columnas en tablaUna tabla cuyas filas tienen un número diferente de celdas que la fila delimitadora (la única verificación estructural)ninguna
27MojibakeUna línea que viaja de ida y vuelta a través de encode('cp1252').decode('utf-8') a una cadena diferenteninguna
28Sello sin last_verifiedUn artículo/libro con source_verification y sin last_verified (invisible para la Verificación 15 obsoleto). INFOninguna
29Enlace de slug fuera del vaultUn wikienlace a un slug en memory_slug_prefixes, en todo el vault. Deshabilitado a menos que la lista no esté vacíamemory_slug_exempt_files
30Sincronización de vocabulario_VOCABULARY.md falta un concepto/método en vivo (falta) o tiene una fila para una nota que ya no existe (fantasma). INFO; remedio /vocabulary-updateninguna
31Sello sin textoUn sello de como máximo 60 caracteres sin texto de verificación descriptivo en ningún canal. INFOninguna
32Par sin selloUn par (nota, obra citada en su bloque de Estado del Conocimiento) cuyo sello de nota fuente no nombra la nota. Bloqueante; la deuda declarada en seal_debt_file se informa pero no se cuentadeuda declarada
33Sin título o sedeUn artículo con un title o venue vacíostub

Invocación

Desde el vault (el wiki.config.json más cercano hacia arriba es la configuración):

python skills/wiki-lint/scripts/lint.py                 # todas las verificaciones; las listas van a _temp/
python skills/wiki-lint/scripts/lint.py --only 5,12     # verificaciones seleccionadas
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            # necesita index_mode "manual" y una ejecución de lint previa

Banderas, claves de configuración y los archivos que cada verificación escribe: references/cli-reference.md.

Cuándo editar qué

  • Nueva carpeta del wiki (por ejemplo datasets/): agréguela a folders en wiki.config.json. Debe registrarse ANTES de que se creen las notas, o cada enlace a ella se leerá como roto.
  • Nuevo valor de estado: agréguelo a lint.status_by_type.{type}. Nuevo tipo de nota: agregue el tipo con sus estados permitidos.
  • Nuevo campo para conceptos/métodos: agregue el slug a field_titlecase_map.
  • Refinar Verificación 4: lint.verb_list. Aflojar/ajustar su tolerancia: lint.defaults.unsourced_radius.
  • Nuevo patrón de marcador de posición: lint.placeholder_wikilink_patterns (recuerde que solo se aplica a destinos que no se resuelven).
  • Una verificación debe omitir stubs: agregue su número a lint.stub_exempt_checks.
  • Activar el radar de idioma: copie examples/languages/es.json (o escriba sus propias listas) en lint.language_radar.
  • Agregar una nueva verificación: impleméntela en wikikit/lint/checks_*.py, agregue sus contadores a expected_counters.txt, agregue un fixture que la ejercite, escriba su entrada en references/check-origins.md. Una verificación cuyo motivo no esté escrito se deshabilita la primera vez que parece ruidosa. Si el motivo no se puede encontrar, escriba "no documentado"; nunca invente uno.

Reglas de seguridad

  • El lint es de solo lectura contra el wiki; solo escribe las listas por verificación en --out-dir (por defecto _temp/).
  • fix.py muta notas solo donde informa (backlinks, estado), mantiene los finales de línea de cada archivo y registra cada cambio para deshacer.
  • Cuando no esté seguro de si un cambio heurístico es correcto, escriba el fixture primero, observe que la autoprueba falle, luego haga el cambio.
  • Los directorios de caché nunca tienen versiones (_temp/ y amigos permanecen en .gitignore). Una medición versionada se lee meses después como si fuera de hoy.

Individual skills in this repo

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

Skills relacionados