# Changelog 参考文档

## 用途

为 Combo SDK for Unity 生成并更新 CHANGELOG.md：
1. 优化用户的更新描述（口语化 → 书面语）
2. 对更新内容进行分类（FEATURES / IMPROVEMENTS / BUG FIXES）
3. 生成格式化的 CHANGELOG 条目
4. 将新条目插入到 `CHANGELOG.md` 文件顶部

## 输入

- `VERSION`：版本号（格式：x.x.x）
- `UPDATE_CONTENT`（可选）：更新内容列表
  - 可以是从 git log 提取的 commit 列表
  - 也可以是从发布分支 CHANGELOG 中提取的已有更新内容（changelog-merge 场景）

## 执行步骤

### 步骤零：验证输入和文件

1. **验证版本号格式**：
   - 检查 `VERSION` 是否符合 `x.x.x` 格式
   - 如果格式不正确，提示用户并终止执行

2. **检查 CHANGELOG.md 是否存在**：
   - 检查项目根目录下的 `CHANGELOG.md` 文件
   - **如果文件不存在**：
     - 提示用户：`"错误：CHANGELOG.md 文件不存在，无法生成更新日志。"`
     - 终止执行

### 步骤一：获取更新内容

**如果用户已提供更新内容**：直接使用

**如果用户未提供更新内容**：
1. 执行 `git log origin/main --oneline --no-merges` 命令获取提交记录
   - **注意**：不要使用 `--grep` 参数，直接获取所有 commit
   - 使用 `origin/main` 而非 `main`，确保无论从哪个分支执行都能正确检索
2. 找到包含 `Prepare for next release x.x.x` 的 commit（x.x.x 为目标版本号）
3. 收集该 Prepare commit **上方**的所有 commit（git log 输出中位于 Prepare commit 之前的行，即时间上更近的 commit）
   - **重要说明**：`git log` 按时间倒序输出，最新的 commit 在最上面。Prepare commit 上方的 commit 是上一版本发布后新提交的代码
   - **示例**：如果 git log 输出为：
     ```
     aaaaaaa 最新功能 commit      ← 收集这些
     bbbbbbb 修复 bug             ← 收集这些
     ccccccc Prepare for next release 2.19.0  ← Prepare commit（以此为界）
     ddddddd Bump version to 2.18.0  ← 不收集（这是上一版本的发布 commit）
     ```
     则应该收集 `aaaaaaa` 和 `bbbbbbb`，即 Prepare commit **上方**的 commit
4. 在代码中过滤掉以下 commit（不要通过 git 命令过滤）：
   - 以 `demo:`、`ai:`、`ci:` 开头的 commit
   - 以 `claude:` 开头的 commit（Claude 自动提交）
   - 仅包含 `合并 `、` 创建分支 `、` 优化` 、`补充` 等模糊词汇的 commit
5. **过滤重复 commit**：
   - 读取当前 `CHANGELOG.md` 文件中已有所有版本的更新内容
   - 提取已有更新条目的关键描述（每条 `-` 开头的内容）
   - 如果某个 commit 的描述与已有更新内容重复（核心语义相同），则过滤掉该 commit
   - **示例**：如果 CHANGELOG.md 中已有 `- seayoo_account: 修复连点导致的闪退问题`，则相同或高度相似的 commit 应被过滤
6. 将过滤后的 commit 列表整理为更新内容

**如果是 changelog-merge 场景（用户提供的是从发布分支提取的 CHANGELOG 内容）**：
- 直接使用用户提供的内容，不再从 git log 提取
- 保持用户提供的内容格式和描述，不做优化或重新分类

### 步骤二：优化更新描述

**如果是 merge-changelog 场景（用户提供的是已格式化的 CHANGELOG 内容）**：
- 跳过本步骤
- 直接使用用户提供的内容，保留原有描述和分类

**如果是 bump 场景（用户提供的是 commit 列表或口语化描述）**：
对更新内容进行优化：
- 将口语化表达改为简洁、专业的书面语
- 保持句式一致，以动词开头（如"新增"、"优化"、"修复"、"升级"）
- 删除冗余词汇，每条控制在 50 字以内
- 技术名词保持准确（如 SDK 名称、API 名称、模块名等）

### 步骤三：分类

**如果是 merge-changelog 场景（用户提供的是已格式化的 CHANGELOG 内容）**：
- 跳过本步骤
- 直接使用用户提供的内容，保留原有分类

**如果是 bump 场景（用户提供的是 commit 列表或口语化描述）**：
对优化后的内容进行分类：
- **FEATURES**：新增功能、新 API、新组件、新模块
- **IMPROVEMENTS**：性能优化、体验优化、代码重构、SDK 升级、非功能性改动
- **BUG FIXES**：Bug 修复、崩溃修复、问题修复

### 步骤四：生成 CHANGELOG 条目

**如果是 merge-changelog 场景（用户提供的是已格式化的 CHANGELOG 内容）**：
- 从用户提供的内容中提取 `## VERSION` 标题下的完整内容
- 或者直接使用用户提供的内容（如果已经是完整的 CHANGELOG 条目格式）
- 将提取的内容插入到 `CHANGELOG.md` 顶部

