mcpField
W
wiki-lint

wiki-lint

github.com/ar9av生产力3.6k3.5k 次安装1 天前更新
代码仓库

关于 wiki-lint

wiki-lint 是用于 Obsidian wiki 的健康审计技能,按结构、链接、元数据和内容可信度等方面检查问题,并给出修复方向。

主要功能

  1. 01检查孤立页面与失效链接
  2. 02检查必需的 frontmatter 字段
  3. 03发现陈旧内容与相互矛盾的说法
  4. 04核对索引、来源标记与标签聚类
  5. 05检查可见性标签和待提升页面

适用场景

  1. 01定期审计大型 Obsidian vault
  2. 02定位断链、孤立页和索引偏差
  3. 03检查来源标记与敏感信息分类

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ar9av/obsidian-wiki --skill wiki-lint

安装后在 Claude Code 中输入/wiki-lint确认已加载。

详细介绍

Wiki Lint — 健康审计

你正在对一个 Obsidian wiki 执行健康检查。目标是找出并修复会随着时间推移降低 wiki 价值的结构问题。

开始扫描之前: 遵循 llm-wiki/SKILL.md 中的 Retrieval Primitives 表。优先使用限定 frontmatter 的 grep 和锚定到章节的读取,而不是读取整页。在大型库中,盲目读取每个页面来执行 lint,正是这个框架旨在避免的做法。

开始之前

写作风格: 起草或改写自然语言 Markdown 之前,请阅读并遵循 llm-wiki/SKILL.md 中的 Writing Profile Resolution 章节。框架 schema、来源信息、安全要求和具体操作要求优先。 仅将 WRITING.md 中的偏好应用于生成的整合报告;确定性发现和修复须保留其现有格式。

  1. 解析配置 — 遵循 llm-wiki/SKILL.md 中的 Config Resolution Protocol(内联 @name 覆盖 → 从 CWD 向上查找 .env → 全局配置 → 提示设置)。由此获取 OBSIDIAN_VAULT_PATH,以及任何 OBSIDIAN_ALLOWED_LIFECYCLES、OBSIDIAN_ALLOWED_RELATIONSHIP_TYPES、OBSIDIAN_REQUIRED_TRUST_FIELDS 和 OBSIDIAN_SCHEMA_SOURCE 值。
  2. 读取所有者规则 — 如果 $OBSIDIAN_VAULT_PATH/AGENTS.md 存在,请在解释任何 schema 之前阅读。所有者规则优先于框架默认值。
  3. 确定有效 schema — 记录 schema 来源定位符,以及有效的必需/可选 frontmatter、生命周期值、关系类型和来源标记。框架值为默认值;准确保留所有者扩展和放宽的必需项。绝不将所有者类型强制转换为框架类型。
  4. 读取 index.md,获取完整页面清单
  5. 读取 log.md,了解近期活动背景

将有效 schema 显式传递给确定性检查。例如,使用 --allow-lifecycle / --allow-relationship-type 添加每项所有者扩展,使用可重复的 --required-trust-field 替换信任字段必需项,并使用 --schema-source "$OBSIDIAN_VAULT_PATH/AGENTS.md" 指定权威来源。JSON 报告的 schema 区块必须与发现问题获认可之前确定的 schema 一致。

Schema 优先级为 CLI 标志 > 已解析的环境/配置值 > 框架默认值;生命周期和关系扩展采用累加方式。使用前移除所有覆盖值。显式配置为空或仅含空格的值,以及逗号分隔列表中的任何空项,均视为失败关闭;绝不能将其视为有效的生命周期、关系类型、必需字段或权威来源定位符。若要使用默认值,请移除相应变量。

当 obsidian-wiki 位于 PATH 中时,优先使用 obsidian-wiki lint "$OBSIDIAN_VAULT_PATH" --json(并使用上述相同的 schema 覆盖标志),将 JSON 中的 findings 纳入健康报告。如果 CLI 不可用,则继续执行下方基于 grep 的检查——不要求必须有该二进制文件。

如果 JSON 报告包含 findings.snapshot_mismatch,请在报告中列出这些页面。缺少或已漂移的 snapshots: 不属于缺少必需 frontmatter(第 3 节仍仅涵盖 title、category、tags、sources、created、updated)。不要为了修复快照漂移而改写 sources:。运行 obsidian-wiki snapshots apply --from-json <lint.json>(试运行),展示预览,并且只有在用户明确确认后才传入 --apply。应用时会写入带引号的 "[[_raw/_archived/stem|stem]]" 列表项(带显示文本的原生 Property 链接)。wiki-lint --consolidate 仍不会应用此项发现。

Lint 检查

按顺序运行以下检查。发现问题时随时报告。

范围: 每项检查都跳过 _archives/、_raw/、_readouts/ 和 .obsidian/。这些目录存放冻结快照、未经处理的暂存草稿和派生的 readout(由 wiki-narrate 保存)——它们不是知识图谱页面,因此孤立页面、frontmatter 和链接检查不适用于这些目录。

