首页
/ Storybook 的 Agent 技能实战:用 update-pr-description 技能让 AI 帮你校准 PR 标题与描述

Storybook 的 Agent 技能实战:用 update-pr-description 技能让 AI 帮你校准 PR 标题与描述

2026-09-05 16:53:43作者:钟日瑜

本篇围绕 Storybook 仓库中的 Agent 技能文件 update-pr-description/SKILL.md 展开,讲解该技能如何通过一套标准化的六步工作流,让编码 Agent 对比 PR 的标题/描述与其实际实现(commit + diff),逐条提出并应用修正。读完后你将掌握:如何在自己的大型仓库中组织"一个核心技能文件 + 多工具镜像"的 Agent 技能体系,以及 PR 描述与 CI 流水线之间如何通过 HTML 注释锚点(如 canary 区段)形成机器可读的协作契约。

技能体系定位:.claude/skills 是指向 .agents/skills 的镜像层

在 Storybook 仓库中,AI 编码 Agent 的指令体系遵循 AGENTS.md 中声明的原则:"This file is the canonical instruction source for coding agents. Files like CLAUDE.md should point here instead of duplicating instructions"——即指令以单一来源为准,其余文件只做指针。

技能(skill)文件同样采用这一"单一来源 + 镜像"策略:

这样做的收益是:技能逻辑只在 .agents/skills/ 中维护一份,Claude Code 与通用 Agent 规范共用同一份定义,避免两处文档漂移——而 PR 描述本身漂移,恰恰是这个技能要解决的问题。

Frontmatter:技能的元数据与触发语义

每个 SKILL.md 以 YAML frontmatter 开头,声明技能的名称与触发条件:

---
name: update-pr-description
description: Evaluate a PR's title and description against its actual
  implementation, then iteratively suggest and apply updates. Use when the
  user asks to check, fix, or update a PR title or description.
---

其中 description 承担了"触发词"的角色:当用户要求"检查、修正或更新 PR 标题/描述"时,Agent 应加载该技能。作为对照,同目录下的 canary 技能 还额外声明了 allowed-tools: Bash,说明 frontmatter 也用于约束技能可用的工具集。

六步工作流:从证据采集到代用户提交

技能的主体是一个明确的六步流程,核心思想是先取证、再比对、最后才动笔,全程以 gh CLI 为操作界面。

第 1 步:定位目标 PR(Resolve)

优先使用用户提供的 PR 编号或 URL;若用户未提供,则用 gh pr view 反查当前分支对应的 PR:

gh pr view   # 查看当前分支关联的 PR

这一步保证了后续所有操作都锚定在正确的 PR 上,而不是凭分支名猜测。

第 2 步:采集三类证据(Gather evidence)

技能要求并行采集三类相互独立的证据,分别回答"声称了什么"与"实际做了什么":

# 1) PR 的标题与正文(声称的内容)
gh pr view <pr> --json title,body

# 2) 提交历史(实际做了什么,按 commit 粒度)
gh pr view <pr> --json commits

# 3) 相对 base 分支的完整 diff(实际改动的最终形态)
gh pr diff <pr>

值得注意的是技能特意区分了 commitsdiff:commit message 反映的是开发过程中的阶段性意图(可能包含已被推翻的中间提交),而 gh pr diff 给出的是合并前相对 base 的最终净改动。只比对其中任何一个都可能误判。

第 3 步:评估实质性偏差(Evaluate divergence)

这是技能中最体现判断力的步骤。技能明确区分了"值得标记的偏差"与"应忽略的差异":

  • 只标记 meaningful divergence(实质性偏差):范围错误(wrong scope)、遗漏重大改动(missing major changes)、过时陈述(stale claims)、不准确的总结(inaccurate summary);
  • 忽略 trivial wording(琐碎措辞差异):措辞风格、形容词选择等不影响信息准确性的差异不触发修改。

这一条实际上是在给 Agent 设定"克制度":PR 描述是写给维护者看的工程沟通文档,不是文学文本,Agent 的职责是纠正事实性偏差,而非润色文风。

第 4 步:汇报并设置"早退"出口(Report)

