Chainlink Flaky Test 修复技能:JIRA 工单语义状态转移协议(transition-ticket)深度解析
【免费下载链接】chainlinknode of the decentralized oracle network, bridging on and off-chain computation项目地址: https://gitcode.com/GitHub_Trending/ch/chainlink
Chainlink 仓库的tools/test模块内置了一个面向 AI Agent 的 flaky test 修复技能(fix-flaky-tests),其中 transition-ticket.md 定义了工单状态流转的核心操作:接收一个语义化目标状态(如In Review、Open),解析为 JIRA 工作流中实际存在的 transition 名称后应用。本文完整继承该协议的操作步骤、别名映射表与指派人策略,并结合仓库中的技能主文件、JIRA 操作索引与子代理契约,讲清它为什么是"语义到实际"的翻译层、FIXED 工单为什么绝不能取消指派,以及它与 claim / abandon 等操作如何拼成完整闭环。
1. 背景:fix-flaky-tests 技能与 JIRA 工单生命周期
tools/test 是基于 testrig 的 Go 测试 harness,提供make test ARGS="diagnose ..."用于复现 flake、race、timeout。SKILL.md 是 Agent 执行 flaky test 诊断-修复循环的技能入口,当用户指定了 JIRA 工单(或 N 个符合条件的 flaky-test 工单)作为目标时,整个工作流就变成:
领取工单(Open → In Progress)→ 诊断修复(diagnose 循环)→ 按结果流转工单(FIXED → In Review / ABANDONED、MISMATCH → Open)→ 写调查更新评论。
其中"流转工单"这一步由 jira.md 统一调度,而具体的状态转移动作委托给本文主角 transition-ticket.md。它被定位为一个可包含引用(includable reference):自声明输入、步骤与输出,供 claim-ticket、abandon-ticket 等操作文件复用。
设计动机在于一个工程现实:不同团队的 JIRA 工作流命名习惯差异极大——有的团队用 "In Development",有的用 "Active",有的把收尾状态叫 "Closed",有的叫 "Resolve"。如果协议硬编码某个 transition 名称,换一个项目就会直接失败。因此 transition-ticket 采用"语义目标 + 别名表"的翻译层设计。
2. transition-ticket 核心操作步骤(完整继承)
原文档定义的操作输入是jira_key(工单键)、target(语义目标状态),可选accountId(当前用户的 Atlassian 账号 ID)与original_assignee(slim record 中记录的原始指派人)。步骤如下:
步骤 1:查询可用 transition调用mcp__atlassian__getTransitionsForJiraIssue,传入jira_key,拿到该工单在当前状态下所有可执行的 transition 列表。
步骤 2:别名匹配将target与返回的可用 transition 做匹配,使用第 3 节的别名表,并取响应中出现的第一个匹配别名(Pick the first alias that appears in the response)。
步骤 3:执行转移调用mcp__atlassian__transitionJiraIssue,传入匹配到的 transition ID。
- 对关闭类目标(
"Won't Do"、"Done"):如果该 transition 支持resolution字段,则设置resolution = "Won't Do"(回退值"Won't Fix")或对应的完成类解决码。
步骤 4:FIXED 交接特例(target = "In Review" 且提供了 accountId)这是"修复者拥有评审"的交接语义:
- 调用
mcp__atlassian__editJiraIssue,设置assignee.accountId = accountId(即修复该 flake 的 investigator); - 不要取消指派。指派人必须保持为当前用户,使工单在 PR 合并前一直挂在对方的看板上;
- 对
target = "In Review"而言,original_assignee仅作信息性字段,不恢复、不清空原始指派人。
失败路径同样被显式约束:claim-ticket 流程规定,若转移失败必须回滚取消指派并把失败原因写入 slim record 的skip_reason(见 claim-ticket.md 步骤 3),保证工单不会停留在半认领状态。
3. 语义目标状态与别名映射表
原文档给出的别名表是协议的核心数据,必须按"按序尝试、首个匹配生效"的语义使用:
| 语义目标 | 按序尝试的名称 |
|---|---|
In Progress | "In Progress", "In Development", "Active", "Start Progress" |
In Review | "In Review", "In Code Review", "Code Review", "Review" |
Open | "Open", "Reopen", "Backlog", "To Do", "Reopened" |
Won't Do | "Won't Do", "Won't Fix", "Reject" |
Done | "Done", "Closed", "Resolved", "Close", "Resolve" |
两条关键规则:
- 顺序即优先级:表中名称按尝试顺序排列,匹配到响应中第一个出现的别名即停止;
- 宁错不猜:若没有任何别名命中可用 transition,协议要求返回错误而非静默挑选一个无关状态(return an error rather than silently picking an unrelated state)。这是对 Agent 幻觉行为的直接防御——错误比把工单流转到错误状态的成本低得多。
从别名表覆盖的名称变体("Reopened"、"Start Progress" 这类非常规命名)可以推断,该协议是针对多个真实团队 JIRA 工作流归纳出的兼容层,而非单一环境的约定。
4. 指派人策略:工单所有权协议
transition-ticket 内置了一张指派策略表(assignee policy),把"状态转移"和"所有权变更"绑定成原子约定:
| 结果 / 目标状态 | 转移后的指派人 |
|---|---|
| FIXED → In Review | accountId(investigator,即修复者) |
| ABANDONED → Open | 取消指派(null)——见 abandon-ticket.md |
| MISMATCH → Open | 若设置了original_assignee则恢复之;否则取消指派 |
其中 FIXED 路径的规则值得展开。jira.md 的assignee_rules记录了这条规则背后的教训:修复完成后取消指派曾是一个实际发生过的错误行为——当original_assignee == accountId(即工单本来就是当前用户领的)时取消指派,会导致"领取即修复"场景下工单在 In Review 阶段失去 owner。因此协议硬性规定:FIXED 工单移入 In Review 时,investigator 必须始终是 assignee,直到 PR 合并。SKILL.md 的 JIRA 参考部分也重复强调:"After a FIXED outcome, the ticket must stay assigned to the investigator ... Do not unassign on FIXED"。
ABANDONED 路径则由 abandon-ticket.md 展开为三步固定序列:①editJiraIssue取消指派(assignee 置 null)→ ② 按 transition-ticket 以target = "Open"流转 → ③ 按 investigation-comment.md 模板写一条 Outcome 为 ABANDONED 的调查更新评论(What was investigated 填停止原因,其余段落填 N/A)。其硬约束是"绝不允许已领取的工单停留在 In Progress"(Never leave a claimed ticket in "In Progress"),覆盖用户取消、用户跳过、未找到可行修复、所有权冲突、会话提前结束等所有中途停止场景。
original_assignee字段来源于 slim record(见 slim-record.md),在 claim 阶段由getJiraIssue读取fields.assignee.accountId保存(无指派人为 null)。MISMATCH 路径恢复它,是为了把"误领/跨仓库"的工单交还给原主;而 FIXED 路径刻意忽略它,因为此时所有权已经合法地转移到了 investigator 手中。
5. 在完整调度逻辑中的位置
jira.md 的<logic>段定义了工单操作的总调度:
- 用户给出具体 JIRA 工单 → 执行 claim-ticket(指派给自己并转移至 In Progress,其中就调用 transition-ticket 以
target = "In Progress"流转); - 用户要求处理 N 个符合条件工单 → 执行 fetch-flaky-tickets 的 JQL 搜索循环(
labels = "flaky-test" AND status = "Open"); - 否则按测试名反查相关工单;
- 工作结束后,无论结果如何,对每个工单:a. 写调查更新评论;b. 按结果转移工单——abandoned →
Open(经 abandon-ticket 取消指派)、mismatch →Open(恢复 original_assignee)、fixed →In Review(transition-ticket 步骤 4 指派给 accountId,绝不取消指派)。所有调用都必须透传atlassianUserInfo的accountId;abandon / mismatch 时透传 slim record 中的original_assignee。
所有数据交换遵循"slim record 单传"原则:<absolute_constraints>规定永不返回原始 JIRA API 对象,调用方只能拿到 slim-record.md 定义的精简 JSON(含jira_key、test_name(customfield_13007)、package(customfield_13009)、previous_attempts、original_assignee、skip_reason),以避免反复调用 Atlassian MCP 重复读取同一工单。
执行层面,SKILL.md 的子代理协议要求:与 JIRA 交互时派生JiraManager子代理,并按 jira-mananger-subagent.md 初始化——该子代理的系统提示中固化了同样的所有权规则("FIXED → In Review: always set assignee to accountId; never unassign"),其输入契约为{operation, accountId, cloudId}加操作特定字段(jira_key、target、original_assignee等),缺失必填字段时快速失败返回success: false;允许的工具白名单仅含getTransitionsForJiraIssue、transitionJiraIssue、editJiraIssue、addCommentToJiraIssue等只读/工单类 MCP 工具,Temperature 固定为 0.0。这解释了 transition-ticket 步骤中那些"看似啰嗦"的前置参数(cloudId、accountId)从何而来:它们是所有 JIRA 操作的公共前置条件,在 jira.md 的operation_requirements中集中声明。
6. 适用前提与实操约束
- MCP 依赖:整套协议依赖 Atlassian MCP 可用且已认证,否则 jira.md 要求立即停止并提示用户安装/认证,不得继续;
- 参数来源固定:
cloudId来自getAccessibleAtlassianResources,accountId来自atlassianUserInfo,均不可手工伪造; - 与诊断循环的衔接:SKILL.md 规定修复后至少要以 Standard profile(
--iterations 30,见其<diagnose-iterations>表)重跑make test ARGS="diagnose ..."验证通过才允许进入 FIXED → In Review 流转,即 transition-ticket 的 FIXED 入口是有"验证门槛"的; - 仓库范围:技能约束只在
core/、deployment/包内免确认跑测试,claim 阶段还会做仓库归属校验(customfield_13009中的{owner}/{repo}与git remote get-url origin比对),不匹配则不领取并写入skip_reason——这与 transition-ticket 的 MISMATCH → Open + 恢复原指派人的路径形成首尾呼应。
7. 小结
transition-ticket 是一个体量很小但设计密度很高的协议文件:它用一张别名表解决了跨团队 JIRA 工作流命名不一致问题,用"首个匹配 + 未匹配即报错"消除了 Agent 的状态猜测,用指派策略表把工单所有权随状态转移原子化,并针对 FIXED 交接明确了"不取消指派"的教训式约束。它与 claim-ticket、abandon-ticket、investigation-comment 一起,构成 Chainlink flaky test 修复技能中完整的工单生命周期管理闭环;其全部设计(slim record 单传、子代理白名单、temperature 0.0、fail-fast 契约)都服务于同一个目标:让 AI Agent 对共享 JIRA 空间的操作可预测、可审计、可回滚。
【免费下载链接】chainlinknode of the decentralized oracle network, bridging on and off-chain computation项目地址: https://gitcode.com/GitHub_Trending/ch/chainlink
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考