2026-06-11 · harness

第 15 章:终章(打磨、上线、发布)

把 PR reviewer 从演示打磨成可信赖的系统,打包成技能发布,并用一份贯穿全书的收尾清单收束。

小满 · 满

一路走来,小满从一团回声,长成了今天的样子。最后一章,让它满。

草稿章节。跑通格式用的第一版,正式索引前会再打磨。

本章目标

PR reviewer 的最终样子:一个打包好、已发布的技能,队友能在干净环境里装上,然后放心用在自己的仓库上。这是终章,所以它做两件事。第一,把你前面十四章搭出的每一块拼成一张图、一个目录。第二,走完「从演示到能放心用」这一步:靠几个具体属性,把「它惊艳过我一次」变成「我愿意让它没人盯着也去评审我的 PR」。

读完你会有一个 pr-reviewer/ 技能目录,里面有 SKILL.md、一份写清楚的契约和一份运行手册,再加一份收尾清单,每一章对应一行,你能拿出证据才打勾。

前置准备

  • 第 13、14 章里已经部署、也做了版本管理的 agent,要回滚只差按一个开关。
  • 当前发布版的评测集全绿。
  • 打开官方 Agent Skills 文档,照着它把打包结构做对(SKILL.md,frontmatter 里有 namedescription)。

动手做

1. 一眼看完整个系统

打包前,先把你真正搭出来的东西画出来。前面每一章做的是其中一个部件,终章是把它们装到一起。画出来,缺了哪个部件一眼就能看见,这张图还能直接当你文档里的架构一节。

                    GitHub PR webhook
                           |
                  [ 部署  ch13 ]            <- 跑循环,收窄 token
                           |
                  [ 发布路由  ch14 ]        <- 金丝雀百分比、版本戳、回滚
                           |
            +------------- agent 循环  ch3 -------------+
            |  系统提示词 = 契约             ch2        |
            |  上下文:diff + 仓库事实        ch4        |
            |  SKILL.md:评审流程            ch5        |
            |  hooks / slash 入口            ch6        |
            |  subagent:深度安全扫描        ch7        |
            |  护栏:沙箱 + 权限范围          ch11       |
            +-------------------+-----------------------+
                                |
                     发表评审评论(仅此)
                                |
       [ 评测 ch9 ] [ 可观测 ch10 ] [ 成本 ch12 ] 在一旁盯着

真正帮你挣到信任的两个部件,不在「一切顺利」那条路上:让 agent 显式失败的护栏,和让你能证明它干了什么的可观测。把它们留在图里,你就不会哪天只把循环单独发出去。

2. 跨过信任那道坎

一个演示可以很惊艳,但还是不能发布。惊艳看的是顺利的时候表现好不好,能不能信任看的是出岔子的时候它会怎样。有三个属性能帮你跨过这道坎,而且每个都能实际验证,不是空话。第一,agent 会显式失败:碰到模棱两可或者超大的 diff,它说「无法评审」,而不是硬猜。第二,它的凭证只够发评论,所以哪怕提示词被完全攻陷,它也合不了、推不了、删不了。第三,每个动作都带着第 14 章的版本号记进日志,这样任何一次评审事后都能查清楚。

# 信任契约,用代码强制,不靠感觉
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, TextBlock

async def review(pr):
    if pr.diff_lines > MAX_DIFF or pr.is_binary_only:
        return comment("无法评审:diff 过大 / 纯二进制。"
                       "已标记转人工评审。")               # 显式失败
    options = ClaudeAgentOptions(
        system_prompt=CFG.contract,
        allowed_tools=["Read"],        # 只读:ch11 护栏,不写不跑命令
        max_turns=6,
        cwd=pr.repo,
    )
    findings = ""
    async for message in query(prompt=f"审查 PR #{pr.id}。", options=options):  # ch3 循环
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, TextBlock):
                    findings += block.text
    log.info("review", version=CFG.version, pr=pr.id)   # ch10:带版本戳
    return post_comments(findings)     # token 权限 = 仅评论,ch11
// 信任契约,用代码强制,不靠感觉
import { query } from "@anthropic-ai/claude-agent-sdk";