技能要求 Agent 先向用户报告"标题和/或描述是否存在实质性偏差",并且如果没有偏差,到此为止(If not, stop here)。这个显式的早退分支很关键——它防止 Agent 为了"展示能力"而对一个本来准确的描述强行重写,与后文 Notes 中的"Do not rewrite a description that's already accurate"形成呼应。

第 5 步:逐条迭代建议(Suggest iteratively)

若存在偏差,技能规定采用"一次只提一个变更"的协商节奏:

  1. 提出具体的更新后标题/描述(Propose concrete updated title/description);
  2. 每次只就一处变更征询用户是否应用(Ask the user one change at a time);
  3. 接受用户的编辑与进一步修正,循环精炼(accept edits, and refine)。

这种"小步提交式"的对话设计,使每次修改都可被独立审查,避免 Agent 一次性提交整篇重写稿让用户难以逐条判断。

第 6 步:代用户应用(Apply)

用户同意后,Agent 通过单条 gh 命令完成提交:

gh pr edit <pr> --title ... --body ...

至此,技能闭环完成:读取(gh pr view/gh pr diff)→ 判断 → 协商 → 写回(gh pr edit)。

Notes 四原则:与 Storybook PR 模板的机器级契约

技能末尾的 Notes 部分看似简短,实则是与仓库 PR 模板 深度耦合的约束规则,逐条展开:

