docs: sync api and planning docs

This commit is contained in:
2026-04-08 16:07:03 +08:00
parent 08c3278e10
commit 31756847ab
1826 changed files with 44502 additions and 29645 deletions

View File

@@ -2,199 +2,217 @@
## 目标
本规范用于维护 `XCEngine` 的唯一正式 API 文档树,并约束后续所有模块级重构的工作方式
这份规范面向维护 `XCEngine` API 文档的 coding agent。它的目标不是“批量生成一套看起来完整的文档”而是持续把当前源码、测试和真实调用链路同步到唯一的 canonical API 文档树里
硬性要求
当前仓库已经进入“增量同步”阶段。重点不再是补骨架,而是
1. `docs/api/XCEngine/**` 必须与 `engine/include/XCEngine/**` 保持平行。
2. canonical API 文档只保留一套;迁移完成后必须删除旧目录与旧入口。
3. 默认情况下,每个 public header 对应一个独立文档目录,每个类型页都使用 `{TypeName}/{TypeName}.md`
4. 方法页优先使用源码中的原始函数名;不要改成 kebab-case、全小写或其它再命名形式。
5. API 文档必须以源码、实现、测试和真实调用点为依据,禁止只根据名字猜测行为。
6. 对于只承担聚合包含职责的 umbrella header可以并入模块页说明不强制再建一个同名类型目录。
- 跟住最新 public header 和 Editor source header 的真实变化
- 清理过期 API 页面和过期叙述
- 保持 overview / guide / method page 的口径一致
## Canonical 目录结构
## 当前范围
```text
docs/api/
├── main.md
├── XCEngine/
│ ├── XCEngine.md
├── Debug/
│ ├── Debug.md
│ │ ├── Logger/
│ │ │ ├── Logger.md
│ │ │ ├── Get.md
│ │ │ ├── Initialize.md
│ │ └── Log.md
│ │ └── RenderDocCapture/
│ ├── RenderDocCapture.md
│ │ └── BeginCapture.md
└── ...
├── _guides/
└── Debug/
└── _meta/
API 文档的正式范围包含两部分:
1. 引擎 public API
- 对齐 `engine/include/XCEngine/**`
2. Editor source-backed API
- 对齐 `editor/src/**`
- canonical 文档入口仍放在 `docs/api/XCEngine/Editor/**`
辅助目录也属于工作流的一部分:
- `docs/api/_guides/**`
- 教程、架构说明、工作流说明
- `docs/api/_meta/**`
- 审计结果、阶段性状态
- `docs/api/_tools/**`
- 审计、生成、修链脚本
- `docs/plan/API文档实时同步任务池_2026-04-03.md`
- 当前多任务并行同步池
- `README.md` / `editor/README.md` / `AGENT.md`
- 这些不是 canonical API 页,但一旦它们引用 API 模块结构、测试目录或 Editor helper 分层,就属于必须同步的活跃协作文档
## 硬约束
1. `docs/api/XCEngine/**` 是唯一 canonical API 树。
2. 文档必须以“当前 header + 当前实现 + 当前测试 + 当前真实调用点”为依据,不能按旧文档或命名猜行为。
3. 删除的 API 页面要一起删除,相关交叉链接也必须一起清理。
4. 方法页优先使用源码中的原始函数名;不要擅自改成 kebab-case 或小写别名。
5. 不要把“设计意图”写成“当前实现行为”。
6. 不要为已经删除的 API 保留默认兼容入口页,除非任务明确要求。
7. `rebuild-status.md` 以审计脚本输出为准并发场景下stdout 比旧文件内容更可信。
8. 只收口活跃文档;`docs/plan/used/**``docs/used/**` 等归档材料默认保留历史写法,不要为了“顺手统一”去重写归档。
9. Windows 工作树里的路径大小写按真实目录名写,例如 `tests/Editor/``tests/Core/``tests/Scripting/`,不要继续传播 `tests/editor/``tests/core/` 之类的历史噪音。
## 工作流
### 1. 开工前先看两份文件
- 任务池:
- `docs/plan/API文档实时同步任务池_2026-04-03.md`
- 最新审计:
- `docs/api/_meta/rebuild-status.md`
如果任务池和工作树不一致,以当前源码和重新执行审计后的结果为准。
如果 `docs/plan/` 下出现日期更晚的 API 相关计划或归档文件,优先读取更新日期更晚的文件,再判断当前任务池是否已经转入 `docs/plan/used/`
如果工作内容会改到 `README.md``editor/README.md``AGENT.md`
- 先对照真实工作树、`Get-ChildItem` 输出和当前测试目录
- 再改目录树与模块说明
- 不要沿用旧摘要、旧计划里的目录快照
### 2. 认领规则
- 一次只认领一个任务块。
- 先把任务状态改成 `DOING`,再写认领人。
- 只修改该任务块的写入范围。
- 如果发现新的失配,但不属于当前任务块,向任务池追加新任务,不顺手扩写。
### 3. 写文档前的取证
至少完成下面四步:
1. 读对应 header
2. 读对应 `.cpp` 或内联实现
3. 搜测试和真实调用点
4. 确认生命周期、线程语义、失败路径、所有权、平台限制
如果是 Editor source-backed API至少额外确认两类锚点
1. `tests/Editor/` 下是否已有对应单测
2. `SceneViewPanel.cpp``ViewportHostService.*` 或其他真实上层调用链是否已经切到新 helper
落文前至少能回答这些问题:
- 这个类型或函数解决什么问题,边界在哪里?
- 调用前需要什么前置条件?
- 失败时返回什么,或者会不会静默 no-op
- 谁拥有对象,谁负责释放资源?
- 当前实现是完整能力、轻量封装、stub还是占位入口
### 4. 改完后的收口
必须重新执行:
```powershell
python -B docs/api/_tools/audit_api_docs.py
```
说明
至少关注这些指标
- `docs/api/XCEngine/**` 是唯一 canonical API 树。
- `docs/api/_guides/**` 用于概念、教程、设计理念和工作流说明,不是第二套 API 树。
- `README.md` 不用于 canonical 模块索引页;模块索引页统一使用 `{DirName}.md`
- `Invalid header refs`
- `Invalid source refs`
- `Broken .md links`
- `Old template pages`
- `Flat header pages`
- `Stale editor doc tokens`
- `Stale editor canonical pages`
## 强制命名规则
如果审计没回绿,不算完成。
### 1. 目录索引页
## Canonical 目录规则
- 根索引页:`docs/api/XCEngine/XCEngine.md`
- 模块索引页:`docs/api/XCEngine/{ModuleName}/{ModuleName}.md`
- 子模块索引页:`docs/api/XCEngine/{ModuleName}/{SubmoduleName}/{SubmoduleName}.md`
### 1. 模块总览页
- 根入口:
- `docs/api/main.md`
- API 根页:
- `docs/api/XCEngine/XCEngine.md`
- 模块页:
- `docs/api/XCEngine/{ModuleName}/{ModuleName}.md`
- 子模块页:
- `docs/api/XCEngine/{ModuleName}/{SubmoduleName}/{SubmoduleName}.md`
示例:
- `docs/api/XCEngine/Debug/Debug.md`
- `docs/api/XCEngine/Core/Core.md`
- `docs/api/XCEngine/RHI/D3D12/D3D12.md`
- `docs/api/XCEngine/Core/Asset/Asset.md`
- `docs/api/XCEngine/Rendering/Passes/Passes.md`
- `docs/api/XCEngine/Editor/Viewport/Viewport.md`
### 2. 类型目录
### 2. Header / source-backed 目录
- 每个 public header 对应一个独立文件夹。
- 文件夹名必须与 header stem 或主要类型名一致。
- 保留源码中的大小写,不做风格改写。
- 如果 header 只是模块聚合入口,不声明独立类型,可以直接并入模块页,不单独建文件夹。
当前不是“每个类型再套一层目录”,而是:
- 每个 public header 或 Editor source header 对应一个文档目录
- 该目录内放主类型页、辅助类型页和方法页
示例:
- `docs/api/XCEngine/Debug/Logger/`
- `docs/api/XCEngine/Core/Asset/ResourceManager/`
- `docs/api/XCEngine/RHI/D3D12/D3D12Device/`
```text
docs/api/XCEngine/Core/Asset/ResourceManager/
├── ResourceManager.md
├── Load.md
├── LoadAsync.md
├── RefreshProjectAssets.md
├── RebuildProjectAssetCache.md
└── GetProjectLibraryRoot.md
```
### 3. 类型总览页
多类型 / helper 同头文件示例:
- 固定为 `{TypeName}/{TypeName}.md`
- 不允许把类型总览页直接平铺在模块目录中
```text
docs/api/XCEngine/Editor/Viewport/SceneViewportRenderPlan/
├── SceneViewportRenderPlan.md
├── SceneViewportRenderPlanBuildResult.md
├── BuildSceneViewportRenderPlan.md
└── ApplySceneViewportRenderPlan.md
```
### 4. 方法详情页
### 3. umbrella header 例外
- 方法页放在所属类型目录内。
- 文件名优先使用原函数名。
- 重载共享同一页,在页内按签名分节说明。
如果一个 header 只是聚合入口,通常不单独建同名类型页,直接并入模块页:
示例:
- 文件主要由 `#include` 组成
- 不声明独立 class / struct / enum / function family
- 单独建页只会制造重复入口
- `Get.md`
- `Initialize.md`
- `SetCaptureFilePath.md`
- `LoadSceneAsync.md`
## 命名规则
### 5. 特殊命名
### 1. 主页面
- 构造函数:`Constructor.md`
- 析构函数:`Destructor.md`
- 运算符使用可读的 PascalCase 名称
- 主类型页通常用主类型名:
- `ResourceManager.md`
- `BuiltinInfiniteGridPass.md`
- helper 类型页直接用真实类型名:
- `ImportedAsset.md`
- `LookupSnapshot.md`
建议映射:
### 2. 方法页
- `operator=` -> `OperatorAssign.md`
- `operator+=` -> `OperatorPlusAssign.md`
- `operator[]` -> `OperatorSubscript.md`
- `operator()` -> `OperatorCall.md`
- 用真实函数名:
- `Initialize.md`
- `TryResolveAssetPath.md`
- `BuildInfiniteGridParameters.md`
## 写作前的取证流程
重载共享同一页,在页内按签名分节说明。
在编写任何 API 页之前,必须完成下面的最小取证:
### 3. 特殊命名
1. 阅读对应 public header。
2. 阅读对应 `.cpp` 或内联实现。
3. 搜索测试、示例和真实调用点。
4. 确认生命周期、线程语义、所有权、失败路径和平台限制。
至少回答以下问题后才能落文:
- 这个类型解决什么问题,边界在哪里?
- 调用前需要什么前置条件?
- 调用失败时返回什么,或者会静默失败?
- 谁拥有对象,谁负责释放资源?
- 多线程下哪些调用安全,哪些只能在初始化阶段使用?
- 当前实现是不是完整的?有没有空实现、占位实现或只做轻量封装?
禁止行为:
- 只根据 `Get``Create``Set` 之类的前缀写模板句。
- 把“设计意图”当成“当前实现行为”来写。
- 把测试里假设成立的场景,误写成通用保证。
## umbrella header 例外规则
以下情况通常应视为模块聚合头,而不是单独类型页:
- 头文件主要由一组 `#include` 组成。
- 不声明独立类、结构体、枚举或函数族。
- 名称与模块目录同名,单独建页会造成 `Debug/Debug.md` 这类重复入口。
处理方式:
- 在模块页中增加“聚合头文件”或“包含入口”小节。
- 使用 `**头文件**: \`...\`` 保留头文件覆盖记录。
- 不再额外创建 `{HeaderStem}/{HeaderStem}.md`
## 契约分层规则
文档必须明确区分下面三层信息:
### 1. 接口契约
来自 public header属于使用者可以依赖的 API 形状。
例如:
- 函数签名
- 参数和返回值
- 可见的数据结构
- 明确暴露的枚举值和宏
### 2. 当前实现行为
来自 `.cpp`、内联实现、测试和调用点,描述当前版本的真实行为。
例如:
- 是否自动初始化
- 是否加锁
- 是否会写日志、刷新文件、拉起窗口焦点
- 是否只是 no-op 或 stub
这一层必须使用明确表述,例如:
- “当前实现中……”
- “按 `engine/src/...` 的实现……”
- “当前版本会……”
### 3. 合理推断
只在确实有必要时使用,而且必须标明是推断。
例如:
- “从 API 形状看,设计上显然是为后续 Chrome Trace 导出预留扩展点。”
如果不能证明,就不要写。
- 构造函数:
- `Constructor.md`
- 析构函数:
- `Destructor.md`
- 运算符:
- `operator=` -> `OperatorAssign.md`
- `operator[]` -> `OperatorSubscript.md`
- `operator()` -> `OperatorCall.md`
## 页面职责
### 1. 模块页 / 子模块页
### 1. 模块页
负责
必须说明
- 说明模块职责、边界和典型使用场景
- 列出子目录与 public headers
- 给出与相邻模块的关系
- 链接相关 guide
- 模块职责
- 与相邻模块的边界
- 典型使用链路
- 关键入口
负责:
- 展开所有方法细节
- 重复 header 全量声明
要在模块页里平铺所有方法细节。
### 2. 类型页
@@ -202,212 +220,122 @@ docs/api/
- 命名空间
- 类型分类
- 头文件
- `头文件``源文件`
- 角色概述
- 生命周期
- 线程语义
- 所有权 / 资源管理方式
- 当前实现限制
- 相关方法页、guide 页的跳转
- 相关方法与相关 guide
如果类型是枚举或结构体,还应补充:
- 字段或枚举值说明
- 值之间的语义关系
- 典型使用方式
如果`struct` / `enum`,还要写清字段或枚举值的实际语义。
### 3. 方法页
必须包含
必须写清
- 准确签名
- 调用目的
- 前置条件
- 参数说明
- 返回值说明
- 当前实现行为
- 返回值
- 副作用
- 线程语义
- 失败路径或 no-op 条件
- 最小可信示例
- 线程语义
- 真实调用点或测试锚点
方法页不能只写“获取对象”“设置状态”这种空描述。
不能只写“获取对象”“设置状态”这种空描述。
## 内容深度要求
## 写法规则
### 1. 解释“是什么”
### 1. 区分三层信息
说明类型或方法的职责,而不是简单复述名字。
文档里要明确区分:
### 2. 解释“怎么用”
- 接口契约
- 来自 header可被调用方依赖
- 当前实现行为
- 来自 `.cpp`、测试和调用链
- 合理推断
- 只有必要时才写,并明确标注是推断
给出最小可运行或最小可信的使用顺序,让用户知道放在初始化、运行时还是销毁阶段。
推荐措辞:
### 3. 解释“为什么这样设计
- “当前实现中……
- “按 `engine/src/...` 的实现……”
- “测试 `tests/...` 当前验证了……”
结合引擎架构解释:
### 2. 优先写真实链路
- 为什么做成 singleton、service、interface、sink、builder、handle
- 这样做的收益是什么
- 有哪些代价或约束
如果一个 API 真正只是更大链路中的一环,要把链路写出来。
### 4. 解释“当前实现做到哪一步”
示例:
商业级 API 文档不能假装所有接口都同样成熟。
- `ResourceManager`
- 不只写“负责资源加载”
- 要写清 `AssetImportService -> ProjectAssetIndex -> loader` 的真实路径
- `SceneViewportRenderPlan`
- 不只写“构建后处理 plan”
- 要写清它如何给 Scene View 组装 `postScenePasses` / `overlayPasses`
对于未完成能力,必须明确说明:
### 3. 明确不成熟部分
- 当前是占位接口
- 当前只有基础实现
- 当前只覆盖某个平台 / 某条后端路径
对未完成能力要直接写明:
## 教程与概念页规范
- 当前是 stub
- 当前只支持某个平台
- 当前只覆盖某条 backend 路径
- 当前仍要求调用方手动轮询或手动 shutdown
当某个模块仅靠 API 页不足以让用户理解时,应增加 `_guides`
不要把不成熟接口包装成成熟系统
## Guide / Overview 规则
`_guides` 不是第二套 API 参考,而是解释:
- 为什么这样组织模块
- 推荐从哪里开始读
- 典型工作流是什么
- 与 Unity / Unreal 等常见心智模型的关系
适合写 guide 的内容:
- 前置知识
- 架构设计理念
- 推荐工作流
- 和 Unity / Unreal / RenderDoc 等常见工具的概念对照
- 最佳实践与反模式
- 架构图景
- 推荐使用顺序
- 设计权衡
- 常见误区
guide 页不是第二套 API 参考,它们负责回答
不适合
- 为什么要这样组织模块
- 用户第一次接触时该从哪里开始
- 这套 API 与常见引擎的对应关系是什么
- 重复抄一遍类型页和方法页
- 延续已经过期的旧工作流
guide 页应尽量包含:
## 常见失误
- 问题背景
- 设计目标
- 推荐流程
- 优点与代价
- 与现有 API 页的链接
- 按名字猜 API 行为,不看实现和测试
- 保留已经删除的 API 页面或链接
- overview 还在传播旧心智,但类型页已经改新了
- 把 helper / wrapper 当成独立大系统来写
- 把 Editor source-backed API 当成 public header 处理,漏掉 `源文件` 语义
- 审计没跑或没回绿就宣布完成
- README / AGENT / editor README 的目录树还停留在旧快照,和当前工作树脱节
- Windows 上真实已有新测试,但类型页还在写“没有独立单元测试”
## Unity 风格的解释性要求
## 推荐命令
当模块涉及常见引擎概念时,可以增加 Unity 对照,但必须克制且准确。
推荐写法:
- “可以把 `Logger` 理解为比 Unity Console 更底层的日志分发中心。”
- “当前 `Profiler` 只覆盖轻量 CPU 埋点,不等同于 Unity Profiler 的完整时间线分析。”
-`RenderDocCapture` 更接近引擎内置的 RenderDoc 工作流桥接,而不是 Unity Frame Debugger 的替代品。”
禁止写法:
- “和 Unity 完全一样”
- “等价于某商业引擎的完整系统”
## 页面模板
### 1. 模块页模板
```markdown
# {DirName}
**命名空间**: `{Namespace}`
**类型**: `module` / `submodule` / `module-root`
**描述**: {一句话说明当前目录职责}
## 概述
{解释职责边界、典型场景和相邻模块关系}
## 设计要点
- {要点 1}
- {要点 2}
## 头文件
- [TypeA](TypeA/TypeA.md) - `TypeA.h`
- [TypeB](TypeB/TypeB.md) - `TypeB.h`
## 相关指南
- [GuideA](../../_guides/.../GuideA.md)
```powershell
rg --files docs/api/XCEngine
rg --files tests/Editor
rg -n "SymbolName" engine/include engine/src editor/src tests docs/api
python -B docs/api/_tools/audit_api_docs.py
```
### 2. 类型页模板
## 一个最小完成定义
```markdown
# {TypeName}
一次 API 文档任务只有同时满足下面条件才算完成:
**命名空间**: `{Namespace}`
**类型**: `class` / `class (abstract)` / `class (singleton)` / `struct` / `enum class`
**头文件**: `XCEngine/.../{Header}.h`
**描述**: {一句话说明}
## 概述
{说明角色、状态、边界、典型使用方式}
## 生命周期
- {初始化与销毁方式}
## 线程语义
- {线程安全说明}
## 公开成员
| 成员 | 说明 |
|------|------|
| [Initialize](Initialize.md) | {说明} |
| [Shutdown](Shutdown.md) | {说明} |
```
### 3. 方法页模板
```markdown
# {TypeName}::{MethodName}
{一句话说明方法职责}
```cpp
{完整签名}
```
## 行为说明
{说明前置条件、后置状态、副作用和当前实现细节}
## 参数
- `param` - {描述}
## 返回值
- `{Type}` - {描述}
## 线程语义
- {线程安全、只建议初始化阶段调用、或必须同线程配对等}
## 示例
```cpp
{}
```
```
## 验收清单
- `docs/api/XCEngine/**` 与 `engine/include/XCEngine/**` 目录平行
- canonical 树下没有模块级 `README.md`
- 每个 public header 都有对应类型目录
- 每个类型总览页都位于 `{TypeName}/{TypeName}.md`
- 方法页使用原函数名或规范化运算符名
- 所有链接都指向真实存在的 `.md` 页面
- 文档中明确区分接口契约、当前实现和合理推断
- 重要模块拥有必要的 guide 页
- 重要限制、stub、平台条件和线程语义都已写清
- 对应源码、测试、调用链已经核对
- 文档页内容已经改到当前实现
- 过期页面和交叉链接已经清理
- 任务池记录已最小更新
- 审计脚本重新执行且结果全绿