关于 lint
lint 是一项 wiki 维护技能,检查代码与 wiki 的偏差,以及链接、索引、过时声明和不一致问题。它只自动处理有限的问题,并将矛盾等标记项留给人工判断。
主要功能
- 01优先检查代码与 wiki 的偏差
- 02查找孤立页面和缺失链接
- 03检测矛盾与过时声明
- 04修复缺失链接和索引条目
- 05报告健康指标但不阻断流程
适用场景
- 01多次 ingest 后检查 wiki 状态
- 02代码变更后核对文档
- 03标记矛盾声明供人工审查
- 04查找缺少链接或索引条目的页面
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ rheinmir/ setup --skill lint安装后在 Claude Code 中输入/lint确认已加载。
详细介绍
技能:lint
内容
用途与上下文
- 用途: 定期检查 wiki 健康状况——孤立页面、缺失链接、矛盾、过时内容(wiki→wiki 和 code→wiki 漂移)、索引缺口;以确定性的 no-op 门禁开头(wiki-sync,0 token)。
- 触发条件(何时调用): 每 ingest 10 次后,或 wiki 过时/不一致时,或 session_start 报告
[wiki-sync] code 已变更 N 个 commit。 - 非目标: 两个页面矛盾时不选边(标记并交由人工处理);不自行猜测
shortcut:标记的升级触发条件;不自行移动 draft(这是/tidy的工作,有人工审核门禁);wiki 已是最新时不为修改而修改。
心智模型
wiki-sync --check(0 current · 3 drift · 2 未锚定)→ [标记档案 ⚑:events → scratch-log → provenance-log] → [docs-impact-plan + 4 类漂移分类] → 扫描 wiki 内部(孤立页面 · 链接 · 矛盾 · 过时内容 · 索引 · 空页面 · Origin)→ 不阻断的 pulse 报告(shortcut · unknown · skill-health · usage · tidy · claim-receipts · decision-liveness)→ 记录日志 → 确认锚点。
输入和输出约定
| 字段 | 必填? | 含义 | |
|---|---|---|---|
| 输入 | llmwiki/wiki/ + wiki-sync 锚点 | 是 | 锚点缺失 → exit 2,完成全部工作后确认锚点 |
| 输入 | harness/scripts/*(或全局版本 ~/.claude/harness/harness/scripts/) | 是 | 下游仓库没有 harness/ 时使用全局版本 |
| 输入 | fdk/tools/skill-usage.py | 否 | 仅适用于框架仓库;下游跳过此步骤 |
| 输出 | 就地修改:缺失链接、索引缺口;对过时页面进行精确修改 | 视结果而定 | 可追溯到一项具体的代码变更 |
| 输出 | 标记清单(矛盾、孤立页面、空页面、缺少 Origin、pulse) | 是 | 等待人工决策 |
| 输出 | llmwiki/wiki/log.md 中的 ## YYYY-MM-DD — lint 行 + 新锚点 | 是 | 即使 no-op 也要记录 |
| 输出 | draft 输出报告 | 是(除非没有 artifact) | Delivery 项 |
规则与能力
- RULE-01(MUST):自动修复:缺失链接(步骤 2)、索引缺口(步骤 5)。
- RULE-02(MUST):标记但不解决:矛盾、孤立页面、空页面——需要人工决策。
- RULE-03(MUST):精确修改(提炼自 openwiki 060726):修复过时页面 = 只替换错误的句子,绝不重写仍然正确的页面;优先修改 1 句话,而不是增加 1 段内容。
- RULE-04(MUST):软性差异预算:代码变更少于 5 个文件 → 最多修改 1–2 个 wiki 页面;如果发现需要修改超过 3 个页面 → 暂停并先反思原因,再进行大范围修改。
- RULE-05(MUST):禁止仅为格式而编辑:不要重新格式化表格,不要在周边内容无误时规范化空行/措辞——造成噪声的差异会给审阅者增加负担。
- RULE-06(MUST):规范归属页:每个概念都有一个主页面;其他页面只做简短提及并加上
[[wikilink]],不要重复说明。 - RULE-07(MUST):允许 no-op:“wiki 已是最新,无需修改”是一次成功的 lint 结果——记录日志后停止,不要为修改而修改。
- 能力:读取 wiki 和本地指标;运行确定性的 0-token 脚本;写入 wiki 页面(精确修改)、索引、日志和 sync 锚点。
失败边界
- Exit 0 且目标是“wiki 是否与 code 一致” → 提前停止,成功(允许 no-op)。
- 疑似过时的页面无法追溯到任何代码变更 → 不要修改。
- 代码变更少于 5 个文件,但需要修改超过 3 个页面 → 暂停并先反思,再进行大范围修改(澄清)。
- 矛盾 → 标记并交由人工处理,不要自行选定胜者。
- why 档案为空 → 记录“档案内容较少,需要查看 diff”,不要默不作声。
操作
主工作流
| 步骤 | 类型 | 输入 | 操作 | 输出/退出 | 失败/下一步 |
|---|---|---|---|---|---|
| W01 | 确定性 | neo wiki-sync | 步骤 0:wiki-sync.py --check | exit 0 / 3 / 2 | 0 + 目标为匹配代码 → 停止;3 → B01;2 → B02 |
| W02 | 确定性 | 代码文件“⇐” | 步骤 0b + 8f:⚑ 标记档案(events、scratch-log、provenance-log) | 会话 · ts · why | why 为空 → 记录“档案信息稀少” |
| W03 | 确定性 | wiki | 步骤 1–7:孤立项、缺失链接、矛盾、过时内容、索引、空内容、Origin | 修复 2 和 5,其余加标记 | — |
| W04 | 确定性 | 仓库 | 步骤 8–8f:非阻塞 pulse 报告 | 标记列表 | 脚本/路径不存在 → 跳过该步骤 |
| W05 | 效果 | 结果 | 步骤 9:追加日志 | 日志行 | — |
| W06 | 效果 | 已检查的 wiki | 步骤 10:wiki-sync.py --mark-synced | 新锚点 | 内容未变 → 不写入 |
| W07 | 效果 | 结果 | 输出报告草稿(Delivery 部分) | 草稿 + 索引 + 日志 | 0 个工件 → 跳过 |
各步骤详情(W01–W07 的事实来源):
- 代码漂移门控(0 个 token) —
RUN: python3 harness/scripts/wiki-sync.py --check(下游仓库中没有 harness/ 时,使用全局版本:python3 ~/.claude/harness/harness/scripts/wiki-sync.py --check --root .)。
0b. 每个 ⚑ 标记的档案(0 个 token — 两步 JOIN 次级记忆,接线日期为 2026-07-18): 对步骤 0 报告为“⇐”的每个代码文件(页面疑似过时的原因):
- 步骤 1 — 哪个会话触及了该文件(密集仓库,文件级):
RUN: grep "<文件名>" harness/metrics/events.jsonl | tail -3→ 获取session+ts。 - 步骤 2 — 原因(该会话的 why):
RUN: grep "<8 位会话 ID>" harness/metrics/scratch-log.jsonl | tail -2。 报告给用户时,将会话 · ts · why附到标记上 — 带档案的标记几秒内即可判断(读 why 就能知道更改是否使声明失效),裸标记则必须翻查 diff。Why 为空/由提交自动生成 → 记录“档案信息稀少,需打开 diff”,不要保持沉默。(实际限制:scratch-log 每个会话仅有 1 条 why;events 信息密集,但只有路径 — why 的丰富程度取决于会话是否手动记录。) - Exit 0(
current):自锚点以来代码未变 → 如果本轮 lint 的目标是“wiki 是否与代码一致”,则在此停止,回复“wiki 已是 current” — no-op 是好的结果,不要凭空编造工作。若仍想扫描 wiki 内部健康状况(孤立项/索引/origin),则继续步骤 1。 - Exit 3(
drift):疑似过时的页面已在stale.json中标记为code-drift,并附上导致问题的代码文件。修改前先制定 docs-impact-plan:每个计划修改的页面都必须追溯到一项具体的代码更改(代码更改 → 页面 → 修改内容 → 原因);无法追溯到任何更改的页面,不要动。- 修改前先对 drift 分类(4 分支判定标准,借鉴 RedPlanetHQ/core 中的 temporal-invalidation 思路,github.com/RedPlanetHQ/core
prompts/statements.ts):旧声明与新实际情况是什么关系?- contradiction — 两项声明无法同时成立(例如“API 使用 key X”,但 key 已改名)→ 旧声明错误,正常覆盖修改。
- superseding — 旧声明曾经正确,但因架构变更而失效(例如更换 engine/refactor)→ 不要悄悄覆盖修改:在页面 frontmatter 中添加 2 个字段 —
invalid_at: YYYY-MM-DD+invalidated_by: <commit-sha 或导致失效的文件>— 然后再更新内容。页面仍保留一条简短说明,指出旧声明曾经正确到何时(不要删除历史,只需加上标记)。 - progression — 两项声明都正确,只是阶段不同(例如“正在设计 X” → “已交付 X”)→ 两者都保留,不要 invalidate,只需追加新声明。
- equivalence — 含义相同但措辞不同(因 ingest 两次)→ 视为重复,合并为一句,不属于真正的 drift。
invalid_at/invalidated_by字段为可选项,R9(okf_frontmatter)不会阻止未知键 — 可以安全添加,无需修改 validator。
- 修改前先对 drift 分类(4 分支判定标准,借鉴 RedPlanetHQ/core 中的 temporal-invalidation 思路,github.com/RedPlanetHQ/core
- Exit 2(没有锚点/锚点失效):完成全部 lint,然后在步骤 10 确认锚点。
-
孤立项 —
RUN: grep -rL "wiki/" --include="*.md" llmwiki/wiki/concepts/ llmwiki/wiki/entities/→ 未在任何位置被引用的文件。逐个标记。 -
缺失链接 — 扫描页面,查找存在对应 wiki 文件但未写成
[[wikilinks]]的实体/概念名称。就地修复。 -
矛盾 — 每次比较最多 2 个页面中关于同一实体的说法。标记成对条目(文件:行号 vs 文件:行号)。不要判断哪一方正确——标记出来供人工审查。
-
过时说法 —
RUN: grep -rl "raw/" --include="*.md" llmwiki/wiki/→ 标记每个引用 raw/ 的页面。 -
索引遗漏 —
RUN: comm -23 <(find llmwiki/wiki -name "*.md" | sort) <(grep -o "llmwiki/wiki/[^)]*" llmwiki/wiki/index.md | sort)→ 找出索引中缺失的文件。添加条目。 -
空页面 —
RUN: for f in llmwiki/wiki/**/*.md; do [ $(wc -l < "$f") -lt 5 ] && echo "$f"; done→ 标记待删除或补充内容。 -
缺少 Origin —
RUN: grep -rL "## Origin" llmwiki/wiki/concepts/ llmwiki/wiki/entities/→ 标记每个不完整页面。 -
欠账标记缺少触发条件 —
RUN: grep -rn "shortcut:" --include="*.py" --include="*.js" --include="*.ts" --include="*.sh" . | grep -v ",";→ 每个有意设置的shortcut:标记都必须采用<当前上限>, <升级触发条件>格式(用逗号分隔两部分)。被此 grep 找出的行 = 标记缺少升级触发条件(无期限欠账 → 容易变成“永远不处理”)。逐行标记,提醒作者补充触发条件;不要自行猜测触发条件。
8c. 未知项欠账(先填充,等待验证——确定性检查,0 token) — RUN: python3 harness/scripts/unknown-ledger.py --list → 输出未解决未知项的数量 + 最早的一项 + 欠账最多的 SPEC。这些是默认模型填写的“先让事情继续运行,之后再处理”项((default, find-out-later))。报告,不阻止——先填充的机制本来就不阻止;在此处阻止就是背弃这一机制。目的:让欠账显现出来,避免被埋没;由审核者自行决定何时偿还(参见 [[150726-unknown-ledger]])。
8b. Skill 健康度(skill 形态,确定性检查——0 token) — RUN: python3 harness/scripts/skill-health.py(仓库包含 skills/ 时)→ 输出模型调用的总上下文负载,以及带有以下标记的 skill:desc(description 过长)· sprawl(SKILL.md 过长且没有渐进式披露)· negation(禁令句比例过高——建议改为肯定句)· weak-criterion(### Task 块末尾缺少可验证条件)· description 开始相似的配对项。原始标准见 [[skill-craft]]。报告,不阻止——这是质量问题,不是安全问题。标记出来供作者斟酌,不要自行批量修改。
8b. Skill 使用情况脉冲检查(0 token,仅限框架仓库) — RUN: python3 fdk/tools/skill-usage.py --weekly --no-html → 输出每周使用频率表 + 未使用的 skill(闲置 ≥4 周)。这是用于测量“哪些 skill 值得保留”的反馈链路(于 2026-07-18 接入,grower 循环):使用量下降/停止使用是决定删留的事实,不是凭感觉判断。下游没有 fdk/tools → 跳过此步骤。
8c. 文档膨胀脉冲检查(0 token) — RUN: python3 harness/scripts/tidy.py check → 根层草稿超过 10 个时退出码为 3 → 提醒用户可运行 /tidy(应用操作会将文件移入 archive/ 并重新索引——需要审核者把关,lint 时工具不会自行移动文件)。Draft/html 是临时渲染产物;任由其膨胀就会让本质被垃圾掩埋——必须有人定期清理其生命周期(于 2026-07-18 接入)。
8d. 检查 ACTIVE 草稿中的主张凭据(0 token) — 对每份 KEEP/TREO 草稿(不检查即将归档的内容):RUN: python3 harness/scripts/claim-receipts.py --check <draft> → 提取所有引用的文本文件/路径,并验证它们在磁盘上仍可解析。无法解析 = 内容已过时的确定性证据(指向已删除/改名的内容)——标记并附上失效引用列表,由人决定修复还是归档。仅供参考(adapter claim-receipts.config.yaml 为 verified:false)——不阻止,只检查(于 2026-07-18 接入,第 7 个未接入的案例)。
8e. 决策锚点活性检查(0 token,确定性) — RUN: python3 harness/scripts/decision-liveness.py check(下游仓库没有 harness/ 时,使用全局版本:python3 ~/.claude/harness/harness/scripts/decision-liveness.py check;仓库没有 harness/mechanisms.yaml → 跳过此步骤)。打印所有带有 anchor_symbol/live_probe 的条目,并标注 LIVE/STALE/ORPHAN/UNAVAILABLE — 审核者只需查看标签,就能区分 ORPHAN(需要修复锚点,或通过 status: retired 移除决策,切勿物理删除)和 STALE(需要重新阅读,可能仍然正确),无需重读全部内容(SC-005)。仅报告,不阻断 — 遵循 draft-age/unknown-ledger 的非阻断模式(步骤 8c)。
8f. 来源日志查询(0 token,确定性) — 对步骤 0b 中正在核查“为何更改”的每个文件/决策:RUN: grep "<文件名或 ID>" harness/metrics/provenance-log.jsonl | tail -5(下游使用与步骤 0 类似的全局版本)。每个匹配行包含 writer_id/topic/ts_utc(明确使用 UTC)/git_sha — 这是步骤 0b 中 events.jsonl/scratch-log.jsonl 之外的第二个“为何”来源,重要区别在于:由 git 跟踪,克隆到其他机器后仍可追溯(另外两个来源要么仅本地 gitignored,要么不一定自动完整记录 — 参见 [[log-model]])。作为补充线索使用,不替代步骤 0b。仅报告,不阻断。
-
追加到
llmwiki/wiki/log.md:## YYYY-MM-DD — lint,记录发现/修复的问题与标记的问题。 -
完成锚点 —
RUN: python3 harness/scripts/wiki-sync.py --mark-synced(或使用与步骤 0 相同的全局版本)。仅当 wiki 内容确实发生变化时才写入(content-hash);自动清除已检查的code-drift标记。必须闭合反馈回路:不完成锚点 = 下次检查会报告虚假 drift。
分支
| ID | 类型 | 条件 | 行为 | 跳过 / 失败 | 重新汇合 |
|---|---|---|---|---|---|
| B01 | conditional_required | 步骤 0 退出码为 3(drift) | 在修改前执行 docs-impact-plan,并分类为 contradiction / superseding / progression / equivalence | 页面无法访问 → 不处理 | W03 |
| B02 | conditional_required | 步骤 0 退出码为 2(尚无锚点 / 锚点已失效) | 完成全部 lint,然后在步骤 10 完成锚点 | — | W03 |
| B03 | user_optional | 步骤 0 退出码为 0,但仍想扫描 wiki 内部健康状况 | 继续步骤 1 | 不想 → 停止并回复“wiki 已是最新” | W03 |
| B04 | capability_optional | 下游仓库没有 harness/ 或 fdk/tools | 使用全局版本 ~/.claude/harness/...;没有 fdk/tools 或 harness/mechanisms.yaml → 跳过相应步骤 | — | W04 |
验证与停止
wiki-sync 的退出码决定入口(确定性);各项 8–8f 检查仅报告。lint 完成后完成锚点,以免下次检查报告虚假 drift。退出码为 0 时可以提前停止。
示例
- 正向: session_start 报告
[wiki-sync] code 已变更 3 次提交→ 步骤 0 退出码为 3,1 个页面被标记 ⇐harness/scripts/tidy.py→ why 记录显示 draft 阈值发生变化 → 分类为 superseding → 添加invalid_at+invalidated_by,修改 1 句话 → 记录日志 +--mark-synced。 - 边界情况/失败: 步骤 0 退出码为 0,且用户只问“wiki 是否与 code 匹配” → 停止,回复“wiki 已是最新”,记录日志,不修改任何页面。
交付 — 输出报告
完成所有主要技能任务后,将一份提案草稿写入 wiki。
步骤
1. 构建文件名:
- 格式:
DDMMYY-<ten>.md DDMMYY= 今天的日期(例如,2026 年 6 月 2 日为020626)<ten>= 2–4 个 kebab-case 单词,用于概括已完成的工作(例如,landing-page-coteccons、brand-kit-fintech、ingest-auth-spec)
2. 写入 llmwiki/wiki/sources/draft/DDMMYY-<ten>.md:
---
type: draft
title: "DDMMYY-<ten>"
status: proposed
tags: [<skill-name>, output-report]
timestamp: YYYY-MM-DD
---
# DDMMYY-<ten>
**Type:** draft
**Status:** proposed
**Tags:** <skill-name>, output-report
**Proposed:** YYYY-MM-DD
## What
<One sentence — what this skill invocation produced or decided>
## Output
<Key artefacts, files created/modified, or decisions made>
## Files
| File | Action |
|------|--------|
| `path/to/file` | created / modified |
## Notes
- Invoked via: `/<skill-name>` skill
## Origin
- **Draft:** `wiki/sources/draft/DDMMYY-<ten>.md`
- **Commit:** _(filled by verify-before-commit)_
- **Date promoted:** _(filled by verify-before-commit)_
3. 更新 wiki 索引和日志:
llmwiki/wiki/index.md— 追加一行:| [DDMMYY-<ten>](sources/draft/DDMMYY-<ten>.md) | draft | YYYY-MM-DD |llmwiki/wiki/log.md— 追加:## YYYY-MM-DD — <skill-name> — <ten>
仅当技能没有产出任何工件且没有任何决策时才跳过(例如,纯展示模式
/caveman-stats)。