跳至内容

输出通道

AICR 把 agent 的职责(代码推理)与自身的职责(报告格式、校验、路由和渲染)分离。 所有正式评审结果都通过 AICR 工具产出,绝不通过 agent 的自由文本 stdout。同一个 problem 可以干净地渲染为 VCS 行内评论、issue 条目或 IM 摘要卡片。

自动提交批次保存分析产物和逐渠道回执。恢复跳过分析与已确认发送,每次远端报告写入都在 发送前持久化稳定操作 ID。GitHub/Gitea 的 issue、review 发布器及 GitLab MR 发布器查询 正文中的隐藏标记,确认响应丢失的写入;managed issue 状态更新和删除查询原资源。

飞书应用在首次尝试后最多 59 分钟内复用稳定 UUID。飞书/企业微信 webhook 无法查询不确定 发送,不会自动重发。标记缺失或歧义、查询被拒、UUID 过期均保留未知状态。查询最多 20 页、 每页 100 项,截止时间 30 秒。远端发布与本地持久化不在同一事务,不保证 exactly-once。

沿用既有重试预算和一次终态失败恢复。管理端批次 API 的 publications、 publicationOperations 提供写入和对账次数。人工 Retry 保留远端日志,修改配置不能清空 不确定发送。日志导致检查点超过 1 MiB 时停止发布并保留最后持久状态。重启恢复需使用 SQLite 或 Redis。旧检查点无法还原从未保存的操作 ID;升级前应停止旧写入进程。

进程内工具注册表向评审执行器暴露以下 AICR 工具:

工具 用途 必填字段
aicr.report_problem 报告一个锚定到变更行的可操作 problem file、line、severity、category、message
aicr.publish_summary 发布结构化 Markdown 评审摘要 markdown
aicr.skip 标记评审被有意跳过 reason
aicr.fetch_more_context 请求变更文件或窄范围相关文件的源码上下文 path、reason
aicr.try_blame 请求 VCS 校验的、尽力而为的行归属(不含文件内容) path、reason

aicr.fetch_more_context 和 aicr.try_blame 是只读上下文工具。编排器会通过配置的 VCS 适配器回放它们,并用获取到的内容/归属跑一次最终 follow-up。

自由文本 stdout 不是报告

Agent 适配器运行绝不能把自然语言 stdout 当作 IM 摘要发布。如果 agent 无法产出 结构化输出,AICR 触发结构化修复 pass;若仍失败,回退到直接 LLM 调用。说明“没有可操作 问题”或“没有可评审代码”的散文会被归一化为 aicr.skip,而不是作为兜底消息发布。

IM 报告保留完整问题正文、建议和代码引用,仅在发送消息超过平台字节上限时裁剪并注明, 原生提醒和报告链接保留。详见 IM 消息限制。

aicr.report_problem 接受最小化、通道无关的形状:

字段 必填 含义
file 是 受影响文件的仓库相对路径
line 是 主锚点的新文件行号(必须是变更行或可评论的 diff 行)
end_line 否 范围 problem 的结束行(渲染为 file:start-end)
severity 是 info、low、medium、high 或 critical
category 是 简短 problem 家族,如 correctness、security、api-contract
message 是 问题分析:哪里错、触发场景、影响
suggestion 否 最小可行的修复方向;可包含 fenced diff 补丁
fingerprint 否 稳定的去重 key(在支持的通道中以隐藏评论保留)

aicr.report_problem 不接受 agent 提供的归属信息。需要作者或修订上下文时,agent 调用 aicr.try_blame;AICR 校验请求并把归属回填到 follow-up pass。

Channel 的 kind 是由输出实现注册表约束的自由字符串(Zod 校验形状;dispatcher 解析 kind)。

Kind Problem 输出 Summary 输出 说明
gitea_pr_review 一条合并的 PR review/评论正文 PR review / 配置的 summary 发布器 problem 先缓冲,再作为一条 Markdown 正文 flush;403/422 时退化为一条 issue 评论
github_pr_review 一条合并的 PR review/评论正文 PR review / 配置的 summary 发布器 与 gitea_pr_review 相同的缓冲+flush;403/422 时退化为 issue 评论
gitlab_mr_review 当 baseSha/headSha 可用时发 MR discussion MR note / 配置的 summary 发布器 行锚点不可用时退化为通用 MR note
gitea_problem_issue / github_problem_issue / gitlab_problem_issue 收集后对账 创建 / 更新 / 解决托管 problem issue 这里 fingerprint 稳定性最重要;github_problem_issue 用字符串标签名,resolved_action 支持 none、close 和 mark_resolved(GitHub 无 issue 删除 API);GitLab 上 assignee 必须是项目成员,CE 实际只支持单个 assignee
gitea_issue / github_issue 收集后渲染为 issue 评论 聚合 issue 评论 适用于 push 事件或基于 issue 的分诊
feishu_bot 收集后聚合 交互卡片(JSON 2.0 schema) 见 IM 机器人
feishu_app 收集后聚合 通过应用消息 API 发送共享飞书卡片 可选来源群目录匹配作者并 @;见 IM 机器人
wecom_bot 收集后聚合 Markdown 消息 见 IM 机器人

