news 2026/9/15 21:34:04

Electric Agent 运行时 DSL 覆盖率全景:从测试矩阵到编排模式验证指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Electric Agent 运行时 DSL 覆盖率全景:从测试矩阵到编排模式验证指南

Electric Agent 运行时 DSL 覆盖率全景:从测试矩阵到编排模式验证指南

【免费下载链接】electricThe agent platform built on sync.项目地址: https://gitcode.com/GitHub_Trending/el/electric

导读:本文围绕 packages/agents-runtime/test/runtime-dsl-ideas.md 展开,这是一份服务于packages/agents-runtime运行时黑盒测试套件的"规范规划与覆盖率追踪"文档。它通过 A–N 十二组场景编号,把 Electric Agent 运行时(基于 durable streams 的行为栈)的实体生命周期、派生机制、共享状态、观察回放、协调编排、Map-Reduce、流水线、同行评审、辩论、Wiki 自治与响应式观察流全部映射为可断言的流历史测试。读完本文,你将理解这套 DSL 测试的编写纪律、83 个场景覆盖了什么、哪些是待办缺口、哪些模式被刻意否决,并能据此为自己的 Agent 编排功能设计同等级的回归测试。

一、这份文档是什么:DSL 覆盖矩阵而非普通笔记

runtime-dsl-ideas.md的定位在文件头写得非常清楚:它是packages/agents-runtime/test/runtime-dsl.test.ts权威规划/覆盖率追踪文件(canonical planning/coverage tracker)。它的核心数据是:

  • runtime-dsl.test.ts当前包含83 个场景测试
  • 完整运行时套件全绿,共256 个测试
  • 文档追踪三件事:已覆盖什么还缺什么哪些想法因编码了错误的编排模式而刻意不"加持"(not blessing)

也就是说,这不是一篇教程,而是一张"测试军规 + 覆盖地图 + 待办看板"三合一的技术文档。作为文章骨架,它最适合用来回答三个问题:Electric Agent 运行时的行为契约是什么?用什么纪律去验证?哪些行为边界还没有被验证?

二、DSL 编写纪律:七条铁律

文档在 "DSL Rules" 一节给出了黑盒场景测试的七条编写纪律,这是理解整个矩阵的方法论前提:

  1. 尽量断言完整流历史,而不是抽查(Assert full stream history wherever possible, not spot checks);
  2. 优先使用过滤快照(filtered snapshots),而不是对调度敏感(scheduler-sensitive)的原始历史快照
  3. 从流开头匹配,禁止固定 sleep(Match from the beginning of the stream; no fixed sleeps)——测试必须靠语义事件驱动,而不是靠等时间;
  4. 断言 spawn 参数、manifest 行与初始 inbox 消息的 eager durability(主动持久化);
  5. 测试回放/再水合(replay/rehydration)行为时强制 wake 边界(Force wake boundaries);
  6. 使用确定性的假助手/假工具,而不是 playground 特有的工具蔓延
  7. 不要因为某些错误编排模式"容易测"就把它们洗白进 DSL

这七条纪律在 runtime-dsl.test.ts 中有直接体现。例如测试基础设施runtimeTest()在 runtime-dsl.ts 中统一管理ElectricAgentsServer+DurableStreamTestServer+ 本地 webhook 处理器,并提供waitForRunwaitForRunCountwaitForSettled语义等待原语;waitForSettled依赖runtime.drainWakes()让运行时达到静默(quiescence),而不是轮询固定次数。这正是"从流开头匹配、禁止固定 sleep"纪律的实现基础。

三、已覆盖场景全解:A–N 十二组矩阵

A. 独立助手(Standalone Assistant,A1–A14)

