# CHANGELOG 与 Changesets 指南
# 1. 概述
# 1.1. 核心原则
- CHANGELOG 只记录用户可见的变更,不记录内部开发过程中的临时修改、重构中间态、待办事项
- 对比基准是 main 分支的上一个发布版本,不是最近的 git commit 或功能开发分支
- 统一使用 changeset 模式:所有包通过 changeset 文件驱动版本管理
- 发布时统一格式:最终 CHANGELOG 格式完全一致——先中文后英文的双语结构
- 日常维护仅写中文,发布时再添加英文——减少日常维护负担
# 1.2. 包模式
所有包统一使用 changeset 模式,包括 cmtx-vscode。不再区分双轨。
# 2. 格式标准
# 2.1. 文件结构
每个包目录下有 CHANGELOG.md 文件。发布后统一采用先中文后英文的双语结构。发布前按第 4 章流程精修为统一格式。
# 2.2. 双语规范
- 文件标题使用双语:
# @cmtx/<name> 更新日志 / Changelog - 每个版本均采用先中文后英文的双语模式,用
---分隔 - 中文与英文条目内容应一一对应,信息一致
- 初始发布版本可省略
---,但双语必须完整
# 2.3. 标题规范
| 位置 | 格式 | 说明 |
|---|---|---|
| 文件第一行 | # @cmtx/<name> 更新日志 / Changelog |
双语命名 |
| 日常维护 | 无固定标题,由 changeset 驱动 | 创建 CHANGESET-XXX 文件,发布时 changeset version 自动生成 |
| 发布后 | ## [<version>] - <YYYY-MM-DD> |
由脚本自动替换 |
# 2.4. 变更类型
| 类型 | 说明 | 使用时机 |
|---|---|---|
Added |
新功能 | 新增面向用户的特性、API、CLI 命令 |
Changed |
现有功能变更 | API 行为变化、内部重构但不影响签名 |
Deprecated |
即将弃用的功能 | 标记即将移除的功能,并说明替代方案 |
Removed |
已移除的功能 | 实际删除已弃用的功能 |
Fixed |
错误修复 | 修复任何用户可见的 bug |
Security |
安全漏洞 | 安全修复(可附带 CVE 编号) |
# 2.5. 条目编写规范
通用 Markdown 格式规则见 DEV-010 文档布局,本节仅定义 CHANGELOG 专有的条目规范。
- 每个条目以
-开头,末尾不加句号 - 英文条目首字母大写,中文条目直接写不加引号
- 如果条目标题不足以说明,另起一行缩进补充细节:
### Added
- **ConfigAdapter**: 新增 `getMaxRetries()` 方法
返回最大重试次数,默认值为 3,可通过构造函数注入
- 条目面向 CHANGELOG 读者(包的使用者),描述"做了什么"和"为什么做",而不是"怎么实现"
- 如果某个变更需要更详细的迁移指南,在 CHANGELOG 中写简要说明,另开文档详述
# 2.6. 禁止写入 CHANGELOG 的内容
- WIP(Work in Progress)的部分实现
- 仅测试代码变更(新增/修改测试用例)
- 仅文档代码变更(修改 JSDoc、README)
- 仅配置变更(修改 CI、打包配置、lint 规则)
- 内部重构但无 API/行为变化
- 依赖版本更新但无行为变化
# 3. 日常维护流程
Changesets 是一个版本管理工具,用于解决 Monorepo 中的版本发布问题。它的核心思想是将「变更意图」与「代码提交」同步记录,而非在发布时回忆。一个 changeset 是一个 Markdown 文件(含 YAML front matter),声明哪些包需要发布、bump 类型以及变更描述。
# 3.1. changeset 模式
不维护 CHANGELOG.md 中的 [Unreleased],通过 changeset 文件驱动。完成一个用户可见功能或修复后,立即创建 changeset 文件:
NEXT_NUM=$(python3 .agents/skills/changeset-workflow/scripts/next-changeset-number.py .changeset)
格式参考 changeset-workflow skill。
禁止直接编辑 CHANGELOG.md——由 changeset version 自动生成 CHANGELOG 条目。
# 3.2. 确定受影响的包
根据变更影响的包来决定:
- 修改了
packages/core/src/filter.ts-> 影响@cmtx/core - 修改了
packages/rule-engine/src/index.ts-> 影响@cmtx/rule-engine - 修改了跨包的类型定义 -> 影响所有受影响包
# 3.3. 比较基准
日常维护只需要关注本次 CHANGELOG 撰写期间的变更范围,即自上一次该包 CHANGELOG 更新以来发生的变化,而非从上一个发布版本开始的全量 diff。
# 4. 发布流程
# 4.1. Changeset 与 CHANGELOG 的关系
| 维度 | CHANGELOG | Changeset |
|---|---|---|
| 维护者 | changeset version 生成 + 开发者精修 |
开发者手动 |
| 内容 | 详细的功能描述(中英文双语) | 简短的版本变更说明(中文) |
| 用途 | 面向用户阅读 | 驱动 changeset version bump |
| 发布时 | release-changelog.mjs 添加日期,开发者精修标题和双语 |
消费后删除 |
# 4.2. 发布后格式统一
最终发布的 CHANGELOG 格式完全一致:先中文后英文的双语结构,使用标准 Keep a Changelog 分类标题。
精修的目标是让 CHANGELOG.md 达到此统一格式。精修过程中只修改 CHANGELOG.md,不修改 changeset 文件。
禁止删除版本号。 即使 changeset version 生成的该版本条目内容没什么用,也要根据 commit 提炼一些内容出来,确保每个版本号都对应有内容的版本。删除版本号会导致 CHANGELOG 与 package.json 的 version 脱节。
# 4.3. changeset 模式精修步骤
pnpm changeset version 执行后,CHANGELOG.md 中新增了自动生成的半成品内容,精修在 CHANGELOG.md 上进行(不修改 changeset 文件):
- 删除
### Patch Changes中仅含依赖更新的块(- Updated dependencies [sha]),这不是用户可见变更 - 将
### Minor Changes/### Patch Changes重命名为 Keep a Changelog 标准类型(### Added/### Changed/### Fixed等),根据实际变更内容判断归属,不留映射规则 - 移除条目中的 commit SHA 前缀(
a539714:部分) - 展开条目内容,将一行简写拆分为多行完整描述
# 4.4. 共同精修步骤
所有包都需要执行以下三步:
# 4.4.1. 步骤 1:验证标题格式与日期
确认版本标题格式为 ## [<version>] - YYYY-MM-DD,与上一个版本的基准对齐。
# 4.4.2. 步骤 2:对比 git diff 审核内容
根据上一次实际发布的版本,对比 git diff 审核当前 CHANGELOG 内容:
# 查找包的上一个发布 tag
LAST_TAG=$(git tag --list '@cmtx/core/*' --sort=-v:refname | head -1)
# 查看自上一个版本以来的 src 变更
git diff "$LAST_TAG"...HEAD -- packages/core/src/ packages/core/package.json | head -100
审核点:
- 发现 diff 中有变更但 CHANGELOG 没有记录 -> 补齐遗漏
- 发现 CHANGELOG 记录了但 diff 中找不到证据 -> 删除虚构条目(可能是中间 commit 走了弯路,实际上不存在的变更)
- 确认所有用户可见的变更都已覆盖
# 4.4.3. 步骤 3:添加英文翻译
每个中文章节完成后,用 --- 分隔,添加对应的英文版本。英文与中文条目一一对应。
# 4.5. 完整示例:精修前后对比
# 4.5.1. Before:changeset version 自动生成
# @cmtx/core 更新日志 / Changelog
## [0.4.0] - 2026-05-06
### Minor Changes
- a539714: frontmatter-id FF1 配置解耦与校验增强
- `ff1` 新增可选 `length`/`radix` 字段,可独立覆盖 counter 格式配置
- `ff1.useCounter` 引用的 counter ID 不存在时返回可读错误,而非静默降级
- 862fc95: - ID 生成器重构:支持多 counter 模板化 ID 生成,移除废弃的 id-generate-rule
- Counter 服务重构:新增 `peek()`/`commit()` 模式,支持多 counter 状态管理
- 新增 `frontmatter-slug` 规则,支持 transform/extract/ai 三种 slug 生成策略
- 集成 `@cmtx/ai` 包,支持 AI 驱动的 slug 生成
- 新增 `transfer-images` 规则,支持跨存储图片转移
- Service registry 注册 `TransferService` 和 `FrontmatterSlugRule`
- `formatForPublish` 更新适配新的 template 化 ID 生成
- 配置类型扩展:新增 counter 配置、FF1 配置、slug 配置、transfer 配置
- frontmatter-id 模板化:`ff1` 新增可选 `length`/`radix` 字段,`useCounter` 引用无效 ID 时报错而非静默降级
- counter 格式配置从顶层移至规则级别,简化配置结构
### Patch Changes
- Updated dependencies [862fc95]
- Updated dependencies [862fc95]
- Updated dependencies [862fc95]
- Updated dependencies [862fc95]
- Updated dependencies [862fc95]
- @cmtx/asset@0.2.0-alpha.3
- @cmtx/autocorrect-wasm@0.1.1-alpha.2
- @cmtx/core@0.4.0-alpha.3
- @cmtx/fpe-wasm@0.1.1-alpha.3
- @cmtx/storage@0.1.1-alpha.3
- @cmtx/template@0.2.0-alpha.3
# 4.5.2. After:精修后(双语 + 标准分类,两条 changeset 合并)
# @cmtx/core 更新日志 / Changelog
## [0.4.0] - 2026-05-06
### Added
- **FF1 配置解耦**: frontmatter-id FF1 配置解耦与校验增强
- `ff1` 新增可选 `length`/`radix` 字段,可独立覆盖 counter 格式配置
- `ff1.useCounter` 引用的 counter ID 不存在时返回可读错误,而非静默降级
- **ID 生成器重构**: 支持多 counter 模板化 ID 生成,移除废弃的 id-generate-rule
- **Counter 服务重构**: 新增 `peek()`/`commit()` 模式,支持多 counter 状态管理
- **frontmatter-slug 规则**: 新增 transform/extract/ai 三种 slug 生成策略
- **transfer-images 规则**: 新增跨存储图片转移能力
- **配置类型扩展**: 新增 counter、FF1、slug、transfer 等配置类型
---
### Added
- **FF1 Config Decoupling**: Decoupled FF1 config with enhanced validation
- Added optional `length`/`radix` fields to `ff1` for independent counter format config
- `ff1.useCounter` now returns a readable error for invalid counter IDs
- **ID Generator Refactor**: Multi-counter template-based ID generation, removed deprecated id-generate-rule
- **Counter Service Refactor**: New `peek()`/`commit()` pattern for multi-counter state management
- **frontmatter-slug Rule**: Three slug strategies: transform, extract, and AI
- **transfer-images Rule**: Cross-storage image transfer support
- **Config Type Extensions**: Added counter, FF1, slug, and transfer configs
(依赖更新块已删除,commit SHA 已移除,### Minor Changes 改为 ### Added,条目按功能拆分合并。)
# 4.6. 补充示例
多个 changeset 合并(同一包)
三个 changeset 文件:
CHANGESET-021-url-check.md:
---
"@cmtx/asset": minor
---
- URL 存在性检测
CHANGESET-022-head-fallback.md:
---
"@cmtx/asset": patch
---
- HEAD 降级策略
CHANGESET-023-batch-check.md:
---
"@cmtx/asset": minor
---
- 批量 URL 检测
changeset version 自动合并后,开发者精修为:
## [0.3.0] - 2026-05-06
### Added
- **URL 存在性检测**: 新增 `checkUrlExists()` 函数
- **批量 URL 检测**: 新增 `checkUrlExistsBatch()` 函数
### Fixed
- **HEAD 降级策略**: HEAD 请求返回 405/501 时自动降级为 GET + Range
---
### Added
- **URL Existence Check**: Added `checkUrlExists()` function
- **Batch URL Checking**: Added `checkUrlExistsBatch()` function
### Fixed
- **HEAD Fallback Strategy**: Auto-fallback to GET + Range on 405/501
破坏性变更
## [0.3.0] - 2026-05-06
### Breaking Changes
- **`uploadImage()` 签名变更**: 第二个参数从 `options` 改为 `config`
迁移方法: 将 `{ timeout, retry }` 改为 `{ strategy, maxRetries }`
---
### Breaking Changes
- **`uploadImage()` signature changed**: Second parameter changed from `options` to `config`
Migration: Replace `{ timeout, retry }` with `{ strategy, maxRetries }`
# 4.7. 发布前验证:对比 git diff
这是发布前最重要的验证步骤。 必须验证 CHANGELOG 内容与实际代码变更一致。
# 1. 查找包的上一个发布 tag
LAST_TAG=$(git tag --list '@cmtx/core/*' --sort=-v:refname | head -1)
# 2. 查看自上一个版本以来的 src 变更
git diff "$LAST_TAG"...HEAD -- packages/core/src/ packages/core/package.json | head -100
# 3. 查看具体新增/删除的函数和导出
git diff "$LAST_TAG"...HEAD -- packages/core/src/index.ts
验证清单:
- [ ] CHANGELOG(或 changeset)中的所有条目都能在 git diff 中找到对应证据
- [ ] 没有"虚构条目"(diff 中不存在的变更)
- [ ] 没有遗漏用户可见的变更(新增/删除的导出函数、API 签名变化、破坏性变更)
- [ ] 移除的公开 API/类型必须在
### Removed中记录 - [ ] 内部重构(仅修改实现、不修改导出签名)不写入 CHANGELOG
- [ ] 仅修改测试文件、JSDoc、lint 配置、CI 配置等不写入 CHANGELOG
# 4.8. 完整发布命令链
# 版本计算(自动触发 CHANGELOG 版本标题添加日期)
pnpm changeset version
# 精修 CHANGELOG(删除依赖更新块 + 重命名分类标题 + 移除 commit SHA + 展开条目)
# 审核内容完整性(对比 git diff,补齐遗漏、删除虚构条目)
# 添加英文翻译
# 验证构建
pnpm prepublish:validate
# 提交 & 发布
git add -A
git commit -m "Release v<version>"
pnpm changeset publish
git push --follow-tags
# 5. CMTX Changesets 配置
# 5.1. 当前 config.json
{
"$schema": "https://unpkg.com/@changesets/config@3.1.4/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
changelog: "@changesets/cli/changelog"— 启用 changelog 生成,changeset version自动生成 CHANGELOG 条目access: "public"— scoped 包公开发布ignore— 所有包均参与版本管理,包括cmtx-vscode
# 5.2. 发布脚本
{
"postchangeset:version": "node scripts/release-changelog.mjs",
"release:version": "pnpm changeset version",
"release:publish": "pnpm changeset publish && git push --follow-tags",
"release:all": "pnpm changeset version && pnpm prepublish:validate && pnpm changeset publish && git push --follow-tags"
}
单步操作直接使用 pnpm changeset <command> 命令,不再通过包装脚本间接调用。
# 5.3. 参与版本管理的包
所有包均参与版本管理:
@cmtx/ai@cmtx/asset@cmtx/core@cmtx/fpe-wasm@cmtx/markdown-it-presigned-url@cmtx/markdown-it-presigned-url-adapter-nodejs@cmtx/rule-engine@cmtx/storage@cmtx/template@cmtx/autocorrect-wasm(新包,尚未发布)cmtx-vscode
# 6. 命令速查
# 6.1. Git 查询命令
# 查找包的上一个版本标签
git tag --list '@cmtx/core/*' --sort=-v:refname | head -1
# 查看自上一个版本以来的变化(按包筛选)
git diff <last-tag>...HEAD -- packages/core/
# 查看所有提交(按包筛选)
git log <last-tag>...HEAD -- packages/core/
# 查看变更的文件列表
git diff <last-tag>...HEAD --name-only -- packages/core/
# 6.2. npm scripts 参考
| 脚本 | 命令 | 触发时机 | 说明 |
|---|---|---|---|
postchangeset:version |
node scripts/release-changelog.mjs |
自动 | 给版本标题添加日期 |
release:version |
pnpm changeset version |
发布 | 版本计算 + CHANGELOG 生成 |
release:publish |
pnpm changeset publish && git push --follow-tags |
发布 | 发布到 npm 并推送 tag |
release:all |
pnpm changeset version && pnpm prepublish:validate && pnpm changeset publish && git push --follow-tags |
发布 | 完整发布流程 |
prepublish:validate |
validate:build + validate:tests + validate:typecheck |
发布前 | 发布前验证三件套 |
# 6.3. 常用操作速查
# 日常:创建 changeset(手动,推荐)
# 直接在 .changeset/ 下创建 CHANGESET-XXX-<描述>.md 文件
# 查看待发布状态
pnpm changeset status --verbose
# 发布:版本计算 + CHANGELOG 版本标题添加日期
pnpm changeset version
# 发布:验证
pnpm prepublish:validate
# 发布:提交
git add -A && git commit -m "Release v<version>"
# 发布:推送到 npm
pnpm changeset publish && git push --follow-tags
# 调试:单独运行 changelog 替换
node scripts/release-changelog.mjs
# 预览发布效果(dry-run)
pnpm changeset version --dry-run
pnpm changeset publish --dry-run
# 7. 参考文档
- Keep a Changelog — CHANGELOG 格式标准
- Semantic Versioning — 语义化版本规范
- Changesets 官方文档 — 版本管理工具
- 包发布指南 — 完整发布流程