遥测仪表盘对抗性验证实战:omo-senpi 原生工具调用并行度卡片如何从 needs-fix 走到 confirmed
【免费下载链接】oh-my-openagentOmO: Just type "mass ulw" keyword with your prompt. Now you are the master of graph engineering.项目地址: https://gitcode.com/gh_mirrors/oh/oh-my-openagent
本文以 oh-my-openagent 仓库中.omo/evidence/telemetry-parallel-latency-v2/verify-t8.md(todo 8「dashboard card + skill docs」的独立对抗性验证报告)为主线,完整还原一套可复用的「仪表盘遥测卡片验证方法论」:从列映射静态核对、哨兵值(sentinel)渲染、像素级高度测量,到诚实标签、比率口径、异常输入矩阵与源码公式交叉核对。读完你不仅能看到 omo-senpi 遥测模块中「原生工具调用并行度(native tool-call parallelism)」卡片的实现细节,还能掌握如何用独立验证者身份发现一个「数据全对、交付却有缺陷」的真实案例,以及修复后如何被二次确认(confirmed)。
背景:parallelism_summary 事件与「实测跨度」并行度卡片
在 omo-senpi 的遥测体系中,工具调用的并行度此前只能靠「同一秒内 delegation_started 记录」反推,属于下界估计。todo 8 引入了一个新事件parallelism_summary:每个会话至多发射一次,携带按调用(call)实测开始/结束时间聚合出的并行度指标。与之配套,仪表盘上新增了一对.g21卡片:
- 네이티브 툴콜 병렬도 — 실측 스팬 기반(Native 工具调用并行度——基于实测跨度):主卡片,展示
modeled_saved_ms(模型估计节省)、saved_round_trips、各类比率; - eval 버킷 · 데이터 품질(eval 桶 · 数据质量):副卡片,展示 eval 独立/混合波次、上界参考值、三个数据质量计数器。
对应的仓库侧核心实现位于 savings-math.ts、wave-assembler.ts 与 eval-classifier.ts。需要特别说明:todo 8 本身只改动本地 skill 文件(~/.agents/skills/omo-native-telemetry/下的templates/unified_model.py、templates/build_unified.py、SKILL.md),并未触碰 git 仓库;仓库源码只作为实现事实的对照物。下表是任务涉及的主要文件与角色:
| 文件(skill 本地路径或仓库路径) | 角色 |
|---|---|
~/.agents/skills/omo-native-telemetry/scripts/fetch_data.py | 执行 41 个查询并落盘 JSON,其中parallelism查询在约第 69 行 |
~/.agents/skills/omo-native-telemetry/templates/unified_model.py | 定义PARALLELISM_COLS、hms()、build_parallelism()视图模型 |
~/.agents/skills/omo-native-telemetry/templates/build_unified.py | 视图模型到 HTML 的模板渲染,含body{height}与新增卡片块 |
~/.agents/skills/omo-native-telemetry/scripts/run_dashboard.py | 一键流水线:fetch → growth → build → headless Chrome 截图 →(可选)Discord |
| savings-math.ts | 仓库内节省量数学实现:modeledWallClockSavedMs、upperBoundSavedMs、savedRoundTrips |
| wave-assembler.ts | 波次组装:spanMs(maxEnd − minStart)、maxConcurrency(扫描线) |
| eval-classifier.ts | eval 波次分类与位置直方图编码 |
以下各节按验证报告的检查顺序展开,每一步都给出「验证方法 + 结论 + 依据」。
一、列映射验证:13 列逐位对齐(PASS 13/13)
仪表盘渲染的前提是:查询返回的每一列必须与视图模型PARALLELISM_COLS中对应的模型标签一一对应。验证者没有相信任务简报里的「11 列」,而是直接解析了 fetch_data.py 中parallelism查询的 SELECT 列表(按括号深度感知的顶层逗号切分),与unified_model.py:12-16的PARALLELISM_COLS逐位 zip 对比:
| idx | 查询列(别名) | 模型标签 | 匹配 |
|---|---|---|---|
| 0 | count() sessions | sessions | match |
| 1 | sum(...non_eval_saved_round_trips) | saved_round_trips | match |
| 2 | sum(...modeled_wallclock_saved_ms) | modeled_saved_ms | match |
| 3 | sum(...non_eval_waves_total) | waves_total | match |
| 4 | sum(...non_eval_waves_multi) | waves_multi | match |
| 5 | sum(...non_eval_joined_calls) | joined_calls | match |
| 6 | sum(...eval_only_waves) | eval_only_waves | match |
| 7 | sum(...mixed_waves) | mixed_waves | match |
| 8 | sum(...incomplete_calls) | incomplete_calls | match |
| 9 | sum(...clock_anomalies) | clock_anomalies | match |
| 10 | sum(...dropped_calls) | dropped_calls | match |
| 11 | sum(...measured_turn_duration_ms_total) | measured_turn_ms | match |
| 12 | sum(...upper_bound_saved_ms) | upper_bound_saved_ms_ref | match |
结论:查询实际返回13 列,而简报声称 11 列——measured_turn_ms与upper_bound_saved_ms_ref被简报遗漏了。作者从源码而非简报建映射是正确的,零 off-by-one。这是一个重要的方法论教训:数据契约以源码为准,不以任务说明为准。
哨兵渲染验证(真正的检验)
静态比对仍可能双双出错,因此验证者注入了一行哨兵数据[[101,102,...,113]](每列一个唯一整数,按查询顺序),重建并渲染后从 PNG 上直接读回数字:
| 哨兵 | 查询列 | 屏幕出现位置 | 结论 |
|---|---|---|---|
| 101 | sessions | 세션 101개 | correct |
| 102 | saved_round_trips | 라운드트립 102회 | correct |
| 103 | modeled_saved_ms | 头条모델 추정 절감 0.1초(=103ms) | correct |
| 104 | waves_total | non_eval 웨이브 104개,作为105/104개的分母 | correct |
| 105 | waves_multi | 105/104개的分子(=101%) | correct |
| 106 | joined_calls | 총 106콜 | correct |
| 107 | eval_only_waves | kvroweval 단독 웨이브 107개 | correct |
| 108 | mixed_waves | kvroweval 혼합 웨이브 108개 | correct |
| 109 | incomplete_calls | 미완결/시계이상/드롭 콜 109 · 110 · 111(第 1 项) | correct |
| 110 | clock_anomalies | 同一行第 2 项 | correct |
| 111 | dropped_calls | 同一行第 3 项 | correct |
| 112 | measured_turn_ms | 측정 턴 0.1초;比率 103/112 渲染为92.0% | correct |
| 113 | upper_bound_saved_ms_ref | 상한 참고치 (상한, 헤드라인 아님) 0.1초 | correct |
衍生健全性检查:eval 桶头条显示215개= 107+108 精确成立;1.01개= 106/105;101%= 105/104。若列位置整体偏移一位,至少会破坏其中三个算式——全部吻合意味着无错标。这套「静态映射 + 哨兵像素回读」双保险是验证数据管线的黄金组合。
二、双状态渲染与像素级高度测量(PASS)
新卡片面临一个现实约束:parallelism_summary尚未全量部署,线上唯一真实路径是零数据。验证者用真实 fetch(41 个 JSON,EXIT=0)确认了生产数据形态:
parallelism.json -> [[0,null,null,null,null,null,null,null,null,null,null,null,null]] parallelism_daily.json -> []即「一行全 null」而非空数组——这正是视图模型必须 gate 的陷阱(详见下文稳健性节)。
高度测量:不是猜,而是扫
验证过程用--force-device-scale-factor=1 --window-size=1080,4200的超大窗口渲染,再把body{height}临时改为 4200,然后自底向上扫描像素行,找出最后一个与背景色#f5f4ed不同的行(容差 6,每隔一列采样):
| 状态 | 最后非背景行(0 起) | 内容底边 | 3060 处留白 |
|---|---|---|---|
| 无数据(真实 fetch) | 2973 | 2974px | 86px |
| 有数据(合成数据) | 3021 | 3022px | 38px |
关键发现:有数据状态比空数据状态高约 48px——真实数字到达后头条会折行成两行。若只按当前全 null 状态调高度,交付时看似正常,等事件真正落地那天会静默裁掉页脚。验证者独立复现了作者声称的 2973/3021 像素级数值,并确认 3060 覆盖两种状态(2580 会裁 442px,3000 会裁掉有数据态页脚第二行 22px)。这就是「measure the TALLEST variant」规则的意义。
两种状态在声明的--window-size=1080,3060 --force-device-scale-factor=2下渲染后逐字阅读:
- 无数据态:头条
모델 추정 절감 수집 대기(STONE 占位色,不会误读为数值)、三根零填充条、副卡eval 버킷 수집 대기全部수집 전,页脚两行完整且下方留白; - 有数据态:
모델 추정 절감 1.3시간 · 라운드트립 9,134회(折两行)、14% · 7,318/51,204개、3.00개 · 총 21,940콜、6.7% · 측정 턴 19.9시간、副卡eval 버킷 2,805개/1,842개/963개/5.4시간/217 · 4 · 38,页脚完整。
同时,对三种状态的可见文本(剥掉标签后)执行None/null/undefined/NaN正则扫描:零命中。HTML 中唯一的裸none是 sparkline 的 SVG 属性fill="none",不是文本——这一点与任务作者用grep -io "none\|null"得到的单一命中完全一致。
三、诚实标签与 eval 桶分离(PASS)
遥测类仪表盘最大的信誉风险是「把模型估计说成实测」。验证者直接从渲染 PNG 而非源码读取:
- 头条字面为
모델 추정 절감(= 模型估计),紧邻数值;副行重复측정된 벽시계 시간이 아니라 모델 추정치(不是实测墙钟时间,而是模型估计);第 3 行标签为턴 측정시간 대비 모델 추정 절감。任何位置都没有把节省量呈现为实测墙钟时间。 upper_bound_saved_ms只以副卡中一行 kvrow 出现,标签为상한 참고치 (상한, 헤드라인 아님)(上界参考值——上界,不是头条)。两种状态下它都从未成为头条。
eval 桶分离同样在像素上验证:
eval 단독 웨이브与eval 혼합 웨이브是两个独立 kvrow;其和eval_bucket_waves是副卡自己的头条,且从不加进waves_total/joined_calls——哨兵运行证明了这一点:eval=107/108 时 non_eval 分母始终是 104/105/106。- 屏上存在排除声明:
eval/코드모드 웨이브는 의도적으로 병렬도 수치에서 제외하고 별도 집계。 - 旧的委派批处理卡片(
병렬 툴콜링 절감 — 시리얼 실행 반사실)仍然存在且可区分:新卡带脚注「上方的委派批处理节省是按同一秒调度推断的下界;本卡是按逐调用实测时刻计算的直接测量值」。
四、比率口径:永不均值化比率(PASS)
build_parallelism中所有除法均为舰队级 sum/sum:
"multi_share": n["waves_multi"] / waves_total * 100 if waves_total else 0.0 "calls_per_multi_wave": joined / n["waves_multi"] if waves_multi else 0.0 "modeled_saved_per_session_ms": n["modeled_saved_ms"] / sessions # sessions>0 由 gate 保证 "saved_share_of_turn": n["modeled_saved_ms"] / n["measured_turn_ms"] * 100 if measured else 0.0分子分母全部来自查询的sum()聚合。查询与视图模型中不存在任何逐会话比率,因此「比率均值的均值」(mean-of-ratios)在结构上不可能出现;每个除数都有守卫,不存在ZeroDivisionError路径。这一点在视图模型定义unified_model.py的build_parallelism()中同样明确注释:fleet rate = sum/sum, not the average of per-session rates。
五、稳健性矩阵:两类崩溃均为存量行为(MOSTLY PASS)
验证者对数据文件做了系统性的破坏性探测:
| 探针 | 结果 |
|---|---|
rm parallelism.json | rc=0,html written 12559,走占位路径,HTML 无 traceback |
rm parallelism_daily.json | rc=0,html written 12559 |
| 两个都删 | rc=0,html written 12559 |
[[5,1,2]](3 列,太少) | rc=0,html written 12431——zip截断,缺失键默认 0 |
| 16 列(太多) | rc=0,html written 12439——多余列被zip丢弃 |
[](空数组) | rc=0,占位路径 |
[[7,null×12]](sessions=7,指标全 null) | rc=0,渲染真实 0 值,无None |
数字位置放入字符串["7","abc",...] | rc=1ValueError: could not convert string to float: 'abc' |
畸形 JSON{oops | rc=1json.decoder.JSONDecodeError |
畸形的parallelism_daily.json | rc=1JSONDecodeError |
两类崩溃(ValueError 与 JSONDecodeError)被判定为整个模块的存量行为、非 todo 8 引入:验证者在未改动的headline.json上复现了完全相同的崩溃(echo 'not json' > headline.json→ 同样的JSONDecodeError;[["abc",1,2,3]]→ 同样的ValueError)。关键在于:构建崩溃时不写任何 HTML 文件(ValueError 运行后index_unified.html不存在),因此栈追踪永远不可能进入 HTML——「HTML 中不得出现栈追踪」的硬性要求无条件满足。构建以非零退出,run_dashboard.py在fail("build_unified", ...)处快速失败。
六、文档公式与仓库源码逐条核对(PASS)
验证者把SKILL.md中的每一个公式主张都与仓库源码对照,全部 exact:
| SKILL.md 主张 | 仓库来源 | 结论 |
|---|---|---|
modeled_wallclock_saved_ms = Σdᵢ − span,span = maxEnd − minStart | savings-math.ts 的modeledWallClockSavedMs→sum(durations) - wave.spanMs;wave-assembler.ts中spanMs: maxEnd - minStart | exact |
max(dᵢ)在链式 A(0-5)/B(4-9)/C(8-12) 上高估 4.5 倍 | 重算:Σd=14,span=12 → 节省 2;Σd−max(d)=9;9/2 =4.5 | exact |
真正同时批次的span == max(d) | savings-math.ts 头注释原文 | exact |
savedRoundTrips = Σ max(maxConcurrency−1, 0),而非N−1 | savings-math.tssavedRoundTrips→Math.max(wave.maxConcurrency - 1, 0) | exact |
upper_bound_saved_ms = (N−1) × mean(d) | savings-math.tsupperBoundSavedMs→(durations.length - 1) * mean | exact |
| eval 过滤会虚增节省:1.20s 报成 0.70s | eval-classifier.ts注释原文;测试用例使用这些字面量 | exact |
8 个位置桶1,2,3,4,5_8,9_16,17_32,33plus,:连接,无标签 | eval-classifier.tsWAVE_SIZE_BUCKET_MAXIMA = [1,2,3,4,8,16,32]与histogram.join(":");测试断言not.toContain("=") | exact |
| 64 字符截断;带标签=69 字符,位置式=39 字符 | telemetry-core/src/events.ts的value.slice(0, 64);最坏位置式2000:...×8= 39;最坏带标签式 = 69 | exact |
MAX_TRACKED_CALLS = 2000 | wave-assembler.ts | exact |
clock_anomalies=endMs < startMs,不假设单调性 | savings-math.tsusableDurations中if (call.endMs < call.startMs) continue | exact |
零数据 = 一行 null,parallelism_daily=[] | 在真实 fetch 上复现 | exact |
事件 schema 行 +(8 events) | parallelism_summary行存在,所有属性列出,计数 7→8 | correct |
parallel_savings必须标注为 LOWER BOUND | 文档更新正确,但渲染文案未更新→ DEFECT-1 | doc ok / render stale |
| 高度流程 + 「测量最高的变体」(2967 空 vs 3021 有数据) | 测量 2974/3022 确认排序与教训 | correct |
值得注意的是最后一行的「文档 ok / 渲染过期」——这正是验证者拒绝confirmed的第一条理由。
七、DEFECT-2:证据文件里的一条假事实(已澄清)
任务作者的证据文件 Risks 第 1 项声称scripts/run_dashboard.py仍以硬编码--window-size=1080,2150(第 61 行)渲染,一次性流水线会静默给 Discord 发送被裁剪的 PNG。验证者用 grep 直接证伪:
$ grep -c 2150 run_dashboard.py -> 0 $ grep -n "window-size" run_dashboard.py 68: f'--force-device-scale-factor=2 --window-size=1080,{height} '真相是run_dashboard.py第 58-62 行从生成的 CSS 中解析高度(re.search(r"body\s*\{[^}]*?height:(\d+)px", html))再喂给 Chrome;第 61 行是fail("render_height", ...)分支而非硬编码尺寸。端到端实测:
$ python3 run_dashboard.py --data-dir /tmp/vt8-pipeline --no-upload { ... "render_height": 3060, "png": ".../dash_unified.png", "discord": {"skipped": true} } EXIT=0结论:当前一次性 Discord 流水线不会发送被裁剪的 PNG。一个证据文件若把「伪造的后续任务」交给下一位工程师,本身就是证据的缺陷——这也是 todo 8 被 reopen 的第二条理由。验证者还披露了会话期间的并发编辑观察:17:53 时run_dashboard.py的正则是body\{[^}]*?height:(\d+)px(不匹配带空格的body {),会误触fail("render_height");17:56 更新为body\s*\{...后匹配成功得到 3060。当前磁盘状态正确,验证结论钉在 17:56 状态的 sha1 上。
八、DEFECT-1:画面自相矛盾(阻断缺陷)
todo 8 的交付在同一个画面里自相矛盾:build_unified.py中既有的「병렬 실행 × 캐시」卡片仍渲染일반 툴콜/eval 병렬도는 여전히 미계측(一般工具调用/eval 并行度仍未插桩),而这行文案恰好位于新卡片上方约 600 CSS px 处——新卡片测量的恰恰就是它。作者把 SKILL.md 中对应句子改对了,却漏掉了像素。这不是数据完整性 bug,而是交付物的可信度 bug,且完全在 todo 8 范围内(「대시보드 카드 + 문서 반영」)。
修复用一行文案替换保留了全部三层语义(代理 → 下界 → 直接测量):
- <div class="cs" style="margin:10px 0 0">일반 툴콜/eval 병렬도는 여전히 미계측 — 아래 절감치는 위임 배치만의 하한</div></div> + <div class="cs" style="margin:10px 0 0">이 카드의 병렬도는 위임 배치 비율 대리치 · 바로 아래 절감치도 위임 배치만의 하한이고, 일반 툴콜/eval 병렬도는 맨 아래 실측 스팬 카드에서 직접 측정</div></div>修复后미계측在模板、SKILL.md 与两份渲染 HTML 中均归零;文案更长的替换句让两种状态的高度从 2974/3022 涨到 2988/3036,3060 下仍有 72/24px 余量,高度维持 3060 无需改动。二次独立验证(verify-t8-repair.md)逐像素确认:三张卡片的陈述互相一致,且 대리치(代理)/ 하한(下界)/ 직접 측정치(直接测量)用三个不同的韩语术语区分,没有把精度压平成含糊其辞。
九、对抗性验证的方法论要点
把这份报告抽象出来,得到一套可复用于任何「数据 → 渲染 → 文档」交付的验证清单:
- 契约以源码为准:简报说 11 列,源码是 13 列——读 fetch_data.py 的查询而不是猜。
- 静态映射 + 哨兵渲染双保险:每列一个唯一整数注入后从 PNG 回读,任何一位偏移都会破坏多个衍生算式。
- 测最高的变体:有数据态比空数据态高 48px,只按当前零数据调高度会在事件落地当天静默裁页脚。
- 诚实标签必须上屏验证:估计值、上界、下界、直接测量分别用不同术语,且「估计」字样与数值相邻。
- 比率口径可审计:sum/sum 而非 per-session 均值,结构上杜绝 mean-of-ratios。
- 崩溃也要分级:区分「本交付引入」与「模块存量行为」,并验证崩溃时不会把栈写入产物。
- 证据文件本身要被审查:一条被证伪的风险声明(2150 硬编码)足以让
confirmed降级为needs-fix。 - 画面一致性检查:同一张图的上下两行文案不得互相矛盾——文档改对而像素漏改是最高发的交付缺陷之一。
最终判定:数据路径(列映射、gate、比率、诚实标签、eval 分离、高度)全部正确,两个缺陷(一条过期屏幕文案 + 一条证据文件假事实)修复后获得confirmed(置信度 0.92)。这个案例的价值在于证明:「数据全对」不等于「交付合格」,对抗性验证必须把文档、像素与证据文件都纳入攻击面。
上图来自 f3-render 人工 QA 留存,展示新卡片在
parallelism_summary尚未流数据时的占位形态:左卡头条为 STONE 色的「모델 추정 절감 수집 대기」,三根 SILVER 零填充条,右卡全部「수집 전」,与本文第三节的诚实标签与占位规范一一对应。相关完整渲染与页脚裁剪证据可继续查看同一目录下的 f3.md 与 task-8.md。
【免费下载链接】oh-my-openagentOmO: Just type "mass ulw" keyword with your prompt. Now you are the master of graph engineering.项目地址: https://gitcode.com/gh_mirrors/oh/oh-my-openagent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考