这组场景回答"单个实体如何从 spawn 到产生完整 run 历史"。核心断言包括:

  • A1:spawn 立即写入entity_created,并携带 spawn 参数(见 A1 测试,快照确认argsentity_type进入历史);
  • A2:spawn 携带initialMessage时,inbox 历史先于任何 run 写入(快照中entity_createdinbox之前,且无 run 记录);
  • A3:单条消息产生完整的 run 历史——快照展示run insert → step insert → text insert → text_delta insert → text update(completed) → step update(completed) → run update(completed)的全链路(见 快照文件);
  • A5:多条消息产生两条 completed run;A5b/A5c分别验证entity.waitForSettled与全局t.waitForSettled两种静默等待路径;
  • A6:无 agent 的实体只记录入站消息(只写 inbox);
  • A7:setup 状态写入出现在 run 历史之前;
  • A9A11:同步/异步工具调用在单个 run 内按序出现、多次工具调用顺序稳定且取最后一次结果;
  • A12:有状态 note 写入跨 wake 持久、后续可读;
  • A13/A14:失败工具干净地关闭 run 并保留持久失败历史,且实体能在后续 run 中恢复。

其中A13对应的fail_tool命令与createFakeToolAssistant(runtime-dsl.test.ts)体现了"确定性假工具"纪律:工具行为全部由测试内联命令解析器驱动,不依赖任何外部服务。

B. 派生机制(Spawn Mechanics,B1–B4)

验证父实体 spawn 子实体的流历史形态:

  • B1:spawn 创建可接收消息的子实体;
  • B2:带initialMessage的 spawn 写入子实体历史;
  • B3:spawn 的 manifest 历史包含解析后的entityUrl
  • B4:spawn 自动创建 observe manifest 条目(对应测试标题 "spawn marks the child manifest row as observed")。

C. 状态集合(State Collections,C1–C3)

  • C1ctx.db上的集合写入反映到完整流历史;
  • C2:setup 初始化的状态在最终历史中仍然可见;
  • C3:实体自己写自己的状态不会触发第二次 run——这是防止"状态回环"(self-triggered loop)的关键行为契约。

D. 共享状态(Shared State,D1–D12)

共享状态是跨实体协作的地基。createSharedState/ctx.mkdb+ctx.observe(db(...))的组合(见d1d4实体定义,runtime-dsl.test.ts)驱动了 12 个场景:

  • D1createSharedState在实体历史中产生 manifest 条目;
  • D2:共享状态流在任何写入之前就已存在
  • D3:对共享状态的写入同时反映在写入方与被观察方两个历史中;
  • D4:第二个实体可连接既有共享状态并读到先前行;
  • D5:共享状态的 update/delete 事件跨 wake 持久;
  • D6:多集合共享状态在 writer/reader 实体间保持一致;
  • D7:多个实体可向同一共享集合贡献持久行;
  • D8:后写入者可覆盖共享行,新 reader 读到最新值;
  • D9:setup 注册的共享状态 effect 在首次 wake 写入时触发并在后续 wake 存活;
  • D10:不同实体可在同一共享状态中向不同集合写入;
  • D11:同一共享 key 的相邻写入者保留完整历史且后写覆盖(last-write-wins)
  • D12:变更一个共享集合不干扰另一集合的读取。

E. 观察回放(Observation Replay,E1–E3)

  • E1:observed effect 在父实体重新 wake 时不重复旧子行;
  • E2:更新被观察行保持单一派生行 key;
  • E3:被观察行更新被回放为 update 而非第二次 insert(E0 还额外验证了"不带 wake 的 observe 在后续子写入时不会重新 wake")。

F. 协调编排(Coordination Orchestration,F1–F12)

这是文档篇幅最大的编排组,覆盖 dispatcher 与 manager-worker 两种经典模式:

  • F1:dispatcher 路由到指定专家类型并记录子实体;
  • F2:manager-worker spawn、observe 并以稳定顺序收集全部 perspectives(测试中optimist/pessimist/pragmatist三种视角,runtime-dsl.test.ts);
  • F3:dispatcher 递增 dispatch 计数并在多次 wake 后保留两个子行;
  • F4:dispatcher 记录 dispatch 过程中的期望状态迁移(idle → classifying → dispatching → waiting,见createDispatcherAssistant);
  • F5/F7:子实体无文本输出时使用文档化占位符(placeholder);
  • F6wait_for_all在未 spawn 前调用返回文档化错误路径;
  • F8:重复spawn_perspectives复用同一批子实体,只返回最新输出;
  • F9/F10:manager-worker 对定向子失败只对该 perspective 用占位符,且可在失败后重试并最终收集完整结果;
  • F11/F12:dispatcher 在专家失败(甚至反复失败)时保留计数器与子行。

