| name | audit-engine |
| description | 多轮收敛审计编排引擎。在十步循环关键检查点编排 agent-team-audit 执行多轮审计,
通过结论集合比较和投票机制判定收敛,支持 convergence 和 challenge 两种模式。
触发场景 (由 Phase Skills 调用,非用户直接调用):
- phase-a-planner 完成 Spec 后 (post_spec)
- brainstorm 完成后 (post_brainstorm)
- task-planner 完成后 (post_planning)
- phase-b-developer 任务进度达阈值 (mid_implementation)
- phase-b-developer 实现完成后 (post_implementation)
- phase-c-integrator 合并前 (pre_merge)
- phase-d-closer 收尾后 (post_closure, 限 convergence + max_rounds=1)
|
| experimental | true |
| user-invocable | false |
| allowed-tools | Read, Glob, Grep, Bash, Skill |
审计引擎 (Audit Engine)
版本: 1.0.0 | 状态: 实验性 (Experimental)
创建: 2026-03-27
依赖: agent-team-audit (单轮执行引擎)
架构关系
audit-engine (多轮编排层)
|
| 调用 (每轮)
v
agent-team-audit (单轮执行引擎)
|
| spawn
v
各 Agent (按检查点配置的 team)
组合而非替代: audit-engine 负责多轮编排和收敛判定,agent-team-audit 保持为
单轮执行引擎。并发控制、超时策略、去重算法全部复用 agent-team-audit 现有实现。
输入参数
| 参数 | 类型 | 必填 | 说明 |
|---|
checkpoint | string | 是 | 检查点名称 (见下方检查点列表) |
mode | string | 否 | convergence / challenge / adaptive,默认从配置读取 |
context | string | 是 | 被审计内容路径 (proposal.md / diff / UPM) |
agents_config | object | 否 | Agent 分组覆盖,默认从 config.json teams 读取 |
检查点列表
| 检查点 | 阶段 | 侧重 | 调用方 |
|---|
| post_brainstorm | A | 决策验证 | brainstorm |
| post_spec | A.1 | 决策验证 | phase-a-planner |
| post_planning | A.2 | 质量保障 | task-planner |
| mid_implementation | B.2 | 质量保障 | phase-b-developer (条件触发) |
| mid_post_spec | B.2 | spec 漂移校验 | phase-b-developer (条件触发, Aria #79) |
| post_implementation | B.2 | 质量保障 | phase-b-developer |
| pre_merge | C.2 | 共识构建 | phase-c-integrator |
| post_closure | D.1 | 经验积累 | phase-d-closer |
post_closure 限制: 代码已合并,限 convergence 模式 + max_rounds=1,侧重经验提取。
mid_post_spec 限制 (Aria #79): Phase B 实施期 SMOKE/集成测试暴露 spec 陈述与运行实际不符时条件触发的快速校验, 非全量审计。恒 max_rounds=1 (镜像 post_closure), scope 限漂移涉及的 spec 陈述; mode 仍走 adaptive_rules (L1 off / L2 convergence / L3 challenge) 但单轮即出 verdict。输出 = append-only spec amendment 建议 (blocking=false, advisory), 采纳后 resume Phase B。详见 agent-team-audit/references/audit-points.md ## mid_post_spec。
执行流程
4 阶段: (1) 入口逻辑 (config + mode + agents 加载) → (2) Pre-merge gate — pre_merge checkpoint 专属横向完整性检查 (Issue #26, 与 #27 互补) → (3) Convergence 模式 (全员讨论 → 汇总 → 四元组比较 → 收敛/振荡) → (4) Challenge 模式 (讨论组+挑战组对抗 → objections resolved 判定)。
完整流程定义 (4 阶段 详细 step / pre_merge gate 5-step 流程 + 错误输出 / convergence 4-step / challenge 4-step + Round 计数): 见 references/execution-modes.md。
Schema 细节: convergence 见 references/convergence-algorithm.md, challenge 见 references/challenge-mode-schema.md。
Step 0: Anchor 固化 (Drift Guard #17, v1.44.0)
入口逻辑完成后、Round 1 启动前一次性执行: 固化本次审计的原始目的 anchor。
{
"anchor": {
"checkpoint": "post_spec",
"primary_goal": "<从 context 提取的原始目的>",
"in_scope": [],
"out_of_scope_hints": [],
"source_sha": "<freeze 时 git SHA>"
}
}
- anchor 写入报告 body 的
drift_metrics 章节 (anchor 快照, 见 references/report-format.md; frontmatter 仅含三个 boolean 标记字段, 保持扁平防 #125/#126 parser), 审计周期内不可变 — mid-audit re-anchor 不支持 (换锚 = 另起一次审计, cross-ref DEC-20260611-001 §9 Out-of-Scope)。
- 每轮收敛判定前由独立 drift-checker 持 anchor 对当轮结论分类, 详见 references/challenge-mode-schema.md drift-checker 节。
per-checkpoint anchor 来源 fallback 链 (带 checkpoint 归属标签, 非单线性):
- [proposal 类: post_spec / post_planning / mid_post_spec] proposal.md 的 Why/Goal 段 (mid_post_spec #79 校验 spec 漂移, 锚定 spec 本身)
- [diff/UPM 类: mid_implementation / post_implementation / pre_merge] 经
change_id 解析 proposal.md (复用 pre-write-validation 既有锚点链, 见 references/pre-write-validation.md)
- [post_brainstorm] brainstorm_decisions (调用契约见下)
- 降级: issue/PR 标题 (此时
source_sha = 当前 HEAD SHA + anchor_source=degraded)
- 全缺 → fail-soft: 跳过 drift 计算 + 报告标注
drift_anchor_missing, 不阻塞审计
post_brainstorm 调用契约 (三点, DEC-20260611-001 §4.1):
- (a) caller (brainstorm skill) 侧
context 传入决策记录文件路径 (如 .aria/brainstorm-{id}.md 或 docs/decisions/DEC-*.md);
- (b) 提取器识别"已确认决策"段 →
in_scope / "DEFERRED" 条目 → out_of_scope_hints / 核心议题 → primary_goal;
- (c)
context 为 Forgejo issue URL 时降级 issue_title。
- (可选 upgrade) 决策记录文件内含 issue 链接时可升级抓 issue 标题作
primary_goal 补充。
NOTE (#17 vs #79 边界): 本机制 (#17) 仅覆盖审计讨论轮内 drift (anchor 固化在单次审计周期内); 实施期偏离 Spec 的检测属 #79 (mid-implementation spec drift), 两者机制独立。#79 已落地为 mid_post_spec 条件触发检查点 (见检查点列表 + agent-team-audit/references/audit-points.md ## mid_post_spec); #17 drift-checker 与 #79 spec-drift 各管各 (前者审计轮内结论漂移, 后者运行实际 vs spec 陈述)。
数据 Schema
结论记录
每条结论提取为结构化记录:
{
"id": "<sha256(category + ':' + scope + ':' + severity + ':' + type)[:8]>",
"type": "decision | issue | risk",
"severity": "critical | major | minor",
"category": "architecture | implementation | testing | documentation",
"scope": "affected module or file",
"summary": "truncated to 50 words"
}
id 字段哈希规范 (mechanical determinism, v1.17.5+):
import hashlib
def finding_id(category: str, scope: str, severity: str, type: str) -> str:
canonical = f"{category}:{scope}:{severity}:{type}"
return hashlib.sha256(canonical.encode("utf-8")).hexdigest()[:8]
输入字段 (与 4-tuple comparison_key 对齐, 顺序固定):
category (architecture | implementation | testing | documentation)
scope (affected module or file path)
severity (critical | major | minor)
type (decision | issue | risk)
输入字段不包括: summary (LLM 措辞每轮不同, 哈希污染), timestamp (轮次间漂移),
agent_role (跨 agent 同 finding 应同 ID).
输出: 8 字符 hex prefix (e.g. a3f2c9b1), 足够 4-tuple 笛卡尔积去重 (~10^4 量级远低于 16^8 = ~4.3×10^9).
为何 SHA-256: 跨语言/跨 agent 可复现 (Python stdlib + JS crypto + LLM 心算近似都能产生一致结果);
truncate to 8 chars 兼顾可读性 (报告文件名 + inline fix 引用 R1-a3f2c9b1).
跨轮稳定性保证:
- 同一 finding 在 R1 / R2 / RN 由不同 agent 报告 → 同 8-char ID
- finding 升级 severity (minor → major) → ID 改变 (符合 4-tuple
comparison_key 不收敛逻辑)
- finding 改 category/scope → ID 改变 (设计如此, 表示语义变化)
详见 references/convergence-algorithm.md "comparison_key 与 finding.id 关系" 章节。
四元组 (比较键)
comparison_key = {type, severity, category, scope}
summary 不参与比较,消除 AI 措辞差异的噪声。
轮次状态记录
round_state:
round: integer
conclusions: [conclusion_record]
comparison_keys: set of tuples
vote: PASS | REVISE
incomplete: boolean
timestamp: ISO 8601
汇总引擎
audit-engine 的内部组件,非独立 Skill。
输入: 同一轮所有 Agent 的原始 issues 列表
处理步骤:
1. 合并: 收集所有 Agent 输出到统一列表
2. 去重: 基于 {category, scope} 匹配 (复用 agent-team-audit 去重算法)
- 相同 → 合并 found_by, 取最高 severity
3. 冲突标记: 同 scope 矛盾意见 → 保留双方, 标记 conflicted: true
- 不自动裁决, 留给下一轮或人工决策
4. 结构化提取: 自由文本 → conclusion_record 格式
- type: 从 issue 内容推断 (decision/issue/risk)
- severity: 继承 agent-team-audit 的 Critical/Major/Minor
- category: 归类到 architecture/implementation/testing/documentation
- scope: 提取 affected module or file
- summary: 截取前 50 词
输出: [conclusion_record]
收敛判定算法
四元组集合比较
current_keys = { (r.type, r.severity, r.category, r.scope) for r in round_N }
previous_keys = { (r.type, r.severity, r.category, r.scope) for r in round_N_minus_1 }
conclusions_stable = (current_keys == previous_keys)
全票 PASS 检查
convergence 模式: convergence_agents 全员 vote == PASS
challenge 模式: objections 全部 status == resolved (无 unresolved)
振荡检测
# #17 振荡豁免: keys 全部取 normal_rounds 重索引序列 (is_refocus 轮剔除),
# 本节为简化概述 — 权威可执行版见 references/convergence-algorithm.md 终局 3
if len(normal_rounds) >= 3:
keys_N = comparison_keys(normal_rounds[-1])
keys_N_1 = comparison_keys(normal_rounds[-2])
keys_N_2 = comparison_keys(normal_rounds[-3])
if keys_N == keys_N_2 and keys_N != keys_N_1:
→ 标记 oscillation: true
→ 取最后轮结论为最终结果
→ 不要求人工介入
收敛条件汇总
converged = conclusions_stable AND unanimous_pass
oscillation = (Round N == Round N-2) AND (Round N != Round N-1)
if converged → 输出最终报告
if oscillation → 取最后轮, 报告标记 oscillation: true
if max_rounds exhausted → 降级策略
else → continue to Round N+1
详细算法说明见 references/convergence-algorithm.md。
降级策略
当 max_rounds 耗尽且未收敛:
1. 展示摘要:
- 最后轮结论列表
- 各轮差异对比 (新增/移除的四元组)
- 未收敛原因分析 (哪些结论在变动)
2. 三路径选择 (AskUserQuestion):
[1] 接受当前结论
→ converged: false, overridden_by_user: true
→ 继续后续流程
[2] 增加轮次
→ max_rounds += 2
→ 继续审计循环
[3] 降级为单轮
→ 取最后轮结论作为最终结果
→ converged: false, degraded: true
错误处理
| 场景 | 行为 |
|---|
| Agent spawn 失败 | 跳过该 Agent, 当轮 incomplete: true, 不阻塞收敛 |
| Agent 超时 (继承 120s) | 同 spawn 失败处理 |
| API 限流 (529) | 等待 30s 重试一次, 仍失败则跳过 |
| 部分收敛 (结论无变化但有 REVISE) | 继续下一轮 |
| 全部 Agent 失败 | 当轮作废, 输出错误报告, 不计入 max_rounds |
| drift-checker spawn 失败/超时 (#17) | drift_ratio=null fail-open 按 < warn 档处理 + drift_check_skipped: true, consecutive_refocus_count 不增加 |
正交声明 (drift-checker vs round_state.incomplete): drift-checker 失败 (drift_check_skipped: true) 与审计 Agent 失败 (round_state.incomplete: true) 正交 — 二者独立标注、互不推导, drift-checker 失败不置 incomplete, Agent 失败不置 drift_check_skipped。整轮超时耗尽场景的归因规则: 审计 Agent 超时记入 incomplete: true (300s/轮 wall-clock 预算内); drift-checker 有独立 30-60s 超时配额 (不占 300s/轮, 见 §并发控制), 仅其自身失败/超时记 drift_check_skipped: true — 不得因整轮 wall-clock 耗尽把 Agent 失败误归因为 drift-checker 失败 (或反之)。
并发控制
继承 agent-team-audit 参数, 多轮场景补充约束:
| 参数 | 值 | 说明 |
|---|
| 单轮并发 | max_parallel: 2, hard_cap: 3 | 每轮内的 Agent 并发 |
| 轮次间 | 串行 | 下一轮依赖上一轮结论 |
| 每轮超时 | 继承 300s/轮 | 独立计时, 不跨轮累计 |
| challenge 组间 | 串行 | 讨论组 → 挑战组 → 全员 (数据依赖) |
审计报告生成
Agent dispatch contract (v1.30.1+)
audit-engine 在 dispatch agent (经 agent-team-audit) 时必须把 8-field YAML frontmatter template 嵌入 prompt 原文, 否则 agent 自由发挥会导致 audit report 缺 frontmatter, dashboard parser 无法解析 (Forgejo Aria #126 实测 40% 报告无 frontmatter 不可见)。
完整契约 + 模板原文 + 责任分工 + backward-compat: 见 references/agent-dispatch-contract.md。
Pre-write validation: change_id 锚点检查 (2026-04-23, Issue #27)
写盘前验证 change_id 有对应的 openspec/changes/{id}/proposal.md 或 openspec/archive/*-{id}/proposal.md 背书; 缺失则拒绝写盘并提示 fix。豁免开关: .aria/config.json audit.allow_dangling_change_ids=true (默认 false)。
完整 4-step 验证流程 + ERROR 提示文本 + 豁免设计: 见 references/pre-write-validation.md。
报告存储 + Verdict (v1.17.4+ schema)
存储路径: .aria/audit-reports/{checkpoint}-R{round}-{timestamp_ms}-{spec_id}-{agent_role}.md — 5-field uniqueness schema 防 4-agent 并行同毫秒落盘碰撞 (Round-2 audit P0.2 fix)。
Verdict 计算: PASS (0 Critical + 0 Major) / PASS_WITH_WARNINGS (0 Critical + ≥1 Major) / FAIL (≥1 Critical)。报告 frontmatter 11 字段含 checkpoint/mode/rounds/converged/verdict/timestamp 等。
完整 schema (5-field uniqueness 字段定义 / 碰撞防护 / backward-compat reader / 引入背景) + Verdict 计算 + converged×verdict 组合含义 + 报告 Frontmatter 模板: 见 references/report-storage.md。
详细报告格式见 references/report-format.md。
配置依赖
通过 .aria/config.json 的 audit.* 块控制。参见 config-loader。
关键字段:
audit.enabled: boolean
audit.mode: string
audit.max_rounds: integer
audit.checkpoints: object
audit.teams: object
audit.adaptive_rules: object
audit.mid_implementation: object
audit.drift_guard: object
audit.allow_dangling_change_ids: boolean
audit.allow_incomplete_checkpoints: boolean
优先级: checkpoints 显式配置 > adaptive_rules 推导 > 默认 off
旧配置兼容: experiments.agent_team_audit: true 自动映射为
audit.enabled: true + audit.mode: "manual" + 旧触发点映射。
file-scope 二次过滤 (#58, v1.35.0)
mode 解析完成后 (checkpoints/adaptive_rules 得出 resolved_mode), 加一道 file-scope 二次判定 —— 当本次变更全部 ⊆ audit.scope_skip_paths (ops/docs-only) 时, 把 mode cap 到 convergence (challenge → convergence; off/convergence 不变)。避免 ops-only / docs-only PR 跑无意义 challenge audit (~5min vs 15-30min)。
仅 audit-on 项目生效 (audit 默认全 off)。降级非 skip (DEC-4): issue #58 实证 deploy script 改动 challenge 能找到真退化 (wget HTTP 4xx 退出 0) → deploy 不能全 skip, convergence 保留安全网。
# 变更文件来源: audit-engine 自取 (不读 snapshot — audit-engine 由 Phase Skill 调用)
base = .aria/config 配置的 base OR git symbolic-ref refs/remotes/origin/HEAD
(fallback origin/main → origin/master; 全部失败 → file-scope skip + warn, 不 crash)
changed_files = git diff --name-only $(git merge-base HEAD <base>)
# merge-base diff: 捕获 base→工作树的 committed+staged+unstaged 全部变更, 跨 checkpoint 正确
# (注: 不能用 `git diff HEAD` — pre_merge 时 hotfix 已 commit 到 HEAD, diff HEAD 会漏掉)
if len(changed_files) == 0: # 防 vacuous-true 空集误触
pass-through (不降级)
elif all(f matches scope_skip_paths for f in changed_files):
resolved_mode = min(resolved_mode, convergence) # challenge → convergence
else: # 任一业务文件 ∉ skip_paths
resolved_mode 不变 (标准 audit)
# 匹配语义: 目录项 (尾斜杠规范化, 如 "deploy/") → path.startswith(prefix)
# 后缀项 (如 "*.md") → path.endswith(".md")
emergency hotfix lane: pre_merge → convergence (#58)
当 emergency_hotfix lane (state-scanner emergency_hotfix 规则触发) 时, pre_merge audit 仅 audit.enabled=true 且 pre_merge checkpoint != off 时降级到 convergence (不 challenge)。与 file-scope 过滤双降级时幂等 (都 → convergence)。phase-c-integrator 在 pre_merge 调用点传递此 lane 信号。
相关文档
最后更新: 2026-06-11 (#17 audit-drift-guard — Drift Guard 原始目的锚定)