async function review(pr) {
  if (pr.diffLines > MAX_DIFF || pr.isBinaryOnly) {
    return comment("无法评审:diff 过大 / 纯二进制。已标记转人工评审。");  // 显式失败
  }
  const options = {
    systemPrompt: CFG.contract,
    allowedTools: ["Read"],        // 只读:ch11 护栏,不写不跑命令
    maxTurns: 6,
    cwd: pr.repo,
  };
  let findings = "";
  for await (const message of query({ prompt: `审查 PR #${pr.id}。`, options })) {  // ch3 循环
    if (message.type === "assistant") {
      for (const block of message.message.content) {
        if (block.type === "text") findings += block.text;
      }
    }
  }
  log.info("review", { version: CFG.version, pr: pr.id });   // ch10:带版本戳
  return postComments(findings);     // token 权限 = 仅评论,ch11
}

一个会出错但闯不了祸的 reviewer,可以发布。一个大多数时候对、但偶尔会搞破坏的 reviewer,不能发布。

3. 打包成技能

现在把流程放进一个 Claude 能发现并加载的结构里。技能就是一个自包含的目录,入口是 SKILL.md:YAML frontmatter 里有两个必填字段,name(小写、用连字符、不能含 “claude”/“anthropic”)和 description(做什么、什么时候用),后面跟着具体说明。又大又不常用的材料放到同级的别的文件里,只有被引用时才加载。这就是官方文档说的渐进式披露:description 一直在上下文里,正文在触发时才加载,引用文件按需加载。

pr-reviewer/
├── SKILL.md            # 入口:frontmatter + 评审流程
├── CHECKLIST.md        # 按类别要查什么(需要时才加载)
├── SECURITY.md         # 更深的安全扫描(ch7 subagent 的任务书)
└── scripts/
    └── post_review.py  # 确定性的评论发表(ch11 权限范围已固化进去)
# pr-reviewer/SKILL.md
---
name: pr-reviewer
description: Reviews a pull request diff for correctness, security, and clarity, then posts inline comments. Use when asked to review a PR, check a diff before merge, or audit changes for risky patterns.
---

# PR Reviewer

## 何时停止
若 diff 超出尺寸预算或为纯二进制,发表「无法评审」并标记转人工。绝不瞎猜。

## 流程
1. 用一句话概括改动(类别见 CHECKLIST.md)。
2. 跑正确性与清晰度两轮检查。
3. 涉及鉴权、加密或输入处理的改动,按 SECURITY.md 走。
4. 用 scripts/post_review.py 发表结论(仅评论权限)。

SKILL.md 保持短,把细节引到 CHECKLIST.mdSECURITY.md 里。入口文件太臃肿,每次技能一触发就白白吃掉上下文预算,哪怕这次任务只是改一个错别字。

4. 诚实写清契约

让人信得过一个工具,靠的不是吹它完美,而是把它的边界说准。写清楚 reviewer 查什么、特意不查什么、已知的盲点在哪,这样用户就能在它擅长的地方放心用,在它弱的地方自己再核一遍。

## 这个 reviewer 做什么、不做什么
检查:  正确性可疑处、明显的安全反模式、命名不清、缺失的错误处理、
        误提交的密钥。
忽略:  风格/格式(交给你的 linter)、架构决策、任何需要它看不到的产品
        上下文的东西。
边界:  可能漏掉细微逻辑 bug;在安全攸关的代码上不能替代人工评审。
        超出尺寸预算的 diff 会被跳过。

5. 发布,并把版本固定下来

把技能分享出去,让别人能装。在 Claude Code 里,技能是基于文件系统的:个人技能放 ~/.claude/skills/,项目技能放 .claude/skills/,要共享可以走插件市场(按官方文档,先 /plugin marketplace add <owner/repo>,再 /plugin install <name>@<marketplace>)。发布版本时打的标签,要和第 14 章的发布 id 一致,这样「某人装的是哪个技能」和「产出某次评审的是哪个配置」就能对上,是同一个版本。

# 项目本地安装
$ cp -r pr-reviewer .claude/skills/

# 或通过插件市场仓库发布,队友再执行:
$ # /plugin marketplace add your-org/agent-skills
$ # /plugin install pr-reviewer@your-org-skills

$ git tag pr-reviewer-2.4.0 && git push --tags   # 与 ch14 同一坐标

只用可信来源的技能,也把这句话告诉装你技能的人:官方文档讲得很清楚,技能里带着说明和代码,所以它该像任何一个依赖那样被审计。

6. 用运行手册完成交接

技能发出去了却没有运维方案,等于第一次出事时没人负责。写一份简短的运行手册,让一个没参与开发的人,在着急上火的时候也能照着做:怎么回滚、出事找谁、日志在哪、SLA 承诺了什么。