1. 孤立页面

查找没有任何传入维基链接的页面。这些知识孤岛没有任何内容与之相连。

检查方法:

  • 使用 Glob 搜索库中的所有 .md 文件
  • 对每个页面,在库的其余部分中使用 Grep 搜索 [[page-name]] 引用
  • 没有传入链接的页面(index.md 和 log.md 除外)即为孤立页面

修复方法:

  • 确定哪些现有页面应链接到该孤立页面
  • 在合适的章节中添加维基链接
2. 失效的维基链接

查找指向不存在页面的 [[wikilinks]]。

检查方法:

  • 在所有页面中使用 Grep 搜索 \[\[.*?\]\]
  • 提取链接目标:删除第一个 |(别名)或 #(标题/块锚点)及其后的所有内容,并去掉表格单元格中转义的 \| 留下的末尾反斜杠
  • 如果目标的扩展名属于附件类型(.png、.jpg、.gif、.svg、.webp、.pdf、.canvas、.base、音频和视频),则跳过该目标:它是嵌入内容,而不是页面链接,在此检查所比对的 .md 清单中没有对应条目
  • 不要把每个点都当作扩展名:[[Node.js]]、[[Next.js]] 和 [[v1.2 release notes]] 都是页面链接,只是名称中恰好带点;剔除它们既会漏掉真正的失效链接,也会让目标页面看起来像孤立页面
  • 从剩余内容中去掉明确的 .md 后缀,然后检查是否存在对应的 .md 文件

修复方法:

  • 如果目标已重命名,更新链接
  • 如果目标应该存在,创建该页面
  • 如果链接有误,删除或更正
3. 缺少 Frontmatter

每个页面都应包含:标题、分类、标签、来源、创建时间、更新时间。

检查方法:

  • 使用 Grep 搜索 frontmatter 块(范围限定为文件开头的 ^---),而不是完整读取每个页面
  • 标记缺少必填字段的页面

修复方法:

  • 添加缺失字段并填写合理的默认值
3a. 缺少摘要(软性警告)

每个页面都应包含 summary: frontmatter 字段,内容为 1–2 句话,≤200 个字符。轻量级检索(例如 wiki-query 的仅索引模式)会读取此字段,以避免打开页面正文。

检查方法:

  • 使用 Grep 搜索库中 frontmatter 内的 ^summary:
  • 标记缺少该字段的页面,但仅作为软性警告,而不是错误——较早创建、尚未添加此字段的页面没有问题;此检查旨在提醒内容导入技能在新写入时补充该字段。
  • 也要标记摘要超过 200 个字符的页面。

修复方法:

  • 重新导入该页面,或手动撰写简短摘要(用 1–2 句话概括页面内容)。
4. 过时内容

updated 时间戳相较于来源较旧的页面。

检查方法:

  • 将页面的 updated 时间戳与来源文件的修改时间进行比较
  • 标记来源文件的修改时间晚于页面最近更新时间的页面

未标注日期的声明(行级)。 obsidian-wiki lint 会报告 undated_claims:陈述可能过时的数量或金额(星标数、用户数、客户数、下载量、交易额、MRR/ARR)且该行未标注日期。位于带日期标题下的行、journal/ 中的页面、名称为 YYYY-MM-… 的页面、代码和引用块均不在此列。此项仅为警告,不会导致失败。对于每一项,请重新核实数字并标注 (as of YYYY-MM-DD),或将其替换为指向实时数字所在位置的链接,或将其移至带日期的标题下作为历史记录。

5. 矛盾

不同页面之间相互冲突的说法。

检查方法:

  • 这需要阅读相关页面并比较其中的说法
  • 优先检查标签相同或相互引用频繁的页面
  • 留意 “however”、“in contrast”、“despite” 等短语,它们可能表示已有记录的矛盾,也可能表示尚未记录的矛盾

修复方法:

  • 添加一个“未决问题”章节,说明矛盾
  • 引用双方来源及其说法
6. 索引一致性

验证 index.md 是否与实际页面清单一致。

检查方法:

  • 将 index.md 中列出的页面与磁盘上的实际文件进行比较
  • 检查 index.md 中的摘要是否仍与页面内容一致
7. 来源标注偏移

检查页面是否如实反映内容中推断与提取部分的比例。请参阅 llm-wiki 中的“来源标记”部分,了解相关约定。

检查方法:

  • 对于包含 provenance: 块或任何 ^[inferred]/^[ambiguous] 标记的每个页面,统计句子/项目符号的数量,以及各标记结尾的数量
  • 计算大致占比(extracted、inferred、ambiguous)
  • 应用以下阈值:
    • AMBIGUOUS > 15%:标记为“推测内容占比高”——即使只有 1/7 的主张确实存在不确定性,也说明该页面需要更严格的来源标注,或应移至 synthesis/
    • INFERRED > 40% 且 frontmatter 中没有 sources::标记为“无来源的综合内容”——页面正在建立关联,却没有任何可引用的来源
    • 枢纽页面(按入站 wikilink 数量排名前 10)中 INFERRED > 20%:标记为“流量较大的页面,来源标注存疑”——枢纽页面中的错误会传播到所有链接到它的页面
    • 偏移:如果页面有 provenance: frontmatter 块,当任何字段与重新计算的值相差超过 0.20 时,予以标记
  • 跳过没有 provenance: frontmatter 且没有标记的页面——按约定视为内容全部提取自来源

