From 62578d9df4624e17cdd38aa7f6c802999ee79c72 Mon Sep 17 00:00:00 2001 From: iven Date: Wed, 22 Apr 2026 22:49:08 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20wiki=20=E7=9F=A5=E8=AF=86=E5=BA=93?= =?UTF-8?q?=E7=BC=96=E5=88=B6=E6=96=B9=E6=B3=95=E8=AE=BA=20=E2=80=94=20?= =?UTF-8?q?=E5=9F=BA=E4=BA=8EZCLAW=E5=AE=9E=E6=88=98=E6=8F=90=E7=82=BC?= =?UTF-8?q?=E7=9A=84=E5=8F=AF=E5=A4=8D=E7=94=A8=E6=8C=87=E5=8D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 6条设计原则 + 5节模块模板 + 集成契约/不变量/症状导航机制 + 维护工作流 + AI辅助开发特殊考量 + 检查清单 Co-Authored-By: Claude Opus 4.7 --- docs/wiki-methodology.md | 360 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 docs/wiki-methodology.md diff --git a/docs/wiki-methodology.md b/docs/wiki-methodology.md new file mode 100644 index 0000000..4d5a096 --- /dev/null +++ b/docs/wiki-methodology.md @@ -0,0 +1,360 @@ +# 项目 Wiki 知识库编制方法论 + +> 基于 ZCLAW 项目实战经验(10 crates + React 前端,~155KB wiki 重构)提炼。 +> 适用于任何有 AI 辅助开发参与的中大型项目。 +> **一句话总结**:Wiki 只记录代码无法告诉你的东西。 + +--- + +## 一、设计原则 + +### 原则 1:Wiki 记录"代码不能告诉你的" + +| 记录在 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 个页面,就需要去重。 + +### 原则 5:Append-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 行 | 控住 |