OmO 并发波组装器(Concurrency Wave Assembler)对抗性复核实录:`MAX_TRACKED_CALLS` 内存闸门修复的独立验证
2026/9/20 1:15:15 网站建设 项目流程
  • 人工智能
  • AI Agent
  • 代码智能体
  • 多智能体
  • MCP Clients
  • Agent 编排

【免费下载链接】oh-my-openagent

OmO: 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
点击查看免费下载

本篇指南围绕 OmO(oh-my-openagent)omo-senpi 遥测管线中一次真实的缺陷修复与对抗性复核展开:并发波组装器wave-assembler.ts的跟踪上限缺陷从发现、修复到独立验证的完整闭环。读者将掌握该模块的区间图波组装原理、六类计数器语义、paired.length + pending.size双结构闸门的正确性论证,以及一套可复用的对抗性验证方法论——包括 RED 重构、变异测试(mutation test)、随机交错扫描与会计恒等式(accounting invariant)审计。

一、背景:为什么遥测需要"并发波"而非"回合"

om -senpi 的并行度遥测要回答一个核心问题:一个会话里有多少工具调用是真正并行执行的,以及并行执行节省了多少墙钟时间。为此,todo 1 在 wave-assembler.ts 中实现了纯函数assembleWaves,把成对的tool_execution_start/tool_execution_end观测按toolCallId配对,再按时间区间重叠关系(区间图连通分量)聚合成"并发波"。

模块头注释(wave-assembler.ts)明确了三个关键设计决策:

  1. 波是区间图连通分量,不是回合:一个调用只要其[startMs, endMs]区间与波内任一调用重叠就加入该波,因此链式执行 A(0-5)、B(4-9)、C(8-12) 会聚成一个波——A 与 C 从不直接重叠,但通过 B 传递连接。
  2. spanMs = maxEnd - minStart而非最长单次时长:下游的 savings 公式需要真实的消逝窗口,max(duration)在链式波上会高估。这正是验证文档中的核心守卫之一(详见"变异测试"一节)。
  3. 驻留明细(resident detail)存在两处:等待 end 的pendingMap 与已完成配对的paired数组,二者之和才是真正的内存占用,也因此成为容量闸门(cap gate)的管控对象。

1.1 模块输入:为什么观测必须自带时间戳

task-1 证据文档(task-1.md)特别指出:senpi 事件ToolExecutionStartEvent/ToolExecutionEndEvent本身不带时间戳字段,因此 todo 4 的订阅者必须在到达时打上时间戳,本模块只接受已打戳的ToolExecutionObservation记录:

export type ToolExecutionObservation = { readonly kind: "start" | "end" readonly toolCallId: string readonly toolName: string readonly atMs: number }

1.2 核心数据结构与输出

export const MAX_TRACKED_CALLS = 2000

WaveCounters是全部会计出口(wave-assembler.ts):

