cursor Init 完善多人协同changelog,以及godot相关基础skill和代码规范
This commit is contained in:
@@ -1,259 +1,222 @@
|
||||
---
|
||||
name: dev-changelog
|
||||
description: >-
|
||||
三层开发进程记录系统。在 Agent 完成代码改动后自动记录,提供从一句话概要到完整日志的
|
||||
多级上下文,帮助 Agent 在跨会话场景下保持对项目开发进展的感知。
|
||||
三层开发进程记录系统(fragment 源 + 自动生成视图)。Agent 完成代码改动后,
|
||||
写入一条独立的 fragment 文件并重建视图,提供从一句话概要到完整日志的多级上下文,
|
||||
帮助 Agent 跨会话保持对项目进展的感知,并支持多人协作下的低冲突合并与作者区分。
|
||||
当用户提到"开发日志"、"changelog"、"最近改了什么"、"回顾改动"等时触发。
|
||||
---
|
||||
|
||||
# Dev Changelog
|
||||
|
||||
三层开发进程记录系统,解决 Agent 跨会话的上下文断裂问题。
|
||||
跨会话开发进程记录系统。**数据源是一条一文件的 fragment,三层视图由脚本自动生成。**
|
||||
这套设计同时解决了三个老问题:体量失控、三层手动同步漂移、以及多人协作时 git merge 冲突。
|
||||
|
||||
## 三层架构
|
||||
## 架构总览
|
||||
|
||||
| 层级 | 文件 | 信息密度 | 条目数量 | 注入方式 |
|
||||
|------|------|---------|---------|---------|
|
||||
| L1 完整版 | `changelog-full.md` | 高(5-15 行/条) | 无上限,只追加 | 用户手动唤醒 |
|
||||
| L2 中期版 | `changelog-recent.md` | 中(3-5 行/条) | 滚动窗口 ~20 条 | 检测到关联时自动读取 |
|
||||
| L3 概要版 | `changelog-headlines.md` | 低(1 行/条) | 滚动窗口 ~50 条 | 每次会话自动注入 |
|
||||
```
|
||||
.cursor/changelog/
|
||||
├─ entries/<author>/<id>.md ← 唯一数据源(一条改动 = 一个文件,提交进 git)
|
||||
├─ changelog-full.md ← 视图(L1 完整,全部条目) \
|
||||
├─ changelog-recent.md ← 视图(L2 摘要,最近 ~20 条) | 全部由
|
||||
├─ changelog-headlines.md ← 视图(L3 一句话,最近 ~50 条) | 生成器产出
|
||||
├─ changelog-by-author.md ← 视图(按作者聚合) /
|
||||
└─ tools/
|
||||
├─ changelog_build.py ← 生成器:entries/ → 4 个视图(确定性、stdlib-only)
|
||||
├─ migrate_changelog.py ← 一次性迁移脚本(已执行,留作参考)
|
||||
├─ install-git-hooks.ps1/.sh ← 安装 pre-commit / post-merge git hook
|
||||
└─ git-hooks/{pre-commit,post-merge}
|
||||
```
|
||||
|
||||
所有数据文件存放在 `.cursor/changelog/` 目录下。
|
||||
| 层级 | 视图文件 | 信息密度 | 窗口 | 注入方式 |
|
||||
|------|---------|---------|------|---------|
|
||||
| L1 完整版 | `changelog-full.md` | 高(完整正文) | 全部 | 用户手动唤醒 |
|
||||
| L2 中期版 | `changelog-recent.md` | 中(3-5 行摘要) | ~20 条 | 检测到关联时自动读取 |
|
||||
| L3 概要版 | `changelog-headlines.md` | 低(1 行) | ~50 条 | 每次会话自动注入 |
|
||||
| 作者视图 | `changelog-by-author.md` | 索引 | 全部 | 按需 |
|
||||
|
||||
> **重要**:视图文件顶部都标了"由 changelog_build.py 自动生成,请勿手改"。
|
||||
> 一切修改都改 fragment,再跑生成器。视图改了不算数(下次生成会被覆盖)。
|
||||
|
||||
## 锚点 ID 机制
|
||||
|
||||
每条记录在写入时生成一个**锚点 ID**,格式为 `CL-YYYYMMDD-HHMM`(如 `CL-20260412-1430`)。
|
||||
同一分钟内有多条时追加字母后缀(`CL-20260412-1430a`、`CL-20260412-1430b`)。
|
||||
格式 `CL-YYYYMMDD-HHMM-<author>`(如 `CL-20260715-1521-alice`)。同一分钟多条时在 `HHMM`
|
||||
后追加字母(`CL-...-1521a-sq`)。历史迁移条目无作者后缀(`author: legacy`),保持原 ID 不变
|
||||
以维持 pitfalls / deferred / source_chat 等处的交叉引用有效。
|
||||
|
||||
锚点 ID 在三层文件中保持一致,用于跨层精准定位:
|
||||
- L3 一句话条目以 `[CL-xxx]` 开头
|
||||
- L2 摘要条目的 H3 标题包含 `[CL-xxx]`
|
||||
- L1 完整条目的 H3 标题包含 `[CL-xxx]`
|
||||
锚点 ID 在 fragment 与三层视图中一致,用于逐级 Grep 精准定位(L3 → L2 → L1)。
|
||||
|
||||
这使得从 L3 → L2 → L1 的逐级查找可以通过 Grep 精准定位,无需全文读取。
|
||||
## 作者标识(多人协作核心)
|
||||
|
||||
## 逐级上溯机制
|
||||
每条 fragment 记录作者,体现在三处:① 目录 `entries/<author>/`、② 文件名 / ID 后缀、
|
||||
③ frontmatter `author` 字段。视图层 L3 行前缀 `@<author>`、L2/L1 有 `author` 字段、
|
||||
另有按作者聚合的 `changelog-by-author.md`。
|
||||
|
||||
当 Agent 在使用 L3 概要作为上下文时,如果某条记录的一句话描述**语义模糊**
|
||||
(如无法判断改动的具体范围、与当前任务的关系不明确),执行以下逐级查找:
|
||||
**作者 handle 的确定顺序**(写入时):
|
||||
1. 读 `.cursor/local-env.json` 的 `changelog-author` 字段(设备绑定、gitignored,每位开发者各自配一次,最稳)
|
||||
2. 缺失则取 `git config user.name`,转小写、取首个英文单词或姓名缩写作为 handle
|
||||
3. 仍无法确定则用 `unknown`
|
||||
|
||||
```
|
||||
1. 从 L3 条目中提取锚点 ID(如 CL-20260412-1430)
|
||||
2. 在 changelog-recent.md(L2)中 Grep 该 ID
|
||||
- 找到 → 读取该条目的 3-5 行摘要,通常足以消除歧义
|
||||
- 未找到(已滚出 L2 窗口)→ 进入步骤 3
|
||||
3. 在 changelog-full.md(L1)中 Grep 该 ID
|
||||
- 找到 → 用 Read 工具读取该 ID 所在行号 ±20 行范围(精准读取,不读全文)
|
||||
- 未找到 → 放弃上溯,该条目上下文不可用
|
||||
> 建议每位协作者在本机 `.cursor/local-env.json` 里加 `"changelog-author": "<你的handle>"`,
|
||||
> 保证 handle 稳定(不随 git user.name 大小写/格式变化而漂移)。
|
||||
|
||||
## fragment 文件格式
|
||||
|
||||
```markdown
|
||||
---
|
||||
id: CL-20260715-1521-alice
|
||||
date: 2026-07-15 15:21
|
||||
author: alice
|
||||
author_name: Alice
|
||||
type: fix
|
||||
merge_source: HEAD
|
||||
status: active
|
||||
superseded_by:
|
||||
title: 一句话标题(用于视图的 H3 标题)
|
||||
source_chat: [对话简述](chat-uuid)
|
||||
tags:
|
||||
- tag1
|
||||
- tag2
|
||||
affected_files:
|
||||
- scripts/player/player_controller.gd
|
||||
- scenes/player/player.tscn
|
||||
---
|
||||
|
||||
<!-- L3 -->
|
||||
一句话描述改动内容(≤80 字,进 headlines)
|
||||
|
||||
<!-- L2 -->
|
||||
做了什么 + 为什么(3-5 行摘要,进 recent;当本条进入最近 20 时被展示)
|
||||
|
||||
<!-- L1 -->
|
||||
- **what**: ...
|
||||
- **why**: ...
|
||||
- **decisions**: ...
|
||||
- **notes**: ...
|
||||
(symptom / root-cause / fix / tests / followups / relation 等按需,正文原样进 full)
|
||||
```
|
||||
|
||||
### 上溯原则
|
||||
|
||||
- **按需触发**:只有在 L3 信息不足以支撑当前任务判断时才上溯,不预防性地批量读取
|
||||
- **精准读取**:对 L1 的访问必须通过 Grep 定位行号 + Read 局部读取,禁止全文读取
|
||||
- **最小化**:一次上溯通常只涉及 1-3 条记录,不批量上溯
|
||||
字段说明:
|
||||
- `type`:`feat` / `fix` / `refactor` / `docs` / `chore` / `infra`(机读,便于统计)
|
||||
- `merge_source`:本条记录时所在分支(`HEAD` / `master` / 分支名),留空则视图不显示
|
||||
- `status`:`active`(默认)/ `reverted` / `superseded`;后两者配 `superseded_by: CL-xxx`
|
||||
- `affected_files`:**必须全路径**(视图 L2 的硬匹配靠它,缩写路径会失效)
|
||||
- `tags` / `affected_files` 为块列表;其余为标量。frontmatter 之外的三段用 `<!-- L1/L2/L3 -->` 分隔
|
||||
|
||||
## 操作 A:记录写入(核心流程)
|
||||
|
||||
### 触发条件
|
||||
|
||||
Agent 完成了一个涉及**代码或配置文件实质性改动**的任务后,自动触发。
|
||||
Agent 完成涉及**代码或配置文件实质性改动**的任务后自动触发。
|
||||
|
||||
以下情况**不触发**:
|
||||
- 纯对话讨论、方案设计、问题解答(无文件改动)
|
||||
- 只读操作(查看文件、搜索代码)
|
||||
- 只改动了 `.cursor/` 目录下的基础设施文件(如画像、延期方案、changelog 自身)
|
||||
**不触发**:纯对话/方案/答疑(无文件改动)、只读操作、只改 `.cursor/` 下基础设施文件
|
||||
(画像、延期、changelog 自身、hooks、tools 等)。
|
||||
|
||||
### 写入流程
|
||||
|
||||
```
|
||||
1. 生成锚点 ID:CL-YYYYMMDD-HHMM(检查是否与已有 ID 冲突,冲突则追加字母后缀)
|
||||
1. 确定作者 handle(见上「作者标识」三步顺序)
|
||||
|
||||
2. 从刚完成的任务中提取以下信息:
|
||||
- 做了什么(what):一句话概括
|
||||
- 为什么这样做(why):动机和背景
|
||||
- 改了哪里(where):受影响的文件/模块列表
|
||||
- 关键决策(decisions):如果有方案选择,记录选了什么、放弃了什么
|
||||
- 注意事项(notes):后续可能受影响的地方、已知限制等
|
||||
2. 生成锚点 ID:CL-YYYYMMDD-HHMM-<author>
|
||||
- 检查 entries/ 下是否已存在同 ID(含其他作者目录),冲突则 HHMM 后加字母后缀
|
||||
|
||||
3. 生成三层内容(共享同一个锚点 ID):
|
||||
- L1 完整条目(包含以上全部信息)
|
||||
- L2 摘要条目(what + why + where,3-5 行)
|
||||
- L3 一句话(what,不超过 80 字)
|
||||
3. 从刚完成的任务提取:what / why / where(affected_files, 全路径) / decisions / notes,
|
||||
并判定 type、merge_source(当前分支)、tags
|
||||
|
||||
4. 写入三个文件(按以下顺序):
|
||||
a. 读取 changelog-full.md,在 "## 记录" 下方追加 L1 条目
|
||||
b. 读取 changelog-recent.md,在顶部插入 L2 条目,如超过 20 条则移除最旧的(与下方「L2 窗口」一致)
|
||||
c. 读取 changelog-headlines.md,在顶部插入 L3 条目,如超过 50 条则移除最旧的
|
||||
4. 用 Write 工具创建单个 fragment 文件:
|
||||
.cursor/changelog/entries/<author>/<id>.md
|
||||
- 按上面的格式填好 frontmatter + L3/L2/L1 三段
|
||||
- L3 ≤80 字一句话;L2 3-5 行;L1 完整正文
|
||||
|
||||
5. 在回复末尾附一行提示:"[已记录到开发日志]"
|
||||
5. 跑生成器重建视图:
|
||||
python .cursor/changelog/tools/changelog_build.py
|
||||
(Windows 控制台先 set PYTHONIOENCODING=utf-8)
|
||||
|
||||
6. 在回复末尾附 "[已记录到开发日志]"
|
||||
```
|
||||
|
||||
### 与旧流程的关键区别
|
||||
|
||||
- **不再用 StrReplace 往三个文件顶部插入**——只新建一个 fragment 文件,零冲突、零半损坏风险
|
||||
(旧的 StrReplace 顶部插入曾导致条目半损坏,fragment 模型下该风险彻底消失)。
|
||||
- **不再手动维护滚动窗口**——recent/headlines 的 ~20/~50 截断由生成器自动算。
|
||||
- **不再手动保持三层同步**——三层都是同一 fragment 的不同密度渲染,天然一致。
|
||||
|
||||
### 静默写入原则
|
||||
|
||||
- **不需要用户确认**——Agent 自己做的改动,对"做了什么"的认知是一手的
|
||||
- 用户如果觉得记录不准确,可通过操作 D 修改或删除
|
||||
- 回滚操作也要记录("回退了 XX 改动"),真实反映开发过程
|
||||
- 不需要用户确认(Agent 对自己的改动是一手认知)。
|
||||
- 回滚也要记录(新建一条 `type: chore` / 在被回滚条目里置 `status: reverted` + `superseded_by`)。
|
||||
|
||||
## 操作 B:L2 自动触发读取
|
||||
|
||||
### 触发条件
|
||||
|
||||
由 `changelog-recall.mdc` Rule 调度。当 Agent 开始处理一个新任务时,判断该任务是否
|
||||
与近期改动相关。
|
||||
|
||||
### 匹配策略(文件 + 标签双匹配)
|
||||
|
||||
```
|
||||
1. 从当前任务中提取:
|
||||
- 涉及的文件路径
|
||||
- 语义关键词(模块名、功能领域等)
|
||||
|
||||
2. 读取 changelog-recent.md,逐条检查:
|
||||
- 硬匹配:当前任务涉及的文件出现在条目的 affected_files 中
|
||||
- 软匹配:当前任务的语义关键词与条目的 tags 有交集
|
||||
|
||||
3. 任一匹配命中 → 将匹配到的 L2 条目作为上下文纳入考量
|
||||
4. 在回复中自然融入,不显式提及"根据开发日志"
|
||||
```
|
||||
由 `changelog-recall.mdc` 调度,读取 `changelog-recent.md`:
|
||||
- 硬匹配:当前任务涉及的文件出现在条目 `affected_files`(现为全路径)
|
||||
- 软匹配:当前任务语义关键词与条目 `tags` 有交集
|
||||
任一命中即纳入上下文。读取的是**视图**,无需读 fragment。
|
||||
|
||||
## 操作 C:L1 手动检索
|
||||
|
||||
### 触发条件
|
||||
用户要求回顾完整记录时,读取 `changelog-full.md` 并按时间 / 模块 / tags 过滤展示。
|
||||
|
||||
用户主动要求回顾完整改动记录时触发。典型话语:
|
||||
- "回顾一下最近的改动"
|
||||
- "XX 模块之前改过什么"
|
||||
- "查看开发日志"
|
||||
- "changelog"
|
||||
|
||||
### 流程
|
||||
## 逐级上溯机制
|
||||
|
||||
L3 信息不足时(语义模糊),按 ID 逐级 Grep:
|
||||
```
|
||||
1. 读取 changelog-full.md
|
||||
2. 根据用户需求过滤:
|
||||
- 按时间范围
|
||||
- 按模块/文件
|
||||
- 按 tags
|
||||
3. 展示匹配的条目摘要表,用户可以进一步查看某条的完整内容
|
||||
1. 从 L3 提取锚点 ID
|
||||
2. Grep changelog-recent.md(L2)→ 命中读该条
|
||||
3. 仍不足 → Grep changelog-full.md(L1)拿行号,Read 该行 ±20 行
|
||||
(也可直接 Read 对应 fragment:entries/*/<id>.md)
|
||||
```
|
||||
原则:按需触发、精准读取、一次 1-3 条、不全文读 L1。
|
||||
|
||||
## 操作 D:记录管理
|
||||
|
||||
用户可以对已有记录进行管理:
|
||||
- **修改**:编辑对应 `entries/*/<id>.md` 后跑生成器(不要直接改视图)。
|
||||
- **删除**:删除对应 fragment 文件后跑生成器。
|
||||
- **标记取代/回滚**:在 fragment 里置 `status: superseded`/`reverted` + `superseded_by`。
|
||||
|
||||
| 操作 | 说明 |
|
||||
## 滚动窗口(自动)
|
||||
|
||||
生成器按 ID 时间倒序排序后:headlines 取前 50、recent 取前 20、full 全量、by-author 全量。
|
||||
**无需任何手动修剪**,被移出窗口的条目仍完整保留在 fragment 与 full 视图中。
|
||||
|
||||
## git 协作与冲突
|
||||
|
||||
- **fragment 几乎不冲突**:不同人写不同文件、不同作者写不同子目录。
|
||||
- **视图冲突自动吸收**:`.gitattributes` 给 4 个视图设 `merge=union`(merge 不中断),
|
||||
pre-commit / post-merge git hook 跑生成器从 fragment **确定性重建**视图,所有人收敛到一致。
|
||||
- 新克隆需跑一次 `tools/install-git-hooks.ps1`(或 `.sh`)装 hook。
|
||||
- CI 可加 `changelog_build.py --check` 校验"视图 == 重建(fragment)"防止有人没装 hook 就提交。
|
||||
- **合并尚未 fragment 化的旧分支**(如重构前的 master):先 `git merge --no-commit --no-ff <分支>`
|
||||
(union 让视图不冲突、`--no-commit` 防止 hook 过早重建),再跑 `tools/merge-import.ps1 [-Ref <分支>]`
|
||||
(或 `.sh`)把对方旧格式条目收割成 fragment(只补缺失 ID、不覆盖已有),自动重建并校验无丢失,最后 `git add -A; git commit`。
|
||||
- **两条改动撞了同一个 fragment ID**(生成器遇重复 ID 会直接报错):给其中一条改 ID(`HHMM` 后加字母,如 `1521`→`1521a`),
|
||||
文件名与 frontmatter `id` 同步改,再跑生成器。两条都保留、不丢内容。
|
||||
|
||||
## 与其他系统协作
|
||||
|
||||
| 系统 | 关系 |
|
||||
|------|------|
|
||||
| 删除 | 从三层文件中同步移除对应条目 |
|
||||
| 修改 | 修改某条记录的描述(三层同步更新) |
|
||||
| 清理 | 手动触发 L1 的归档(如按月分文件,暂不实现,作为演进方向) |
|
||||
|
||||
## 条目格式
|
||||
|
||||
### L1 完整条目
|
||||
|
||||
```markdown
|
||||
### [CL-20260412-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-20260412-1430] YYYY-MM-DD — 一句话标题
|
||||
- **tags**: tag1, tag2, tag3
|
||||
- **affected_files**: file1, file2
|
||||
- **summary**: 做了什么 + 为什么(3-5 行)
|
||||
```
|
||||
|
||||
### L3 一句话条目
|
||||
|
||||
```markdown
|
||||
- [CL-20260412-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 读取 |
|
||||
| `deferred-decisions` Skill | 互补 | deferred 记"没做什么",changelog 记"做了什么" |
|
||||
| `profile-memory` Skill | 结构对称 | profile 是"是什么",changelog 是"做了什么" |
|
||||
| `epee-orchestrator` | 注册 | 在 registry.md 中注册本 Skill |
|
||||
| `changelog-recall` Rule | 下游消费者:注入 L3、按需读 L2、上溯 L1 |
|
||||
| `deferred-decisions` | 互补:记"没做什么" |
|
||||
| `profile-memory` | 结构对称:记"是什么" |
|
||||
| `epee-orchestrator` | 在 registry.md 注册本 Skill |
|
||||
|
||||
## 自迭代日志
|
||||
|
||||
本节记录使用本 Skill 过程中发现的必要检查项。
|
||||
|
||||
### 已知必要检查
|
||||
|
||||
1. **大任务收尾遗漏风险** — 当单次任务涉及 5+ 个文件改动时,Agent 容易在输出总结回复后遗漏被动写入流程。应在生成最终回复前,先执行 `changelog-recall.mdc` 中的"任务完成 Checklist",确认三层日志已写入后再输出回复。绝不能"先回复再补写"。
|
||||
1. **大任务收尾不要遗漏写入** — 单次 5+ 文件改动时,先按 `changelog-recall.mdc` 的
|
||||
"任务完成 Checklist" 写完 fragment + 跑生成器,再输出回复;绝不"先回复再补写"。
|
||||
|
||||
2. **L3/L2 滚动窗口必须落地** — 操作 A 第 4 步不是「插入即结束」:写入后必须数清条目(L3 为以 `- [` 开头的列表行,L2 为 `### [CL-` 标题行)。L3 超过 50 条、L2 超过 20 条时,必须从**文件底部(最旧)**整段删除条目直至恰好满足上限;禁止长期只追加不修剪。若发现 `changelog-headlines.md` 列表行多于 50,说明上次写入未执行本项,本次补修剪并自检。
|
||||
2. **affected_files 必须全路径** — 视图 L2 的硬匹配依赖全路径;缩写路径(如只写文件名)
|
||||
会让 recall 的硬匹配失效。迁移前的旧 L2 缩写路径问题已由本次重构(从 frontmatter 全路径渲染)解决。
|
||||
|
||||
3. **顶部插入 StrReplace 范式(L1/L2)** — L1 和 L2 的每个条目都是多行结构(标题 + 多条 `- **字段**:`)。使用 StrReplace 在顶部插入新条目时,anchor(`old_string`)有且仅有两种合法选择:
|
||||
(a) 只包含新条目之前的"稳定前缀"(如 L1 的 `## 记录\n\n` 或 L2 的整段文件头说明),**不触及任何已有条目的任何一行**;`new_string` = 稳定前缀 + 新条目完整内容 + 空行。
|
||||
(b) 把旧首条目的**完整多行内容**(标题行 + 全部字段行)都纳入 `old_string`;`new_string` = 新条目完整内容 + 空行 + 旧首条目完整内容。
|
||||
3. **写完务必跑生成器** — 只建 fragment 不跑 `changelog_build.py`,视图就不会更新(recall 读的是视图)。
|
||||
pre-commit hook 会兜底重建,但当前会话内的 recall 注入读的是已落盘视图,故应即时生成。
|
||||
|
||||
**绝对禁止**:只把旧首条目的标题行(或前 1-2 字段)当 anchor 而不带上剩余字段行——StrReplace 会吞掉这些 anchor 行但不动剩余字段,造成"旧标题丢失、字段游离"的半损坏状态(2026-04-20 在 `pitfall-journal` 的写入中已实际踩过此坑)。
|
||||
4. **作者 handle 要稳定** — 优先用 `.cursor/local-env.json` 的 `changelog-author`,避免每次从
|
||||
`git config user.name` 推导导致 handle 漂移(同一人出现多个目录)。
|
||||
|
||||
**写入后自检**:Read 文件头部 30 行,确认看到新条目完整 + 旧首条目标题行仍存在且字段完整跟随。L3 的一行条目不受本条约束(它就是单行,天然无此风险)。
|
||||
5. **Windows 控制台编码** — 跑脚本前 `set PYTHONIOENCODING=utf-8`(或 PowerShell `$env:PYTHONIOENCODING="utf-8"`),
|
||||
否则中文输出在 GBK 控制台显示乱码(不影响 UTF-8 文件写入,仅影响 stdout 观感)。
|
||||
|
||||
Reference in New Issue
Block a user