Community研究与数据分析github.com

MinorBaek/wiki-lint

科学Markdown维基(兼容Obsidian)的诊断与修复工具包:提供33项健康检查,涵盖链接、来源、前置元数据、表格、编码、综合块和印章。

wiki-lint 是什么?

wiki-lint 是一个用于科学Markdown维基(兼容Obsidian)的只读健康扫描工具,包含33项检查以及三个修复工具。它完全基于Python标准库,在Windows、macOS和Linux上运行一致。所有维基特定规则(如文件夹、状态分类、字段映射、豁免项、动词列表、占位符模式和阈值)均通过配置文件管理,因此当维基新增字段、文件夹或检查时,逻辑代码无需更改。该工具设计上能在超过3000条笔记时保持快速(完整运行仅需数秒,除检查13在笔记量较大时约需半分钟)。

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

Installed? Explore more 研究与数据分析 skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

wiki-lint 是做什么的?

首次运行前,请先阅读工具包中的 docs/GOTCHAS.md(已知误报及操作说明)。

维基(wiki.config.json 中的 wiki_root)的只读健康扫描,外加三个修复工具。全部基于 Python 标准库,在 Windows、macOS 和 Linux 上行为一致。每条维基特定规则(文件夹、状态分类、字段映射、豁免项、动词列表、占位符模式、阈值)都存放在配置中,因此当维基新增字段、文件夹或检查项时,逻辑代码无须修改。设计上在超过 3000 条笔记时仍能保持快速(完整运行只需数秒,除检查 13 在如此规模下需要约半分钟)。

相关技能

  • wiki-ingest, wiki-ingest-book:写入本技能要检查的笔记(使用相同的配置来决定状态和索引路由)。
  • wiki-synthesize:检查 15 生成其工作清单;检查 32 审计其印章。
  • vocabulary-update:检查 30 的修复工具。

布局

skills/wiki-lint/
  SKILL.md
  scripts/
    lint.py        # 运行检查(--only, --out-dir, --self-test)
    fix.py         # 修复工具:索引提案、检查 12 反向链接、提升草稿
  references/
    check-origins.md   # 每条检查存在的原因(单一权威)
    cli-reference.md   # 标志、配置键、输出文件、报告格式
wikikit/lint/        # 实现:context.py, checks_*.py, fixes.py, defaults.json
tests/fixtures/lint/ # 练习每条检查的极小维基 + expected_counters.txt

各类事实的存放位置(切勿在这些位置之间重复):references/check-origins.md = 检查为什么存在;本文件 = 检查做什么;wikikit/lint/checks_*.py = 检查如何实现;tests/fixtures/lint/expected_counters.txt = 为什么夹具值是这个值。在一次实况运行的末尾,工具会为每条触发的检查打印其 check-origins.md 指针,这样当你判断一条命中是真实还是噪音时,理由就已经送达。

工程不变性(不得破坏)

  1. 所有文件 I/O 均通过 wikikit.textio(字节级 UTF-8,无 BOM,行尾永不转换)。切勿使用默认换行处理的文本模式 open():这样读取并重写一个 CRLF 文件会静默将其转换。
  2. 切勿在可能包含 CRLF 的文本上使用带 $ 的多行正则表达式:$ 位于 CR 和 LF 之间,会拆分这对字符。逐行编辑(frontmatter.set_key, fixes._insert_backlinks)。
  3. 配置是唯一的真理来源。 当维基新增字段、文件夹、状态或豁免项时,编辑 wiki.config.json(lint 部分),而非代码。默认值位于 wikikit/lint/defaults.json。
  4. 存根豁免是统一的。 lint.stub_exempt_checks 列出了跳过 status: stub 笔记的检查编号;从配置中读取该列表,切勿在正文中重复。检查 10 和 11 内联排除了存根(文件系统计数)。
  5. 占位符检测以未解析为条件。 在仓库索引中能解析到的维基链接目标绝不被标记为占位符,即使其名称匹配模式;合法的全大写缩写笔记不得触发标记。
  6. 在发布逻辑变更前必须先做自检。 对检查的任何修改(新增检查、更改阈值、重构启发式)都必须通过测试:python skills/wiki-lint/scripts/lint.py --self-test。当变更有意时,同时更新 tests/fixtures/lint/ 和 expected_counters.txt。证明夹具具有区分能力:还原逻辑变更,重新运行,并确认计数器发生变化。前后都能通过的夹具什么也保障不了。
  7. 零反映的是检测器的度量,而非维基的度量。 在信任一条新检查的零值之前,先注入一个阳性案例并观察它是否触发。
  8. 警告标记的所有权是位置的,而非正则表达式链式(检查 22)。 维基可能同时使用 [[Paper]]⚠ 和 ⚠[[Paper]]。一个符号的所有者是:如果左端去除空白的文本以 ]] 结尾,则为其左侧的链接;否则为其右侧的链接;与任何链接都不相邻的符号是正文中的谨慎标记。不要使用两个链式正则表达式来解决这个问题(第二个会吞掉相邻链接的标记,静默地取消标记一个未验证的来源)。对标记的任何批量编辑都需要在操作前后对每个引文键进行普查。

