changelog
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesechangelog
changelog
Generate or update the changelog entry for the current branch under
: derive its metadata from git and the diff,
write the frontmatter and a grouped, categorised body, run the deterministic
enrichment scripts, then validate the result.
changelog/YYYYMMDD-HHMMSS-<slug>.mdThis skill is the single source of truth for what a valid changelog entry is
— the frontmatter schema, the field-ownership boundaries, idempotent
update-vs-create, and the validation gate. The same contract is enforced
downstream by a consumer repo's CI and relied on by a release-orchestrator that
finalises the post-merge fields, so the authoring rules live here once.
It is invoked two ways:
- Standalone () — author, refresh, or repair this branch's entry and leave it uncommitted in the working tree for review. No commit, push, or PR.
/changelog - Inside a ship flow (e.g. a ) — the changelog step that runs before push; the ship flow commits the entry, pushes, and opens the PR.
/send-it
生成或更新当前分支的changelog条目,存储在路径下:从git和差异中提取元数据,编写前置内容和分组分类的正文,运行确定性增强脚本,然后验证结果。
changelog/YYYYMMDD-HHMMSS-<slug>.md该技能是有效changelog条目标准的唯一权威来源——包括前置内容 schema、字段归属边界、幂等更新/创建逻辑以及验证机制。下游消费仓库的CI会强制执行同一标准,发布编排工具也会依赖该标准来完善合并后的字段,因此编写规则仅在此处定义一次。
它有两种调用方式:
- 独立调用()——撰写、刷新或修复当前分支的条目,将其未提交地留在工作区供审核。不会执行提交、推送或创建PR操作。
/changelog - 嵌入发布流程(例如)——在推送前运行的changelog步骤;发布流程会提交该条目、推送代码并创建PR。
/send-it
Configuration
配置
Config lives in beside this file; the bundled
scripts read it automatically. Edit your copied to match the
consuming repo (a neutral ships as a
template). and are required — they have no
default, so a missing or either key absent makes the scripts fail
loudly rather than silently inherit ACME's identity. The rest are structural and
keep generic, overridable defaults:
config.jsonconfig.jsonconfig.example.jsonissueKeyslinearWorkspaceSlugconfig.json| Key | Meaning | Default |
|---|---|---|
| Team-key prefixes used to recognise issue IDs in the branch and body. The issue-ID regex is built from these. | required |
| Linear workspace slug used to build issue links ( | required |
| The trunk the branch diff is taken against ( | |
| Directory the dated entries live in (scanned by the enrichment + validation scripts). | |
| Monorepo dir prefixes mapping | |
| Package name for changed paths matching no | |
| Whether to emit the | |
All bundled scripts use only Node built-ins — no , no build step.
They operate on the consumer repo's root directory (run them
from the repo root).
npm installchangelog/配置文件为该技能旁的;捆绑脚本会自动读取该文件。编辑你复制的以匹配消费仓库的需求(附带一个中立的作为模板)。和为必填项——它们没有默认值,因此缺失或任一必填项会导致脚本直接报错,而非默认继承ACME的标识。其余配置为结构性设置,带有可覆盖的通用默认值:
config.jsonconfig.jsonconfig.example.jsonissueKeyslinearWorkspaceSlugconfig.json| 配置项 | 说明 | 默认值 |
|---|---|---|
| 用于识别分支和正文中问题ID的团队密钥前缀。问题ID正则表达式将基于这些前缀构建。 | 必填 |
| 用于构建问题链接的Linear工作区标识(格式: | 必填 |
| 分支差异对比的基准主干分支( | |
| 日期化条目存储的目录(增强和验证脚本会扫描该目录)。 | |
| 单仓多包项目的目录前缀,用于将 | |
| 当变更路径不匹配任何 | |
| 是否输出 | |
所有捆绑脚本仅使用Node内置模块——无需,也无需构建步骤。它们操作的是消费仓库根目录下的目录(请在仓库根目录运行脚本)。
npm installchangelog/Running it
运行步骤
Step 1 — Detect an existing entry (idempotency)
步骤1——检测现有条目(幂等性)
Grep for a file whose frontmatter contains .
If exactly one matches, you are in update mode: preserve its and
filename, rewrite the rest. Otherwise you are in create mode.
changelog/branch: "<current-branch>"created_at在目录中查找前置内容包含的文件。如果找到恰好一个匹配文件,则进入更新模式:保留其字段和文件名,重写其余内容。否则进入创建模式。
changelog/branch: "<current-branch>"created_atStep 2 — Analyse the branch
步骤2——分析分支
- — full commit list including bodies and trailers.
git log origin/<base>..HEAD --pretty=full - — changed files, for grouping the body by package.
git diff origin/<base>...HEAD --name-only
<base>config.jsonbaseBranchmaingit fetch origin <base>- ——包含正文和尾部信息的完整提交列表。
git log origin/<base>..HEAD --pretty=full - ——变更文件列表,用于按包分组正文内容。
git diff origin/<base>...HEAD --name-only
<base>config.jsonbaseBranchmaingit fetch origin <base>Step 3 — Derive metadata
步骤3——提取元数据
| Field | How to derive |
|---|---|
| Match the issue-ID regex (built from |
| |
| Parse |
| Infer from commit subjects and diff: |
| Infer from |
| One-sentence user-facing summary distinct from |
Field ownership — what this skill authors vs. what it must leave alone is the
crux of the contract; see
for the full rules. In short:
references/changelog-contract.md- Authored here: ,
title,release_note,category,breaking,issues,co_authors, and — only whenauthoris on —affectedPackages(written by the enrichment script in Step 5, not hand-edited). Single-package repos leaveaffected_packages(the default) and omit the field entirely.affectedPackages: false - is sacred — set once on create (UTC time of first run); on update, preserve it verbatim.
created_at - Never authored here: (
stats,files_changed,loc_added,loc_removed) and the post-merge fieldscommits/merged_at/commit/pr. A release step finalises them from canonical GitHub PR data after merge —merge_strategyincluded, resolved from the merged PR by itspr(never written by the ship flow). Emit them as blank placeholders on create; leave existing values untouched on update.branch:
The skill emits the derived array as a handoff — a ship flow reuses
it for the PR body and any Linear writeback (e.g. via a skill).
issueslinear-sync| 字段 | 提取方式 |
|---|---|
| 基于 |
| 取自 |
| 解析所有分支提交中的 |
| 从提交主题和差异中推断: |
| 从 |
| 面向用户的单句摘要,与 |
字段归属——该技能负责撰写哪些字段、必须保留哪些字段是契约的核心;完整规则请参阅。简而言之:
references/changelog-contract.md- 在此处撰写:、
title、release_note、category、breaking、issues、co_authors,以及——仅当author开启时——affectedPackages(由步骤5中的增强脚本写入,而非手动编辑)。单包项目请设置affected_packages(默认值),并完全省略该字段。affectedPackages: false - 为只读字段——仅在创建时设置一次(首次运行的UTC时间);更新时需完全保留原始值。
created_at - 绝不在此处撰写:(
stats、files_changed、loc_added、loc_removed)以及合并后的字段commits/merged_at/commit/pr。发布步骤会在合并后从GitHub PR的标准数据中完善这些字段——包括merge_strategy字段,它会通过合并PR的pr字段解析(绝不会由发布流程写入)。创建条目时将这些字段作为空白占位符输出;更新时保留现有值不变。branch:
该技能会输出提取到的数组作为传递数据——发布流程可将其复用至PR正文以及任何Linear回写操作(例如通过技能)。
issueslinear-syncStep 4 — Generate the body
步骤4——生成正文
Group bullets by package, categorised under / / .
Only include headings that have entries. For multi-package changes use
subheaders.
## Added## Changed## Fixed**<pkg-name>:**If , the body MUST start with a section describing
the change and the migration path.
breaking: true## BreakingWrite the , , and body prose in the consuming repo's documented
prose language. Across this estate that is British English (, ,
/) — prose only, never identifiers, dependency names, or upstream API
field names.
titlerelease_notecolourbehaviour-ise-yse按包分组项目符号,归类到//标题下。仅保留包含内容的标题。对于多包变更,请使用子标题。
## Added## Changed## Fixed**<pkg-name>:**若,正文必须以部分开头,描述变更内容和迁移路径。
breaking: true## Breakingtitlerelease_notecolourbehaviour-ise-yseStep 5 — Write or update the file
步骤5——写入或更新文件
Filename: , where the timestamp is
(UTC time of first run) and the slug derives from (lowercase,
non-alphanumerics → , collapse repeats, ~60-char cap on a word boundary).
changelog/YYYYMMDD-HHMMSS-<slug>.mdcreated_attitle-Always quote timestamp strings in YAML ().
Unquoted ISO timestamps parse as Date objects and gain millis on the
enrichment round-trip; quoting keeps them lossless.
created_at: "2026-04-26T13:24:00Z".000ZOn update: preserve and the filename; rewrite ,
, , , , , and the body;
leave / / / / alone (the
release/enrich step fills them post-merge, branch-resolved).
created_attitlerelease_notecategorybreakingco_authorsissuesmerged_atcommitprmerge_strategystatsprUse the frontmatter field order shown in
. Only when
is on, emit as a placeholder — the
script fills it in place. When it is off (the single-package default), omit the
field; is a no-op.
references/changelog-contract.mdaffectedPackagesaffected_packages: []set-affected-packages.mjsThen run the two deterministic enrichment scripts from the consumer repo root
(both idempotent; they match the entry by its frontmatter and leave the
post-merge fields blank):
branch:bash
node skills/changelog/scripts/set-affected-packages.mjs # writes affected_packages from the branch diff
node skills/changelog/scripts/add-links.mjs # rewrites bare issue IDs in the current branch's entry to Linear URLsAdjust the path prefix if you installed the skill to a different location.
Both enrichment scripts also accept (alias ) — a read-only
preview that reports what would change and writes nothing, exiting when the
entry is already up to date and when a rewrite is needed (prettier-
style, so CI can gate on it):
--check--dry-run01--checkbash
node skills/changelog/scripts/set-affected-packages.mjs --check # current branch's entry only
node skills/changelog/scripts/add-links.mjs --check # ALL entries in the changelog dirBoth enrichers are branch-scoped by default (A-603): with no
arguments rewrites only the entry/entries whose frontmatter matches the
current git branch, so authoring a new entry never churns unrelated, already-merged
ones. Two modes still scan the whole directory: (a deliberate
full-directory rewrite) and / (the completeness gate, which can
exit on a historical entry). Use to confirm the directory is fully
enriched; use the default for the per-PR pass on one branch's entry. (When git is
unavailable the default falls back to the full sweep.)
add-links.mjsbranch:--all--check--dry-run1--check文件名:,其中时间戳为(首次运行的UTC时间),由派生而来(小写,非字母数字字符替换为,合并重复符号,在单词边界处限制约60字符)。
changelog/YYYYMMDD-HHMMSS-<slug>.mdcreated_atslugtitle-YAML中的时间戳字符串必须加引号(例如)。未加引号的ISO时间戳会被解析为Date对象,在增强脚本往返过程中会添加毫秒;加引号可确保数据无损失。
created_at: "2026-04-26T13:24:00Z".000Z更新时:保留和文件名;重写、、、、、和正文;保留////不变(这些字段由发布/增强步骤在合并后填充,字段通过分支解析)。
created_attitlerelease_notecategorybreakingco_authorsissuesmerged_atcommitprmerge_strategystatspr请遵循中所示的前置内容字段顺序。仅当开启时,输出作为占位符——脚本会自动填充该字段。当关闭时(单包项目默认值),省略该字段;将不执行任何操作。
references/changelog-contract.mdaffectedPackagesaffected_packages: []affectedPackagesset-affected-packages.mjs然后在消费仓库根目录运行两个确定性增强脚本(均支持幂等性;它们通过前置内容中的字段匹配条目,并保留合并后的字段为空):
branch:bash
node skills/changelog/scripts/set-affected-packages.mjs # 从分支差异中写入affected_packages字段
node skills/changelog/scripts/add-links.mjs # 将当前分支条目中的裸问题ID重写为Linear URL如果技能安装在其他位置,请调整路径前缀。
两个增强脚本均支持(别名)——只读预览模式,报告将要进行的变更但不写入任何内容,当条目已为最新时返回,当需要重写时返回(与prettier的风格一致,因此CI可基于此进行校验):
--check--dry-run01--checkbash
node skills/changelog/scripts/set-affected-packages.mjs --check # 仅检查当前分支的条目
node skills/changelog/scripts/add-links.mjs --check # 检查changelog目录中的所有条目两个增强脚本默认按分支范围处理(A-603):无参数的仅重写前置内容中字段匹配当前git分支的条目,因此撰写新条目时绝不会修改已合并的无关条目。仍有两种模式会扫描整个目录:(主动重写整个目录)和/(完整性校验,可能因历史条目不符合要求而返回)。使用确认目录已完全增强;默认模式用于PR流程中对单个分支条目的处理。(当git不可用时,默认模式会回退为扫描整个目录。)
add-links.mjsbranch:--all--check--dry-run1--checkStep 6 — Validate against the contract
步骤6——根据契约验证
This is the gate:
bash
node scripts/preflight-changelog-ci.mjs # optional: checks Node vs engines/.nvmrc, then pnpm install --frozen-lockfile
node scripts/validate-changelog.mjs # validates frontmatter schema, filename format, field types, ISO timestamps, Breaking section, issue IDspreflight-changelog-ci.mjs这是校验关卡:
bash
node scripts/preflight-changelog-ci.mjs # 可选:检查Node版本与engines/.nvmrc是否匹配,然后执行pnpm install --frozen-lockfile
node scripts/validate-changelog.mjs # 验证前置内容schema、文件名格式、字段类型、ISO时间戳、Breaking部分、问题IDpreflight-changelog-ci.mjsStandalone vs inside a ship flow
独立调用 vs 嵌入发布流程
- Standalone () runs Steps 1–6 and then reports, leaving the entry uncommitted in the working tree for the user to review and commit. It never pushes or opens a PR.
/changelog - Inside a ship flow the same steps run before push; the ship flow then
commits the entry (), pushes, and opens or updates the PR. It leaves
docs(changelog): <title>blank — the release/enrich step fills it post-merge, branch-resolved from the merged PR.pr
- 独立调用()运行步骤1-6后生成报告,将条目未提交地留在工作区供用户审核和提交。绝不会执行推送或创建PR操作。
/changelog - 嵌入发布流程时,相同步骤会在推送前运行;发布流程随后会提交该条目(提交信息为)、推送代码并创建或更新PR。
docs(changelog): <title>字段留空——发布/增强步骤会在合并后通过分支解析填充该字段。pr
Implementation
实现细节
All the scripts the changelog lifecycle needs live under
in this bundle and run on plain Node (no npm dependencies, no build step). They
cover the whole lifecycle the bundle owns — authoring (run by this skill) and
finalisation (wired into the consumer's / CI / release
orchestrator). Each takes (usage, exit 0) and (an offline
smoke test of its pure logic); the file-writing scripts also take /
(report, write nothing).
scripts/package.json--help--self-test--check--dry-runAuthoring — run by this skill (the flow):
/changelog- — writes
scripts/set-affected-packages.mjsfrom the branch diff (monorepo consumers only; a no-op whenaffected_packagesis off).affectedPackages - — rewrites bare issue IDs in the body to Linear URLs.
scripts/add-links.mjs - — optional Node/lockfile CI-parity check (pnpm).
scripts/preflight-changelog-ci.mjs - — validates the entry against the contract.
scripts/validate-changelog.mjs
Finalisation and the CI gate — run by the consumer, not by this skill. These
ship in the bundle too, and an adopter wiring up the orchestrator/CI gate needs
them. They are referenced from the consumer's scripts and
workflows rather than invoked during authoring:
package.json- — release-time enrichment + version-stamping for npm targets, run by the release orchestrator right after
scripts/finalise-changelog.mjs(the consumer exposes it as therelease-please release-prscript). For each un-finalised entry it resolves the merged PR viachangelog:finalise/gh, fills the post-merge fields (git/merged_at/commit/pr/merge_strategy, the last including the merge-excludedstatscount from the PR commits API), stampscommitswith the just-bumpedversionversion, and links bare Linear IDs. It composespackage.json(the PR-metadata fill),lib/enrich.mjs(the merge-excluded commit count) andlib/commit-count.mjs(the version stamp).lib/stamp.mjs - — post-merge enrichment for deploy targets (octavo, shared-workflows), which are never checked out during the release flow and so can't finalise inline. Run by the release orchestrator's daily
scripts/enrich-changelog.mjscron on the checked-out target (the consumer exposes it as theenrich-changelogs.ymlscript). It reads one merged PR's data from an env-var interface (changelog:enrich/BRANCH_NAME/MERGED_AT/MERGE_SHA/MERGE_STRATEGY/PR_NUMBER/ADDITIONS/DELETIONS), finds the entry by itsCHANGED_FILES, and fills the same post-merge field group as finalise (minusbranch:, which a deploy target's own tag flow owns, and minusversion, which the cron doesn't resolve). A thin wrapper overcommits; fill-once and idempotent, so the cron can re-run safely.lib/enrich.mjsexits 1 when an entry still needs enriching;--checkpreviews.--dry-run - — the CI completeness gate, run by the consumer's validation workflow: a release-triggering (
scripts/check-changelog-completeness.mjs/feat/breaking) PR title must carry a datedfixentry, or the build fails.changelog/ - — a one-off backfill of
scripts/backfill-commits.mjsacross the existingstats.commitsbacklog (for adopting the count after the fact). Resolves each entry's merged PR viachangelog/, splices in only theghline (no re-serialise), and is idempotent;commitspreviews. Not part of authoring or the release flow.--dry-run
They share helpers under (, ,
, , , , ). So while this skill
itself stops at authoring + validation and leaves the post-merge fields blank,
the finalisation and completeness scripts that fill them are part of this
bundle — the consumer's / CI / release orchestrator run them, not
the flow.
scripts/lib/changelog.mjsderive-packages.mjsfrontmatter.mjsconfig.mjsenrich.mjscommit-count.mjsstamp.mjspackage.json/changelogNote for adopters: unit tests for these scripts are maintained in therepo (not bundled into the skill). See the skill's README.agent-skills
changelog生命周期所需的所有脚本均位于此捆绑包的目录下,可在纯Node环境运行(无npm依赖,无需构建步骤)。它们覆盖了捆绑包负责的整个生命周期——撰写(由该技能运行)和完善(集成到消费仓库的/CI/发布编排工具中)。每个脚本均支持(显示用法,返回0)和(离线冒烟测试纯逻辑);写入文件的脚本还支持/(报告变更但不写入)。
scripts/package.json--help--self-test--check--dry-run撰写阶段——由该技能运行(流程):
/changelog- ——从分支差异中写入
scripts/set-affected-packages.mjs字段(仅适用于多包项目;当affected_packages关闭时不执行任何操作)。affectedPackages - ——将正文中的裸问题ID重写为Linear URL。
scripts/add-links.mjs - ——可选的Node/锁文件CI一致性检查(适用于pnpm)。
scripts/preflight-changelog-ci.mjs - ——根据契约验证条目。
scripts/validate-changelog.mjs
完善阶段和CI校验——由消费仓库运行,而非该技能。这些脚本也包含在捆绑包中,集成编排工具/CI校验的用户需要它们。它们会被引用到消费仓库的脚本和工作流中,而非在撰写阶段调用:
package.json- ——针对npm目标的发布时增强和版本标记,由发布编排工具在
scripts/finalise-changelog.mjs之后运行(消费仓库将其暴露为release-please release-pr脚本)。对于每个未完善的条目,它通过changelog:finalise/gh解析合并后的PR,填充合并后的字段(git/merged_at/commit/pr/merge_strategy,其中stats包含PR提交API中排除合并提交的stats计数),用刚更新的commits版本标记package.json字段,并链接裸Linear ID。它整合了version(填充PR元数据)、lib/enrich.mjs(排除合并提交的计数)和lib/commit-count.mjs(版本标记)。lib/stamp.mjs - ——针对部署目标(octavo、shared-workflows)的合并后增强,这些目标在发布流程中不会被检出,因此无法在线完善。由发布编排工具的每日
scripts/enrich-changelog.mjs定时任务在检出的目标上运行(消费仓库将其暴露为enrich-changelogs.yml脚本)。它从环境变量接口(changelog:enrich/BRANCH_NAME/MERGED_AT/MERGE_SHA/MERGE_STRATEGY/PR_NUMBER/ADDITIONS/DELETIONS)读取单个合并PR的数据,通过CHANGED_FILES字段找到对应条目,并填充与finalise脚本相同的合并后字段组(不含branch:,该字段由部署目标自身的标签流程负责;不含version,定时任务不会解析该字段)。它是commits的轻量封装;支持一次性填充且幂等,因此定时任务可安全重跑。lib/enrich.mjs在条目仍需增强时返回1;--check提供预览。--dry-run - ——CI完整性校验关卡,由消费仓库的验证工作流运行:触发发布的PR标题(
scripts/check-changelog-completeness.mjs/feat/破坏性变更)必须包含fix目录下的日期化条目,否则构建失败。changelog/ - ——一次性回填现有
scripts/backfill-commits.mjs历史条目中的changelog/字段(用于在事后采用该计数)。它通过stats.commits解析每个条目的合并PR,仅插入gh字段(不重新序列化),且支持幂等;commits提供预览。不属于撰写或发布流程的一部分。--dry-run
这些脚本共享目录下的工具模块(、、、、、、)。因此,尽管该技能仅负责撰写+验证,并保留合并后的字段为空,但填充这些字段的完善和完整性脚本也属于该捆绑包——由消费仓库的/CI/发布编排工具运行,而非流程。
scripts/lib/changelog.mjsderive-packages.mjsfrontmatter.mjsconfig.mjsenrich.mjscommit-count.mjsstamp.mjspackage.json/changelog**适配者注意事项:**这些脚本的单元测试维护在仓库中(未包含在技能捆绑包内)。请参阅技能的README文档。",agent-skills