从实现看,子完成通过wake: { on:runFinished, includeResponse: true }注册唤醒,父实体在非 inbox wake 中读取finished_child载荷并更新childStatus集合(见f2ManagerapplyWakeStatus,runtime-dsl.test.ts)。

G. Map-Reduce(G1–G4)

  • G1:即使各 chunk 完成时间不同,结果仍按 chunk 顺序返回(测试用delayMs打乱完成时序,见createMapReduceAssistant);
  • G2:单 chunk 的 map-reduce 仍走编排路径;
  • G3:后续 run 复用 chunk 子实体且不泄漏上一次的 chunk 输出;
  • G4:仅对失败 chunk 使用占位符,其余保留。

H. 流水线(Pipeline,H1–H6)

  • H1:流水线在首次 wake、阶段执行之前就写入状态行;
  • H2:每个阶段消费上一阶段的输出并持久化最终状态;
  • H3:状态上限封顶于stage_5,更长流水线仍能完成——这与实现中Math.min(stageNumber, 5)的写法一致(runtime-dsl.test.ts);
  • H4:逐阶段持久化currentInput更新;
  • H5:后续 run 复用阶段子实体但重置到最新输入链;
  • H6:失败阶段以占位符输入继续传给后续阶段。

I. 同行评审(Peer Review,I1–I4)

  • I1:评审者通过共享状态聚合 reviewer 写入(测试含 3 名评审者:clarity/correctness/completeness,见 runtime-dsl.test.ts);
  • I2summarize_reviews在无评审时返回空状态错误路径;
  • I3/I4:分别配置 1 名与 2 名评审者时,只汇总对应的持久行——评审者数量必须精确对应聚合结果

J. 辩论(Debate,J1–J3)

  • J1:辩论父实体在裁决前从共享状态读取正反双方论点;
  • J2end_debate在无论点时返回空状态路径;
  • J3:只有一方论点时辩论保持 partial,直到缺失一方到达才 resolve。

K. Wiki 自治(Wiki,K1–K10)

  • K1:Wiki 专家累积共享文章,后续查询可读;
  • K2:重复create_wiki复用既有专家,只 spawn 缺失的子主题;
  • K3get_wiki_status在专家文章落地后报告完整覆盖;
  • K4create_wiki拒绝切换既有 wiki 的主题;
  • K5/K7:未创建任何文章/未创建 wiki 时返回空状态消息;
  • K6:同主题同子主题的重复create_wiki幂等;
  • K8:wiki 镜像持久化的子实体/文章通知元数据(含 topic/author);
  • K9:幂等重建不重复共享文章行;
  • K10:同主题扩展只新增缺失文章并更新后续查询覆盖。

L. 响应式观察流(Reactive Observation Flows,L1–L5)

  • L1:显式observe + createEffect转发 insert/update/delete 三类通知;
  • L2:子实体无新变更时重新 wake watcher 不重复旧通知;
  • L3:watcher 休眠期间发生的子删除在回放时只产生一条 delete 通知;
  • L4:同一子实体被观察两次保持去重(deduped);
  • L5:一个 watcher 可观察多个子实体并保留来源归属(source attribution)。

从实现看,l1Watcher实体通过_mirror集合记录每个子 URL 的镜像行,在每次 wake 时做"增/改/删"三向比对并生成insert:/update:/delete:通知行(runtime-dsl.test.ts),是响应式观察流的参考实现。

M/N 附加组:Deep Researcher 与 Wake 语义

文档的 Active Backlog 提到 Deep Researcher(M 组)已覆盖 spawn-timeinitialMessagewait_for_results前调用错误路径、多子研究员跨 wake 隔离。测试文件中对应的M1M3(runtime-dsl.test.ts)验证了"研究员从 spawn 的 initialMessage 启动,无需额外 send"。此外N1N5组专门验证 wake 语义:runFinished唤醒时父实体收到wake类型事件、spawn wake 与子 manifest 共享同一条runFinished注册、ctx.agent.run可携带 wake 载荷执行第二次 run。

四、待办缺口:Active Backlog 逐项解读

文档明确区分"已覆盖"与"待办"。待办中有一部分已打勾,有一部分仍是缺口,其中值得关注的有:

共享状态(第 1 节)

  • 已覆盖:相邻 wake 下两个实体对同一 key 的写竞争、reader 观察一个集合时 writer 变更另一集合;
  • 缺口:setup 时间与动态 update/delete 组合作用于可变行时的 effect 覆盖。

协调失败与恢复(第 2 节)——全部为缺口

  • dispatcher 子失败路径上的runFinished延续聚合;
  • 跨多次 wake 的反复失败需保留子行与计数器(注:F12已在测试文件中实现为 "dispatcher preserves counters and child rows across repeated failing dispatches");
  • 子失败后在同一父实体上替换子实体。

Map-Reduce 与流水线边界(第 3 节)——已全部覆盖

  • 单 chunk 失败占位符、跨 wake 的重复 chunk id 复用、阶段失败语义、done后的重跑重置语义。

同行评审与辩论(第 4 节)

  • 缺口:评审已持久后跨 wake 边界的汇总;
  • 已覆盖:评审者数量变体(1/2/3)、辩论双方向缺失前的 partial 状态。

Deep Researcher(第 5 节)——已全部覆盖。

Wiki 自治(第 6 节)——全部为缺口

  • 无需第二次用户干预的 build-and-answer 流程;
  • 文章足够后自动 resolve 的 pending query 状态;
  • 只有部分专家写完时的 partial wiki 答案;
  • 同一实体上的显式子主题扩展与后续跟进查询;
  • 面向观察者的更清晰的父侧高层进度面。

观察 / Effects(第 7 节)——全部为缺口,且文档给出了关键判断

  • 无效 observe 目标的错误路径;
  • observe-once 与 first-write-wins 配置不匹配的固定化;
  • 多种编排模式下的live .send()观察句柄;
  • 可变行 effect 回放/update/delete(需上游 effect gating 落地);
  • 多源 joined effects(依赖上游createEffect语义稳定)。

文档在 第 7 节末尾 给出一条重要的前置依赖说明:ElectricAgents 现在已经有了按源命名空间隔离的 StreamDB collection id 与逐消息 offset,但上游createEffect的稳定回放语义仍不够可靠,因此**暂时不"加持"(bless)**可变行与多源 joined 这两类用例。

Trading Floor(第 8 节)——全部为缺口

  • 开放市场播种与时钟初始化;
  • 新闻注入扇出(fanout);
  • 跨会话的时钟推进;
  • 由持久共享状态派生的市场摘要。

横切压力(第 9 节)——全部为缺口

  • 混合 spawn + observe + shared state + replay + 多子实体的组合场景;
  • 带反复再水合与过滤快照的长多 wake 场景。

五、Import Idea Triage:想法分级与"刻意否决"清单

2026-03-21 的一次头脑风暴被映射进 DSL 计划,文档给出三种归宿:

1. 已由 DSL 覆盖(如 1–8 由 A1–A14/C1–C3 覆盖,9–19 由 B1–B4/A1–A2/F3/F8 覆盖,80–85 由 F/G/H/I/J/K 各组合覆盖)。

2. 更适合放在 DSL 之外的低层测试setup-contextwake-handlerprocess-wake的单元/集成测试),包括:spawn manifest 的entityUrlcreateSharedState/connectSharedState的 manifest 条目、createEffect的 manifest/functionRef/dedupe 规则、agent factory 与 re-wake 回放内部机制、spawn/setup 失败的 crash-only 行为。这类条目不是行为洞,而是测试层级选择

3. 明确不在当前产品方向内:"子完成通过runFinished唤醒父实体,编排应表示为持久化的延续唤醒(durable continuation wakes)"。

真实遗留 DSL 待办包括:状态删除流覆盖(15)、受保护状态迁移示例(28)、agent factory 中创建共享状态与幂等创建(39–40)、协调实体存活直到所有子完成(86)、trading-floor 场景(94–95)、无效 guard 迁移错误路径(97)。

**Explicitly Rejected Patterns(明确否决的模式)**是本文档的独特价值——它警告了三种"看似能测但方向错误"的测试:

  • 依赖同步子输出读取的同实体重复 map-reduce 再聚合
  • 假设立即子复用与聚合的同实体重复流水线重跑
  • 依赖偶然调度顺序而非持久语义历史的测试。

