夜雨聆风学习资料网

ARTICLE · 1063233

文档检查 · 检查放在文档里,等于没有

文档检查 · 检查放在文档里,等于没有

你仓库的文档里,可能就有一句早就不成立的话——没人发现,agent 也没说。

这篇是把这类话捞出来,两样东西,都能直接复制走:一份补漏的检查,补上现成工具看不见的那类命令引用;三条审计约束,管机器查不出的约定过期。这两样我都在自己的仓库里跑过。

先说结论:检查写在文档里等于没有,得挂在门口。 下面的事都围着这一句。

关注「老刘的Agent手记」——agent 工具一个个拆开、自己跑一遍再给判断;想拿文件原件的,后台回复「文档检查」。

📦 这份资料包里有什么

👉 滑动

PART 01

补上那段检查

命令引用

PART 02

挂上去

别只放在文档里

PART 03

三条判据卡

机器查不出的

PART 04

拿去用

三份原样复制

PART ///

十秒自检

现在就能做

01

PART

先补上现成工具看不见的那一类

PATCH · 命令引用

现成的工具里有一个 driftlint。文档里写着 npm run deploy——deploy 不在 scripts 里,它就报错。

可 npm test 这种写法,它一个字都不说:命令名直接跟在 npm 后面,中间没有 run。这恰恰是我们写文档时最顺手的写法。

它只认「npm run + 名字」这一种格式,别的命令写法一概不看——pnpm buildyarn dev 都一样。

补它,逻辑就三句话:

一、把文档里反引号包着的命令全捞出来

二、每条命令的最后一个词,就是脚本名

三、拿去 package.json 的 scripts 里找,没有就报

脚本我写在最后一节了,27 行,不用读——存成 scripts/check-commands.sh 就能用。

我那个小项目的文档里留了一行早就不存在的 npm test,它只报这一行;有问题时退出码是 1,所以能挂在钩子上拦住提交——下一节说怎么挂。

一句说明:它只认 package.json,也只读文档、不写任何文件。你的项目要是用 justfileMakefile,把取脚本名的那两行换掉,三句话的逻辑不变。npm install 这类内置命令它跳过了;项目里压根没有 package.json,它会一声不响地退出——那不等于“检查过了”

02

PART

挂上去

HOOK · 不挂就等于没有

两段配置——挂 pre-commit,提交时拦;挂 CI,推送时查——都在最后一节,选一个或都上。

⚠️ .git/hooks/ 这个目录不进版本库,换台机器、重新克隆就没了。团队要一起用,把它放在仓库里的 .githooks/ 下,再执行一次 git config core.hooksPath .githooks——这样它跟着代码走。

这是挂了之后的效果。文档里留一行 npm test——就是第一节说的、现成工具漏掉的那种写法。两道检查挨着跑,第一道没看出问题,第二道把它拦下来,那条提交没进历史

...bash

$ npx -y @alifurkangokce/driftlint

driftlint: 0 errors, 0 warnings across 1 context file

your agent context files agree with your code. rare.

$ bash scripts/check-commands.sh

✗ 文档里写着 npm test,scripts 里没有 test

上面这几处,改完再提交。

把那行改对,再提交就过了。这一条是关键:拦住的不是提醒,是提交本身。

也正因为这样,两道都得挂:driftlint 那一道只管 npm run 那种格式,补的这道管它看不见的写法。只挂一道,另一道漏的错照样进历史。

挂哪儿,是我自己跑出来的结论:

查“文档点名的东西还在不在”,放提交时 —— 快,不拖你

查“内容有没有过期”(比文件时间),放推送时或者 CI 里 —— 它要翻 git 历史,慢

那份判据卡的审计,每次推送带一次,再每周过一遍

最后一句实话:driftlint 是 8 月 11 号发的第一版,一个多月更了 11 个版本,最近一周下载 66 次。它哪天不在了、改得你不认识了,或者你不想多装一个包,把 npx 那行删掉,剩下的照样跑。

03

PART

机器查不出的那类:三条判据卡