计数器语义
observedCalls每个格式良好的 start 观测 +1(永不饱和)
pairedCalls成功配对的调用数
incomplete组装结束时仍驻留在pending的 start 数(=pending.size
clockAnomaliesend 时间早于 start 时间的调用数(第四会计出口)
droppedCalls超过容量闸门被拒绝的 start 数
malformed结构上无法解析的输入数

输出WaveAssembly携带waves: ConcurrencyWave[](每个波含callsspanMsmaxConcurrency)与上述计数器。

二、原始缺陷:只拦paired.length的闸门形同虚设

2.1 缺陷定位

初始提交b8078d13a的容量闸门只检查已完成配对数组的长度:

// b8078d13a: wave-assembler.ts:69(缺陷版本) if (paired.length >= MAX_TRACKED_CALLS) { counters.droppedCalls += 1 continue }

但调用明细首先累积在pendingMap 中——一个 start 只有等 end 到达后才会变成paired条目。因此对"5000 个 start 全部先到、5000 个 end 全部后到"的全并行到达顺序paired.length全程为 0,pending无界增长,闸门从未触发。独立对抗性验证(verify-t1-t3.md)实测:5000 starts + 5000 ends 得到tracked=5000, dropped=0,而声明的上限是 2000。

2.2 为什么原测试漏掉了它

原 case (f) 夹具是严格交错的[start, end, start, end, ...]——恰好是paired.length闸门碰巧有效的唯一到达顺序,因为每个 end 都在下一个 start 到来前清空了pending。而全 start 后全 end 恰恰是本遥测存在的意义所在(测量全并行批处理),计划文档的 MUST-NOT("배열을 무한히 키우지 말 것",即数组不得无限增长)在最关键处未被强制执行。

三、修复方案:对两个驻留结构之和设闸

3.1 一行代码的修复

修复提交791437517将闸门改为对两个驻留结构之和施限(wave-assembler.ts):

if (paired.length + pending.size >= MAX_TRACKED_CALLS) { counters.droppedCalls += 1 continue }

正确性论证:一个 start 在配对时会从pending迁移到paired,迁移前后paired.length + pending.size之和不变,因此该和在整个组装过程中单调有界——无论到达顺序如何交错,驻留明细都不会超过 2000。

3.2 计数器语义不变

observedCalls仍然统计每个格式良好的 start,droppedCalls统计超过上限被拒绝的 start。修复提交总 diff 仅 8 行:6 行模块注释 + 1 行闸门变更 + 1 行删除,纯逻辑改动是单行。

四、独立复核:三个声明形状全部精确重现

独立验证者(未参与实现,verify-t1-repair.md)从头编写了/tmp/vt1/probe.ts,直接导入导出的assembleWavesMAX_TRACKED_CALLS,作者脚本被删除且未被复用:

SHAPE1 5000-starts-then-5000-ends tracked=2000 paired=2000 dropped=3000 observed=5000 incomplete=0 anomalies=0 malformed=0 accounted(paired+incomplete+dropped)=5000 residentDetail=2000 CAP=2000 INVARIANT_OK=true BOUND_OK=true SHAPE2 2500-starts-no-ends tracked=0 paired=0 dropped=500 observed=2500 incomplete=2000 anomalies=0 malformed=0 accounted(paired+incomplete+dropped)=2500 residentDetail=2000 CAP=2000 INVARIANT_OK=true BOUND_OK=true SHAPE3 2010-interleaved-pairs tracked=2000 paired=2000 dropped=10 observed=2010 incomplete=0 anomalies=0 malformed=0 accounted(paired+incomplete+dropped)=2010 residentDetail=2000 CAP=2000 INVARIANT_OK=true BOUND_OK=true

三个形状与作者声明逐位一致,原始缺陷(tracked=5000 dropped=0、2500 驻留)确认关闭。

五、攻击不变式:六种对抗到达顺序 + 400 次随机扫描

验证者用resident = trackedDetail + incomplete(paired 数组 + pending Map)作为真实内存占用,构造了两种极端到达顺序都未覆盖的攻击集(/tmp/vt1/probe2.ts):

探针场景结果
(a)3000 starts → 1500 ends → 1500 更多 starts(部分排空后重入)resident=2000,BOUND_OK
(b)3 starts : 1 end 比例 × 2000 轮(pending 持续非零且 paired 增长)resident=2000,BOUND_OK
(c)2500 starts 后 2500 ends,含被拒 starts 的 endsresident=2000,无损坏、无复活
(c2)2100 starts,ends 仅针对 100 个被拒 startsresident=2000,dropped=100
(d)边界 n=1999/2000/2001,两种到达顺序n=2000 全收、n=2001 恰好拒 1,>=比较符正确
(e)时钟异常 + 正常配对anomalies=1,第四会计出口生效

5.1 关键发现一:被拒 start 的 end 静默丢弃,无复活

探针 (c)/(c2) 验证:end 的 start 若已被拒绝,命中pending.get(...) === undefined(wave-assembler.ts)后被静默丢弃——既不增加pairedCalls,也不重新接纳明细,且不计入malformed。这与既有文档化的孤儿 end 语义一致(task-1 判定记录 3 曾专门澄清:nan/negative的 end 是格式良好的观测,其 start 被拒绝,故按孤儿 end 处理而非 malformed 输入)。

5.2 关键发现二:作者的不变式缺了第四出口

探针 (e) 证明作者的paired + incomplete + dropped == observed并非普遍成立:时钟异常调用被从pending移除、永不进入paired、只落入clockAnomalies。正确的完整恒等式为:

paired + incomplete + dropped + clockAnomalies == observed

这是b8078d13a就存在的既有行为(本次修复未改变),且每个调用都落在某个计数器中,无静默丢失。验证者将其记录为对作者声明的一次精度修正,而非修复本身的缺陷。

5.3 随机化扫描:构造不出反例

/tmp/vt1/probe3.ts使用确定性 LCG 生成 400 次交错(每次 2500-4500 条观测,62% start 偏置,乱序 ends):

400 randomized interleavings: worstResident=2000 CAP=2000 boundBreaks=0 invariantBreaks=0

作者的正确性论证——start 从pending迁移到paired时二者之和不变、和单调有界——在攻击下成立,验证者无法构造出反例。

六、RED 重构与 GREEN:修复是真实的,不是伪造的

6.1 RED 重构(针对旧闸门)

验证者独立把修复前模块从 git 取出,让当前测试文件指向它,作者工件未复用:

$ git show b8078d13a:packages/omo-senpi/src/components/telemetry/wave-assembler.ts > /tmp/vt1/oldgate/wave-assembler.ts $ bun test /tmp/vt1/oldgate/wave-assembler.test.ts (fail) #given every start arriving before any end beyond the tracking cap ... expect(trackedCalls).toBe(MAX_TRACKED_CALLS) Expected: 2000 Received: 2500 (fail) #given unmatched starts beyond the tracking cap ... expect(result.counters.incomplete).toBe(MAX_TRACKED_CALLS) Expected: 2000 Received: 2500 11 pass 2 fail

与作者声称的 RED 完全一致(11 pass / 2 fail,incompleteExpected 2000 Received 2500)——两条新测试确实钉住了缺陷,RED 捕获非伪造。

6.2 GREEN(已发布代码)

$ bun test packages/omo-senpi/src/components/telemetry/wave-assembler.test.ts 13 pass 0 fail 35 expect() calls

6.3 变异检查:span 守卫仍然非重言式

把当前(修复后)模块复制到/tmp/vt1/mutant/,将spanMs: maxEnd - minStart换成spanMs: max(endMs - startMs)(即计划明令禁止的max(d)基准):

(fail) #given tool executions that overlap in time ... #then all three calls join one wave carrying a span (fail) #given a chained wave where the first and last calls never overlap ... #then one wave reports the full span and a concurrency of two expect(result.waves[0]?.spanMs).toBe(12) Expected: 12 Received: 5 11 pass 2 fail

max(d)变异体仍被两条测试捕获(而非一条)——修复没有削弱 span 守卫。这印证了 task-1 的原始回归守卫:链式 A(0-5) B(4-9) C(8-12) 中 A 与 C 从不重叠,朴素"最长时长"会报 5,朴素"波大小"并发会报 3,实测是 12 和 2。

6.4 指标逻辑零回归

链式波用例不受修复影响:1 个波、span=12maxConcurrency=2;spans、波划分、incompleteclockAnomalies全部与先前确认值一致。8 行 diff(6 行注释 + 1 行闸门 + 1 删除)不存在扰动 span/波/并发计算的可能,测量也证实未扰动。

七、被点名的遗留问题:incomplete少报与 schema 缺口

7.1 模块内可接受,线上不可审计

一旦触顶,被拒 starts 落入droppedCalls而非incomplete。2500-starts 用例上报incomplete=2000,但实际有 2500 个 start 未完成——incompleteMAX_TRACKED_CALLS处饱和,少报了被拒数量。

模块层面可接受的理由incomplete定义为残差 pending 明细,计划明确要求超限时"카운터만 유지하고 상세는 버림"(只保留计数器、丢弃明细);observedCalls精确且不饱和,droppedCalls精确承载亏空,完整会计恒等式在全部 400 个随机形状与每个手工形状上成立。持有全部五个计数器的消费者总能还原真相,没有调用被静默丢失。

7.2 真正的风险:parallelism_summary不带dropped_calls

验证者点名 omo-native-parallel-summary.ts:buildParallelismSummary在事件里暴露了incomplete_callsclock_anomalies暴露了dropped_calls——但验证文档写作时点所引用的注册 schema(parallelism-schema.ts)尚未携带dropped_calls属性(该文件现已包含dropped_calls: NUMBER_PROPERTY,对应 todo 5 的演进)。读取该事件的仪表盘若只看到incomplete_calls = 2000,将无从得知另有 500 个 starts 被拒绝、也无从判断该值是被截断的天花板而非测量值——"会让仪表盘读到的指标静默损坏"的失效模式只是被推迟了一层,并未消除。

验证者对 todo 6 的建议(非 todo 1 的阻塞项):要么为parallelism_summary增加dropped_calls数值属性使恒等式可在线上重建,要么发出饱和标志(saturation flag)让读者区分真实的incomplete_calls = 2000与被截断的值。schema 文件归 todo 5 所有,本修复正确地未触碰。

八、范围纪律与约定合规

$ git show --stat 791437517 .omo/evidence/telemetry-parallel-latency-v2/task-1.md | 121 +++++++++++++++ packages/omo-senpi/src/components/telemetry/wave-assembler.test.ts | 40 ++++ packages/omo-senpi/src/components/telemetry/wave-assembler.ts | 8 +-

提交恰好只触碰三个许可路径;savings-math.tseval-classifier.tsproduct-identity.tsproduct-identity.test.ts、senpi-telemetry.md、packages/telemetry-core/packages/omo-codex/packages/omo-opencode/plugin/extensions/index.ts均未被该提交触碰(范围 diff 中出现的其他文件来自中间提交d6dd78b4fde7416776,属其他 worker 的 todo 2/5)。

交错夹具被保留git diff b8078d13a 791437517 -- .../wave-assembler.test.ts的删除行计数为 0——原 case (f) 夹具逐字节未动,未被重写来迁就修复。两条新用例纯为新增。这是正确之举:保留严格交错夹具即保留了旧闸门唯一能处理的到达顺序,测试套件现在同时覆盖两种顺序。

约定检查(verify-t1-repair.md 第 7 节):

  • given/when/then:两条新用例均用嵌套describe("#given ...") > describe("#when ...") > test("#then ..."),符合 AGENTS.md 约定;
  • 代码卫生:新增行中as any0 处、@ts-ignore0 处、em dash 0 处、非 ASCII/emoji 0 处;
  • 纯 LOC:wave-assembler.ts 157 行、测试 204 行,均低于 250 上限;
  • 测试数据完全字面化:无Date.now()、无定时器、无 sleep、无 async——两条新用例不可能靠时序运气通过。

九、套件健康度

$ bun test packages/omo-senpi/src/components/telemetry/ 133 pass 0 fail 491 expect() calls Ran 133 tests across 15 files. [2.67s] $ bun run --cwd packages/omo-senpi typecheck $ tsgo --noEmit -p tsconfig.json TYPECHECK_EXIT=0

0 fail。133 而非作者记录的 118,是因为其他 worker 并发落地了 todo 2/5 的提交及未跟踪的 todo-4 文件;这些进行中的工作不在本次范围内且均为绿色。

十、方法论沉淀:对抗性验证的可复用清单

从这份验证实录可以提炼出一套可复用的复核流程:

  1. 独立复现声明数字:从头编写探针直接导入被测模块,不复用作者脚本,逐一核对每个声明值(本文三个 SHAPE);
  2. 攻击不变式:构造两种极端到达顺序都覆盖不到的场景(部分排空后重入、被拒 start 的 end、纯被拒尾部、精确边界 n=1999/2000/2001、时钟异常);
  3. 随机化扫描:用确定性 PRNG 生成数百次任意交错,验证最坏驻留与恒等式零破坏;
  4. RED 重构git show取出修复前模块,指向当前测试文件,验证 RED 捕获真实(11 pass / 2 fail,Expected 2000 Received 2500);
  5. 变异测试:对守卫本身施加禁止的变异(如max(d)span),确认测试仍能击杀、守卫非重言式;
  6. 会计恒等式审计paired + incomplete + dropped + clockAnomalies == observed在每个形状上成立,任何调用都不静默丢失;
  7. 范围与约定检查:提交只触碰许可路径、夹具未被重写、约定扫描干净、套件零失败。

结论

verdict: confirmed。修复真实且完整:闸门现在约束paired.length + pending.size;三个声明复现数字集全部精确重现;上界在六种手工对抗到达顺序与 400 次随机交错下成立(最坏驻留 2000,零越界);对旧闸门的 RED 精确重现(11 pass / 2 fail);交错夹具被保留而非重写;指标逻辑未受扰动且其 span 守卫在变异下仍非重言式;范围恰为三个许可文件;约定干净;套件 0 fail。

两条带出的非阻塞修正:

  1. 作者不变式应写作paired + incomplete + dropped + clockAnomalies == observed——clockAnomalies是第四个会计出口(既有行为,非本次修复引入);
  2. incomplete_calls在上限处饱和,schema 是否携带dropped_calls决定了该权衡背后的恒等式能否被仪表盘重建——留待 todo 6(该属性现已在 parallelism-schema.ts 中注册,属 todo 5 的后续演进)。

想深入底层实现的读者可直接阅读 wave-assembler.ts(区间图分组、sweepline 最大并发、解析边界拒绝)与其测试套件 wave-assembler.test.ts(13 条 given/when/then 用例),以及上游证据 task-1.md(初版实现与缺陷复盘)和 verify-t1-t3.md(首次对抗性验证,7/7 变异击杀矩阵)。

  • 人工智能
  • AI Agent
  • 代码智能体
  • 多智能体
  • MCP Clients
  • Agent 编排

【免费下载链接】oh-my-openagent

OmO: 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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询