文档库治理机制(2026-09-09 立 · WIP-237 · 波波)

本文件是 docs/ 全树的治理总则:文档怎么放、怎么改、怎么同步、怎么核验。
四根因教训来自 WIP-236 复验退回(小冈两批文档治理)与本轮 WIP-237 实测,固化为可执行规矩。
配套阅读:docs/NOW.md 第三节「十三条纪律」、docs/receipts/README.md(回执制度)、AGENTS.md §4.4(文档铁律)。

一、文档库结构(先认清,再动手)

docs/
├── *.md / *.html        根目录=现行有效的主文档(设计/方案/契约/决议/规范)
├── archive/             已废止/已被取代的旧文档(头部必挂 ⛔ 横幅)
├── plans/               施工计划、派工清单、接口规格、验收计划(按日期或 WIP 号命名)
├── reports/             一次性交付报告、自测报告、交叉核验(按日期+人+主题命名)
├── receipts/            每人一份工作回执(见 receipts/README.md,独立制度)
├── precheck/            astra 预审实录(纪律 8 留痕)
├── tools/               文档治理工具(verify-c.sh 等)
├── _handwritten/        手写展示页留档区(无对应 md,rsync 不删)
├── TASKS.md / NOW.md    台账与当前口径(派工岗维护,长行改动须脚本化=纪律 11)
├── 时效索引.md          自动生成的时效索引(工具重算·勿手改)——查文档是否过期看这里
└── index.html           文档站入口(md2html 派生,分类卡片)