RUBRIC · 审计约束

路径和命令,脚本对得了。但有一类机器永远看不出来:约定过期了。

文档写着“我们的组件还在用类组件”,其实早就全换成函数组件了;写着“改表结构必须走评审”,那个流程半年前取消了。

这种没有唯一答案,只能让另一个 agent 读。但它读的时候你得给它三条约束——不给,它会“顺手把文档更新一下”,然后跟你说更完了。

一、只出报告,不改文件(改不改,我点头之后再说)二、每条发现必须能说成“某处写着 X,但 X 不成立”;写不成的,别放进报告三、分不清是文档错了还是代码歪了,两个都列出来,交给人

第二句是整张卡的重心。像“组件应该用函数写”这种话,说不成那个格式——它不是“某处写着 X 但 X 不成立”,它是个没落地的观点。这一句卡住,报告里剩下的就都是能查证的。

能直接粘给它的一段:

...text

读一遍 AGENTS.md 和 docs/ 下的文档,对照当前代码,只回答一个问题:

这里面哪一条,现在的代码已经不这么干了?

三条规矩:

一、只出报告,别改任何文件——改不改,我点头之后再说

二、每条发现必须能说成“某处写着 X,但 X 不成立”;说不成的,别写进报告

三、分不清是文档错了还是代码歪了,两个都列出来交给我

每条给我:哪份文档、哪一行、代码在第几行。

还有两件事,比指令本身更要紧:

别让它一边干活一边顺手更文档。 它对自己刚干的活,判断力最差。

agent 自己说“我更新过了”,不算数。 要独立的一步,专门对账。

04

PART

拿去用

APPENDIX · 三份原样复制

三份,原样复制。不用读。 前两份今天就能做完;第三份,等你有了 CI 那天再回来拿。

一、补漏的检查 → scripts/check-commands.sh

...bash

#!/usr/bin/env bash

# check-commands.sh —— 文档里点名的命令,还在吗?

set -uo pipefail

DOCS="AGENTS.md CLAUDE.md README.md docs"

[ -f package.json ] || exit 0

have=$(sed -n '/"scripts"/,/}/p' package.json \

| grep -oE '"[^"]+":' | tr -d '":' | grep -vx scripts | sort -u)

RE='`(npm|pnpm|yarn|bun)( run)? [a-zA-Z0-9:_-]+`'

cmds=$(grep -ohrE --include='*.md' "$RE" $DOCS 2>/dev/null \

| tr -d '`' | sort -u)

fail=0

while IFS= read -r c; do

name=${c##* }

case "$name" in

install|ci|add|remove|audit|publish|update|init|ls|help) continue ;;

esac

if ! grep -qx "$name" <<< "$have"; then

echo "✗ 文档里写着 $c,scripts 里没有 $name"

fail=1

fi

done <<< "$cmds"

[ $fail -eq 0 ] && echo "✓ 文档点名的命令都还在"

[ $fail -eq 0 ] || { echo; echo "上面这几处,改完再提交。"; }

exit $fail

二、挂在提交上 → .githooks/pre-commit(放仓库里,chmod +x,再跑一次 git config core.hooksPath .githooks

...sh

#!/bin/sh

npx -y @alifurkangokce/driftlint || exit 1

bash scripts/check-commands.sh || exit 1

三、挂 CI → .github/workflows/docs.yml

...yaml

# .github/workflows/docs.yml

name: docs

on: [push, pull_request]

jobs:

check:

runs-on: ubuntu-latest

steps:

- uses: actions/checkout@v4

with:

fetch-depth: 0 # 时间漂移那类要完整历史,浅克隆会算错

- run: npx -y @alifurkangokce/driftlint

- run: bash scripts/check-commands.sh

还有一层在 PART 03 · 三条判据卡:三条约束,加那段可粘给 agent 的指令——留到你要清文档的那天用。

///

LAST

十秒自检

LAST · 现在就能做

翻一遍你的文档,问一句:

这里面哪句话是错的,也不会有人发现?那一句,就是你要接的那根线。

相关学习资料