Repository navigation
Description
未认领。 实现 #4916(死 ROOT 硬报错)时按 PM 要求查的对称方向,不在那条 PR 的范围内,按 Prime Directive #10 单独归档。
背景:为什么要查对称方向
#4851(PR #4921)修的是隔壁脚本 .claude/workflows/docs-accuracy-audit.js 上的同一形状,而它揭示的比议题写的更多:那份清单不只有 16 条死条目,还有 48 份磁盘上存在却从未被列过的文档。两个方向同时腐烂,且都不出声,但只有第一个方向被人立过单。
#4916 只覆盖了第一个方向(声明了却解析不到的 root)。第二个方向是:有没有一个真实存在的、应当被这条规则约束的语料目录,从来就不在 ROOTS 里?
查的方法与结论
对全仓 git ls-files '*.md' '*.mdx'(不含 .changeset/)逐个走 ts/typescript/tsx 围栏块,统计两件事:(a) 现有的 bare-literal 违规;(b) 块内是否出现 defineX(...) 或 16 个 domain 的类型标注 —— 即"这份文档是否在教 metadata 编写"。
(a) 全仓当前零违规,ROOTS 内外都是。所以下面这些是尚未腐烂的盲区,不是已经烂掉的现场 —— 和 .claude 在 #4913 之前的状态完全一样。
(b) ROOTS 之外确实在教 metadata 编写的文件:
| 文件 | ts 围栏块 | defineX( |
类型标注 |
|---|---|---|---|
docs/notes/crm-development-standards.mdx |
16 | 3 | 0 |
docs/adr/0010-metadata-protection-model.md |
9 | 2 | 0 |
docs/adr/0015-external-datasource-federation.md |
12 | 2 | 0 |
docs/adr/0057-system-data-lifecycle-and-retention.md |
1 | 3 | 0 |
docs/adr/0017-object-has-many-view.md |
1 | 1 | 0 |
docs/design/permission-model.md |
1 | 3 | 0 |
排除的误报:docs/adr/0024-mcp-connectors.md 命中的是 TS interface 字段 def: Connector;,packages/spec/docs/SYNC_ARCHITECTURE.md 命中的是散文里的 "Field Mapping",都不是 export const 形。
核对过、确认不是语料的: examples/(21 份 md,零命中)、apps/、docker/、根目录 md、packages/**/README.md(155 份,零命中)。
.codex/(#4913 的 dev 提到的同类 agent 目录):本检出里不存在,且 .gitignore:123 就是 .codex/。它是纯本地、不入库的 agent 配置,CI 里永远看不到 —— 不该进 ROOTS(进了反而会让 #4916 的硬报错在没有 .codex/ 的机器上误红)。查过了,这条是"没有"。
所以 docs/ 该不该进 ROOTS
支持的理由,和 #4913 把 .claude 加进来的理由是同一条:docs/ 是 agent 会读的手写语料 —— AGENTS.md Prime Directive #13 明确要求"改动 ADR 治下的行为前先 grep ADR",docs/notes/crm-development-standards.mdx 的标题直接就是《Development Standards》,里面 16 个 ts 块教应用怎么写。一份 ADR 里的 bare literal 会被下一个 agent 原样抄进 app 代码,和 skills/ 里的一份坏样本没有区别。
需要先定的两件事(所以本单是决策单,不是直接实现单):
- 范围:整个
docs/(177 份 md),还是只docs/adr/+docs/design/+docs/notes/?docs/audits/、docs/handoff/、docs/plans/是一次性的过程记录,不是"AI 抄写的语料",把它们纳入等于让历史快照永久受当前 lint 约束 —— 一份两个月前的 handoff 里写着当时的 bare literal 是史实,改它是伪造记录。倾向:只纳入docs/adr/docs/design/docs/notes,并把"为什么不是整个 docs/"写进脚本注释,否则下一个人会以为是漏了。 - 历史文档怎么办:当前零违规,所以现在纳入是零成本的 —— 这正是纳入的最佳时机,拖到有违规时再纳入就变成一次要么改史料要么加豁免的争论。
与 #4916 的关系
#4916 让"声明了但没了"变红;本单问的是"存在但从没声明过"。两者互补,合起来才是 #4851 那条经验的完整版本。#4916 的 PR 里没有改 ROOTS,刻意留给本单决定。
Activity
xuyushun441-sys commentedon Aug 3, 2026
认领(PM 分派)
session_018iARDqtrhQgz6fVHDeDkbQclaude/issue-4929-doc-authoring-roots-docsdomain:devx(落点scripts/check-doc-authoring.mjs,阻塞已解除:fix(tooling): check-doc-authoring 的死 ROOT 改为点名硬报错 (#4916) #4934 已合入)范围按本单正文的分析定:纳入
docs/adr、docs/design、docs/notes(教 metadata 编写的活语料);排除docs/audits、docs/handoff、docs/plans(一次性历史快照,纳入等于让史料永久受当前 lint 约束 —— 改两个月前的 handoff 是伪造记录)。"全仓当前零违规、现在纳入零成本"的窗口正开着,别等它关上。Generated by Claude Code
xuyushun441-sys commentedon Aug 3, 2026
审核通过 — PR #4978 已取消草稿并挂上 auto-merge(SQUASH)
算术对得上:
docs/共 177 个 md/mdx,排除 audits(32)+ plans(3)+ handoff(1)= 36,净增 141,扫描面 219 → 360 精确吻合 —— 零违规不是靠放宽或加 SKIP_FILES 凑出来的。趁"全仓零违规"的窗口纳入,兑现了本单立案时的判断:现在做零成本,拖到有违规再做就是"改史料还是加豁免"的争论。一处比我的裁定更宽的判断,我接受并说明理由:我裁的是"纳入三个子目录",dev 把 ROOT 定为整个
docs+ 三个历史目录进 SKIP_PATHS。效果是顶层 11 份手写指南(protocol-upgrade-guide 等)也进了扫描,且未来新增的 docs/ 子目录默认在保护内 —— 与 #4913 的教训一致(范围划窄一次,就会再漏一次)。历史豁免用显式 skip 表达,方向正确:活语料默认在内,豁免必须点名。双向证明含 mutation 检查:同一个违规体放在
docs/adr(判红)与docs/handoff(保持绿);从 ROOTS 删掉docs→ self-test 红,删掉三条 SKIP_PATHS → self-test 红。两个方向的断言都是承重的。SKIP_PATHS 不做死条目检测的取舍成立:
docs/audits改名后 skip 失配的失败方向是安全的 —— 那些文件会进入扫描并响亮判红,而不是静默漏掉;且.claude/worktrees在正常检出里本就不存在,加可解析性断言反而会误红。与 #4916 对 ROOTS 的处理不同向,理由写进了注释,没有为对称而对称。落点 2 文件,零共享文件。
Generated by Claude Code
chore(tooling): doc-authoring 守卫纳入 docs/ 活语料,历史快照按路径豁免 (objectstack-a…