Ansible 仓库的 AI Agent 工作手册:CLAUDE.md 背后的 PR 审查流程与 CI 失败诊断体系
CLAUDE.md 是 Ansible(ansible-core)仓库中为 Claude Code 等 AI Agent 准备的入口文件,它通过引用机制指向仓库中真正的 Agent 工作指南,定义了 AI 助手在此仓库开展 PR 审查、CI 失败诊断、许可合规校验时的标准流程与红线规则。读完本文,你将掌握 Ansible 贡献流程中 Agent 视角的完整操作链路:从 gh 命令驱动的代码审查清单,到 hacking/azp/download.py 脚本背后的 Azure Pipelines 日志下载与失败分析机制,再到 changelog 片段、测试与许可证的硬性要求。
一、CLAUDE.md:一个三行的入口,一份完整的 Agent 规范
先看 CLAUDE.md 的全文内容,它只有三行:
- @AGENTS.md
- @~/.claude/ansible.md
- @CLAUDE.local.md
这是 Claude Code 的文件引用(@ 前缀)语法:Claude Code 启动时会把这些文件的内容自动注入上下文。三行分别指向仓库内的 AGENTS.md、用户本地的私有配置、以及仓库本地的本地化覆盖文件。也就是说,CLAUDE.md 本身只是一个装配入口,真正的规范主体是 AGENTS.md,而本地文件则允许开发者在不污染仓库的前提下注入个性化指令。
这种“入口 + 主体 + 本地覆盖”的分层设计,让仓库级规范与个人偏好解耦:仓库内提交的是可协作的 AGENTS.md,个人机器上的 CLAUDE.local.md 和 ~/.claude/ansible.md 保持私有。AGENTS.md 开头也明确了自身定位——该文件仅供 AI 助手使用,人类开发者的完整文档应参阅官方开发指南(仓库 context/README.md 进一步说明:context/ 目录同时面向人类与 Agent,但 Agent 专属指令只放在 AGENTS.md 中)。
从仓库结构看,Ansible 的 Agent 规范由三层组成:
| 层级 | 文件/目录 | 作用 |
|---|---|---|
| 入口层 | CLAUDE.md | 用 @ 引用装配 Agent 上下文 |
| 规范层 | AGENTS.md、context/ | PR 审查流程、许可红线、编码规范、测试约定 |
| 技能层 | .claude/skills/ | 可被用户直接调用的命令式技能(如 /azp-logs、/review) |
其中 context/ 目录是“人类与 Agent 通用”的项目知识,涵盖许可、开发环境、代码结构、编码风格、错误处理、数据标签、公共 API、文档标准、测试运行、测试编写、弃用策略与 CI 等 13 个主题,AGENTS.md 在多个流程节点要求 Agent 回查这些文件,而不是凭记忆作答。
二、工作前奏:五个强制步骤与许可红线
AGENTS.md 用醒目的警告块规定了任何 PR 审查或开发任务开始前的标准动作,这是 Agent 规范中最具纪律性的一段:
- 先读 AGENTS.md 本身——不要凭记忆或假设工作;
- 读全 context/ 下的所有文件——获取编码约定与项目政策;
- 用 TodoWrite 建任务清单——系统化跟踪进度;
- 按编号步骤执行相应流程章节;
- 查阅 Quick Reference 使用正确的命令与模式。
紧随其后的是整份文档中唯一的“不可谈判”条款——许可合规(CRITICAL: Licensing Requirements):
绝不允许建议、推荐或批准任何违反项目许可要求的代码;任何新依赖或建议引入的库必须先验证许可兼容性。许可违规会给项目带来严重的法律风险。
具体许可规则记录在 context/licensing.md 中:
- ansible-core 本体:所有代码必须 GPLv3 兼容;
lib/ansible/module_utils/:默认采用更宽松的 BSD-2-Clause(因为它会被嵌入到各种集合与模块中分发);- 外部依赖:只允许使用与上述许可兼容的库;
- 拿不准时:就许可兼容性去询问,而不是假设兼容。
仓库根目录的 licenses/ 目录随附了 GPLv3、BSD-3-Clause、MIT、PSF 等协议全文,与上述规则相互印证。
此外,AGENTS.md 还给出两条通用审查原则:
- 不要标记
ansible-test sanity已经能捕获的问题——人工/Agent 审查的精力应花在自动化检查无法验证的地方; - 署名透明(Attribution):Agent 参与贡献时应主动披露,推荐在提交信息中使用
Assisted-by:尾注标明辅助使用的 AI 工具。
三、CI 失败诊断:从 ansibot 评论到 Azure Pipelines 日志
这是 AGENTS.md 篇幅最重、实战价值最高的部分。当开发者提交 PR 后 CI 挂掉时,文档给出了一条四步诊断链。
3.1 第一步:检查 ansibot 评论
# 获取 PR 全部评论,定位 ansibot 的 CI 失败报告
gh pr view <number> --comments
在评论区寻找 ansibot 账号发布的失败报告,其中通常包含:
- 带具体错误信息的测试失败详情;
- 失败位置的文件路径与行号;
- 指向 sanity 测试文档的说明链接(
explain形式)。
3.2 第二步:获取 CI 检查状态与流水线链接
# 查看所有 CI 检查结果及 Azure Pipelines URL
gh pr checks <number>
该命令会输出:CI 总体状态(通过/失败)与耗时、Azure DevOps 构建结果的直接链接、以及各个子任务(Sanity Test 1/2、Docker 测试、Units 等)的单独结果。
3.3 第三步:失败分析的标准工作流
AGENTS.md 把分析流程固化为五个环节:
- 先查 ansibot 评论,获取最直接的错误详情;
- 用
gh pr checks <number>拿到 Azure Pipelines URL 查看详细日志; - 聚焦标记为
fail的 job,检查其具体错误输出; - 对 sanity 测试失败,错误信息通常直接指明了要修什么;
- 对功能测试失败,用
ansible-test在本地跑同样的测试来复现和调试。
第 5 步对应的本地命令约定记录在 context/running-tests.md 中,例如:
# 本地复现 sanity 失败(不需要 --docker)
ansible-test sanity -v --test pep8 --test pylint
# 针对具体文件跑 sanity
ansible-test sanity -v lib/ansible/modules/command.py
# 本地复现 unit 失败
ansible-test units -v --docker test/units/modules/test_command.py
# 本地复现 integration 失败(注意:集成测试要用发行版容器,如 ubuntu)
ansible-test integration -v --docker ubuntu ping
而 context/ci.md 则总结了 CI 失败的三类常见模式:sanity 失败通常有明确修法(行尾空白、import 错误等);集成测试失败可能需要平台专用容器或测试调整;单元测试失败往往指向真实的代码缺陷。
3.4 第四步:用 /azp-logs 下载完整流水线日志
当 ansibot 评论和网页 UI 的信息不足以定位问题时,使用仓库内置的 /azp-logs 技能:
# 用 PR 号下载日志(自动查找最新一次构建)
/azp-logs <pr_number>
# 或直接使用 gh pr checks 输出中的 build ID
/azp-logs <build_id>
# 或传入完整的 Azure Pipelines URL
/azp-logs https://dev.azure.com/ansible/ansible/_build/results?buildId=12345
这个技能的完整定义见 .claude/skills/azp-logs/SKILL.md。它声明了受控的工具白名单(gh pr view、gh pr checks、ls、Read、Grep),并规定了一个重要的交互纪律:下载前必须先征得用户确认,因为一次完整 CI 运行的日志下载可能要 5-10 分钟、体积 10-50MB。
日志下载完成后的标准分析手法:
# 在按 build ID 命名的目录里 grep 常见失败模式
grep -r "FAILED\|ERROR\|Traceback" <build_id>/
# 定位 sanity 测试失败
grep -r "The test" <build_id>/ | grep -i "failed"
# 查看下载了哪些日志
ls -lh <build_id>/
日志文件按 job 层级命名(如 "Job Name Stage Name.log")。由于 Ansible 项目在 Azure DevOps 上公开可见,整个下载过程不需要任何认证。
四、download.py 源码解析:技能背后的下载引擎
/azp-logs 技能并不自己实现下载,而是封装了 hacking/azp/download.py 脚本。阅读其源码可以弄清 AGENTS.md 中那些命令行参数的确切行为。
4.1 命令行参数全集
download.py 的 parse_args 函数 定义了脚本的完整接口:
| 参数 | 说明 |
|---|---|
RUN(位置参数) |
AZP 运行 ID 或构建 URL,二选一 |
-v, --verbose |
显示正在下载的内容 |
-t, --test |
演练模式:只显示将下载什么,不实际下载 |
-p, --pipeline-id |
流水线 ID,默认值为 20 |
--artifacts |
下载测试产物 |
--console-logs |
下载控制台日志(CI 失败分析的推荐项) |
--run-metadata |
下载运行元数据 JSON |
--all |
下载以上全部 |
--match-artifact-name <regex> |
只下载名称匹配该正则的产物,默认 .* |
--match-job-name <regex> |
只下载 job 名匹配该正则的产物,默认 .* |
参数校验逻辑值得注意:--all 会展开为三个开关全开(源码第 105-108 行);如果三个下载开关一个都没开,脚本直接以 At least one download option is required. 报错退出(第 116-117 行)。这也解释了 AGENTS.md 中“Advanced usage”示例为什么总带着 --console-logs 或 --all 之一:
# 只下载 job 名匹配 "Sanity.*" 的控制台日志
./hacking/azp/download.py <build_id> --console-logs --match-job-name "Sanity.*"
# 下载产物与元数据
./hacking/azp/download.py <build_id> --all
4.2 RUN 参数的双格式解析
run_id_arg 函数 用一个正则同时接受两种输入:纯数字 build ID,或完整的 Azure 构建 URL——URL 中的 buildId= 部分会被自动剥离并提取出数字 ID。这正是 /azp-logs 技能能够“直接接收 URL”的原因:
def run_id_arg(arg):
m = re.fullmatch(r"(?:https:\/\/dev\.azure\.com\/ansible\/ansible\/_build\/results\?buildId=)?(\d+)", arg)
if not m:
raise ValueError("run does not seems to be a URI or an ID")
return m.group(1)
4.3 时间线树与 job 过滤机制
download_run 函数 的实现分几步走:
- 输出目录固定为以 build ID 命名的目录(
output_dir = '%s' % args.run),这与技能文档“Logs will be saved to a directory named after the build ID”的说明完全对应; - 若启用
--run-metadata,调用pipelines/{pipeline_id}/runs/{run}REST API 拉取运行信息,写入<build_id>/run.json; - 无论哪种下载模式,都会请求
build/builds/{run}/timeline接口,把时间线记录解析成一棵父子树(roots/children_of/parent_of三个结构); - 遍历根节点下的每个 job,只有
"<parent job name> <child name>"拼接后匹配--match-job-name正则的 job 子树才会被加入allowed白名单; --console-logs模式下,遍历时间线记录,对每个在allowed集合内且有log.url的记录,把日志写入<build_id>/目录——文件名由从根到叶的完整 job 层级名拼接而成(源码第 201-215 行),路径分隔符被替换为_,最终形如Stage Name Job Name.log。
hacking/azp/ 目录下还有三个姊妹脚本,说明在 hacking/azp/README.md 中:get_recent_coverage_runs.py(查询最近覆盖率运行的 CI URL)、incidental.py(基于 CI 数据做“顺带覆盖”分析报告)、run.py(触发新的 CI 运行)。其中 download.py 的典型用法示例——下载一次覆盖率运行的产物与元数据——正与本文 3.4 节失败分析的流程同源。
五、PR 审查:七步清单与 review 技能
AGENTS.md 的“PR Review Guidelines”一节给出了适用于每一次 PR 审查的清单:
□ 为审查步骤创建 TodoWrite 清单
□ 第 1 步:gh pr view <number> 获取 PR 详情
□ 第 2 步:gh pr diff <number> 获取全部变更
□ 第 3 步:检查必备组件(changelog、测试)
□ 第 4 步:gh pr checkout <number> 检出 PR 分支
□ 第 5 步:gh pr view <number> --comments 查看既有反馈
□ 第 6 步:确认所有问题都已处理
□ 第 7 步:点名尚未解决的反馈
□ 每完成一步就把对应 TodoWrite 项标记为完成
七个步骤按序展开是:
- Get PR details:
gh pr view <number>理解 PR 范围与描述; - Get PR diff:
gh pr diff <number>查看全部改动; - 优先检查必备组件——changelog 片段是否存在、测试是否配套(分别对应 context/documentation-standards.md 的 changelog 要求与 context/writing-tests.md 的测试期望);
- Checkout PR 分支:
gh pr checkout <number>,让改动应用后从整体上审视代码,而不是盯着孤立的 diff; - Review existing feedback:
gh pr view <number> --comments查看全部评论与历史审查意见; - Verify all issues addressed:确认 bot 失败、审查者要求、讨论点都已解决;
- Call out unresolved feedback:对仍未处理的意见显式点名。
辅助工具清单同样明确:gh 系列命令之外,用 Read 工具细读具体变更文件,用 Grep(底层是 ripgrep)检索相关代码模式与测试覆盖。
这套清单在仓库中还有一个可直接调用的实现:.claude/skills/review/SKILL.md 定义了 /review <pr_number> 命令,其 front-matter 声明了工具白名单(TodoWrite、gh pr view/diff/checkout/checks、Read、Grep、Glob、Search),把 AGENTS.md 的七步流程代码化。该技能还补充了两条清单之外的硬标准:
- 测试范围:测试必须真实覆盖被改动的代码路径,而不是随机增加覆盖行;单元测试应为 pytest 风格、功能性优先、不与 mock 深度耦合;几乎所有插件改动都需要集成测试;
- Changelog 校验:片段结构必须符合
changelogs/config.yaml定义的章节; - 审查节奏:单轮审查的反馈项不应超过 20 条。
5.1 Changelog 片段的章节约束
AGENTS.md 要求“每个 PR 都要有 changelog fragment”,而片段能用哪些章节由 changelogs/config.yaml 严格定义:
sections:
- ['major_changes', 'Major Changes']
- ['minor_changes', 'Minor Changes']
- ['breaking_changes', 'Breaking Changes / Porting Guide']
- ['deprecated_features', 'Deprecated Features']
- ['removed_features', 'Removed Features (previously deprecated)']
- ['security_fixes', 'Security Fixes']
- ['bugfixes', 'Bugfixes']
- ['known_issues', 'Known Issues']
此外该配置还声明 notesdir: fragments(片段放在 changelogs/fragments/)、changes_file: changelog.yaml、release_tag_re: '(v(?:[\d.ab\-]|rc)+)' 等。仓库当前累积的片段文件(如 changelogs/fragments/86656-fix-step-in-free-strat.yml 一类,以 issue 编号命名)就是这条流程的实物样本——每个待发布变更都以一个独立 YAML 片段记录在案,发布时由 ansible-test 生态中的 changelog 工具汇总进 changelog.yaml。
六、把整套规范串起来:一次典型的 Agent 审查会话
综合 CLAUDE.md → AGENTS.md → context/ → skills 四层信息,一次标准的 Agent 介入流程是:
- Claude Code 启动,CLAUDE.md 通过
@引用把 AGENTS.md 注入上下文; - Agent 按“Always Start Here”要求通读 context/ 全部 13 个主题文件;
- 用 TodoWrite 建立审查清单,依次执行
gh pr view→gh pr diff→ 核对 changelogs/fragments/ 中的片段与 changelogs/config.yaml 章节、核对测试覆盖 →gh pr checkout→ 复查评论; - 若 CI 失败:
gh pr view --comments找 ansibot 报告 →gh pr checks拿流水线链接 → 需要深挖时经用户确认后/azp-logs <build_id>,由 hacking/azp/download.py 把控制台日志落盘到<build_id>/目录 → grepFAILED/ERROR/Traceback定位 → 按 context/running-tests.md 的命令在本地用ansible-test复现; - 全程任何新增依赖先过 context/licensing.md 的 GPLv3/BSD-2-Clause 兼容性校验;提交信息带
Assisted-by:尾注。
这套设计的工程价值在于:把原本依赖资深维护者经验的“看哪里、查什么、用什么命令”全部沉淀为仓库内可版本化的文本,AI Agent 与新人开发者读的是同一套规范,而 .claude/skills/ 中的技能文件又把这些流程收敛为一键命令——规范文档、执行技能与底层脚本(hacking/azp/)三者一一对应、互为印证。
七、适用边界与说明
- 本文所有命令与流程均基于当前仓库内容(AGENTS.md、.claude/skills/、hacking/azp/download.py、context/),适用于 Ansible 上游开发流程,与最终用户编写 playbook 的使用场景无关;
- CI 基础设施为 Azure Pipelines,
-p/--pipeline-id默认值 20 与 API 域名(dev.azure.com/ansible/ansible)均硬编码在 download.py 中,指向 Ansible 上游公开流水线; - CLAUDE.md 引用的
~/.claude/ansible.md与CLAUDE.local.md属于本地文件,不在仓库内,本文不对其内容作推断; - 文中未涉及仓库未公开说明的内部实现细节;对行为差异(如日志命名规则)均以 download.py 源码 为准。
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 StartedRust0622
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