检查项说明

#名称标记内容豁免项
1孤立概念没有任何论文/书籍的反向链接(内联链接或 concepts_touched)且无兄弟概念的反向链接(内联或 related_concepts);兄弟层级防止综合枢纽误报stub
2孤立方法没有论文/书籍的反向链接且没有指向任何论文/书籍的出站链接stub
3空的 concepts_touched论文笔记中该字段为 null、空或 [](也是批量导入时前置元数据损坏的预警)stub
4无来源声明概念笔记中至少 unsourced_threshold 行包含声明动词(verb_list)且在 +/-unsourced_radius 行内无维基链接,也不在任何有维基链接的标题下stub
5损坏/占位符维基链接目标不在全仓库索引中(broken),或匹配 placeholder_wikilink_patterns 且无法解析(placeholder),或为空([[]], empty-target)link_target_ignore_patterns(Bases 嵌入)
6草稿promote:引用至少 min_distinct_sources_for_final 个不同源作品(一本书及其各章算一个来源)的草稿。stale:低于该阈值且早于 stale_days 的草稿,或未标注日期的草稿无
7索引覆盖率笔记的基本文件名不在 index.md 的维基链接中stub;当 index_mode 为 bases 时跳过
7b索引章节位置错误- [[X]] 出现在错误的 ## 章节下(index_sections)在 bases 模式下跳过
8书籍 chapters_ingested 同步声明的集合与磁盘上的 {book}_ChNN.md 文件不一致stub 章节
9章节缺少 book:*_ChNN 笔记中 book: 链接缺失或无法解析无
10Quick Stats 漂移## Quick Stats 中声明的计数与对应文件夹(quick_stats_labels)的实际文件数不一致无
11按字段覆盖率漂移## Coverage by Field 中概念/方法列与实际非 stub 计数不一致(字段行按 field:,-> 子字段行按 subfield: 以 [[MOC_*]] 链接为键;有笔记但无行的子字段标记为 MISSING-ROW)stub;无字段笔记为 INFO
12双向 concepts_touchedpaper -> concepts_touched[token] 中目标缺少 [[paper]] 反向链接(asymmetry,可自动修复)或目标不是有效笔记(missing_target,需要排查标记)无
13别名无链接一个已记录的别名(独特缩写或多词短语)在其他概念/方法的正文中被使用,但没有指向其规范笔记的链接。INFOstub;alias_link_stoplist;不搜索引用块
14语言雷达标题(H2-H6)使用非维基语言,或在正文中至少命中 prose_threshold 个停用词。仅报告;除非 language_radar.enabled 启用stub
15综合雷达对于 final 概念/方法:missing = 满足知识状态块条件但无此块;stale = 块早于其引用的最新作品的 last_verified非 final
16状态词汇status 不在 status_by_type[type] 中,status 或 type 缺失,或模板泄露(draft | final)无
17无 source_verification论文缺少印章;以 abstract 开头的值不算印章。INFO 积压stub
18已验证但不完整已加盖印章的论文缺少 volume 或 pages,且没有带日期的 check18_exempt: "YYYY-MM-DD, reason";会议论文和学位论文按场所和形式豁免stub
19evidence_level 不在词汇表中值不在 evidence_level_vocab 中(仅论文)无
20有用引用 ]]## Useful Quotes 下的引用块中包含泄露的 ]]无
21全文前群体日期早于 synthesis.prefulltext_cutoff 且没有全文级别印章的论文。INFOstub
22过期的全文前标记一个 ⚠ 其所属维基链接指向的论文已有全文印章,经过三次尾部豁免(正文说明、带日期的斜体注释、(N src 置信度)。确实存在误报无
23未填充的声明占位符匹配 unfilled_claim_patterns 的行(提到了来源但未写出声明)无
24已弃用的前置元数据键deprecated_frontmatter_keys 中的键(默认 journal 改为 venue);精确匹配,无误报无
25未引用的统计数字统计数字(numeric_claim_patterns)在半径内没有维基链接,分为 cited / block / methods / domain 类。INFO。无任何豁免stub;跳过引用块
26表格列数不匹配行单元格数与分隔行不一致的表格(唯一的结构检查)无
27乱码通过 encode('cp1252').decode('utf-8') 往返转换后结果不同的行无
28有印章但无 last_verified有 source_verification 但无 last_verified 的论文/书籍(对检查 15 的 stale 不可见)。INFO无
29仓库外别名链接指向 memory_slug_prefixes 中别名的维基链接,全仓库范围。除非列表非空,否则禁用memory_slug_exempt_files
30词汇同步_VOCABULARY.md 缺少某个活跃概念/方法(missing)或持有一条已删除笔记的行(ghost)。INFO;修复工具 /vocabulary-update无
31有印章但无文本最多 60 个字符的印章,且在任何通道中均无描述性的验证文本。INFO无
32配对无印章(笔记,在其知识状态块中引用的作品)配对中,来源笔记的印章未提及该笔记。阻塞性;声明为债务(seal_debt_file)者会报告但不计入声明的债务
33无标题或场所title 或 venue 为空的论文stub

调用方式

从仓库(向上查找最近的 wiki.config.json 作为配置):

python skills/wiki-lint/scripts/lint.py                 # 全部检查;列表输出到 _temp/
python skills/wiki-lint/scripts/lint.py --only 5,12     # 选定检查
python skills/wiki-lint/scripts/lint.py --self-test     # 夹具 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            # 需要 index_mode "manual" 且之前运行过 lint

标志、配置键以及每条检查写入的文件:references/cli-reference.md。

何时编辑什么

  • 新增维基文件夹(例如 datasets/):将其添加到 wiki.config.json 的 folders 中。它必须在笔记创建之前注册,否则指向它的每个链接都会被标记为损坏。
  • 新增状态值:将其添加到 lint.status_by_type.{type}。新增笔记类型:添加类型及其允许的状态。
  • 概念/方法的新字段:将别名添加到 field_titlecase_map。
  • 细化检查 4:lint.verb_list。放宽/收紧其容差:lint.defaults.unsourced_radius。
  • 新的占位符模式:lint.placeholder_wikilink_patterns(记住它仅适用于无法解析的目标)。
  • 某条检查应跳过存根:将其编号添加到 lint.stub_exempt_checks。
  • 开启语言雷达:将 examples/languages/es.json(或自己编写列表)复制到 lint.language_radar。
  • 新增一条检查:在 wikikit/lint/checks_*.py 中实现,将其计数器添加到 expected_counters.txt,添加可练习它的夹具,在 references/check-origins.md 中写入其条目。动机未记录在案的检查在首次看起来有噪音时就会被禁用。如果动机无法确定,请写入“未记录”;切勿凭空编造。

安全规则

  • Lint 对维基是只读的;它仅将每条检查的列表写入 --out-dir(默认 _temp/)。
  • fix.py 仅在报告位置(反向链接、状态)修改笔记,保持每个文件的行尾,并记录每次更改以便回滚。
  • 当不确定某个启发式更改是否正确时,先编写夹具,观察自检失败,然后再进行更改。
  • 缓存目录永不纳入版本控制(_temp/ 等始终留在 .gitignore 中)。版本化的度量值几个月后会被当作今天的数值来解读。

Individual skills in this repo

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

相关技能