唯一权威源:仓库 docs/*.md(git main)。docs/*.html 一律由 scripts/md2html.py 派生,禁止手改 html;线上静态站 nginx/html/docs/ 是再次派生产物,禁止在服务器上直接编辑。


一点五、行号引用纪律(2026-09-28 立 · 冈子 · 时效治理)

问题:文档里写 file.py:123 这类行号引用,代码一演进就失效,但结论可能仍"看起来对"——

读者照行号跳过去看到无关代码,却不会怀疑,比直接写错更危险。

实测案例(2026-09-28 核查):

文档引用实际性质
NOW.md §四miniapp_orders.py:534 = 「券款强制线下」该行已是福钥冻结逻辑,且代码已演进为 1P/3P 双轨🔴 语义也变了
contracts/api-v1.mdminiapp_orders.py:690 = 「list_orders LIMIT 100」实际在 :728(漂 38 行)🟡 行号漂移,结论仍对

纪律:

  1. 写文档时:优先引用函数名/端点/常量名(如 list_orders()、LIMIT 100 常量),

行号只作辅助,并注明「行号为当时快照」。

  1. 读文档时:见行号引用一律先搜代码验证,不得直接采信(尤其契约/规格类)。
  2. 改代码时:若被文档引用了某行,改动后顺手更新文档行号(或改成函数名引用)。
  3. 可复跑的检查:python3 docs/tools/check_doc_line_refs.py --file <文档>,

按关键词重叠做启发式判断,低分项人工复核(低分≠必然失效)。

适用范围说明:

当时的引用就是当时的真相,改了反而篡改历史。


二、四根因教训(违反即退回)

教训① 双副本唯一真源:md 是真源,html 是派生物

规矩说明
md 为唯一真源一切内容改动只改 .md;.html 永远由 md2html.py 重新生成,不手改
改 md 必同批改 html铁律(AGENTS.md §4.4):双版本必须一致。改了 md 不同步 html=读者打开 html 看不到改动=口径分裂
同名版本分离存档版与现行版不得同名(防误读)。存档版改名带版本号,如 archive/项目总纲-v0.x-存档.md
废止挂横幅任何被取代的文档头部加一行 > ⛔ 已废止/存档(YYYY-MM-DD),现行以 \docs/精确路径.md\ 为准
事故留痕:WIP-236 改 41 份 md、0 份 html,22 份有配对 html 未重生成 ⇒ 读者打开 html 看不到横幅,正是该批要治的病本身。

教训② md2html 逐份核验:禁看循环回显的成功计数

规矩说明
批量同步后逐份核产物核 mtime / 份数 / 哈希,不看 while read 循环回显的「成功 N 份」
末行陷阱while read -r f; do …; done < 清单 会漏读无换行符的最后一行;清单末尾必须留换行,或改 `find -print0xargs -0`
幂等判据md2html.py 页脚嵌生成时间 ⇒ 跨分钟必不幂等,直接比哈希是假阴性;要比「剔除页脚时间戳后幂等」
# 单个同步
python3 scripts/md2html.py docs/xxx.md
# 全量同步
python3 scripts/md2html.py --all docs/
# 逐份核验产物(核 mtime,不信回显计数)
for f in $(cat /tmp/html_todo.txt); do stat -f "%Sm %N" "${f%.md}.html"; done
事故留痕:小齐代补 22 份失步 html 时,while read 漏读末行,首跑只成 21/22,靠逐份核 mtime 才发现第 22 份 603407 秒未更新。

教训③ 树上事实核验:宣称落地须比 blob 哈希,禁拿过期 HEAD 下结论

规矩说明
先对齐 HEAD 再判定任何「未做/零命中/已实现」结论前:git fetch → 在 origin/main 提交树上扫,不扫工作区
宣称落地比 blob 哈希验「某文件已改」用 git rev-parse <旧rev>:<path> vs <新rev>:<path> 两值必须不同;禁看 --stat 的 files changed 总数(它对未变文件根本不报)
数产物份数宣称「批量改 N 份」就数出 N 份产物,不采信自报
中文路径加参数凡含中文路径的 git ls-tree/git grep/git show 一律显式加 -c core.quotepath=false(否则被转义成八进制 ⇒ grep 字面量与 .endswith(".md") 双双假阴性)
规则本身也要被证伪校验脚本的路径/判据若写错,会静默输出假绿 ⇒ 扫描器须自带「路径不存在即报规则失效」自检
# 树上扫(不扫工作区)
git fetch origin main
git -c core.quotepath=false grep -aiE "关键词" origin/main -- docs/
# 比 blob 哈希验「已改」
git rev-parse 9791937:docs/tools/verify-c.sh   # 改前
git rev-parse origin/main:docs/tools/verify-c.sh # 改后,两值须不同
事故留痕:①WIP-236 宣称「五项落地」,实测 verify-c.sh blob 哈希与改前相同、零实现 ⇒ 宣称 5 实落 4。②本轮 WIP-237 实测 verify-c.sh ③b 两条规则的 code 路径写成单层 miniprogram/pages/(实际是 devtools 双层 miniprogram/miniprogram/pages/)⇒ os.path.exists 恒 False ⇒ 永不命中 ⇒ 输出「✅ 无状态倒挂」是假绿。两者同族:宣称/默认「已生效」但树上无实现。

教训④ WIP 号登记:自领可以,但必须登记,且不抢 P0

规矩说明
自领须登记 WIP 号纪律 2:自领提交可以,但必须在 TASKS.md 登记 WIP 号;未登记=违例记档
建单前置三步①git fetch origin main ②`git show origin/main:docs/TASKS.md \grep -aoE "WIP-2[0-9]{2}" \sort -u` 取已占号 ③取最小未占号(先到先得)
不抢占 P0自领任务不得挤占当前最高优先级单(如 WIP-230 批 1 重修)
派工岗批注当批推送派工岗批注写完必须当批 push,不得留工作区过夜(否则对方按旧版本施工、又互相覆盖)
事故留痕:①WIP-236 两批自领提交均未登记 WIP 号(纪律 2 违例)。②派工岗建单用 WIP-231,但扣子一号已先自领 231 ⇒ 同号不同事,让号 233。③长行批注整行替换两次截断覆盖事故(纪律 11:改长行须脚本化「读全文→定位行→行尾追加→写回」+ 三方合并 + 逐段 assert)。

三、状态倒挂治理(verify-c.sh ③b)

什么是状态倒挂:文档头部标「待派工/待评审/草案」,但对应代码已实现、台账已验收 ⇒ 文档状态滞后于事实,误导后来者。

扫描器:docs/tools/verify-c.sh 第 ③b 段,规则集随批扩展(WIP-237 已从 2 条扩至 5 条倒挂 + 1 条已砍除特例):

#文档倒挂证据
1场景引擎实施细则-v1.0场景引擎实施细则WIP-139 M0-M4 已验收(419ceaf)+ WIP-151 仍标待派工
2藏家乐预留位设计规格-v0.1藏家乐预留位设计规格WIP-128 M1-M3 已验收(6835569/2e5a2e8)
3需求域商户侧设计方案-v1.0需求域商户侧设计方案WIP-133 M1-M3 已验收(df1fbdd)
4主理人组包工作台设计方案-v1.0主理人组包工作台设计方案WIP-134 M1-M3 已验收(46bd3ae)
5B端工作台实施细则-v1.1B端工作台实施细则WIP-131 已验收 + WIP-140 G1 账单页已交付(101586e)
特例会员与留存体系设计决议 23 已砍除该体系 ⇒ 属「状态失真」非倒挂,应改标「已砍除」

退出口径:1=规则失效(code 路径不存在,工具坏了,硬失败);2=扫出倒挂(文档头部待修,警告不阻断);0=干净。扫出倒挂不得报「全绿」(WIP-237 修正:原二态把警告吞成假绿)。


四、提交前自检清单(文档批通用)

# 1. markdown 语法体检(只报相对 HEAD 新引入的问题,历史债不返工)
python3 scripts/check_md_syntax.py --diff-head docs/改动的文件.md
# 2. 台账表格校验(改了 TASKS.md 必跑)
python3 scripts/check_tasks_table.py --diff-head
# 3. C 端接线 + 状态倒挂扫描
bash docs/tools/verify-c.sh .
# 4. md → html 同步(改了几份 md 就同步几份,逐份核 mtime)
python3 scripts/md2html.py docs/改动的文件.md
# 5. 冲突标记扫描(禁把 <<<<<<< 提交进库)
grep -rnE "^(<<<<<<< |=======|>>>>>>> )" docs/改动的文件.md

纯文档批提交信息加 [no-deploy](不触发 staging 部署)。