修复方法:

  • 对于模糊内容占比较高的页面:从来源重新摄取内容,厘清不确定的主张,或将推测性内容拆分到 synthesis/ 页面
  • 对于无来源的综合内容:在 frontmatter 中添加 sources:,或明确将页面标记为综合内容
  • 对于 INFERRED > 20% 的枢纽页面:优先重新摄取内容——这类页面中的错误影响范围最广
  • 对于偏移:更新 provenance: frontmatter,使其与重新计算的值一致
8. 标签簇碎片化

检查共享标签的页面是否彼此链接。标签意味着主题簇;如果这些页面互不引用,该簇就会碎片化,形成彼此隔离的知识孤岛,而它们本应相互串联。

检查方法:

  • 对于出现于 ≥ 5 个页面的每个标签:
    • n = 带有此标签的页面数量
    • actual_links = 此标签组中任意两个页面之间的 wikilink 数量(检查两个方向)
    • cohesion = actual_links / (n × (n−1) / 2)
  • 对于 cohesion < 0.15 且 n ≥ 5 的标签组,予以标记

修复方法:

  • 对碎片化的标签运行 cross-linker 技能——它会找出并补充缺失的链接
  • 如果标签组很大(n > 15)且仍然碎片化,可考虑将其拆分为更具体的子标签
9. 可见性标签一致性

检查 visibility/ 标签是否正确应用,以及是否在重要页面中被遗漏。

检查方法:

  • **未标记的 PII 模式:**对页面正文执行 Grep,查找通常表示敏感数据的模式——包含 password、api_key、secret、token、ssn、email:、phone: 且后面跟有实际值(而非字段说明)的行。如果页面匹配且缺少 visibility/pii 或 visibility/internal,则将其标记为可能的分类错误。
  • **缺少 sources: 的 visibility/pii:**带有 visibility/pii 标签的页面应始终包含 sources: frontmatter 字段——如果没有来源,就无法验证分类。标记任何缺少 sources: 的 visibility/pii 页面。
  • 分类体系中的可见性标签:visibility/ 标签是系统标签,不得出现在 _meta/taxonomy.md 中。如果在其中发现这些标签,则标记为配置错误——它们会计入包含这些标签的页面的 5 标签上限。

修复方法:

  • 对于未标记的 PII 模式:在页面的 frontmatter 标签中添加 visibility/pii(如果内容属于团队上下文而非个人数据,则添加 visibility/internal)
  • 对于缺少 sources: 的页面:添加来源信息,或升级给用户处理——不要自动填充
  • 对于分类体系污染:从 _meta/taxonomy.md 中移除 visibility/ 条目
10. 杂项晋升候选项

查找 misc/ 中项目关联度已足够高、可以晋升的页面。