1. 匹配仓库既有模板风格(Match the repository's existing PR template/style)

Storybook 的 PR 模板 .github/PULL_REQUEST_TEMPLATE.md 有严格的分区结构:

  • Closes #:关联 issue 编号,多 issue 需拆分列出;
  • ## What I did:变更摘要;
  • Checklist for Contributors:自动化测试覆盖(stories / unit tests / integration tests / end-to-end tests 四个复选框)+ 强制性的 Manual testing 小节(模板明确标注 "This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly");
  • Checklist for Maintainers:CI 沙箱标签(ci:normal/ci:merged/ci:daily,对应沙箱集合定义在 code/lib/cli-storybook/src/sandbox-templates.ts)、QA 标签(qa:needed/qa:skip)、以及必选的类别标签(bugmaintenancedependenciesbuildcleanupdocumentationfeature requestBREAKING CHANGEother);
  • Canary release 区段Benchmark 区段(由 HTML 注释锚点占位)。

Agent 在重写描述时必须保留这套骨架,只填充内容,不改变结构。

2. 不重写已经准确的描述(Don't rewrite a description that's already accurate)

与第 4 步的"早退"逻辑一致,属于幂等性约束:技能的最终状态是"描述与实现一致",而非"描述被我改过"。

3. 同步更新复选框状态(Update the state of checkboxes where appropriate)

PR 正文中的 - [ ] 复选框是维护者流程的输入。典型场景:PR 初开时 Manual testing 步骤缺失,Agent 补齐步骤的同时把对应的测试覆盖项从 - [ ] 改为 - [x]。这与模板"填写章节、保留注释"的约定("put an 'x' inside the '[ ]'")配合。

4. 填充章节时删除占位符/提示注释(Remove section placeholders/reminders when filling out a section)

模板中大量使用 HTML 注释作为给人类贡献者的填写提示,例如 <!-- Briefly describe what your PR does -->。当 Agent 实际填写了某章节后,应删去对应提示注释,避免"说明文字"与"填写内容"并存的冗余。

5. 绝不删除 canary release 区段(Do not remove the canary release section)

这是 Notes 中唯一一条"禁止性"规则,其背后有直接的工程原因,可以从发布流水线得到验证。

publish.ymlpublish-canary 作业中,canary 发布完成后有一个 "Replace Pull Request Body" 步骤,使用 ivangabriele/find-and-replace-pull-request-body 动作,以 CANARY_RELEASE_SECTION 这一 HTML 注释作为定位锚点,把整个区段替换为发布结果(见 publish.yml#L380-L405):

- name: Replace Pull Request Body
  uses: ivangabriele/find-and-replace-pull-request-body@...
  with:
    githubToken: ${{ secrets.GH_TOKEN }}
    prNumber: ...
    find: 'CANARY_RELEASE_SECTION'
    isHtmlCommentTag: true
    replace: |
      This pull request has been released as version `0.0.0-pr-<PR_NUMBER>-sha-<SHORT_SHA>`.
      Try it out in a new sandbox by running `npx storybook@<VERSION> sandbox` ...

也就是说,模板中包裹 canary 说明的成对注释:

<!-- CANARY_RELEASE_SECTION -->
...
<!-- CANARY_RELEASE_SECTION -->

是 CI 与 PR 正文之间的机器可读接口:流水线发布 canary 版本(版本号格式为 0.0.0-pr-<PR_NUMBER>-sha-<SHORT_SHA>,由 publish.yml#L365-L372yarn release:version --exact 步骤确定)后,依赖这对锚点原地注入版本号与 npx storybook@<VERSION> sandbox / upgrade 的试用命令。一旦 Agent 在校准描述时把这个区段当作"未填写的模板残留"删掉,后续所有 canary 发布的 PR 回写都会静默失效。同理,模板末尾的 BENCHMARK_SECTION 注释也承担类似职责。

这条规则因此可以从一般性的"谨慎编辑"升格理解为:PR 描述不仅是给人读的文档,还是 CI 系统写入结果的挂载点,编辑 Agent 必须把锚点注释视为不可变结构。

兄弟技能:update-pr-description 在 PR 生命周期中的位置

.agents/skills/ 下的技能集合看,update-pr-description 并非孤立工具,而是 Storybook PR 流水线上"开 PR → 发 canary → 校准描述"链条的一环:

技能 文件 职责 与本文技能的关系
pr SKILL.md 定义 PR 标题格式 [Area]: [Description](如 CSFFactories: Fix type export)与三类必选标签(category/CI/QA),要求逐字复制模板并保留全部 HTML 注释 定义了"描述应该长什么样",是本文技能评估偏差时的风格基准
open-pr SKILL.md 从当前分支开 draft PR:自动探测 base 分支(支持 stacked PR)、按模板填正文、创建后主动询问是否发 canary 开 PR 阶段产出"第一版描述",后续可能随代码演进偏离实现
canary SKILL.md 通过 gh workflow run --repo storybookjs/storybook publish.yml --field pr=<PR_NUMBER> 触发 canary 发布,并说明如何从 PR 正文中读取发布版本号 canary 发布会改写 PR 正文的 canary 区段,进一步提高了"编辑描述不得破坏锚点"的必要性
update-pr-description SKILL.md 本文主角:比对标题/描述与实际实现,迭代式修正 在 PR 生命周期中任何时点(新增 commit、rebase、拆分合并后)都可触发,兜底保证描述不失真

可以看到一个清晰的设计思路:pr/open-pr 技能保证开 PR 时描述是模板化、准确的;canary 技能保证发布时CI 能写回 PR;而 update-pr-description 保证整个迭代过程中描述持续与实现同步。三者共同依赖同一个契约文件 .github/PULL_REQUEST_TEMPLATE.md,以及其中不可删除的注释锚点。

可迁移的实践要点

从这个技能中可以提炼出若干对任意大型仓库都有参考价值的做法:

  1. 技能文件用"证据驱动"而非"模板驱动"编写。流程的每一步都绑定可执行命令(gh pr view --jsongh pr diffgh pr edit),Agent 的每个判断都有数据源,而不是凭上下文"感觉"PR 描述写得对不对;
  2. 显式定义"不做什么"。"只标记实质性偏差""已准确则不重写""逐条协商"等约束,比步骤本身更能决定技能的实际效果,它们共同压制了 LLM 常见的过度改写倾向;
  3. 单一来源 + 镜像引用.claude/skills/ 一行指针 → .agents/skills/ 权威文件)让多 Agent 工具生态共享同一份技能定义;
  4. 文档锚点即接口CANARY_RELEASE_SECTION 这类 HTML 注释让 PR 正文同时服务人类阅读与 CI 程序化改写,任何自动编辑流程都必须把"保留锚点"列为硬约束——这正是 update-pr-description/SKILL.md 最后一条 Note 存在的原因。

综合来看,update-pr-description 技能 的价值不仅在于"帮人改 PR 描述",更在于它示范了如何在 Storybook 这样的工程仓库中,把 PR 正文当作一份同时面向人与 CI 的可执行文档来治理:模板定义结构,注释锚点定义机器接口,Agent 技能则负责在整个 PR 生命周期内维持内容与实现的持续一致。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384