已关闭
[issue] duplication_output_bytes 超限时 stdout 非合法 JSON #9
cezarbbb创建于 9月9日关闭于 9月17日
WangZijun
9月15日 评论:
9月15日 评论:
https://gitcode.com/xuanwu/bot-metric/merge_requests/8
结论:
- 问题可复现:已通过修复前最小复现/回归测试确认。
- 问题可修复:当前分支集成测试已验证修复行为。
具体修复:
- 在输出预算检查前完成机器 JSON 序列化,避免 stdout 产生截断 JSON。
- 区分输出预算超限与格式错误的 BM403 原因。
- 明确 duplication top 模式的重复行数及 stable_subject 字典序取舍规则并增加测试。


WangZijun
9月15日 评论:
9月15日 评论:
回归测试:
Issue #10(时间单位:ms;每种策略 5 次平均;benchmark 与 updated 在同一轮交错配对运行):
| 项目 | benchmark | updated | ||||||
|---|---|---|---|---|---|---|---|---|
| 串行首轮 | 串行热 | 并行首轮 | 并行热 | 串行首轮 | 串行热 | 并行首轮 | 并行热 | |
| bot-compass 263 files / 115583 NBNC | 1259.52 ms | 1221.95 ms | 455.62 ms | 421.70 ms | 1285.33 ms | 1194.71 ms | 429.91 ms | 415.12 ms |
| bot-forge 64 files / 25516 NBNC | 374.14 ms | 376.58 ms | 183.05 ms | 185.85 ms | 369.51 ms | 406.71 ms | 186.79 ms | 187.04 ms |
| bot-gate 59 files / 30848 NBNC | 433.49 ms | 381.81 ms | 193.50 ms | 200.54 ms | 415.13 ms | 392.29 ms | 196.11 ms | 200.46 ms |
| bot-metric 29 files / 25074 NBNC | 321.09 ms | 336.50 ms | 205.03 ms | 244.38 ms | 353.83 ms | 337.01 ms | 208.09 ms | 244.42 ms |
| rust 2818 files / 828622 NBNC | 11491.19 ms | 11735.57 ms | 2793.08 ms | 2758.75 ms | 11280.33 ms | 11416.64 ms | 2736.05 ms | 2670.30 ms |
共同运行配置(benchmark 与 updated 相同):
- scope: reachable
- aggregation: physical
- format: json
- cache_policy: cold_then_filesystem_warm
- toolchain: rustc 1.98.0-nightly (d595fce01 2026-06-02)
- warm_runs: 5
- cpu_cores: 4
- logical_cpu_cores: 8
- parallel_count: 8
- ram_bytes: 0
- ram_gib: None
结果说明:
- 五个项目的 files/NBNC 语义摘要全部一致。
- 严格逐格 updated <= benchmark 检查受运行时噪声影响,结果为 passed=false;配对比值约在 0.96x 到 1.10x,没有跨项目、跨策略的系统性回退。
- issue #10 的 stable_subject 只影响 baseline finding identity,不进入五个 analyze workload;没有发现需要针对 benchmark 主路径的性能优化。全量测试、Clippy、格式检查和 release 构建均通过。


