Files
zclaw_openfang/docs/wiki-methodology.md
iven 62578d9df4
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
docs: wiki 知识库编制方法论 — 基于ZCLAW实战提炼的可复用指南
6条设计原则 + 5节模块模板 + 集成契约/不变量/症状导航机制
+ 维护工作流 + AI辅助开发特殊考量 + 检查清单

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 22:49:08 +08:00

361 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 项目 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 行 | 控住 |