diff --git a/AGENTS.md b/AGENTS.md index 537665e..9ea32a9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -153,7 +153,7 @@ git push origin develop │ ├── getting-started/ # 从零开始、学习地图、环境与 AI CLI 配置 │ ├── concepts/ # 核心概念、方法论与工程思想 │ ├── philosophy/ # 哲学方法论、思维模型与底层认知模型 -│ ├── references/ # 清单、约束、常见坑、模板(README 由 sources/ 生成) +│ ├── references/ # 清单、约束、常见坑、模板和技术栈参考 │ └── research/ # 新技术、优秀 repo 与工程范式研究 │ ├── prompts/ # 提示词库入口(指向云端表格) @@ -240,6 +240,14 @@ git push origin develop - `docs/references/README.md#reference-technology-stack` - 常见软件系统技术栈、选型维度、组合案例与初学者学习路径 - `skills/auto-skill/` - Skills 生成、重构与校验的元技能 +### docs README 结构契约 + +- `docs/**/README.md` 面向人类读者;维护者规则、目录边界和同步要求写入对应 `AGENTS.md`。 +- 标准块顺序固定为:顶部标题块 -> `## 字多不看` -> `## 快速导航` -> 完整细粒度目录 -> `## 使用方式` -> `## 正文`。 +- H1 后必须直接进入 `## 字多不看`,禁止在两者之间插入引用块、说明段或其他夹层内容。 +- README 中禁止出现 `和其他目录的边界` 与 `维护规则` 标题。 +- 修改 docs README 后,运行 `make sync-doc-toc` 和 `make test`;`make check-doc-structure` 是硬门禁。 + --- ## 7. Common Pitfalls(常见坑与修复) diff --git a/docs/AGENTS.md b/docs/AGENTS.md index 0ec1ede..8de138d 100644 --- a/docs/AGENTS.md +++ b/docs/AGENTS.md @@ -47,12 +47,34 @@ docs/ - 大规模重命名/移动文件导致链接失效(如必须调整,需同步更新引用)。 - 新增目录但不补 `README.md` 和 `AGENTS.md`。 +## README 结构契约 + +所有 `docs/**/README.md` 必须面向人类阅读,按以下标准块顺序组织: + +1. 顶部标题块:只允许一个 H1,且 H1 后必须直接进入 `## 字多不看`。 +2. `## 字多不看`:用 3-7 条说明最短判断和阅读入口。 +3. `## 快速导航`:列出主要章节、路线或常用入口。 +4. `完整细粒度目录(点击展开/收起)`:使用标准 `
/` 折叠块。 +5. `## 使用方式`:说明人类读者如何使用本文档。 +6. `## 正文`:承载真正内容;没有正文内容时也保留结构锚点。 + +禁止在 README 中出现以下结构: + +- H1 和 `## 字多不看` 之间的引用块、说明段或任何夹层内容。 +- `### 和其他目录的边界`。 +- `### 维护规则`。 +- “本目录只保留”“不再新增”“同步 metadata”“同步 AI 引用”等维护者口径。 + +这些维护规则必须写入对应 `AGENTS.md`,不写入面向人类的 README。 + ## 维护规则 - 每个目录必须同时维护 `README.md` 和 `AGENTS.md`。 - 新增、删除、移动、重命名文档时,必须同步更新 `docs/README.md`、所在目录索引和 `metadata/taxonomy.yml`。 - 面向 AI 引用的重要入口变化,必须同步更新 `assets/ai-citation/llms-full.txt` 和相关摘要文件。 - 不确定信息标注 TODO,不用猜测补齐。 +- 修改任意 docs README 后,运行 `make sync-doc-toc` 和 `make test`。 +- `make check-doc-structure` 是 README 结构契约硬门禁;失败时必须先修结构,再继续提交。 ## 命名规范 diff --git a/docs/concepts/AGENTS.md b/docs/concepts/AGENTS.md index f8cd7a2..6694b57 100644 --- a/docs/concepts/AGENTS.md +++ b/docs/concepts/AGENTS.md @@ -20,13 +20,16 @@ concepts/ ## 修改规则 +- 继承 `docs/AGENTS.md` 的 README 结构契约:H1 后直接进入 `## 字多不看`,再按 `快速导航 -> 完整细粒度目录 -> 使用方式 -> 正文` 排列。 - 新增概念内容时,必须追加到 `README.md` 的对应章节。 - 不再新增同级主题 `.md` 文件;如确需拆分,必须同步更新全仓链接和 `metadata/redirects.yml`。 - 概念文档应优先使用稳定术语,避免同一概念多种叫法并存。 - 不把一次性操作步骤放入本目录;操作型内容应放入 `docs/getting-started/` 或 `docs/references/`。 +- 不在 README 正文中写 `和其他目录的边界` 或 `维护规则`;维护者规则只写本文件。 ## 质量要求 - 每个概念先说明它解决的问题。 - 尽量给出使用场景、判断标准和简单例子。 - 不确定的外部事实必须标注 TODO,或放入 `docs/research/` 等待验证。 +- 修改后必须运行 `make sync-doc-toc` 和 `make test`。 diff --git a/docs/getting-started/AGENTS.md b/docs/getting-started/AGENTS.md index cbcc331..2e7e694 100644 --- a/docs/getting-started/AGENTS.md +++ b/docs/getting-started/AGENTS.md @@ -20,15 +20,17 @@ getting-started/ ## 修改规则 +- 继承 `docs/AGENTS.md` 的 README 结构契约:H1 后直接进入 `## 字多不看`,再按 `快速导航 -> 完整细粒度目录 -> 使用方式 -> 正文` 排列。 - 保持 `README.md` 作为单文件线性教程,避免重新拆散为多个碎片文档。 - 新增步骤时,必须说明适用系统、前置条件、执行命令和成功判断。 - 命令必须可复制执行;涉及平台差异时分别写明 Windows、WSL、Linux 或 macOS。 - 默认路线优先是:网络环境和订阅准备 -> Codex CLI -> 让 Agent 配置后续环境。 - 不把抽象方法论堆进本目录;方法论应链接到 `docs/concepts/` 或 `docs/references/`。 +- 不在 README 正文中写 `和其他目录的边界` 或 `维护规则`;维护者规则只写本文件。 ## 质量要求 - 假设读者没有前置依赖。 - 每个关键步骤都要有失败时的处理方法。 - 避免“自行安装”“配置一下”这类不可执行表述。 -- 修改后必须跑本地链接检查。 +- 修改后必须运行 `make sync-doc-toc` 和 `make test`。 diff --git a/docs/philosophy/AGENTS.md b/docs/philosophy/AGENTS.md index 64e23d0..ddf1980 100644 --- a/docs/philosophy/AGENTS.md +++ b/docs/philosophy/AGENTS.md @@ -20,13 +20,16 @@ philosophy/ ## 修改规则 +- 继承 `docs/AGENTS.md` 的 README 结构契约:H1 后直接进入 `## 字多不看`,再按 `快速导航 -> 完整细粒度目录 -> 使用方式 -> 正文` 排列。 - 新增模型时,优先补到 `README.md` 的对应章节。 - 不再新增同级主题 `.md` 文件;如确需拆分,必须同步更新全仓链接和 `metadata/redirects.yml`。 - 哲学内容必须落到工程判断或认知工具,不写成纯概念堆叠。 - 重命名章节锚点时,必须同步更新全仓链接和 `metadata/redirects.yml`。 +- 不在 README 正文中写 `和其他目录的边界` 或 `维护规则`;维护者规则只写本文件。 ## 质量要求 - 每个模型说明适用场景和使用方法。 - 抽象概念应配工程例子或判断清单。 - 保持术语稳定,避免同一模型出现多个标题口径。 +- 修改后必须运行 `make sync-doc-toc` 和 `make test`。 diff --git a/docs/references/AGENTS.md b/docs/references/AGENTS.md index 38b30a3..0f22fc1 100644 --- a/docs/references/AGENTS.md +++ b/docs/references/AGENTS.md @@ -21,14 +21,16 @@ references/ ## 修改规则 +- 继承 `docs/AGENTS.md` 的 README 结构契约:H1 后直接进入 `## 字多不看`,再按 `快速导航 -> 完整细粒度目录 -> 使用方式 -> 正文` 排列。 - 新增参考资料时,直接追加到 `README.md` 的对应章节。 - 检查清单、模板、质量门禁和经验类内容优先合并进 `工程实践` 章节。 - 技术选型、技术栈组合和学习路径优先合并进 `技术栈` 章节。 - 不在本目录写一次性研究笔记;新技术判断应先放入 `docs/research/`。 +- 不在 README 正文中写 `和其他目录的边界` 或 `维护规则`;维护者规则只写本文件。 ## 质量要求 - 参考文档必须可执行、可检查、可复用。 - 门禁类内容尽量转成测试、CI、脚本、schema、类型或检查清单。 - 不确定项必须标注 TODO,不能编造成熟结论。 -- 提交前必须运行 `make test`,确保锚点、链接和目录结构一致。 +- 提交前必须运行 `make sync-doc-toc` 和 `make test`,确保锚点、链接和目录结构一致。 diff --git a/docs/research/AGENTS.md b/docs/research/AGENTS.md index bbe0a73..5ebc201 100644 --- a/docs/research/AGENTS.md +++ b/docs/research/AGENTS.md @@ -22,13 +22,16 @@ research/ ## 修改规则 +- 继承 `docs/AGENTS.md` 的 README 结构契约:H1 后直接进入 `## 字多不看`,再按 `快速导航 -> 完整细粒度目录 -> 使用方式 -> 正文` 排列。 - 每篇研究笔记聚焦一个技术、repo、范式或工具,并追加到 `README.md`。 - 不再新增同级主题 `.md` 文件;如确需拆分,必须同步更新全仓链接和 `metadata/redirects.yml`。 - 研究内容稳定后,放入 `docs/concepts/`、`docs/references/` 或 `docs/philosophy/` 的对应章节。 - 外部项目、模型、工具、版本和事实状态可能变化,涉及最新信息时必须核验来源。 +- 不在 README 正文中写 `和其他目录的边界` 或 `维护规则`;维护者规则只写本文件。 ## 质量要求 - 不写新闻转述,要给出判断、边界、采用建议和后续观察点。 - 对不确定信息标注“待验证”或 TODO。 - 引入外部事实时优先引用官方文档、原始仓库、论文或可信一手来源。 +- 修改后必须运行 `make sync-doc-toc` 和 `make test`。 diff --git a/scripts/check-doc-structure.py b/scripts/check-doc-structure.py index f32e157..9704410 100644 --- a/scripts/check-doc-structure.py +++ b/scripts/check-doc-structure.py @@ -16,6 +16,7 @@ SKIP_PREFIXES = [ Path("tools/external"), ] ANCHOR_PATTERN = re.compile(r" str: @@ -122,6 +124,11 @@ def check_standard_readme_blocks(path: Path, text: str) -> list[str]: errors: list[str] = [] positions: list[tuple[str, int]] = [] + for lineno, line in enumerate(text.splitlines(), start=1): + heading = HEADING_PATTERN.match(line.strip()) + if heading and heading.group(2).strip() in DISALLOWED_README_HEADINGS: + errors.append(f"{rel}:{lineno}: README must not contain heading '{heading.group(2).strip()}'") + for block_name, pattern in STANDARD_README_BLOCKS: match = pattern.search(text) if match is None: