Cline 事件驱动自动化实战:用 pr-changelog-check 规范自动审查 PR 的 CHANGELOG 更新
本篇基于 Cline 仓库中的事件驱动自动化示例 pr-changelog-check.event.md,完整讲解这份“PR 自动检查 CHANGELOG”规范的字段配置、检查逻辑与部署方式,并结合 cron 事件入口层 与 自动化控制器 的源码,说明事件如何被去重、过滤、限流并落地为一次 Agent 运行。读完后,你可以直接复制该模板到自己的仓库,搭建一套“PR 修改代码却漏更 CHANGELOG 时自动在 PR 上提醒”的事件驱动自动化。
规范是什么:事件驱动的 CHANGELOG 守卫
Cline 的自动化(Automation)体系支持两类规格文件(spec):
- 定时规格(
.cron.md)——按 cron 表达式周期运行,如每日代码审查、周五生成 changelog; - 事件规格(
.event.md)——当某个“归一化事件”被摄入(ingest)时触发。
本文章的主体 pr-changelog-check 属于第二类的典型应用:每当一个 PR 打开(github.pull_request.opened)且满足过滤条件时,自动运行一次 Agent 任务,检查该 PR 是否同步更新了 CHANGELOG,并把结论以 PR 评论形式反馈给作者。在 sdk/examples/cron/README.md 的选型表中,它被定位为 “Check PR changelog / On PR opened / act 模式”。
完整规范原文与逐字段解析
先给出规范文件的完整内容(YAML frontmatter 是配置,正文是给 Agent 的提示词):
---
id: pr-changelog-check
title: Check for Changelog Updates in PRs
workspaceRoot: /absolute/path/to/repo
event: github.pull_request.opened
filters:
repository: your-org/your-repo
pullRequest:
baseBranch: main
debounceSeconds: 10
cooldownSeconds: 60
maxParallel: 3
modelSelection:
providerId: cline
modelId: anthropic/claude-opus-4.7
tags:
- automation
- github
- documentation
metadata:
owner: development
---
Automatically check if a PR that modifies code also updates the CHANGELOG:
1. Detect if the PR modifies source files (src/, lib/, etc.)
2. Check if the PR also includes changes to CHANGELOG.md or relevant changelogs
3. If significant code changes but no changelog update:
- Extract a summary of the changes
- Suggest what should be added to CHANGELOG
- Request the author to add an entry
4. If CHANGELOG is updated:
- Verify the format matches the project style
- Check that entry is concise and user-facing
- Ensure version number is appropriate
Provide feedback as a comment on the PR:
- ✅ CHANGELOG properly updated
- ⚠️ No CHANGELOG changes detected - please add an entry
- 🤔 CHANGELOG entry format seems off - consider [example]
This helps maintain an up-to-date CHANGELOG without manual reminders.
下面按字段组逐一说明其含义与在事件入口层的实际作用。
身份与工作区字段
| 字段 | 示例值 | 说明 |
|---|---|---|
id |
pr-changelog-check |
唯一标识,规范要求字母数字加连字符 |
title |
Check for Changelog Updates in PRs |
人类可读标题 |
workspaceRoot |
/absolute/path/to/repo |
必填,Agent 运行时的项目绝对路径;复制模板后必须改成自己的仓库路径 |
mode |
(本规范省略) | 缺省为 yolo;同目录的姊妹示例 pr-review.event.md 显式写了 mode: act,允许执行命令。README 的选型表把本规范标注为 act 模式,因为“在 PR 上发表评论”需要执行 GitHub 相关命令 |
modelSelection |
{ providerId: cline, modelId: anthropic/claude-opus-4.7 } |
为本规范单独覆盖模型/提供方,不影响全局默认模型 |
tags / metadata |
automation、github、documentation;owner: development |
分组标签与自定义元数据,便于管理和检索 |
事件触发与过滤字段
| 字段 | 示例值 | 说明 |
|---|---|---|
event |
github.pull_request.opened |
事件规格必填。事件类型即触发器 |
filters |
repository: your-org/your-repo + pullRequest.baseBranch: main |
过滤条件:只在指定仓库、且目标分支为 main 的 PR 上触发。替换为你自己的 org/repo |
filters 的匹配并非简单的键值相等——从 cron-event-ingress.ts 的 resolveFilterValue 和 matchesExpected 实现可以看到:
- 过滤键支持点路径(如
pullRequest.baseBranch),会依次在事件的attributes、payload中按路径取深层字段(getPath按.逐段下钻); - 期望值支持数组(语义为“任一匹配即可”)、嵌套对象(递归要求所有键匹配)以及普通标量(严格相等比较)。
因此 pullRequest: { baseBranch: main } 这一层对象过滤,会被递归展开为“事件属性中的 pullRequest.baseBranch 必须等于 main”。
限流三兄弟:debounce / dedupe / cooldown
事件类规范独有的四个字段(README 的 Field Reference 给出完整清单,默认值均为 0/不限):
| 字段 | 本规范取值 | 默认值 | 作用 |
|---|---|---|---|
debounceSeconds |
10 |
0 | 合并事件:收到事件后等待 N 秒,期间同一 dedupeKey 的新事件不新建 run,而是把已有排队 run 的 scheduledFor 顺延 |
dedupeWindowSeconds |
(未设置) | 0 | 滑动窗口去重:N 秒内同一 dedupeKey 的事件直接跳过 |
cooldownSeconds |
60 |
0 | 运行冷却:某次 run 之后 N 秒内不再为该规范触发新 run(不限 dedupeKey) |
maxParallel |
3 |
不限 | 该规范最多并发 3 个 run |
这三者的行为在入口层源码中有精确对应。materializeForSpec(cron-event-ingress.ts)按顺序执行:
- debounce 分支:若
debounceSeconds > 0且已存在同一(specId, dedupeKey)的排队 run,则调用updateQueuedEventRunForDebounce将scheduledFor更新为max(原 scheduledFor, receivedAt + debounceSeconds)并复用该 run——本规范设为 10 秒,意味着 PR 打开后 10 秒内的抖动事件(如重复 webhook 推送)会合并成一次检查; - dedupe 分支:若
dedupeWindowSeconds > 0且窗口内已有同 dedupeKey 的 run,则以dedupe_window原因抑制; - cooldown 分支:若
cooldownSeconds > 0且冷却窗内该 spec 已跑过 run,则以cooldown原因抑制——本规范的 60 秒冷却防止作者连续开 PR 或对同一 PR 反复操作时刷屏评论; - 均通过后才调用
enqueueRun落库一条triggerKind: "event"的 run,scheduledFor为receivedAt + debounceSeconds(无 debounce 则立即)。
抑制原因会被完整记录:CronEventSuppressionReason 类型为 "duplicate_event" | "filter_mismatch" | "dedupe_window" | "cooldown"(cron-event-ingress.ts),配合事件日志可审计“某个事件为什么没触发”。
事件从摄入到运行的完整链路
规范只是声明,真正把 pr-changelog-check 跑起来的是事件摄入链路。
第一步:事件归一化
CronEventIngress.ingestEvent 首先调用 normalizeEvent(cron-event-ingress.ts):校验 eventId/eventType/source,规范化 occurredAt 为 ISO 时间戳,并在未显式提供 dedupeKey 时按 `${eventType}:${source}:${subject ?? eventId}` 自动生成。随后 store.insertEventLog 做持久化先于匹配(“Durable ingress for normalized automation events”——先落库再匹配,即使后续处理失败也有事件日志可查)。若该 eventId 已存在,直接返回 duplicate: true 且抑制原因为 duplicate_event。
第二步:规范匹配与 run 物化
入口层通过 store.listEventSpecsForType(eventType) 取出所有声明 event: github.pull_request.opened 的规范,逐个做 automationEventMatchesFilters 过滤;匹配上的逐个走 materializeForSpec(即上一节讲的 debounce/dedupe/cooldown 判定)。最终事件日志状态被写成三态之一:unmatched(无规范匹配)、queued(有 run 入队)、suppressed(全部被抑制)。
第三步:谁来执行
需要注意入口层的职责边界:源码注释明确写着 “It deliberately does not execute agents; the normal runner claim loop owns execution”——摄入层只负责把 cron_runs 物化进队,真正的 Agent 执行由 cron runner 的 claim 循环领取。每次 run 结束后,报告会写入 cron-report-writer.ts 描述的 ~/.cline/cron/reports/<run-id>.md(workspace scope 下则写到工作区旁),报告中包含 YAML frontmatter(run ID、状态、耗时、token 用量)、执行摘要、工具调用记录,以及触发事件上下文——对事件驱动规范,这意味着事后排查“这次检查为什么给出 ⚠️ 结论”时,可以在报告里看到当时的 PR 事件 payload。
事件从哪里来(摄入渠道)
按 sdk/examples/cron/README.md 的说明,归一化事件有四条摄入渠道:
- GitHub App 或 webhook 接收器——
pr-changelog-check的生产用法:GitHub 推送pull_request.opened后,由接收端归一化为AutomationEventEnvelope(含eventType、subject(如仓库名)、attributes(含pullRequest.baseBranch等)并摄入; - 插件事件——参考 automation-events.ts 插件自行
emit; - Connector 适配器;
- SDK 编程式摄入——
cline.automation.ingestEvent(event)。该方法在 automation.ts 中由ClineCoreAutomationController.ingestEvent实现:它委托CronService.ingestEvent,并把入口层结果映射为对外 API 的ClineAutomationEventIngressResult(event、duplicate、matchedSpecIds、queuedRuns、suppressions),供调用方判断事件是否真正触发了运行。
本地无外部依赖地验证这套链路,可以使用同目录的 local-manual-test.event.md(event: local.manual_test,debounceSeconds: 0 立即触发)配合 hub WebSocket 客户端发送 cron.event.ingest 消息来演练,而不必真的接 GitHub webhook。
提示词设计:一个双向的检查清单
规范的正文部分就是 Agent 的系统级任务说明,其价值在于定义了双向验证而非单向提醒:
方向一:代码改了但 CHANGELOG 没改(最常见的漏更新场景)
- 检测 PR 是否修改了源码文件(
src/、lib/等); - 检查 PR 是否包含
CHANGELOG.md或相关 changelog 的变更; - 若有实质性代码变更但没有 changelog 更新:提取变更摘要 → 建议应补充的条目 → 要求作者补写。
方向二:CHANGELOG 改了但质量不佳
- 校验条目格式是否符合项目风格;
- 检查条目是否简洁、面向用户(user-facing);
- 确认版本号是否恰当。
最后以三种标准化的 PR 评论反馈:
- ✅ CHANGELOG properly updated(通过)
- ⚠️ No CHANGELOG changes detected - please add an entry(漏更新)
- 🤔 CHANGELOG entry format seems off - consider [example](格式存疑并给出示例)
这套“三种状态 + 给出示例”的反馈设计,使得 Agent 的评论对作者是可行动的(actionable):不是干巴巴地说“格式不对”,而是附一个参照示例。它与 changelog-generator.cron.md(定时从近期 commit 自动生成 changelog 条目)形成互补——一个在 PR 关口“防守”,一个在周五“主动生成”,组合起来即可覆盖 README “Practical Automation Workflows” 中推荐的完整自动化套件里的 changelog 维护部分。
部署步骤
# 1. 创建事件规格目录
mkdir -p ~/.cline/cron/events
# 2. 复制模板
cp sdk/examples/cron/events/pr-changelog-check.event.md ~/.cline/cron/events/
# 3. 编辑 spec:
# - workspaceRoot 改成你项目的绝对路径
# - filters.repository 改成 your-org/your-repo
# - 按需要调整 debounceSeconds / cooldownSeconds / maxParallel
# - 接入 GitHub App 或 webhook,把 pull_request.opened 归一化后摄入
启用自动化运行时(三选一,见 README):
// SDK:ClineCore 开启 automation
const cline = await ClineCore.create({
automation: true, // 布尔值会被 normalizeAutomationOptions 归一为空选项对象
});
// Hub:带 cronOptions 启动
new HubWebSocketServer({
cronOptions: { workspaceRoot: "/absolute/workspace" }
});
# CLI
cline --enable-automation
启动后 spec 会在 reconcile 阶段被加载;此后每个满足过滤条件的 github.pull_request.opened 事件都会按“debounce 10s 合并 → 60s 冷却 → 最多 3 并发”的节奏触发一次 changelog 检查,运行报告落在 ~/.cline/cron/reports/ 供追溯。
适用边界与调整建议
结合仓库事实,使用这份模板时需要注意:
- 事件载荷契约:
filters的pullRequest.baseBranch能否命中,取决于你的 webhook 接收端把 PR 属性放进了事件的attributes还是payload(入口层会按attributes→payload→ 顶层字段的顺序解析点路径)。接入 GitHub webhook 时应先本地ingestEvent一条样例事件,用返回的suppressions中是否出现filter_mismatch来验证载荷结构; - 模型与预算:
modelSelection固定了模型,timeoutSeconds、maxIterations、tools(如限制为run_commands,read_files只读工具 + 评论所需工具)在本模板中均未显式设置,生产环境建议像 pr-review.event.md 那样显式补齐timeoutSeconds: 1800、maxIterations与mode: act; - 多仓库复用:同一事件类型下多条规范会被逐一匹配(
listEventSpecsForType返回全部候选),因此不同仓库可各建一份 spec,通过filters.repository区分,互不干扰,但共享各自独立的冷却与并发预算; - 非阻塞定位:该自动化以“评论提醒”而非“卡 CI”的方式工作(README 对姊妹规范 pr-test-coverage 也强调 “helpful rather than blocking”),适合作为 changelog 维护的第一道自动化防线,最终质量把关仍由 reviewer 完成。
小结
pr-changelog-check.event.md 是 Cline 事件驱动自动化(.event.md spec)的一个可直接上生产的模板:它用 event + filters 精确声明触发条件(github.pull_request.opened、指定仓库、目标分支 main),用 debounceSeconds/cooldownSeconds/maxParallel 控制触发节奏(10 秒合并、60 秒冷却、3 并发),用双向检查清单式的提示词定义了 Agent 的具体职责与三态 PR 评论输出。其背后是 cron 事件入口层 提供的“先持久化、再过滤匹配、后物化 run”的可靠链路,以及 ClineCore 自动化 API 暴露的编程式摄入入口。复制模板、改三个占位值(workspaceRoot、filters.repository、模型)、接上 webhook,即可获得一个无需人工催促的 CHANGELOG 守卫。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00