检查方法:

  • Glob $OBSIDIAN_VAULT_PATH/misc/*.md
  • 对每个页面,读取 affinity frontmatter 字段
  • 标记任一单个项目得分 ≥ 3 的页面

修复方法:

  • 如果关联度得分看起来已过时(例如,页面有许多 wikilinks,但 affinity: {}),先运行 cross-linker skill
  • 要晋升页面:将其移至 projects/<project-name>/references/(或其他合适的类别),更新其 category frontmatter,移除 promotion_status,并使用 grep 搜索知识库中的反向链接并更新它们
12. 置信度与生命周期 Schema

强制执行置信度与生命周期 frontmatter schema(参见 llm-wiki/SKILL.md 的 Confidence and Lifecycle 部分)。

两种模式:

  • --check(默认,只读)——报告错误和警告
  • --consolidate——可以应用单独批准的结构维护,但绝不重写 base_confidence

置信度是一种语义判断。确定性工具无法仅凭源字符串推断独立证据链或整页声明覆盖情况。因此,置信度自动化会验证经过明确批准的手动信任账本;它绝不会以 URL 计数替代审核。

规则 12a——lifecycle 枚举验证

**检查方法:**在所有页面的 frontmatter 中搜索 ^lifecycle:。标记有效生命周期集合之外的任何值(框架默认值:{draft, reviewed, verified, disputed, archived})。

**修复方法:**不适用(只能由人工设置生命周期状态)

规则 12b——base_confidence 范围

**检查方法:**在所有页面的 frontmatter 中搜索 ^base_confidence:。标记所有超出 [0.0, 1.0] 范围的现有值;仅当生效的所有者 schema 要求此字段时,才标记字段缺失。

**修复方法:**不适用(值错误意味着 skill 计算有误——应交由人工更正)

规则 12c——过时页面报告(计算覆盖层)

过时状态绝不存储——而是在读取时计算:is_stale = (today − updated) > 90 days。

**检查方法:**对于每个页面,从 frontmatter 读取 updated: 并计算 is_stale。如果页面过时,也检查 lifecycle:。报告:

  • lifecycle: verified 的过时页面,并附加更醒目的标注(这是最危险的情况——高信任度页面可能有误)
  • 所有其他过时页面,作为常规警告报告

修复方法:--fix 不会重写 lifecycle。重新摄取时更新 updated,过时状态便会自动清除。

规则 12c-2——非法生命周期转换

生命周期枚举是一个状态机,不是自由格式的标签。obsidian-wiki lint 会将每个页面当前的 lifecycle 与其上次审核时记录在 _meta/trust-ledger.json 中的值进行比较,并报告 illegal_lifecycle_transitions。

**标记:**任何回退到 draft 的状态(只有摄取操作会设置 draft),以及任何退出 archived 的转换(这是终止状态——恢复操作需要由人工有意删除并重新创建)。

不标记:draft → verified。账本快照并不完整,两次审核之间可能发生过合法的中间状态 reviewed;标记这种情况会误报有效历史记录。

默认发出警告;使用 --strict-trust 时则会失败。账本条目早于 lifecycle 字段的页面没有基线,将被静默跳过。

**修复方法:**不适用——页面沿禁止的路径转换,意味着 skill 在不应写入 lifecycle 时写入了该字段,或者需要记录一次人工转换。应交由人工处理。

规则 12d——替代关系完整性

**检查方法:**对于每个设有 superseded_by: "[[target]]" 的页面:

  • 验证目标页面存在
  • 验证目标页面本身未归档(不得存在循环或链式替代)
  • 验证不存在循环(A 替代 B,而 B 又替代 A)
  • 如果设置了 superseded_by,但 lifecycle != archived,则发出警告(状态不一致)

**修复方法:**不适用——标记后交由人工处理

规则 12e — 置信度审查完整性

检查方法: 首先运行确定性台账验证器:

obsidian-wiki trust-check "$OBSIDIAN_VAULT_PATH" --strict --json --pretty

在 CI 和定时门禁中使用 --strict:过期、未审查或缺少页面的警告会导致返回非零状态。不使用 --strict 时,trust-check 仍是只读报告命令,只有遇到硬性台账错误或分数不匹配时才会返回非零状态。

已批准的台账位于 _meta/trust-ledger.json。每个条目都记录人工审查的分数,以及页面实质内容和证据元数据的 SHA-256 指纹。该指纹不包含易变的记录字段(updated、base_confidence 和生命周期转换字段),因此仅修改时间戳不会重新触发审查。

结果解读如下:

  • reviewed — 当前实质内容指纹和存储分数都与已批准的审查相符;不要根据源字符串重新计算。
  • stale — 正文、摘要、来源、溯源信息、标签或关系发生了变化;请重新进行人工溯源和声明覆盖率审查。
  • unreviewed — 页面没有已批准的台账条目;必须进行人工审查。
  • score_mismatches — 实质内容仍然相符,但存储的 base_confidence 与已批准的值不同;Lint 必须失败。
  • errors — 台账数据格式错误或缺失;Lint 必须失败。

对于单独批准的全知识库审查,请明确记录已接受的状态:

obsidian-wiki trust-record "$OBSIDIAN_VAULT_PATH" \
  --all --reviewed-at "<ISO-8601 timestamp>" --approved --json --pretty

单独批准仅针对特定过期或未审查页面的审查后,只更新这些条目:

obsidian-wiki trust-record "$OBSIDIAN_VAULT_PATH" \
  --page "concepts/example.md" --page "skills/example.md" \
  --reviewed-at "<ISO-8601 timestamp>" --approved --json --pretty

--approved 表示人工已批准所有要记录的分数。这是工作流断言,而非加密签名:请将 _meta/trust-ledger.json 纳入版本控制,并要求合并台账变更前进行人工差异审查。只有在完成全知识库审查后,才可使用 --all;对于部分审查,请使用可重复的 --page,以便其他无关的过期页面继续保持待处理状态。切勿仅为消除警告而运行 trust-record。

过期或未审查页面的人工重新计算流程:

  1. 将页面拆解为实质性声明,并将每项声明对应到证据。
  2. 将相互依赖的证据归并为独立溯源链:来自同一代码仓库的文件/提交、同一任务链中的重试、快照及其捕获的来源、重复记忆,以及父子任务都只计一次。
  3. 使用 llm-wiki 的分档,对每条独立溯源链评定审查质量。
  4. 计算原始基础分数,然后评估整页的声明覆盖率。该公式是起点,而非自动目标。
  5. 将结果分类为 raise、keep、lower 或 repair first;更改 base_confidence 或刷新台账前必须获得批准。

修复方法: 置信度没有自动修复方式。仅应用明确批准的精确补丁,验证其范围,然后只刷新已审查的台账状态。--consolidate 绝不能重写 base_confidence。

当前执行规则

在框架默认设置下,每个非保留内容页面都必须包含一个 [0.0, 1.0] 范围内的有限 base_confidence,以及有文档记录的生命周期值。所有者架构可以放宽其中任一字段;但仍会验证已有值。信任字段缺失或格式错误、台账数据格式错误,以及缺少必需的台账,均属于硬性错误。具有有效信任字段但没有已批准台账条目的新页面会被标记为 unreviewed;已批准页面的实质性变更会被标记为 stale。

输出补充

添加到 Wiki 健康报告:

### Confidence/Lifecycle Issues (N found)
- `concepts/foo.md` — missing `lifecycle` field (warning: Phase 1)
- `entities/bar.md` — `lifecycle: stalestate` is not a valid enum value
- `concepts/scaling.md` — `base_confidence: 1.4` is out of range [0.0, 1.0]
- `synthesis/old-analysis.md` — STALE (last updated 2025-10-01, 182 days ago) lifecycle=verified ⚠️ HIGH PRIORITY
- `concepts/outdated.md` — STALE (last updated 2025-11-15, 137 days ago) lifecycle=draft
- `entities/tool-v1.md` — `superseded_by: [[entities/tool-v2]]` but lifecycle=draft (expected archived)
- `concepts/drift-example.md` — confidence review stale: material fingerprint changed; manual lineage + coverage review required
- `entities/mismatch.md` — confidence mismatch: stored=0.80, approved=0.59

追加到 LINT 日志条目:

- [TIMESTAMP] LINT ... lifecycle_issues=N
13. 类型化关系有效性

验证 relationships: 前置元数据块。跳过没有 relationships: 块的页面——该字段为可选项。

框架默认类型: extends、implements、contradicts、derived_from、uses、replaces、related_to。应用所有者扩展后,根据有效类型集合进行验证。

检查方法:

  • 在所有知识库页面的前置元数据中搜索 ^relationships:
  • 对每个包含 relationships: 块的页面,读取其前置元数据(而非完整页面正文)
  • 对块中的每个条目:
    1. 类型验证——标记任何不在上述允许集合中的 type: 值
    2. 目标失效——从 target: 字符串中去掉 [[ 和 ]],然后进行规范化(转为小写、空格替换为连字符、去掉 .md),并检查知识库中该路径下是否存在 .md 文件。标记无法解析的目标。 规范化前,删除第一个 |(别名)或 #(标题/区块锚点)及其后的所有内容:管道别名或标题锚点目标不会仅仅因为字面括号内容与文件名不匹配而被视为失效。
    3. 自引用——标记已解析目标与页面自身节点 ID 相同的条目

修复方法:

  • 无效类型:报告该值和有效架构来源。仅当该类型既不存在于框架默认类型中,也不存在于所有者扩展中时才进行修正;绝不要将有效的所有者类型替换为 related_to。
  • 目标失效:更新或移除该条目;如果目标页面应当存在,请先创建该页面
  • 自引用:移除该条目

输出补充:

### Typed Relationship Issues (N found)
- `concepts/foo.md` — relationships[1]: type "contradication" is not an allowed type (did you mean "contradicts"?)
- `concepts/bar.md` — relationships[0]: target "[[skills/nonexistent-skill]]" resolves to no page in vault
- `entities/baz.md` — relationships[2]: self-reference (target resolves to this page's own id)

追加到 LINT 日志条目中:

... relationship_issues=N
14. 事件时间有效性

验证前置元数据中的 valid_from / valid_until / superseded_by。这三项均为可选字段——跳过不包含其中任何字段的页面。

created / updated 是录入时间;这三项是事件时间,表示声明本身成立的时间。valid_until 已过期的页面是历史页面,并非错误页面:它会继续保留在知识库和图谱中,只是不再出现在默认检索结果中。

检查方法:

  • 在所有知识库页面的前置元数据中搜索 ^valid_from:、^valid_until:、^superseded_by:
  • 对每个包含其中任意字段的页面:
    1. 日期可解析性——每个值必须为 YYYY-MM-DD 或完整的 ISO 8601 时间戳。标记其他格式。
    2. 时间窗口顺序——标记任何 valid_until 早于 valid_from 的页面
    3. 悬空后继页面——从 superseded_by 中去掉 [[/]],删除第一个 | 或 # 及其后的所有内容,去掉 .md,再进行规范化,并检查页面是否存在。标记无法解析的目标和自引用。

obsidian-wiki lint 会将这三类问题分别报告为 temporal_errors(日期、时间窗口)和 superseded_dangling(后继页面)。使用方括号的悬空后继页面也会出现在 broken_links 中。

日期错误为何会导致失败而非警告: 检索会将无法解析的时间窗口视为当前有效,因此未报告的笔误会让过时的声明被当作事实返回——这正是这些字段旨在防止的问题。

修复方法:

  • 无法解析的日期:改写为 YYYY-MM-DD;如果实际日期未知,请移除该字段,而不是猜测
  • 时间窗口颠倒:根据页面来源确认哪个日期有误;绝不要不加说明地交换日期
  • 悬空后继页面:创建替代页面、修正指针;如果该声明没有替代内容,则移除该字段
  • 绝不要通过将历史页面改写为当前有效来“修复”它——这会破坏时间窗口旨在保留的记录

输出补充:

### Event-Time Issues (N found)
- `references/gateway-nginx.md` — valid_until (2026-04-01) precedes valid_from (2026-05-01)
- `references/old-limits.md` — valid_until "soon" is not a date
- `references/legacy-auth.md` — superseded_by "[[oauth-rollout]]" resolves to no page in vault

追加到 LINT 日志条目中:

... temporal_issues=N
11. 综合分析缺口

找出 Wiki 中缺失的高价值综合分析机会——在多个页面中共同出现、但没有 synthesis/ 页面将其关联起来的概念对。

检查方法:

  • 列出 synthesis/ 中的所有页面,收集每个页面已涵盖的概念对(根据其 [[wikilinks]] 或标题)
  • 从 concepts/ 和 entities/ 中挑选 10-15 个经常被链接的概念
  • 对每一对概念,快速运行 grep,统计同时链接到这两个概念的页面数量:
    rg -l --glob '*.md' "\[\[ConceptA\]\]" "$OBSIDIAN_VAULT_PATH" > /tmp/a.txt
    rg -l --glob '*.md' "\[\[ConceptB\]\]" "$OBSIDIAN_VAULT_PATH" > /tmp/b.txt
    comm -12 <(sort /tmp/a.txt) <(sort /tmp/b.txt) | wc -l
    
  • 标记共同出现次数 ≥ 3 且没有现有综合分析页面的概念对

修复方法:

  • 运行 /wiki-synthesize,自动发现并填补最重要的缺口

输出格式

以结构化列表的形式报告发现:

## Wiki Health Report

### Orphaned Pages (N found)
- `concepts/foo.md` — no incoming links

### Broken Wikilinks (N found)
- `entities/bar.md:15` — links to [[nonexistent-page]]

### Missing Frontmatter (N found)
- `skills/baz.md` — missing: tags, sources

### Stale Content (N found)
- `references/paper-x.md` — source modified 2024-03-10, page last updated 2024-01-05
- `projects/foo.md:28` — undated claim: "GitHub: 6★" (stamp it, link it, or date the heading)

### Contradictions (N found)
- `concepts/scaling.md` claims "X" but `synthesis/efficiency.md` claims "not X"

### Index Issues (N found)
- `concepts/new-page.md` exists on disk but not in index.md

### Missing Summary (N found — soft)
- `concepts/foo.md` — no `summary:` field
- `entities/bar.md` — summary exceeds 200 chars

### Provenance Issues (N found)
- `concepts/scaling.md` — AMBIGUOUS > 15%: 22% of claims are ambiguous (re-source or move to synthesis/)
- `entities/some-tool.md` — drift: frontmatter says inferred=0.10, recomputed=0.45
- `concepts/transformers.md` — hub page (31 incoming links) with INFERRED=28%: errors here propagate widely
- `synthesis/speculation.md` — unsourced synthesis: no `sources:` field, 55% inferred

### Fragmented Tag Clusters (N found)
- **#systems** — 7 pages, cohesion=0.06 ⚠️ — run cross-linker on this tag
- **#databases** — 5 pages, cohesion=0.10 ⚠️

### Visibility Issues (N found)
- `entities/user-records.md` — contains `email:` value pattern but no `visibility/pii` tag
- `concepts/auth-flow.md` — tagged `visibility/pii` but missing `sources:` frontmatter
- `_meta/taxonomy.md` — contains `visibility/internal` entry (system tag must not be in taxonomy)

### Misc Promotion Candidates (N found)
Pages in misc/ that have ≥ 3 connections to a single project and are ready to be promoted:

| Page | Top Project | Affinity Score |
|---|---|---|
| `misc/web-martinfowler-articles-microservices.md` | `obsidian-wiki` | 4 |

### Typed Relationship Issues (N found)
- `concepts/foo.md` — relationships[1]: type "contradication" is not an allowed type
- `concepts/bar.md` — relationships[0]: target "[[skills/nonexistent]]" resolves to no page

### Synthesis Gaps (N found)
Concept pairs that co-occur frequently but have no synthesis page:

| Pair | Co-occurrence | Suggested Action |
|---|---|---|
| [[Caching]] × [[Consistency]] | 5 pages | Run `/wiki-synthesize` |
| [[Testing]] × [[Observability]] | 3 pages | Run `/wiki-synthesize` |

检查后

在 log.md 中追加:

- [TIMESTAMP] LINT issues_found=N orphans=X broken_links=Y stale=Z contradictions=W prov_issues=P missing_summary=S fragmented_clusters=F visibility_issues=V promotion_candidates=C synthesis_gaps=G relationship_issues=R

主动提出自动修复问题,或让用户决定要处理哪些问题。


整合模式(--consolidate)

由 wiki-lint --consolidate 触发。从仅报告切换为执行并报告——定期运行的“梦境循环”,让 Wiki 自我修复。

安全协议

始终先进行试运行。 写入任何内容之前:

  1. 运行全部 12 项检查(步骤 1–12)。
  2. 以结构化列表形式打印计划执行的整合操作(见下方“试运行输出”)。
  3. 询问用户:"Apply these N changes? [yes / no / select]"。
  4. 仅在获得明确确认后才开始写入。如果用户选择单项操作,则只执行这些操作。
  5. 切勿合并页面——使用 wiki-dedup 执行此操作。只添加链接、提升、降级和标记。此处切勿处理 snapshot_mismatch;该问题由 snapshots CLI 处理,并有单独的确认流程(见“开始之前”)。
整合操作(确认后按顺序执行)

写入前快照——首次写入文件之前,检查 Vault 本身是否为 Git 仓库的根目录。仅仅是更大仓库的子目录并不符合条件:在那里运行 git add -A 可能会包含无关文件。如果 Vault 不是独立的 Git 仓库,则静默跳过此步骤——不要提醒,也不要建议运行 git init。

VAULT_REAL_PATH=$(cd "$OBSIDIAN_VAULT_PATH" && pwd -P)
VAULT_GIT_ROOT=$(git -C "$OBSIDIAN_VAULT_PATH" rev-parse --show-toplevel 2>/dev/null || true)
SNAPSHOT_SHA=""

if [ -n "$VAULT_GIT_ROOT" ] && [ "$VAULT_GIT_ROOT" = "$VAULT_REAL_PATH" ]; then
  if git -C "$OBSIDIAN_VAULT_PATH" diff --quiet \
    && git -C "$OBSIDIAN_VAULT_PATH" diff --cached --quiet \
    && [ -z "$(git -C "$OBSIDIAN_VAULT_PATH" ls-files --others --exclude-standard)" ]; then
    SNAPSHOT_SHA=$(git -C "$OBSIDIAN_VAULT_PATH" rev-parse HEAD)
  else
    if ! git -C "$OBSIDIAN_VAULT_PATH" add -A; then
      echo "Pre-write snapshot failed; abort the skill without writing any vault files." >&2
      exit 1
    fi
    if ! git -C "$OBSIDIAN_VAULT_PATH" commit -m "pre-wiki-lint snapshot" --quiet; then
      echo "Pre-write snapshot failed; abort the skill without writing any vault files." >&2
      exit 1
    fi
    SNAPSHOT_SHA=$(git -C "$OBSIDIAN_VAULT_PATH" rev-parse HEAD)
  fi
fi

干净仓库分支会刻意避免调用 git commit,因此“没有要提交的内容”不会被视为错误。如果 git add 或 git commit 失败,则应在编辑 Vault 之前停止;切勿在没有创建承诺的快照时继续操作。

如果 SNAPSHOT_SHA 非空且此技能写入了文件,则在最终报告中包含该 SHA。若要撤销整个运行,在确认没有后续变更值得保留后,用户可以运行:

git -C "$OBSIDIAN_VAULT_PATH" reset --hard "$SNAPSHOT_SHA"
git -C "$OBSIDIAN_VAULT_PATH" clean -fd
操作 1:修复失效的 wikilink

对于检查 2 中发现的每个失效 [[Target]]:

  • 在 Vault 中搜索标题或文件名最接近的页面(使用 Grep 搜索 index.md 中的标题)
  • 如果存在唯一的最佳匹配(编辑距离 ≤ 2 个字符或根词相同):重写链接。注明重写内容:[[Oringal]] → [[corrected-page]]。
  • 如果没有匹配项或匹配不明确:将其转换为纯文本(~~[[Target]]~~ → Target)并添加注释 ``。
  • 切勿仅为满足失效链接而创建新页面。
操作 2:为孤立页面添加缺失的交叉引用

对于检查 1 中发现的每个孤立页面(零个入链):

  • 使用 grep 在 Vault 正文中搜索对该页面标题或别名的提及(不区分大小写)。
  • 对于在其他页面中找到的每处提及,使用 [[wikilink]] 替换纯文本提及。
  • 每个孤立页面最多插入 3 处链接——不要在页面中大量添加链接。
  • 此操作仅针对孤立页面(与广泛运行的 cross-linker 不同)。
操作 3:修正生命周期状态

自动应用以下规则(这些规则不需要人工判断——它们用于执行已记录的状态机):

  • 将 draft 晋升为 reviewed: 对于 lifecycle: draft、created 距今超过 30 天且 base_confidence > 0.7 的页面。设置 lifecycle: reviewed、lifecycle_changed: <today>、lifecycle_reason: "auto-promoted by wiki-lint --consolidate: age>30d, confidence>0.7"。
  • 将 verified 降级为 stale: 这不是状态转换——stale 是计算得出的叠加状态,而非生命周期值。对于 is_stale = (today − updated) > 180 days 的已验证页面,在页面正文顶部添加提示:> ⚠️ **Stale**: This page was last updated <date>. Verify before relying on it. 仅在尚未存在该提示时添加。
  • 不要将 reviewed 更改为 verified 或进行任何其他状态转换——这些操作仅限人工执行。
操作 4:降级层级

对于 tier: supporting(或未设置)、传入链接数为 0 且 90 天或更久未更新的页面:

  • 设置 tier: peripheral。
  • 输出降级列表,供用户审核。
  • 不要自动降级 tier: core 页面——这些页面是手动设置的。
操作 5:规范化标签

读取 _meta/taxonomy.md 获取别名映射(例如,ml → machine-learning)。对于每个页面,在 tags: frontmatter 字段中将已知别名替换为其规范形式。这只是 tag-taxonomy 工作的一部分——仅修正别名,不进行完整审核。

操作 6:添加矛盾提示

对于每对标记为相互矛盾的页面(通过 frontmatter 中的 relationships: contradicts 标记,或在检查 5 中标记):

  • 检查相关论点附近是否已存在 > ⚠️ Contradiction flagged with [[Other Page]] 提示。
  • 如果没有,将其添加到“Key Ideas”章节末尾(如果没有“Key Ideas”章节,则添加到“Open Questions”之前)。保持简洁——一行即可。
  • 不要解决矛盾;只需在视觉上标记。
操作 7:撰写整合报告

完成所有操作后,将报告写入 synthesis/consolidation-<YYYY-MM-DD>.md:

---
title: Consolidation Report <YYYY-MM-DD>
category: synthesis
tags: [maintenance, consolidation]
sources: []
summary: Auto-generated consolidation report from wiki-lint --consolidate run on <date>.
lifecycle: draft
lifecycle_changed: <date>
tier: peripheral
created: <obsidian-wiki memory now>
updated: <obsidian-wiki memory now>
---

# Consolidation Report — <YYYY-MM-DD>

## Summary
- Broken links fixed: N
- Cross-references added: M
- Lifecycle states updated: K
- Tier demotions: D
- Tags normalized: T
- Contradiction callouts added: C

## Broken Link Fixes
- `concepts/foo.md:12` — [[OldTarget]] → [[correct-target]]
- `entities/bar.md:8` — [[Missing]] → `Missing` (no match found)

## Cross-References Added (orphan rescue)
- `concepts/baz.md` — now linked from: [[concepts/alpha]], [[skills/beta]]

## Lifecycle Updates
- `concepts/old-draft.md` — draft → reviewed (age 45d, confidence 0.74)
- `synthesis/stale-verified.md` — stale callout added (last updated 2025-10-01)

## Tier Demotions
- `concepts/unused-concept.md` — supporting → peripheral (0 links, 120 days stale)

## Tag Normalizations
- `entities/some-tool.md` — `ml` → `machine-learning`

## Contradiction Callouts
- `concepts/scaling.md` — flagged contradiction with [[synthesis/efficiency]]
试运行输出(在写入任何内容前显示)
wiki-lint --consolidate — Dry Run

Planned actions (N total):
[1] Fix broken link: concepts/foo.md:12 [[OldTarget]] → [[correct-target]]
[2] Add cross-ref: concepts/baz.md ← [[concepts/alpha]] (orphan rescue)
[3] Lifecycle: concepts/old-draft.md → reviewed (age 45d, confidence 0.74)
[4] Tier demotion: concepts/unused.md → peripheral (0 links, 112 days stale)
[5] Tag alias: entities/some-tool.md: ml → machine-learning
[6] Contradiction callout: concepts/scaling.md ↔ [[synthesis/efficiency]]

Apply these 6 changes? [yes / no / select by number]
consolidate 模式的日志条目
- [TIMESTAMP] LINT_CONSOLIDATE links_fixed=N orphans_rescued=M lifecycle_updates=K tier_demotions=D tag_fixes=T contradiction_callouts=C report=synthesis/consolidation-YYYY-MM-DD.md

写入 Vault 后刷新 QMD

QMD 是搜索索引,不是真实数据源。如果 $QMD_WIKI_COLLECTION 为空或未设置,请跳过此步骤。仅在此技能写入或重写 Vault Markdown 后运行。如果 QMD 刷新失败,不要回滚 Vault 更改;应单独报告 QMD 状态。

如果已设置 $QMD_CLI,则使用它;否则使用 qmd。

${QMD_CLI:-qmd} update

如果输出显示需要向量或嵌入可能已过时,请运行:

${QMD_CLI:-qmd} embed

通过以下任一方式验证集合:

${QMD_CLI:-qmd} ls "$QMD_WIKI_COLLECTION"

或者,在已知特定页面路径时:

${QMD_CLI:-qmd} get "qmd://$QMD_WIKI_COLLECTION/<page>.md" -l 5

记录以下一项:

  • QMD refreshed: update + embed + verified
  • QMD refreshed: update only + verified
  • QMD skipped: QMD_WIKI_COLLECTION unset
  • QMD skipped: qmd CLI unavailable
  • QMD failed: <short error summary>

评论

支持 Markdown