gitea_problem_issue、github_problem_issue 和 gitlab_problem_issue 跨评审对账过期的托管 issue。关键行为:

  • Fingerprint 稳定性。 每个 problem 带一个 fingerprint。AICR 在每个托管 issue 内的 隐藏 aicr:problems 标记里跟踪打开的 fingerprint。当之前打开的 fingerprint 消失,该 issue 被移到 Resolved 段(可选关闭)。
  • 文件范围解决守卫。 只有当生命周期模型对照当前源码确认修复后,problem 才会被标记为“已解决”。 这通常要求当前评审确实重新分析了包含该 problem 的文件;但一次真正的空评审(例如 lgtm 运行)在生命周期分析启用时,会改为验证该 issue 所有仍打开的 fingerprint。未经模型确认时, 由触及无关文件的提交触发的评审——或什么都没发现的评审——不会 把之前报告的每个 problem 都标记为已解决。每个托管 issue 正文嵌入 aicr:file=<path>,以便恢复文件归属。
  • 最近 issue 上限。 对账只列出仍处于 open 状态的 issue(state=open),上限由 review.problem_issue.max_recent_issues 控制(默认 30,范围 1–200,可按 workspace 覆盖)。 最近窗口之外的 fingerprint 不会在该 run 去重或关闭。
  • GitHub resolved_action。 支持 none、close 和 mark_resolved(GitHub 无 issue 删除 API)。Gitea 和 GitLab 额外支持 delete(GitLab 上 token 用户必须是项目 owner 或 admin)。
  • GitLab assignee。 非项目成员的 assignee 会被静默丢弃,且 CE 忽略复数 assignee_ids 字段,因此 AICR 通过 assignee_id 发送单个 assignee。新增成员要等 GitLab 异步成员授权 传播完成后才可被指派。

issue_mode、resolved_action、assign_committer、owners_file 和严重性标签字段见 输出通道配置。

未指定 trigger 的 channel 使用接收事件的兼容 profile;channel 显式指定的 trigger 优先。GitHub App installation token 按输出 channel 的 trigger 和目标仓库获取。

GitLab MR channel 保留包含子群组的完整项目路径,并使用项目内的 MR iid。 Note Hook 从顶层 merge_request 读取该标识,不能用 note ID 或全局 MR ID 替代。 参见 GitLab discussion API。

某次评审的 line_comments 和 summary 发往哪些 channel 按事件解析,适用哪套路由世代 取决于配置:

  • v2 routing.rules[](配置携带路由规则时):规则按 triggers、target_kinds 和 source.repo_ref 匹配,带显式 priority。channel 选择按事件依次解析为:命中规则的 outputs、workspaces.instances.<id>.outputs、workspaces.defaults.outputs、 outputs.routes.default。显式 [] 关闭该输出类型;只有未设置的字段才继承。同一 trigger 不得由两套路由世代同时控制。
  • 遗留 outputs.routes(未配置路由规则时):一个 default 块加上按 trigger 和 target_kind 匹配的可选 rules。数组顺序中第一个匹配且列表非空的规则生效;空列表回落到 workspace 实例,再到 default;仅 line_comments 最后回落到第一个 *_pr_review channel。
outputs:
routes:
default:
line_comments: [gitea-pr-review]
summary: [gitea-pr-review]
rules:
- match: { trigger: p4-main, target_kind: commit }
summary: [feishu-code-review]

no_problems.action 决定一次成功但无可操作问题的评审是否通知各 channel (publish、suppress 或 publish_if_summary)。channel 可以按 channel 或按 workspace 覆盖全局策略。如果所有选中的 summary channel 都抑制零问题结果,run 会被 记为跳过,skipReason="no_problems_suppressed"。该策略只控制可见的通知: 托管 problem issue channel 仍会在每次真正的零问题评审后对账已有指纹, 让经模型确认已修复的 issue 得以关闭(resolved_action: none 可关闭该行为)。

  • 完整的按 channel 选项和 IM Markdown 转换:见输出通道配置。
  • 完整 MCP 工具输入 schema 和 .aicr-output-state.json 流转:见 MCP 工具。
  • summary/problem 渲染的模板变量:见模板变量。
  • 配置飞书或企业微信群机器人:见 IM 机器人。