问题概述
[thresholds].duplication_output_bytes设为极小值(如 100)触发输出预算超限时,stdout 为被截断的 JSON 片段(实测 1116 字节)与 BM403 错误文本直接拼接,不是合法 JSON,机器消费方解析失败;完整错误信息在 stderr。根因:v1.1.0 流式输出(BoundedSink)先写出后报错,超限后无法回滚已输出内容。首次出现版本:v1.1.0(流式机器输出引入;v1.0.0 无此配置键,遇新键直接 BM401 拒绝,不存在该场景)。受影响对象:所有输入类型(输出层问题,与输入无关)。实际影响:预算超限场景 stdout 机器可读契约被破坏,CI 管道 JSON 解析报错。本问题不涉及指标数值,涉及报告输出契约。影响范围
--output写文件(文件内容完整、stdout 干净);② 调大duplication_output_bytes预算复现步骤
最小源码样例:夹具
fixtures\dup-many(48 个 .rs 文件、831 行,22 组 11 行重复块 + tiny_dup_a.rs/tiny_dup_b.rs 完全重复文件对,重复发现量大以触发超限)。自包含最小样例如下(与夹具同构的重复文件对,足以触发输出预算超限;下述命令中的<dup-pair>即指向该样例目录):Cargo.toml:[package] name = "dup-pair" version = "0.1.0" edition = "2021"src/lib.rs:pub mod dup_a; pub mod dup_b;src/dup_a.rs:// dup_a.rs — intentionally duplicated with dup_b.rs (12 identical NBNC lines). pub fn transform_a(values: Vec<u32>, factor: u32) -> Vec<u32> { let mut out = Vec::with_capacity(values.len()); for v in values { if v == 0 { continue; } let scaled = v * factor; if scaled > 1000 { out.push(1000); } else { out.push(scaled); } } out } pub fn summarize_a(values: &[u32]) -> u32 { values.iter().copied().sum() }src/dup_b.rs:// dup_b.rs — intentionally duplicated with dup_a.rs (12 identical NBNC lines). pub fn transform_b(values: Vec<u32>, factor: u32) -> Vec<u32> { let mut out = Vec::with_capacity(values.len()); for v in values { if v == 0 { continue; } let scaled = v * factor; if scaled > 1000 { out.push(1000); } else { out.push(scaled); } } out } pub fn summarize_b(values: &[u32]) -> u32 { values.iter().copied().sum() }配置
bot-metric-dup-out.toml:[thresholds] duplication_output_bytes = 100 [rules] duplication_findings = "all"BM110 analyze <dup-many> --config bot-metric-dup-out.toml --format json(stdout 重定向到文件)预期结果
stdout 为合法 JSON(错误以结构化字段表达),或干净失败(stdout 为空、错误仅走 stderr),进程退出码非 0 且可被机器判定。
实际结果
stdout = 1116 字节截断 JSON 片段 + BM403 错误文本拼接,不是合法 JSON;完整错误信息在 stderr。两平台输出逐字节相同。证据:
x86_linux\records\batch-09\verify-groupB_5-2_5-3_5-4.txt;arm_linux\records-arm64\batch-09\verify-groupB_5-2_5-3_5-4.txt、arm_linux\records-arm64\batch-05\out\t56-out.json。证据原文(x86_linux\records\batch-09\verify-groupB_5-2_5-3_5-4.txt):
证据原文(arm_linux\records-arm64\batch-09\verify-groupB_5-2_5-3_5-4.txt):
证据原文(arm_linux\records-arm64\batch-05\out\t56-out.json,1116 字节全文):
{ "tool": "bot-metric", "component": "metric", "schema": "https://bot-metric.dev/schema/analysis-report.json", "tool_version": "1.1.0", "config_hash": "{ "component": "metric", "diagnostics": [ { "code": "BM403", "column": null, "file": null, "level": "error", "line": null, "message": "rendered report requires more than 200 bytes, exceeding configured output limit" } ], "error": { "code": "BM403", "command": "Analyze", "message": "rendered report requires more than 200 bytes, exceeding configured output limit", "stage": "complete" }, "errors": [ { "code": "BM403", "message": "rendered report requires more than 200 bytes, exceeding configured output limit" } ], "findings": [], "gate": { "blocking_findings": 0, "blocking_rules": [], "blocking_severities": [], "findings_by_rule": {}, "findings_by_severity": {}, "status": "failed" }, "schema": "https://bot-metric.dev/schema/analysis-report.json", "status": "failed", "tool": "bot-metric", "tool_version": "1.1.0" }分析环境与范围
--config bot-metric-dup-out.toml --format json指标、发现与报告证据
t56-out.json、verify-groupB_5-2_5-3_5-4.txt)性能与资源证据
附件与提交确认