这与 DSL Rules 第 7 条"不要将坏编排模式洗白进 DSL"形成闭环:测试矩阵不仅测"对的",也明确拒绝"错的"。

六、落地运行与仓库证据索引

如果你想亲自验证这套矩阵,仓库提供了完整的运行路径:

  • 包名:@electric-ax/agents-runtime,版本0.6.3,见 packages/agents-runtime/package.json;
  • 运行命令:在packages/agents-runtime下执行pnpm test(vitest run)或pnpm test:watch;完整运行时套件 256 个测试全绿(文档记录),其中runtime-dsl.test.ts贡献 83 个场景;
  • 测试基础设施:runtimeTest()在 packages/agents-runtime/test/runtime-dsl.ts 中自动拉起ElectricAgentsServerDurableStreamTestServer与本地 webhook 处理器,并注入system:runtime-dsl-test主体验证 spawn 权限;
  • 快照断言:流历史快照集中在 packages/agents-runtime/test/snapshots/runtime-dsl.test.ts.snap,A1A4entity_created → inbox → run → step → text → text_delta事件链是理解"完整流历史断言"的最佳样本;
  • 相关运行时代码:ctx.spawn/ctx.observe/ctx.mkdb等上下文能力对应 packages/agents-runtime/src/setup-context.ts,wake 分发逻辑见 packages/agents-runtime/src/process-wake.ts,实体定义与注册见 packages/agents-runtime/src/define-entity.ts 与 packages/agents-runtime/src/index.ts。

七、结论:一张"活的"编排行为契约

runtime-dsl-ideas.md的价值不在于罗列测试数量,而在于它把"行为契约"工程化了:用可断言的流历史替代时序猜测,用语义等待替代固定 sleep,用确定性假助手替代外部依赖,用"明确否决"清单守住编排模式的正确方向。对于在 Electric Agent 运行时之上构建协调类功能的开发者,这张矩阵既是回归测试的规格说明书,也是判断"某个行为该不该进入 DSL"的决策框架——当你想给一个新编排模式补测试时,先问自己:它能断言完整流历史吗?它依赖偶然调度吗?它是不是把坏模式洗白了?答案会引导你走向 A–N 中正确的那个分组,或者走向setup-context级别的低层测试,又或者直接进入"Not Current Product Direction"清单。

【免费下载链接】electricThe agent platform built on sync.项目地址: https://gitcode.com/GitHub_Trending/el/electric

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 21:33:12

联发科AI生态全解析:NeuroPilot、APU与端侧部署实战

在手机芯片这个圈子里摸爬滚打这么多年,MTK(联发科)一直是个绕不开的名字。早几年大家聊它,多半是“性价比”、“千元机标配”,再往前还能扯上“山寨机之王”的历史包袱。但最近这两三年,情况明显变了——M…

作者头像 李华
网站建设 2026/9/15 21:32:50

gitingest 如何用 --include-submodules 把 Git 子模块纳入 digest?

gitingest 如何用 --include-submodules 把 Git 子模块纳入 digest? 【免费下载链接】gitingest Replace hub with ingest in any GitHub URL to get a prompt-friendly extract of a codebase 项目地址: https://gitcode.com/GitHub_Trending/gi/gitingest …

作者头像 李华
网站建设 2026/9/15 21:30:43

2026前端删包指南:5个npm包被原生API替代的实操路径

1. 这不是“删包指南”,而是一份 JavaScript 生态演进的实操观察笔记2026 年这个时间点,不是凭空设定的预言,而是基于当前浏览器能力落地节奏、主流框架内部重构进度、以及 Node.js 官方模块稳定路径综合推演出来的合理窗口。我从 2015 年开始…

作者头像 李华
网站建设 2026/9/15 21:30:35

Mac 窗口管理工具 Loop:径向菜单、循环布局与窗口暂存

Mac 窗口管理工具 Loop:径向菜单、循环布局与窗口暂存 【免费下载链接】Loop Window management made elegant. 项目地址: https://gitcode.com/GitHub_Trending/lo/Loop 五个窗口来回 CmdTab 切到手酸,拖动窗口边缘对齐半天又歪回去——这是多数…

作者头像 李华