**如果是 bump 场景（用户提供的是 commit 列表或口语化描述）**：
生成格式如下的 CHANGELOG 条目：

```markdown
## VERSION (YYYY-MM-DD)

**FEATURES:**

- xxx

**IMPROVEMENTS:**

- xxx

**BUG FIXES:**

- xxx
```

- 日期使用当前日期（YYYY-MM-DD）
- 没有内容的分类不显示
- **注意**：版本标题行不需要添加锚点（如 `{#v2.19.0}`），保持简洁

### 步骤五：更新 CHANGELOG.md

**目标**：将生成的新版本条目插入到 `CHANGELOG.md` 文件顶部，同时完整保留旧版本内容。

**具体操作步骤**：

1. **读取当前 CHANGELOG.md 文件**，找到第一个版本块：
   - 第一个版本块以 `## x.x.x` 开头
   - 到下一个 `## x.x.x` 之前结束（或到文件末尾）

2. **使用 Edit 工具进行替换**：
   - `old_string`：必须包含**完整的第一个版本块**（从 `## x.x.x` 标题到下一个 `##` 之前的所有内容）
   - `new_string`：`新版本完整条目` + `\n\n` + `旧版本完整条目`

3. **关键规则**（必须遵守）：
   - ❌ **禁止**只替换版本标题行（如只替换 `## 2.18.0...` 这一行）
   - ✅ **必须**确保 `old_string` 包含该版本的完整内容（包括所有分类和条目）
   - ✅ `new_string` 中必须显式包含旧版本的完整内容，避免内容丢失或重复

4. **验证步骤**（强烈推荐）：
   - 编辑完成后，立即读取文件前 20 行
   - 确认以下两点：
     1. 新版本条目完整（标题 + 所有分类）
     2. 旧版本条目完整，**没有重复的分类标题**（如两个 `**BUG FIXES**:`）

**错误示例**（禁止这样做）：
```
❌ old_string = "## 2.18.0 (2026-03-05)"  ← 只替换标题行
❌ new_string = "## 2.19.0 (2026-03-29)\n\n...\n\n## 2.18.0 (2026-03-05)"
```
结果：旧版本的 `**BUG FIXES**:` 等内容会残留，形成重复。

**正确示例**：
```
✅ old_string = "## 2.18.0 (2026-03-05)\n\n**BUG FIXES**:\n\n- 修复问题...\n\n## 2.17.0..."
✅ new_string = "## 2.19.0 (2026-03-29)\n\n**FEATURES**:\n\n- 新增功能...\n\n## 2.18.0 (2026-03-05)\n\n**BUG FIXES**:\n\n- 修复问题...\n\n## 2.17.0..."
```

**简化做法**（如果旧版本内容太长）：
1. 先用 Read 工具读取 CHANGELOG.md 的完整第一个版本块
2. 将完整内容保存到变量中
3. Edit 时使用该变量作为 `old_string` 的一部分

## 执行要求

1. 如果用户未提供更新内容，自动从 git log 中提取
   - 执行 `git log origin/main --oneline --no-merges` 获取所有 commit
   - **不要使用 `--grep` 或其他过滤参数**，在代码中进行过滤
   - 仅检索 `origin/main` 分支上的提交记录（使用 `origin/main` 而非 `main`，确保从任意分支执行都能正确检索）
   - 找到 `Prepare for next release x.x.x` commit，收集该 commit **上方**的所有 commit（即时间上更近的提交）
   - 过滤掉 `demo:`、`ai:`、`ci:`、`claude:` 开头的 commit
   - 过滤掉 `合并 `、` 创建分支 `、` 优化` 等模糊 commit
   - **过滤重复 commit**：读取 CHANGELOG.md 中已有所有版本的更新内容，如果某个 commit 的描述与已有更新内容重复（核心语义相同），则过滤掉该 commit
   - 只保留包含具体模块名和描述的 commit
2. **changelog-merge 场景**：
   - 用户提供的是从发布分支提取的已格式化 CHANGELOG 内容
   - 跳过优化、分类步骤，直接使用用户提供的内容
   - 将提取的内容插入到 `CHANGELOG.md` 顶部
3. 优化后的描述要简洁专业
4. 分类要准确，不要强行分类
5. 保持 CHANGELOG 格式一致
6. 只更新 CHANGELOG.md，不修改版本号文件

## 示例

### 示例 1

输入：`VERSION=2.19.0`, `UPDATE_CONTENT=["新增微信登录功能", "优化了登录界面的 UI 效果", "修复了 iPad 上会崩溃的问题"]`

输出：
```markdown
## 2.19.0 (2026-03-29)

**FEATURES:**

- 新增微信登录功能

**IMPROVEMENTS:**

- 优化登录界面 UI

**BUG FIXES:**

- 修复 iPad 设备崩溃问题
```

### 示例 2（只有 Bug 修复）

输入：`VERSION=2.18.1`, `UPDATE_CONTENT=["修复了抖音 SDK 初始化崩溃的问题"]`

输出：
```markdown
## 2.18.1 (2026-03-29)

**BUG FIXES:**

- 修复抖音 SDK 初始化崩溃问题
```
