Files
STM32F4-Base/docs/文档规范.md
T
wandering1 88601422c3 docs(文档规范): 清空壳变更记录节,例外清单改成可复跑口径
17 篇文档的变更记录(含修订记录、带编号与中文序号标题)节里只剩一句
「不再记流水账」的占位话,整节删掉,连带它前面的分隔线。
仍保留真台账的只有 5 篇(看门狗 / 配置文件设计 / RAM 预算台账 /
内容页架构 / 本地工具路径方案),外加 scripts/archive 归档区。

份数口径改成可复跑的普查:文档规范 §5.1 补自查命令,
stale-doc-count-sweep 的速查表与陷阱各加一条——只 grep 裸标题会漏
带编号与中文序号的两种写法,实测 5 篇只数得出 3 篇,差点据此把
全仓正确的份数改错。

门禁:逐篇与全量 check_doc_links 除 simulator/SDL2 联接假红外 0 问题;
skill-size rc=0;表格列数与字节体检相对 HEAD 零新增问题。
2026-10-29 21:21:59 +08:00

26 KiB
Raw Blame History

文档规范

适用对象:本仓库 docs/ 下的全部 Markdown 文档,以及根目录 README.md、AGENTS.md。 强制程度:§1~§6 为强制(pre-commit 机械校验,违反即拦截提交);§7~§8 为约定(评审时人工把关)。 相关文档:README.md(文档索引)、代码规范/pre-commit使用说明.md(钩子清单)、架构设计/图形绘制流程.md(配图流程)。


1. 目录与命名

1.1 目录

规则 说明
目录名一律不含空格 空格迫使脚本/链接/CI 处处加引号,且 URL 编码形态(UI%20设计)极易被漏改(2026-09-25 起强制;全库已无含空格目录)
按领域归入子目录 顶层不放散落 .md;新领域先建无空格子目录,再在 README.md 登记
现有目录 架构设计/ 子系统设计/ 算法/ 网络/ 测试说明/ 代码规范/ 内存管理/ 问题记录/ 环境与部署/ UI设计/ 硬件平台/ 芯片手册/ images/

1.1b 代码目录的 README.md

每个自建代码目录(非第三方库、非 HAL/CMSIS 生成)必须有一份 README.md, 说明该目录的职责、文件清单与关键约束,让新接手者不必读遍代码即可建立认知。

规则 说明
覆盖范围 App/(含 log/ task/ util/)、Drivers/BSP/(含各芯片子目录)、Src/、Inc/、scripts/、tools/(含各子工具)、test/、MDK-ARM/、simulator/(含 sim/ tests/)、docs/
排除 第三方库与生成代码:Drivers/CMSIS/、Drivers/STM32F4xx_HAL_Driver/、Middlewares/Third_Party/、Lib/(FatFs/dhara/lvgl)、simulator/SDL2/、构建产物目录
必备内容 ① 一句话定位 + 是否自研 ② 文件/子目录清单表(每个一句话作用)③ 关键约束或陷阱(改前须知)④ 指向 docs/ 权威文档的链接
命名 一律 README.md(大写),放该目录根部
链接 目录间互链用同级相对路径(如 ../NET/README.md);指向 docs/ 用仓库根相对路径
门禁 README 内所有链接受 doc-links 钩子检查;新增/改名目录或文件后须同步更新对应 README

目的:目录即文档的入口。根 README.md 给全局地图,各目录 README.md 给局部细节, 二者构成"地图 + 地标"的导航体系(避免所有信息堆在单一 README)。

1.2 文件名