## 运行手册
回滚:    agentctl release set-active pr-reviewer-<上一版>  (数秒接管)
呼叫:    #pr-reviewer-oncall ;负责人:<名字>
日志:    可观测看板 -> 按版本戳过滤
SLA:     可用性 99%,p95 <= 60s,评测下限 0.85(见 ch14)
已知坏况:false-flag 率飙升时,先停金丝雀,再排查。

习得「独立交付」小满现在能自己收尾了:遇到看不懂或者太大的 diff 就说「无法评审」,不硬猜;权限只够发评论;每个动作都带版本记进日志;还打包成了一个带契约和运行手册的技能,队友在干净环境里装上就能放心用。

如何验证

  • 在一个干净检出里装上已发布的技能,端到端跑一次评审,确认它只发评论、别的什么都不干。
  • 喂它一个超大 diff,确认它会用「无法评审」显式失败。
  • 确认下面清单每一行背后都有证据(一个通过的测试、一行日志、一段配置),不是光打个勾。
  • 把运行手册交给一个没参与开发的人,让他自己完成一次回滚。

习得「放手发布」你现在能在干净检出里装上发布版,端到端跑通一次评审,确认它只发评论、碰到超大 diff 会显式失败,再把运行手册交给一个没参与开发的人去独立回滚。做到这些,你就能放心把小满交出去了。

原理

全书讲的其实是同一件事,只是换了十四个角度看:agent 是一个系统,不是一段提示词。提示词定下它的契约,循环驱动它一步步往下走,上下文和技能是它当下能用的记忆,评测替你盯着它对不对,护栏拦住它去做危险的事,可观测让你事后能查清它做了什么,版本管理保证出事能退回去。打包做的,就是把这套系统变得能搬到别处用,把契约写得让下一个人也看得懂。你交付出去的是「能让人放心」,不是「看着聪明」。

收尾清单

每章一行,拿到证据才能打勾:

  • ch0 心态 把 agent 当作你运维的系统,而非你展示的演示。[ ]
  • ch1 搭建 可复现的开发循环;任何人都能本地跑起 reviewer。[ ]
  • ch2 提示词即契约 系统提示词说清职责、边界与停止条件。[ ]
  • ch3 agent 循环 循环会终止,并处理无工具与出错的情形。[ ]
  • ch4 上下文 只有它需要的 diff 与仓库事实进入上下文。[ ]
  • ch5 SKILL.md 评审流程住在技能里,而非一段巨大提示词里。[ ]
  • ch6 hooks / slash 一个干净入口在 PR 打开时触发评审。[ ]
  • ch7 subagents 深度安全扫描作为一个聚焦的 subagent 运行。[ ]
  • ch8 Codex / 互操作 它与开发流里其它工具配合良好。[ ]
  • ch9 评测 当前发布版评测全绿,有 pass-rate 下限。[ ]
  • ch10 可观测 每次评审都带版本戳记了日志。[ ]
  • ch11 错误处理 + 护栏 显式失败;沙箱;仅评论 token。[ ]
  • ch12 成本 每次评审的 token 与美元成本被跟踪并有上限。[ ]
  • ch13 部署 部署在稳定入口后,带健康检查。[ ]
  • ch14 版本 + SLA 钉死配置、回归闸门、金丝雀、一开关回滚、已发布 SLA。[ ]

小结

你交付了一个能让人放心、有版本、已发布的 PR reviewer:它会显式失败、token 只够发评论、每个动作都带版本记日志、写清了自己的边界、能当技能装上、还附了运行手册方便交接。这门手艺从来不靠某一个技巧,而是提示词、循环、上下文、工具、评测、护栏和运维当成一个系统一起配合。这就是 AgentCraft。

常见坑

  • 把演示当成品发。 演示看的是顺利时的表现,能不能信任看的是出岔子时的表现。发布前先跨过这道坎。
  • SKILL.md 太臃肿。 细节该放进按需加载的引用文件,别堆在每次都触发的入口文件里。
  • 边界没写清。 用户不知道边界在哪,就会在不该信的地方信它。
  • 技能和配置对不上。 给已发布的技能打上和产出评审的那个发布版相同的 id。
  • 没有运行手册。 没运维方案就发布,第一次出事就没人负责。

全图点亮。你不再盯着它了。这天你下班关机,它没有像初醒之隅那天那样只会回声,而是自己把今天的活收了尾,留下一句:「明天见。」将满未满,而此刻,刚刚好满。彩蛋:把它发布出去,让别人也能领养一只自己的小满。

刚点亮 满 · 地图已点亮 16 / 16

来源

  1. Anthropic: Agent Skills · official
  2. Anthropic: 开源 Skills 仓库 · official