docs: wiki 知识库编制方法论 — 基于ZCLAW实战提炼的可复用指南
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

6条设计原则 + 5节模块模板 + 集成契约/不变量/症状导航机制
+ 维护工作流 + AI辅助开发特殊考量 + 检查清单

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
iven
2026-04-22 22:49:08 +08:00
parent 9756d9d995
commit 62578d9df4

360
docs/wiki-methodology.md Normal file
View File

@@ -0,0 +1,360 @@
# 项目 Wiki 知识库编制方法论
> 基于 ZCLAW 项目实战经验10 crates + React 前端,~155KB wiki 重构)提炼。
> 适用于任何有 AI 辅助开发参与的中大型项目。
> **一句话总结**Wiki 只记录代码无法告诉你的东西。
---
## 一、设计原则
### 原则 1Wiki 记录"代码不能告诉你的"
| 记录在 Wiki ✅ | 不记录在 Wiki ❌ |
|---------------|-----------------|
| 为什么这样设计WHY | 字段列表、函数签名 |
| 跨模块数据流走向 | 单文件内的代码逻辑 |
| 历史踩坑和教训 | 可用 `grep` 直接查到的信息 |
| 必须始终成立的约束(不变量) | CRUD 操作、getter/setter |
| 模块间调用接口(集成契约) | 具体的行号、变量名 |
**判断标准**:如果 `git log``grep` 能在 30 秒内回答这个问题,就不需要写在 wiki 里。
### 原则 2每个模块页统一 5 节结构
按**阅读优先级**排列(先给最重要的信息):
```
1. 设计决策 (WHY) — 为什么这样设计、历史背景、权衡取舍
2. 关键文件 + 数据流 — 3-7 个核心文件 + 跨模块接口
3. 代码逻辑 — 数据流走向 + 不变量 + 非显而易见的算法
4. 活跃问题 + 陷阱 — 当前未解决 + 历史教训
5. 变更记录 — 最近 5 条,超出的归入全局日志
```
**为什么是这个顺序**:新的 AI 会话(或开发者)首先需要知道"这个模块为什么存在"和"文件在哪",然后才是"怎么工作的",最后是"有什么问题"。
### 原则 3页面大小必须有预算
| 页面类型 | 行数预算 | 原因 |
|---------|---------|------|
| 首页/索引 | ≤ 120 行 | 需要快速扫描AI 一次加载 |
| 模块页 | 100-200 行 | AI 一次加载 2-3 个模块不爆 context |
| 全局日志 | ≤ 50 条活跃 | 防止无限膨胀,旧条目归档 |
**超过预算怎么办**:把详细内容归档到 `archive/` 目录,模块页只保留摘要 + 链接。
### 原则 4单一真相源
同一信息只出现在一个页面。其他需要该信息的地方只放引用。
```
错误:安全认证流程同时写在 saas.md、security.md、middleware.md
正确security.md 拥有完整描述saas.md 只写"详见 [[security]]"
```
**检查方法**`grep` 关键内容,如果出现在 ≥ 3 个页面,就需要去重。
### 原则 5Append-only 内容必须封顶
日志、问题列表等只增不减的内容,必须设置上限并定期归档。
```
活跃日志 ≤ 50 条 → 旧条目归入 archive/log-{YYYY-MM}.md
活跃问题 ≤ 5 条/模块 → 修复后立即移除
变更记录 ≤ 5 条/模块 → 旧记录在全局 log.md
```
### 原则 6用症状导航补充模块导航
模块导航解决"这个模块是什么"的问题。但实际开发中,人们更多是在解决"出了问题该看哪里"。
**症状导航表**格式:
| 症状 | 先查 | 再查 | 常见根因 |
|------|------|------|----------|
| 流式响应卡住 | routing | chat → middleware | 连接断开 / 超时 |
| 数据没持久化 | data-model | 对应模块 | 表结构 / 迁移缺失 |
放在首页/索引页,让新来的人(或 AI 会话0 跳就能定位排查方向。
---
## 二、结构模板
### 2.1 三级层级
```
项目 Wiki
├── Level 1: index.md — 纯导航 + 症状索引(≤ 120 行)
├── Level 2: {module}.md — 每个功能模块一个页面100-200 行)
├── Level 3: archive/ — 历史内容归档
└── (可选) known-issues.md — 活跃问题全局索引
```
### 2.2 首页模板 (index.md)
```markdown
# {项目名} 知识库
> 一句话定位。使用方式说明。
## 关键数字
| 指标 | 值 | 验证方式 |
|------|-----|---------|
## 系统数据流
{ASCII 全景图}
## 模块导航
- [[module-a]] — 一句话说明
- [[module-b]] — 一句话说明
## 症状导航
| 症状 | 先查 | 再查 | 常见根因 |
|------|------|------|----------|
```
### 2.3 模块页模板 ({module}.md)
```markdown
---
title: {模块名}
updated: {YYYY-MM-DD}
status: active | stable | developing
tags: [{tags}]
---
# {模块名}
> 从 [[index]] 导航。关联: [[related-1]] [[related-2]]
## 1. 设计决策
{为什么这样设计、历史背景、权衡取舍}
{用 Q&A 格式记录关键架构决策}
## 2. 关键文件 + 数据流
### 核心文件
| 文件 | 职责 |
|------|------|
| `path/to/file` | 一句话说明 |
### 数据流
{ASCII 流程图}
### 集成契约
| 方向 | 模块 | 接口 | 触发时机 |
|------|------|------|---------|
| 调用 → | {module} | `{function/API}` | {when} |
| 被调用 ← | {module} | `{function/API}` | {when} |
## 3. 代码逻辑
### 关键数据流
{跨函数/跨文件的完整路径,附意图说明}
### 不变量
⚡ {不变量 1}: {必须始终成立的约束}
⚡ {不变量 2}: {描述}
### 非显而易见的算法
{读代码难以理解的逻辑}
## 4. 活跃问题 + 陷阱
### 活跃问题
| 问题 | 级别 | 状态 | 说明 |
|------|------|------|------|
{0-5 条,修复后移除}
### 历史教训
- {教训}: {一句话描述}
### 注意事项
⚠️ {易出错的地方}
## 5. 变更记录
| 日期 | 变更 |
|------|------|
{最近 5 条}
```
---
## 三、关键机制详解
### 3.1 集成契约
**问题**:跨模块边界的信息(谁调谁、接口形状)是最难从代码中获取的知识,也是 wiki 最大的结构性缺口。
**做法**:每个模块页的"关键文件"节下增加一个"集成契约"小表,回答四个问题:
| 问题 | 对应列 |
|------|--------|
| 这个模块调用了谁? | 调用 → |
| 这个模块被谁调用? | 被调用 ← |
| 通过什么接口? | 接口(函数名/API路径 |
| 什么时候触发? | 触发时机 |
**示例**(中间件模块):
| 方向 | 模块 | 接口 | 触发时机 |
|------|------|------|---------|
| 被调用 ← | kernel | `create_middleware_chain()` | 内核启动 |
| 调用 → | runtime | `run_before_completion()` | 每次聊天请求 |
| 提供 → | 所有模块 | `AgentMiddleware` trait | 14 个实现 |
### 3.2 不变量标记
**问题**:系统中有一些"必须始终成立的约束",它们不像代码那样显式存在,但一旦被违反就会产生隐蔽的 bug。
**做法**:用 ⚡ 标记不变量,放在"代码逻辑"节下。
```
⚡ Priority 是升序排列0-999数值越小越先执行
⚡ memories.db 和 data.db 是独立数据库,跨库查询需确认目标库
⚡ 记忆注入在中间件@150在管家路由@80之后技能索引@200之前
```
**判断什么是好的不变量**
- 它描述的是一种**关系或顺序**,不是单个组件的行为
- 如果有人不知道这个约束,修改代码时很可能无意中违反它
- 违反的后果不会立即显现,而是演化几轮后变成隐性 bug
### 3.3 去重规则
| 重复类型 | 处理方式 |
|---------|---------|
| 完整描述出现在 A 和 B | 选择一个为真相源,另一个只引用 |
| 相同信息出现在 ≥ 3 页 | 必须去重,指定唯一归属 |
| 概述 vs 详情 | 概述页保留一句话 + 链接,详情页拥有完整描述 |
**去重检查命令**
```bash
grep -l '关键内容' wiki/*.md | wc -l
# 结果 ≥ 3 → 需要去重
```
### 3.4 症状导航
**为什么需要**:模块导航是"模块→功能"方向,但排查问题时需要的是"症状→模块"方向。
**编制方法**
1. 收集团队/AI 会话中反复出现的调试场景8-12 个)
2. 每个场景记录:症状、先查哪个页面、再查哪个、最常见根因
3. 放在首页,新会话/新人 0 跳可达
**示例**
| 症状 | 先查 | 再查 | 常见根因 |
|------|------|------|----------|
| API 返回 502 | saas | routing | Token 耗尽 / 服务超时 |
| 数据不持久 | data-model | 对应模块 | 表缺失 / 字段不匹配 |
| 流式中断 | chat | middleware | 连接断开 / 超时守护 |
---
## 四、维护工作流
### 4.1 什么时候更新 Wiki
| 触发事件 | 更新什么 |
|---------|---------|
| 修复 bug | 对应模块页"活跃问题" + 全局 known-issues 索引 |
| 架构变更 | 对应模块页"设计决策" + 集成契约 |
| 文件结构变化 | 对应模块页"核心文件"表 |
| 跨模块接口变化 | 涉及双方的"集成契约"表 |
| 发现新不变量 | 对应模块页"代码逻辑"节的 ⚡ 项 |
| 每次更新 | 模块页"变更记录"(保持5条) + 全局 log.md |
### 4.2 防止 drift 的策略
| 策略 | 做法 |
|------|------|
| 页面大小预算 | 超过 200 行强制裁剪,移入 archive/ |
| 活跃问题生命周期 | 修复后立即移除,不保留已修复项 |
| 变更记录滑动窗口 | 只保留最近 5 条,旧的自然滚入全局日志 |
| 数字验证 | 关键数字标注验证命令,定期执行确认 |
| "最后验证"日期 | 在 frontmatter 的 `updated` 字段记录,超过 30 天需要复查 |
### 4.3 重构 Wiki 的执行顺序
如果需要对已有 wiki 进行重构,按依赖关系分阶段:
```
Phase 1: 归档/封顶 — 压缩日志、归档旧内容(无依赖)
Phase 2: 确立真相源 — 最被其他页面引用的模块优先重构
Phase 3: 依赖页面 — 引用 Phase 2 模块的页面去重
Phase 4: 剩余模块 — 独立页面逐一重构
Phase 5: 首页/索引 — 最后改(依赖所有模块页完成)
```
**关键约束**:每个模块页独立提交,可安全 `git revert` 回滚单个页面。
---
## 五、AI 辅助开发的特殊考量
### 5.1 Wiki 的主要读者可能是 AI
在 AI 辅助开发中wiki 的主要读者是每次新会话的 AI 实例context 从零开始)。这改变了 wiki 的设计优先级:
| 传统 wiki | AI 辅助 wiki |
|-----------|-------------|
| 详细、全面 | 精炼、可快速加载 |
| 按主题组织 | 按任务场景导航 |
| 历史记录丰富 | 只保留活跃信息 |
| 人工索引 | 症状→页面直接映射 |
### 5.2 Context 预算思维
AI 的 context window 是有限资源。wiki 的每个字节都在消耗这个预算。
**优化策略**
- 首页只放导航,不放内容(让 AI 按需读取模块页)
- 模块页控制在 100-200 行(一次加载 2-3 个不爆 context
- 代码逻辑只写流向和不变量,不写可从代码读取的细节
- 使用 `archive/` 存放低频需要的历史内容
### 5.3 Wiki 作为新会话的启动燃料
设计 wiki 时要问:**一个全新的 AI 会话,读完首页后能定位问题吗?读完 2 个模块页后能开始工作吗?**
如果答案是"不能",说明 wiki 的导航层不够好(首页缺症状导航)或模块页的结构不对(信息不在前两节)。
---
## 六、检查清单
### 创建 Wiki 时
- [ ] 首页 ≤ 120 行,包含:项目一句话定位、关键数字、模块导航、症状导航
- [ ] 每个模块页统一 5 节结构
- [ ] 每个模块页有集成契约表
- [ ] 每个模块页有 ⚡ 不变量
- [ ] 每个模块页 100-200 行
- [ ] 无内容重复出现在 ≥ 3 个页面
- [ ] 全局日志封顶 50 条,有归档机制
### 维护 Wiki 时
- [ ] 修复 bug 后更新对应模块"活跃问题"
- [ ] 架构变更后更新对应模块"设计决策"+ 集成契约
- [ ] 每次更新追加全局 log.md 条目
- [ ] 每次更新模块页变更记录(保持 5 条)
- [ ] 定期检查页面是否超过大小预算
---
## 附录ZCLAW 重构效果
| 指标 | 重构前 | 重构后 | 变化 |
|------|--------|--------|------|
| 模块页总行数 | ~2,800 | ~1,547 | -45% |
| 重复内容 | 安全×3, 进化×3 | 各×1 | 消除 |
| 集成契约覆盖 | 0/10 页 | 10/10 页 | 全覆盖 |
| 症状导航 | 无 | 8 条路径 | 新增 |
| 首页 | 144 行 | 101 行 | +症状导航 |
| 最大单页 | 424 行 | 199 行 | 控住 |