规则 说明
不含空格 同目录规则
主题词 + 类型后缀 xxx设计说明.md / xxx_Test_Guide.md / xxx_Trap_Records.md / xxx使用说明.md
中英混排 中文主题词直接写(如 系统墙钟时间维护说明.md);含专有名词/缩写可用下划线连接(如 BSD_Socket_API_使用指南.md)
只用 ASCII 与中文 不含 ()【】〔〕 等全角括号、不含 &、?、*、<、>、`
版本号写法 版本后缀用下划线连接,不用全角括号:xxx_V1.0.md(✅)/ xxx(V1.0).md(❌)

例外:docs/芯片手册/ 为外部芯片数据手册转录,文件名沿用上游原名(含空格等),不受本节约束。


2. 编码与换行

项 要求
编码 UTF-8;.md 文档不带 BOM
换行 与文件现状保持一致;新建文档用 LF
行尾空白 禁止(pre-commit trailing-whitespace 自动清理)
文件尾 必须以单个换行结束(end-of-file-fixer)
乱码 禁止出现 U+FFFD(替换字符,字节序列 EF BF BD)
长中文正文与跨语言字面量 经 run_code 等程序化工具改写本文时,程序体内定界符只用一种 ASCII 引号;正文里的中文引号用全角「」,反引号字符用码位现取后再拼,不把反引号或 shell 变量形态写进字面量。落点选唯一锚点并断言命中数为 1,全部替换在内存串上跑完才一次性写回;落盘后打印 bom、crlf、乱码字节数与占位残留,并回读目标行确认已是新文本

⚠️ 本仓库 BOM 铁律(见 AGENTS.md「铁律:源码编辑与编码」):C 源码中 Drivers/BSP/UI/*、App/task/ui_task.c、App/cfg/cfg_file.c、Lib/lv_conf.h 等带 BOM,被工具改写后 BOM 会静默丢失 → ARMCC 改按 CP936 解码 → 中文字面量编译失败。 文档(.md)不受此限,一律用无 BOM UTF-8。

行尾策略(2026-10-09 起写死进 .gitattributes,本节是权威口径):* text=auto eol=lf(仓库 blob 与工作区统一 LF)+ *.bat/*.cmd 强制 CRLF(cmd.exe 对 LF-only 的 goto/标签不可靠)+ PNG/TTF/DLL/LIB 等显式 binary + *.jpg 走 LFS 且 -text(该条必须排在 * 之后才能覆盖)。不要再依赖 core.autocrlf,也不要把工作区文件"改回 CRLF"——CubeMX 重生成写的就是 LF;此前每次重生成后 40+ 个第三方文件在 git status 里显示"已修改",根因就是行尾由每台机器各自的 autocrlf 决定。用脚本批量改写文档时仍须按原样回写换行符,否则会产生整文件行尾漂移的巨型 diff。


3. 链接规范

3.1 文档间互链:仓库根相对路径

文档之间引用一律使用仓库根相对路径(形如 `docs/xxx/yyy.md` 或 [文本](docs/xxx/yyy.md)),不使用 ../ 相对链接。

理由:根相对路径对文档所在层级不敏感,迁移子目录时零改动;../ 形态在目录调整时会成片失效。

3.2 图片链接:文档所在目录相对

图片是例外——用相对当前文档的路径:

文档位置 图片写法
docs/xxx.md(docs 根下) ![标题](images/RemoDispBus帧格式.svg)
docs/子目录/xxx.md ![标题](../images/RemoDispBus帧格式.svg)

⚠️ 踩坑记录:2026-09-25 目录重组时,5 篇文档从 docs/ 迁入子目录,images/xxx.svg 未同步改为 ../images/xxx.svg → 7 处真实断链(由 doc-links 门禁揪出)。迁移含图文档时务必检查此项。

3.3 引用尚未创建 / 已删除的文件

场景 写法 示例
计划中、尚未创建 反引号内加 [计划] 前缀 `[计划] scripts/gen_task_table.py`
已删除 写明「已删除」等状态词 删除 \tools/ui_mock/render_mockup.py`(已删除)`
引用报错样例 / 日志片段(含路径) 该行加 [示例] 标记 | **典型报错** | \[示例] docs/a.md:1 [markdown 链接] x.svg` |`

为什么:check_doc_links.py 会豁免这些标记;否则门禁会把"诚实标注了未创建"的引用误判为断链。

3.4 链接写法示例须放行内代码

讲「怎么写链接」的语法示例必须包在反引号里(行内代码 span):

  • ✅ 正确:写 `![标题](相对路径.svg)` 的形式
  • ❌ 错误:写 ![标题](相对路径.svg) 的形式(会被门禁当作真实链接去校验存在性)

check_doc_links.py 扫描前会剥离行内代码 span,故写法示例不会误报;但反引号内的仓库根相对路径(docs/xxx.md)仍会被校验——那是本工程的引用约定形态。

3.5 引用章节:紧邻写法 + 别名表,让门禁能校验

引用某文档的某小节,写成 `docs/xxx/yyy.md` §N.M(文档名与 § 紧邻,中间只允许空白/反引号/括号)。

写法 门禁
`docs/子系统设计/看门狗设计说明.md` §10.4 ✅ 硬门禁(失效拦提交)
`看门狗设计说明.md` §10.4(裸文件名,全库唯一) ✅ 硬门禁
看门狗设计说明 §10.4(省略 .md,文件名全库唯一) ✅ 硬门禁
链路延迟 §8.3(文档名前缀,全库唯一) ✅ 硬门禁
「内存方案 §2.1」——已登记别名 ✅ 硬门禁
「报告 §4.2」——昵称歧义、未登记 [示例] ⚠️ 判不了 → 进 --section-todo 清单
本文档内「见 §3.1」 ✅ 硬门禁(本文档必须有该编号;确实指别篇却省了文档名的,机器判不了 → 跳过并进待办)

两档严重性:目标明确(路径 / 裸名 / 前缀 / 别名 / 同句 §A / §B 链)→ 错误;按自引用解析 → 默认告警,但 pre-commit 钩子带 --sections-strict,两档都拦提交(2026-10-11 起:全库告警已清零,清零之后就该守住)。手工跑想只看告警:去掉该 flag。

别名表 scripts/section_aliases.json:昵称 → 文档路径。登记一次,正文一个字不用改,引用就纳入硬门禁。只登记无歧义的昵称(「报告」命中多篇 → 不登记,逼着写清楚)。

覆盖率必须看着:每次跑 doc-links 都打印一行

章节引用:共 1576 处,机器可判定 843 处(53%);跳过 → 昵称式 68 / 变更记录 419 / 外部手册 187 / …

比例只许涨不许跌。清 backlog:

& '.venv\Scripts\python.exe' scripts/check_doc_links.py --all --section-todo

它列出全部机器判不了的 §(能唯一猜到的还给「建议改写:docs/… §N」),改一处涨一处;猜不到的就是必须写清楚文档名的那些。

口径怎么调出来的:全库 1578 处 §。宽松版报警 173 处(几乎全是昵称误判)→ 加文档名解析 111 → 加紧邻 + § 链 + 前缀匹配 + 别名表 + 「父级编号不存在就不是自引用」判别 → 可判定比例 7% → 58%(914 处),--section-todo 待办 83 → 0;清完 backlog 后两档都拦提交。变更记录小节(422 处)与外部手册编号(218 处)刻意不校验:前者是「当时那个编号」的历史指称,后者归厂商文档。

把待办清零靠的三类动作(按性价比排序;引号内是改前写法 [示例]):① 手册引用写全名——「手册 §9.2.1」一律改成 docs/芯片手册/CH395F.md §9.2.1(CH395F / GD5F / SD2506 / RM0090 摘录里都有编号标题,改完立刻纳入校验);② 昵称写全或登记别名——「架构 §5.5」→ UI_设计架构.md §5.5、「报告 §6.5」→ 全路径、「V0.0 报告 §4.1」→ V0.0 §4.1(别名表登记 V0.0);③ 路径补 docs/ 前缀——子系统设计/xxx.md 这种「从 docs/ 起算」的写法机器解析不到。

两条写作铁律(机器只看同一行):§ 必须与文档名紧邻(换行/跨句就判不了);「见/按/该 + 昵称」这类含糊指代,宁可多打 30 个字符写全路径。

首轮清账揪出的真断链(41 处,已修)——[示例] 下列编号是修复前的错值,故意原样保留作反例:链路延迟测试说明.md 10 处引 §8.1,而该文 §8 下只有 8.2/8.3/8.4(§8.1 早被删);GD5F2GQ5UE_Test_Guide.md 引 §4.8(BBT 实为 §3);自动化测试流程.md 引 ST-LINK_CLI_复位使用说明.md §10(该文只到 §7);模拟器差距清单.md 引 §219(实为 §4.1);实机测试实施指南.md 引 §4.4 白名单(白名单在 看门狗设计说明.md §4.3);V0.1_网表详细分析报告.md 表格里 12 处裸 §3.4/§5.3 其实指 V0.0 报告(补 V0.0 前缀 + 登记别名)。教训:编号会随重构漂移,只有机器校验能发现。

3.6 改名 / 挪目录:用 scripts/rename_ref.py,不要手工扫

固定动作(改名、挪目录、合并文档一律走这条,别靠 git grep 手改):

# 1) 预览:看它打算改哪些文件的哪些行(默认 dry-run,不落盘)
& '.venv\Scripts\python.exe' scripts/rename_ref.py docs/旧/名.md docs/新/名.md

# 2) 确认无误后落盘:git mv + 改写全库引用 + 自动跑 check_doc_links --all 复核
& '.venv\Scripts\python.exe' scripts/rename_ref.py docs/旧/名.md docs/新/名.md --apply

# 整目录搬迁(末尾带 / = 挪进该目录并保留文件名;旧/新都是目录 = 前缀改写)
& '.venv\Scripts\python.exe' scripts/rename_ref.py docs/旧目录/ docs/新目录/ --apply

它覆盖的引用形态:反引号根相对引用、Markdown 链接(根相对与文档相对都按原风格改写)、图片链接的 ../ 层级换算(§3.2 那条实证坑由它兜住)、#include "x.h" 裸文件名、MDK-ARM/*.uvprojx 的 <FilePath>、simulator/CMakeLists.txt 的 ${PROJECT_ROOT}/… 与 ${VAR}/…、以及 skill / 脚本 / 配置里的路径串。

它管不到的三件事(脚本会在结尾提示):

  1. 昵称式引用(「内存方案 §2.1」)与正文里的裸文件名散文 → 落盘后 git grep -n '<旧文件名>' 扫一遍;
  2. 生成物(docs/images/引用关系图.*)不改写 → 重跑 & 'tools\refgraph\gen_refgraph.bat';
  3. 改的是 .c/.h 且新增了目录 → 还要把目录加进 uvprojx 的 <IncludePath>(→ new-source-file skill),随后 @build 验证。

4. 门禁:文档-代码一致性

三个层次,全部由 pre-commit 机械校验:

层次 钩子 检查内容 触发条件
存在性 doc-links docs/**/*.md 里的链接、反引号路径是否指向真实文件;§N.M 章节引用是否指向真实小节(§3.5) 改动任意 .md
数值 task-table README.md、AGENTS.md 的 FreeRTOS 任务表是否与 Src/freertos.c 一致 改动 README.md / AGENTS.md / Src/freertos.c
体积 mem-numbers 内存/Flash 数字是否与最新 .map 一致(受管区 + 陈旧散句数字) 改动内存文档 / App·Src·Inc 源码 / 脚本
体积 check-added-large-files 阻止 >1MB 大文件入库 任意文件

4.1 本地手动运行

# 全库文档链接存在性
& '.venv\Scripts\python.exe' scripts/check_doc_links.py --all

# 改名 / 挪目录(先预览再落盘,见 §3.6)
& '.venv\Scripts\python.exe' scripts/rename_ref.py docs/旧/名.md docs/新/名.md
& '.venv\Scripts\python.exe' scripts/rename_ref.py docs/旧/名.md docs/新/名.md --apply

# 任务表一致性(只检查)
& '.venv\Scripts\python.exe' scripts/gen_task_table.py --check

# 任务表不一致时:自动重写受管表格区
& '.venv\Scripts\python.exe' scripts/gen_task_table.py --write

# 内存数字(受管快照 + 陈旧散句数字扫描)
& '.venv\Scripts\python.exe' scripts/check_mem_numbers.py --scan
& '.venv\Scripts\python.exe' scripts/check_mem_numbers.py --write   # 同步受管快照

# 只看期望内容,不写文件
& '.venv\Scripts\python.exe' scripts/gen_task_table.py --diff
& '.venv\Scripts\python.exe' scripts/check_mem_numbers.py --diff

# 生成完整内存台账(人工分析用)
& '.venv\Scripts\python.exe' scripts/ram_report.py -o docs/内存管理/data/ram_report_<日期>.md

4.2 受管区域(锚点)

文档里凡随代码变化的具体数值,都必须放进受管区,由脚本生成、禁止手改:

任务表(README.md / AGENTS.md)——表格外的说明文字原样保留:

<!-- TASK_TABLE:BEGIN generated by scripts/gen_task_table.py -->
| Task | 栈 (words) | 优先级 |
|---|---|---|
| ... |
<!-- TASK_TABLE:END -->

内存/Flash 快照(docs/内存管理/RAM使用分析与优化方案.md §2.1):

<!-- MEM_SNAPSHOT:BEGIN generated by scripts/check_mem_numbers.py -->
| 区域 | 用量 | 容量 | 占比 |
|---|---|---|---|
| ... |
<!-- MEM_SNAPSHOT:END -->

改栈流程:先改 Src/freertos.c 的 osThreadAttr_t → 跑 gen_task_table.py --write → 提交。 改内存流程:先改代码 + @build 出 .map → 跑 check_mem_numbers.py --write → 提交。 钩子报不一致时不要手改受管区——跑 --write 让脚本重算。

陈旧数字扫描(mem-numbers --scan)

除受管区外,脚本还会扫正文里的陈旧区域数字:从 docs/内存管理/data/ram_report_*.md 历史快照提取「曾经是区域用量、现已变化」的值(如旧 RW_IRAM1 82,048), 若正文仍以陈述现状的口吻引用即告警。

允许保留旧数字的情况(脚本按行内关键词自动放行):该行含 「历史 / 旧 / 曾 / 此前 / 快照 / data/ / 修复前 / 优化前 / 迁入前 / 实施时 / 当时」等标记。 讲任务栈 / 内存池 / 峰值水位等非区域用量的行也自动跳过(那些数字语义不同)。

设计取舍:朴素地"扫所有 4~7 位数字"实测产生 45 处误报(栈配置 4096、堆配置 49,152、 峰值 1184 全是合法数字),门禁会被无视。改为"只报历史快照里出现过、当前已变的区域值"后 误报 0、真问题全中。宁可窄而准,不可宽而吵。

4.3 豁免机制

check_doc_links.py 的豁免(不算失效,不报错):

  • `[计划] ` 前缀标记
  • 该行含 [示例] 标记(引用报错样例 / 日志片段等含路径的引文)
  • 引用附近 ±40 字符内出现「未创建 / 尚未创建 / 已删除 / 待排期」等状态词
  • 含通配符 *、尖括号 <模块> 等占位符
  • 模板变量样式(NN_ / XX_ / 界面名 / 模块名 / ${...} / %s 等)
  • 行内代码 span 里的链接写法
  • 外部 URL(http/https/mailto)与纯锚点(#...)
  • docs/芯片手册/ 等外部资料目录

章节引用(D 类)另有的跳过:昵称式引用(「内存方案 §2.1」)、非紧邻写法、变更记录小节内的历史指称、外部手册编号(RM0090 等)、目标文档本身不用数字编号标题。

「变更记录小节内的历史指称」这条跳过规则为何还留着:2026-10-28 起新文档不再设该节(见 §5.1),它现在只为保留变更记录的 3 篇真台账与 scripts/archive/ 下的归档文档服务——历史行里的编号是「当时那个编号」,既不回改也不校验。

⚠️ 状态词按就近(±40 字符)判定,不是整行——否则文件名本身含「不存在」「删除」等字样时会误豁免同行的其它真实引用(2026-09-25 实测修正)。

4.4 生成物与生成器:必须同一笔提交(generated-fresh)

规矩:改了生成器(或它的输入)就必须重跑,并把生成物与生成器放进同一笔提交。 判据不是 「看起来差不多」而是逐字节:generated-fresh 钩子把生成器拷进系统临时目录重跑一遍, 与工作区逐字节比对,任何差异(含「重跑会新增文件」)即拦提交。钩子本身不写仓库,因此它不需要 还原现场、也不会 stash 别人在飞的改动(多人共用一棵工作树也能跑)。

为什么这条要机械化(两条实证,不是假想):

  • 0f7b5a87(编号迁移)改了 tools/menu_gen/gen_menu.py 的模板文字却没重跑生成物 → HEAD 里 Drivers/BSP/UI/ui_menu_tab.h 与模板不一致,后来是别人重跑生成器才被顺带纠正(属主确认以 生成器输出为准)。
  • 2026-10-26 接线前实测又扫出 5 张 docs/images/*.svg 与各自生成器不一致——全是文档挪目录后 scripts/rename_ref.py 改写了 tools/ 里的引用路径、产物没跟着重跑(见 §3.6)。

事故形态:改生成器的人看不到任何 diff(脚本改动编译、单测全过,因为产物没变),代价却 转嫁给下一个碰巧重跑生成器的人——他要么连带提交一段「不是我改的」改动,要么 revert 掉别人 真正的修复。两种处置都错,而门禁能让他不必遇到这个选择。

在册生成器(判定表 = scripts/check_generated_fresh.py 里的 GENS;新增生成器同笔在此登记一行):

生成器 生成物 一并核对的副作用
tools/menu_gen/gen_menu.py Drivers/BSP/UI/ui_menu_tab.h、Drivers/BSP/UI/ui_menu_tab.c、Drivers/BSP/UI/ui_page_registry.h、Drivers/BSP/UI/ui_page_registry.c 回写 MDK-ARM/STM32F407-Demo.uvprojx 与 simulator/CMakeLists.txt(双端注册表一起比)
tools/font_gen/extract_cn.py ui_cn_chars.txt 唯一不按裸字节判的一项,见下
tools/font_gen/make_font.py Drivers/BSP/UI/ui_font_cn_12.c 需 node + 全局 lv_font_conv + 系统宋体,缺则该项 SKIP
tools/arch_diagram/gen_*.py(逐个) docs/images/*.svg 5 条存量在基线、只减不增;业务生成物零豁免面

两点配套:

  • 改名 / 挪目录之后(§3.6):scripts/rename_ref.py 会改写 tools/ 里生成器源码的引用 路径,但不会重跑任何生成器 → 只要 tools/ 被它改过,就要重跑对应生成器再提交。
  • 字库清单不是裸字节判定:ui_cn_chars.txt 按 font-regen 约定 = 源码在用 ∪ KEEP_EXTRA (历史落盘记录用字),钩子改判「txt 恰等于 重跑结果 ∪ KEEP_EXTRA」,两向都不许差;清单一律 直载 scripts/check_font_charset.py,不留第二份(两套清单必然漂移,教训见 docs/代码规范/pre-commit使用说明.md §5.5)。

逐项详解(八段:查什么 / 拦下过什么真事 / 触发面 / 报错怎么读 / 限制与盲区 / 豁免与基线) → docs/门禁说明/generated-fresh.md。


5. 文档结构

5.1 必备要素

要素 要求
一级标题 文档首行为 # 标题,标题即主题,不写"文档""说明"等冗余后缀
开篇引言 可选 > 引用块,写明适用对象 / 阅读前提 / 相关文档
章节编号 多章节文档用 ## 1. ### 1.1 编号,便于交叉引用(§3.2)
变更记录 一律不设该节(用户裁定 2026-10-28 起新文档、2026-10-29 起老文档也清完;标题变体 修订记录 / 带编号的 ## 6. 变更记录 / ## 九、变更记录 同规则)——文档只写现状、改了什么是正文说了算,改动过程查 git log。例外只有 5 篇(整表保留:表里是真台账、且被别处当唯一证据出处引用):docs/子系统设计/看门狗设计说明.md、docs/子系统设计/配置文件设计说明.md、docs/内存管理/RAM预算台账.md、docs/UI设计/内容页架构.md、docs/环境与部署/本地工具路径环境变量方案.md;scripts/archive/ 下的归档文档整片都是历史,不受本条约束

数"还剩几篇留着这节"的命令(别只 grep 裸标题——带编号的 ## 6. 变更记录、中文序号的 ## 九、变更记录、## 修订记录 三种写法都要算): grep -rn "^## " docs scripts 再看命中的标题;2026-10-29 实测 5 篇真台账(上表那五篇)+ scripts/archive/ 归档一篇。

5.2 新增文档检查清单

新增一篇文档时逐项确认:

  • 放在正确的子目录(目录名无空格)
  • 文件名符合命名约定(无空格 / 主题词+类型后缀)
  • UTF-8 无 BOM、LF 换行
  • 互链用仓库根相对路径;图片用当前目录相对路径
  • 尚未创建/已删除的引用加 [计划] 或状态词
  • 已在 README.md 对应章节登记一行(否则视为未完成)
  • 若涉及任务表/栈,跑 gen_task_table.py --check
  • pre-commit run --files <新文档> 通过

6. 与代码文档的边界

内容 归属
项目级铁律、构建/烧录/测试命令、平台约束 AGENTS.md(AI 协作上下文,精简优先)
开发者入门、架构速览、目录导航 README.md
详细设计、专项说明、测试指南 docs/ 下对应子目录
跨文档待办登记 docs/任务规划/README.md(统一登记簿)
评审报告与专项审计 docs/问题记录/

避免重复:同一事实只在一处详述,其它位置用链接指向。典型如 FreeRTOS 任务表——Src/freertos.c 是唯一事实源,README.md/AGENTS.md 的表由脚本生成,不在别处再抄一份。


7. 写作约定

项 约定
语气 陈述事实,不用"我们认为""大家注意"等口语
标点 中文正文用全角标点;代码、路径、命令、文件名用行内代码 `...`
术语 首次出现给全称 + 缩写(如"配置引擎(cfg_file)"),此后统一用同一术语
表格 对比、清单、参数优先用表格而非长段落
命令 用 powershell 代码块,含 & '.venv\Scripts\python.exe' 等本仓库统一入口
图 拓扑类用 Mermaid 代码块;技术配图走 SVG 生成器(见 架构设计/图形绘制流程.md)
状态标记 ✅ 已完成 / ⚠️ 注意事项 / ❌ 禁止 / 📌 要点(克制使用,不滥用 emoji)

8. 常见错误速查

现象 原因 修复
doc-links 报失效链接 文件被移动/删除后引用未同步 改引用路径,或加 [计划] / 状态词
doc-links 报语法示例行 链接示例没包反引号 把示例包进 `
task-table 报不一致 freertos.c 改栈后文档未同步 跑 gen_task_table.py --write
提交 diff 出现整文件行尾变化 脚本改写时强制了 LF/CRLF 改写须按原换行符回写(见 §2)
图片不显示 文档迁入子目录后未改 ../images/ 补 ../(见 §3.2)
引用"计划中"文件被拦 没加 [计划] 前缀 加前缀