自举双轨对比方法论评审
评审人: methodology-reviewer(团队 bootstrap-review-squad) 日期: 2026-07-11 评审范围: 用于评估 xwcode-dev 输出的双轨对比方法论的结构性评审 来源文档:
v0770-bootstrap-and-dual-track/design.md,boot-phase1/proposal.md,boot-phase1/design.md,boot-phase1/specs/self-hosted-review/spec.md,v0780-goal-and-plan.md,crates/xw-runtime/src/agent/bootstrap.rs
1. 比较框架:DiffCategory 五维、DiffSeverity 四级、DiffClassifier 规则
1.1 DiffCategory — 五个维度
系统定义了五个正交的比较维度:
| 维度 | 信号含义 | 当前检测方式 | 分配严重级别 |
|---|---|---|---|
| Prompt | System prompt 或 user message 内容不同 | 代理指标:summary 长度差异 >50% | Info |
| Tool | 工具调用序列/参数/数量不同 | modified_files 数量不匹配 | Major |
| Orchestration | 阶段/Agent 路径不同 | completion_ratio 差异(任何非零差异) | Critical |
| Model | LLM 输出不同(prompt 相同) | 未检测 — 保留给未来使用 | — |
| Token | Token 消耗量不同 | total_tokens 差异 >10% | Info |
1.2 DiffSeverity — 四个级别
| 级别 | 定义 | DiffClassifier 中的示例 |
|---|---|---|
| Critical | 可能导致不同结果 | 完成率比例不同(Orchestration) |
| Major | 显著但可能不改变结果 | 修改文件数量不同(Tool) |
| Minor | 可察觉但不太可能影响结果 | 尚无规则分配此级别 |
| Info | 信息性观察,不构成关注点 | Token 差异 >10%(Token)、Summary 长度 >50%(Prompt) |
1.3 DiffClassifier 规则 — 实际实现
分类器使用四条确定性规则,全部基于 ExecutionResult 字段:
1. TOKEN (Info)
如果两个 total_tokens 都存在且 (max-min)/max > 0.10
→ DiffCategory::Token, 严重级别 Info
2. TOOL (Major)
如果 modified_files.len() 不同
→ DiffCategory::Tool, 严重级别 Major
3. PROMPT (Info)
如果 |summary_a - summary_b| > max(|a|,|b|) / 2 (即 >50% 长度差异)
→ DiffCategory::Prompt, 严重级别 Info
4. ORCHESTRATION (Critical)
如果 completed_count/total_count 不同(任何差异,甚至 f64::EPSILON)
→ DiffCategory::Orchestration, 严重级别 Critical
1.4 评估
优势:
- 纯确定性规则 → 来自模型噪声的零误报,完全可复现
- 每条规则都能用简单的算术断言测试(已有 25 个测试)
- 无 ML 依赖,无训练数据需求 — 适用于 v0.77–v0.78 阶段
- 严重级别映射与影响合理对应:比率差异(Critical)vs. Token 膨胀(Info)
劣势:
- Prompt 维度检测不足:代理指标(summary 长度比)只捕获冗长度差异,不捕获 prompt 的语义差异。两次运行可能有完全不同但长度相同的 prompt,会被分类为一致。
- Model 维度完全未检测:已预留但未实现。需要在
ExecutionResult中捕获 LLM 输出,实现成本不低。 - Orchestration 阈值过于敏感:完成率比例的任何浮点数 epsilon 差异都会触发 Critical 差异。两次都完成所有任务但相差 0.001% 的运行也会被标记为 Critical。
- Minor 严重级别未被使用:没有规则分配
DiffSeverity::Minor,严重级别谱系有缺口。 - 缺少工具调用序列比较:Tool 维度只统计修改文件数量;遗漏了调用哪些工具、什么顺序的差异,这可能是更重要的信号。
建议:
- 当
ExecutionResult捕获 prompt 文本后,用实际 prompt 内容比较(哈希或结构化 diff)替换 summary 长度代理指标。 - 为 orchestration 比率检查增加迟滞/阈值(例如仅当 |ratio_a - ratio_b| > 0.05 时标记),避免 epsilon 触发的噪声。
- 实现至少一条 Minor 严重级别的规则(例如:工具调用次数匹配但顺序不同 → Minor)。
- 通过向
ExecutionResult添加可选的 LLM 响应捕获,计划 Model 维度的检测。
2. 质量标准:评分标准和正确性定义
2.1 当前状态
方法论没有定义评分标准或数值质量分数。而是依赖:
- DiffClassifier diffs — 分类差异(非统一分数)
- DiagnosisResult — 根因分类 + 置信度 [0.0–1.0]
- DiagnosisReportGenerator — 按严重级别分组的 Markdown 报告
正确性被隐式定义为:"Track A 和 Track B 产生相同的 ExecutionResult 字段"(无差异)。当存在差异时,方法论不做正确性判断 — 将解释权委托给人类(claude-ar)。
2.2 轨道不一致时
系统没有机制判断哪个轨道是正确的。框架设计用于比较,而非评估。具体来说:
- Track A(opencode-dev)在上下文被标记为"ground truth",但
ExecutionResult没有 ground truth 标注。 - Track B(xwcode-dev)可能以框架无法检测的方式出错(两个轨道可能以相同方式出错)。
DiagnosisResult::confidence在存在差异时硬编码为 0.8,无差异时为 1.0 — 这是占位符,不是有意义的置信度分数。
2.3 评估
优势:
- 诚实地面对自己的局限:不假装判断正确性,只报告差异
DiagnosisReportGenerator输出人类可读,结构化便于专家审查- 严重级别分组有助于分类处理
劣势:
- 无 ground truth 锚定:没有已知正确的第三方参照,轨道分歧时正确性无法定义
- 硬编码置信度:
run_bootstrap_task中的DiagnosisResult::new(...)存在差异时始终设置 confidence=0.8,不论差异的规模或类别。这是桩代码,不是真正的置信度估计。 - 无通过/失败阈值:没有规则定义"X 个严重级别 Y 的差异 = 任务失败"。框架纯粹是描述性的。
建议:
- 为每个
BootstrapTask.eval_criteria定义明确的正确性标准 — 该字段存在于结构体中但从未被DiffClassifier或DiagnosisResult使用。例如:"critical_count==0 AND major_count<=2" 可作为通过阈值。 - 用基于 diff 数量/严重级别的启发式方法替换硬编码置信度(例如:confidence = 1.0 - (critical_count * 0.3 + major_count * 0.1))。
- 为自托管评审工作流增加第三方验证步骤:claude-ar 的独立评审在轨道分歧时充当近似 oracle。
3. 合并决策框架:四种场景
3.1 定义
v0780-goal-and-plan.md 中定义了四种合并场景:
| 场景 | 合并方式 | 判断标准 |
|---|---|---|
| Track B 输出可接受 | --no-ff |
代码评审 + ComparisonReport + 测试 + 质量门禁全部通过 |
| Track B 部分正确 | squash |
部分差异可接受,代码整体比基线有改进 |
| Track B 贡献了特定修复 | cherry-pick |
个别 commit 或 diff 有价值 |
| Track B 输出不可接受 | abandon |
存在 Critical 差异、失败或回归 |
3.2 评估
优势:
- 覆盖完整决策空间(接受/拒绝/部分/选择性)
- 合并方式映射到真实 git 操作 — 无抽象理论
- 决策权明确分配给 claude-ar
劣势:
- 判断标准模糊:"部分差异可接受"和"整体比基线有改进"没有被操作化。多少个 Critical 差异是可接受的?什么算"改进"?
- 无明确优先级规则:当 ComparisonReport 和代码评审不一致时(例如 ComparisonReport 显示 Critical orchestration 差异但人工评审说"没问题"),没有定义优先级规则。
- 无超时/回退:如果 claude-ar 不可用,没有自动回退机制(例如委托给 opencode-dev)。
- 自托管评审工作流(来自
boot-phase1/specs/self-hosted-review/spec.md)将 xwcode-dev 的输出定义为非阻塞式 — 这对 Phase 1 是合理的,但使合并决策不对称:即使 xwcode-dev 客观上更好,claude-ar 也能推翻。
建议:
- 为每个场景定义数值阈值(例如:"有任何 Critical 差异 OR >2 个 Major 差异 OR 任何测试回归 → abandon")。
- 添加决策优先级阶梯:ComparisonReport 信号 > 自动化测试结果 > 人工判断(或相反 — 指定冲突时哪个优先)。
- 对于 cherry-pick 场景,定义什么构成"有价值的单个 commit" — 是功能修复、重构还是文档?
4. 偏差分析:双轨是减少还是引入了偏差?
4.1 已识别的偏差来源
| 偏差类型 | 风险 | 方向 |
|---|---|---|
| 确认偏差 | claude-ar 预期 Track A 更好 → 将模糊差异解释为有利于 Track A | 倾向 Track A |
| 选择偏差 | 初始自举任务由 opencode-dev/人类选择(简单的内部任务)— 可能不代表真实难度 | 倾向 xwcode-dev(简单任务放大能力假象) |
| 比较不对称 | Track A(opencode-dev)拥有更多上下文/历史;Track B(xwcode-dev)在较不成熟的环境中运行 | 倾向 Track A |
| 实现缺口 | DiagnosisReportGenerator 未接线;DiffClassifier 只覆盖 4/5 类别 — 缺失的比较意味着不可见的偏差 |
不确定 |
| 非盲法 | claude-ar 和 opencode-dev 都知道哪个轨道是哪个 | 倾向 Track A(感知权威性) |
4.2 双轨是否减少了偏差?
是的,在特定方面:
- 结构化证据:框架强制对差异进行明确分类,而不是整体判断。评审者不能说"Track B 感觉不对"— 他们必须指向特定的 DiffCategory 并提供证据。
- 严重级别纪律:DiffSeverity 级别防止琐碎差异被过度加权。
- 审计轨迹:
DiagnosisReportGenerator输出 +ComparisonReportJSON = 可复现的评审用产物。
但也引入了新的偏差:
- 虚假等同:将 Track A 标记为"opencode-dev(ground truth)"、Track B 标记为"xwcode-dev(被评估者)",即使 Track B 实际上更好,也会隐式偏向 Track A。
- 测量偏差:被测量的内容(token 数量、文件数量、比率)塑造了被优化的内容。未测量的维度(代码质量、测试覆盖率)对框架不可见。
- 注意力不对称:Critical 差异(orchestration 比率)因被标记为 Critical 而获得不成比例的注意力,即使比率差异可能只是微不足道的舍入问题。
4.3 盲法 vs. 非盲法
当前设计是非盲法(轨道被标记为 A/B 且身份已知)。对于更严格的比较:
选项 1 — 保持命名(当前):更简单,允许上下文解释。接受倾向 Track A 的偏差。
选项 2 — 匿名轨道:标签变为"绿/蓝"或"Alpha/Beta",比较后才揭示身份。减少权威偏差,但更难在上下文中解释差异。
选项 3 — 带两个独立分类器的盲法:两个代理(或两次独立的 DiffClassifier 运行)独立分类差异,然后比较结果以达成共识。对 Phase 1 过度设计。
建议:
- 对于 v0.78.0 Phase 1,保持非盲法(简单性 > 严谨性)。
- 在比较报告上添加一个小型盲法机制:随机化报告中哪个轨道是 A 或 B,人类审查后解码。这不影响 DiffClassifier(确定性)但影响人类阅读。
5. 反馈循环:结果如何改进 xwcode-dev
5.1 预期循环
来自 boot-phase1/design.md(D2)和 self-hosted-review/spec.md:
opencode-dev 完成 Wave → push
→ xwcode-dev 评审(并行、只读)
→ xwcode-dev 通过 comm 发送评审
→ claude-ar 对比两份评审
→ claude-ar 产出六维诊断报告
→ claude-ar 决定是否推进到 Phase 2
对于双轨对比的具体流程:
BootstrapTask 定义
→ Track A(opencode-dev)通过 MockProvider 执行
→ Track B(xwcode-dev)通过 RealProvider 执行
→ DiffClassifier 产出 ComparisonReport
→ DiagnosisReportGenerator 产出 Markdown
→ 人类阅读报告 → 调整 xwcode-dev 配置 → 重新运行
5.2 当前实现状态
| 循环组件 | 状态 | 缺口 |
|---|---|---|
| BootstrapTask 定义 | ✅ 已实现 | — |
| 双轨执行(A/B) | ✅ run_bootstrap_task 自由函数 |
使用了已弃用的 run_turn_with_callback;S1 Wave 将修复 |
| DiffClassifier::classify | ✅ 已实现 + 25 个测试 | 仅 4/5 维度;Minor 未使用 |
| ComparisonReport | ✅ 已实现 | — |
| DiagnosisReportGenerator::generate | ✅ 代码存在(~88 行) | 未接线 — 在任何执行路径中都未被调用(C3) |
| 基于 comm 的评审流程 | 部分实现 | xwcode-dev 代理必须在 km 机器上注册 |
| 人类决策循环 | ⬜ 未自动化 | 仅手动 |
5.3 评估
优势:
- 架构支持闭环:数据 → 分析 → 洞察 → 调整
DiagnosisResult有suggested_fix字段,设计用于自动化修复建议- 自托管评审工作流定义了具体的诊断维度(覆盖率、误报、遗漏、延迟、安全)
劣势:
- 循环在 C3 处断裂:
DiagnosisReportGenerator生成了完美的 Markdown,但没有代码调用它。因此循环产生原始 JSON 差异后停止 — 没有人类可读的诊断输出。 - 无自动回归跟踪:没有机制比较今天的差异与昨天的基线。每次比较都是独立分析,没有趋势数据。
- suggested_fix 是字符串占位符:在
run_bootstrap_task中,修复建议硬编码为"Review the ComparisonReport diffs for details." — 桩代码,不可执行。 - 无配置调整循环:框架诊断但不建议或应用对 xwcode-dev 的配置更改(例如"将 temperature 从 0.7 降低到 0.3"或"向 system prompt 添加这些指令")。
run_bootstrap_task使用run_turn_with_callback(已弃用路径)而非run_turn_with_sink— 这是已知的技术债务,正在 v0.78.0 Wave 1 中处理。
建议:
- 将 C3 接线作为最高优先级:
DiagnosisReportGenerator::generate()必须在每次run_bootstrap_task()后被调用。这已在 v0.78.0 Wave 2 中计划。 - 添加
ComparisonReport::summary_stats()方法,产出一小组可趋势化的指标(总差异数、Critical 数量、Major 数量、token 比率方差),用于跨运行比较。 - 用基于规则的推荐引擎替换硬编码的
suggested_fix,将(DiffCategory + DiffSeverity)模式映射到具体操作。例如:Tool Major 差异 → "检查 xwcode-dev 配置中的工具选择启发式方法。" - 接线 C3 后,添加
--compare-previous标志,加载上一次的 ComparisonReport JSON 并产出"改进/退步"对比。
6. 总体评估
6.1 方法论成熟度
| 标准 | 评分 | 备注 |
|---|---|---|
| 框架完整性 | 6/10 | 4/5 维度已实现;Minor 未使用;Model 维度缺失 |
| 实现正确性 | 8/10 | 代码与规范一致;25 个测试;0 个未解决 bug |
| 决策清晰度 | 5/10 | 合并标准模糊;无评分标准;置信度硬编码 |
| 偏差意识 | 7/10 | 隐式偏差来源已识别;无主动缓解措施 |
| 反馈循环闭合 | 3/10 | C3 未接线;suggested_fix 是桩代码;无趋势跟踪 |
| 可扩展性 | 7/10 | 清晰的枚举类型;serde 支持;易于添加规则 |
6.2 关键问题(生产使用前必须修复)
- C3 接线:
DiagnosisReportGenerator::generate()从未被调用。整个输出管线在ComparisonReport结构体处终止 — 没有报告被写入磁盘或展示给人类。 - 置信度硬编码:
DiagnosisResult存在差异时始终设置 confidence=0.8。这毫无意义,可能误导人类评审者信任一个没有依据的指标。 - Orchestration 阈值溢出:任何浮点数 epsilon 差异都触发 Critical 严重级别。0.00001% 的完成率比例差异与 50% 的差异被标记为同一级别。
6.3 重要问题(应在 v0.78.x 中解决)
- Prompt 维度是代理指标,非实际 prompt 比较:Summary 长度比率不衡量 prompt 差异。两个完全不同但长度相似的 prompt 不可见。
- Minor 严重级别未使用:严重级别谱系有缺口。至少应有一条规则产生 Minor 差异。
- 无趋势/回归跟踪:每次比较是独立的。没有持久化,无法判断 xwcode-dev 是否在随时间改进。
- 匿名盲法:虽然对 Phase 1 不关键,但缺乏盲法在人类解释中引入了可预测的倾向 Track A 偏差。
6.4 次要问题(延迟处理)
- 相同长度不同内容的零差异:
test_classify_same_length_different_content证明框架不检测相同长度摘要的语义差异。目前可接受,但应在报告输出中记录此限制。 run_bootstrap_task使用已弃用 API:已知技术债务,在 v0.78.0 Wave 1 中修复。不是方法论问题,但影响可靠性。- 无 CLI 集成:整个自举管线只能通过 Rust API 调用,不能从
xwcodeCLI 调用。使得临时比较更困难。
7. 建议(按优先级排序)
P0 — 首次真实双轨运行前必须完成
-
接线 C3:在
run_bootstrap_task中调用DiagnosisReportGenerator::generate()并将输出写入文件(例如{report_dir}/bootstrap-diagnosis-{task_id}.md)。这已在 v0.78.0 Wave 2 中计划,但应通过集成测试验证。 -
修复 orchestration 阈值:将
f64::EPSILON替换为有意义的阈值(例如> 0.05表示 5% 的比率差异)。防止噪声被标记为 Critical。 -
从证据推导置信度:用基于 diff 数量 × 严重级别权重的简单函数替换硬编码的 0.8:
fn compute_confidence(diffs: &[Diff]) -> f64 { if diffs.is_empty() { return 1.0; } let penalty: f64 = diffs.iter().map(|d| match d.severity { DiffSeverity::Critical => 0.3, DiffSeverity::Major => 0.1, DiffSeverity::Minor => 0.05, DiffSeverity::Info => 0.01, }).sum(); (1.0 - penalty).max(0.0) }
P1 — v0.78.x 期间
-
添加 Minor 严重级别规则:最简单的选项是"工具调用次数匹配但顺序不同" — 这可以从事件日志中检测,无需 LLM 输出捕获。
-
添加趋势端点:添加
ComparisonReport::key_metrics()->Metrics结构体,包含(total_diffs, critical_count, major_count, token_ratio_variance),并可选择持久化到 JSONL 文件用于跨运行比较。 -
用内容哈希比较替换 summary 长度代理指标:对完整 summary 文本进行哈希并比较。这是一行代码的改动(对两个 summary 进行哈希,比较),立即比长度比率更准确。
P2 — v0.79.0+
-
实现 Model 维度检测:向
ExecutionResult添加可选字段llm_outputs: Vec<String>用于实际的 LLM 响应比较。这实现了真正的 prompt → 响应因果跟踪。 -
添加 CLI 入口:
xwcode bootstrap --task <file> --track-a-config <json> --track-b-config <json>用于无需 Rust 代码修改的临时双轨运行。 -
实现选择性盲法:在 Markdown 报告中随机化 Track A/B 标签(不在 JSON 中,保留身份用于调试),人类审查后解码。
8. 结论
双轨对比方法论的设计和实现对于 Phase 1 自托管评审在结构上是合理的,但存在三个关键缺口:
- 输出管线断裂(C3 未接线)— 诊断报告代码存在但从未到达人类手中。
- 置信度评分是桩代码 —
DiagnosisResult置信度硬编码且具有误导性。 - Orchestration 阈值过于敏感 — epsilon 级别的差异产生 Critical 警报。
五维分类框架(DiffCategory)设计良好,实现干净,但只有 4/5 维度在运行,且活跃的四个维度中有一个(Prompt)使用代理指标而非实际的 prompt 比较。
总体结论:方法论适用于其 Phase 1 目的(对 xwcode-dev 输出的结构化人机协同比较),前提是三个 P0 问题在首次真实双轨运行前得到解决。对于 Phase 2(自动化评估和配置调整),框架需要 ground truth 锚定、趋势跟踪和实际的 prompt 内容比较。