自举双轨对比方法论评审

评审人: 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 当前状态

方法论没有定义评分标准或数值质量分数。而是依赖:

  1. DiffClassifier diffs — 分类差异(非统一分数)
  2. DiagnosisResult — 根因分类 + 置信度 [0.0–1.0]
  3. 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 输出 + ComparisonReport JSON = 可复现的评审用产物。

但也引入了新的偏差:

  • 虚假等同:将 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 关键问题(生产使用前必须修复)

  1. C3 接线:DiagnosisReportGenerator::generate() 从未被调用。整个输出管线在 ComparisonReport 结构体处终止 — 没有报告被写入磁盘或展示给人类。
  2. 置信度硬编码:DiagnosisResult 存在差异时始终设置 confidence=0.8。这毫无意义,可能误导人类评审者信任一个没有依据的指标。
  3. Orchestration 阈值溢出:任何浮点数 epsilon 差异都触发 Critical 严重级别。0.00001% 的完成率比例差异与 50% 的差异被标记为同一级别。

6.3 重要问题(应在 v0.78.x 中解决)

  1. Prompt 维度是代理指标,非实际 prompt 比较:Summary 长度比率不衡量 prompt 差异。两个完全不同但长度相似的 prompt 不可见。
  2. Minor 严重级别未使用:严重级别谱系有缺口。至少应有一条规则产生 Minor 差异。
  3. 无趋势/回归跟踪:每次比较是独立的。没有持久化,无法判断 xwcode-dev 是否在随时间改进。
  4. 匿名盲法:虽然对 Phase 1 不关键,但缺乏盲法在人类解释中引入了可预测的倾向 Track A 偏差。

6.4 次要问题(延迟处理)

  1. 相同长度不同内容的零差异:test_classify_same_length_different_content 证明框架不检测相同长度摘要的语义差异。目前可接受,但应在报告输出中记录此限制。
  2. run_bootstrap_task 使用已弃用 API:已知技术债务,在 v0.78.0 Wave 1 中修复。不是方法论问题,但影响可靠性。
  3. 无 CLI 集成:整个自举管线只能通过 Rust API 调用,不能从 xwcode CLI 调用。使得临时比较更困难。

7. 建议(按优先级排序)

P0 — 首次真实双轨运行前必须完成

  1. 接线 C3:在 run_bootstrap_task 中调用 DiagnosisReportGenerator::generate() 并将输出写入文件(例如 {report_dir}/bootstrap-diagnosis-{task_id}.md)。这已在 v0.78.0 Wave 2 中计划,但应通过集成测试验证。

  2. 修复 orchestration 阈值:将 f64::EPSILON 替换为有意义的阈值(例如 > 0.05 表示 5% 的比率差异)。防止噪声被标记为 Critical。

  3. 从证据推导置信度:用基于 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 期间

  1. 添加 Minor 严重级别规则:最简单的选项是"工具调用次数匹配但顺序不同" — 这可以从事件日志中检测,无需 LLM 输出捕获。

  2. 添加趋势端点:添加 ComparisonReport::key_metrics() -> Metrics 结构体,包含(total_diffs, critical_count, major_count, token_ratio_variance),并可选择持久化到 JSONL 文件用于跨运行比较。

  3. 用内容哈希比较替换 summary 长度代理指标:对完整 summary 文本进行哈希并比较。这是一行代码的改动(对两个 summary 进行哈希,比较),立即比长度比率更准确。

P2 — v0.79.0+

  1. 实现 Model 维度检测:向 ExecutionResult 添加可选字段 llm_outputs: Vec<String> 用于实际的 LLM 响应比较。这实现了真正的 prompt → 响应因果跟踪。

  2. 添加 CLI 入口:xwcode bootstrap --task <file> --track-a-config <json> --track-b-config <json> 用于无需 Rust 代码修改的临时双轨运行。

  3. 实现选择性盲法:在 Markdown 报告中随机化 Track A/B 标签(不在 JSON 中,保留身份用于调试),人类审查后解码。


8. 结论

双轨对比方法论的设计和实现对于 Phase 1 自托管评审在结构上是合理的,但存在三个关键缺口:

  1. 输出管线断裂(C3 未接线)— 诊断报告代码存在但从未到达人类手中。
  2. 置信度评分是桩代码 — DiagnosisResult 置信度硬编码且具有误导性。
  3. Orchestration 阈值过于敏感 — epsilon 级别的差异产生 Critical 警报。

五维分类框架(DiffCategory)设计良好,实现干净,但只有 4/5 维度在运行,且活跃的四个维度中有一个(Prompt)使用代理指标而非实际的 prompt 比较。

总体结论:方法论适用于其 Phase 1 目的(对 xwcode-dev 输出的结构化人机协同比较),前提是三个 P0 问题在首次真实双轨运行前得到解决。对于 Phase 2(自动化评估和配置调整),框架需要 ground truth 锚定、趋势跟踪和实际的 prompt 内容比较。