--- name: dev-changelog description: >- 三层开发进程记录系统。在 Agent 完成代码改动后自动记录,提供从一句话概要到完整日志的 多级上下文,帮助 Agent 在跨会话场景下保持对项目开发进展的感知。 当用户提到"开发日志"、"changelog"、"最近改了什么"、"回顾改动"等时触发。 --- # Dev Changelog 三层开发进程记录系统,解决 Agent 跨会话的上下文断裂问题。 ## 三层架构 | 层级 | 文件 | 信息密度 | 条目数量 | 注入方式 | |------|------|---------|---------|---------| | L1 完整版 | `changelog-full.md` | 高(5-15 行/条) | 无上限,只追加 | 用户手动唤醒 | | L2 中期版 | `changelog-recent.md` | 中(3-5 行/条) | 滚动窗口 ~20 条 | 检测到关联时自动读取 | | L3 概要版 | `changelog-headlines.md` | 低(1 行/条) | 滚动窗口 ~50 条 | 每次会话自动注入 | 所有数据文件存放在 `.claude/changelog/` 目录下。 ## 锚点 ID 机制 每条记录在写入时生成一个**锚点 ID**,格式为 `CL-YYYYMMDD-HHMM`(如 `CL-20260424-1430`)。 同一分钟内有多条时追加字母后缀(`CL-20260424-1430a`、`CL-20260424-1430b`)。 锚点 ID 在三层文件中保持一致,用于跨层精准定位: - L3 一句话条目以 `[CL-xxx]` 开头 - L2 摘要条目的 H3 标题包含 `[CL-xxx]` - L1 完整条目的 H3 标题包含 `[CL-xxx]` 这使得从 L3 → L2 → L1 的逐级查找可以通过 Grep 精准定位,无需全文读取。 ## 逐级上溯机制 当 Agent 在使用 L3 概要作为上下文时,如果某条记录的一句话描述**语义模糊** (如无法判断改动的具体范围、与当前任务的关系不明确),执行以下逐级查找: ``` 1. 从 L3 条目中提取锚点 ID(如 CL-20260424-1430) 2. 在 changelog-recent.md(L2)中 Grep 该 ID - 找到 → 读取该条目的 3-5 行摘要,通常足以消除歧义 - 未找到(已滚出 L2 窗口)→ 进入步骤 3 3. 在 changelog-full.md(L1)中 Grep 该 ID - 找到 → 用 Read 工具读取该 ID 所在行号 ±20 行范围(精准读取,不读全文) - 未找到 → 放弃上溯,该条目上下文不可用 ``` ### 上溯原则 - **按需触发**:只有在 L3 信息不足以支撑当前任务判断时才上溯,不预防性地批量读取 - **精准读取**:对 L1 的访问必须通过 Grep 定位行号 + Read 局部读取,禁止全文读取 - **最小化**:一次上溯通常只涉及 1-3 条记录,不批量上溯 ## 操作 A:记录写入(核心流程) ### 触发条件 Agent 完成了一个涉及**代码或配置文件实质性改动**的任务后,自动触发。 以下情况**不触发**: - 纯对话讨论、方案设计、问题解答(无文件改动) - 只读操作(查看文件、搜索代码) - 只改动了 `.claude/` 目录下的基础设施文件(如 changelog 自身、hook 脚本等) ### 写入流程 ``` 1. 生成锚点 ID:CL-YYYYMMDD-HHMM(检查是否与已有 ID 冲突,冲突则追加字母后缀) 2. 从刚完成的任务中提取以下信息: - 做了什么(what):一句话概括 - 为什么这样做(why):动机和背景 - 改了哪里(where):受影响的文件/模块列表 - 关键决策(decisions):如果有方案选择,记录选了什么、放弃了什么 - 注意事项(notes):后续可能受影响的地方、已知限制等 3. 生成三层内容(共享同一个锚点 ID): - L1 完整条目(包含以上全部信息) - L2 摘要条目(what + why + where,3-5 行) - L3 一句话(what,不超过 80 字) 4. 写入三个文件(按以下顺序): a. 读取 changelog-full.md,在 "## 记录" 下方追加 L1 条目 b. 读取 changelog-recent.md,在顶部插入 L2 条目,如超过 20 条则移除最旧的 c. 读取 changelog-headlines.md,在顶部插入 L3 条目,如超过 50 条则移除最旧的 5. 在回复末尾附一行提示:"[已记录到开发日志]" ``` ### 静默写入原则 - **不需要用户确认**——Agent 自己做的改动,对"做了什么"的认知是一手的 - 用户如果觉得记录不准确,可通过操作 D 修改或删除 - 回滚操作也要记录("回退了 XX 改动"),真实反映开发过程 ## 操作 B:L2 自动触发读取 ### 触发条件 由 `changelog-recall.md` Rule 调度。当 Agent 开始处理一个新任务时,判断该任务是否 与近期改动相关。 ### 匹配策略(文件 + 标签双匹配) ``` 1. 从当前任务中提取: - 涉及的文件路径 - 语义关键词(模块名、功能领域等) 2. 读取 changelog-recent.md,逐条检查: - 硬匹配:当前任务涉及的文件出现在条目的 affected_files 中 - 软匹配:当前任务的语义关键词与条目的 tags 有交集 3. 任一匹配命中 → 将匹配到的 L2 条目作为上下文纳入考量 4. 在回复中自然融入,不显式提及"根据开发日志" ``` ## 操作 C:L1 手动检索 ### 触发条件 用户主动要求回顾完整改动记录时触发。典型话语: - "回顾一下最近的改动" - "XX 模块之前改过什么" - "查看开发日志" - "changelog" ### 流程 ``` 1. 读取 changelog-full.md 2. 根据用户需求过滤: - 按时间范围 - 按模块/文件 - 按 tags 3. 展示匹配的条目摘要表,用户可以进一步查看某条的完整内容 ``` ## 操作 D:记录管理 用户可以对已有记录进行管理: | 操作 | 说明 | |------|------| | 删除 | 从三层文件中同步移除对应条目 | | 修改 | 修改某条记录的描述(三层同步更新) | | 清理 | 手动触发 L1 的归档(如按月分文件,暂不实现,作为演进方向) | ## 条目格式 ### L1 完整条目 ```markdown ### [CL-20260424-1430] YYYY-MM-DD HH:MM — 一句话标题 - **tags**: tag1, tag2, tag3 - **affected_files**: - path/to/file1 - path/to/file2 - **what**: 做了什么的简要描述 - **why**: 动机和背景 - **decisions**: 选择了 A 方案(放弃了 B 因为 xxx) - **notes**: 后续注意事项 - **source_chat**: [对话简述](chat-uuid) ``` ### L2 摘要条目 ```markdown ### [CL-20260424-1430] YYYY-MM-DD — 一句话标题 - **tags**: tag1, tag2, tag3 - **affected_files**: file1, file2 - **summary**: 做了什么 + 为什么(3-5 行) ``` ### L3 一句话条目 ```markdown - [CL-20260424-1430] 一句话描述改动内容(不超过 80 字) ``` ## 滚动窗口维护 ### L2 窗口(~20 条) ``` 写入新条目后,检查总条目数: - <= 20 条:不做处理 - > 20 条:移除文件底部(最旧的)条目,直到恰好 20 条 ``` ### L3 窗口(~50 条) ``` 写入新条目后,检查总行数(排除文件头部的标题和说明): - <= 50 条:不做处理 - > 50 条:移除文件底部(最旧的)条目,直到恰好 50 条 ``` 被移除的条目不需要额外归档——L1 完整版保留了所有历史。 ## 数据文件模板 首次写入时,如对应文件不存在,按以下模板创建。 ### changelog-full.md ```markdown # Dev Changelog — Full 完整的开发改动记录,按时间倒序排列。作为主动 RAG 的数据源,用户手动唤醒时读取。 ## 记录 ``` ### changelog-recent.md ```markdown # Dev Changelog — Recent 最近 ~10 次改动的摘要记录,按时间倒序排列。 当 Agent 检测到当前任务与近期改动相关时自动读取。 ``` ### changelog-headlines.md ```markdown # Dev Changelog — Headlines 最近 ~50 次改动的一句话概要,按时间倒序排列。每次会话自动注入上下文。 ``` ## 与其他系统的协作 | 系统 | 关系 | 说明 | |------|------|------| | `changelog-recall` Rule | 下游消费者 | 每次会话注入 L3,自动触发 L2 读取,并在 Checklist 中强制调用本 Skill | | `check-changelog` Hook | 被动守护 | stop hook 比较源文件 mtime 和 changelog-headlines.md,发现未同步时提醒调用本 Skill | | `claude-init` Skill | 重置器 | init 阶段 3 会重置 changelog 三层数据文件 | | `epee-orchestrator` Skill | 注册 | 在 registry.md 中注册本 Skill | | `pitfall-journal` Skill | 互补 | changelog 记改动事实,pitfall 记经验教训 | | `deferred-decisions` Skill | 互补 | deferred 记"没做什么",changelog 记"做了什么" | ## 自迭代日志 本节记录使用本 Skill 过程中发现的必要检查项。 ### 已知必要检查 1. **大任务收尾遗漏风险** — 当单次任务涉及 5+ 个文件改动时,Agent 容易在输出总结回复后遗漏被动写入流程。应在生成最终回复前,先执行 `changelog-recall.md` 中的"任务完成 Checklist",确认三层日志已写入后再输出回复。绝不能"先回复再补写"。 2. **L3/L2 滚动窗口必须落地** — 操作 A 第 4 步不是「插入即结束」:写入后必须数清条目(L3 为以 `- [` 开头的列表行,L2 为 `### [CL-` 标题行)。L3 超过 50 条、L2 超过 20 条时,必须从**文件底部(最旧)**整段删除条目直至恰好满足上限;禁止长期只追加不修剪。若发现 `changelog-headlines.md` 列表行多于 50,说明上次写入未执行本项,本次补修剪并自检。 3. **顶部插入 Edit 范式(L1/L2)** — L1 和 L2 的每个条目都是多行结构(标题 + 多条 `- **字段**:`)。使用 Edit 工具在顶部插入新条目时,`old_string` 有且仅有两种合法选择: (a) 只包含新条目之前的"稳定前缀"(如 L1 的 `## 记录\n\n` 或 L2 的整段文件头说明),**不触及任何已有条目的任何一行**;`new_string` = 稳定前缀 + 新条目完整内容 + 空行。 (b) 把旧首条目的**完整多行内容**(标题行 + 全部字段行)都纳入 `old_string`;`new_string` = 新条目完整内容 + 空行 + 旧首条目完整内容。 **绝对禁止**:只把旧首条目的标题行(或前 1-2 字段)当 anchor 而不带上剩余字段行——Edit 会吞掉这些 anchor 行但不动剩余字段,造成"旧标题丢失、字段游离"的半损坏状态。 **写入后自检**:Read 文件头部 30 行,确认看到新条目完整 + 旧首条目标题行仍存在且字段完整跟随。L3 的一行条目不受本条约束(它就是单行,天然无此风险)。