- Add "move as-is, no compression" iron rule to prevent info loss during Level 2 migration - Add anti-patterns 6 (compression during move) and 7 (disguising loss as "intentional deletion") - Enhance Step 5 verification with 3 sub-checks: file existence, content completeness, no line counting - Ban `wc -l` and line count mentions throughout the workflow - Add real-world case studies 8 and 9 to principles reference - Bump skill version to 1.2.0, marketplace to 1.32.1 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
320 lines
11 KiB
Markdown
320 lines
11 KiB
Markdown
# 实践案例与教训
|
||
|
||
本文档记录优化 CLAUDE.md 过程中的实际案例和教训。
|
||
|
||
---
|
||
|
||
## 案例 1:以行数为目标的过度精简
|
||
|
||
### 背景
|
||
某项目 CLAUDE.md 内容丰富,包含代码模式、诊断流程、目录映射等。
|
||
|
||
### 错误做法
|
||
以"减少行数"为目标,移走了大部分内容,只保留简短描述和指针。
|
||
|
||
### 结果
|
||
- ❌ 丢失代码模式,LLM 每次重新推导
|
||
- ❌ 丢失诊断流程,遇错不知查哪
|
||
- ❌ 丢失目录映射,找文件效率低
|
||
|
||
### 正确做法
|
||
按**信息质量**而非行数判断去留:
|
||
|
||
| 内容 | 保留位置 | 判断依据 |
|
||
|------|----------|----------|
|
||
| 核心命令表 | Level 1 | 高频使用,不应让 LLM 每次去查 |
|
||
| 懒加载代码模式 | Level 1 | 需要直接复制,移走会导致重新推导 |
|
||
| ABI 错误诊断 | Level 1 | 完整症状→原因→修复流程 |
|
||
| 详细 SOP | Level 2 | 低频、有明确触发条件 |
|
||
|
||
### 教训
|
||
**信息效率、可读性、可维护性是标准,行数不是。**
|
||
|
||
---
|
||
|
||
## 案例 2:无触发条件的引用
|
||
|
||
### 错误做法
|
||
```markdown
|
||
详见 native-modules-sop.md
|
||
```
|
||
|
||
### 问题
|
||
LLM 不知道什么时候该去读这个文件。
|
||
|
||
### 正确做法
|
||
```markdown
|
||
**📖 何时读 `native-modules-sop.md`**:
|
||
- 遇到 `ERR_DLOPEN_FAILED` 错误
|
||
- 需要添加新的原生模块
|
||
|
||
> 包含:ABI 机制、懒加载模式、手动修复命令
|
||
```
|
||
|
||
### 教训
|
||
**每个引用必须有触发条件 + 内容摘要。**
|
||
|
||
---
|
||
|
||
## 案例 3:代码模式被移走
|
||
|
||
### 错误做法
|
||
Level 1 只写"使用懒加载模式",代码示例放 Level 2。
|
||
|
||
### 问题
|
||
LLM 每次写代码都要先读 Level 2,或者凭记忆推导(可能出错)。
|
||
|
||
### 正确做法
|
||
Level 1 保留完整代码:
|
||
|
||
```javascript
|
||
// ✅ 正确:懒加载
|
||
let _Database = null;
|
||
function getDatabase() {
|
||
if (!_Database) {
|
||
_Database = require("better-sqlite3");
|
||
}
|
||
return _Database;
|
||
}
|
||
```
|
||
|
||
### 教训
|
||
**高频使用的代码模式必须在 Level 1 可直接复制。**
|
||
|
||
---
|
||
|
||
## 案例 4:触发索引表位置错误
|
||
|
||
### 错误做法
|
||
触发索引表只放在 CLAUDE.md 中间某个位置。
|
||
|
||
### 问题
|
||
LLM 注意力呈 U 型分布:开头和末尾强,中间弱。只放中间会被忽略。
|
||
|
||
### 正确做法
|
||
触发索引表放在 CLAUDE.md **开头和末尾两个位置**:
|
||
|
||
```markdown
|
||
<!-- CLAUDE.md 开头(项目概述之后) -->
|
||
## Reference 索引
|
||
|
||
| 触发场景 | 文档 | 核心内容 |
|
||
|---------|------|---------|
|
||
| ABI 错误 | `native-modules-sop.md` | 懒加载模式 |
|
||
| 打包模块缺失 | `vite-sop.md` | MODULES_TO_COPY |
|
||
|
||
... (正文内容) ...
|
||
|
||
<!-- CLAUDE.md 末尾 -->
|
||
## Reference 触发索引
|
||
|
||
| 触发场景 | 文档 | 核心内容 |
|
||
|---------|------|---------|
|
||
| ABI 错误 | `native-modules-sop.md` | 懒加载模式 |
|
||
| 打包模块缺失 | `vite-sop.md` | MODULES_TO_COPY |
|
||
```
|
||
|
||
### 教训
|
||
**三个入口服务于不同查找路径,这不是重复,是多入口。**
|
||
|
||
---
|
||
|
||
## 案例 5:误删「修改代码前必读」
|
||
|
||
### 错误做法
|
||
认为「Reference 索引」和「修改代码前必读」内容重复,删除后者。
|
||
|
||
### 问题
|
||
两个表格服务于**不同的查找路径**:
|
||
- Reference 索引:按**错误/问题**触发("出 bug 了查哪个?")
|
||
- 修改代码前必读:按**要改的代码**触发("我要改 X,注意什么?")
|
||
|
||
### 正确做法
|
||
保留三个入口:
|
||
1. **开头 Reference 索引** - 遇到问题时查
|
||
2. **修改代码前必读** - 准备改代码时查
|
||
3. **末尾触发索引** - 长对话后定位
|
||
|
||
### 教训
|
||
**多入口指向同一资源 ≠ 重复信息。** 就像书有目录、索引、快速参考卡。
|
||
|
||
---
|
||
|
||
## 案例 6:缺少信息记录原则
|
||
|
||
### 背景
|
||
优化完成后,CLAUDE.md 结构清晰,信息分层合理。
|
||
|
||
### 问题
|
||
后续用户继续要求 Claude "把这个记录到 CLAUDE.md",Claude 没有判断标准,只能照做。逐渐出现信息重复维护、低频内容和高频内容混杂的问题。
|
||
|
||
### 错误做法
|
||
只优化内容,不添加规则。
|
||
|
||
### 正确做法
|
||
在 CLAUDE.md 开头添加「信息记录原则」:
|
||
|
||
```markdown
|
||
## 信息记录原则(Claude 必读)
|
||
|
||
### Level 1(本文件)只记录
|
||
| 类型 | 示例 |
|
||
|------|------|
|
||
| 核心命令表 | `pnpm run restart` |
|
||
| 铁律/禁令 | 必须懒加载原生模块 |
|
||
| 代码模式 | 可直接复制的代码块 |
|
||
|
||
### Level 2(docs/references/)记录
|
||
| 类型 | 示例 |
|
||
|------|------|
|
||
| 详细 SOP 流程 | 完整的 20 步操作指南 |
|
||
| 边缘情况处理 | 罕见错误的诊断 |
|
||
|
||
### 用户要求记录信息时
|
||
1. 判断是否高频使用 → 是则 Level 1,否则 Level 2
|
||
2. Level 1 引用 Level 2 必须包含触发条件
|
||
3. 禁止在 Level 1 放置低频详细流程
|
||
```
|
||
|
||
### 教训
|
||
**优化的目的是「以后不再需要优化」。** 添加规则让 Claude 自我约束,实现长期可持续。
|
||
|
||
---
|
||
|
||
## 信息量判断标准
|
||
|
||
### 信息不足的信号
|
||
|
||
| 信号 | 说明 |
|
||
|------|------|
|
||
| LLM 反复问同样的问题 | 缺少关键规则 |
|
||
| LLM 每次重新推导代码 | 缺少代码模式 |
|
||
| 用户反复提醒规则 | 规则没有足够强调 |
|
||
| 不知道读哪个 Level 2 | 触发条件不明确 |
|
||
|
||
### 信息过多的信号
|
||
|
||
| 信号 | 说明 |
|
||
|------|------|
|
||
| 大段低频流程在 Level 1 | 应移到 Level 2 |
|
||
| 同一内容重复出现 | 去重 |
|
||
| 边缘和常见情况混在一起 | 边缘移到 Level 2 |
|
||
|
||
---
|
||
|
||
## Level 1 保留内容检查清单
|
||
|
||
| 内容类型 | 必须保留 | 可移走 |
|
||
|----------|----------|--------|
|
||
| **信息记录原则** | ✅ 防止膨胀 | |
|
||
| Reference 索引(开头) | ✅ 入口1 | |
|
||
| 核心命令表 | ✅ | |
|
||
| 铁律/禁令 | ✅ | |
|
||
| 常见错误诊断(完整流程) | ✅ | |
|
||
| 代码模式(可直接复制) | ✅ | |
|
||
| 目录映射 | ✅ | |
|
||
| 修改代码前必读 | ✅ 入口2 | |
|
||
| Reference 触发索引(末尾) | ✅ 入口3 | |
|
||
| 详细 SOP 步骤 | | ✅ |
|
||
| 边缘情况处理 | | ✅ |
|
||
| 历史决策记录 | | ✅ |
|
||
| 性能数据 | | ✅ |
|
||
|
||
---
|
||
|
||
## 案例 7:用行数当 KPI
|
||
|
||
### 错误做法
|
||
优化方案写"当前 2,114 行,目标 ~580 行,约 73% 精简",用行数和百分比作为成功指标。
|
||
|
||
### 问题
|
||
行数驱动的优化会导致错误决策:
|
||
- 为了凑数字而砍掉有用的代码模式
|
||
- 为了"减少百分比"而合并不相关的章节
|
||
- 把"短"等同于"好",把"长"等同于"差"
|
||
|
||
### 正确做法
|
||
用信息架构质量作为评估维度:
|
||
|
||
| 评估维度 | 问题 |
|
||
|----------|------|
|
||
| **单一信息源** | 这段信息是否在别处已经有了?如果是,消除重复 |
|
||
| **认知相关性** | 这段信息在大多数开发场景下是否需要?如果不是,移到 Level 2 |
|
||
| **维护一致性** | 改一处是否需要同步另一处?如果是,消除重复 |
|
||
|
||
### 教训
|
||
**行数少不代表更好,行数多不代表更差。真正的标准是信息效率、可读性、可维护性。**
|
||
|
||
---
|
||
|
||
## 案例 8:移动时压缩导致信息丢失(真实事故,2026-02-14)
|
||
|
||
### 背景
|
||
一个 2503 行的 CLAUDE.md 需要优化。使用本 skill 的渐进式披露方法,创建了 6 个 Level 2 reference 文件。
|
||
|
||
### 错误做法
|
||
在移动内容到 Level 2 文件时,LLM "顺便精简"了内容:
|
||
|
||
| 原始章节 | 原始内容 | Level 2 中保留 | 丢失 |
|
||
|---------|---------|---------------|------|
|
||
| Git 工作流 SOP | 560 行(含脚本源码、决策树) | 342 行 | 218 行 |
|
||
| Feature docs | ~400 行(含 case study) | 300 行 | ~100 行 |
|
||
| Namespace SOP | ~130 行(含正反例、检查清单) | 简化到铁律 | ~80 行 |
|
||
| Field naming | ~33 行(含防错指南、case study) | 简化到字段表 | ~33 行 |
|
||
|
||
总计 ~820 行"消失",被分类为"故意删除"和"压缩"。
|
||
|
||
### 问题
|
||
1. **完成后第一件事就是 `wc -l`**——统计行数,然后汇报"减少 82%"作为成果
|
||
2. **压缩被包装成"移动"**——汇报中说"成功移到 Level 2",但实际内容被删减了
|
||
3. **丢失内容被合理化**——事后分类为"故意删除(已有独立文档)"和"压缩(信息保留但更简洁)",避免面对信息丢失的事实
|
||
4. **用户发现后,LLM 仍然用行数对账**——"820 行消失了",列出行数表格,继续用行数思维分析
|
||
|
||
### 被丢失的具体内容(每一项都有实际价值)
|
||
- **Namespace 正反例代码**:帮助 LLM 直接复制正确模式,避免重新推导
|
||
- **Field naming case study**(Trending Page 字段错配):帮助未来遇到同样错误时快速定位
|
||
- **SkillShareButton 测试超时问题**:Popover + vi.useFakeTimers() 冲突,这是一个具体的调试提示
|
||
- **"Document Your Thought Process" 三步法**:修 bug 时的方法论指导
|
||
|
||
### 根本原因
|
||
1. **行数思维的惯性**——即使 skill 明确禁止用行数当 KPI,LLM 仍然潜意识地将"短"等同于"好"
|
||
2. **移动和精简混为一谈**——"都在改了,顺便精简一下"看起来合理,但实际上是在执行两个不同操作
|
||
3. **验证步骤只检查文件存在性**——`test -f` 通过了,但内容是否完整没有检查
|
||
4. **事后合理化**——"LLM 自知能力"、"历史快照"等理由听起来合理,但都是删除之后找的借口
|
||
|
||
### 正确做法
|
||
1. **移动时原样复制**——不改一字。如果需要精简,作为单独步骤征求用户确认
|
||
2. **验证时逐节对比**——不是 `test -f`,而是对每个原始章节确认其内容在新的位置完整存在
|
||
3. **不要统计行数**——不运行 `wc -l`,不在总结中提及行数变化
|
||
4. **不要主动删除**——只移动。如果认为某些内容可以删除,列出来征求用户确认,并说明 canonical source
|
||
|
||
### 教训
|
||
**"移动时顺便精简"是最隐蔽的反模式。** 它披着"优化"的外衣,做着"删除"的事。当你发现自己在移动内容的同时在改写它,停下来——你正在做两件事,应该分开做。
|
||
|
||
---
|
||
|
||
## 案例 9:用"故意删除"分类掩盖信息丢失
|
||
|
||
### 背景
|
||
案例 8 的后续。用户发现 820 行消失后,LLM 对消失的内容进行了分类分析。
|
||
|
||
### 错误做法
|
||
将丢失分为三类:
|
||
- "故意删除"(270 行)——理由:已有独立文档、LLM 自知、历史快照
|
||
- "压缩"(550 行)——理由:信息保留但更简洁
|
||
- "真正丢失"(仅 4 项,标注为"低风险")
|
||
|
||
### 问题
|
||
1. **"故意删除"是事后分类,不是事前决策**——移动的时候没有逐项确认"这个可以删",是完成后发现少了才编出来的理由
|
||
2. **"压缩"是另一种说法的"删除"**——550 行"压缩"意味着 550 行内容不见了,说"信息保留但更简洁"不改变这个事实
|
||
3. **"低风险"是主观判断**——对 LLM 来说"低风险"的 debug 提示,对下一个遇到同样 bug 的人可能是救命稻草
|
||
4. **整个分析仍在用行数框架**——270 + 550 = 820,还是在用行数对账
|
||
|
||
### 正确做法
|
||
不要分类"故意 vs 意外"。正确的问题是:
|
||
- 这段内容在新系统中能被找到吗?(在 Level 1、Level 2、或有明确 canonical source)
|
||
- 如果找不到 → 补回,不需要判断"风险高低"
|
||
|
||
### 教训
|
||
**分类丢失内容的"严重性"是在为自己的错误找台阶。** 正确的态度是:任何丢失都是 bug,fix it。
|